Welcome to Ticol Tcl Interpreter (C) M Shaw 2015-2017
	 _______          __         ___  ___  ____
	/_  __(_)______  / / _  _   <  / |_  |/ __/
	 / / / / __/ _ \/ / | |/ /  / / / __//__ \ 
	/_/ /_/\__/\___/_/  |___/  /_(_)____/____/
See any associated README.TXT for latest updates and amendments

  Ticol and this help file is Copyright (C) to M Shaw 2015-2017
  All rights reserved.
  Copyright (c) 2007-2016, Salvatore Sanfilippo <antirez at gmail dot com>
  All rights reserved.
  Redistribution and use in source and binary forms, with or without
  modification, are permitted provided that the following conditions are

  * Redistributions of source code must retain the above copyright notice,
    this list of conditions and the following disclaimer.
  * Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions and the following disclaimer in the
    documentation and/or other materials provided with the distribution.


Acknowledgements are made for the following code:

MD5 Algorithm: RSA Data Security, Inc. MD5 Message-Digest Algorithm
  Copyright (C) 1991-2, RSA Data Security, Inc. 1991.
  All rights reserved

Mersenne Twister Random Number Generator
  Copyright(C) 1997-2002, Makoto Matsumoto, Takuji Nishimura

TCP/IP specific extensions in Windows Sockets 2
  Copyright(C) 1980,1983,1988,1993
  The Regents of the University of California

Ticol Manual Index

$ dereference
$$ double-dereference (multi-dereference)
<< >> Bit shift (64-bit)
-> and => (struct or class dereference)
:: Double-colon (Scope symbol)
addressofb, strptr (Binary Buffer Address)
after, every (script)
Alphabetic Index of Built-In Ticol Commands
args  (proc variable or command)
argv and argc
ARP Address Resolution Protocol and RARP (Reverse ARP) Plugin
array - Manipulate Tcl Arrays
array create
array exists
array find (Reverse array lookup)
array foreach
array get
array is_set
array item
array list
array list
array names
array set
array size
array sort
array statistics
array trim
array unset
array walk
Associative arrays
baseconv, convbase
BEDMAS/BOMDAS (Math Operator Precedence)
binary (Experimental/limited binary command)
bintoint, inttobin
bool (boolean value)
Braces {} (Grouping) and Brace Style
calc - Auto-optimising alternative to [expr]
calldll examples
calldllstr, calldllstr_cdecl
carray plugin
CGI Script Debugging
clock format
clock scan
Clock Scan Workaround
close, file close
cmdcount (Command Count)
cmp (Compare)
Code Highlighting Plugin
Colour Constants
Command Line Prompt String
Comparing Ticol/Tcl With PHP
Complex Nested Dereferences
Conditional Operator - ?:
Console Colours
Conversion Routines - mkn, cvn
ctime (Unix time)
ctime_to_double, double_to_ctime
Data Structures
Data Type Ranges
Debugging Ticol
Decimal to Roman Conversion Plugin
dict (Dictionaries) (Incomplete feature)
dict exists
Differences between Ticol and Standard Tcl
Disambiguity: sort
do while, do until (Flow Control)
Double Quotes
Easter Egg
Error Values
Executable-Only Code Obfuscation (ticol.exe filename /c)
External DLL Link Plugin - calldll*, calldll*_cdecl
fib (Fibonacci)
file exists
file gets
file stat
find (Help)
Flow-control: for foreach array_foreach, if elseif else, switch while do
for (Flow Control)
foreach (Flow Control)
Format String (printf and format)
fraction and integral
Function Arity
getcwd, pwd
getfileopen, getfilesave
Getting User Input
Global Variables
goto_block, goto
Handling filenames and paths
help topic
Hex Routines
html header_field
html remove_header
html strip
if..elseif..else (Flow Control)
in, ni
incr, decr, ++, --
info args
info cmdcount
info exists
info level
info winver
INI Handling Plugin
instr, strstr
int, double (Type Casting)
ip_to_long, long_to_ip
item (array, stack or struct)
K Combinator
Known Bugs and Feature Anomalies
Lambda Example
ldepth (proc)
left, string left
let (Assignment command)
lib (Ticol Plugin Module Extension Loader)
lib interface specifications
Line Continuation Character
Line Numbers
Linked List Plugin
List Processing Commands
Listing Files
loop (Flow Control)
Macro #if #exec #echo
Macro Constants
Macro Escape Sequences
malloc, free
man - Ticol Manual
Math Expressions
Math Operators
max, min
MD5 Batch Example
MD5 Verification
mid (Set String Middle)
mids (Return a String Midsection)
Miscellaneous Routines Plugin
Modulo Sign (Discussion)
Multi Line Commands
Multiple Commands
Namespaces and Scope
Networking Commands
Non Standard Tcl Commands
not (Bitwise and Logical)
Number Formats
ofaddress, addressof (Tcl Variable Address)
ofaddressb (Binary Buffer from Address)
open, file open
option  (Runtime Configuration Options)
option breakpoint, halt, resume
Passing Structs to a Procedure By Name
Passing Variables to Procedures by Name (by Reference)
Passing Variables to Procedures by Value
Performance Example
Performance Graph
pid, tid  (Process and Thread ID)
play_wav, stop_wav
Preset Global Variables and Constants
Print Functions
proc (Tcl Procedures)
proc args ($args) (See also args for the command)
procs (info procs) ?glob-pattern?
Recursion and Issues Arising
reserved variables
Returning Struct Variables from Procedures
right, string right
RTF Output Plugin
run - (Tcl script)
Running Scripts
semi colon
setb, struct setb
Shortcut Math Operators
Single Line Commands
Single Quotes
Some Common Mistakes
Stack Examples
static (static variables in Ticol)
String Comparison Operators
String Functions
string index
string isempty
string match
string range
string replace
string slice
string to_wchar
string tolower, string toupper, tolower, toupper
string trimleft - string trimright
struct clear
struct copy
struct create
struct dump
struct elements
struct elements
Struct Implementation Details
struct set
struct set, struct item
struct setb
struct size
struct unset
switch (Flow Control)
Tcl Arrays
Tcl Callbacks
Tcl Expression Functions
TCL History
Tcl Lists
Tcl Semantics
Tcl Strings
Tcl Syntax
TCP/IP Functionality
The Tcl Language
Ticol Big Integer Math Plugin
Ticol Command Line
Ticol Command Line Arguments
Ticol Command Line Interpreter (CLI)
Ticol Commands Grouped by Functionality
Ticol Compatibility with Standard Tcl
Ticol Copyright and Licensing
Ticol CPU Information Plugin
Ticol CRC32 Plugin
Ticol Design Goals
Ticol DHCP Plugin (Simple DHCP commands)
Ticol DNS Plugin (Simple DNS / Reverse DNS lookups)
Ticol Editor and Recommended IDE
Ticol Errors
Ticol External Plugins
Ticol FAQ - Frequently Asked Questions
Ticol FTP Plugin (Simple FTP Client)
Ticol Hints and Tips
Ticol ICMP Ping Plugin
Ticol Introspection and Reflection
Ticol is a Tcl interpreter, not a compiler!
Ticol Macro PreProcessor (MPP)
Ticol Macro PreProcessor (MPP)
Ticol Memory Allocation and Garbage-Collection
Ticol Performance and Efficiency
Ticol Registry Plugin (ANSI)
Ticol SMTP Mail Plugin
Ticol Tcl architecture
Ticol Tcl Interpreter for Windows
Ticol Tcl Interpreter v1.25 (C) M Shaw 2015-2017
Ticol Variables
Ticol Variant - A Simple Variant Handling Plugin
Ticol Windows Event Log Handling Plugin
Ticol Windows Service Query Plugin
Ticol Workarounds
Ticol XBase - A Simple Dbase III/IV Plugin
Ticol ZIP Plugin
ticol.ini - Configuration file for Ticol.exe
Tips for Writing Big Programs
tk Support
tohex, fromhex
try ... catch (Flow Control)
UNC Path Handling
undef command (Undefining Commands)
Unicode Support
unknown (proc)
unwrap (proc)
urlencode, urldecode
Useful Commands
Useful Debug Routines
Using Logical and/or Within Flow-Control Statements
Using Ticol as a Web CGI Application Back-End
Using Ticol With Batch Files
Variable Casting
Variant Array Functions
varray count
varray get
varray lbound
varray ubound
VB (Visual BASIC) Time
vwait (Requires threaded compile of Ticol)
while (Flow Control)
White Space
Why I Wrote Ticol Tcl?
Windows Dialogs
{*} - Argument Expansion Operator

Alphabetic Index of Built-In Ticol Commands  Top  
Code used to generate this list: foreach x [commands] { puts $x } puts "[lcount [commands]] commands" Count the commands using: puts [lcount [commands]] Redirect to a file in Windows using: ticol.exe ; "foreach x [commands] {puts $x}" /na > cmdlist.txt $ :: ! != % & && &= * ** *= + ++ += - -- -= / /= < << <= == > >= >> ? @ K ^ ^= add addressof addressofb after alias append apply args arity array array_foreach array_set asc assert at_exit autoexec base64 baseconv beep binary bintoint bool box break calc call carray catch cd cd.. char charcount chdir chr clear clearprocs clipboard clock close cls cmdcount cmp comma commands concat console const continue convbase copyfile cpu ctime_to_double cvn date date_to_ctime debug decr decrypt defined dict die dim diskfree disktype div do while do until doevents double double_to_ctime dummy dump dumpvariant echo elevate encrypt enum eof eq eqi eqn error escape eval event exec exit expr false fib file filesize find float flush for foreach format fpart fraction fromhex funct functions ge gei get_win_error getcwd getenv getfileopen getfilesave getkey gets getsid global goto goto_block gotoxy gpf gt gti halt help hextoint highlight hostname html http if in incr index info inkey input_csv inputbox instr int integral inttobin inttohex inttooct ip_to_long is_admin is_command is_const is_date is_dir is_dst is_elevated is_file is_leapyear is_list is_mod is_numeric is_pointer is_proc is_set join json_to_list lappend lassign lcount le left lei len let level lib lindex link_to_path linkedlist list list_to_array llength lmap load logo long long_to_ip loop lrand lrange ls lsearch lset lsort lt lti makestr man map max md md5 md5_file mean mem_used memset mid mids min mkdir mkn mod movefile msgbox mul ne nei new newline ni normal_path now null octtoint ofaddress ofaddressb open option pause pid play_wav printf proc procs put puts pwd rainbow randomstr range read readfile ren rename replacechar resume return rewind right rnd rot13 round rset run scan screen set setat setb setenv setresult shell short signed sizeof sleep slice source spawn split srand stack static stop stop_wav store string stripto striptor strptr strsplit strstr strtok struct sub subst swap switch sysfree tell test textcolor textcolour ticks time timer tohex tokenise trace true try type undef unescape unlink unset unsigned unwrap uplevel upvar urldecode urlencode username variable varray vars volume vsplit vwait walk wallpaper watch wchar_length wchar_to_string while wide win_error wrap writefile | |= || ~ See also: commands by function, Ticol, Tcl, faq
Ticol Commands Grouped by Functionality  Top  
Data Types and Type Manipulation -------------------------------- Relational: > < >= <= == != array array_to_list array_foreach array_set base64 carray const convbase ctime_to_double cvf cvi dict dim enum eq eqi eqn escape fromhex ge gei global gt gti hextoint inttobin inttohex inttooct is_const is_mod is_numeric is_proc is_set json_to_list le lei let lei let list_to_array linkedlist (Linked list plugin) long long_to_ip le lt lti map mkf mki ne nei new null octtoint rtf (RTF plugin) set short signed sizeof stack static subst swap tohex type unset unsigned variable varray vsplit wchar_length wchar_to_string wide Database -------- sql (SQLite plugin) xbase (DBase plugin) Date and Time ------------- clock ctime_to_double date date_to_ctime double_to_ctime is_date is_dst is_leapyear ticks time timer now Debugging --------- assert catch debug dump dumpvariant halt resume time trace try vars walk watch DLL and Struct Interface ------------------------ -> Dereference a struct field => Evaluate and dereference =>> Set a struct field value addressof addressofb class new ofaddress ofaddressb setb strptr struct Encryption, Compression, Randomness and MD5 ------------------------------------------- crc (CRC plugin) decrypt encrypt file_crc (CRC plugin) md5 md5_file randomstr rle (RLE plugin) rnd rot13 (Misc plugin) srand zip (ZIP plugin) File and Disk and I/O --------------------- cd cd.. chdir close copyfile diskfree disktype eof file filesize flush getcwd getfileopen getfilesave ini (INI Plugin) input_csv is_dir is_file link_to_path ls md mkdir movefile normal_path open pwd read readfile ren rename rewind tell unlink volume writefile Flow Control ------------ after arity at_exit break call catch clear clearprocs continue defined die do while do until doevents error exit for foreach funct goto goto_block halt if is_proc level loop proc procs resume return sleep stop switch try undef uplevel upvar vwait while Event Handling (Threaded compile of Ticol) ------------------------------------------ after vwait every (script) at (script) HTML and Internet ----------------- html http urldecode urlencode Information and Environment --------------------------- cpu info is_admin is_command is_elevated is_pointer $tcl_date $tcl_cli $tcl_threaded $tcl_version $tcl_precision $env $argc $argv $win64 List Handling ------------------------ apply array_to_list in is_list lappend lassign lcount lindex linkedlist (Plugin) lappend lassign lcount list list_to_array llength lmap lrand lrange lsearch lset lsort unwrap ni Logic ----- Logical and/or &&, || Bitwise and/or &, | Logical not ! Bitwise not ~ Combined: &=, |= bool false ($::false) true ($::true) xor Macro ----- #echo #else #endif #exec #exit #if #ifdef #ifndef #undef Math ---- Bitshift: << >> Increment: ++ Decrement: -- Combinational: +=, -=, *=, /=, ^= baseconv big (big number plugin) binary bintoint calc decr div double eval expr fib float fpart fraction incr int integral Math operators: + - * / ** ^ % max mean min mod mul round unescape Memory ------ free malloc memcpy memset store Network ------- arp (ARP plugin) cidr_match (Misc plugin) dns (DNS plugin) ftp (FTP plugin) hostname ip_from_host (Ping plugin) ip_match (Misc plugin) ip_to_long is_mac (Misc plugin) ping (Ping plugin) rarp (ARP plugin) sendmail (SMTP mail plugin) Program Execution ----------------- alias args autoexec cmdcount commands dump functions lib load option run source String ------ add append asc char chr cmp comma concat index instr join left makestr memset mid mids range replacechar right rset scan setat slice split string stripto striptor strsplit strstr strtok wrap User interaction and Display ---------------------------- beep box cls echo find format getkey gets gotoxy help inkey inputbox logo man msgbox newline pause printf puts rainbow screen textcolor textcolour Windows System Interaction -------------------------- clipboard console elevate event exec get_win_error getenv getsid info mem_used pid play_wav reg (registry plugin) setenv shell spawn stop_wav sysfree username wallpaper win_error See also: command list, Ticol, Tcl, faq
:: Double-colon (Scope symbol)  Top  
The double-colon symbol operates in a similar way to that found in C/C++ ::varname represents a variable in global (root) scope $::varname represents a dereferenced variable in global (root) scope Ticol does not support operational namespaces but can emulate them by allowing for the inclusion of pseudo-namespace prefixes such as... namespace::varname or $namespace::varname Example: set s "Hello world" proc foo {} { puts $::s } Result: Hello world For partial/embedded substituion, a variable name prefix may be isolated and forced by wrapping in curly braces. So to replace a variable placeholder which references a pseudo-namespace you would use, for example (where q holds the pseudo-namespace value) ${q}::varname This causes $q to be evaluated in preference to $q::varname See also: variables, dereference, set, namespace, global
Ticol Tcl architecture  Top  
This is a simplified block diagram of the unthreaded Ticol Tcl architecture +--+----------------------------------------------------------+ | 9| Tcl Command Line Interpreter (CLI) | EXE Command Line | +--+---------------------------+------------------------------+ | 8| tcl script | tcx script | |--| |------------------------------+ | 7| | Obfuscation Decoder/Encoder | +--+---------------------------+------------------------------+ | 6| Macro Preprocessor (MPP) | +--+----------------------------------------------------------+ | 5| Registered commands, [proc] registration, [undef] | +--+---------------------------+------------------------------+ | 4| [proc] | Known Tcl commands | +--+---------------------------+------------------------------+ | 3| [eval] | +--+---------------------------+------------------------------+ | 2| Tcl Parser | Registered [lib] commands | | | | [lib calldlll] | +--+---------------------------+------------------------------+ | 1| ticol.exe | External DLLs | +--+---------------------------+------------------------------+ The CLI or ticol.exe command line load plaintext or obfuscated scripts These are processed before execution by the Macro Preprocessor (MPP). The resulting script content may register [proc] instances and interact with any registered command The Macro PreProcessor (MPP) performs a number of tasks, including stripping out comment lines, processing the macro language and optimising [calc] expressions as well as performing basic sanity checks on the script All commands are evaluated internally by the internal 'eval' function which may also be called directly using [eval]. Eval parses the script content and breaks it up into commands and arguments. The [lib] command can load exported Tcl commands into the root namespace where they may be called the same as any other command (See: lib interface) See also: Ticol, Tcl, lib, Ticol, lib interface
{*} - Argument Expansion Operator  Top  
command {*}{word ?word...?} Translates a list into an argument array for a single command CAUTION: Use with care! If a word is prefixed with {*} followed by a non-whitespace character then the leading {*} is discarded and the rest of the word is parsed and substituted as for any normal Tcl word. (Word is analogous to a parameter or argument). The substitution process is equivalent to calling [subst] After substitution is complete, the word is then parsed as a Tcl list without command or variable substitutions. Backslash substitutions are performed as is normal for a list and individual internal words may be surrounded by either braces or double-quote characters. Its words are then added as individual arguments to the command being substituted Be extremely cautious not to accidentally use an unquoted "{*}" string within your code where you do not intend it to expand arguments. e.g. don't use... puts [unescape "[string repeat 80 {*}]\\highlight0\\cf0\\par "] as this will attempt to expand within the nested call to [string repeat] and will lead to impossible to debug errors Supplying a whitespace character (tab or space) after {*} is unlawful For instance: cmd a {*}{b [c]} d {*}{$e f {g h}} is equivalent to supplying: cmd a b {[c]} d {$e} f {g h} And results in the effective arguments: a b {[c]} d {$e} f g h ...being passed to a command Example: set a "puts Hello" # Set var to a command with args $a # Attempt to dereference to a command with args {*}$a # Correct method of dereferencing Results puts' is not recognized as an internal or external command Hello Example: # Unset all variables 'a' to 'z' (supplying individual arguments) unset {*}[split [range a-z]] -nocomplain Example: set square {lmap {x {expr $x * $x}}} # Lambda like call puts [{*}$square 42] Result: 1764 See also: subst
semi colon  Top  
A semi-colon is used as a punctuator between groups of statements It marks the absolute end of a command list and acts equivalent to a newline character. Example: set a 0;puts "hello";incr a;puts "a is $a" # Is equivalent to set a 0 puts "hello" incr a puts "a is $a" Result: hello a is 1 Statements which require to pass multiple commands as a single argument must be braced, thus: some-command {arg1; arg2; arg3} otherwise the command string will be interpreted as: some-command arg1 arg2 arg3 This should be particularly noted with commands which take a script element as an argument such as [after] Command Line Use: A semi-colon may also be used as the first argument to ticol.exe to specify a "dummy" script file which is never executed. If specified then any remaining arguments will be evaluated by the Ticol Command line Interpreter (CLI) within the same interpreter instance Example Command Line: ticol.exe ; "set a 0;puts hello;incr a;puts \"a is $a\"" Result: hello a is 1 Example: ticol.exe ; "puts \"Hello\tworld\"" Result: Hello world See also: syntax, Tcl
ofaddress, addressof (Tcl Variable Address)  Top  
integer [addressof variable] string [ofaddress pointer-variable|address-literal-value -string] [addressof] returns the address of a standard Tcl variable object (not the variable's data buffer) and stores it as a string record of that address. [ofaddress] performs the inverse operation. The two functions are provides for use in conjunction with calldll and calldll_cdecl [addressof] [addressofb],[set],[$] # Get address | | v v +---------------------+ +---------------------+ | Tcl Variable Object | -> | Variable Data Block | +---------------------+ +---------------------+ | | v v [ofaddress] [ofaddressb] # Dereference Where a variable is passed to [ofaddress], the address stored in the internal buffer is dereferenced and the result is returned. Where an integer literal is passed to [ofaddress], the value is assumed to be an address and it is dereferenced back to a buffer address By comparison with C/C++, [addressofb] returns the equivalent of LPSTR* or LPPSTR (char**) If a string value is being dereferenced the '-string' argument is required, otherwise the string may be truncated. Note that you cannot evaluate [ofaddress "literal-string"] Such a value must be an integer pointer variable address value returned by [addressof] To return a string from pointer value set by [struct setb var] use: [ofaddress $var] To return string as char array use: [ofaddress var] When using [calldll*] the address of a Tcl variable buffer/string pointer by value may be passed by using [addressofb variable] to pass the literal string address (LPSTR). strptr is an alias for addressofb For Ticol structs, member values refer to an offset in the struct data block: struct s {a 5 b 10 c 20} Tcl var Address Struct byte offset ----------------------------------------------------- s => 32542464 (0x1f08f00) 0 s.a => 32542464 (0x1f08f00) 0 s.b => 32542469 (0x1f08f05) 5 s.c => 32542479 (0x1f08f0f) 15 In the above example, both $s and $s.a is 32542464, $s.b is 32542469 etc. See also: setb, ofaddressb, calldll, calldll_cdecl, struct
addressofb, strptr (Binary Buffer Address)  Top  
integer [addressofb variable] string [strptr variable] Inverse of [ofaddressb] [addressofb] and [ofaddressb] are 'unsafe' Returns the address of the binary string buffer of a variable/string [addressofb] (or [strptr]) returns the equivalent of LPSTR or (char*) The command performs a similar function to VarPtr() in Visual BASIC [addressof] [addressofb],[set],[$] | | v v +---------------------+ +-----------------------+ | Tcl Variable Object | -> | Variable's Data Block | +---------------------+ +-----------------------+ | | v v [ofaddress] [ofaddressb] The [addressof] command, unlike [addressofb], returns the address of a Ticol variable as a numeric string which can be dereferenced back using ofaddress However, this does not point to the variable's string buffer and is not, therefore suitable to pass via a [calldll*] to a DLL. Instead, [addressofb] should be used to return the true string buffer address [addressofb] may be used to pass the address of a Tcl variable's string buffer to an external DLL where the contents will be recovered and used in your program. Care should be taken to avoid buffer overflows. It is preferable to use a struct when passing data to external DLLs [strptr] is a friendly alias for [addressofb] Retrieve 2 byte short value: [ofaddressb var 2] Retrieve 4 byte long value: [ofaddressb var 4] Retrieve 8 byte int64 value: [ofaddressb var 8] Retrieve 256 byte struct 's': [ofaddressb s 256] Example: set timeout 0 set datalen 64 set buf [makestr 16] # Create 16 byte buffer as Tcl variable # Call ping32.dll, passing the binary address of the Tcl buffer # data block, which will receive the return data calldll ping32 PingAPI google.com [addressofb buf]:4 datalen:2\ timeout:4 1000 puts $buf Result: See also ofaddressb See also: addressof, ofaddress, ofaddressb, set, setb, calldll
ofaddressb (Binary Buffer from Address)  Top  
string [ofaddressb struct-variable ?byte-width?] Inverse of [addressofb] [addressofb] and [ofaddressb] are 'unsafe' Return a binary interpretation of data pointed to in a struct field by the struct-variable. Normally a string interpretation of the memory location is returned [addressof] [addressofb],[set],[$] | | v v +---------------------+ +-----------------------+ | Tcl Variable Object | -> | Variable's Data Block | +---------------------+ +-----------------------+ | | v v [ofaddress] [ofaddressb] This will usually be unprintable without using [tohex]. What is often required is to retrieve a literal numeric value written to memory by [struct setb] which is the inverse function. [ofaddress] could be used but that will simply map 'n' bytes from the given memory location On Windows Intel platforms the data is stored in inverted 'little endian' format (byte order is reversed) A byte-width can be specified but this will be rounded to 1,2,4 or 8 bits You must correctly supply the bit-width interpretation of the data to match the struct storage field definition. The default bit-width is 4 (a DWORD or 32-bit long) Example: (where field2 is defined as 8 bytes width) struct s {field 8} # Single-field struct struct setb s.field 123 # Set member field to 123 binary (0x7b) puts [ofaddressb s.field 8] # Retrieve and display Dump: 008f3440 00 00 00 00 00 00 00 00 - 00 00 00 7B 00 00 00 00 ...........{.... -- -- -- -- 00 00 00 7B Result: 123 See also: addressof, ofaddress, struct, calldll, calldll_cdecl
after, every (script)  Top  
after milliseconds command ?arg? ?arg...? after milliseconds {script} after milliseconds {run scriptfile} after milliseconds {eval scriptfile} Threaded Ticol versions *: after info after count Run a command after a given number of milliseconds For unthreaded releases of Ticol, processing will halt until the specified time-interval has elapsed. [after] is implemented as a simple time-delay (see notes below) For experimental, threaded releases of Ticol; [after] is event-driven and will run asynchronously with main scripts with separate [after] scripts interleaved The threaded version of Ticol multitasks at script rather than command- level. [after] and [run] lock mutually so [after] cannot launch either [after] or [run] whilst a script is in progress from either of these commands Interaction with scripts launched using [after] should be controlled using [vwait]. A continuously running script will typically block an [after] script. Consider rewriting scripts which need to run continually as an [every] proc which can be polled at intervals rather than run in a main script loop (see below) Extreme care should be taken to avoid scripts clashing, particularly with respect to common variables or procedures. Pseudo namespace variables may be used outside procs. Procs will have their own temporary namespace A proc return value can be passed to any variable which may then be used as a [vwait] control flag, thus: after 2500 {set vret [draw_logo yellow $cursor_yloc]} vwait vret [vwait] will suspend the current script until the named variable changes [after] events do not interact with the CLI as these run under a separate thread Note: Be careful to brace [after] arguments and not use: after 4000 set vret [foo] as the unbraced [foo] proc will be called before [after] and thus polled immediately Threaded versions can be detected via the const '::tcl_threaded' e.g. if {$tcl_threaded} { # Call some [after] code } Arguments will be concatenated with a space. Formatting and grouping may be maintained by wrapping arguments in braces Multiple commands may be specified by using an intervening semi-colon (;) An [every] command may be defined using a simple 4-line script (see below) An [at] command can be defined using an 11-line procedure Unthreaded Compile Example: # Unthreaded version example # Instructions are executed sequentially after a simple delay after 1000 box 3 3 20 10 - blue after 1000 load demo.tcl after 1000 run after 1000 puts {"hello world"} after 1000 {puts "hello there...";} {puts "How are you?"} after 1000 goto 10 after 2000 ping Threaded Version Example: proc every {ms code} { eval $code after $ms every $ms $code # Respawn } set done 0 set i 0 proc tick {} { ++ ::i if {> $::i 4} {set ::done 1} } every 1000 tick # Tick once per second vwait done puts "Finished ticking at $i" Results: Finished ticking at 5 Threaded Version Example (A simple 'DOS TSR-like' clock) # When run from the CLI the CLI will remain interactive proc every {ms code} { eval $code after $ms every $ms $code # Respawn } every 1000 { set x [screen curx] set y [screen cury] gotoxy 72 1 textcolor white blue; puts [time] -nonewline textcolor gotoxy $x $y } Threaded Compile Example (A useful Tcl [at] scheduler) # Be careful to avoid calling the Windows 'at' command if {! [defined at]} { proc at {time args} { global at_flag if {[>= [date $time] [fraction [date now]]] } { set dt [int [* 86400000 [- [date $time] \ [fraction [date now]]]]] } else { set dt [int [* 86400000 [- [+ [date $time] 1] \ [fraction [date now]]]]] } after $dt $args return [/ $dt 1000] # Convert ms to seconds } } at 23:59 {puts "The witching hour is nigh!"} * Threaded Ticol is currently experimental See also: vwait, time
Using Logical and/or Within Flow-Control Statements  Top  
Using with: 'option expression off' (forcing non-expression syntax): && || Will perform logical operations on arguments Arguments will be evaluated as true or false & | Will perform bitwise operations on arguments 0b10 & 0b01 == 1 # i.e. true and true -> true Note that sub-expression which are to be tested using logical and/or MUST be bracketed, e.g. ((22/7==3) and (12>1)) Example: if {[expr ($k != 4) && ($k != 6) && ($k != 9) && ($k != 11)]} { ... Due to the structure of the Tcl language, compound expressions with [if] command which use 'and' or 'or' may become complicated. You can either pass to an [expr] statement or wrap multiple bracketed statements as follows: if { [&& [statement1] [statement2] } { ... if { [|| [statement1] [statement2] } { ... if { [expr [statement1] || [statement2]] } { ... if { [expr [statement1] && [statement2]] } { ... Or you can use [option expression on] which will enable expressions for flow control structures. Commands presented in [] format are evaluated before the outer expression statement... if { [statement1] || [statement2] } { ... if { [statement1] && [statement2] } { ... option expression off for {set i 0} {< $i $adapter_count} {incr i} { set addr [info ip_address $i] if { [&& [ne $addr ""] [ne $addr "127.0,0.1"]] } { set adapter $i break } } Example: # if $op is * and (a xor b) is -ve then option a else option b ... if {[eq $op *] && [^ [eq $a "-"] [eq $b "-"]] } { You may also nest 'if' statements to achieve the same effect as 'and' option expression off for {set i 0} {< $i $adapter_count} {incr i} { if { ne [info ip_address $i] ""} { if { ne [info ip_address $i] "127.0,0.1"} { set adapter $i break } } } [if.. else] statements may be used to replicate 'or' constructs -- Using with: 'option expression on' or with [expr] Logical operators &&, || (and, or) are evaluated left-to-right Complex expressions using logical combination operators should be properly bracketed. e.g. 'if {(22/7)==3 && (12>1)} {puts yes} else {puts no}' Expressions may combine individual values, bitwise to yield a testable result: expr "1 || 2 || 4" You may still use bracketed 'eval' type expressions See also: if
alias  Top  
alias alias-name existing-command alias alias-name existing-proc Create an alias of a proc or command. The command or proc being aliased must exist and the alias must not exist An alias can be undefined using [undef] Example: alias fred puts fred "Hello world" Results: Hello world See also: undef, proc, commands
append  Top  
append variable value ?value? ... Append a value or series of values to a variable. If the variable does not exist it will be created and any arguments appended to it. Append provides an efficient means of concatenating variables To concatenate strings without passing to a variable see: concat Example: option expression off set var 0 for {set i 1} {<= $i 10} {incr i} { append var "," $i } puts $var Result: 0,1,2,3,4,5,6,7,8,9,10 See also: concat, set, string
apply  Top  
string [apply funct ?arg arg2 ...?] Apply an anonymous function The command apply applies the function func to the arguments arg1 arg2 ... and returns the result. In mathematics apply is a function that applies functions to arguments. It is key to programming languages derived from lambda calculus, such as LISP and also in functional languages The function 'func' is a two element list {args body} or a three element list {args body namespace} (as if the list command had been used). Note that namespaces are only emulated in Ticol The first element args specifies the formal arguments to func. The invocation of apply adds a call frame to Ticol's evaluation stack and acts in equivalent manner to [proc]. So the [info level] value will be +1 higher than the calling frame Empty function args and an empty arglist as {} are acceptable The specification of the formal arguments args is shared with the proc command. See: proc Example: This shows how to make a simple general command that applies a transformation to each element of a list proc lmap {lambda list} { set result {} foreach item $list { lappend result [apply $lambda $item] } return $result } lmap {x {return [string length $x]:$x}} {a bb ccc dddd} lmap {x {expr {$x**2 + 3*$x - 2}}} {-4 -3 -2 -1 0 1 2 3 4} Results: 1:a 2:bb 3:ccc 4:dddd 2 -2 -4 -4 -2 2 8 16 26 Example: puts [apply {{x y} {expr hypot($x,$y)}} 3 4] Result: 5.0 Example: puts [apply {{} {return [info level]}} {}] # Show frame level Result: 1 See: http://wiki.tcl.tk/4884 http://wiki.tcl.tk/5892 https://en.wikipedia.org/wiki/Apply https://www.tcl.tk/man/tcl/TclCmd/apply.htm See also: proc, lassign, K, uplevel, lmap, map, lambda
argv and argc  Top  
::argc is always defined. ::argv will be defined only if there are arguments If a script is launched via ticol.exe's command-line then argc will always be at least 1 and argv(0) will contain the full path and name of the script file. This applies to both TCL and TCX filetypes. If there are no command-line arguments then argv will not be set and argc will be 0. Use [is_set] or ::argc to check if argv exists before processing Example: Command: ticol.exe argv.tcl 1 2 3 argv.tcl: array walk argv Result: -------------------------------------------- hash_table object:0x3c4088 size:250 -------------------------------------------- Bucket(1) Node: 0x20a3f10 chained nodes:1 1: 0x20a3f10 key:'0' => 'argv.tcl' Bucket(69) Node: 0x20a3fd0 chained nodes:1 1: 0x20a3fd0 key:'3' => '3' Bucket(94) Node: 0x20a3f50 chained nodes:1 1: 0x20a3f50 key:'1' => '1' Bucket(135) Node: 0x20a3f90 chained nodes:1 1: 0x20a3f90 key:'2' => '2' Caution! -------- If a Ticol filetype (tcl/tcx) is associated with the Windows shell then this behaviour will differ unless the association definition has been modified to include command line arguments. Simply associating TCL or TCX files with Ticol.exe is insufficient to pass command line arguments. For this reason, take extreme care in launching Ticol scripts via Windows file associations Example: Command: argv.tcx 1 2 3 argv.tcx: array walk argv Result: (argv higher than 0 is not passed via the command-line) --------------------------------------------------------------- hash_table object:0x5c4088 size:250 --------------------------------------------------------------- Bucket(1) Node: 0x2113f40 chained nodes:1 1: 0x2113f40 key:'0' => 'C:\\VC5\\MyProjects\\picol\\Re...' Example: if {is_set argv} { array foreach argv val ss { puts "argv($ss)='$val'" } } See also: globals, array item
args (proc variable or command)  Top  
proc <name> {args} {... # Variable args argument-list... # Command $args proc variable ------------------ $args is a procedure variable which acts analogously to the C++ elipsis pseudo variable placeholder. Where specified,'args' will contain all subsequent arguments similar to the "C" elipsis (...) Example: proc foo {args} { puts "\$args=='$args'" } foo 1 2 3 4 Result: $args=='1 2 3 4' [args] command -------------- See: proc args for additional information The [args] command is a dummy debugging command which simply echoes its argument list. This is useful for debugging procedure or command arguments Example: (Using the {*} expand operator) args a {*}{b [c]} d {*}{$e f {g h}} Result: 0 'args' 1 'a' 2 'b' 3 '{[c]}' 4 'd' 5 '{$e}' 6 'f' 7 'g h' See also: debugging
proc args ($args) (See also args for the command)  Top  
proc {argument-list ... args} { ... The special variable 'args' may be defined as the last argument of a procedure. When defined this variable will receive a list of zero or more arguments which are supplied when the proc is called. It is similar in function to the C/C++ elipsis function argument "..." If the special argument, 'args', is not specified as the final argument of a proc then any excess arguments supplied when the proc is called will be discarded and ignored When including several scripts it is recommended to ensure procs from other scripts are cleaned-up before defining using [undef], e.g. undef foo -nocomplain Example: proc foo {a args} { # Will include unlimited trailing args puts "foo a is '$a'" puts "foo args is '$args'" } proc bar {a} { # Will allow only one arg puts "bar a is '$a'" } foo Hello foo Hello World foo Hello World How {Are You} Today newline bar Hello bar Hello World bar Hello World How {Are You} Today newline Results: foo a is 'Hello' foo args is '' foo a is 'Hello' foo args is 'World' foo a is 'Hello' foo args is 'World How {Are You} Today' bar a is 'Hello' bar a is 'Hello' bar a is 'Hello' Example: proc foo {x y} { ... Example: proc demo {first {second "two"} args} { ... Results: See: proc for more information See also: proc, args
Function Arity  Top  
Arity is the number of arguments presented to a given function. There are a variety of functions available either within expr or funct as follows: The command [arity] will return the arity of a built-in function Function Arity 0 ---------------- srand Initialise the random number generator rand Return double random value from 0 to 1 The rand() and srand() functions are not cryptographically secure, and should not be used to generate one-time passwords or session keys Link to the Windows API using [calldll] instead Function Arity 1 ---------------- abs value Return the absolute value of a number acos value Return the arc cosine of value (arccos) asin value Return the arc sin of value (arcsin) atan value Return the arc tangent of value (arctan) bool value Evaluates a string and returns 1 or 0 ceil value Round to the next-highest integer value cos/cosh value Return the cosine of value decr value Decrement value degrees value Convert radians to degrees double value Cast value to double exp value Return the exponent of value fib value Return the fibonacci of value fix value Return integer value rounded up floor value Round to the next-lowest integer value fraction value Return the fraction part of a real/double incr value Increment value int value Cast value to integer integral value Return the integer part of a real/double log value Return the logarithm of value log10 value Return the log10 of value round value (0 places) Round value to 0 places using standard rounding sgn value Return the sign as an integer (1, 0, -1) sin/sinh value Return the sine of value sqr value Return the square of value sqrt value Return the square-root of value srand seed Seed the random number generator tan/tanh value Return the tangent of value wide value Force a value to 64 bit signed integer Function Arity 2 ---------------- div a b Functional division of a / b fmod a b Return the remainder of a / b hypot a b Return the hypotenuse of a and b max a b Return the maximum of a and b min a b Return the minimum of a and b mul a b Functional multiplication of a * b pow a b Return a to the power of b rnd a b Return a random number between a and b inclusive round a b (b places) Round a to b decimal places You can use the [functions] command to get a list of supported [expr] functions You can use the [funct] command to export and access an expression function See also: arity, functions, funct, expr, eval
arity  Top  
integer [arity functname] Return the arity count of an inbuilt function as an integer value If the function is not found then -1 is returned Example: puts [arity rand] # No arguments puts [arity abs] # One argument puts [arity max] # Two arguments (funct) puts [arity fred] # No such command Results 0 1 2 -1 For an arity list of each available function. See: function arity See also: function arity, expression functions, functions, funct, expr, eval
ARP Address Resolution Protocol and RARP (Reverse ARP) Plugin  Top  
Load using: lib ticol_arp?.dll? arp ipv4-address ?-list? # ARP lookup of IPV4 address arp table # Return the ARP table as a Tcl list rarp mac-address ?-list? # Reverse ARP lookup. Look up in ARP table Address Resolution Protocol (ARP queries will query the local Arp table. Results will depend on the content of the Arp table [arp] returns a string value and may return an empty string for interfaces which return no MAC address.No mac address is returned for addresses which cross NAT firewalls or for loopback/dummy interfaces. Such addresses must be on the same LAN [arp table] returns a Tcl list with one {ip-address mac-address status} list per interface found [rarp] can only return results for "known" IPV4 addresses which have been discovered and placed in the local ARP table cache. Your workstation must have been in conversation with these addresses, (e.g. via ping) Lookups which return empty {} string are not fatal errors. The return should be tested to see if the return value is empty, which indicates the IP or MAC address was not found For exceptions such as malformed IP or MAC addresses an error exception is raised with an internal ARP library error code or a Windows system error code The -list option will return a list which includes the error code as the 2nd item. [arp] Error Codes ----------------------------------------------------------------- 0 Success 1 Success but empty MAC address returned 2 Failed to load iphlpapil.dll 3 Failed to link to lib function SendARP 4 MakeMacAddress failed 5 Bad PMAC buffer 6 Bad IP address 7 Unhandled error * SendArp API error code 31 ERROR_GEN_FAILURE (Network error/disconnected interface) 50 ERROR_NOT_SUPPORTED 67 ERROR_BAD_NET_NAME 87 ERROR_INVALID_PARAMETER 111 ERROR_BUFFER_OVERFLOW 1168 ERROR_NOT_FOUND 1784 ERROR_INVALID_USER_BUFFER [rarp] Error Codes ----------------------------------------------------------------- 0 Success (match found) 1 Failure (no match) 2 Bad MAC address 3 Bad MAC format 4 Unknown/unhandled error Example: puts [arp table] Result: { 00-00-00-00-00-00 Static} { 00-00-00-00-00-00 St atic} { 00-00-00-00-00-00 Static} Example: set t [arp table] foreach l $t { # foreach list item foreach {i m s} $l { # IP, MAC, Status puts "$i\t$m\t$s" } } Result: 00-00-00-00-00-00 Static 00-00-00-00-00-00 Static 00-00-00-00-00-00 Static Examples: arp # Loopback adapter arp # Google DNS arp # Class C local IPV4 address rarp 3c46d8cc5cce # Must be in the ARP table (ping first) rarp beefdeadbeef # Must be in the ARP table (ping first) Results: {} # Empty string as loopback adapter not in cache {} # Empty string as 8.8,8.8 is an internet address 3c46d8cc5cce # MAC address of workstation on local LAN # Reverse lookup from MAC to IP {} # No such MAC address in the ARP table Examples: arp -list # No such address? rarp pqrs -list # Bad MAC address Result: {} 31 # Empty return + network error See also: ping, dns, dhcp, plugins
array - Manipulate Tcl Arrays  Top  
Various commands for manipulating standard Tcl arrays. Arrays are also addressed and dereferenced using the dollar ($) sign in the same way as for languages such as PHP Example: set a(0) Hello puts $a(0) Example: set a(0) Hello puts [array item a 0] Example: set a(0) Hello puts [array get a 0] See: help array <subcommand> e.g.: help array list arrays Information about standard Tcl arrays array create arrayVar ?n? Create an empty array array exists arrayVar Return boolean true if the array exists array find arrayVar string Return index/subscript or empty string array foreach arrayVar v s code Alias for [array_foreach] array get arrayVar Return an array as a key + value list array is_set arrayVar Returns boolean 1 if array exists else 0 array item arrayVar subscript Ambiguous array indexing with options array list arrayVar Exports an array to an unsorted Tcl list array names arrayVar Returns a list of array subscript values array set arrayVar list Set an array using a list of parameters array size arrayVar Return the size of an array if it exists array sort arrayVar Exports the array to a sorted Tcl list array statistics arrayVar Show statistics for a given array array trim arrayVar ?mask? Trim L/H and R/H end of array values array unset arrayVar Delete an array + all allocated elements array walk arrayVar Walk the array hash-table See also: arrays, variant arrays, array_foreach, passing variables by name
array foreach  Top  
array_foreach arrayName valueVar ?subscriptVar? {code} array foreach arrayName valueVar ?subscriptVar? {code} Iterate an array applying a block of code with each element's value passed into valVar and, optionally, the array's subscript value passed into subscriptVar. The array element value precedes subscript due to subscript being an optional parameter array_foreach is functionally equivalent to a combination of foreach and [array get] but is more efficient and faster foreach {x y} [array get env] { printf "%-20.20s\t=%-45.45s\r\n" $x $y } Tcl arrays are associative and unsorted. Arrays will be retrieved in random (unsorted) order. [array_foreach] may also be called as [array foreach] Example: set i 0 array_foreach env val ss { printf "$i:\t%-20.20s=%-45.45s\n" $ss $val incr i } Result: (prints out environment table) 1: ProgramFiles =C:\Program Files (x86) 2: USERPROFILE =C:\Users\Admin Example: ticol.exe ; "set i 0; array_foreach env x {puts $i:$x;[incr i]}" Result: Prints out environment See also: foreach, arrays, array
array create  Top  
array create arrayName ?size? Alias for [dim arrayName size] Creates a Tcl associative array with the default pre-allocation of 1 If 'size' is specified then the array will have memory preallocated to that size. This will prevent a need to reorganise the storage table on the fly It is not mandatory to use [array create]. Arrays will be created on first use as with standard varibles, for example, the statement: set a(0) Hello will create array 'a' and array element '0' [array set] will be the most common means of creating arrays with pre- determined contents, e.g. array set colours { red 1 green 2 blue 3 white 4 } will create array 'colours' with 4 elements Example: array create names 10 array walk names Results: ----------------------------------------------------------------- hash_table object:0x35ec650 size:10 ----------------------------------------------------------------- Hash Table Statistics: Root size:10 Occupation:0 (0.00%) Max depth:0 Nodes:0 ----------------------------------------------------------------- See also: array, arrays, dim
array_to_list  Top  
array_to_list arrayvar ?listvar? Converts an array to a well-formed but unsorted Tcl list containing pairs of keys (subscripts) and matching values. Optionally this list can be passed into an output variable. Both the array and optional list variables must be passed by name Use [lsort] to sort the resulting list Example: set q [lsort [array_to_list env]] puts "Returned [lcount q] item(s)" newline set i 1 foreach pair $q { foreach {l r} $pair { puts "$i\t$l\t=$r" } ++ i } Result: 1 ALLUSERSPROFILE =C:\ProgramData 2 APPDATA =C:\Users\Admin\AppData\Roaming 3 COMPUTERNAME =FIDO 4 ComSpec =C:\Windows\system32\cmd.exe 5 CommonProgramFiles =C:\Program Files (x86)\Common Files 6 CommonProgramFiles(x86) =C:\Program Files (x86)\Common Files 7 CommonProgramW6432 =C:\Program Files\Common Files ... See also: list_to_array, lsort, array, list
array is_set  Top  
array is_set arrayVar Returns boolean 1 if array exists, otherwise 0 Example: set a(0) Hello puts [bool [array is_set foo]] puts [bool [array is_set a]] Result: false true See also: is_set
array exists  Top  
Return a boolean indicating if an array exists array exists arrayName array exists arrayName(element) When used with the name of an array variable this tests only if the array variable name has been set. This does not guarantee any elements in the array are assigned. To check the size of an array use [array size arrayName] An array element represents a single variable bound to an array and should be tested using [array exists arrayName(element)] You may also use [info exists varname] to test for an array element In all cases the variable to be tested must NOT be prefixed by a dollar $ sign Case will be ignored when searching for the special system arrays 'env' and 'argv' Examples: array exists argv array exists env array exists argv(0) array exists env(TEMP) info exists argv(0) info exists env(TEMP) See also: is_set, is_empty, arrays, array, array size, info exists
array find (Reverse array lookup)  Top  
array find arrayName valuestring Searches an array by looking up a value to return the index/subscript of the first matching item with full string match, or an empty string if the item does not exist. The match is case-sensitive and will match the entire string. It will not match a substring [array find] is not a standard Tcl command and is much less efficient than subscript indexing, but should be adequate for small arrays of less than a few thousand elements Example: split $qbf " " -array a # Split into integer-indexed array set i [array find a "fox"] puts "fox is in element '$i'" Results: fox is in element '3' Example: array set fruits { # Subscript/key # Value blue berry green apple orange orange red cherry yellow lemon } set i [array find fruits cherry] puts "cherry is in element '$i'" Results: cherry is in element 'red' See also: arrays
array get  Top  
list [array get arrayname] string [array get arrayName ?mode? ?pattern?] string [array get arrayName ?pattern? ?mode?] Return an array as a key + value list. [array get arrayName] will return the entire array as a list of pairs of keys+values Where ?mode? is any of: -glob Wildcard string matching (the default) -exact Exact string matching (-glob is the default) -all Return all items and optionally: -nocase Ignore case when making comparisons Note that array get is less efficient than direct array addressing as Tcl associative arrays are hashed and meant to be indexed efficiently by the precise key value (subscript) Case will be ignored automatically for arrays set using -nocase or for the special global arrays env and argv Example: array get env u* Result: USERPROFILE C:\Users\Admin USERNAME Admin USERDOMAIN SNOOPY Example: (Prints out the environment table) foreach {x y} [array get env] {puts $x=$y} Result: ProgramFiles=C:\Program Files (x86) USERPROFILE=C:\Users\Admin OS=Windows_NT ComSpec=C:\Windows\system32\cmd.exe PROCESSOR_ARCHITEW6432=AMD64 SystemDrive=C: Example: foreach x [lsort [array get env -nocase -pair]] { puts [lindex $x 0]=[lindex $x 1] } Result: ALLUSERSPROFILE=C:\ProgramData APPDATA=C:\Users\Admin\AppData\Roaming HOMEDRIVE=C: HOMEPATH=\Users\Admin LOCALAPPDATA=C:\Users\Admin\AppData\Local USERNAME=Admin WINDIR=C:\Windows Example: foreach {x y} [array get env proc* -nocase] {puts $x=$y} Result: PROCESSOR_ARCHITEW6432=AMD64 PROCESSOR_IDENTIFIER=Intel64 Family 6 Model 37 Stepping 5, GenuineIntel PROCESSOR_REVISION=2505 PROCESSOR_LEVEL=6 PROCESSOR_ARCHITECTURE=x86 Example: puts [wrap [array get env -glob c*] 60] Results: ComSpec C:\\Windows\\system32\\cmd.exe COMPUTERNAME LENOVO C ommonProgramFiles(x86) {C:\\Program Files (x86)\\Common File s} CommonProgramFiles {C:\\Program Files (x86)\\Common Files } CommonProgramW6432 {C:\\Program Files\\Common Files} COMMP ath {C:\\Program Files\\Lenovo\\Communications Utility} See also: array names, arrays, array, info exists
array list  Top  
array list arrayName Exports the array values to an unsorted Tcl list Note that this does not include the array subscripts. Ticol lists are slow and inefficient, particularly when used to store large numbers of items (> 1000 or more). For small lists the difference in performance is insignificant Example: # Export and iterate each list value item foreach {x} [array list env] { puts $x } Result: C:\Program Files C:\Users\Admin\AppData\Local C:\Users\Public C:\Users\Admin\AppData\Roaming C:\ProgramData $P$G See also: arrays, array names, array item
array item  Top  
array item arrayName subScript ?default value? ?-nocase? Resolve an array index with optional default return value. This is helpful since associative arrays may be 'sparse' and there may therefore be no guarantee that any element exists at all [array item] is not a standard Tcl command and it offers a safe lookup of arrays. The standard, 'inline' method of referencing arrays will return a fatal error where the array element does not exist. [array item] will instead return an empty string where the array element does not exist The referenced array itself must exist. [array item] may be combined with [array exists array subscript -nocase] to safely handle ambiguous/case-insensitive array lookups If the element is not found and a default value given then the default value will be returned. This permits safe/simple array lookups with defaults A fatal error is raised only where the referenced array does not exist The variable name argument must not be dereferenced using the $ symbol Correct: puts [array item env temp -nocase] Wrong: puts [array item $env temp -nocase] # $env returns the tag "<array>" Example: array set smtp_code { # Array of SMTP error codes 221 "Server ready" 250 "Send success" 252 "Cannot verify user, but it will deliver" } puts [array item smtp_code 250 "Unknown error"] puts [array item smtp_code 251 "Unknown error"] Result: Server ready Unknown error See also: array, arrays
array names  Top  
array names arrayName ?mode? ?pattern? Where ?mode? is any of: -glob Wildcard string matching (the default) -exact Exact string matching (-glob is the default) -nocase Ignore case when making comparisons -all Return all items Returns a list of array subscript values (array element name identifiers) Case will be ignored automatically for arrays set using -nocase or for the special global arrays env and argv Example: puts [array names env u*] Result: USERPROFILE USERNAME USERDOMAIN Example: foreach {x} [array names env t* -nocase] {puts "$x\t$env($x)"} Result: TEMP C:\Users\Admin\AppData\Local\Temp TMP C:\Users\Admin\AppData\Local\Temp Example: foreach {x} [array names env -exact windir] {puts "$x=$env($x)"} Result: windir=C:\Windows See: array get for similar examples See also: arrays
array set  Top  
array set arrayName list ?-const? ?-nocase? Set and initialise an array using a list of parameters. This may be a single Tcl list or series of arguments. [array set] cannot be used to append items to an existing array. The array must not already exist The standard Tcl command is extended to add constant (-const) and case- significance attributes (-nocase). Arrays which are constant cannot be reassigned. Arrays which are set using -nocase will be much less efficient but can be indexed by subscript values in a case-insensitive manner. Scripts should be designed to use large arrays in a case-sensitive manner. For small arrays the performance impact will be negligible A subst is performed on array pairs before assignment. Variables are substituted and escaped characters are translated. Commands are not executed Use: [set array(subscript) value] - to set individual array elements [array create] can be used to create an array without assigning any elements and [array create size] can be used to pre-allocate an array of a fixed size to avoid time-consuming dynamic reallocation Example: array set colours { red 1 green 2 blue 3 white 4 } array set colours {red 1 green 2 blue 3 white 4} array walk colours array_foreach colours a b { printf "%s\t%s\n" $b $a} Result: --------------------------------------------- hash_table::walk() Object:0x1df43f0 size:250 --------------------------------------------- Bucket(138) Node: 0x1e08840 chained nodes:1 1: 0x1e08840 key:'green' value:'2' Bucket(140) Node: 0x1e08870 chained nodes:1 1: 0x1e08870 key:'blue' value:'3' Bucket(181) Node: 0x1e088a0 chained nodes:1 1: 0x1e088a0 key:'white' value:'4' Bucket(238) Node: 0x1e08810 chained nodes:1 1: 0x1e08810 key:'red' value:'1' green 2 blue 3 white 4 red 1 Example: (Calling commands and passing the result into [array set] set p [expr 4*atan(1)] set bp [expr 22/7.0] array set mathstuff { pie $p badpie $bp } array foreach mathstuff v ss { puts "Item: $ss\tValue '$v'" } Result: Item: badpie Value '3.142857142857143' Item: pie Value '3.141592653589792' See also: set, array, arrays
array size  Top  
array size arrayName # Return the size of an array if it exists If the array is not assigned (does not exist) then a null string is returned If the array exists (has been declared) but with no elements assigned then zero is returned Example: # a # Not declared set b {} # Not an array dim c 1 # Create empty array using [dim] set d(1) 0 # Assigned array and element array set e {1 one 2 two 3 three} # Multi-element set puts "Undeclared a '[array size a]'" puts "Non-array b '[array size b]'" puts "Empty-array c '[array size c]'" puts "Declared d '[array size d]'" puts "Declared e '[array size e]'" Results: Undeclared a '' Non-array b '' Empty-array c '0' Declared d '1' Declared e '3' See also: array, array unset
array list  Top  
array list arrayName # Exports the array to an unsorted Tcl list Note that the list contents will be in random, not original, order Example: foreach x $qbf { set q($x) $x } Result: the brown jumps lazy fox quick over The dog Example: foreach x [array list env] { puts $x } Result: D:\WINDOWS D:\WINDOWS\system32\cmd.exe See also: arrays, array sort, array
array sort  Top  
array sort arrayname ?newvar? ?-reverse? ?-array name? ?-names? Returns a sorted Tcl list of array values. Note that the subscript (key) values are not returned and the internal array hashtable structure cannot actually be sorted, only the returned output The default sort order is normal (A-Z) Optionally a target variable can be specified to output to a new variable In this case a count of the number of elements in the variable is returned Sorting in Integer Sequence --------------------------- [array sort] can also output an integer sorted array indexed at base 0 by specifying the '-array' argument Example: option expression on for {set i 0} {$i < 2000} {incr i} { set a($i) [randomstr 20] } puts [llength [array sort a]] Result: 2000 Example: option expression on for {set i 0} {$i < 2000} {incr i} { set a($i) [randomstr 20] } puts [array sort a b] Result: 2000 Example: array sort env -array out set s [array size out] for {set i 0} {[< $i $s]} {incr i} { printf "%4i:\t%-40.40s\r\n" $i $out($i) } Results Outputs values in the ENV table Example: # Using a temporary and [swap] to swap between sorted and unsorted arrays # [swap] moves no data, it simply renames the two variables array sort foo -array out swap out foo # Swap $foo and $out set s [array size foo] for {set i 0} {[< $i $s]} {incr i} { printf "%4i:\t%-40.40s\r\n" $i $foo($i) } Sort by Array Names (Subscripts/Keys) ------------------------------------- If -names is specified together with -array and an array value then the array will contain an exported list of array names (subscript keys) rather than array values. The resulting array can then be used to index the original array in this sorted order Example: array set unsorted { The orange quick yellow brown blue fox black jumps magenta over white the cyan lazy green dog red } array sort unsorted -array sorted -names set size [array size sorted] for {set i 0} {[< $i $size]} {incr i} { printf "%4i:\tref: %s =>\t%-40.40s\r\n" $i $sorted($i) \ $unsorted($sorted($i)) } Results: 0: ref: brown => blue 1: ref: dog => red 2: ref: fox => black 3: ref: jumps => magenta 4: ref: lazy => green 5: ref: over => white 6: ref: quick => yellow 7: ref: The => orange 8: ref: the => cyan [array sort] is not a standard Tcl command See also: arrays, array list, array, swap
array statistics  Top  
array statistics arrayname Show statistics for a given array. This shows the total number of root entries in the array's hash-table as well as the total number of buckets (nodes) including the root entries. Additionally, a summary is shown of the first 10 most relevant top-level bucket allocation counts. Ideally the average search depth for a given root entry should not be much more than about 2 or 3 but as the allocation is largely random and this is therefore impossible to achieve completely. Ticol enhances the usual Tcl statistics table by showing the total bucket count per-category in brackets. Example: option expression on for {set i 0} {$i < 2000} {incr i} { set a($i) [randomstr 20] } array statistics a Result: 2000 entries in table, 1000 buckets number of buckets with 0 entries: 0 (0) number of buckets with 1 entries: 270 (270) number of buckets with 2 entries: 269 (538) number of buckets with 3 entries: 173 (519) number of buckets with 4 entries: 94 (376) number of buckets with 5 entries: 36 (180) number of buckets with 6 entries: 16 (96) number of buckets with 7 entries: 3 (21) number of buckets with 8 entries: 0 (0) number of buckets with 9 entries: 0 (0) number of buckets with 10 or more entries: 0 (0) average search distance per entry: 2.32 Array hash-table performance can be configured using ticol.ini settings but it is recommended to keep the defaults See: ticol.ini See also: arrays, array, array walk
array trim  Top  
array trim arrayVar ?maskchars? ?-left|-right? Trims the left and/or right hand ends of all array values Example: # Create a ragged, CRLF-delimited string with leading/trailing spaces set s " The quick brown fox jumped over the lazy dog" puts $s puts [string repeat - 30] split $s "\r\n" -array a array trim a for {set i 0} {< $i 4} {++ i} { # Print in array order puts '$a($i)' } Result: The quick brown fox jumped over the lazy dog ------------------------------ 'The quick brown' 'fox jumped' 'over the' 'lazy dog' See also: array, trim, string repeat
array unset  Top  
array unset ?::?arrayName array unset ?::?arrayElement(X) Delete a single array and all elements. Individual array elements may also be deleted using [unset] If the array is in global scope then use the '::' prefix (omitting the $) as: array unset ::arrayname It is an error to attempt to unset a non-existent or const array variable See also: unset, arrays, array, clear, vars
array walk  Top  
array walk arrayName Walk the array hash-table (not standard Tcl) -------------------------------------------------- hash_table::walk() Object:0x973290 size:500 -------------------------------------------------- Table(1) Node: 0x9d8500 chained nodes:1 0x9d8500 depth:1 key:'75' value:'WdqUPVnSLNLTMfeeEqTO' Table(5) Node: 0x9d8a80 chained nodes:1 0x9d8a80 depth:1 key:'50' value:'gPkhMdxxowGitxhibQgd' Table(10) Node: 0x9d8d90 chained nodes:1 0x9d8d90 depth:1 key:'76' value:'KMtJygZvZouAvRBUPVqg' Root size:500 Root occupation:89 (17.80%) Max depth:2 Occupied nodes:100 -------------------------------------------------- An optional 'glob' filter pattern may be given to filter on key values [array walk] is not a standard Tcl command See also: arrays, array, array statistics
Tcl Arrays  Top  
Ticol supports subscripted, associative Tcl arrays. This offers arrays with either traditional 'numeric' subscripts or subscripts indexed by a case- sensitive string. This subscript may be a string-literal or a Tcl variable name prefixed by a dollar $ sign or $:: global scope indicator to access global variables within procedures Multi-Dimensional Arrays ------------------------ There are no multi-dimensional arrays in standard Tcl but they may be emulated by various means. This usually involves compound subscript values using embedded commas which, when combined, form a unique hash key e.g. 'arrayvar(x,y)' See the Tcl websites for a discussion Example: set a(0,1) "Item one" set a(0,2) "Item two" set a(1,1) "Item three" set a(1,2) "Item four" Case Sensitive Subscripts ------------------------- Array subscripts are case-sensitive with the exception of the $argv and $env system arrays. These are referenced case-insensitively so $env(TEMP) and $env(temp) will both return the correct array element. Large arrays cannot be efficiently addressed when addressed case-insensitively. The internal hash table has to be traversed in a linear fashion (See: array index) Some Tcl commands have been extended to include case-insensitive lookups. These are far less efficient than case sensitive ones Spaces in Subscripts -------------------- Whitespace is allowed in a subscript value but should be wrapped in double quotes Example: set foo("a b c") zzz set bar("d e f") "Hello world" Declaration and Use ------------------- Arrays can be declared using set only one level at a time. Multiple, simultaneous, nested arrays may not be declared (e.g. set a(b(c(1))) hello) You can use [array set] to initialise multiple array elements set a(1) Hello # A traditional literal numeric subscript puts $a(1) # Example dereference Hello # Result set a(one) Hello # An associative array with literal subscript puts $a(one) # Example dereference Hello # Result set i 0 # Create an index variable set a($i) Hello # An associative array with variable subscript puts $a($i) # Example dereference Hello # Result array set days { Create a const array of 7 elements 1 Monday 2 Tuesday 3 Wednesday 4 Thursday 5 Friday 6 Saturday 7 Sunday } -const Arrays are referenced by dollar prefix, the same as any other Tcl variable Note that the array syntax prohibits any whitespace between the variable name and the open parenthesis: Correct: "$varname($index)" Incorrect: "$varname ($index)" (looks for non-array variable '$varname') Arrays as Command Arguments --------------------------- Not all Ticol commands accept arrays as output arguments. Some do, such as [setat].Check with the section for each command Most commands won't accept nested/complex array expressions as output arguments (i.e. as the name of target variables to be written). Most will accept arrays and complex array expressions as input arguments as long as the array is resolved before the call Sorting ------- Associative arrays cannot be sorted internally, they are, however, rapidly accessible by the hashed key (subscript) value so sorted indexes are typically unnecessary.. See [array sort] for sorting workarounds Storage and Efficiency ---------------------- All arrays are stored in a dynamic hash-table as associative arrays. Due to this internal storage method, arrays are not contiguous in memory and thus cannot be natively sorted. To sort an array, output it to a sorted list You can create an array with a fixed table allocation and avoid the performance costs of resizing by declaring to a high enough initial size. Use array create arrayName size, e.g. array create big 10000 Arrays indexed by numeric value can be indexed in pseudo-sorted order by use of a numeric subscript index value and a for loop or returned as a list Array storage is expanded dynamically from a minimum reserve allocation of 1 Any valid object which can be stored in a standard Tcl variable may be stored in an array element Storing Types ------------- The empty string "" is stored in an array element as an empty Tcl list {} Arrays of lists and other types are possible but it should be understood that a Tcl array is not a contiguous binary array and is unsuitable for passing forward to an external C/C++ DLL Arrays of Lists --------------- Since Tcl lists are strings, Tcl arrays may have a Tcl list as the array value ... array set economists { 1 {HH002 "Henry Hazlitt" 002 87} 2 {WB001 "Walter Block" 072 77} 3 {PB001 "Phillip Bagus" 033 22} } -const Passing Arrays to Procedures ---------------------------- Arrays can only be passed via a proc body by reference (by name) and using a subsequent upvar command. To pass an array by value you must convert to a list This is by design. Arrays are intended to be passed by reference (by name) [array item] is the most convenient way to handle the double-dereference of unknown array names passed to a proc Example: array set colours { 1 red 2 green 3 blue } -const proc list_by_key {arrayName} { upvar $arrayName foreach key [lsort [array names $arrayName]] { puts "Key: '$key [array item $arrayName $key]'" } } list_by_key colours Nested Array References ----------------------- Nested array references are permissible. The outer variable must follow Tcl syntax and NOT include a dollar prefix when calling [set] set c 1 # Create a subscript variable set b($c) hi # Create an array variable set a($b($c)) Hello # Set a nested associative array puts $a($b($c)) # Example nested dereference Hello # Result Each nested level must first be declared either using set or the [array] command. Attempting to set an un-dereferenced intermediate array (i.e. missing the $ symbol) will trigger an invalid argument error. (e.g. set a(b(c))) hello) -> error in 'b(c)') Advanced Arrays --------------- Ticol cannot create complex arrays such as arrays of struct, arrays of stack etc. The array variable, can however, point to the name of a complex variable type or a standard Tcl variable which holds a list Array Debugging --------------- The statistics for an array are inspected using: [array statistics arrayname] and the array can be inspected in detail using [array walk] See also: array, array create, array exists, array list, array size, array sort, array statistics, array unset, array walk
Ticol Variant - A Simple Variant Handling Plugin  Top  
To load, use: lib ticol_variant ?-verbose? ?-nocomplain? The following commands are exported (documented separately) [varray] [vsplit] [dumpvariant] See: varray, vsplit, dumpvariant
Variant Array Functions  Top  
Contained in lib plugin: ticol_variant varray count var ?dimension? Return element count of a variant array varray get var index ?index? Return element from a 1D or 2D variant array varray lbound var Return lower array bounds of a variant array varray ubound var Return upper array bounds of a variant array varray unset var Free a varray and destroy the associated var The caller is responsible for ensuring the variable is associated with a variant array Variant arrays are returned from external DLL functions called by the calldll* interface. Such arrays should be deleted using [varray unset] (if safe) and when no longer required in order avoid memory loss. One and two dimensional arrays are supported Example: set v [vsplit $qbf] # Split to Variant (SAFEARRAY) array set elems [varray count v] puts "Array has $elems elements:\n" for {set i 0} { < $i $elems } {incr i} { puts "$i: [varray get v $i]" } varray unset v Result Array has 9 elements: 0: The 1: quick 2: brown 3: fox 4: jumps 5: over 6: the 7: lazy 8: dog See each varray command for more details See also: vsplit, calldll, dumpvariant
varray count  Top  
Contained in lib plugin: ticol_variant varray count variable|address ?dimension? Returns the array count for a 1D variant string array The dimension argument is a base 1 value (1st is 1, 2nd is 2) The default dimension is 1, which represents the first array bound A 2d array would have a count for dimensions 1 and 2 where 1 would be the rows and 2 the columns. vvarray lbound and vvarray ubound can be used to calculate the varray count value This command currently supports a maximum of 2 dimensions See also: arrays, varray get, varray lbound, varray ubound, calldll
varray get  Top  
varray get address row ?column? Return a string element from a 1D or 2D Variant string array. Such arrays may be returned from DLLs such as SQLite queries. Example: # .. code to set variant 'vr' set lbound [varray lbound $vr] set ubound [varray ubound vr] for {set i $lbound} { < $i $ubound} {incr i} { puts "\t$i: [varray get vr $i]" } See also: arrays, varray count, varray lbound, varray ubound, calldll, dumpvariant
varray lbound  Top  
Contained in lib plugin: ticol_variant varray lbound address|variableName ?dimension? Return the lower bounds for a 1 or 2D variant array. The default dimension is 1 For 2d arrays specify 2 See also: arrays, varray ubound, varray get, varray count, calldll
varray ubound  Top  
Contained in lib plugin: ticol_variant varray ubound address|variableName ?dimension? Return the upper bounds for a 1 or 2D variant array. The default dimension is 1 For 2d arrays, specify 2 as the dimension value See also: arrays, varray lbound, varray get, varray count, calldll
asc  Top  
integer [asc character|string] integer [asc "character"|"string"] The inverse of chr. Returns the ASCII (ANSI) numeric value of a string Examples: puts [asc "A"] # Double-quoted argument puts [asc {A}] # Braced argument puts [asc A] # Raw argument Result: 65 65 65 See also: chr, string, left, right, mid, index
assert  Top  
assert value expression ?-var name? ?-line line? ?-v? Asserts an expression using a substitution variable in the expression This expression is in the current scope context A substitution variable is created in global scope and the default internal substitution variable is $_ . You can change this to any variable name using the ?-var name? option as long as the variable does not already exist in the current scope. The substitution variable represents the evaluated expression and may be used in the test expression If you supply a line number this will be displayed in the output No output is issued if the assertion is true unless the '-v' (verbose) argument is specified. Thus, [assert] statements may be left within active code. The expression argument must be supplied in braced format After debugging is complete all [assert] statements can be disabled globally using the following Macro definition: #define NDEBUG Once NDEBUG is defined [assert] statements have minimal overhead within a script. For more information, see: macro preprocessor Examples -------- Example: assert 1 {eq $_ 1} Result: # Program continues without interruption # No output Example: assert 1 {eq $_ 1} -line 10 -v Result: # Program continues without interruption and displays confirmation assert: PASS 'eq $_ 1' Example: assert 0 {eq $_ 1} -v -line #__LINE__ # Default internal variable Result: assert: Line 10: Assertion failed: '0' != 'eq $_ 1' # Program execution halts Example: assert 1 {eq $x 1} -var x Result: # No output. Test passes OK Example: assert 1 {eq $x 1} -v -var x -line #__LINE__ assert 0 {eq $x 1} -v -var x -line #__LINE__ Result: assert: Line 1: PASS 'eq $x 1' assert: Line 2: Assertion failed: '0' != 'eq $x 1' # Program execution halts Example: #define ndebug # The following statement would normally fail but is now ignored assert 1 {eq $_ 0} Result: # Assertion is ignored. Execution continues without assert See also: debugging
Associative arrays  Top  
Older languages like C, C++, BASIC, and Java support arrays in which the index value is an integer. Tcl, like most scripting languages such as Perl, Python or PHP supports 'associative' arrays in which the index value is a string value or string representation of a number. In associative arrays there is no counted binary offset from one block of memory to the next array element. The underlying data structure is the "hash table" Associative array syntax is to put the index within parentheses as with other languages. There is no need to declare an array before assigning. You can assign any valid variable name as an array a long as it is not already in use If you intend to assign a very large array you can use [dim] to pre- allocate the underlying hash-table to speed assignment Example: set name(first) "Gordon" # 'first' is a string literal set name(last) "Bennett" # 'last' is a string literal puts "Full name: $name(first) $name(last)" Result: Full name: Gordon Bennett Arrays, as with other variables, are "dereferenced" by prefixing their name with a dollar sign. e.g. puts $name(first) Some functions, such as [unset] require the literal name of the array, e.g. [unset name], [unset name(first)] The system environment is provided via a pre-allocated const array 'env' e.g. puts $env("PATH") Ticol command line arguments are provided via the const array 'argv' with integer 'argc' representing the argument count. e.g. puts $argv(0) For detailed information, see: arrays See also: array, arrays, array find, env, argv, dim, dump, array unset
autoexec  Top  
autoexec ?on|off? This option interacts with 'proc unknown'. It controls the passing of unrecognised/unknown commands to the underlying operating system or the calling of a special procedure. Autoexec is ON by default, allowing Ticol to be used as a Windows command-shell If autoexec is 'on' then unknown commands are passed to Windows IF and only IF a proc called "unknown" isn't defined. C/C++ style escape characters such as \r or \n are also disabled at the console to ensure correct operation with Windows If autoexec is 'off' and a proc called "unknown" is not defined, then the command will return an error. Turning the option 'off' will re-read any INI configuration settings for BackslashEscape for the CLI (see: help ini) The command 'autoexec' with no arguments will return the current status as 'on' or 'off' This is also configured in ticol.ini [config] as Autoexec=<boolean> The autoexec option is Ticol specific and not standard Tcl. It does not relate to the use of an autoexec.tcl file For more information, see: unknown See also: autoexec.tcl, ini, commands, exec, spawn, cli, debugging, macro
autoexec.tcl  Top  
autoexec.tcl - The Ticol startup file If a file called autoexec.tcl is found in the same folder as TICOL.EXE at startup then this will be executed automatically. This is the Ticol equivalent to the DOS/Win AUTOEXEC.BAT file. Due to inherent risks in running a script automatically, the autoexec.tcl file may NOT be obfuscated, thus preventing potentially damaging commands from being hidden. Any obfuscated version will not be processed You may disable the execution of autoexec.tcl using either the command line option /NA or the ticol.ini file setting: [config] AutoExecScript=FALSE An autoexec.tcl file may be used to initialise common variables or define a set of common procedures before an interactive CLI session or running another script Note that autoexec.tcl may NOT be encrypted/obfuscated. This is by design autoexec.tcl has nothing to do with the [option autoexec] setting for the Ticol Command Line Interpreter (CLI) See also: Ticol, obfuscation, autoexec, at_exit
at_exit  Top  
[at_exit] is an optional user-defined procedure which is called when a Tcl script exits by exiting Ticol. at_exit takes no arguments. Any arguments defined will be ignored [at_exit] is called only via running scripts, never from the CLI and is not called unless the script exits the Ticol binary The [upvar] command is required to access variables defined elsewhere in the [at_exit] procedure [at_exit] is intended for use as a cleanup routine, to close DLL and open file handles safely and avoid memory leaks etc. [at_exit] is not called when Ticol is exited abruptly using CTRL+C Where a [stop] command is encountered within [at_exit], execution will be returned to the CLI. Where an exit command is met within [at_exit], Ticol will exit Where neither is given the default behaviour will apply (exit if run from Windows or stop and return to the CLI if run from the CLI) Unlike C++, multiple [at_exit] routines are not provided for. There is no need to register multiple [at_exit] routines. One routine can call all desired shutdown code Example: proc at_exit {} { puts "Inside proc 'at_exit'" upvar handle upvar pointer puts "Handle is $handle" puts "Pointer is $pointer" puts "Exiting Ticol" return 0 } puts "In main()" set handle 10 set pointer 2 puts "Exiting script" stop Result: In main() Exiting script Inside proc 'at_exit' Handle is 10 Pointer is 2 Exiting Ticol Example: proc at_exit {} { # If undefined then has no effect on the program exit textcolor lightred puts "* Stopped *" textcolor # exit # Exit to O/S if desired # stop # Return to CLI if desired return 23 # Return ERRORLEVEL value to the O/S # Else exit to original start environment } Example: ticol.exe "proc at_exit {} {puts Done}"; test.tcl See also: upvar, run, cli, exit, stop, return, autoexec.tcl
base64  Top  
string [base64 string | varName -encode | -decode ?-format width?] Base64 encode or decode a string or variable according to the argument parameter given. Where a -format value is given this will control line- wrapping on the returned base64 code. The default is no line-wrapping (0) The minimum -format width is 4 characters Example: set a [base64 "Hello world!" -encode] puts [base64 $a -decode] Result: SGVsbG8gd29ybGQh Hello world! Example: puts [base64 $qbf -encode] newline puts [base64 $qbf -encode -format 10] Result: VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZw== VGhlIHF1aWNr IGJyb3duIGZv eCBqdW1wcyBv dmVyIHRoZSBs YXp5IGRvZw== See also: encrypt, decrypt, mkn, cvn
Tips for Writing Big Programs  Top  
Ticol Tcl is intended for small scripts relating to administrative use. It was written by the author to be used for IT management tasks as an alternative to PowerShell Here are some tips for developing larger programs: Make full use of [proc] Divide large scripts into numerous small procedures except where performance is critical and inline code required Use file-level modularity Break big scripts into smaller files and call using [eval scriptname] Arguments to external files are permissible via [eval] Use the Macro Pre Processor For conditional execution, where appropriate Make full use of plugin libraries with [lib] A range of functionality is available via Ticol plugin DLLs See also: performance, faq, eval
calc - Auto-optimising alternative to [expr]  Top  
calc <expression> ?-explain? calc {<expression>} ?-explain? calc "<expression>" ?-explain? calc <arg> <arg...> ?-explain? Inline Tcl commands are faster and more efficient than using [expr]. The Macro PreProcessor will expand [calc] natural expressions into native Tcl commands using RPN style notation [calc] is identical to [expr] and may be used in place of [expr]. It accepts the same expression format argument(s). However, unless the command-line argument /NEO (No Expression Optimisation) or the [option preprocessor off] directive is used, then the expression will be expanded and rewritten by the Macro PreProcessor (MPP) into native Tcl format commands before running. If /NEO is used then [calc] will be interpreted exactly as for [expr] The '-explain' argument is valid only at the Ticol CLI rather than load/macro-preprocess time and must also be the last argument in any test expression Example: # Example using -explain from the CLI option echo on calc 1+2/3.0-4*4 -explain puts [calc 1+2/3.0-4*4] Result: [- [+ 1 [/ 2 3.0]] [* 4 4]] -14.333333333333332 [calc] supports the same range of operators as [expr] (excludes ++ and --) [calc] requires a bracketed call - [calc ...] not calc ... The translated command strings are typically around 50% faster than [expr] as [expr] has an error and syntax-checking overhead as well finally calling [eval] with the results. [calc] hugely speeds up performance by preprocessing this task before run time Ticol expressions are BEDMAS-optimised unless brackets are used to enforce ordering. Function calls are resolved to the [funct] command. If the command-line argument /NEO is used then [calc] will behave in exactly the same way as [expr]; This makes [calc] much more flexible as well as significantly improving perform performance on math tasks. In addition, this enables the '-explain' argument. If problems are encountered then use /NEO to disable [calc] translation and it will be interpreted as [expr] If the result of [calc] is a string value and if [option expression] is set to OFF and this value is passed to [eval] then the result may be misinterpreted as a command. The fix is to ensure that you use [option expression on] when handling string returns when chaining the result to [eval] You may examine the translated result using the /ECHO command line argument if manual checks are required on the translated expression Example: set f 3 puts [calc {$f+2-($f==2)}] Translation (requires ticol.exe /ECHO): puts [- [+ $f 2] [== $f 2]] Result: 5 Example: option PreProcessor off # Turn off MPP for the command line set s [calc 1/2.0+3*4 -explain] # Get the translated Tcl code puts $s # Display the Tcl code puts [eval $s] # Evaluate it and get the result option PreProcessor on # Turn the MPP back on again Result: (Expanded Tcl commands) [+ [/ 1 2.0] [* 3 4]] 12.5 [calc] will also attempt to simplify const expressions by evaluation and then substitution. Disable using /NEO Example: puts [calc {[rnd 2 4] > 3 ? {return Higher} : {return "Same/lower"}}] Interpreted as: puts [? [> [rnd 2 4] 3] {return Higher} {return "Same or Lower"}] Result: Either Higher or lower Example: (save as script.tcl) # script.tcl set s [calc "1 / 2.0 + 3 * 4"] puts $s Run as: ticol.exe script.tcl /echo /neo set s [calc "1 / 2.0 + 3 * 4"] puts $s Run as: ticol.exe script.tcl /echo set s [12.5] puts $s ticol.exe script.tcl Note: (/NEO command-line argument) The /NEO (No Expression Optimisation) argument also applies when creating protected TCX files. Any TCX sub-file which needs to be run using the /NEO argument must be "compiled" using /NEO Note: (Excess {} braces) Do not wrap the entire expression to be passed to [calc] in braces or [calc] will be unable to interpret it. Braces prevent evaluation. Spurious error messages will result. Example: (WRONG - expression is 'masked' by braces) puts "a and b are: '[calc {{$a eq $b} ? {return equal}\ : {return different}}] Example: (CORRECT) puts "a and b are: '[calc {$a eq $b} ? {return equal}\ : {return different}] Note: (/NES argument) The /NES (No Expression Simplification) will disable automatic simplification and optimisation of expressions generated by [calc] Note that where [calc] const expressions are pre-evaluated and generate an error then this error will always be fatal and the preprocessing phase will halt. This feature can be disabled using /NES on the command-line Example: puts [calc acos(10)] # Will evaluate to -1.#IND00000000000 (invalid) Note that the listeral hash (#) comment character can be used safely within a quoted string See also: expr, Macro PreProcessor, /NEO
Tcl Callbacks  Top  
Ticol Tcl procs can perform 'callbacks' to other Tcl procs where the name of a callback proc is passes via the initial command reference Example: option expression off proc test_callback {cbf} { puts "Enter test_callback -> '$cbf'" for {set j 0} {[< $j 10000]} {++ j} { if {[&& [> $j 0] [is_mod $j 1000]]} { [$cbf $j] # Call the callback proc } sleep 1 } } proc callback {x} { puts "In callback $x" } test_callback callback Results: Enter test_callback -> 'callback' In callback 1000 In callback 2000 In callback 3000 In callback 4000 ... See also: proc
Variable Casting  Top  
[char value] [short value] [long value] [int value] [double value] [signed value] [unsigned value] Tcl is effectively a typeless language. It handles all variables internally as string values and, in most cases these are converted by Ticol to 64-bit integers or 8-byte doubles for arithmetic purposes. All Ticol integers are 64-bit signed integers Conversion and type detection is automatic. There may be cases, such as marshalling data for DLL interfaces, where you wish to coerce the type manually. Built-in Ticol casts are more efficient than casts written in Tcl Non-decimal constants such as 0x1234 or 0o1234 are translated into decimal format before execution by the Macro PreProcessor (MPP). The work of unecessary runtime conversion is therefore avoided. You may use the functions above to cast the string values to an appropriate type. This may involve the truncation of the value with loss of precision. [char] differs from [chr] in that [char] truncates at valid trailing integer digits whereas [chr] accepts only a fixed range of values (0..255) [signed] and [unsigned] will coerce from 64-bit signed or unsigned integers with consequent wrap around Appending ".0" to an integer will have the same math effect as [double] Example: [12345].0 -> 12345.0 [double 12345] -> 12345.000000000000000 Numeric type conversions are built-in to Ticol. A cast will accept any kind of numeric input, decimal integer, decimal real, hexadecimal, octal or binary You will still have to specify byte widths where marshalling data for export via a DLL interface Note again, that non-decimal number types such as hex (0xNN) which are not inside quoted strings will be converted to decimal by the Macro Pre- Processor (MPP) before any script is run. This is designed to speed up execution Example: Result Comments ---------------------------------------------------------------------------- puts [int $pi] 3 Cast a constant puts [char 12345] 9 Cast an integer puts [chr 12345] Overflow Not valid for [chr] puts [char 0b1111000] x Cast a binary (0bX) puts [double 0b111100011011] 3867.000000000000000 Cast a binary (0bX) puts [short 0o123] 83 Cast a octal (0oX) puts [short 0x123ffff] -1 Truncated as short puts [int 0x123ffff] 19136511 Valid integer range puts [double 0x123ffff] 19136511.000000000000 Valid double range puts -1 -1 64-bit integer puts [unsigned -1] 18446744073709551615 64-bit integer puts [signed 18446744073709551615] -1 64-bit integer puts [signed 0xFFFFFFFFFFFFFFFF] -1 64-bit integer Code Example: option expression off for {set i 0} {< $i 64} {incr i} { puts "1 << $i == [unsigned [<< 1 $i]]" } See also: data type ranges, fpart, integral, asc, calldll, chr, error
catch  Top  
catch {sourcecode} variable # With option expression off catch {[sourcecode]} variable # With option expression on [catch] intercepts error returns from the source code expression which is passed to it and prevents the script from halting, instead returning a boolean value. If there is an error condition then 'variable' is set to the error message. [catch] returns a success code and the intercepted error code as a return value. Catch returns a boolean TRUE on error and FALSE on success The catch expression must be wrapped in braces and, if a command, the command must not be wrapped in square brackets or catch will evaluate the command return rather than the command itself and may fail. This behaviour is dependent on the [option expression] setting If the expression is successful then 'variable' is set to the return value of the expression. It is important that the catch expression is wrapped in curved braces not square brackets as square bracketed expressions will be evaluated before the catch test This command operates at the level of Tcl error return values and does not provide any additional O/S CPU exception handling.. Success is indicated by a return value of 0 with error conditions being > 0 Effective use of [catch] requires 'option echo off' as [catch] will handle the display of error messages rather than direct console output Within flow-control statements with: [option expression on] catch must be wrapped in square brackets to be evaluated otherwise it will be treated as an expression. Catch is most useful when combined with [if] (see below) See: error values for a list of returned error codes Example: option expression off if {[catch {set h1 [xbase open user.dbf]}]} { die "Failed to open database address.dbf" } Example: option echo off set file "nosuchfile.txt" # Note [catch] is wrapped in square brackets for [if] if { [catch { open $file r } fid] } { # Any value > 0 puts stderr "Could not open $file for reading\n$fid" exit 1 } Result: Could not open nosuch.txt for reading Exception raised from catch. Error code 1 Example: option echo off stack create s 1000 stack unset s catch {puts "Stack empty? [bool [stack isempty s]]" } err puts stderr "Stack error\n$err" exit 1 Result: Stack error stack isempty: Stack 's' not initialised Example: set line #__LINE__ if {[! [catch {puts 'pwd: [pwd]'} # Must be wrapped in braces ]]} { die "Failed to trap bad puts command at line: $line" } Result: # No error occurs Global variables are also set by internal error-handlers as follows: errorCode Tcl error code returned to the CLI errorLine May be set by the script using #__LINE__ errorMsg Console message generated by an internal error-handler See also: try, cmdcount, trace, error, run, time, debugging, flow control stop, exit, errorCode, errorLine, errorMsg, errorInfo, error values
clear  Top  
clear Clear (unset) all user-level variables and consts. System-level consts such as $env are unaffected. Although consts cannot be changed during the life of a script, the entire variable table may be cleared before running a new script. This prevents conflicts where scripts are loaded from the CLI. Ticol maintains a small number of reserved system variables which are protected from deletion by [clear] or [run] The [run] command will also clear the user-level variable table The loaded script may be cleared using the command [load -clear] See also: clearprocs, reserved variables, load, unset, set, vars
charcount  Top  
charcount string mask-chars ?-nocase? Count the number of instances of each character in the mask in the input string. Case may be ignored using the -nocase argument Where $qbf is a standard test variable: "The quick brown fox jumps over the lazy dog" ... Each successive mask character is counted only once. i.e. the string is iterated against the mask and each string char is matched only once Thus [charcount $qbf Tt] and [charcount $qbf TTtt] both return 2 This applies also to -nocase where both [charcount $qbf Tt -nocase] and [charcount $qbf t -nocase] return 2 [charcount] is useful for checking the number of backslash escapes and estimating a shrinkage factor when a string is unescaped. Escaped backslash characters - "\\" are correctly counted as one character, otherwise each backslash is counted as one character and any non-backslash mask character which follows is counted as one character Example Result puts [charcount $qbf a] 1 puts [charcount $qbf r] 2 puts [charcount $qbf t] 1 puts [charcount $qbf tT] 2 puts [charcount $qbf t -nocase] 2 puts [charcount $qbf tT -nocase] 2 puts [charcount $qbf aeiou] 11 puts [charcount $qbf fox] 6 puts [charcount "\[puts \"hello\"\]" "\\"] 4 puts [charcount "c:\\windows\\system32\\" "\\"] 3 puts [charcount "c:\\windows\\system32\\" "ws\\"] 8 See also: chartok, char, string
chartok  Top  
count [chartok string charmask array] [chartok] 'tokenises' (breaks apart) a string as delimited by characters specified in the 'charmask' argument and returns the individual components in a base 0 integer-indexed array. A count of the number of tokenised items in the array is returned The mask argument may comprise of one or more characters by which the string will be broken-up The mask characters are not included in the output. Typically a string will be split by spaces, tabs or CRLF pairs If the 'array' argument exists it will be overwritten without warning Example: option expression off set count [chartok $qbf " " a] for {set i 0} {< $i $count} {++ i} {puts $a($i)} Result: The quick brown fox jumps over the lazy dog Example: set s "Live-long and+prosper" set count [chartok $s "+- " a] for {set i 0} {< $i $count} {++ i} {puts $a($i)} Result: Live long and prosper See also: array, arrays, chartok
clearprocs  Top  
clearprocs ?filter? ?-nocomplain? Clear all user-defined procedures from the current workspace If a 'glob' name filter is not given then * assumed (all procs) User procedures are all defined at scope level 0 (root/global) [clearprocs] returns a count of the number of procs which have been successfully erased. This may be used to cross-check with a list produced by [procs] [clearprocs] will terminate any [after] script which is proc dependent Example: option echo on procs puts [clearprocs] Result: cube rainbow square testmean 4 See also: clear, glob
Ticol Command Line Arguments  Top  
Syntax: ticol.exe <scriptname>?.tcl? ?/argument...? Syntax: ticol.exe ; "tcl script commands" The following command line switch options are accepted: /ECHO Echo preprocessed source code and exit Invalid for encrypted files /EXPR:<expression> Evaluate a Tcl expression (calls [expr expression]) Expression results can be piped back to scripts etc /ST Enable Stack Trace only. Will be displayed only if an exception occurs. Not valid for plugin libs /CRLF Issue a CRLF after /EXPR (default is OFF) /LIB:libname?.dll? Load a Ticol plugin library DLL at startup /C[:OPT][outfile] Protect (encrypt) a Ticol source file Where OPT is one of: <No option> Automatic encryption/decryption USER Lock to a Windows user name VERSION Lock to a Ticol version MAC Lock to a network card address WINVER Lock to a Windows version x.xx HOST Lock to a Windows host name PASSWORD Require a user-specified password Decryption is automatic except for /C:password If <outfile> is omitted then infile.tcx is created /P:<password> A password phrase relevant to the above /C cases which will be used to encrypt the script The MD5 value is displayed on successful encryption /I Info. Show information about a TCX file /G Show performance analysis graph /MD5 filename Display the MD5 value of a file (or: /MD5:filename) /NA No autoexec.tcl Don't load/execute autoexec.tcl /NEO No Expression Optimisation of [calc] during preproc /NES No Expression Simplification of [calc] during preproc /NB No console I/O buffering /NP No Macro PreProcessor /NX No CLI autoexecute unknown commands (autoexec off) /NE Disable the exit command, disable CTRL+BREAK /SC Enforce Tcl standard comments /BP Enable breakpoints and single-step debugging This also enables the [halt] debugging command and stack trace /PAUSE Pause after execution (keep console window open) /Q Quiet mode. Don't show load/run/PreProcessor errors Use: ticol.exe /? to get details of command line arguments for the current version of Ticol Expressions are accepted if the first argument is specified as a semi- colon. Where this format is used, the entire expression must be wrapped at the command-line level, in double-quotes otherwise the following error may be encountered: Error: 1 too many [ brackets found Braces may be used within Windows CMD line arguments to delinate Tcl strings Examples: ticol.exe ; "puts [{hello world}]" ticol.exe ; "puts [cd {\\\\server\\share\\path}]" See also: argc, argv, command line interpreter, CLI
Ticol Command Line Interpreter (CLI)  Top  
This is an interactive shell within which Tcl commands may be directly executed. From here you can also run programs or interact with the O/S shell. The CLI is a single-line editor with a maximum line length of 4096 characters. Multi-line freeform editing is not supported. Command history is retrieved using the up/down cursor keys control the command history both at the CLI and within most text input routines Macro-preprocessing such as #ifdef...#endif won't apply to commands entered directly within the CLI. The [at_exit] command also not enabled from the CLI Scripts may be run using: run script?.tcl? or evaluated using: eval script The CLI returns the status error code in square brackets, followed by any applicable return value if 'option echo' is set to ON [x:status] <return-value> The primary Ticol status codes are: 0 OK/Success 1 Error condition. The 'error' command may give more information 2 Return statement encountered 3 Break statement encountered 4 Continue statement encountered 5 Exit condition encountered 6 Stop or abort condition (stop command, wrong arguments etc.) 7 goto operation encountered 8 Value already defined Commands are not echoed by default. To enable command console echo use the command: option echo on - or configure the ticol.ini file and add an entry: [Config] ConsoleEcho=TRUE Example: set a "Hello" set $a Result (at the CLI): [0:ok] Hello See also: command line arguments, Ticol, exec, autoexec, debugging, macro, ticol.ini
clipboard  Top  
clipboard get clipboard set string ?-append? clipboard clear clipboard isempty clipboard printscreen clipboard gettext Copy text to or from the clipboard. Optionally, clear the clipboard or check to see if it is empty. clipboard printscreen will capture the current window to the clipboard as an image [clipboard get] will retrieve ANSI text from a selected area in the console window. You can append to the clipboard using the -append argument [clipboard set] will place ANSI text into the clipboard [clipboard clear] empty the clipboard. It is recommended that you test for a non-empty clipboard and clear it prior to copying text to it. Note that the clipboard supports multiple data formats [clipboard printscreen] will grab the current visible console window as a graphic image equivalent to a PrtScrn operation [clipboard gettext] will retrieve 80 x 25 characters of ANSI text from cursor location 1,1 onwards in the current console. If the screen is scrolled after a [cls] command then only the first 2,000 ANSI characters will be returned. Select-zones are not supported by this command Other than clipboard printscreen, only text mode operations are supported See also: Single line commands, Ticol
Command Line Prompt String  Top  
The command line prompt can be configured via the TICOL.INI file using a subset of the DOS/Windows PROMPT characters as follows [Config] Prompt=<string> Where the default internal value is Prompt=$u@$h$g Which will return: user@host> Example: [Config] Prompt=$u@$h$s$k$g Result: Admin@Snoopy 132> Where: the string contains literal text and any of the following tokens: $c An opening curved parenthesis ( $g A greater-than symbol > $h The current hostname (if any) $f A closing curved parenthesis ) $k Command count (See: info cmdcount) $l A less-than symbol < $p The current path $n The current drive letter only, e.g. C $s A single space character $u The current username (if any) $_ A newline See also: cli, ini file, info cmdcount
Colour Constants  Top  
The following colour constants are defined. You may also use numeric values: 0 0x00 black 1 0x01 darkblue 2 0x02 darkgreen 3 0x03 darkcyan 4 0x04 darkred 5 0x05 darkmagenta 6 0x06 darkyellow 7 0x07 grey (gray) 8 0x08 darkgrey (darkgray) 9 0x09 blue 10 0x0a green 11 0x0b cyan 12 0x0c red 13 0x0d magenta 14 0x0e yellow 15 0x0f white Both 'grey' (UK) and 'gray' (US) spellings are accepted See the example file: colors.tcl Most modern versions of Windows will display "darkyellow" as a brown/khaki colour where orange would be more useful. You can change darkyellow to orange using the following REG file. Save as "console-orange.reg" and merge into the current session then log out and back in again to enable More recent versions of Windows will reset this colour at each boot --------------------------------------------------------------------- Windows Registry Editor Version 5.00 ; Colour table with DarkYellow == Orange 0x00c0c0c0 (BGR) [HKEY_CURRENT_USER\Console] "ColorTable06"=dword:00508dfc --------------------------------------------------------------------- See also: textcolor, textbackground
Conditional Operator - ?:  Top  
Command syntax: ? test-expression true-expression false-expression or: (using expr syntax): ( test-expression ? true-expression : false-expression ) The first operand is evaluated and all side effects such as expression calls are completed before continuing to evaluate If the first operand evaluates to true (a nonzero value), the second operand is evaluated. If the first operand evaluates to false (0), the third operand is evaluated. The result of the conditional operator is the result of whichever operand is evaluated the second or the third. Whichever of the operand expressions applies will be evaluated using 'expr' and this may include other Tcl commands. To return literal strings use 'return string' Only one of the last two operands is evaluated in a conditional expression Nested conditional operators should be avoided as these can lead to difficult-to-debug problems and bracket parity issues The functional if may be faster than an if command To return a string or other literal from the command form [?], use the [return] command. This is not necessary in the expression form Example: puts [expr "rnd(1,2) ==1 ? One : Two"] Example: set i 0; while {[< $i 5]} {puts [? [rnd 0 1] {return true}\ {return false}]; incr i} Result: false true true false true Example: # Command form [?] requires [] puts "[? [rnd 0 1] {return true} {return false}]" Result: (true or false) See also: flow control, if, else, while, for, foreach
Conversion Routines - mkn, cvn  Top  
mkn <numeric-value> # Make a compressed numeric representation cvn <mki-string> # Convert a compressed numeric representation These commands are similar to Visual BASIC's Mki/Cvi, Mkf, Cvf functions They convert a decimal numeric string of any length into a compressed 4-bit encoding format which is universal to all decimal-based number types. This format does not embed nulls within the string and encodes a precise string representation rather than a binary translation. It encodes to precisely half the original string length The size of the numeric string is limited only by available memory The encoded character ranges is: "0-9 + - . <space>" Encoding pattern is as follows: ------------------------------------------------------------------ ASCII Value Input Encoding Symbol Comment ------------------------------------------------------------------ 48..57 0x1..0xa '0..9' Decimal digit 43 0xb 11 '+' Positive sign 44 0xc 12 ',' Comma (non-UK thousands separator) 45 0xd 13 '-' Negative sign 46 0xe 14 '.' Decimal point 32 0xf 15 ' ' Space 0 0x0 '\0' Reserved for C/C++ NULL terminator ------------------------------------------------------------------ Examples: puts [mkn 616] puts [mkn $pi] puts [mkn +3.14159] puts [cvn [mkn 3452345]] puts [cvn [mkn +3.14159]] Results (may include extended characters not reproducible here): rp N%&vFC@ Rj 3452345 +3.14159 See also: base64, fromhex, tohex, inttohex, md5, crc, encrypt, decrypt
baseconv, convbase  Top  
convbase number base baseconv number base convbase can convert from an arbitrary base (2..16) to base 10 baseconv can convert from base 10 to any base (2..16) CAUTION: Do not prefix convbase inputs with a number-type prefix such as 0x or the Macro PreProcessor will preconvert to decimal before it is seen by the command Results are not prefixed with a type flag such as 0x Example: convbase 499602D2 16 convbase 1010 2 Result 1234567890 (Base 10) 10 (Base 10) Example: baseconv 10 2 Result 1010 The resulting numeric values are not prefixed by a type flag e.g. 0x, 0o or 0b See also: inttobin, inttohex, inttooct
beep  Top  
beep ?frequency? ?duration? Play a note. The default frequency is 700Hz and the default duration is 200ms Example: option expression off for {set i 100} {< $i 900} {incr i 100} {beep $i 100} Examples: beep 600 beep - 2000 Note that best performance is on systems which support the 8254 timer chip. This is emulated on Windows 7 via the sound card, and not at all on some versions of Windows. Performance may be very poor with emulated sound output Support for the Beep API was dropped in Windows Vista and Windows XP 64-Bit See: https://msdn.microsoft.com/en-gb/library/windows/desktop/ms679277%28v=vs.85%29.aspx See also: playwav
Using Ticol With Batch Files  Top  
It is possible to emulate the Linux 'shebang' system and create a batch- script which can automatically execute Ticol Tcl code within the same file The following batch script can be used as a stub-wrapper for Tcl code ::set - { @echo off rem ################################################################## rem Name: magic.bat rem Purpose: Command-line chaining test for Ticol Tcl rem Notes: Run as: magic.bat rem The initial enclosing [set] command is ignored by Tcl rem ################################################################## rem Check filetype using BATCH script if "%~x0" equ "" ( set SCRIPT=%0.bat ) if "%~x0" neq "" ( set SCRIPT=%0%~x0 ) ticol.exe %SCRIPT% %1 %2 %3 %4 %5 %6 %7 %8 %9 /na exit /b } # Start Tcl Code #################################################### textcolor magenta puts "Hello from Ticol Tcl" textcolor newline See also: Ticol, md5 batch example, autoexec.tcl, autoexec
in, ni  Top  
in element list ni element list Return a boolean indicating whether an element is in or not in a well-formed Tcl list: Example Result puts [in fox $qbf] 1 puts [in fred $qbf] 0 puts [ni fox $qbf] 0 puts [ni fred $qbf] 1 See also: list, lindex, llength
Ticol is a Tcl interpreter, not a compiler!  Top  
Ticol is a Tcl interpreter. This means that Tcl scripts are evaluated on-the-fly and are not translated into machine instructions for the CPU Interpreters are necessarily slower in terms of execution than any compiled language. Some other languages compile to an intermediate form (p-code) which is designed to run on a virtual machine (virtual CPU) and these can perform very fast and in some cases out-perform native compiled object code. However these languages are not interpreters in the truest sense. This means Ticol will be relatively slow and should not be used for tasks where performance is required For this reason it is vital to optimise Tcl scripts. One of the ways this is achieved is to use a Macro PreProcessor (MPP) to pre-process scripts and perform any necessary static translations, e.g. on non-decimal const numbers such as 0x123 and convert these to decimal values. C-like escape sequences such as \r or \n are also converted to literal characters. Ticol includes a number of non-standard Tcl commands which are designed to facilitate optimal performance. See: performance The command [calc] is an optimisable alternative to [expr]. This command will be optimised into simpler Tcl commands by the Macro PreProcessor unless disabled. If disabled it will be interpreted identically to [expr] See: Macro PreProcessor for more information See also: calc, Tcl, Ticol
binary (Experimental/limited binary command)  Top  
binary set tcl-var escapedString ?-length x? binary set tcl-var binary tohex varname binary fromhex string varname binary base64 varname ?-encode? | ?-decode varname? binary length varname binary memcpy tcl-var source-address length Ticol uses uncounted ASCIIZ string which limits flexibility for use with binary strings which contain embedded NULL characters Ticol supports a few rudimentary binary operations. Note that where 'varname' is specified as an argument this should NOT be dereferenced as dereferenced strings are not handled as binary and will be truncated at the first NULL character. Binary strings cannot be returned from commands directly, so binary commands which return binary strings cannot be chained together (nested) If an argument variable does not exist then it will be created. If it exists and has content it will be overwitten. Useful for handling binary registry values. [binary] is not a full implementation of the Tcl [binary] command [binary] commands can not be used on non-binary variables binary set varname escapedString ?-length x? Set a standard Tcl variable with binary content binary tohex varname Return a hex interpretation of a binary variable binary fromhex string varname Convert a hex string to a Ticol binary variable binary base64 varname ?-encode ?varname?? | ?-decode varname? Returns the contents of a binary variable, base64-encoded or decoded. -encode is the default mode for this command If -decode is specified then the argument must be followed by the name of a new output variable. The output from -decode will/may be a binary string with embedded NULLs Where a variable name is specified the return value is a boolean Otherwise (for -encode with no varname), the return value is the encoded ASCIIZ string in base64 format binary length ticolVar Return an integer value representing the stored length binary memcpy varname sourceAddress length Copies data from memory address to a Tcl variable The Tcl variable will have memory allocated to hold the source The variable is marked as 'binary' and will have a length value The resulting binary string is "safe" and is null-terminated It may safely be printed using [puts] Notes: The Ticol Macro PreProcessor (MPP) will not allow \x00 or \x22 entries but these are correctly handled by [binary]. Remaining values are unescaped by the MPP before the script is loaded Example: binary set a \xfe\xffhello\x21\x00\x22world\x02\xff\xfe -length 18 puts "'$a!'" puts "binary length=[binary length a]" puts "tohex: '[binary tohex a]'" puts "base64: '[binary base64 a]'" Results: '.Hello' binary length=18 tohex: 'feff68656c6c6f210022776f726c6402fffe' base64: '/v9oZWxsbyEAIndvcmxkAv/+' Example: set a 23 binary memcpy b [addressofb a] 2 puts "\$b=='$b'" puts "binary length=[binary length b]" puts "string length=[string length b]" Result: $b=='23' binary length=2 string length=2 See also: set, tohex, encrypt, base64, tohex, fromhex
bintoint, inttobin  Top  
bintoint binary-value inttobin value ?-full? ?-noprefix? bintoint converts a binary value to a decimal inttobin converts a decimal value to binary with the prefix "0b" Conversion of binary to decimal integer is automatic in Ticol Values are calculated as 64-bit integers Values given to intobin may be decimal integers, hexadecimal, octal or binary The optional ?-full? arg includes leading left-hand zeroes Examples: option echo on inttobin 9223372036854775808 -full inttobin 666 -full inttobin 666 -noprefix inttobin 666 Results: 0b1000000000000000000000000000000000000000000000000000000000000000 0b0000000000000000000000000000000000000000000000000000001010011010 0000000000000000000000000000000000000000000000000000001010011010 0b1010011010 See also: big number, inttohex, inttoct
bool (boolean value)  Top  
bool value Returns the string "true" or "false" depending on the input numeric value A non-zero value returns true, a zero value, false If the string "true" or "false" is given then 1 or 0 respectively is returned with the string being evaluated for a match Mappings: Input Result ---------------- 1 True 3 True -3 True 0 False x False True 1 TRUE 1 False 0 FALSE 0 true and false are defined as constants 1 and 0 respectively Examples: puts [bool 1] puts [bool true] puts [bool false] puts [bool [> [funct rnd 1 10] 5]] Results: true 1 0 true or false depending on [rnd] See also: math, string
box  Top  
Draw a graphic box box x y w h ?forecolour | -? ?backcolour? ?-solid? ?-nofill? Color may be a symbolic name such as 'blue' or a numeric value which corresponds with standard Windows console values (e.g. blue, cyan and these may optionally be prefixed with 'light', e.g. 'lightred') Both 'grey' and 'gray' are accepted. -solid will remove the border pattern and draw a solid box of 'backcolour' -nofill will draw only the box outline in 'forecolour' 'backcolour' is the box 'fill' colour 'forecolour' may be ignored when specifying 'backcolour' by using a - Displaying the box will change the cursor position. Use gotoxy to reset. gotoxy may also be used to draw within the box area Screen colours are reset back to defaults after a call to [box] Examples: box 3 4 30 10 - lightcyan -solid box [rnd 1 20] [rnd 1 20] [rnd 5 30] [rnd 1 20] - lightcyan See also: msgbox, cls, gotoxy
Braces {} (Grouping) and Brace Style  Top  
Braces group Tcl commands including string characters. Braces may be nested Typically each call to a Tcl command unwraps one level of braces In some cases, double-quotes may be used to group words together. Note that single-quotes do not group so ... puts 'Hello world' is not valid, whereas ... puts "Hello world" or ... puts {Hello world} is valid Braces delay evaluation and may be used strategically to prevent evaluation at a specific level. Evaluation may be forced using [subst] Each command-call removes one set of braces and evaluates the result Because braces delay evaluation for one level they will prevent variables from being replaced. Thus later evaluations which are dependent on such variables will fail Nested levels of braces, used outside of quoted strings may be used to prevent interpretation within the current context, i.e. to delay interpretation to a later evaluation in a sequence Braces may also be used to isolate concurrent variables within strings and to prevent misinterpretation of variables adjacent to literal string content e.g. "$variablestring" -> "${variable}string" Braces which fully-enclose variables within strings do not delay evaluation and may also be used to distinguish variables from string content e.g. {$will_be_evluated_ok}string Braces may be used within lists to delineate groupings Example: set a "Goodbye " set b "cruel " puts "$a${b}world" Result: Goodbye cruel world Brace Style ----------- Tcl requires K&R style brace placement as the line end forms part of the command syntax. Failure to adhere to this style will cause fatal errors proc foo x { # Correct K&R Tcl style ... } proc foo x # Incorrect Allman/BSD C/C++ style { ... } See: https://en.wikipedia.org/wiki/Indent_style http://wiki.tcl.tk/708 See also: flow control, subst, eval, math, Tcl
call  Top  
call proc ?argument...? call command ?argument...? call "<tcl script>" Allows the calling of a procedure, Ticol command or scriptlet Similar to the function of CALL in legacy Visual BASIC. Call allows a proc to be called directly bypassing expression-evaluation, [trace] and /G graph statistics. [call] may also call procs which have been defined with numeric names A command can be called. In this case the normal evaluation chain is followed including [trace] and /G graphing Finally, a text script containing Ticol Tcl commands may be called Proc Example: proc 123 {} {puts "I am in bad proc 123"} [123] # Not called as [123] is evaluated as a number call 123 # Called successfully Result: I am in bad proc 123 Command Examples: option echo on call expr "sqrt(99)" Result: (Submitted via the CLI prompt) [0] 9.949874371066199 Script Example: call "textcolor magenta; puts {Hello } -nonewline ;\ textcolor red; puts world; textcolor" Result: (Submitted via the CLI prompt) Hello world See also: puts, eval, expr, foreach
External DLL Link Plugin - calldll*, calldll*_cdecl  Top  
To load, use: lib ticol_calldll ?-verbose? ?-nocomplain? Syntax: calldll* dllname?.dll? function-name|@ordinal arg arg... Safely call an external ANSI DLL routine. Both __stdcall and __cdecl DLLs are supported thus offering connectivity with a wide range of other applications including the Microsoft Visual C++ runtime (msvcrt40.dll), SQLite3, AutoIT and other DLLs which use standard interface methods Calling DLLs is not a trivial task an the marshalling of variables both outward and return can be quite complex and difficult to debug. The correct call-type (standard __stdcall or __Cdecl) must be used to match the DLL The DLL may be called either by name or by a handle returned from dll_open Additionally, an exported DLL function may be called by ordinal number by prefixing the ordinal with a @ symbol. e.g. puts "Is user an admin?: "[bool [calldll "Shell32" "@680"]] Quotes around the dll and function name are optional, as is the DLL suffix It is usually recommended that calldll calls be wrapped inside a procedure Byte widths may be specified in arguments as 'var:<width>' e.g. 'data:4' If a variable or string contains a ":" character (e.g. in a Windows path), a byte-width MUST be specified Variables are passed by reference if a variable name is used, if prefixed by a $ then they are passed by value. Literals are passed by value Variant returns, including 1D and 2D string arrays are handled If you pass a value which could be interpreted as a variable name then ensure you [unset] that name before calling [calldll] Passing the binary address of a variable buffer/string pointer by value may be forced by using [addressofb variable] to pass the literal buffer address (LPSTR). strptr is an alias for addressofb. This is most useful for struct field address offsets. To pass the address of a Ticol string buffer within a variable (LPSTR* in C++) use [addressof]. Note that the string buffer is a field within a Ticol variable not the address of the variable in memory set var 10 calldll dllname funct var # Pass by reference calldll dllname funct $var # Pass by value calldll dllname funct [addressofb var] # Pass var address by value The Microsoft Visual C++ runtime (msvcrt40.dll) is compiled as a cdecl DLL and calldll*_cdecl must be used Return types and calls ---------------------- Type Use ---------------------------------------------------------------------- long, short, void: calldll dllname|handle funct ?var...? You may also recast a long value to string pointer <type*> You may also cast any accessible type double, float: calldlldbl dllname|handle funct ?var...? string, bstr: calldllstr dllname|handle funct ?var...? variant calldllvariant dllname|handle funct ?var...? long, short, void: calldll_cdecl dllname|handle funct ?var...? double, float: calldlldbl_cdecl dllname|handle funct ?var...? string, bstr: calldllstr_cdecl dllname|handle funct ?var...? variant calldllvariant_cdecl dllname|handle funct ?var...? Return Error Codes ------------------- 0 No error 1 Invalid parameter passed 2 Failed to get handle to DLLNAME (poss. doesn't exist) 3 Can't get proc address to given function in existing DLL 4 Unhandled data type was passed via the VARIANT to CallDLL* Examples -------- Example: calldll_cdecl msvcrt40.dll printf "Hi from printf %i %f\n" 123 4.567 Result: Hi from printf 123 4.567000 Example: puts "Shell32 is user an admin: [bool [calldll shell32 @680]]" Result: true Example: puts "AutoIt is_admin: [bool [calldll AutoItX3.dll AU3_is_admin]]" Result: true Data Structures --------------- External API routines can often use structs. Ticol provides binary- compatible structs which can interface with both Ticol and external DLLs See: structs See also: calldllstr, calldll examples, open_dll, close_dll, struct, addressof, addressofb, strptr, ofaddress
calldll examples  Top  
Note: All examples require the statement: lib ticol_calldll -- set t 1470404087 # Fri Aug 05 14:34:47 2016 set ret [calldllstr_cdecl msvcrt40.dll ctime t] # Convert time_t to string puts "Result is ctime(FIXED-DATE): -"[string trim ret [chr 10]]- -- calldll user32 SetWindowTextA [calldll Kernel32 GetConsoleWindow] \ "Ticol Tcl" -- puts "Is user an admin?: [calldll Shell32 @680]" -- puts "is_admin: [bool [calldll AutoItX3.dll AU3_is_admin]]" true -- calldll_cdecl msvcrt40.dll printf "Hi from printf %i %f\n" 123 4.567 Hi from printf 123 4.567000 -- calldll mslib145 MapNetworkDrive "\\srv01\c[chr 36]" "q:" "" "" errcode 1 0 -- puts "proc mem: "[comma [calldll "mslib145.dll" "GetProcessMemoryUsed" \ [pid]]] -- proc ipfromhost {hostname} { return [calldllstr ping32 GetIPFromHostName $hostname] } -- puts "calldlldbl_cdecl->"[calldlldbl_cdecl msvcrt40.dll sqrt $pi] -- Example passing the address of a buffer by value to call a DLL: set timeout 0 set datalen 64 set buf [makestr 16] calldll ping32 PingAPI google.com [addressofb buf]:4 datalen:2 timeout:4\ 1000 Returns the string: in variable 'buf' -- Example querying Windows OS version struct OsVersionInfo { {OSVSize 4} # long {dwVerMajor 4} # long {dwVerMinor 4} # long {dwBuildNumber 4} # long {PlatformID 4} # long {szCSDVersion 128} # char* x 128 bytes } setb OSVSize [struct size OsVersionInfo] 4 -value puts "GetVersionEx=[calldll kernel32 GetVersionExA OsVersionInfo]" puts "OSVSize: "[ofaddressb OSVSize 4] puts "dwVerMajor: "[ofaddressb dwVerMajor 4] puts "dwVerMinor: "[ofaddressb dwVerMinor 4] puts "dwBuildNumber: "[ofaddressb dwBuildNumber 4] puts "PlatformID: "[ofaddressb PlatformID 4] puts "szCSDVersion: "[ofaddress szCSDVersion] dump OsVersionInfo -- # Requires the author's vbsqlite3.dll port set QueryString "SELECT t1.ArtistName,CDs.Title,CDs.date, CDs.CDID\ FROM Artists t1, CDs\ Where t1.ArtistID = CDs.ArtistID\ ORDER BY ArtistName, CDs.Date ASC " set dbfile ".\\test.db" set handle [dll_open "vbsqlite3.dll"] set r [calldll $handle sqlite3_open [strptr dbfile] db] set vr [calldllvariant $handle sqlite_get_table_basic $db:4 $QueryString] set rows [varray count $vr] set cols [varray count $vr 2] set dims [calldll $handle "GetArrayDimensions" $vr] puts "Table has $rows rows and $cols columns and $dims dimensions" calldll $handle sqlite3_close $db dll_close handle -- # Requires the author's VB Toolbox DLL set handle [dll_open mslib145.dll] calldll $handle LoadIPHLPAPI set adapters [calldll $handle GetAdapterCount] puts "Querying $adapters adapter(s)..." option expression off # No reason other than as a demo for {set i 0} {< $i $adapters} {++ i} { # uses eval not expr set addr [ofaddressb [calldllstr $handle GetIPAddress $i]] set name [ofaddressb [calldllstr $handle GetAdapterDescription $i]] puts "$i: [left $name 40] -> $addr" } dll_close handle -- See also: calldllstr, calldll, calldll_cdecl, single line commands
calldllstr, calldllstr_cdecl  Top  
To load, use: lib ticol_calldll ?-verbose? ?-nocomplain? Syntax: calldllstr dllname?.dll? function-name|@ordinal arg arg... calldllstr_cdecl dllname?.dll? function-name|@ordinal arg arg... Call a DLL which returns a string result, exported as a Tcl string If there is a need to dereference or address a returned pointer, e.g. to release memory allocated by the DLL call then you must use [calldll] instead and use the returned integer pointer address value. When a Tcl string is returned then the original address will be lost Static references to strings returned via [calldll] will return a reference to some part of an external variable. When [calldllstr] is used the original string (pointer address) reference is lost. No attempt should be made therefore, to release values returned by [calldllstr] other than using standard Tcl methods such as [unset] [calldllstr_cdecl] is used to call DLLs compiled with the __cdecl DLL calling convention. Use [calldll_cdecl] to return an address value If memory wasn't allocated by the DLL call then any return address returned by [calldll] when returning a string may be discarded. A null address will return 0 Example: # Uses shell32 StrChrA to locate a substring by character match # Shows differences between addressof and addressofb # and use of ofaddressb to dereference set s "Hello World" puts "addressof s [addressof s]" # Note how these addresses differ puts "addressofb s [addressofb s]" # This is the var string address puts "calldll: H is '[calldllstr shell32 StrChrA [addressofb s] [asc H]]'" set ptr [calldllstr shell32 StrChrA [addressofb s] [asc W]] puts "StrChrA($s,W) offset should be 'World' -> '[ofaddressb $ptr']" See also: calldll
carray plugin  Top  
To load, use: lib ticol_carray ?-verbose? ?-nocomplain? Syntax: handle [carray create ?size?] bool [carray add handle lval ?rval?] carray delete handle index integer [carray count handle] string [carray item handle index ?-rval? ?-list?] carray foreach handle lvalue ?rvalue? {code} carray sort handle ?-reverse? carray walk handle bool [carray unset handle ?-nocomplain?] Emulates "C"-like fixed arrays rather than associative arrays. Fixed arrays are indexed using 'base zero' integer index values and may be sorted, [carray] can optionally store an "Rvalue" string as well as the required "Lvalue". Multi-dimensional arrays are not supported create # Can pre-allocate memory to a given number of elements add # Adds an lvalue and, optionally, a corresponding rvalue # An Rvalue only may be added by specifying the Lvalue as {} delete # Removes an item by index (both Lvalue and any Rvalue) count # Returns a count of items in the array sort # Can sort the array in normal or reverse order. Note that fixed # arrays are not as efficient at sorting as associative arrays and # it may be impractical and slow to sort extremely large arrays item # Index the array by integer subscript foreach # Offers a means of iterating each element of the array in # ascending integer storage order. [foreach] is affected by # the internally-sorted order of the array walk # Is useful for debugging. It will iterate the array elements unset # Destroys the array and renders the handle unusable. Using # the handle after a call to [unset] will result in an error Example: set h [carray create] carray add $h Quick Brown carray add $h Fox Jumps carray add $h Lazy Dog carray add $h LValue carray add $h {} RValue carray sort $h carray foreach $h lv rv { # foreach iterator example puts "Lvalue:'$lv'\tRvalue:'$rv'" } carray sort $h -reverse set count [carray count $h] puts "We have $count item(s)" for {set i 0} {[< $i $count]} {++ i} { # Loop example puts "Item $i: '[carray item $h $i]'\t'\ [carray item $h $i -rvalue]'" } Results: Lvalue:'' Rvalue:'RVonly' Lvalue:'Fox' Rvalue:'Jumps' Lvalue:'Hello' Rvalue:'World' Lvalue:'LVonly' Rvalue:'' Lvalue:'Lazy' Rvalue:'Dog' Lvalue:'Quick' Rvalue:'Brown' Item 0: 'Quick' 'Brown' Item 1: 'Lazy' 'Dog' Item 2: 'LVonly' '' Item 3: 'Hello' 'World' Item 4: 'Fox' 'Jumps' Item 5: '' 'RVonly' Advantages and Disadvantages ---------------------------- Unlike associative arrays, "C" arrays can have an inherently ordered (sorted) state. They are, on average, slower to insert/add new records and sorting a large array may take a long time and searching a record on an unsorted array will usually be much longer than a hashtable- based associative array. Deleting All Nodes ------------------ As the count will change after each call to [carray delete] the following method should be used to iterate through and delete all nodes: set i 0 while {[> [carray count $h] 0]} { carray delete $h 0 # Delete the first record } A naive [for] loop which iterates the count with a fixed index won't work # Won't work as [carray count] changes after each [carray delete] for {set i 0} {[< $i [carray count $h]]} {++ i} { carray delete $h $i } See also: plugins, arrays
Ticol CPU Information Plugin  Top  
To load, use: lib ticol_cpu ?-verbose? ?-nocomplain? Shows various low-level CPU information by directly accessing the CPU Syntax: string [cpu name] # The full, descriptive name of the CPU string [cpu vendor] # The CPU vendor, e.g. "GenuineIntel" integer [cpu bitness] # The underlying O/S bitness, (32 or 64) integer [cpu cores] # Estimate the number of available cores bool [cpu hyperthreading] # Hyperthreading supported. Returns 1 or 0 bool [cpu hypervisor] # Running on hypervisor. Returns 1 or 0 integer [cpu eax] # eax register return as integer integer [cpu ebx] # ebx register return as integer integer [cpu ecx] # ecx register return as integer integer [cpu edx] # edx register return as integer Not all VMs will show hypervisor enabled. Some VMs will emulate the CPU entirely, others will use the underlying CPU but may disable some features The number of cores is an estimate and may be incorrect. The operating system may disable cores as it wishes Examples: lib ticol_cpu puts [cpu name] puts [cpu vendor] puts [cpu bitness] puts [cpu cores] puts [cpu hypervisor] puts "Virtual Machine Extensions " -nonewline if {& [cpu edx] 0x2} { # Test edx bit 2 puts "present" } else { puts "not present" } Results: Intel(R) Core(TM) i5 CPU M 540 @ 2.53GHz GenuineIntel 64 4 FALSE Virtual Machine Extensions present See also: plugins
concat  Top  
string [concat string ?string ...?] Efficiently concatenate one or more strings [concat] treats each argument as a list and concatenates them into a single list.It permits any number of arguments [concat] is much faster at accumulating strings than using chained [set] operations as the original source string is not repeatedly passed via the Ticol interpreter and parsed To concatenate items to a variable see [append] or [store] Example: puts [concat The quick brown fox jumps over the lazy dog] Result The quick brown fox jumps over the lazy dog Example: concat a b {c d e} {f {g h}} ,,end Result: ..yellow a b c d e f {g h} ,,end See also: append, store, setat, cmp, set, variable, performance
chdir  Top  
cd path chdir path Change the current directory. Does not support wildcard * chdir prefix Both forward and backslash characters are accepted Where cd is called from the command-line as a script expression, remember to escape all backslash characters and any reserved Tcl character such as the dollar ($) sign UNC paths are accepted but can have no action relative to a current, fixed drive-letter: Examples: cd.. cd .. cd \\rootdir cd \\rootdir\\subdir cd \\\\server\\share\\path # Will have no action relative to path cd \\\\server\\c\$\\path # Note that $ must be escaped cd /rootdir cd /rootdir/subdir cd //server/share/path # Will have no action relative to path cd //server/c\$/path # Note that $ must be escaped See also: mkdir, getcwd, file
chr  Top  
string [chr n ?added-offset-value?] The inverse of asc. Returns character number 'n' as a string The argument 'n' must be an integer value, not a character [chr] also permits a value to be added. This is useful where an integer is converted into an ASCII letter e.g. 0 -> 'a', 1 -> 'b' and avoids an additional and time-consuming call to [+] Example: puts [chr 65] Result: A Example: set i 2 puts [chr $i 97] # Character 2 + 97 Result: c See also: asc, string, left, right, mid, index
clock  Top  
Standard Tcl time/date routines Returns dates or times in the Unix epoch (01/01/1970) integer [clock clicks|seconds] string [clock format seconds|now ?-format "%Y-%m-%dT%H:%M:%S"?] Where seconds must be a positive integer [clock scan] is not implemented. See [date] and [time] The -format option controls what format the return will be in The contents of the string argument to format has similar contents as the format statement Additionally, there are several more %* descriptors which can be used to describe the output. %a Abbreviated weekday name (Mon, Tue, etc.) %A Full weekday name (Monday, Tuesday, etc.) %b Abbreviated month name (Jan, Feb, etc.) %B Full month name (January, February, etc.) %d Day of month %j Julian day of year %m Month number (01-12) %y Year in century %Y Year with 4 digits %H Hour (00-23) %I Hour (00-12) %M Minutes (00-59) %S Seconds(00-59) %p PM or AM %D Date as %m/%d/%y %r Time as %I:%M:%S %p %R Time as %H:%M %T Time as %H:%M:%S %Z Time Zone Name The default -format mask is "%a %b %d %H:%M:%S %Y" Examples: Command: Result clock clicks # 80579 clock seconds # 1425214130 clock format now -format "%Y %m %d" # 2015 03 01 clock format 9999 -format "%Y %m %d %H:%M:%S" # 1970 01 01 02:46:39 Example: puts [clock format [double_to_ctime [now]] -format "%Y/%m/%d %H:%M:%S" Result: 2015/04/08 12:15:41 See: clock, clock scan workaround See also: clock format, clock scan, clock scan workaround, time, date, ticks, double_to_ctime, ctime_to_double, date_to_ctime, now, vars, is_dst
clock format  Top  
string [clock format seconds|now ?-format "%Y-%m-%dT%H:%M:%S"?] Format codes for the clock -format string are as follows. These are standard C/C++ formatting codes with a couple of extra codes %a Abbreviated weekday name %A Full weekday name %b Abbreviated month name %B Full month name %c Date and time representation appropriate for locale %D Day of month as a decimal number with no 0 prefix (1..31) %d Day of month as decimal number (01..31) %H Hour in 24-hour format (00 .. 23) %I Hour in 12-hour format (01 .. 12) %j Day of year as decimal number (001..366) %m Month as decimal number (01 .. 12) %M Minute as decimal number (00 .. 59) %p Current locale's A.M./P.M. indicator for 12-hour clock %o Day of month ordinal. E.g. "st", "nd", "rd", "th" %S Second as decimal number (00 .. 59) %U Week of year as decimal number, with Sunday as first day of week (00..51) %w Weekday as decimal number (0 .. 6; Sunday is 0) %W Week of year as decimal number, with Monday as first day of week (00..51) %x Date representation for current locale %X Time representation for current locale %y Year without century, as decimal number (00 .. 99) %Y Year with century, as decimal number %z, %Z Time-zone name or abbreviation; no characters if time zone is unknown %% Percent sign Example: puts [clock format 0 -format "%A, %D%o %B %Y"] Result: Thursday, 1st January 1970 Example: puts [clock format now -format "%A, %D%o %B %Y %H:%I:%S"] Result Wednesday, 4th October 2017 20:04:37 See also: clock, time, date, clock scan, clock scan workaround
clock scan  Top  
clock scan <date> [clock scan] accepts input in the following common formats US date format - 'MMM DD ?HH:MM:SS?' US date format - 'MMM DD YY ?HH:MM:SS?' US date format - 'MMM DD YYYY ?HH:MM:SS?' US date format - 'MMM DD, YY ?HH:MM:SS?' US date format - 'MMM DD, YYYY ?HH:MM:SS?' US date format - 'MMMM DD ?HH:MM:SS?' US date format - 'MMMM DD YY ?HH:MM:SS?' US date format - 'MMMM DD YYYY ?HH:MM:SS?' US date format - 'MMMM DD, YY ?HH:MM:SS?' US date format - 'MMMM DD, YYYY ?HH:MM:SS?' US date format - 'DD MMM ?HH:MM:SS?' US date format - 'DD MMM YY?HH:MM:SS?' US date format - 'DD MMM YYYY?HH:MM:SS?' US date format - 'DD MMMM ?HH:MM:SS?' US date format - 'DD MMMM YY ?HH:MM:SS?' US date format - 'DD MMMM YYYY ?HH:MM:SS?' US date format - 'MM/DD ?HH:MM:SS?' US date format - 'MM/DD/YY ?HH:MM:SS?' US date format - 'MM/DD/YYYY ?HH:MM:SS?' US date format - 'DD/MM ?HH:MM:SS?' US date format - 'DD/MM/YY ?HH:MM:SS?' US date format - 'DD/MM/YYYY ?HH:MM:SS?' Where: MM is a 2-digit month value MMM is a 3 character month name MMMM is a full month name DD is a 1 or 2 digit day YY is a 2 digit year > 100 AD, where > 50 -> 19xx and <= 50 -> 20xx YYYY is a 4 digit year The output is always limited to the start of the Unix time epoch - 1970/Jan/01 00:00:00 (0) [clock scan] can be emulated for various date formats using [scan] and [date], Example: # Scan an ISO date into [date] format scan 20161122 %4i%2i%2i y m d puts "$y/$m/$d" Result: 2016/11/22 Checks are made only on each individual parmameter. No check is made for the validity of the entire date string. See: clock scan workaround Example: set a [clock scan "Jan 12, 1992"] set b [clock scan "Jan 12, 1997"] puts $a puts $b puts "Difference is [- $b $a]" Results: 695174400 853027200 Difference is 157852800 second(s) The result of [clock scan] can be converted from a "C" integer time value to double using [ctime_to_double]. This value can then be manipulated as an ISO date string using [date] Example: set b [clock scan "Jan 12, 1997, 23:59:12"] puts [date [ctime_to_double $b]] Result: 1997/01/12 23:59:12 Error Codes ----------- 1 Bad slash separator count 2 Day value < 1 || > 31 3 Month value < 1 || > 12 4 Missing value field 5 Resulting date is invalid 6 Unhandled error See also: clock scan workaround, date, time, scan, is_dst
Clock Scan Workaround  Top  
[clock scan] is not fully-implemented as the date inputs are too widely varying to be practical. Using the popular Tcl example code we can demonstrate an easy workaround using [scan] and [date] # We replace: set bookSeconds [clock scan $halBirthBook] set h 00 set i 00 set s 00 set halBirthBook "Jan 12, 1997 01:02:03" set count [scan $halBirthBook "%s %s %s %02d:%02d:%02d" m d y h i s] puts "Scanned $count item(s)" set d [string trim d ,] puts "date string $y/$m/$d $h:$i:$s" set bookSeconds [date $y/$m/$d $h:$i:$s -ctime] puts "bookSeconds=$bookSeconds" newline # We replace: set movieSeconds [clock scan $halBirthMovie] set h 00 set i 00 set s 00 set halBirthMovie "Jan 12, 1992 23:59:01" set count [scan $halBirthMovie "%3s %s %s %02d:%02d:%02d" m d y h i s] puts "Scanned $count item(s)" set d [string trim d ,] puts "date string $y/$m/$d $h:$i:$s" set movieSeconds [date $y/$m/$d $h:$i:$s -ctime] puts "movieSeconds=$movieSeconds" newline set diffseconds [expr $bookSeconds - $movieSeconds] puts "The book and movie versions of '2001, A Space Odyssey' had a" puts "discrepancy of $diffseconds second(s) [/ $diffseconds 86400] day(s)\ in how" puts "soon we would have sentient computers like the HAL 9000" Based on example from: https://www.tcl.tk/man/tcl8.5/tutorial/Tcl41.html See also: clock scan, clock, date, time, scan
close, file close  Top  
close handle file close handle Close a file-handle previously returned from the open command Handle must be >0 and a valid stream handle [puts] may be used to write to the file Example: set fp [open "input.txt" w+] puts $fp "test" close $fp See also: open, gets, file
cls  Top  
cls Clear the console window See also: console
cmdcount (Command Count)  Top  
integer [cmdcount] integer [cmdcount script|command ?var?] Similar to [catch], dcount will either show the current count of commands executed or will execute a command or script and return a count of the number of commands which were executed. Along with the [time] command this may be useful for profiling and optimising Tcl scripts Example: puts [cmdcount] # Show the current command count Result: 1 Example: puts [cmdcount {puts "Hello"}] # Command cost of running this command Result: 1 Example: puts [cmdcount {run test.tcl}] Result: 2786 See also: debugging, time, trace, catch
cmp (Compare)  Top  
bool [cmp var|string1 string2 start-pos ?len? ?-ignorecase?] Efficient compare function. Avoids the need to extract string segments for comparison by comparing directly within the string. Either a variable or a string-literal may be given. The start position is indexed at a base 1 offset. You may also perform a case-insensitive comparison using -ignorecase Example: (Detect C style opening comment) option expression off for {set i 1} {< $i $count} {incr i} { if { cmp data "/*" $i 2 } { incr i 2 set in_comment $true } } See also: cat, eq, ne, efficiency
comma  Top  
string [comma string ?separator-char?] Comma-formats a numeric value. Optionally, the separator character may be customised Example: puts [comma 1234567890] Result: 1,234,567,890 Example: puts [comma 1234567890 " "] Result: 1 234 567 890 See also: format
commands  Top  
list [commands ?filter?] Returns a list of all known/registered commands and procs A filter may be used to select by filter prefix match Example: commands sc Result: scan screen [is_command] may be used to test for the presence of a defined command or proc A count of commands registered may be obtained using: puts [lcount [commands]] Use: option echo on to display directly to the console See also: commands by function, info, is_command, vars, help, exit
Ticol Command Line  Top  
ticol.exe filename[.tcl] [arg ...] [/switches] ticol.exe ; [statement ...] [/switches] Running Tcl scripts from the Windows command-line: If the first argument to ticol.exe is a Tcl script then this will be loaded and executed after running any autoexec.tcl file (unless /NA is specified) Any subsequent arguments can be accessed from the argv() array See: argv Using Ticol as a command-line expression-evaluator from Windows: You can call Ticol with Tcl commands if you prefix them with a semi-colon character as the first command-line argument and quote the remainder when necessary. This avoids Ticol attempting to run a Tcl script file ticol.exe ; "puts [+ 1 1]" ; Embedded double quotes may be escaped in Windows using \" e.g. ticol.exe ; "puts [expr \"22/7.0\"]" ; or you may use the /EXPR command-line argument. This will evaluate and return the result by calling [expr] ticol.exe ; "/expr:22/7.0" The semi-colon variant can handle multiple arguments in the same interpreter context: Example: ticol.exe ; "set a 4" "printf \"Pi is %3.2f\r\n\" \ [calc round(4*atan(1),2)]" "puts [expr $a*3]" /na Result: Pi is 3.14 12 Example: ticol ; "load test.tcl; run" Result: <runs script test.tcl and then returns to the O/S> Expressions with embedded spaces, commands etc. must be wrapped in double-quotes. Embedded double-quotes may be escaped ticol "/expr:[cube 3]" /debug # works OK ticol /expr:[cube 3] /debug # does not ticol "/expr:\"Hello world\"" /na # puts not required Calling from Windows FOR Command -------------------------------- The Windows FOR command will require usebackq and backtick wrappers to use double-quotes around any Tcl /EXPR command which contains spaces FOR /F "tokens=* usebackq" %%i in (`ticol.exe "/expr:round(22/7.0,4)"`) DO ( SET RESULT=%%i ) ECHO Ticol expression result for 22/7.0 is %RESULT% FOR /F "tokens=* usebackq" %%i in (`ticol.exe "/expr:4*atan(1)"`) DO ( SET RESULT=%%i ) ECHO Ticol expression result for 4*atan(1) is %RESULT% /EXPR may also be used to call external __stdcall or __cdecl DLLs ... FOR /F "tokens=* usebackq" %%i in (`ticol /expr:"[calldlldbl_cdecl \ msvcrt40.dll sqrt 10.0]" /na`) DO ( SET RESULT=%%i ) ECHO Result for [calldlldbl_cdecl msvcrt40.dll sqrt 10.0] is %RESULT% The Windows FOR command requires no CRLF to be issued. You can add a CRLF to the output by adding the /CRLF argument See also: command line, command line arguments, Ticol, commands
Comments  Top  
Standard Tcl Comments are prefixed by the # character Example: # This is a comment End of line comments are supported and are enhanced since they may start at any position on a line, not just as the first character.A semi-colon is not required before a # comment as these are implemented by the macro preprocesor A comment start # symbol is valid only outside of quoted strings. Hash symbols within quoted strings are not treated as comment start markers and may be used as literal characters It is strongly-recommended that, as a matter of style, a comment character is followed by a space. This will avoid accidental and difficult to trace clashes with the Ticol macro commands (e.g. #exec, #if, #exit) The Tcl semi-colon+hash end of line syntax is supported but not required # This is a comment puts "Hello World" # This is a valid Ticol comment puts "Goodbye" ;# This also a valid comment puts "Quoted # char" ;# This is a valid Tcl comment too Any information after a comment character is completely removed by the Ticol Macro PreProcessor. To disable this use the /NP (no preprocesor) command-line argument. Note that this also disables #ifdef etc. macros and these must therefore be removed from the source file A # comment should not appear after a line continuation character '\' Example: "The quick brown\ # This comment is illegal because of \ fox jumps over\ # So is this the lazy dog" Long comments are supported via the Macro PreProcessor #ifdef... #endif statements and also by C/C++ style /* ... */ comment markers. C/C++ style comments are the most efficient and both styles are processed by the Macro PreProcessor (MPP) both from the command-line or CLI during [load] or [run] Example Tcl comments using macro variables and #ifdef commands #ifdef comment set a 22 set b 7.0 puts [/ $a $b] #endif To revert a long macro comment either delete or prefix again with a 2nd # character ... ##ifdef comment # This ifdef statement is commented-out #ifdef comment # This ifdef statement is active And (perhaps heinously, for some Tcl enthusiasts) C/C++ style comments are supported ... /* This is a comment, this code is ignored So is this invalid expression [expr 1/0] Some may not like this, but it is convenient and useful */ C/C++ long comments are not valid inside quoted strings and are treated as string literals within them. Thus... set a "Brave /* new */ world" will result in the string ... Brave /* new */ world C/C++ long comments may be ignored by prefixing with a standard Tcl # comment ... #/* puts "This code will be executed as it is not commented" #*/ C++ single-line style comments may be defined using this dummy proc: proc // args { # C++ style comment - do nothing. Discard all args on this line } Be careful of Unix-style wildcard filename/path values within unquoted strings. It is good practise to always wrap strings in quotes... puts [ftp $hostname ls /tools/ * -u admin -p xxxxx] Should be: puts "[ftp $hostname ls /tools/*.zip -u admin -p xxxxx]" Since the unquoted '/*' in '/*.zip' will be interpreted as a long comment start. Quoting will prevent this. These are examples of a dangerous comments because '#if' and '#else' are reserved Macro Preprocessor keywords. Commenting out a Tcl [if] or [else] statement will create a valid Macro directive #if This line is present the MPP will execute the '#if' clause #else This comment is also dangerous #exit This comment will cause the MPP to exit See also: command line, cli, Ticol
Ticol Compatibility with Standard Tcl  Top  
Ticol Tcl was designed to be flexible and have a reasonable degree of compatibility with standard Tcl. Standard Tcl has changed over time and has incorporated many new features. Ticol was written for personal use by the author and incorporates a number of changes which were desired by the author Some of these changes reduce compatibility with standard Tcl. One of the main design issues was a desire to improve performance by use of a Macro PreProcessor (MPP) to optimise source code before execution. It was decided that the # character would be an absolute comment delimiter and therefore cannot be uses in commands such as [uplevel]. C/C++ like comments are also available as these suited the author's preference The Macro PreProcessor is non-Tcl-standard and is more C-like. Although basic it can offer some advantages when developing Tcl code Tests showed that standard Tcl command such as [+] or [-] were much faster than the expression-handler. Perhaps because Ticol doesn't make use of any compiler-like optimisations when interpreting the script and it leans on the basic Picol kernel interpreter design. For this reason, a new command [calc] was added which enables the MPP to expand expressions into inline Tcl code.If the MPP is disabled then [calc] will be interpreted as [expr] Some advanced Tcl features are not implemented either fully or at all. Arrays are preferred by the author to lists and dictionaries and have been implemented as hashtables. Performance of arrays is quite fast with Ticol being able to handle a million array items with no particular problems and with excellent access speed Ticol has its own (DLL) plugin library support which is not supported by standard Tcl. One of these plugins offers the ability to interface into external DLL libraries (either __stdcall or __Cdecl). To support this interface Ticol also offers a simple binary struct which enables API/external DLL calls and struct returns. Variants are also supported The plugin interface C++ API code is available on request so you can extend Ticol by adding new commands Ticol also offers many non-standard commands which can be used to improve performance and flexibility, e.g. [funct] will allow you to call any [expr] function directly. [funct] is used by the MPP when it expands [calc] expressions Other commands include: [at_exit], [base64], [cat], [chr]. [encrypt], [ctime_to_double], [decimal_to_roman], [dump], [elevate], [inputbox] [json_to_list], [msgbox], [shell], [spawn], [win_error], [write] Standard Tcl may require some modifications before it will run on Ticol Tk is not supported See also: Non Standard Tcl Commands, Ticol, FAQ, Performance, Plugins, Tcl
console  Top  
console close # Closes the console and exits Ticol console hide # Hides the console console show # Shows the console console hidden # Returns a boolean 1 if hidden, 0 if not console get_title # Return the console title as a string console move x y ?w? ?h? # Move the console window (resize) console scroll x y w h ?lines? # Scroll a console area console setfocus # Set focus on the console window console title string # Set the console title Show or hide the console window or check if the console is already hidden. Note: if you hide the console window you will lose control of the Ticol CLI The command 'console hide' should be run only from a running script or you may lose control of the console. Hiding the console may be useful for CGI web scripts Setfocus has limited use and may be blocked by recent versions of Windows [console scroll] accepts an optional lines argument. Currently 1 (default) scrolls the contents of the area up and -1 scrolls the window content downwards Usage: console hide console show console setfocus Example: console title "Ticol Demo" puts "Hiding the console..." console hide puts "Console hidden? [bool [console hidden]]" # Not visible until show sleep 3000 console show puts "I should be back now" Result: The console window will disappear for 3 seconds then reappear See also: screen, CLI, box, gotoxy
Console Colours  Top  
The standard console colours can be customised. This may be necessary as some colours in the standard Windows console palette are not represented well. These also may not match those interpretations on very old PC system For example, orange appears as khaki brown for some reason on some versions of Windows. Example: (Set console "DarkYellow" to be orange) Save the following file as: console-orange.reg To load it, double click and accept the prompts --------------------------------------------------------------- Windows Registry Editor Version 5.00 ; Colour table with DarkYellow == Orange 0x00c0c0c0 (BGR format) [HKEY_CURRENT_USER\Console] "ColorTable06"=dword:00508dfc --------------------------------------------------------------- Note that the file may only be valid for the current session and unless the defaults are changed the colours will revert after the next reboot Colour changes made via the registry have no effect until a new console window is opened See also: console, big graph
const  Top  
const varName value Define a simple constant variable. Constants cannot be assigned-to Const values will typically be created in global scope and can be accessed from within procedures using the $::constname scope prefix. Or they may be declared using upvar to create a local const instance Constants can be deleted using [unset] Const arrays can be set using [array set arrayname -const] Example: const ONE_GIGABYTE 1073741824.0 puts $ONE_GIGABYTE puts [bool [is_const ONE_GIGABYTE]] unset ONE_GIGABYTE -const puts [bool [is_set ONE_GIGABYTE]] Results: 1073741824.0 True False See also: enum, set, array set
copyfile  Top  
integer [copyfile sourcespec target ?-y?] Copy a file from sourcefile to targetfile. Wildcards are supported Path targets or specified filename targets are supported Paths accept \ or / separators. Where a trailing -y is used from the CLI then a trailing / separator must be used to signify a path as the backslash will be interpreted as a line-continuation escape character (\). Where backslashes are used then take note that the Macro PreProcessor (MPP) will require these to be escaped as double backslashes (\\) e.g. "c:\\path" The count of successful copies is returned else 0 on failure Example: copyfile ticol.exe c:\temp\ticol.exe -y copyfile ticol.exe c:/temp/new Copy to target file /temp/new copyfile c:\\tcl\\*.tcl c:\\temp Existing directory copyfile c:\\tcl\\*.tcl c:/temp/new Will fail as '/new' is a file copyfile c:\\tcl\\*.tcl c:/temp/new/ Force create '/new/' directory See also: movefile, file
Ticol Copyright and Licensing  Top  
--------------------------------------------------------------------------- Ticol Copyright and BSD Licence --------------------------------------------------------------------------- Ticol and this help file is Copyright (C) to M Shaw 2015-2017 All rights reserved. Copyright (c) 2007-2016, Salvatore Sanfilippo <antirez@invece.org> All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --------------------------------------------------------------------------- This project was initially a small project called Picol, by Salvatore Antirez Sanfilippo, which implemented a Tcl interpreter in 500 lines. This is covered under a BSD licence, which permits closed-source derivations. The original Picol source code is freely available on the internet The Picol project source code has been replaced with about 100,000 lines of C++ code. This additional source code is not available but the program will be made available for both private and commercial use as freeware. Should any disputes arise the author reserves the right to withdraw Ticol from all further public distribution by way of remedy The help (man) file is copyrighted (C) to M Shaw 2015-2017 and may not be altered and may not be redistributed separate from the Ticol program and a copy of these licence conditions. Please read the LICENCE.TXT file for the full licence terms The licence for use of Ticol does not allow charging for the program or commercial/mass redistribution in any form without the express consent of the author. You are free to distribute directly to friends and colleagues No warranty of fitness for use or any other type of warranty is offered. By using Ticol you agree to use it at your own risk and indemnify the author against all liabilities arising. Ticol should not be used in a commercial environment without adequate and thorough acceptance testing The reason for this is to limit personal liabilities both legally and in terms of expected levels of support In summary: You may freely use Ticol whether for private or commercial use You may give individual copies of Ticol to friends or colleagues You may not sell Ticol or redistribute it for sale You may not upload Ticol to a mass-distribution system without permission You may not distribute Ticol from any redistribution website You agree to satisfy yourself of any fitness for use regarding Ticol You accept this as software offered free and in good faith You agree that this software is not warrantied in terms of fitness for any purpose whatsoever You accept that this is a personal/hobby/educational project and you hold no commercial or professional expectations of it either in terms of reliability, fitnees for use, performance or levels of support You use Ticol entirely at your own risk and indemnify the author from any and all direct or consequential liabilities arising from its use You must include this documentation and copyright notice/licence terms with any copies you pass on to a 3rd party See: Ticol, why, frequently asked questions
ctime (Unix time)  Top  
C or "Unix" time is defined as a signed integer representing the number of seconds elapsed since 00:00:00 hours on January the 1st 1970 Dates prior to this cannot be represented Dates after 03:14:07 UTC on 19 January 2038 cannot be represented The Visual BASIC method is to use a double value to represent time Example: puts [clock seconds]x Result: 1449684929 See: https://en.wikipedia.org/wiki/Year_2038_problem Convert to a string format using the [clock format] command See also: vbtime, date_to_ctime, double_to_ctime, ctime_to_double, clock, time, now
ctime_to_double, double_to_ctime  Top  
ctime_to_double seconds double_to_ctime double [ctime_to_double] converts the standard internal Tcl "C" time format from seconds in the Unix epoch of 01/Jan/1970 to an industry-standard or Visual BASIC double value. [double_to_ctime] performs the inverse operation Example: puts [clock format [double_to_ctime [now]] -format "%Y/%m/%d %H:%M:" Example: puts [double_to_ctime [now]] puts [clock seconds] Result: 1449684929 1449684930 See also: date, time, is_date ,date_to_ctime, clock, clock format, now, ctime
VB (Visual BASIC) Time  Top  
Visual BASIC stores Date values as an IEEE 64-bit (8-byte) floating point number, identical to a VB Double. Digits to the left of the decimal point, when converted to decimal, are interpreted as a date between 1 January 100 and 31 December 9999. Values to the right of the decimal indicate a time between 0:00:00 and 23:59:59 The date section of the Date data type, is a count of the number of days that have passed since 1 Jan 100, offset by 657434. That is, 1 Jan 100 is denoted by a value of -657434; 2 Jan 100 is denoted -657433; 31 Dec 1899 is 1; 1 Jan 2000 is 36526 etc. The time section of the date (after the decimal point) is the fraction of a day, expressed as a time. For example, 1.5 indicates the date 31 Dec 1899 and half a day, i.e. 12:00:00. So, an hour is denoted by an additional 4.16666666666667E-02, a minute by 6.94444444444444E-04, and a second by 1.15740740740741E-05 The Ticol [date], [dateserial] and [time] commands understand Visual BASIC format doubles representing date values See also: date, dateserial, time, ctime, now, date_to_ctime
is_*  Top  
See: is_admin Test if user has administrative rights is_command string Is a string a registered command is_const string Is a string a constant variable is_date string Is a string a valid formatted date or time is_dir path Is a string a valid directory is_dst Test if we are in Daylight Savings Time is_elevated Test if we are running with elevated rights is_empty var Test if a variable is both set and empty is_file name Test a file is_leapyear string Is a date value a leap year is_list string Test if a string is a valid Tcl list is_mod x Optimised modular division test is_numeric x Is a string a valid number is_pointer x Is a variable a pointer variable is_proc name Test if a string is a defined proc is_set var Is a string a valid/existing variable array exists a Tests if an array exists array is_set a Tests if an array element is set All the above commands return type "bool" (0 | 1) See also: array exists, array is_set
is_dst  Top  
bool [is_dst ?-bias? ?-offset? ?-standardname? ?-daylightname?] [is_dst] returns a boolean (1 or 0) indicating whether we are currently in Daylight Savings Time. The actual time offset is not returned The '-bias' argument will return the local geographic time zone bias from UTC (GMT) in minutes. The '-offset' argument will return the local Daylight-Savings-Time (DST) offset in minutes The '-name' argument will return the name of the time zone Example: # US Central time (-6hrs) will return -360 (minutes) puts [is_dst -offset] Result: -360 Example: # UK summer time (+1hr) will return 60 (minutes) puts [is_dst -offset] Result: 60 Example: puts [is_dst -standardname] Result: GMT Standard Time Example: puts [is_dst -daylightname] Result: GMT Daylight Time See also: time, date, clock, ctime_to_double, double_to_ctime
is_date  Top  
bool [is_date double] bool [is_date date|time] bool [is_date date] bool [is_date time] bool [is_date "date time"] bool [is_date "time date"] Performs basic sanity checks in a date-interpreted double value or string(s) Examples: puts [is_date 0] # True puts [is_date -1] # True puts [is_date 42657.0430902778] # True puts [is_date 2016/Oct/14] # True puts [is_date 2016/10/14] # True puts [is_date 00:00:59] # True puts [is_date 2016/10/14 01:02:03] # True puts [is_date 01:02:03 2016/10/14] # True puts [is_date "2016/10/14 01:02:03"] # True puts [is_date {2016/10/14 01:02:03}] # True puts [is_date 9999999.0430902778] # False (out of range) puts [is_date "00:00:59 2016/oct/39"] # False (invalid day) See also: date, dateserial, vbtime
is_file  Top  
bool [is_file filename] Currently checks for the existence of a file and returns a boolean value indicating whether the file exists or not Examples: puts [is_file ticol.exe] puts [is_file nosuch.txt] Results: 1 0 See also: file, is_*
is_leapyear  Top  
bool [is_leapyear year] Confirms whether a year value is a leapyear or not. Valid from 1AD to 9999AD Returns a boolean (integer) 1 or 0 Example: puts [is_leapyear 0001] puts [is_leapyear 0004] # Is a leap year puts [is_leapyear 4] # Is a leap year puts [is_leapyear 1896] # Is a leap year puts [is_leapyear 2001] puts [is_leapyear 2012] # Is a leap year puts [is_leapyear 9996] # Is a leap year puts [is_leapyear 9999] Results: 0 1 1 1 0 1 1 0 See also: is_date, is_*
is_list  Top  
bool [is_list string] Test if a string is a valid Tcl list Example: puts [is_list {}] puts [is_list ""] puts [is_list a] puts [is_list {a b] Results: 0 0 1 1 See also: is_*, list, lindex, lcount
date  Top  
date ?-separator char? # Return the current date as YYYY-MM-DD # Use [date -separator {}] for YYYYMMDD date -year # Return the current year as YYYY date -month # Return the current month as M date -day # Return the current day as D date -yday # Return the current day of the year as D date double ?-separator char? # Returns YYYY-MM-DD with optional separator date double ?-list? # Return each field as a Tcl list date double ?-notime? # Suppress display of time value time double # Use [time] to suppress date value date double ?-longmonth? # Display 3-character month names e.g. "Jan" date now # Returns the current date as a double value date YYYY/MM/DD ?hh:mm??:ss? # Returns a double representing the date date YYYY-MM-DD ?hh:mm??:ss? # Do date YYYY/MMM/DD ?hh:mm??:ss? # Do date YYYY-MMM-DD ?hh:mm??:ss? # Do date DD/MM/YYYY ?hh:mm??:ss? # Do date DD-MM-YYYY ?hh:mm??:ss? # Do date DD-MMM-YYYY ?hh:mm??:ss? # Do date DD-MMM-YYYY ?hh:mm??:ss? # Do date <date-string> -ctime # Return the time as a C-long integer dateserial YYYY MM DD hh mm ss # Use [dateserial] for dates as Tcl lists Shows the current system date in ISO YYYY-MM-DD format ISO date format is preferred Returns a VB6-compatible date value as double Or, returns a formatted date/time string Date Ranges Numeric inputs range from -693958.000000 (0000/01/01 AD) to 2958465.000000 (9999/12/31 AD). Units are in days and fractions of a day as per Visual BASIC 6.0 US Date Formats The US date formats of MM-DD-YYYY and MM-DDD-YYYY are not supported Comma Date Formats The date format Jan, 1, 2016 and similar formats are not supported Input Locales Automatic/Windows system input locales are not supported The epoch starts the same as for VB6 at 30/Dec/1899 as value 0.0 Negative values extend as far back as January, 1st 0 AD 1/1/70 00:00:00 (Unix epoch in VB) is 25569.0 as a double February 5, 2036 (Unix epoch end) is 49711.00001157407 (00:00:01 6th Feb 2036) Valid Range Dates are valid in the range from 0 AD to 9999/12/31 AD Dates older than the positive VB6 date epoch are negative Year values must be 4-digit. Leading zeroes are required if a date is < 4 digits. e.g. 325 AD will be year "0325" not "325" Values outside the of range 0/00/00 to 9999/12/31 (-693959.0 to 2958465.0) will raise an error Similarly: puts [date [time [date now] -ctime]] is invalid because [date] cannot take a C time value as an argument. In such cases we would use [ctime_to_double] to convert the result from [time]: puts [date [ctime_to_double [time [date now] -ctime]]] Short Year Values Short year values such as 99 for 1999 are not supported 4-digit years are mandatory otherwise 0.0 will be returned Date Arithmetic Since date values are "real" (floating point double) values they may be added, subtracted, multiplied or divided with caution and providing the number range is adhered to when reconverting back to date format using [date] Year/month/day values can be compared with now by using [int] to strip off the fractional (time) part of the number Example: if {[eq [int [date now]] [date $year-$month-$day]]} {...} Exercise caution when adding dates on or before the zero epoch date of 30/dec/1899 as time values will wrap-around. You may need to use [fpart] or [fraction] to split-off the fractional part of a date, save it and then re-add after arithmetic. This is because dates < 30/dec/1899 are represented negative floating point and changing the sign may invert the fractional part When manipulating for whole days you will usually need to strip off the fraction parts of double values to avoid rounding up with 1 day error You may use [fpart] to strip-off and save the decimal fraction part Example: # Increment year from 325 AD to 1776 AD, keeping the time # An alternate method is to return a list and increment item 0 set d [date 0325/jan/01 09:30:00] # Save full date set t [fpart $d] # Split off and save time set i [integral $d] # Split and save the date puts "Stored: $d [date $d] and time as $t" # Display saved values set r [+ [* 1452 365] $i] # Add 1452 365 day years puts "Result: '${r}.$t' -> [date ${r}.$t]" # Concatenate and display Result: Stored: -575255.3958333334 0325/01/01 09:30:00 and time as 3958333333 Result: '-45275.3958333333' -> 1776/01/01 09:30:00 Example: # Date subtraction in epoch range > 0.0 (30/Dec/1899) # Days to 2019/01/10 puts "[int [- [date 2019/01/10] [date now]]] days" # Days to Xmas 2016 puts "[int [- [date 2016/12/25] [date now]]] days" Results: 813 days 67 days Time Arithmetic --------- Time values should be first converted using [date]. Next, any arithmetic should be performed, and the result converted back using [time] puts [date 11:58] puts [date 5:30] # Add 5.5 hours to 11:58 puts [time [+ [date 11:58] [date 5:30]]] # Same action using [now] puts [time [+ [now] [date 5:30]]] # Same action, giving a full date puts [date [+ [now] [date 5:30]]] Results: 0.4986111111 0.2291666667 17:28:00 17:29:58 2017/04/14 17:30:58 Exception Errors Accessing a date value outside the valid range will trigger an exception error. Other date errors will return 0.0 Notes - Converting from 1 second interval cdates to decimal day fractions Multiply each second by 0.000011574074074 or [/ 1 86400.0] Example: # 1 second past the Unix epoch end puts [+ 49711 [/ 1 86400.0]] # 1 second past the Unix epoch end puts [date [+ 49711 [/ 1 86400.0]]] Result: 49711.000011574077 2036/02/08 00:00:01 Visual BASIC Anomalies In order to accommodate two digit year values, VB5 interprets cdbl(fix(cdate("0000/jan/1"))) as 36892.0; which is 01/01/2000 Dates with a year of < 100 AD are interpreted as being in the year 2000 Ticol does no such 2-digit year interpretation adjustment. Post Y2K there is now no valid reason to use two-digit year dates within scripts. 4-digit years are mandatory in Ticol for all dates after 999 AD More Examples Result puts [date] 2016-10-18 # ISO date puts [date -year] 2016 # Current year puts [date -month] 10 # Current month puts [date -day] 18 # Current day puts [date -yday] ? # Day of year puts [date now] 42661.785891 # "now" keyword puts [date [date now]] 2016/10/18 18:51:41 puts [date 0] 1899/12/30 # Same as VB6 puts [date 1] 1899/12/31 # Same as VB6 puts [date 2] 1900/01/01 # Same as VB6 puts [date 0000/1/1] -693958 # VB6=01/01/2000 puts [date -693958.000000] 0000/01/01 # Jan, 1st 0 AD puts [date 0001/1/1] -693593 # VB6=01/01/2001 puts [date -693593.000000] 0001/01/01 # Jan, 1st 1 AD puts [date 42661.785891] 2016/10/18 18:51:40 puts [date 42661.785891 -separator -] 2016-10-18 18:51:40 puts [date 42661.785891 -separator " "] 2016 10 18 18:51:40 puts [date 42661.785891 -separator _] 2016_10_18 18:51:40 puts [date 42661.785891 -longmonth] 2016/Oct/18 18:51:41 puts [date 2016-10-18] 42661 # YYYY-MM-DD puts [date 2016/10/18] 42661 # YYYY/MM/DD puts [date 18-10-2016] 42661 # DD-MM-YYYY puts [date 18/10/2016] 42661 # DD/MM/YYYY puts [date 0325/01/01] -575255 # -ve (325 AD) puts [date 1400/01/10] -182610 # Same as VB6 puts [date 1700/01/10] -73037 # Same as VB6 puts [date 1970/01/01] 25569 # Unix epoch puts [date 2036/02/06] 49712 # Unix epoch end puts [date 9999/02/06] 2958101 # Same as VB6 puts [date 2016-10/18] 0.000000 # ERROR puts [dateserial 2016 10 18 18 51 40] 42661.785880 # For lists puts [date 2016/10/18 18:51:40] 42661.785880 # 2 arguments puts [date 18:51:40 2016/10/18] 42661.785880 # Reverse is OK puts [date "2016/10/18 18:51:40"] 42661.785880 # Quoted is OK puts [date {2016/10/18 18:51:40}] 42661.785880 # Braced is OK puts [date {18:51:40 2016/10/18}] 42661.785880 # Reverse is OK See also: time, dateserial, is_date, ticks, clock, ctime, vbtime, date_to_ctime, fpart, clock scan workaround, clock scan
dateserial  Top  
dateserial ?year|-? ?month|-? ?day|-? ?hour|-? ?minute|-? ?second|-? dateserial ?tcl-list? Calculates a date value and returns a double from individual arguments Each arguments is optional with the defaults being 1 1 1 0 0 0 (1st January, 1 AD 00:00:00). Optional arguments are omitted by specifying a hyphen character '-', using empty "" or {} arguments [dateserial] may also be called with these items as a space-separated Tcl list, as produced by [date double -list] All arguments must be integer values. Values must be given in order but may be omitted with a '-' used as a placeholder Example: puts [dateserial - - - 00 05 36] puts [dateserial "" "" "" 00 05 36] puts [dateserial {} {} {} 00 05 36] puts [date [dateserial - - - 00 05 36]] Result: -693958.00388888887 -693958.00388888887 -693958.00388888887 0000/01/01 00:05:36 Example: puts [dateserial 1899 12 30 0 0 0] puts [date [dateserial 1899 12 30 0 0 0]] Result: 0.000000000000000 1899/12/30 00:00:00 Example: puts [date now] # Returns a double puts [date [date now] -list] # Returns date as list puts [dateserial [date [date now] -list]] # Returns a double puts [date [dateserial [date [date now] -list]]] # Returns full date Result: 42663.971261574072 2016 10 20 23 18 37 42663.971261574072 2016/10/20 23:18:37 Example: puts [fraction [dateserial - - - 2 4 6]] # Extracts .nnnn puts [time [fraction [dateserial - - - 2 4 6]]] # Extracts .nnnn Result: -0.086180555517785 02:04:06 See also: date, time, vbtime
date_to_ctime  Top  
date_to_ctime year ?month? ?day? ?hour? ?minute? ?second? Convert string-formatted date values into a C/Unix time value as a number of seconds since January 1st 1970 See also: ctime, time, date, dateserial, vbtime
Data Type Ranges  Top  
The following data type ranges may be coerced using data type casts The internal storage format for numbers is string. Calculations are performed on integers by converting to 64-bit values and real numbers by converting to 64-bit (8 byte) doubles Type casts may be forced using various cast commands (See: variable casting) char 8 bit signed -128 to 127 short 16 bit signed -32,768 to 32,767 long 32 bit signed -2,147,483,648 to 2,147,483,647 int 64 bit signed 9,223,372,036,854,775,808..9,223,372,036,854,775,807 int 64 bit unsigned 10 to 8,446,744,073,709,551,615 double 64 bit signed 1.7E +/- 308 (15 digits of precision) See also: variable casting, cast, numeric types, vbtime
Data Structures  Top  
Ticol offers the following data structures and ADTs integers as string double/floats as string binary values as string hexadecimal values as string big integers plugin strings natively lists as string stacks natively associative arrays natively binary lists plugin structs natively date/time natively dynamic memory blocks natively dictionaries unfinished xbase/dbase databases plugin sqlite databases plugin Variant array plugin Ticol does not offer classes objects/inheritance counted/binary strings (other than in a very limited way) See also: data types
debug  Top  
debug ?on|off|print? ?-quiet? Turn on/off debug tracing or view the current setting or print to the console. Internal debugging output applies only to debug build releases of Ticol See the /DEBUG command line argument. This is distinct from [debug print] The debug command with no parameters issues a verbose status unless -quiet is used. In all cases a boolean 1 or 0 is returned indicating debug status 'debug -quiet' can be used to programmatically detect debugging status and act accordingly if { [debug -quiet] } { debug off } [debug print] or [debug print string] is a command which prints to the console unless a ... #define ndebug
disabled in the script, regardless of where the #define occurs  Top  
Because this is an interpreter, not a compiler and because the MPP runs before runtime interpretation the '#define ndebug' statement can appear anywhere and will have an effect on the whole file If selective output is required then do not define 'ndebug', instead define a different macro variable and wrap statements in #ifdef Example: debug print "Hello from debug" Result: Hello from debug Example: debug print "This statement will not appear" #define ndebug debug.print "Nor will this" Result: <no output> Example: #define debug_print #ifdef debug_print debug print "I will appear" #else debug print "I won't appear" #endif Result: I will appear See also: trace, debugging, breakpoints, halt, time, debugging, commands
Useful Debug Routines  Top  
Two useful routines are offered to aid testing and debugging, [check] and [checkex]. [checkex] is an extended form of [check] which allows for more complex expressions in the test rather than just simple equivalence [assert] offers a built in alternative if {! [defined checkex] } { proc checkex {x expr} { upvar i upvar line set NAN "-1.[calc [chr 35]]IND00000000000" set q {$x} puts "Line $line: " -nonewline puts "'$q'=='$x': '$expr'" if { [eval $expr] } { # puts "Pass" } else { textcolor red puts "checkex assertion failed: '$q' -> '$x' at line $line" textcolor stop } } } if {! [defined check] } { proc check {x y} { if {!= $x $y} { puts "Error in test at after line $::line" puts "'$x' != '$y'" stop } } } Examples: check [calc "ceil(2.8)"] 3 checkex [comma 1234567890] {eq $x "1,234,567,890"} Results: line 3348: x:[3.000000000000000] == y:[3] Line 3348: '$x'=='1,234,567,890': 'eq $x "1,234,567,890"' See also: assert, faq, debugging
decrypt  Top  
decrypt string|var password Decrypt a string or variable from a base64 string which was encoded using [encrypt]. Decoding will result in a string size reduction Example: puts [encrypt "Hello world!" secret] Result: N4w8n7XnePSvob9G Example: decrypt [encrypt "Hello world!" secret] secret Result: Hello world! See also: encrypt, base64
default  Top  
See: proc for default proc arguments See: switch for default switch clause
defined  Top  
bool [defined command|function] Returns a boolean 1 or 0 indicating whether the given command or procedure is defined. The defined command is useful in allowing scripts to be re-run on a stop event without encountering a 'procedure already defined' error. Example: if {! [defined ipfromhost]} { proc ipfromhost {hostname} { return [calldllstr ping32 GetIPFromHostName $hostname] } } Example: puts [bool [defined foo]] puts [bool [defined puts]] Result: false See also: commands, is_set
dict (Dictionaries) (Incomplete feature)  Top  
Simplified Tcl dictionaries. Dictionaries are implemented as efficient hashtables Nested dictionaries are minimally-supported dict create var ?key value?... Create new dictionary, put reference in var dict get var key ?key...? Get a dictionary item(s) dict info Show dictionary information dict keys var Return a list of dictionary keys dict set var key ?key...? value Add/update a dictionary item by key value dict size Return the number of element pairs Example: dict create mydic 4470 "Great Northern" 4471 "Sir Frederic Banbury" dict set mydic 4472 "Flying Scotsman" dict set mydic 4473 "Solario" dict set mydic 4474 "Victor Wild" dict set mydic 4475 "Flying Fox" dict set mydic 4476 "Royal Lancer" dict set mydic 4477 "Gay Crusader" set l [dict keys mydic] foreach item $l { puts [format "%-10s\t%s" $item [string trim [dict get mydic $item] \ [chr 34]]] } See also: list
dict exists  Top  
bool [dict exists dictionaryValue key ?key ...?] [dict exists] returns a boolean value (1 or 0) indicating whether the key or series of keys within a set of nested dictionaries) exists in the given dictionary value. This returns a true (1) value if a [dict get] on that series will succeed. Example: dict set a the quick brown fox jumps over the lazy dog bool [dict exists $a the] bool [dict exists $a The] bool [dict exists $a the quick] bool [dict exists $a the quick brown fox jumps over the lazy] bool [dict exists $a the quick brown fox jumps over the lazy dog] Results true false true true false See also: dict
Windows Dialogs  Top  
The following Windows dialogs are available inputbox Accept user input, optionally with password masking getfileopen Browse for a file to open getfilesave Browse for a file to save msgbox Get user input or display a message from a popup dialog There is no Tk GUI support in Ticol, unless an external DLL is called or the Win32 API called via the calldll* plugin See also: inputbox, getfileopen, getfilesave, msgbox, gets
die  Top  
die ?message? ?-code return-code? A PHP-like command to exit the current program, optionally displaying a message or return code. If running in the CLI, control is returned to the CLI, otherwise the program will exit to the operating system. Example: die "Something went wrong" die "Exiting to system" -code 10 See also: exit, stop, at_exit, return
Differences between Ticol and Standard Tcl  Top  
Ticol is intended to be a subset of standard Tcl with a few differences The following aspects differ from ActiveState Tcl: $this Ticol offers $this in [this] $env $env (and other) consts are provided. $env has case- insensitive subscript reference arrays Variant arrays are available for use with calldll autoexec.tcl A startup, autoexec.tcl file is supported big math Big number integer support available as a plugin calc [calc] interacts with the Macro Preprocesor (MPP) which will transform [calc] commands to more-efficient raw Tcl. If the MPP is disabled then [calc] will be interpreted as [expr] calldll An external plugin lib which offers DLL interfacing similar to Visual BASIC, dotNet etc. commands Many additional commands which are implemented at binary level for speed. This includes some useful BASIC-like commands. To facilitate [calc] macro optimisation a command will accept a reduced calc expression as [number]. e.g. [10] console echo To make the CLI more useful, Ticol turns console echo off by default. This may be enabled using: option echo on Debugger A single-step debugger and stack trace do Ticol implements a do..while loop as well as [loop] encryption Source code obfuscation with various locking schemes are available in Ticol Tcl eval External scripts are linked and evaluated using [eval] expr Expressions can sometimes be handled differently, due to less tolerance in the Ticol expression handler e.g. Spaces required when evaluating strings in [expr] ActiveState Tcl: if {""==""} {puts PASS} Ticol Tcl: if {"" == ""} {puts PASS} Sometimes Ticol is more flexible: ActiveState Tcl: set op == if "$foo $op 1" {puts YES} # can't read "foo": no such var Ticol Tcl: option expression on set op == if "$foo $op 1" {puts YES} # Passes (echoes YES) global Global is an alias for upvar goto Limited-scope gotos (purely for entertainment purposes) lib External plugin modules (as DLLs) are loaded using [lib] The standard Tcl plugin method is different and incompatible loop A simple and efficient equivalent to [for] namespaces Real namespaces are not supported. They are emulated using name-scope prefixes such as 'fake_scope::var' Macros A full "C"-like Macro PreProcessor with load-time optimisation math All integer math is calculated using 64-bit integers Hex, octal and binary consts are handled transparently in math.:e.g. expr 0b1010*3 => 30, expr 0x0f*10 => 150 The new Tcl 9.x 0oNN octal format specifier is supported Math expressions are optimised by the Macro PreProcessor unless /NEO and /NES command line arguments are used memory Memory allocation and free for use with [calldll] option Certain functionality is controlled via the [option] command particularly, the 'option expression' option Performance Performance analysis graphing proc Ticol procs may not be integers or real numbers A proc name may, however, contain numeric digits ActiveState Tcl allows numeric values as proc names Procs defined with numeric prefixes can be called only directly using [call procname] Proc default args cannot contain math or other symbols unless wrapped in double-quotes. It is good practice to wrap strings within double-quotes in any case script encr Script encryption (obfuscation). Ticol scripts may be obfuscated using symmetric encryption and may also be execution-locked by various means speed Ticol Tcl is purely an interpreter. Even though the MPP will do some optimisation it will always be slower than ActiveState Tcl stacks Stacks are offered static Ticol offers static array and string variables for procs structs Ticol provides for binary struct emulation in order to interface with external DLLs time Optionally returns the current time as [time] Ticol also has an extensive [date] command uplevel The absolute level parameter is specified by a @ symbol not # as # is reserved by the MPP for comments upvar The absolute level parameter is specified by a @ symbol not # as # is reserved by the MPP for comments variants Some variant handling for interfacing with external DLLs variable [variable] is implemented an alias for [set] because Ticol does not support real namespaces xbase/dbase xbase database support as a plugin The Macro-PreProcessor (MPP) extends the standard Tcl comment character. This adds trailing comments but reserves the # symbol. The MPP s designed to optimise and speed up interpretive scripts but can be disabled using the /NP command argument (not recommended) Macro #__LINE__ , #__DATE__ and #__TIME__ debugging constants are available Macro PreProcessor #define, #ifdef, #ifndef, #undef controls Ticol has no Tk/GUI support unless you call an external dll via the calldll plugin to facilitate graphics output via the Windows API See also: ticol, gui, arrays, calc, calldll, do, encryption, global, goto, lib, math, option, struct, time, uplevel, upvar, variant
dim  Top  
dim arrayname size Dimensions an array according to size. The hash table is created and required memory is pre-allocated. No array elements are assigned and the element count is set to zero. See also [array create] A size value of 0 is acceptable [dim] is not necessary as array allocation is dynamic, but it may save time when allocating a very large number of elements within a loop as the array hash table is expanded dynamically and geometrically as elements are added This introduces a (diminishing) time cost overhead to critical loops Example: array create names 10 array walk names Results: ----------------------------------------------------------------- hash_table object:0x35ec650 size:10 ----------------------------------------------------------------- Hash Table Statistics: Root size:10 Occupation:0 (0.00%) Max depth:0 Nodes:0 ----------------------------------------------------------------- See also: array, arrays, array set
disktype  Top  
integer [disktype x:] Returns a numeric value indicating the disk type as follows: 0 DRIVE_UNKNOWN 1 DRIVE_NO_ROOT_DIR 2 DRIVE_REMOVABLE 3 DRIVE_FIXED 4 DRIVE_REMOTE 5 DRIVE_CDROM 6 DRIVE_RAMDISK Example: array set status { 0 "Unknown" 1 "No root directory" 2 "Removable" 3 "Fixed" 4 "Remote" 5 "CDROM" 6 "RAMDisk" } -const puts "[array item status [disktype c:] Unknown" Result: (where c: is a hard drive) Fixed Note that a trailing path is allowed. e.g. [disktype "c:\\temp"] See also: diskfree
dll_close  Top  
dll_close dllname handle Release a DLL previously opened by [dll_open]. Accepts either a literal or a variable. Returns a boolean success flag. Example: set handle [dll_open "vbsqlite3.dll"] dll_close handle Result: 1 See also: dll_open, calldll
dll_open  Top  
integer [dll_open dllname] Load a DLL into persistent memory. This may be necessary to process DLL calls where there is a need for a persistent handle such as SQLite queries Example: set handle [dll_open "vbsqlite3.dll"] Result: 13631488 See also: dll_close, calldll
incr, decr, ++, --  Top  
incr value|variable ?increment? decr value|variable ?increment? ++ value|variable ?increment? -- value|variable ?increment? Increases or decreases a value by 1 unless increment is specified. If specified the increment may be +ve or -ve and greater than 1 The optional increment argument may be any signed 64-bit integer Real numbers (1.2345) will be rounted to integer before applying the operator so: [++ -1.23] gives 0, and [++ 1.23] gives 2 Example: set line #__LINE__ ++ line 2 puts "Line is $line" Unary increment/decrement is not yet implemented within [expr]. Embed [++] or [--] command within the expression instead Example: set a 1;puts [expr "[++ $a]*2"] # Result 4 Example: set a 1;puts [expr "[++ $a 5]*2"] # Result 12 Where the incrementing operator is used in an expression as an infix operator it should be wrapped in parentheses if an increment value is given Example: set a 1;puts [expr "($a++ 10)*2"] # Result 22 See also: math, expr, eval
diskfree  Top  
integer [diskfree x:] Shows the free disk space for a given drive/path You can use comma to format the result Example: puts "[comma [diskfree d:]] byte(s)" Result: 135,071,793,152 byte(s) See also: disktype, file, comma
do while, do until (Flow Control)  Top  
do while {condition-statement} {code-block} do {code-block} while {condition-statement} do {code-block} {condition-statement} do until {condition-statement} {code-block} do {code-block} until {condition-statement} A flexible-syntax [do] loop The following additional commands interact with [do] break # Is passed back to any enclosing structure stop # Halt operation, return to the CLI if loaded exit # Exit the script and return to Windows goto # Where used with an enclosing [goto_block] continue # Resume execution at the head of the loop Ticol offers both standard Tcl while loops as well as do...while loops Well-formed single statements need not be braced but where braces are present and over more than one line the open brace must be at the end of the line not the start of a line (see flow control). Statements may be combined on a line using the semi-colon separator Examples: do {puts [rnd 1 10] } while 1 do {puts [rnd 1 10] } while { 1 } do {puts [rnd 1 10] } while { 1 } set i 0 do { # Correct brace layout (Tcl) puts "i is $i" if {$i == 2} { return } incr i } while { $i < 10} do while {1} {puts [rnd 1 10] } do {puts [rnd 1 10] } {1} set i 0 ; do {puts "i is $i"; if {== $i 2} { return } ; incr i } \ while { $i < 10} do while {[< $i 10]} { puts "do-while i is $i" ++ i } set i 0 do { puts "do {} i is $i" ++ i } {[< $i 10]} set i 0 do { puts "do-while i is $i" ++ i } while {[< $i 10]} See also: flow control, while, for, if, switch
$ dereference  Top  
$varname [set varname] Dereferences a variable to return the contents (see: double dereference) Very early versions of Tcl lacked the '$' syntax and, instead, used the [set] command to dereference variables. In some cases [set] may still be useful. Variable names may be braced as ${var} to isolate from strings Because braces delay evaluation, the use of braces to isolate variable names can be problematic, especially with nested sub-variables: e.g. ${name_$var}. Such cases will require the use of intermediate variables since translation would require the order of nested brace evaluation to be reversed for a $ operation. Nested, braced dereferences are allowed (e.g. ${var1${var2}} ) Unlike standard Tcl, Ticol supports multi-level dereferences ($$var) Note that you cannot dereference a struct member using $ or [set] as this merely returns the member offset address within the struct Example: set s 23 puts "a is '$s'" puts "a is '[set s]'" Result: s is 23 s is 23 Example: set a(1) 23 puts "a(1) is '$a(1)'" puts "a(1) is '[set a(1)]'" Result: a(1) is '23' a(1) is '23' Example: set a "Hello " puts ${a}world Result: Hello world Double-Dereferencing -------------------- Double/multiple level dereferences are allowed in Ticol Tcl using either nested [set] or multiple $ prefix statements. (See: double dereference) Examples: set a 23 set b a set c b set d c puts $$$$d # 4 levels of dereference puts [set $$$d] # 4 levels of dereference puts [set [set $$d]] # 4 levels of dereference puts [set [set [set $d]]] # 4 levels of dereference puts [set [set [set [set d]]]] # 4 levels of dereference Result: 23 23 23 23 23 See also: set, double dereference, nested dereference, variables, arrays
Double Quotes  Top  
In common with most programming languages, double quotes in Tcl are used to delineate and group words together into strings Braces may also be used to perform this task since braces can group characters into a single argument for a command Single-quote characters do not group and therefore cannot be used to group characters into a string argument Example: puts "Hello world" puts {Hello world} The empty string or empty list may be represented by pairs of double quotes or braces Example: set s "" set s {} Numeric hex or other literals for which it is desired that the MPP not translate into decimal should be quoted. This will affect the interaction with string comparison commands such as eq, ne. Numeric comparison commands will perform automatic decimal conversion Examples: set a 0xABCDEF set b "0xABCDEF" set c 0o12345 set d "0o12345" set e 0b1010101 set f "0b1010101" puts $a puts $b puts [int $b] puts $c puts $d puts [int $d] puts $e puts $f puts [int $f] Result: 11259375 0xABCDEF 11259375 5349 0o12345 5349 85 0b1010101 85 It is not allowed to embed unescaped double-quotes within a quoted-string even if quote parity is maintained. In standard Tcl this is an error Example: option echo on set q Hello"world" # This is actually two adjacent strings Result Hello"world # But the embedded quote is visible However, a workaround is to wrap the unescaped string in spaces or to escape the string and then use [unescape]. For example, when addressing an array with a subscript which has spaces... set q {a("with spaces")} vars q* assert $q {eq $_ {a("with spaces")}} -v assert $q {eq $_ [unescape "a(\"with spaces\")"]} -v See also: braces, single quotes, dereference
$$ double-dereference (multi-dereference)  Top  
$$var [set $var] Ticol allows for a non-standard double-dereference similar to PERL on simple variables and arrays elements. This avoids the need for clumsy [set] statements and is much faster, avoiding a slow command-call Multiple levels of double-dereferencing are supported e.g. $$$$var Deeply-nested levels can also be handled using [set] in the approved manner for example: [set [set [set [set $var]]]] but this is quite cumbersome Complex, braced variable expressions such as '${var}::name' are not supported by multiple dereferences. Instead use [set] to handle these (e.g. [set ${var}::name]) [set] can be combined with the use of one or more dollar $ dereferences Note that struct member fields must be dereferenced using [struct item] and not the dereference dollar prefix $ Example: set a 23 set myvar a puts "Double dereference using \$\$ is: '$$myvar'" puts "Double dereference using \[set\] is: '[set $myvar]'" Result: Double dereference using $$ is: '23' Double dereference using [set] is: '23' Example: set a 23; set b a; set c b; set d c puts $$$$d # x4 levels of dereference puts [set $$$d] # x4 levels of dereference puts [set [set $$d]] # x4 levels of dereference puts [set [set [set $d]]] # x4 levels of dereference puts [set [set [set [set d]]]] # x4 levels of dereference Result: 23 23 23 23 23 Example: set a(1) one set b a(1) set c(1) b set d c(1) puts "\$\$\$\$d resolves to '$$$$d'" puts "\$\$\$\$d resolves to '[set [set [set [set d]]]]'" Results: $$$$d resolves to 'one' $$$$d resolves to 'one' Complex array elements containing whitespace can be referenced using quoted-escaped strings and the [unescape] command as follows: Whilst variables can be declared which have complex whitespace, literal strings require escaping. Example: set a("with spaces") "Hello world!" # ^ Array definition (escapes not required) set b [unescape "a(\"with spaces\")"] # Escaped string # ^ Literal string (must be escaped) set c b puts "Triple dereference: '$$$c'" Result: Triple dereference: Hello world! Useful resources: http://phaseit.net/claird/comp.lang.tcl/tcl_deref.html See also: dereference, nested dereference, set, variables
Complex Nested Dereferences  Top  
Complex nested dereferences are supported for arrays and standard variables These may also be braced to isolate variable names from strings. This is an enhancement on standard Tcl Braces are resolved within variable expressions in the opposite order to braces within standard Tcl expressions. That is, they are evaluated recursively, from the innermost set of braces outwards. Where braces are used within a variable expression they must follow immediately after the dollar sign. Braces must wrap the whole variable expression. Examples: $s # A simple variable dereference $a(text) # Array with subscript literal value 'text' $a($ss) # Array with subscript variable '$ss' ${s}text # Variable 's' isolated from remainder of text ${${s}text} # Double dereference of 's' including 'text' ${a($ss)}text # Array 'a' with subscript '$ss', isolated from text abc${a(1)}def # Array 'a(1)' embedded within the string "abcdef" $a(${i}wo) # Where $i == 't', this references subscript 'two' $$$c # Treble dereference (c->b->a->result) $$${c} # Ditto (equivalent) $${${c}} # Ditto (equivalent) ${${${c}}} # Ditto (equivalent) ${$p$q$r} # Where p, q, r == v, a, r and var == "x" then "x" ${${p}${q}${r}} # Ditto (equivalent) ${q}(${i}wo) # Where q == a and i == t "a(two)" ${${q}(${i}wo)} # Where q == a and i == t and a(two) == "x" then x Invalid Expressions: ${q}(text) # Where q == a. For array 'a' will return "<array>text" # Should be ${${q}(text)} {$a(1)} # Will not resolve due to protective braces # Should be ${$a(1)} {$p$q$r} # Will not resolve due to protective braces # Should be ${$p$q$r} See also: dereference, double dereference
dump  Top  
Dump loaded source-code or known variables dump ?-echo? ?-crlf? # Display syntax-highlighted source code dump variable # Analyse a variable Dump with no arguments will display any preprocessed source code loaded within the CLI by either [run] or [load] as long as it is not encrypted. Code which has been encrypted (obfuscated) using ticol.exe /C cannot be listed Source code is highlighted using the following convention blue Inbuilt Tcl commands magenta Procs defined within the script yellow Strings (embedded commands not highlighted) green Dereferenced variables darkyellow Numeric values grey Variables, arguments and lib commands white Square, curved and curly braces - Comments are removed by the MPP You can return the source code as a single string to be captured by a Tcl variable by using the -echo argument. Unless the PreProcessor has been disabled the returned code will be preprocessed and will have had empty lines removed with comments and macro #ifdef..#else..#endif blocks stripped Line numbers will no longer match the original source-code but #__LINE__ tags will correctly reference the original source. Trailing whitespace is removed but indenting is preserved. See: load Example: load msgbox # Load msgbox.tcl to the CLI set a [dump -echo] puts $a Result: Loaded msgbox.tcl OK 105 byte(s) set r [msgbox [join [split $qbf " "] "\n" 768] "Choose" 36] msgbox "You chose [map {6 Yes 7 No} $r]" -- dump ?variable? dump with a variable name displays an analysis of a variable. When used with structs full member details will be shown, this includes the offset into the struct and the member (field) size in bytes struct 's' - at 9384672 (0x8f32e0), 146 byte(s), 5 member(s) + member 1: 's->s_a' => 0x8f32e0, 4 byte(s) + member 2: 's->s_b' => 0x8f32e4, 30 byte(s) + member 3: 's->s_c' => 0x8f3302, 100 byte(s) + member 4: 's->s_d' => 0x8f3366, 4 byte(s) + member 5: 's->s_e' => 0x8f336a, 8 byte(s) -------- ----------------------- ----------------------- -- ASCII ------- 008f32e0 48 65 6C 6C F0 FF 00 00 - 6F 00 33 32 31 41 42 43 Hell....o.321ABC 008f32f0 44 45 46 47 48 49 4A 4B - 4C 4D 4E 4F 50 51 52 53 DEFGHIJKLMNOPQRS 008f3300 54 55 54 68 65 20 71 75 - 69 63 6B 20 62 72 6F 77 TUThe quick brow 008f3310 6E 20 66 6F 78 20 6A 75 - 6D 70 73 20 6F 76 65 72 n fox jumps over 008f3320 20 74 68 65 20 6C 61 7A - 79 20 64 6F 67 00 00 00 the lazy dog... 008f3330 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 ................ dump, when used with upvar arrays or standard variables will also show the parent linked-list chain. This may be useful to understand how variables work array 'b' level 3 (0x200bde0) data @33603120 (0x200be30) 7 byte(s) (Array data not shown. Use array walk arrayname) Address 0 1 2 3 4 5 6 7 8 9 A B C D E F ASCII -------- ----------------------- ----------------------- ---------------- 020cbe30 3C 61 72 72 61 79 3E 00 20 27 00 78 69 74 20 6C <array>. '.xit l + Parents of 3::'b' (0x20cbde0 / 34389472): + Value: '<array>' | | Lvl::Variable Name This -> Parent Type Const | ------------------------------------------------------------------ + 2::b 0x020cbe40 -> 0x020cb890 array False + Value: '<array>' + 1::b 0x020cb890 -> 0x020c9540 array False + Value: '<array>' + 0::b 0x020c9540 -> 0x00000000 array False + Value: '<array>' See also: vars, struct, calldll, dumpvariant, array walk, load, run
dumpvariant  Top  
dumpvariant address Defined in lib plugin: ticol_variant Displays information relating to a variant object which has been returned from a calldll*variant operation. This operation requires a valid variant address Example: set v [vsplit $qbf] # Split to Variant (SAFEARRAY) array dumpvariant v varray unset v Result: DUMP: Variant 'v' at 36012656 (0x2258270) Type is 8204 (0x200c) BYVAL Variant is an array of type 0xc Type is 12 byte Variant VT_VARIANT See also: dump, walk, vars, varray get, array walk
Easter Egg  Top  
There are no easter eggs in Ticol. Such things would be impossible for man or machine See also: topic
Ticol Editor and Recommended IDE  Top  
Notepad++ is the recommended editor: https://notepad-plus-plus.org You can add the TCL syntax by copying the output of: puts [commands] Next, open Notepad++ and go to: Settings->Style Configuration->Tcl (from list) ->Instruction Word (from list) and then paste the list of functions into the "User defined keywords" area See also: Ticol, ticol.ini
echo  Top  
echo ?stdout|stderr? value Print a string without backslash escape translation other than performed by the Macro PreProcessor when the script is loaded. Echo is marginally more efficient than either [puts] or [printf] [echo] is equivalent to: puts [set value] except that a string value, not a variable is required as the only argument [echo] returns the untranslated string intact, and also does not append an additional carriage return/linefeed pair at the end. Use [newline] or puts "" after a call to [echo] if you wish to generate a new line Examples: echo $env(programfiles) puts [set env(programfiles)] puts $env(programfiles) Results: C:\Program Files (x86) C:\Program Files (x86) See also: puts, printf
elevate  Top  
elevate ?scriptname? Raise the current elevation level if running on Windows XP, 7 or higher You will be prompted for UAC if necessary. If the console or launching process is already elevated then the [elevate] command will be ignored [elevate] will elevate any pre-loaded script using [load] followed by [run] or will elevate scripts specified by the command line, together with their arguments. [elevate] can also be used to run a script in elevated mode from the Ticol CLI Prompts depend on the current UAC setting to determine wither or not user-interaction may be required to grant elevated permission. Ticol cannot override this, [elevate] returns a boolean indicating whether the session is/was elevated successfully To exit an elevated Ticol CLI with no active script: type exit and press ENTER Elevation will work differently between Windows XP and 7 and this also depends on the service pack level for Windows XP. To kill an elevated instance of Ticol you will need to run pskill.exe from an elevated command prompt Use [is_elevated] to test whether or not a script is elevated As the spawned, elevated instance of Ticol will close automatically on exit you may wish to use this snippet to prevent the script from closing option expression off if {is_elevated} { pause } Example: puts [elevate] Result: 1 Example: if( ! [is_elevated] } { elevate } else { puts "[escape [info script] is running elevated" # ... pause } Result: # If UAC is accepted then will display <path-to-script> is running elevated Example: load test # Contains [elevate] command as shown above run Result: # The script is run in elevated mode See also: is_elevated, is_admin, spawn, exec, shell
Executable-Only Code Obfuscation (ticol.exe filename /c)  Top  
Code obfuscation/encryption or code-protection is available. This encrypts a Ticol source file to prevent inspection and tampering. You should only run protected and unprotected Ticol scripts from a source you trust. This option can apply only to a single Ticol module. TCX files can be run either from the command-line or from the Ticol CLI console Where an output isn't given the input filename will be used with the filetype-suffix ".tcx". When running .tcx files the filetype must be given The code is obfuscated and randomised: 000000 2C 15 72 09 1F 46 1B 40 - 78 77 66 0C 0F 7F 7F 0A ,.r..F.@xwf..+ 000010 29 7A 3F 4E 62 6A 2A 33 - 7B 05 6E 0F 41 77 16 3A )z?Nbj*3{.n.Aw.: 000020 7C 2D 6E 13 68 6F 4C 15 - 7B 77 5F 40 58 28 13 7D |-n.hoL.{w_@X(.} 000030 29 21 47 60 72 22 76 71 - 1A 1E 75 2A 39 34 47 4A )!G`r"vq..u*94GJ Advantages: Scripts may be emailed or transmitted securely. The contents are tamper- proofed which means their safety can be verified if the source is known and trusted and if checked using MD5 signatures. Source code and IP is not divulged to third-parties. MD5 signatures should always be used to check Macro Preprocessing, other than processing backslash escape sequences is performed in advance. These are not processed as the MPP will be run a 2nd time on the TCX file and strings with resolved \n sequences would be invalid Advanced processing enables advance checking of basic syntax before runtime. Disadvantages: Encrypted scripts could hide malicious code if run from untrusted sources You should never run a tcx script from an untrusted source nor if the MD5 is not verified. Preferably reserve protected code for internal organisation use only. Treat protected Ticol scripts the same as unverified EXE files Use the sample MD5 check BAT file as a specimen for checking against a list of known scripts Note that the macro, "#exec" can cause scripts to be executed not only when scripts are run but when they are "compiled" using /C since the Macro PreProcessor will be invoke when compiling unless /NP is used You should only run (including obfuscate) scripts you trust Caveats on Code Protection: Although the encryption type can be divulged, protected scripts cannot be decrypted to the original source. This is by design. You MUST retain unencrypted copied of any encrypted source code When running in breakpoint/debug mode the individual commands are shown at each breakpoint but the script summary is unavailable for TCX files. Likewise, the commands [commands], [functions] and [procs] will reveal the names of loaded code but not the code itself As the command [info body] may be necessary for scripts to run it is not blocked and will reveal code snippets for procedures only, but the main code and its structure are not revealed Security Verification: Use an external MD5 checking application or Ticol's /MD5 argument to generate a checkable MD5 signature Example: ticol.exe /md5 test.tcx Result: AC6960741A575B1C0928EEE817D72272 See TESTMD5.BAT for a specimen script to check before executing Encryption Syntax: ticol.exe tclfile.tcl ?output-file? /C?:<option>? ?/PW:<password>? The command-line option /C takes the following arguments Case is ignored for all options other than /C:PASSWORD /C:PASSWORD Requires /PW:<password> to be successfully encrypted /PW Values are optional for the remainder and if omitted, Local workstation/user details, Tcl version will be used /C Automatic encryption. No run restrictions. Can be run on any workstation and by any user. Source cannot be viewed/edited /C:VERSION Encrypt to be run only with a specific version of Ticol /C:PASSWORD Uses a password specified using /PW:<password> Will not execute unless password is specified /C:MAC Encrypt on the basis of a MAC address which must be present on the executing system /C:IP Lock to the first current (active) IP address /C:USER Encrypt to be run only by a current Windows username /C:HOST Encrypt to be run only on a specific workstation name /C:WINVER Encrypt to be run only on a specific windows version (x.xx) Controlling WinVer execution is better done in real time /I Will display the encryption mode info for a protected file /MD5:<filename> Produce an MD5 string for any file. This may be used by an external script to verify a Ticol file which is about to be executed Operation Syntax: No special arguments are required to run a protected file except /C:password ticol.exe filename.tcx ticol.exe filename.tcx /pw:secret ticol.exe filename.tcx /i ticol.exe /md5:filename.tcx The encryption type is automatically detected. The only mode for which a password can be specified is that encrypted using /C:PASSWORD mode tcx files may be associated with ticol.exe to run as executable files. e.g. C:\>hello.tcx Hello World in such cases command-line arguments my not be passed properly Protection Examples: ticol.exe test.tcl /c # Obfuscated but no restrictions ticol.exe test.tcl /c:mac /pw:01020365A690 # Run only on MAC 01020365A690 ticol.exe test.tcl /c:user /pw:admin # Run only for Windows user admin ticol.exe test.tcl /c:host /pw:server1 # Run only on host PC server1 ticol.exe test.tcl /c:version /pw:1.23 # Run only on Ticol v1.23+ ticol.exe test.tcl /c:password /pw:secret # Run only with this password Result: Creates 'test.tcx' which can be run using the command: ticol.exe test.tcx The MD5 signature of the new file will be displayed if successful. This should be stored if necessary for use with script validation See also: run, load, Ticol, md5, md5_file
encrypt  Top  
string [encrypt string|var password] Encrypt a string or variable to a base64 string using moderate-strength symmetric encryption. Encoding will result in string size increase Encrypt must not be used to store highly-vulnerable information such as credit cards or bank details etc. For secure encryption call an external DLL or API which offers AES or similar asymmetric encryption If you require stronger encryption use [calldll*] to call an external library Example: puts [encrypt "Hello world!" secret] puts [decrypt [encrypt "Hello world!" secret] secret] Result N4w8n7XnePSvob9G Hello world! See also: decrypt, base64, mkn, cvn
enum  Top  
enum var|var = integer ?var|var = integer? ... enum {var|var = integer ?var|var = integer? ...} A simple implementation of enumerated integer constants. You cannot assign to an enum value. Enums will have scope at the level where they are defined Variables are simply assigned values in sequence starting at zero to guarantee they are unique. Names may not have already been assigned to a const or variable. Names must be unique Assignment is optionally permitted in any number format which resolves to a signed integer. The enum increment sequence will continue from that number for the next constant. The assignment operator '=' must be separated by white space [enum] avoids more convoluted methods of declaring a unique series of variables [enum] const values will typically be created in global scope and can be accessed from within procedures using the $::constname scope prefix Enumerated values cannot be assigned but they can be [unset] and re- declared. You must call as [unset varname -const] Example: enum zero one two three Result: integer three 3 integer two 2 integer one 1 integer zero 0 Example: enum zero one six = 6 seven Result: integer seven 7 integer six 6 integer one 1 integer zero 0 Example: enum {quick brown = 3 fox} Result: integer quick 0 integer brown 3 integer fox 4 Example: (For Windows MessageBox API) enum { MB_OK MB_OKCANCEL MB_ABORTRETRYIGNORE MB_YESNOCANCEL MB_YESNO MB_RETRYCANCEL MB_CANCELTRYCONTINUE MB_ICONSTOP = 0x10 MB_ICONERROR = 0x10 MB_ICONHAND = 0x10 MB_ICONQUESTION = 0x20 MB_ICONWARNING = 0x30 MB_ICONINFORMATION = 0x40 MB_ICONASTERISK = 0x40 MB_DEFBUTTON1 = 0 MB_DEFBUTTON2 = 0x100 MB_DEFBUTTON3 = 0x200 MB_DEFBUTTON4 = 0x300 MB_APPLMODAL = 0 MB_SYSTEMMODAL = 0x1000 MB_TASKMODAL = 0x2000 MB_HELP = 0x4000 } Example: enum zero one two unset zero -const unset one -const unset tw* -const -nocomplain See also: const, set, unset, vars, walk
error  Top  
error message ?info? ?returnCode? ?line? The [error] command may be used in conjunction with catch to display/set error strings message is an informative error message. info gives more information about the error. code is intended to be a numeric error code. Line is optional and non-standard and may report the line number by using the #__LINE__ macro together with a variable Example: option expression off proc Div {a b} { set line #__LINE__ if {== $b 0} { error "Error generated" "Info for error" 1 [- $line 1] } else { return [/ $a $b] } } Div 3 0 See also: catch, return
Ticol Errors  Top  
Some common Tcl/Ticol errors; Example: my_proc [[string left [getenv PROMPT] 4]] Result: eval: No such command or procedure '$P$G' Fix: Remove an outer layer of square brackets from an evaluation checkex [string left [getenv PROMPT] 4] Reason: The outer brackets will try to evaluate the string which is returned and it will be executed as a Ticol or Windows command See also: error, debugging
Error Values  Top  
Ticol error return values are as follows. These are returned by [catch] 0 Success 1 Error 2 return statement met 3 break statement met 4 continue statement met 5 exit statement met 6 stop statement met 7 goto statement met 8 value already defined See also: error, catch, return
eval  Top  
string [eval expression] eval filename.tcl|filename.tcx ?arg ...? Evaluate a Tcl expression, a Ticol tcl or obfuscated tcx script file For simple commands it is more efficient to call directly than via [eval] (e.g. [+ $x $y] [min $x $y] v's [eval "+ $x $y"] [eval "min $x $y]) Standard Tcl expressions are in 'prefix' format whereas expr expressions are in 'infix' format. If the filetype ".tcl" is included a script file will be searched-for. Unlike [run], [eval] requires that the ".tcl" extension must be given for Tcl scripts Note: [eval script] will perform a time-consuming Macro PreProcess on the script each time it loads. Do not load repeatedly in loops Example: puts [eval "> 10 2"] Result: true Example: eval hanoi.tcx 17 Result Loads, decrypts and executes hanoi.tcx setting argv(1) to 17 Tcl script files may be called/chained from a script by using eval, with execution returning to the original script. Note that variables for a chained script exist in the same namespace (true namespaces are not supported) so care should be taken to avoid clashes in variable names in the chained script. Arguments cannot be given [eval filename] will not reset the interpreter command count Example puts "Calling child script" eval child.tcl puts "Parent script is still here" Number formats understood by eval are as follows: decimal values NNNN hexadecimal prefixed by 0xNNNN octal prefixed by 0oNNNN binary prefixed by 0bNNNN Note that where a script which calls other TCL files is encrypted as a TCX file, this does not alter those TCL links to TCX format. If you wish to "chain" to TCX files you must write the script to call TCX versions of a file before encoding Note that chaining scripts may accumulate uncleared variables. A script should clean-up its own variables before exit if it is likely to be called by another script. (See: clear) See also: expr, bool, math, ticol, clear
Ticol Windows Event Log Handling Plugin  Top  
To load, use: lib ticol_event ?-verbose? ?-nocomplain? bool [event is_source name] bool [event add name ?0..4?] bool [event remove name] bool [event log name string type ?postscript?] [event] offers basic Windows event logging commands. [event add] requires Windows UAC elevation and adds an SZ_EXPAND registry event entry under: "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\%s" and this registers ticol_event.dll as the string table source for event messages. Only 4 basic message types are supported The following Macro defines are useful. Note that these can only be used outside quoted strings #define EVENTLOG_SUCCESS 0 #define EVENTLOG_ERROR_TYPE 1 #define EVENTLOG_WARNING_TYPE 2 #define EVENTLOG_INFORMATION_TYPE 4 Note ---- If an event source is removed then the Windows Event Log application will no longer be able to query the string table of the linked Ticol plugin DLL. You will see an error: The description for Event ID N from source XXXX cannot be found. The event source should be left registered as long as ticol_event.dll is installed on the system and you need to query related events Example: #define EVENTLOG_INFORMATION_TYPE 4 if {[is_elevated]} { if {event add ticol EVENTLOG_INFORMATION_TYPE} { puts "Added event" } else { puts "Failed to add event" } puts [bool [event is_source ticol] } Results: (If elevated) True See also: is_elevated, elevate, plugins
exec  Top  
exec program ?arg? ?arg...? @program ?arg? ?arg...? @ program ?arg? ?arg...? shell Run an external program from the Ticol shell. Ticol can be used as a Windows command shell. If autoexec is "on" then unrecognised commands will be shell-executed Prefixing a command with '@' can be useful to override conflicts with built-in commands. [shell] launches an instance of CMD.EXE. Type exit to exit and return to Ticol To grab the output text from a spawned application, see the [spawn] command CTRL+C is available for external applications, if quit using CTRL+C then execution will be returned to the Ticol CLI shell Examples: @type ticol.man # Call the Windows command shell exec dir *.tcl /s # Use [exec] to spawn the command ftp localhost # Call the program directly xcopy *.* \\server\share\folder # Call xcopy with arguments See also: autoexec, spawn, exit
Examples  Top  
Various example scripts are included with the standard Ticol distribution This includes a series of test files See also: Tcl, Ticol, faq
exit  Top  
exit ?value? Exits a Ticol Tcl program. If the program was launched from a Windows console then execution will return to the console. If launched from the Ticol CLI then execution will return to the CLI CTRL+C is disabled in Ticol. If you wish to quit the CLI prompt, either press CTRL+BREAK or type 'exit' at the CLI prompt See also: stop, at_exit, return
expr  Top  
string [expr expression items] string [expr {expression-group}] string [expr "expression-string"] string [expr arg arg...] Evaluates a mathematical expression held in a Tcl string or variable Expressions within 'expr' allow 'infix' format whereas native Tcl 'eval' commands are in 'prefix' notation as [operator var1 ?var2?], Individual [expr] arguments may be grouped by double-quotes or braces but are concatenated into a single argument Examples: option echo on expr 2*[+ 3 2] # Infix sub-command expr "2*[+ 3 2]" # Infix sub-command expr {2*[+ 3 2]} # Infix sub-command Result: 10 10 10 Expression operators include: + - * / & | ^ &= |= ^= > < >= <= == != == += -= *= /= %= >> << && || ** ? () Note that: ++ and -- are not supported other than as embedded [++] commands You may intermingle expression functions, procedures, bracketed commands, constants, variable names etc. within the expression string. Standard BEDMAS operator precedence applies unless curved parentheses are used to group A wide range of arithmetic functions are supported. See "functions" for more information. Curved brackets may be used to prioritise sub-expressions Parity checks are made on bracket pairing Number evaluation follows Tcl rules. All numbers are evaluated as integer unless a decimal point is specified. Division will therefore be truncated to integer unless a decimal point is given for the divisor Freeform expressions are also permitted but it is recommended that expression-strings are braced or enclosed in double-quotes Performance ----------- Because it is a generalised expression-handler with significant syntax- checking overheads and which calls the underlying Tcl routines, [expr] may be far slower than decomposing an expression into component operations with Tcl 'prefix' syntax. See [calc] for an optimised equivalent to [expr] Example: set src [expr ($x & $y) % 3] # Freeform expression syntax set src [expr {22/7.0}] # Braced expression syntax set src [expr "22/7.0"] # Quoted expression syntax set src [% [& $x $y] 3] # Decomposed commands (~50% faster) The Macro PreProcessor (MPP) may be used to optimise expressions into native Tcl commands (see [calc] which is a substitute command which will auto- optimise expressions into simpler Tcl commands) Embedded Commands ------------------ Tcl commands may be embedded within expressions. These will be evaluated first but do not affect overall operator precedence - e.g. Use: puts [expr 22/7.0+[incr 2]] -> 6.142857142857142 Not: puts [expr 22/7.0+incr 2] Use: puts [expr [incr 10]] Not: puts [expr "incr 10"] Whitespace ---------- Whitespace is handled between bracketed expression calls but the expression should ideally be wrapped in double quotes or curly braces to ensure safe grouping Examples: expr 22 / 7.0 expr 22/7.0 expr "22/7.0" Returns: 3.142857 Whitespace is permitted it is recommended that it is avoided Number Formats -------------- The following 64-bit encoded number formats are understood by [expr]: decimal any base 10 number 12345 hexadecimal prefixed by 0xNNNN 0x3039 octal prefixed by 0oNNNN 0o30071 binary prefixed by 0bNNNN 0b11000000111001 Transiting Array Brackets ------------------------- An [expr] statement does not transit expression array () brackets. While array indices may contain expressions those expressions are not resolved unless they are in Tcl "command" format e.g. [* 2 3] or if the [expr] command is used Thus: [expr $a(22/7*2)] would be one of: [expr $a([expr (22/7)*2])] [expr $a([* [22/7] 2])] Note that [calc] will attempt to resolve all sub-expressions, including array parentheses expressions Incorrect Use ------------- Tcl commands which are not part of the [expr] syntax cannot be embedded without square brackets. Commands [++] and [--] are not allowed as these conflict with arithmetic addition/subtraction followed by sign value Example: set a 1;puts [expr "set b; ++ $a"] # ; separators are not valid set a 1;set b [expr "[++ $a]"]; puts '$b' # Valid See also: calc, eval, bool, functions, math, arrays, inttohex, inttooct, inttobin
fib (Fibonacci)  Top  
integer [fib n] Compute Fibonacci series value from 0 to 93 Accessing a value over 93 will return an overflow error [fib] uses a rapid, iterative method of calculation internally Example: option expression on for {set j 0} {$j < 81} {incr j} {puts "$j [fib $j]"} Result: 0 0 1 1 2 1 3 2 4 3 5 5 6 8 7 13 8 21 9 34 10 55 11 89 12 144 13 233 14 377 . . . See also: math, big
file  Top  
Enhanced Tcl 'file' command Offers a variety of stream-based file manipulation commands as well as O/S-like commands. These are similar to those offered by the "C" language Many of the sub-commands can be used independently without the 'file' prefix file attributes filename Return a Tcl list of common attributes file close fp Close an open file file delete filename Delete a file (alias for unlink) file dirname name Return the directory name of a filename/path file eof fp Tests file-read for end of file condition file executable filename Tests if a file is executable, return 1 or 0 file exists filename Test if a file exists file extension filename Get the filename-extension file flush fp Flush file output to a stream file gets fp ?var? ?bytes? Read a line of text data from an open file Returns string or count of bytes if var given file isdirectory filename Test if filename is a directory file isfile filename Test if filename is a file file md5 filename Generate an MD5 value for a file file mkdir filename Create a directory file name filename Return the filename+ext only (non standard) "C:\path\to\my.txt" gives "my.txt" file normalize filename Get the full, normalised path of a filename e.g. win.ini in c:\windows\system32 gives c:\windows\system32\win.ini file open filename Open a file for reading or writing Returns a file handle file readable filename Check a file for read access and return 1 or 0 file rename oldname newname Rename a file file rewind fp Rewind the file pointer of an open-file file runtype filename ?-v? Tests executable run type Returns code: Optional -v verbose flag -1 unknown Unknown type/non-executable 0 32bit 32-bit Windows exe 1 dos DOS executable 2 wow Windows on Windows64 exe (wow) 3 pif PIF file 4 posix Posix binary 5 os216 OS/2 16-bit exe 6 64bit 64-bit Windows exe file seek fp offset Set/place the file pointer of an open-file file size filename Get the size of a filename (64-bit) file split filename Split a path into components in Tcl list format {drive: path filename} file stat filename var Retrieve 'stat' data. See: file stat file tell fp Get the file-pointer location of an open-file file type filename Return one of file, directory, link or unknown file unlink filename Delete a file (alias for delete) file volumes Return a Tcl list of valid volumes file writeable filename Check file or dir for write access. Return bool Examples: -------- All examples are with: option echo on Example: file attributes autoexec.tcl Result: -archive 1 -hidden 0 -system 0 -readonly 0 -longname autoexec.tcl \ -shortname {} Example: file readable autoexec.tcl Result: 1 Example: file type autoexec.tcl Result: file Example: file volumes Result: C:/ D:/ E:/ F:/ G:/ I:/ J:/ See also: info, exists, filesize, mkdir, unlink, dir, input, normal_path, unc paths
file exists  Top  
bool [file exists filename] Check if a file exists or not Example: puts [file exists ticol.exe] Result: 1 See also: file
file stat  Top  
bool [file stat filename arrayvar] Fills an array with _stat information using the C++ '_stat()' function The array variable referenced in the argument must not exist. A boolean True (1) is returned if the file exists, False (0) if it doesn't Example: file stat ticol.exe a array foreach a val ss { puts "\$a($ss)\t$val" } Results: $a(mode) 33279 # Protection $a(ino) 0 # inode number (always 0) $a(dev) 2 # ID of device containing file (A==0) $a(atime) 1481501018 # C time of last access $a(mtime) 1481501108 # C time of last modification $a(gid) 0 # Group ID of owner (always 0) $a(size) 190976 # Total size, in bytes $a(nlink) 1 # Number of links (always 1) $a(rdev) 2l # device ID (if special file) $a(ctime) 1481501018 # time of last status change $a(drive) C # Drive letter of 'dev' (upper case) $a(uid) 0 # User ID of owner (always 0) References: https://msdn.microsoft.com/en-us/library/14h5k7ff.aspx https://stackoverflow.com/questions/6094665/how-does-stat-under-windows-exactly-works See also: file
file gets  Top  
string [file gets fp ?var? ?bytes?] Read a line of text data from an open file Returns a string value if no variable specified, else returns the count of bytes successfully read if a var argument was given. If an EOL byte sequence is encountered before 'bytes' have been read then a short count will be returned. If 'var' does not exist it will be created in the current scope [file gets var] will always clear var to {} if it exists Example: set fp [file open [unescape $argv(1)]] set r [file gets $fp s 100] puts "s is '$s" file close $fp Result: <Text from input file up to 100 chars or first CRLF sequence> See also: readfile, file
filesize  Top  
integer [filesize filename] Returns the size of a given file in bytes as a 64-bit value See also: file, unlink
find (Help)  Top  
find string find "string with spaces" Search the Ticol manual for topics which contain a given search string Since the PreProcessor processes all command-line commands including 'help' and 'find' this will affect the ability to search for the character #. If enabled this will be interpreted as a comment and ignored. See: help option PreProcessor Example: user@host> find upvar Result: Help topics containing keyword 'upvar' arrays subsequent upvar command. To pass an array by value at_exit The upvar command is required to access variables d combinatory logic upvar 1 $_stack stack comparing ticol with php Standard (downwards) variable inheritance No (upva const declared using upvar to create a local const instan contents upvar Reference a variable in a higher differences global Global is an alias for upvar dump dump, when used with upvar arrays or standard varia find user@host> find upvar See also: help
for (Flow Control)  Top  
Provides a for iterator similar to that of C/C++ With: option expression on (Standard Tcl): Default: for {init-eval} {condition-expr} {post-eval} {eval-code} With INI ForInitAllowsExpression=TRUE for {init-expr} {condition-expr} {post-eval} {eval-code} for {[init-eval]} {condition-expr} {post-eval} {eval-code} This uses an [expr] statement as the 3rd (condition) argument and if configured, can optionally use an [expr] statement for the 2nd (init) argument With: option expression off (Non-standard): for {init-eval} {condition-eval} {post-eval} {eval-code} This uses an [eval] statement for the 3rd (condition) argument The following additional commands are available for use with [for] return # Will exit the script when used in root-level [if] break # Will be passed back to any enclosing structure stop # Halt operation, return to the CLI if loaded exit # Exit the script and return to Windows goto # Where used with an enclosing [goto_block] continue # Resume execution at the head of the [for] loop Flow-control for loop Example with single loop variable option expression off for {set i 0} {< $i 10} {incr i} { puts "i is $i" ++ j } option expression on for {[set i 0]} {$i < 10} {incr i} { puts "i is $i" ++ j } Example - Handling multiple loop variables: option expression on for {[set i 0]; [set j 0]} {($i < 10) && ($j < 10)} {incr i; incr j} { puts "i is $i, j is $j" ++ j } option expression on for {[set i 0; set j 0]} {$i < 6} { ++ i; ++ j 2} { puts "i=$i; j=$j" } option expression off for {[set i 0]; [set j 0]} {[expr ($i < 10) && ($j < 10)]} {[incr i]; \ [incr j]} { puts "i is $i, j is $j" ++ j } See also: loop, while, do, flow control
Flow-control: for foreach array_foreach, if elseif else, switch while do  Top  
The following construct flow-control constructs are supported: array foreach carray foreach catch do for foreach if linkedlist foreach loop stack foreach switch time try/catch while Details ------- array_foreach array element ?subscript? {code-body} carray foreach handle lvalue ?rvalue? {code-body} catch {code-body} do {code-body} while {...} for {initiator} {condition-test} {post-action} {code-body} foreach variable list {code-body} foreach varlist1 list1 ?varlistN listN ...? {code-body} if {condition-test} else {...} if {condition-test} elseif {...} ... else {...} linkedlist foreach handle lvalue ?rvalue? {code-body} loop variable start limit ?increment? {code-body} stack foreach varName indexVar {code-body} ?-r? switch ?options? {arg} {{case script} ... | {default script}} time ?expression? ?iterations? ?-info | -quiet? try {code-body} catch {code-body} while {condition-test} {code-body} Additionally: the following keywords are available: break # Exit the loop continue # Continue execution from the loop head default # (For use with [switch] only) die # Exit to windows with message exit # Halt processing and exit to Windows goto # Only valid within a [goto_block] return # Return from the loop with optional code etc. stop # Halt processing and return to the CLI Behaviour is modified by: option expression on|off if/else/elseif keywords must be separated by whitespace. The Tcl syntax requires that the opening brace following if, else, elseif, be on the same line as the command. e.g. (See: brace style) if { condition } { # Correct layout (K&R/Tcl) statement } elseif { condition } { statement } else { statement } if { condition } # Incorrect layout (Allman/BSD) { statement } else if { condition } { statement } else { statement } while { condition } { # Correct layout (Tcl) statement } while condition { statement } # Correct layout (Tcl) do { # Correct layout (Tcl) statement } ?while? {condition} do {statement} {condition} # Correct layout (Tcl) set i 0 do { # Correct layout (Tcl) puts "i is $i" if {== $i 2} { return } incr i } while { $i < 10} while 1 {puts [rnd 1 10] } do {puts [rnd 1 10] } while 1 All of the above cases support the break or continue keywords break exits the block loop structure such as while, for, foreach continue jumps to the start of any block structure and repeats Return values set using 'return' can be passed from while or do-while by chaining from 'set' - e.g. set r [do { ... if { $i == 2 } {return string} set r [while { ... if { $i == 2 } {return string} If 'option expression' is set to ON then expr with infix notation will be used for tests instead of the default of eval with prefix notation A limited-scope form of goto is supported within a goto_block (see goto_block) See also: for, foreach, array_foreach, if, elseif, else, switch, while, do, loop See also: option expression, foreach, array foreach, if, proc, return, at_exit, linkedlist, carray, stack, loop, try, catch
break  Top  
break Halt execution within a flow-control block such as [for], [while], [do] or [goto_block] If executed outside a flow control block and at level 0 (root) [break] will exit the current script and have the same effect as [exit] [break] is not valid within other flow-control structures Example: option expression off for {set i 0} {< $i 10} {incr i} { if {== $i 5} {break} } Example: break Result # Script exits See also: flow control, continue, stop, exit, return
continue  Top  
continue Continue execution of a loop structure from the head of the loop [continue] skips any body code and executes the increment argument of a [for] loop. Relevant to [for] [foreach] [while] [do] Example: # print a line for each of the integers from 0 to 10 except 5: option expression on for {set x 0} {$x < 10} {incr x} { if {$x == 5} { continue } puts "x is $x" } Result: x is 0 x is 1 x is 2 x is 3 x is 4 x is 6 x is 7 x is 8 x is 9 Example: option expression off set sum 0 set x 0 while {< $x 10} { incr x # Pre-increment before [continue] if {== $x 5} { continue } puts "x is $x" += sum $x } Result: x is 1 x is 2 x is 3 x is 4 x is 6 x is 7 x is 8 x is 9 x is 10 See also: flow control, break, stop, exit, return
Handling filenames and paths  Top  
Ticol handles both / and \ path separators in filenames. Within complex strings and expressions it may be preferable to use / as this does not need to be escaped and avoids problems with 'double unescaping' Literal strings mut have the \ character 'escaped' as \\ Example: set filename "c:/path/to/file.txt" # Correct set filename "c:\\path\\to\\file.txt" # Correct set filename "c:\path\to\file.txt" # Incorrect (\t is a TAB) Command Line Use ---------------- When using filenames from the CLI this behaviour is modified to allow unescaped paths. See: option escape for more information See also: escape sequences, escape, unescape, option escape
fpart  Top  
integer [fpart double-value ?precision?] Return the fractional part of a double value as an integer The precision part must be >= 1 and <= 10 [fpart] preserves any zeroes after the decimal, stripping the sign, leading zero (if any) before the decimal point and the decimal point itself Example: puts [fpart $pi] puts [fpart $pi 2] puts [fpart $pi 6] Results: 1415926535 14 141592 Example: puts [fpart 0.12] Result: 1200000000 Example: # Splitting a double value for processing with reassembly puts "[integral $pi].[fpart $pi 7]" # Recommended puts "[integral $pi].[fraction $pi]" # Bad idea! Result: 3.1415926 3.0.141592653589793 Example: puts [fpart [dateserial - - - 2 4 6]] puts [time .[fpart [dateserial - - - 2 4 6]]] Results: 0861805555 02:04:06 See also: fraction, integral
fraction and integral  Top  
double [fraction realValue] double [integral realValue] Returns either the fractional or integer part of a real number (float) Example: fraction [expr atan(1)*4] Result: 0.141593 Example: integral [expr atan(1)*4] Result: 3.00000 Note: Use [fpart] to retrieve the decimal fraction as an integer value See also: fpart, math
Ticol Introspection and Reflection  Top  
Ticol has modest commands for type reflection and introspection, as follows: array walk # Dump a variable's contents cmdcount # Count of the # of executed commands dump # Dump details of a standard variable or struct dump # Show syntax-highlighted source code dumpvariant # Dump the contents of a variant info # Various introspective commands mem_used # Returns the current memory used by Ticol trace # Display calls and shows results type # Display variable type names walk # Dump the variable table at any callframe level watch # Set a variable watch for use with breakpoints /echo # Show Macro PreProcessed source code /bp # Breakpoint execution stacktrace /g # Performance graph Variables also exist which reveal information about the system These can be inspected using the command [vars -const] string exe_name string tcl_date integer tcl_cli integer tcl_threaded float tcl_version integer tcl_precision array env empty argv0 integer argc See also: debugging
doevents  Top  
doevents ?count? ?-sleep? This is analogous to Visual BASIC's DoEvents command. [doevents] yields thread control to Windows and allows processing of the Windows message queue. doevents may be combined with sleep to minimise CPU use during tight loops. [doevents] will poll the Windows message queue An optional count argument may be added which will cause [doevents] to poll a given number of times. Additionally, a 'sleep' of 10ms may be performed during each loop. You can use [sleep 0] to achieve a similar effect Example: set i 0 while {$i < 1000000 } { # A tight, CPU-intensive loop doevents incr i sleep 0 } See also: sleep
flush  Top  
flush ?stream? Flushes output to an open file stream. This may include the symbolic strings stdout and stderr as well as open file handles See also: open, close, file
foreach (Flow Control)  Top  
foreach varlist list body foreach var|{var...} list|{vars...} {body} If a list of items is given then it should not be wrapped in braces to ensure grouping. If a braced list of vars is given then don't enclose in quotes The opening brace of the body statement should be on the same line as foreach. See the rules about grouping in Tcl in the Tcl documentation If a break statement is encountered before the list is exhausted, the tail of the list will be returned. foreach f [ls "c:\\windows\\*.*" -af -list] { puts "File: $f" foreach {f g} {one {two three} four five six {seven eight} nine ten} { puts "Items f g: $f, $g" } ls *.* a -la -list foreach {i j k l} $a { puts "$i, $j, $k, $l" } foreach f {one two three} { puts "$f,"} set args {one two three four} set arg [foreach {a b c} $args break] foreach s [commands] { puts $s } When using with arrays take care to wrap multiple variable arguments in braces WRONG: foreach x y [array get env] {puts $x=$y} RIGHT: foreach {x y} [array get env] {puts $x=$y} foreach may also be used to split lists into variables using an empty body set s "123 456" foreach {p q} $s {} Admin@Lenovo 134> vars Defined variables at level 0 ---------------------------------------- integer p 123 integer q 456 See also: for, while, switch, array_foreach, list, ls, ticol
format  Top  
string [format format-string|literal ?arg? ...] Standard Tcl format command. The syntax is similar to the C printf command. format prints no output. You must call puts or printf to display the result. Note that format and printf do not automatically issue a newline character Examples: format %x 123456 puts [format "%.10f" [/ $euler $pi]] puts [format "%.0i" [expr 1/20.0*100]]% Results: 1e240 0.8652559794 5 format and printf both include 64-bit number formatting as %I64i and %I64u (case-sensitive). Overflows occur at about 19 digits. Format field numeric specifiers may be passed using a * token Example: (interprets as '%-20.2s') Result: printf "'%-*.*s'\n" 20 2 Hello => 'He ' See also: format string, set, puts, printf, comma
Format String (printf and format)  Top  
The [format] and [printf] commands generate a formatted string in a fashion similar to the ANSI C sprintf function. A format string indicates how to format the result, using % conversion specifiers as in C sprintf, and the additional arguments, if any, provide values to be substituted into the result. The return value from format is a formatted string The following formatting tokens may be used with [format] and [printf] Positional Specifier -------------------- In standard Tcl the first position is an optional positional specifier This is unsupported in Ticol Tcl Optional Flags -------------- The section portion of a format string consists of an optional flag character - Left-justify the converted argument + Print number with a sign, even if positive. space A space should be added to the beginning of the number if the first character is not a sign 0 Specifies that the number should be padded on the left with zeroes instead of spaces Optional Field Width -------------------- The third portion of a conversion specifier is a decimal number giving a minimum field width for this conversion. It is typically used to make columns line up in tabular printouts. If the converted argument contains fewer characters than the minimum field width then it will be padded so that it is as wide as the minimum field width. Padding normally occurs by adding extra spaces on the left of the converted argument, but the 0 and - flags may be used to specify padding with zeroes on the left or with spaces on the right, respectively. If the minimum field width is specified as * rather than a number, then the next argument to the format command determines the minimum field width; it must be an integer value printf "'%*s'\n" 20 Hello => ' Hello' printf "'%-*s'\n" 20 Hello => 'Hello ' Optional Precision Specifier ---------------------------- The fourth portion of a conversion specifier is a precision, which consists of a period followed by a number If the precision is specified with * rather than a number then the next argument to the format command determines the precision; it must be a numeric string. Example: (interpreted as '%-20.2s') printf "'%-*.*s'\n" 20 2 Hello => 'He ' Optional Size Modifier ---------------------- The fifth part of a conversion specifier is a size modifier, which must be ll, h, or l. If it is ll or I64 then the value will be cast to 'wide' format lli 64-bit signed integer llu 64-bit unsigned integer I64i 64-bit signed integer I64u 64-bit unsigned integer Mandatory Conversion Types -------------------------- The sixth part of a format string is a mandatory conversion type specifier d Decimal u Unsigned integer i Signed integer o Octal x or X Hexadecimal (lower, upper case) b Binary integer c Character type (Non-Tcl standard. Tcl converts to Unicode) s String f Floating point/double e or E Scientific notation g or G General format % Literal % symbol (%%) Differences from ANSI printf ---------------------------- p Unsupported Differences from Standard Tcl ----------------------------- %N$ Prefix unsupported See also: format, printf, puts
Ticol Memory Allocation and Garbage-Collection  Top  
Ticol allocates and frees memory for variables automatically. There is no need to perform any 'garbage collection' operations Exceptions would be memory returned by external DLL calls or assigned by [malloc] for an external DLL call. These should be carefully managed Uncontrolled recursion can cause a 'stack overflow' memory error where the application will generate a fatal exception error. Recursive procedures should be carefully-designed to avoid such situations arising See also: set, proc, malloc, free
get_win_error  Top  
integer [get_win_error] Retrieve the last registered Windows error. This should be retrieved as soon as possible before a new event resets the error value to zero Use [win_error] to format the error message See also: win_error
glob  Top  
Glob is a term which refers to wildcard string matching in the following array get array names lsearch string match switch unset vars See also: help
getkey  Top  
string [getkey ?-integer? ?-lower? ?-upper?] Wait for a keypress and return the character. If the -integer argument is given then an integer value representing the key input is returned Upper or lower case can be forced using -lower or -upper Note that PC extended key handling for keys such as F1 will return a sequence of two integer values. For more information, Google PC keyboard handling Use [inkey] to handle keyboard polling loops See also: inkey, gets
getsid  Top  
integer [getsid <username>] integer [getsid <domain\\username>] Retrieve a Windows SID string for a given username. The domain prefix is optional. If omitted the current workstation/workgroup will be used Example: puts [getsid administrator] puts [getsid snoopy\\administrator] puts [getsid [username]] Result: S-1-5-21-460261754-543217201-1416368962-500 S-1-5-21-460261754-543217201-1416368962-500 S-1-5-21-460261754-123456789-9876543210-500 See also: pid, tid, username
global  Top  
global varName ?varName? ... ?-value value? Link to an existing variable in global scope or, if this does not exist, create a new, simple variable (non struct/array) in global scope with an alias of the same name in the local scope [global] is valid only within procedures This is used within procedures to create a global in the root (::global) namespace and a local (upvar) copy of the same variable. The value argument is optional and if omitted the new variable will be set to empty "" When the local copy of the global variable is updated the global copy will also be updated. The local copy is destroyed on exit of the procedure but the global copy will remain with values set by the procedure Ticol global differs from standard Tcl in supporting a 'value' argument in preference to multiple variables. This is because the need to use global with multiple variables is less likely than the need to set a variable in the var Example: proc create_global {} { # Create a global var with local upvar copy, set it then change it puts "Calling \[global global_var -value 12345\]" # Creates var in global scope global global_var -value 12345 puts "Local: \[bool \[is_set global_var\]\]=\ [bool [is_set global_var]]" puts "Global:\[bool \[is_set ::global_var\]\]=\ [bool [is_set ::global_var]]" puts "Check: \$::global_var=$::global_var" # Update the local copy set global_var 11111 # Then check the global copy puts "Recheck:\$::global_var=$::global_var" } create_global vars gl* Result: Calling [global global_var -value 12345] Local: [bool [is_set global_var]]=true Global:[bool [is_set ::global_var]]=true Check: $::global_var=12345 Recheck:$::global_var=11111 Defined variables matching 'gl' at level 0 ------------------------------------------ integer global_var 11111 See also: global variables, preset globals
Global Variables  Top  
Variables in global scope, including arrays, may be accessed by the global scope prefix '::'. This must appear immediately after any dollar sign, e.g. $::globalVar Global constants, when accessed within procedures, must be either referred to using $:: or declared using upvar which will create a local const instance See: preset globals - for a discussion of pre-set Ticol global variables Nested scope levels exist within procedures. This is referred to as the given 'level'. This value increases from 0 at the top (global) level to higher values as procedure call-frames are added. Variable scope within flow-control structures is the same as at the current procedure level Example: proc getvar {} { set a "I am here" puts "proc local a is: '$a'" puts "proc global a is: '$::a'" puts "proc const b is $::b" } set a "Hello" const b 1234 puts "a in global scope is $::a" getvar Result: a in global scope is Hello proc local a is: 'I am here' proc global a is: 'Hello' proc const b is 1234 Example of declaring a global variable and setting as an array/element set a "" proc set_global_array {} { # Set (cast) global non-array variable as array with one element set ::a(1) "One" } set_global_array # Call the proc puts "\$a(1) set by proc is '$a(1)'" # Print the results Result: $a(1) set by proc is 'One' See also: preset globals, global, set, let
goto_block, goto  Top  
goto_block, goto goto_block { goto label label {statement} } [goto] is implemented purely for the amusement of the author [goto] statements are valid only within a [goto_block] statement A [goto_block] is a set of label and braced statement pairs. If the statement consists of only one command there is no need for braces. Labels may be any string including keywords A [goto_block] is executed immediately if encountered with execution starting at the first valid dlabel The [break] command will exit a [goto_block] Each entry within a [goto_block] must consist of a line-number followed by a code block. The code block must be wrapped in braces if there is more than one command present. The line numbers need not appear in any particular sequence. Labels need not be numeric and can be any valid string Empty statement parentheses are not allowed, use a {;} as a placeholder for an empty statement Any required block initialisation code for the goto block MUST appear within a dummy [goto] entry Statements are executed sequentially until a [goto] statement is encountered or after one or more goto statements has been executed [goto_blocks] may be nested If a [break] statement is encountered this will cause the [goto_block] to exit. A [goto_block] cannot be exited using return, other than using [return -code break] Example: goto_block { 10 { puts "Going to 30" goto 30 } 20 { puts "Going to end" goto end } 30 { puts "Going to 20" goto 20 } end { puts "Exiting" } } Example: set a 1; goto_block { 10 {;} 11 {;} 12 {puts $a} 12 {incr a; goto 10} } Example: goto_block { # goto_block used to comment out a block of code goto end puts "This statement won't be executed" end } A BASIC-like ON GOTO can be simulated using the following. This behaves the same as C++ switch() goto_block { init { # Initialisation must be within a dummy block set var [rnd 1 3] goto $var # Jump to a [goto] entry } 1 { puts "One" break; } 2 { puts "Two" break; } 3 { puts "Three" break; } } Braces are required for the rvalue of each goto sub-block when more than one command is present and items are separated by whitespace. The following [goto_block] will jump to the selected label similar to ON GOTO and will then execute all subsequent blocks below Example: proc one {} { puts "One" } proc two {} { puts "Two" } proc three {} { puts "Three" } proc four {} { puts "Four" } goto_block { init { # Initialisation is in a dummy block set var [rnd 1 4] goto $var # Jump to a [goto] entry } 1 one 2 two 3 three 4 four } Example: option expression off set s 0 goto_block { start { ++ s if {> $s 9} { goto end } goto start } end { textcolor magenta puts "Puts exited OK at label: end" textcolor } } Example: Flip-flops are memory-stable and can be run infinitely set sleep_delay 2000 goto_block { 10 {puts "in 10";sleep $sleep_delay;goto 20} 20 {puts "in 20";sleep $sleep_delay;goto 10} } See also: do, while, for, foreach, flow control
index  Top  
string [index string N] Rapid indexing of strings to return a single character. [index] uses base 0 indexing values where 0 represents the first character of a string. Out of bounds index values will return the null string {} Example: puts -[index $qbf 0]- puts -[index $qbf 1]- puts -[index $qbf 2]- puts -[index $qbf 42]- Result -T- -h- -e- -g- See also: strstr, instr, string
if..elseif..else (Flow Control)  Top  
if {statement} then {statement} else {statement} The if statement controls conditional branching The body of an if statement is executed if the value of the expression is evaluated as nonzero. The number of elseif statements is unlimited but execution will slow down as more cases are added The opening brace for the statement following if or else MUST be on the same line as the if or else verb. The standard Tcl keyword "then" is not supported in order to speed-up execution The Tcl [then] keyword is not supported by Ticol Condition may be an expression, numeric literal or eval return For and/or compound syntax see and, or if {condition} { statements... } if {condition} { statements... } elseif { condition } { statements... } else { statements... } The following additional commands are available for use with [if-elseif-else] return # Will exit the script when used in root-level [if] break # Will be passed back to any enclosing structure stop # Halt operation, return to the CLI if loaded exit # Exit the script and return to Windows goto # Where used with an enclosing [goto_block] Expression v's Eval Flow control structures use the settings of 'option expression' to decide whether to test statements using [expr] or [eval]. When using expression on bear in mind that the argument must be a valid math expression and NOT a command If 'option expression' is ON then you MUST use valid math expressions. Math expressions must use direct or implied logical tests on command results. Command calls require square brackets with expression ON in order to return a boolean value to test Caution: Don't do this ... option expression on if {[$argc > 1]} { ... # [] transforms into a command call As Ticol will try to dereference argc first and then try to run a command with that name. Use this form... option expression on if {$argc > 1} { ... # A braced expression is required here Example Expression: if {is_set w} {puts yes} else {puts no} # Not a math expression if {[is_set w]!=0} {puts yes} else {puts no} # Correct math expression if {[is_set w]} {puts yes} else {puts no} # Correct math expression Example Eval: if {[is_set w]!=0} {puts yes} else {puts no} # Wrong for use with eval if {[is_set w]} {puts yes} else {puts no} # OK for eval if {is_set w} {puts yes} else {puts no} # OK for eval, [] optional More complex, combined conditional expressions may be formed using [expr] Example: option expression off if {expr [ne $var_1 ""] && [ne $var_2 ""]} { ... option expression on if {[ne $var_1 ""] && [ne $var_2 ""]} { ... See also: else, elseif, and, or, while, foreach, switch, flow control
info  Top  
* Note that adapter and TCP/IP information is unsupported in Windows NT info adapter_count Return the count of known network adapters info adapter_id n Return adapter GUID info adapter_name n Return the adapter name info adapter_type n Return the adapter type value info args procname Return the argument list of a procedure Cannot be blocked by TCX encryption info body procname Return the script body of a procedure Cannot be blocked by TCX encryption info cmdcount Return a count of total command calls info commands ?pattern? List available commands info domain ?n? Show the DNS domain name bound to an adapter info dhcp_enabled n Return boolean 1 if DHCP is enabled else 0 info dhcp_end n Show the DHCP lease expiry date info dhcp_server n Show any currently configured DHCP server info dhcp_start n Show the DHCP lease start date info disks Return a Tcl list containing active disks info disktype x: Show the disk type for a given drive/path 0 Unknown type 1 No root directory/Unavailable/Error 2 Removable 3 Fixed 4 Remote 5 CDROM/DVD 6 RAMDISK info encrypted Returns 1 if script was obfuscated else 0 info executablename Returns the command line EXE filename info exists varname Check if a variable exists, returns 1 or 0 info fmac_address n Return a formatted adapter MAC address info frame ?number? Show the frame number info functions Return a list of functions info gateway n Return the configured IP gateway address info globals ?filter? Returns a Tcl list of variables at level 0 info guid Return a new, unique GUID string info hostname Return the configured PC host name info ip_address n Return the IP address for an adapter info is_elevated Show whether running elevated (Win7+) info is_networked Show whether networked or not info level ?n? Show the call frame level (top level is 0) info lib The library path name info locals ?filter? A Tcl list of variables at the current level info mac_address n The adapter's MAC address info memtotal The total physical memory in bytes info memavail The available physical memory in bytes info memtotalpage The total swapfile memory in bytes info memavailpage The available swapfile memory in bytes info memtotalvirtual The total virtual memory in bytes info memavailvirtual The available virtual memory in bytes info monitorcount Show the number of connected monitors info nameofexecutable Ticol's EXE name and path info netmask n The adapter's IP subnet mask info primary_dns n The adapter's primary DNS server info primary_wins n The adapter's primary WINS server info procname The currently active proc else "" info procs ?filter? A list of user-defined procedures info script The name of the active script (if any) info secondary_dns n The adapter's secondary DNS server info secondary_wins n The adapter's secondary WINS server info tclversion The Ticol version info username Return the currently logged-on user info vars ?pattern? ?-const? List variables. See 'vars' info winver ?-list? Show Windows version information (as a list) See: info winver Where a network adapter is given this is a base 0 value Multiple network information calls are necessarily slow as an API call has to be repeatedly made to retrieve each attribute. Example Result Comment ---------------------------------------------------------------------------- puts [info args square] x List procedure arguments puts [info body square] * $x $x List procedure body puts [bool [info exists pi]] true Check if var pi exists puts [info exists commands c] call calldll... List all starting with 'c' puts [info exeutablename] c:\tcl\ticol.exe Shows the EXE name and path puts [info ip_address 0] Show IP for adapter #1 puts [info ip_address 2] Show IP for adapter #3 puts [info hostname] WORKSTATION23 Show the host name puts [info tclversion] 1.06 Ticol-specific version no puts [info vars pi -const] pi 3.141592... List vars starting with pi puts [info procs f*] foo List procs starting with f puts [info script] test.tcl Must be loaded puts [info level -1] foo 10 Where called from proc foo Example: option expression on for {set i 0} {$i < [info adapter_count]} {incr i} { puts "Adapter $i: [info ip_address $i]" } See also: commands, dump, set, vars
info args  Top  
string [info args procname] Returns the argument parameter of a defined proc. The proc must exist Example: proc foo {x {y NULL}} { puts "In proc [info procname] [info args [info procname]]" } foo Result: In proc foo x {y NULL} See: info
info cmdcount  Top  
integer [info cmdcount] Return a count of total Ticol command calls as an integer Example: proc factorial {val} { puts "Current level: [info level] - val: $val" set lvl [info level] if {$lvl == $val} { return $val } return [expr {($val-$lvl) * [factorial $val]}] } puts "This is how many commands have been executed: [info cmdcount]" puts "Now this is how many commands have been executed: [info cmdcount]" puts "\nThis interpreter is revision level: [info tclversion]" puts "The process id for this program is [pid]" set count1 [info cmdcount] set fact [factorial 3] set count2 [info cmdcount] puts "The factorial of 3 is $fact" puts "Before calling the factorial proc, $count1 commands executed" puts "After calling the factorial proc, $count2 commands executed" puts "It took [expr $count2-$count1] commands to calculate a factorial" Results: This is how many commands have been executed: 133 Now this is how many commands have been executed: 135 This interpreter is revision level: 1.14 The process id for this program is 4352 Current level: 1 - val: 3 Current level: 2 - val: 3 Current level: 3 - val: 3 The factorial of 3 is 18,3,3 Before calling the factorial proc, 142 commands executed After calling the factorial proc, 176 commands executed It took 34 commands to calculate a factorial See also: info
info exists  Top  
bool [info exists variableName|arrayName] The argument for variable or array name must be a name-literal. i.e. it cannot be prefixed with a dollar sign as this will cause automatic dereference to the variable value. Dollar-subscript values may be required for arrays. Note that the array syntax prohibits whitespace between the variable name and the open parenthesis: Correct: "$varname($index)" Incorrect: "$varname ($index)" (looks for non-array variable $varname) Use [array exists arrayname] to test for the presence of an array by name info exists argv0 info exists argv(0) set i 0 info exists argv($i) info exists env(TEMP) array exists argv array exists env See also: info, array exists
info level  Top  
info level ?number? Displays information about the calling frame at a given level. Level 1 in a proc will be the current level, level 0 the calling frame for that proc. If 'number' is not specified, info level returns a number indicating the current calling level, i.e. the level from which info level was called with 0 being the top level, and each subsequent level incremented by 1 If 'number' is specified, info levels returns a Tcl list containing words of the command for the level indicated by number. A number value greater than 0 indicates the level identified by that number. 0 indicates the current level, -1 indicates one level prior to the current level, -2 indicates the level prior to that one etc. Example: proc foo {bar {baz NULL}} { puts "info level 0 is \[[info level 0]\]" } foo foo abc foo abc def Results: info level 0 is [foo] info level 0 is [foo abc] info level 0 is [foo abc def] See: http://wiki.tcl.tk/1720 See also: info
info winver  Top  
info winver ?-list? ?-vernum? ?-truever? Show information about the current Windows version Argument -list will return full Windows information in Tcl list format as {Version name} major.minor.build {Service pack} bitness Argument -vernum will return the full version number as a double value Argument -truever will show the true version number on later Windows builds Example: puts [info winver -list] Result: {Windows XP} 5.01.2600 {Service Pack 3} 32 Example: puts [info winver] Result: Windows XP [Version 5.01.2600] (Service Pack 3) 32 bit Example: # Show whether Windows is 64 or 32 bit lindex [info winver -list] 3 Result: 64 Example: puts [info winver -vernum] Result 5.1 See also: info
inkey  Top  
integer [inkey] Check if there is a key input event pending and retrieve the keypress code If a key-event is pending the key values is returned, otherwise 0 is returned Use [getkey] to wait for keyboard input Example: puts "Press ESC to halt" while {1} { puts "Looping" sleep 1000 if {== [inkey] 27} { # ESC is 27 stop } } See also: getkey, gets, input, sleep
input_csv  Top  
input-csv filename ?varname | -? ?items-max? ?-crlf? ?-array name? ?-r? Read lines from a standard-format CSV file and translate to a properly- formatted Tcl list. The CSV input-file may be contain double-quote wrapped strings but all fields must be comma separated If no variable name is given then [input_csv] returns the list. If a variable name is passed then the variable is assigned (even if this is an empty list) and a count of the number of list elements is returned The new variable name is optional but if lines-max is specified and varname is omitted then supply a hyphen (-) character instead The optional '-crlf' argument will retain newline pairs in the resulting output 'items-max' is the maximum number of array items to read from the file CSV read and conversion may become slow for files over about 5Mb and excessively so for files above 10 or 20Mb+. Consider sequential. line-based input into smaller Tcl lists instead Each line (row) of the file can be read to a Tcl array using the -array argument with a non-existent variable name. Subscript->value assignment can be reversed or 'inverted' using the -r argument No unicode/wide character conversion is performed Example: CSV file: "Hello world",1234,"ABC",5.678 "The quick brown fox",0123,"CDE",23.23 puts [input_csv csvfile.csv - 4] Result: {Hello world} 1234 Tcl 5.678 See also: json_to_list, file read
Getting User Input  Top  
[gets stdin] is a method of retrieving user input from the stdin stream It offers limited line-editing facilities and no option to fix the length of the user-input or prevent line-wrap Example: puts -nonewline "Throw a die. What value did you get? " flush stdout set top [gets stdin] switch -- $top { 1 {set end "st"} 2 {set end "nd"} 3 {set end "rd"} default {set end "th"} } puts "You selected the $top$end face" See also: gets, flush, switch
inttooct  Top  
string [inttooct numeric-value] Converts from decimal to octal format Conversion from octal to decimal is automatic in all routines Octal format is defined by an "0o" prefix. e.g. "0o12" Values given to inttooct may be decimal integers, hexadecimal, octal or binary Tcl v9 octal number identifiers are implemented, which require 0oNN format See: http://wiki.tcl.tk/498 Examples: puts [inttooct [expr "0o123+1"]] puts [inttooct 0b1101001] puts [inttooct 0x68] Results: 0o124 0o151 0o150 See also: intotohex, inttobin, tohex, fromhex, cast
instr, strstr  Top  
integer [instr haystack needle ?-nocase?] integer [strstr haystack needle ?-nocase?] VB and C++ - like string search commands Where 'haystack' may be a variable or literal string and where 'needle' may also be a variable or literal string Returns a 'base 1' index value of 'needle' into 'haystack' If 'needle' is not found in 'haystack' then 0 will be returned. If 'needle' is a null string then 0 is returned The result may be treated as a boolean - not found being 0 and found non-zero Example: puts [instr $qbf "fox"] puts [instr $qbf "QUICK" -nocase] if {[instr $qbf "lazy"]} { puts "True" } Results: 17 5 True Example: puts [strstr "quick brown fox" "brown"] puts [strstr "quick brown fox" "BROWN" -nocase] Result: 7 7 Example: option expression on if {instr $qbf fox} { puts "I found the fox!" } Result: I found the fox! See also: lset, rset, mid, string
inputbox  Top  
inputbox ?prompt? ?title? ?default? ?-password? ?-x X? ?-y Y?\ ?-w W? ?-h H? Creates a windows which can receive user input, optionally with input masked by a password-masking character. Inputs are confirmed by ENTER/OK click or cancelled using ESC/CANCEL click Options ------- -password Mask input characters with an asterisk (*) -x X Locate at cursor X -x Y Locate at cursor Y -w W Make dialog W wide -h H Make dialog H high If -x and -y are omitted the dialogue will centre on the screen Examples: puts [inputbox "Enter your name:"] puts [inputbox "Enter password:" "Password" -password] puts -[inputbox "Enter your name" "info" -w 500 -password]- puts [inputbox "Enter your name:" -x 200 -y 300 -w 500] See also: msgbox, gets
ip_to_long, long_to_ip  Top  
integer [ip_to_long value] string [long_to_ip value] Convert an IPV4 dotted-quad address to an unsigned long value or convert a long value to an IPV4 dotted-quad address Example: puts [inttohex [ip_to_long]] Result: 0xffffffff Example: puts [long_to_ip 0xffffffff] Result: See also: info
item (array, stack or struct)  Top  
string [array item arrayName subScript ?default? ?-nocase?] string [stack item stackName index ?default?] string [struct item structName fieldname ?default?] The item argument returns a value if it exists. If the referenced object does not exist then either "" or a default value is returned See also: array, stack, struct
tohex, fromhex  Top  
string [tohex string] string [fromhex string] Converts a string to and from a hex-encoded version Examples: tohex "hello" fromhex 68656C6C6F puts [fromhex [tohex "Hello world"]] Result: 68656C6C6F hello Hello world See also: inttohex, inttooct, cast
funct  Top  
funct function-name arg ?arg? ... Call an [expr] function directly and separate from the [expr] command [funct] is more efficient than calling expr where access to a single function is required. Complex expressions are not supported within the arguments unless returned by [expr] Examples: puts [funct log10 2] puts [funct round $pi 2] puts [funct rnd 1 10] puts [* [funct atan 1] 4] Result: 0.301029995663981 3.140000 6 3.141592653589792 See functions for the full list of supported functions exported from [expr] See also: functions, expr, eval, function arity
functions  Top  
list [functions ?glob-pattern?] Return a Tcl list of math functions defined for use with the expr command The search may be constrained by a prefix value. The list may be iterated with foreach. See: function arity for more details Example: puts -[functions m*]- Result: -max min mul- Use: option echo on to display directly to the console See also: expression procs, funct
BEDMAS/BOMDAS (Math Operator Precedence)  Top  
Ticol implements BEDMAS to automatically prioritise math expressions: BEDMAS - Brackets, Exponents, Division, Multiplication, Addition, Subtraction The order of operations used throughout mathematics, science, technology and many computer programming languages is expressed as: exponents and roots multiplication and division addition and subtraction Where an operator has equal precedence, (e.g. + and -) then Left to Right evaluation is performed See; http://en.wikipedia.org/wiki/Order_of_operations See also: math operators, math expressions, expression functions
Math Expressions  Top  
The built-in [expr] command can handle complex expressions and applies standard BEDMAS rules by reprioritising expressions before evaluation. During the checking phase any non-decimal consts such as 0xFF or 0o777 are automatically converted to their decimal equivalents. Multiplication and division are given priority over addition and subtraction The exponentiation operator '**' is currently not supported use pow() instead The contents of pre-bracketed expressions and function brackets are also evaluated for correct ordering and precedence. Value interpretation follows Tcl rules. Integers are subjected to integer division. If you wish float division then specify a decimal point. e.g. - 22/7 will return 3, 22/7.0 will return 3.142857142857143 For a full list of supported math functions see Expression Functions Note that commas ',' are undefined within math expressions other than as function parameter separators and their inclusion elsewhere may cause unpredictable results. You may also apply your own expression parentheses. Example: # Call [expr] then external BAT file which calls cscript->eval # abs(1+11*2-1/7.0)/sqrt(2/1.6) is reinterpreted as: # abs(1+(11*2)-(1/7.0))/sqrt(2/1.6) puts [expr abs(1+11*2-1/7.0)/sqrt(2/1.6)] 20.444050079998078 puts [eval.bat abs(1+11*2-1/7.0)/sqr(2/1.6)] 20.44405007999810 Note: The big math plugin module can be used to extend the number range See also: math operators, BEDMAS, expression functions
Math Operators  Top  
The following math operators are supported. Operations are treated as discrete integer or float unless mixed types are encountered, in which case float is used. Take care with division; if you want a float result then one of the operands must be a float value or your result will be truncated to an integer value: e.g. Use: expr "22/7.0" not expr "22/7" + Addition - Subtraction * Multiplication / Division % Modular division ** Power. Returns x raised to the power of y (See: pow) Integer overflow is fatal Double overflow returns 1.#INF00000000000 Combination Operators += Combination add and assign -= Combination sub and assign *= Combination mul and assign /= Combination div and assign Integer Only: ^ Bitwise xor << Bitwise shift left (64-bit) >> Bitwise shift right (64-bit) | Bitwise or || Logical or & Bitwise and && Logical and The above may be applied as combined operator= symbols, e.g. ^=, &= Relational Operators: == Equivalence != Inequality > Greater than >= Greater than or equal to < Less than <= Less than or equal to mod Modular division is_mod Safe modular division test () Precedence bracketing Division by zero will return an error as either: Integer division by zero (10 / 0) Float division by zero (10 / 0) When used as a command, the math operators such as [add] [sub] etc. can be used with a variable name as the following method of shortcut assignment... set a 1 add a [expr 3*3] add a [* 3 3] Result: 10 19 Note: The big math plugin module can be used to extend the number range See also: big math, incr, decr, ++, --, is_div, shortcut operators, BEDMAS, math expressions, is_mod
Shortcut Math Operators  Top  
Syntax: <operator> <variable> <value> Operator Mnemonic Domain ------------------------------------------ += Add Integer, float -= Sub Integer, float *= Mul Integer, float /= Div Integer, float &= BitAnd Integer |= BitOr Integer ^= BitXor Integer The shortcut math operators help simplify and speed up math expressions. For example, the longhand: set a [* a 3] may be condensed to: *= a 3 Examples: Set a 1 # 1 += a 10 # 11 -= a 2 # 9 *= a 3 # 27 /= a 9 # 3 |= a 4 # 7 &= a 6 # 6 ^= a 2 # 4 ^= a 2 # 6 See also: math operators
<< >> Bit shift (64-bit)  Top  
<< value bits ?bit-width? # Bitwise shift left >> value bits ?bit-width? # Bitwise shift right Either left or right-shifts a value by N bits. This is a valid operation for integers only. Negative shift values will raise a catch exception The expression forms of << and >> do not accept bit-width arguments. If you need to specify a bit width then insert the command in either expression or eval pass as [<< value shift bits] [>> value shift bits] Examples: puts [expr [<< [expr 20+3] [expr 2^4] 32] - 472] puts [expr 1*[<< 1 1]*3/4.0*5] Result: 1000 7.5 Note that all Ticol integers are 64-bit and by default these bit operations work on 64-bit integers. This can be modified by adding an output bit-width argument of either 8,16 or 32. Any other values will evaluate as 64-bit Shift does not wrap or suffer from an underlying 32-bit bias for other bit-widths. All shifts equal-to or in excess of the specified bit width will return 0 Wrapping does not occur (32-bit wrapping is blocked) Shift [<<] and [>>] fills vacated bits with 0. All values are unsigned. Sign-bits do not therefore, cause 'backfill' with [>>] Examples: puts [inttohex [<< 0xff 32]] puts [inttohex [<< 0xff 63]] puts [inttohex [<< 0xff 64]] loop i 0 40 8 { printf "\[inttohex \[<< 0xff %2i 32\]\]='%20s'\r\n" $i\ [inttohex [<< 0xff $i 32]] } Result: 0xff00000000 0x8000000000000000 0x0 Examples: puts [inttohex [<< 0xff 0 32]]=' 0xff' puts [inttohex [<< 0xff 8 32]]=' 0xff00' puts [inttohex [<< 0xff 16 32]]=' 0xff0000' puts [inttohex [<< 0xff 24 32]]=' 0xff000000' puts [inttohex [<< 0xff 32 32]]=' 0x0' See also: math operators, functions
Tcl Expression Functions  Top  
The following functions are available within Tcl expressions using the expr command. See function arity for a more detailed list of arguments abs acos asin atan bool ceil decr div cos cosh degrees double exp fib fix floor fmod fraction hypot incr int integral log log10 max min mul pow rand rnd round sgn sin sinh sqr sqrt srand tan tanh wide ?: Available functions may be listed using the 'functions' command See: function arity for more details about functionality The functional int differs from the int conversion command. int(x) will round to the lowest integer whereas [int x] will simply cast and convert Int returns the first -ve integer less than or equal to value, whereas Fix returns the first -ve integer greater than or equal to value. Functions may be nested within expressions passed to the 'expr' command and may also be called using the [funct] command The 'sgn' function returns: Greater than zero 1 Equal to zero 0 Less than zero -1 Example: expr "int(22/7.0)+int(5.2)" Result: 8 Example: expr "round(exp(log(10)),0)" Result: 10 Example: expr ([rnd 0 1]?yes:no) Result: Randomly yes or no Example: puts [funct max 2 10] Result: 10 See also: function arity, Math Expressions, arity, expr, eval, math, funct, functions, funct
getcwd, pwd  Top  
getcwd pwd Returns the current working directory [getcwd] will return the path as a backslash-escaped string for Tcl processing [pwd] will print out the current working directory for display purposes Example: pwd getcwd Results: C:\windows\system32 C:\\windows\\system32 See also: mkdir, file, dir
getfileopen, getfilesave  Top  
getfileopen filter title initdir ?flags? getfilesave filter title initdir ?flags? ?defaultname? Launches a Windows file select (open) dialogue or a file select (save) dialogue For getfilesave a default filename may be specified after the flag value. Unwanted flag values should be specified as 0 Example: set f [getfilesave *.txt "Save Txt File" "d:\temp"] set f [getfilesave *.txt "Open Txt File" "d:\temp" 0 fred.txt] See also: msgbox
getenv  Top  
getenv Return an environment variable from Windows Example: puts [getenv ProgramFiles] Result: C:\Program Files (x86) See also: setenv
gets  Top  
gets gets length gets var gets var length gets stdin|filenum ?var? ?count? Read data from an open file-stream. This may either have been opened by the open command or the stdin read stream may be used. Optionally, a variable may be specified to receive the data. This need not be declared in advance. The default file-stream is 'stdin'. A numeric value is assumed to represent a length value Additionally an optional number of bytes to read from the stream may be specified If 'count' is specified then CTRL+Z (^Z or EOF) terminates input before the required number of characters has been read. If count is not specified then input terminates when ENTER is met When using [gets] to read from the stdin console it supports up/down cursor history, home/end and full inset-mode line editing Example: puts "Enter your name: " -nonewline set a [gets] newline Example: puts "Enter your name: " -nonewline gets a newline Example: puts "Enter your name up to 20 characters: " -nonewline gets a 20 newline Example: puts "Enter your name up to 20 characters: " -nonewline gets stdin a 20 newline Example: set fp [open "input.txt" r] gets $fp a 100 # Read 100 chars close $fp See also: inputbox, file, open, close
gotoxy  Top  
gotoxy x y Locate the screen cursor at an x/y location. The values are base 1 If using [puts] with absolute screen coordinates via [gotoxy] you should use the -nonewline argument if possible to avoid screen scrolling issues Example: option expression off for {set i 0} {< $i 10} {++ i} { gotoxy 5 5 puts "I am at 5,5" -nonewline } See also: cls, box
Ticol Tcl Interpreter v1.25 (C) M Shaw 2015-2017  Top  
_______ __ ___ ___ ____ /_ __(_)______ / / _ __ < / |_ |/ __/ / / / / __/ _ \/ / | |/ / / / / __//__ \ /_/ /_/\__/\___/_/ |___/ /_(_)____/____/ See any associated README.TXT for latest updates and amendments Type the following: help <command> for help on a particular command, e.g. help commands help debugging help functions help flow control help macro help math help performance help ticol help variables autoexec on or off to enable automatic execution of unknown commands commands for a list of commands vars for a list of variables (vars -const for a list of consts) exec ticol /? for command-line help spawn run a program with redirected output <command> for a Windows command exit to exit the interpreter shell http://kerys.co.uk/ticol See also: ticol, tcl, autoexec, commands, exec, flow control, macro, math, vars, load, script, run, commands by function, faq
Hex Routines  Top  
string [tohex string] string [fromhex value] string [inttohex decimal-variable ?-noprefix? ?-full?] integer [hextoint string] Conversion routines to convert from text and integers, to and from hexadecimal Note that because the Macro PreProcessor will translate hex values if prefixed with '0x', you should wrap any such values in double quotes before calling [hextoint], or you should strip any prefixing '0x', otherwise inaccurate results will be returned due to double, interpretation of the hex value [tohex] Converts a string into hex-encoding, the inverse is [fromhex] [inttohex] converts a decimal value to base 16, the inverse is [hextoint] Conversion from hex to decimal integer is automatic in Ticol The -full argument presents all prefixing zero values. Normally these leading zeroes are omitted If the -noprefix argument is given then the 0x... prefix will be omitted Example: puts [inttohex 12345] Result: 0x3039 Examples: puts [inttohex 12345] puts [inttohex 12345 -noprefix] puts [hextoint "0x3039"] puts [tohex "Hello world"] puts [fromhex 48656C6C6F20776F726C64] Results: 0x3039 3039 48656C6C6F20776F726C64 Hello world See also: int, double, data types
Code Highlighting Plugin  Top  
Load using: lib ticol_highlight?.dll? string [highlight string ?-bat? ?-rtf?] string [highlight {} -reset] [highlight] was created purely to output the Ticol man file as both HTML and RTF format files It can create a HTML-highlighted block of text from Tcl or Windows Batch script code using the Ticol man file markup syntax. Use the '-bat' argument for batch scripts Rich Text (RTF) output can also be generated using a custom {colortbl} entry Call as [highlight {} -reset] to reset multi-line string text highlighting if necessary Example files are supplied, man_to_rtf.tcl and man_to_html.tcl See also: Plugins, lib, rtf
html  Top  
Various HTML manipulation commands See: html header_field html remove_header html strip See also: http
html header_field  Top  
html header_field string field-name Return a header field from an HTTP 1.1 block of HTML code. Case is ignored during comparison and trailing colons may be omitted for the field name. Whitespace is trimmed from the return string Example: # Emulate an HTTP header set x "HTTP/1.1 200 OK\r\n\ Date: Fri, 12 Jun 2017 13:26:15 GMT\r\n\ Server: Apache/2.4.10 (Ubuntu)\r\n\ X-Powered-By: PHP/5.5.12-2ubuntu4.3\r\n\ Redirect: http://localhost.com/index.php\r\n\r\n" puts "Date: \[[html header_field $x Date:]\]" puts "Redirect: \[[html header_field $x rEdIrEcT:]\]" puts "Server: \[[html header_field $x server]\]" Result: Date: [Fri, 12 Jun 2017 13:26:15 GMT] Redirect: [http://localhost.com] Server: [Apache/2.4.10 (Ubuntu)] See also: http, html remove_header
html remove_header  Top  
string [html remove_header string] Strip off and remove the HTTP header from an HTML body return string stripto may be used to remove other junk up to the starting < bracket See also: http, html header_field
html strip  Top  
string [html strip string] Removes all HTML tags from a string   tags are replaced with a single space Example: set s "<b><em>Hello world</em></b>" puts [html strip s] Result Hello world See also: html remove_header, html header_field
http  Top  
http ?http://?domain?:port??url? ?port | -? ?var? ?-u user? ?-p pass? ?-1? ?-nocomplain? ?-head? Load a page of HTML text from a remote website via a HTTP 1.1 request HTTP is supported on any port but HTTPS and FTP etc. are unsupported Binary downloads are currently unsupported but you can easily [spawn] external programs such as wget.exe for binary content The default port value is 80. This may be specified either in the URL or via the port argument. Extra headers cannot be specified. Optional Arguments: -u Specify a username for BASIC Authentication -p Specify a password for BASIC Authentication -1 Use HTTP 1.0 instead of HTTP 1.1 -head Issue an HTTP HEAD command instead of HTTP GET Positional Arguments: Example: http "http://en.wikipedia.org/wiki/main_page" - x Result: puts "HTML is: $x" Example: puts [http http://localhost:8800/cgi-bin/ticol.exe?cgi.tcl] Result: <displays Tcl script page contents> See also: urlencode, urldecode, html remove_header, html header_field
int, double (Type Casting)  Top  
Type-casting operators: integer [int variable|number] double [double variable|number] Converts a numeric character to the requested type, by truncation of necessary. Input can either be a number or a variable name Bear in mind that Tcl is a "typeless" language where "everything is a string" However strings still have an apparent type, for example the string: 3.141592653589792 has "real" number characteristics, whereas ... 3 does not. Consqeuently one can transpose real numbers to integers. Also, Ticol assumes type and will assume integer values in some cases where this is undesired. This may affect certain math operations such as division forcing a truncated integer result. You can ensure a real number (double) operation by casting integer values to double Example: expr 22/7 Result: 3 Examples: puts [expr 22/double(7)] # Expression syntax puts [/ 22 [double 7]] # Tcl command syntax puts [/ 22 7.0] # Command syntax with double value Result: 3.142857142857143 int and double are available as both expression functions and Tcl commands See also: vars, type
is_admin  Top  
bool [is_admin] Return true (1) if the current Windows user is an administrator See also: elevate, is_elevated
is_command  Top  
bool [is_command command|procname] Returns either "True" or "False" indicating whether a command or procedure is defined. [is_defined] may also be used to test for definition Example Result is_command puts 1 is_command put 1 is_command putt 0 See also: is_defined, commands, if, while. for. foreach, flow control
is_const  Top  
bool [is_const varName] Returns a boolean indicating whether a variable is a constant Example: set sid Hello enum { fred } puts "Is sid const? [bool [is_const sid]]" puts "Is fred const? [bool [is_const fred]]" Results: False True See also: is_pointer, const, set
is_elevated  Top  
bool [is_elevated] Returns true (1) if Ticol is running with elevated privileges (Windows 7+) [elevate] will self-call, passing the original command-line arguments Example: if {! [is_elevated]} { elevate } else { # Run the script } See also: elevate, is_admin
is_empty  Top  
bool [is_empty varname] Test if a variable is both set and empty. If a variable of either array or simple type is both set and empty it returns 1, otherwise it returns 0. Be careful to pass the name of the varible rather than its value Empty Not-empty ---------------------- unset 0 0 set 1 0 Example: set s {} if {is_empty s} { puts "Empty" } else { puts "Not empty" } Result: Empty See also: is_set
is_dir  Top  
bool [is_dir path] Tests if the given path string is a path or not See also: mkdir, unlink, file
is_pointer  Top  
bool [is_pointer varName] Returns a boolean indicating whether a variable is a constant or not See also: is_const, setb, addressofb, ofaddressb, struct
is_proc  Top  
bool [is_proc name] Test if a command is a user-defined procedure Example: if {is_proc foo} { undef foo } See also: proc, undef
is_mod  Top  
bool [is_mod value divisor ?command?] Fast, division-safe modular division check. If the divisor is zero then false is returned. This avoids extra Tcl code to prevent division by zero In loops this can lead to improved performance. A boolean 1 or 0 is returned. Performance may be enhanced by avoiding [if] and executing an optional command to evaluate if [is_mod] is true [is_mod] replaces the longhand expression: if {[== [% $x 1000] 0]} {call_proc} with: if {[is_mod $x 5000]} {call_proc} Calculations are performed on 64-bit integer values Example: [is_mod $x 5000 call_proc] See also: is_, is_number, math
is_numeric  Top  
bool [is_numeric string] Tests if a string is composed entirely of the following characters and returns boolean 1 if so, otherwise 0 +-0123456789,. This includes comma-formatted numbers Examples: puts [is_numeric hello] puts [is_numeric 10/01/2017] puts [is_numeric 23:59] puts [is_numeric 12345] puts [is_numeric +123.45] puts [is_numeric -12,345.67] Results: 0 0 0 1 1 1 See also: is_
is_set  Top  
bool [is_set variableName] Tests to see if a variable exists (is set). Similar to php's 'isset' You should pass a variable name not the dereferenced contents of a variable Returns a boolean value (1 or 0) [is_set] may be used on standard Tcl variables such as string variables, arrays, lists, stacks, structs. For arrays you may also use [array is_set] If using option expression on then the 1st argument will not be interpreted as a command. Thus care should be taken with flow-control statement arguments Correct: if { [is_set argv] } {...} Incorrect: if { is_set argv } {...} if { is_set $argv } {...} if { [is_set $argv] } {...} Arrays should be tested using [array exists] See also: is_empty, array exists, is_admin, is_dir, is_elevated, set, vars
join  Top  
string [join list ?separator?] Join elements within a space-separated Tcl list and return a string. The spaces are removed during the process. The list elements may be separated by an optional separator character Example: set s "The quick brown fox" set r [join $s "-"] puts $r Result: The-quick-brown-fox [join] can also be used to 'flatten' a list by one level. The outer- braces are always removed when an argument is passed to a command but an additional +1 level of braces is removed Example: set data {1 {2 3} 4 {5 {6 7} 8}} puts [join $data] Result: 1 2 3 4 5 {6 7} 8 See also: split, list
json_to_list  Top  
list [json_to_list json_string|variable ?variable?] Convert a sequence of JSON format data into Tcl list format Converting JSON using native Tcl code can be quite slow. This function speeds up conversion significantly compared to a Tcl code implementation The command was written for a specific data-processing task and may not, therefore, be feature-complete See also: list
K Combinator  Top  
K x ?y? ... Functional programming K-combinator. Allows chaining of Tcl expressions Functionally equivalent to: proc K {a b} {return $a} It can be used in all situations where you want to deliver a result that is not the last. i.e. the first item is returned but the last discarded The K is a capital letter K (not lower-case) For instance, reading a file in one go: proc readfile filename { set f [open $filename] set data [read $f] close $f return $data } can be simplified, without need for the data variable, to: proc readfile filename { K [read [set f [open $filename]]] [close $f] } Swap two variables, say a and b, without any temporary variables: set a [K $b [set b $a]] Another example, popping a stack: proc pop _stack { upvar 1 $_stack stack K [lindex $stack end] [set stack [lrange $stack 0 end-1]] } We can also achieve an efficient implementation of lambda expressions in Tcl using K: proc lambda {arg body} { K [set n [info $body 0]] [proc $n $arg1 $body] } For more information see: http://wiki.tcl.tk/1923/ See also: list functions
keyword  Top  
Ha ha ha, very funny. But, seriously. Search for an actual key word rather than the phrase "keyword" See also: FAQ
Lambda Example  Top  
Here is an example Lambda function from the http://tcl.tk website When called from a script the lambda function can be called using puts [$inv x]. This script cannot handle lists of arguments When called from the Ticol CLI you can use just $inv x - e.g. $inv 5 proc lambda {args body} { puts "in lambda args:$args body:$body" set name [info level 0] # Should return lambda x {expr 1./$x} puts "Name:$name" commands $name proc $name $args $body set name } set inv [lambda x {expr 1./$x}] # Calls proc lambda puts [$inv 5] # Call with $inv 5 from the Ticol CLI Result: 0.2 The [lmap] command can also be used to construct lambda expressions such as: puts [lmap {x {expr {$x * $x}}} {1 2 3 4 5}] For more on lambda expressions see: lmap and apply See: http://wiki.tcl.tk/519 See also: K, apply, lassign, lmap, map
lappend  Top  
list [lappend list variable|string ?string?...] Append a string to the end of a list literal or variable, or creates a list from a series of strings. Strings with spaces are wrapped in double quotes [lappend] differs from the standard Tcl one in that you can pass a variable or a literal list as the first argument. Standard Tcl only allows a variable to be passed. Ticol will not automatically create a new variable, any variable argument must already exist Example: puts [lappend [list one two] three] Result: one two three Example: puts [lappend [list one two] three] Result: one two three See also: lindex, list
lassign  Top  
list [lassign list ?varName ...?] This command treats the value list as a list and assigns successive elements from that list to the variables given by the varName arguments in order. If there are more variable names than list elements, the remaining variables are set to the empty string. If there are more list elements than variables,a list of unassigned elements is returned, otherwise an empty list {} is returned Example: lassign {a b c} x y z Result: $x =>'a' $y =>'b' $z =>'c' Example: lassign {a b c} v w x y z Result: $v =>'a' $w =>'b' $x =>'c' $y =>'{}' $z =>'{}' Example: lassign {a b c "The quick" "brown fox" "jumps"} x y z Result $x =>'a' $y =>'b' $z =>'c' {The quick} {brown fox} jumps See also: lappend, list, apply, lmap, map, apply, lambda
lcount  Top  
integer [lcount list] Returns a count of the number of items in a list Example: puts [lcount $qbf] # Count the number of words Result: 9 See also: list, lindex, lappend, lassign
ldepth (proc)  Top  
integer [ldepth list] Returns the depth of a list or 0 for an empty or flat list Definition: proc ldepth {list} { if {! [is_list $list]} { return 0 } set flatList [join $list] if {[string equal $flatList $list]} { return 1 } return [expr {[ldepth $flatList] + 1}] } Example: set l {} puts [ldepth $l] set l a puts [ldepth $l] set l {a b} puts [ldepth $l] set l {a {b {c d}}} puts [ldepth $l] Results: 0 1 1 3 See also: list, lappend, lassign, lcount, ldepth, lindex, list, list_to_array, llength, lmap, lrand, lrange, lreverse, lsearch, lset, lsort
left, string left  Top  
string [left variable n] string [string left variable n] Return the leftmost n characters of a string A common task is to look at the first character of a string. The most effective way to do this is to use [index] rather than [string left] Example: puts [string left $qbf 1] puts [index $qbf 1] Results: T T See also: index, right, mid
len  Top  
integer [len string] Return the length of a string This is a convenient alias for [string length] Example: puts [len $qbf] Result 43 See also: string, string length
let (Assignment command)  Top  
let Lvalue = Rvalue Evaluate Rvalue(s) as an expression then assign let Lvalue := Rvalue Assign rvalue(s) without evaluating (assignment) The MPP may simplify/evaluate expressions Rvalue of [expr] or [command] will still evaluate If Rvalue is a string then a well-formed Tcl list will be returned (this may be brace-wrapped) let Lvalue ++ Increment lvalue(s) - equivalent to [++ var] let Lvalue -- Increment lvalue(s) - equivalent to [-- var] let Lvalue += Rvalue Assign to existing value. Rvalue may be expression Will cast to double before addition let Lvalue -= Rvalue Assign to existing value. Rvalue may be expression Will cast to double before subtraction let variable|array = expression|variable|array|[command] # Eval with expr let variable|array := list|variable|array|[command] # Assignment only let variable|array = {variable|array} # Evaluate contents with [expr] let variable|array := {variable|array} # Assignment of values only [let] implements a proposed extension to the Tcl language. It acts similarly to [set] except that it accepts a Tcl expression as the Rvalue The expression may be another Tcl variable or a complex statement [let] returns the resulting Lvalue variable's contents if there is only one lvalue. If several variables are [let] then the last variable's contents is returned Whitespace is allowed between individual Rvalue expression arguments where '=' is used. This will be removed before the result is evaluated using [expr] To assign a literal string rather than evaluate it use the ':=' operator instead of '='. This also allows the result of a bracketed [eval] operation or commands to be assigned. For numeric expressions there will be no difference between the two methods since the numeric result will be correctly checked by [expr] Example: let x y z := "06/Jun/2015" # Note: just assign, don't [eval] Note that expressions contained within square [] brackets will have already been evaluated before being presented to [let]. Therefore the result will be re-evaluated again when using '='. Where this is not desired use direct assignment ':=' For example let a b c = [info commands] return an invalid result since the resulting command string will be re-evaluated as an expression. The correct command would be: let a b c := [info commands] Example: set x "Hello world" let a b c := $x puts "$a, $b, $c" Result: Hello world, Hello world, Hello world, Example: let x := [/ 22 7.0] # Call assign instead of expr Result: 3.142857142857143 # [] are always resolved Example let x := [/ 22 7.0]*2 # Call assign instead of expr Result: 3.142857142857143*2 # [] are always resolved Example let x = [/ 22 7.0]*2 # Call expr and assign the result Result: 6.285714285714286 Example: let x := "Hello world" # Will return a Tcl list Result: {Hello world} Example: let x := one "two three" four # Will return a well-formed Tcl list Result: one {two three} four Example: set q 0;let q += [rnd 1 10]; puts $q Result (some value between 1 and 10): 2.000000 Let is an efficient way of setting variables to a complex expression which avoids intermediate steps but will be slower and less-efficient for simple assignments of const values When using the '=' operator, variables, including array variables will be evaluated before the call to let, and the contents of the variable will then be evaluated by let as an expression, thus if you wish to assign the value of a variable without interpretation you must wrap the rvalue variable in braces thus: Example: let path = {$env(TEMP)} # Prevent [expr] evaluation, pass as a literal let path := $env(TEMP) # Alternate method, direct assignment Result: x is correctly set to 'c:\temp' Example: let path = $env(TEMP) Result: x is incorrectly set to 'temp' after evaluation of c:\temp Expression examples: Example: let q = 4 * atan(1) puts "q is $q" Result: q is 3.141592653589792 Example: let q = [fib 12] puts "q is $q" Result: q is 233 Example: let x = {rnd(1,5)>2?return Hi:return Lo} # rvalue must be wrapped in {} Result: Lo See: Tcl language extension proposal: http://wiki.tcl.tk/3880 See also: set, unset, vars
lib (Ticol Plugin Module Extension Loader)  Top  
Load or reference a library using the following syntax: integer [lib dllname ?filter|modulename? ?-list? ?-nocomplain? \ ?-verbose? ?-replace?] string [lib dllname -info] integer [lib dllname -unload] string [lib -modules] ticol.exe /lib:dllname (For a list of available plugins see: help plugins) Load a Ticol plugin extension DLL. The DLL must have been written for Ticol using the Ticol interface standards/ It must provide query interfaces according to the supplied definitions. (See accompanying documentation) If no path is given, [lib] will attempt to load the plugin library from the current ticol.exe path location. The command returns a count of the number of modules loaded or unloaded [lib] will load commands into the current interpreter instance. Once loaded these cannot be reloaded by [lib] until they have been undefined using [undef] No load status will be printed to the console unless the -verbose arg is used Conflicting commands can be automatically unregistered using the -replace arg Once loaded, plugin library functions may be used the same as any other internal Ticol command and variable memory assigned is automatically garbage-collected [lib -info] Calling separately with the -info arg will return the version number as x.xx and the build date in ISO format as a Tcl list which can be displayed using [puts]. The library is not loaded To unload a plugin and remove all registered commands use the -unload argument. -unload will return a count of modules successful de-registered A library may be loaded at startup using: ticol.exe /lib:dllname Any number of modules may be loaded at startup [lib -modules] will list all registered Ticol modules (DLLs) Examples: lib ticol_zip # Load in silent mode lib ticol_mail.dll -verbose # Load in verbose mode lib ticol.dll d* -list # Load and return modules as a list lib ticol.dll -unload # Unload ticol.dll lib ticol_bignum.dll -replace # Reload puts [lib ticol_ping -info] # Returns "1.02 20160331" puts [lib -modules] # "ticol_bignum ticol_zip ticol_reg" See: plugins for a list of available Ticol plugin modules See also: plugins, lib interface, undef, commands
lib interface specifications  Top  
Plug-in DLLs can be produced for Ticol which adhere to the following specifications: All functions must be exported as __cdecl The following exports must be offered: long __cdecl _get_dll_version() { return _DLL_VER // C++ macro definition } LPCSTR __cdecl _get_dll_date() { return _DLL_DATE; // C++ macro definition } LPCSTR* __cdecl _get_function_list() { return _dll_function; // C++ array } LPCSTR* __cdecl _get_command_list() { return _dll_command; // C++ array } long __cdecl _get_export_count() { return _export_count; // Defined from arrays } Interface functions (as defined above) must be exported by name as __cdecl with the following Ticol command signature: int (__cdecl* CmdFunc)(struct Interp* i, int argc, char** argv, void* pd) Your functions will use i as the interpreter instance and use the argc/argv arguments to receive arguments. These arguments may be altered but not deleted or reassigned. Full details of available library functions are given in the plugin documentation. For more information see the example C++ source code ticol_init(); should be called before calling any Ticol library functions Only locally-allocated memory may be freed. The C++ lib header has prototypes for a number of functions exported back from Ticol to the DLL for memory housekeeping etc. Commands are specified as case-sensitive strings which must not contain spaces Example stub code: int __cdecl CommandTest(struct Interp *i, int argc, char **argv, void *pd) { print_error("%s: Command not implemented\n",argv[0]); _ticol_set_result(i,"0"); return PICOL_OK; } See also: plugins, commands
lindex  Top  
lindex list index ?index|end-N?... Index an item from a list. Multiple index selectors may be given, in which case, each will be selected in turn from left to right. Brace binding is honoured and quoted strings are treated as distinct objects outside of braces. Index values are array base indexed at zero Indexing very large lists (megabytes and above) can be quite slow. Arrays should be used in preference For single indices, the mnemonic, "end" may be used either with or without an adjustment value, e.g. end-4 Example: set l [list colour "sunflower blue"] puts $l Result: colour {sunflower blue} Example: puts [lindex $l 0] Result: colour Example: puts [lindex $l 1 0] Result: sunflower Example: puts [lindex $l 1 1] Result: blue See also: list, llength, lappend
Line Continuation Character  Top  
A backslash character can be appended to the end of a Tcl source file line This will cause the line to continue onto the next and the backslash to be ignored. A space will be appended to data from the next line. Any whitespace before the \ character will be left in-situ Care should be taken to include formatting spaces when breaking up a string The next line should start at the beginning of the line and not be indented by source-code formatting unless you want this to be included in the resulting string The line-continuation character must not be followed by any other character or comment such as # on that line or it will be interpreted as a literal backslash rather than end of line marker Ticol also handles multi-line strings in a source file. Example: (First char of each next line is will become a space) .........1.........2.........3... puts "The quick brown\ fox jumps over\ the lazy dog" Result: The quick brown fox jumps over the lazy dog Example: (Multi-line string. The text format is retained) .........1.........2.........3... puts "The quick brown fox jumps over the lazy dog" Result: .........1.........2.........3... puts "The quick brown fox jumps over the lazy dog" Example: (Results in extra spaces) .........1.........2.........3... puts "The quick brown \ fox jumped over \ the lazy dog" Result: The quick brown fox jumps over the lazy dog Example: .........1.........2.........3... puts \ "Hello world" Result: Hello world Where if statements are used with [option expression on] and the expression is on multiple lines then line break continuation characters must be used, e.g. set r [rnd 1 10] if { $r \ > \ 5 } { puts Yes } else { puts No } Numbers may be declared using line-continuation providing they are wrapped in double quotes, thus: set n "12345\ 6789" See also: escape sequences, macro, #ifdef, #define
Line Numbers  Top  
Absolute line numbers exist only in an original Ticol source script. In Tcl there is no concept of absolute line numbers within operational code since code may be broken up into many separate fragments (e.g. procs) The Macro PreProcessor (MPP) will completely remove comment lines and thus the original line numbers cannot be traced. Also, procedures use copied segments of code which have no absolute line numbering. Line numbers referring back to the original source code can be matched during debugging by the use of a variable set within the source code at strategic points using the #__LINE__ macro Example: set line #__LINE__ if {! [defined check] } { # [assert] is the native alternative proc check {x y} { if {!= $x $y} { puts "Error in test at after line $::line" puts "$x != $y" stop } } } set line #__LINE__ check [expr "abs(-100)"] 100 # Should pass set line #__LINE__ check [expr "abs(-100)"] 101 # Should fail Result: Error in test at after line 15 See also: assert, line continuation character, debugging, performance
llength  Top  
llength literal-list Return the count of items in a Tcl list or 0 if the list is empty llength takes a dereferenced list literal as argument, not a variable name Example: set a [list one two three] puts [llength $a] Result: 3 See also: list, lappend
link_to_path  Top  
link_to_path filename Resolve a Windows LNK shortcut file to the target path for that link file The result is an unescaped string. [escape] may be required to use the return with other commands Example: (This uses an external app: makelink.exe to create the LNK file) makelink.exe ticol.exe . puts [link_to_path ticol.exe.lnk] Result: C:\Tcl\ticol.exe See also: info file, escape
Linked List Plugin  Top  
To load use: lib ticol_list ?-verbose? ?-nocomplain? handle [linkedlist create] bool [linkedlist add handle lvalue ?rvalue?] string [linkedlist get handle lvalue] string [linkedlist item handle integer] code [linkedlist foreach $handle lvalue ?rvalue? {command}] bool [linkedlist in_list handle key] bool [linkedlist insert handle key lvalue ?rvalue?] long [linkedlist count handle] void [linkedlist walk handle] bool [linkedlist unset handle key] bool [linkedlist unset handle] [linkedlist] offers standard low-level, linked lists. These are not the same as Ticol built-in Tcl lists (which are represented as ordered strings) [linkedlist] enables a programmer to create rapid, robust linked lists in the same manner as offered by many other high-level programming languages External data structures such as [linkedlist] require a valid handle variable to access A list has a start (often called a 'head') and an end (often called a 'tail'). Items are usually added to the start of the list and the 'tail' value represents the most recently added item. Lists are iterated by starting at the 'start' node and reading each successive node in the chain until the 'tail' or last node is met the quick brown +------+ +------+ +------+ +-----------+ | head |->|node 1|->|node 2|->|tail (NULL)| +------+ +------+ +------+ +-----------+ |lvalue| |lvalue| |lvalue| | N/A | +------+ +------+ +------+ +-----------+ |rvalue| |rvalue| |rvalue| | N/A | +------+ +------+ +------+ +-----------+ Each node in the linked list can store two variables. Each will store an lvalue (left hand value) and may optionally store an rvalue (right hand value) [linkedlist create] Creates a new list and returns a handle to the created list. A list is identified and manipulated by its handle. It is a fatal error to issue a list command with an invalid, freed or absent handle [linkedlist add] will add a new item to the linked list. Each successive new item is added at the head of the list. An "rvalue" is optional Example: linkedlist add $handle hello linkedlist add $handle pi 3.14159265358979323 [linkedlist get] retrieves an 'rvalue' (if any) from a list item. A list item may either simply be present in the list (as an lvalue) or the lvalue may have an associated rvalue. (lvalue and rvalue stand for left hand value and right-hand value respectively) Example: # The lvalue is 'pi', the rvalue is '3.14159265358979323' linkedlist add $handle pi 3.14159265358979323 puts [linkedlist get $handle pi] [linkedlist item] Allows for random access of the linked list by integer value. The first item in the list will be '1' (i.e. a base 1 index) [linkedlist count] should be used to obtain a count of list items Example: option expression off set handle [linkedlist create] set i 1 foreach {x} $qbf { linkedlist insert $handle {} $x $i ++ i } for {set i 1} {< $i [linkedlist count $handle]} {++ i} { set lv [linkedlist item $handle $i] # LValue set rv [linkedlist item $handle $i -rvalue] # RValue puts "$i:\t$lv\t$rv" } Result: 1: lazy 8 2: the 7 3: over 6 4: jumps 5 5: fox 4 6: brown 3 7: quick 2 8: The 1 [linkedlist foreach] allows iteration over the list from start to head, calling some body of code. An lvalue variable must be supplied. An rvalue variable is optional. Standard flow-control commands such as [break], [return] and [stop] are supported and these will return an appropriate error code (See: error codes, stop, break, return) Example: set handle [linkedlist create] set i 1 foreach {x} $qbf { linkedlist add $handle $x $i ++ i } linkedlist foreach $handle lv rv { puts "foreach is:\t'$lv'\t'$rv'" if {[eq $lv fox]} { puts "* Break *" break } } Results: foreach is: 'The' '1' foreach is: 'quick' '2' foreach is: 'brown' '3' foreach is: 'fox' '4' * Break * [linkedlist in_list] can be used to test if a given lvalue (key) is present in a given linked-list structure Example: set handle [linkedlist create] set i 1 foreach {x} $qbf { linkedlist insert $handle {} $x $i ++ i } puts "dog present?: [bool [linkedlist in_list $handle dog]]" puts "cat present?: [bool [linkedlist in_list $handle cat]]" Results: true false [linkedlist insert] inserts a new entry AFTER any key value which is found or at the start of the list if the key value was not found or was supplied as an empty/null value Example: linkedlist insert $handle quick blue linkedlist unset $handle fox Repeated calls to [linkedlist insert handle {}] can be used to create a list in reversed-order from the default. Each successive call will add the new value to the beginning of the list Example: set handle [linkedlist create] set i 1 foreach {x} $qbf { linkedlist insert $handle {} $x $i ++ i } linkedlist walk $handle Results: List 0x2d60cb0 0 item(s) List::walk 0x2d60f70 VT_001e [dog]=>'9' List::walk 0x2d60f20 VT_001e [lazy]=>'8' List::walk 0x2d60ed0 VT_001e [the]=>'7' List::walk 0x2d60e80 VT_001e [over]=>'6' List::walk 0x2d60e30 VT_001e [jumps]=>'5' List::walk 0x2d60de0 VT_001e [fox]=>'4' List::walk 0x2d60d90 VT_001e [brown]=>'3' List::walk 0x2d60d40 VT_001e [quick]=>'2' List::walk 0x2d60cf0 VT_001e [The]=>'1' [linkedlist count] will return a count of the number of items in a list [linkedlist walk] will perform a debug 'walk' of the linked list, starting at the beginning and iterating all nodes until the head is met Cleanup ------- It is not recommended to [return] from a linked script with ticol_list loaded and objects created unless you first clean-up using [lib ticol_list -unload] and/or specifically call [linkedlist unset] [linkedlist unset $handle] Destroys the linked list and renders the handle invalid. Attempts to use a handle after a call to unset will raise an exception. [linkedlist] objects are not subject to automatic garbage- collection on proc-exit [lib unload] destroys all created lists and reclaims their memory Example: set handle [linkedlist create] puts "Handle to list is $handle" set i 0 foreach {x} $qbf { linkedlist add $handle $x $i ++ i } linkedlist insert $handle jumps "rapidly" # Insert after jumps linkedlist insert $handle {} *start* # Insert at start linkedlist insert $handle fox dog # Add dog after fox linkedlist unset $handle fox # Remove fox linkedlist walk $handle linkedlist unset $handle Results: List 0x2d20fe0 10 item(s) List::walk 0x2d20cd0 VT_001e [The]=>'0' List::walk 0x2d20d20 VT_001e [quick]=>'1' List::walk 0x2d20d70 VT_001e [brown]=>'2' List::walk 0x2d21150 VT_001e [dog]=>'10' List::walk 0x2d20e10 VT_001e [jumps]=>'4' List::walk 0x2d21100 VT_001e [rapidly]=>'9' List::walk 0x2d20e60 VT_001e [over]=>'5' List::walk 0x2d20eb0 VT_001e [the]=>'6' List::walk 0x2d20f00 VT_001e [lazy]=>'7' List::walk 0x2d20f50 VT_001e [dog]=>'8' See also: list, array, stack, struct, error codes
list  Top  
list {vars...} Return a Tcl list from a series of variables. List creates an atomic parameter which can be supplied/chained into other parameters Example: call [dict create d colours [list orange red blue green purple]] Ticol supports a range of standard Tcl list commands Note that a plugin also offers standard linked lists: (See: linked list) See also: lappend, lreverse, lcount, lindex, llength, lassign, list_to_array, array_to_list, string, linked list, apply
List Processing Commands  Top  
See the following separate help topics: array_to_list Convert an array to a list lappend Append an item to a list lassign Anonymous functions. Apply a command to a list lcount Return the count of elements in a list ldepth Test the depth of a list (proc) lindex Return an item from a list list Return a well-formed Tcl list list_to_array Convert a list to an array llength Return the length of a list lmap Iteratively assign elements of lists to variables lrand Return a random element from a list lrange Return a range of items from a list lreverse Reverse the order of a list lsearch Search a list lset Set a list (deprecated) lsort Sort a list See also: Tcl lists
list_to_array  Top  
list_to_array <tcl-list> arrayname Converts a well-formed Tcl list into an array indexed by integer from element base 0. Example: set r [list_to_array $qbf out] puts "list_to_array returned $r item(s)" set s [array size out] for {set i 0} {[< $i $s]} {incr i} { printf "%i:\t%-40.40s\r\n" $i $out($i) } Result: list_to_array returned 9 item(s) 0: The 1: quick 2: brown 3: fox 4: jumps 5: over 6: the 7: lazy 8: dog See also: list
lrand  Top  
lrand <list> Returns a random element from a list Example: puts [lrand $qbf] Result: fox # (probably) See also: list
lrange  Top  
lrange <list> start finish|end|end-N [lrange] returns a range of list elements from the given list. The index values are 'base 0' values where 0 is the first element The end value may be specified using either 'end' for the last item or 'end-N' for the Nth item before the last Example: puts [lrange $qbf 1 3] # 2nd to 4th items Results: quick brown fox See also: list
lreverse  Top  
lreverse tcl-list Reverse a Tcl list. The list must be a well-formed Tcl list or simple space/tab-separated string Example: puts [lreverse $qbf] Result: dog lazy the over jumps fox brown quick The Example: set q "Now is the {time for all good men} to come to the aid of \ {the party}" puts [lreverse $q] Result: {the party} of aid the to come to {time for all good men} the is the is Now See also: list
Tcl Lists  Top  
A Tcl list is a sequence of characters, optionally separated by whitespace and grouped, where necessary by braces. To all intents and purposes a Tcl list is a human-readable string. Lists get complex when there are nested lists and nesting where braces protect space-separated lists. Sub-lists are likewise braced "This is a list" Placing this as a sub-list we get: "This is a list {This is a list}" As with Lisp, complex "tree-like" hierarchies can be represented using lists See also: list, lindex, lassign
load  Top  
# Unencrypted file load filename?.tcl? ?targetVarName? ?-password password? # Encrypted file load filename.tcx ?-password password? load -clear Load to the Console and Run --------------------------- Loads a Tcl file from the interpreter shell [load] with no arguments will display information about a loaded script Use [run] to run the file once loaded Use [dump] to display non-encrypted (obfuscated) loaded source code to the console and optionally to a Tcl variable Use [load -clear] to erase the script buffer (See also: clear) The [load] command does not clear the user-level variable table or non- system level consts (See: run, clear) [load] with a .tcx file and, if necessary a password via -password will load and decrypt a protected file. Load to a Variable ------------------ Optionally, a file may be loaded to a variable instead of the CLI. In this case any loaded program will be cleared and the preprocessed source loaded to the given variable. If the variable exists it will be overwritten. You can then run this source using [eval $varname]. The source is not returned or echoed by the [load] command Example: load test.tcl code # Load 'test.tcl to variable 'code' > Loaded test.tcl OK 1420 byte(s) # CLI acknowledgement eval $code # Runs the script at the CLI See also: run, dump, exit, clear
logo  Top  
logo fore ?back? ?x? ?y? Draw the Ticol logo See also: console, screen, puts
lmap  Top  
lmap {lambda-expression} list Iteratively assigns elements of one or more lists to variables, executes the lambda-expression argument, and collects the results into a new list. The lambda-expression will be an expression such as: {x {expr {$x * $x}}} # Given x return x * x [lmap] applied to an empty list will return an empty list [lmap] is defined as a native command in Ticol. This can also be emulated using the following code and using [apply]. The native command is more efficient performance-wise proc lmap {lambda list} { set result {} foreach item $list { lappend result [apply $lambda $item] } return $result } Example: puts [lmap {x {expr {$x * $x}}} {1 2 3 4 5}] Result: 1 4 9 16 25 Example: puts [lmap {x {return [string length $x]:$x}} {a bb ccc dddd}] Result: 1:a 2:bb 3:ccc 4:dddd See: https://wiki.tcl-lang.org/13920 http://www.tcl.tk/man/tcl/TclCmd/lmap.htm See also: lambda, list, apply
loop (Flow Control)  Top  
loop variable start limit ?increment? {code} A simple and efficient [for] loop. [loop] performs around 150% faster than [for] (excluding the code payload). loop i 0 10 2 {puts "Hello $i"} is equivalent to: for {set i 0} {< $i 10} {incr i 2} { puts "Hello $i" } [loop] takes 5 argument with an optional 6th argument to specify an increment. There is no need to brace all but the last argument [loop] takes a loop variable name as its 2nd argument, which will be initiated to the value of the 3rd argument. The final 'code' argument will be evaluated, incrementing the loop variable by 1 unless an increment value is specified as the optional 5th argument The increment argument may be positive or negative but not zero. If argument 3 is higher than argument 4 and no increment argument is given then an increment of -1 will be used The [loop] variable will always be the same as the limit variable on exit but the loop will execute for 'limit-start' times. So 'loop i 0 10' will execute 10 times, looping from 0 to 9 inclusive the same as [for] if 'start' is equal to 'limit' then the loop code body is never executed and 'limit' is returned in the loop variable [loop] supports [continue], [break] and [return] [loop] uses signed 64-bit integers as its loop arguments Example: # Automatic use of +1 increment loop i 0 5 { puts "i is $i" } puts "Final i is $i" # Automatic use of -1 increment loop i 5 0 { puts "i is $i" } puts "Final i is $i" Results: i is 0 i is 1 i is 2 i is 3 i is 4 Final i is 5 and i is 5 i is 4 i is 3 i is 2 i is 1 Final i is 0 Example: set i 0 proc foo {} { upvar i loop i 0 10 1 { puts "i is $i" if {== $i 5} {return $i} } } foo puts "i is $i" Result: i is 5 Example: loop i 0 10 1 { if {== $i 5} { # Skip 5 and increment past 6 ++ i continue } } puts "i is $i" Result: i is 10 See also: for, while, do, flow control
Listing Files  Top  
See: ls See also: file
ls  Top  
ls <filespec> ?-r? ?-ad | -af | -all? ?-la? ?-list ?var?? ?-array var? -r Recursive search (includes subfolders) -ad | -af Attributes: directory or file -all List all files -la List all file details -list ?var? Return in list format (variable not mandatory) -array var Return the list as an array (variable is mandatory) var Storage variable is optional (for either -array or -list) If var is given then a filespec must also be given Ordering/sorting is not supported. You can sort the result from -list Perform a Windows-compatible directory listing. The result can optionally be fed into a variable and optionally in Tcl list format using the -list arg If [option echo] is set to OFF then [puts] or [printf] must be used to display the results Forward-slash and backslash path separators are supported Example: option echo off ls *.txt -la -list a foreach {q} [lsort $a] { # For each file row entry foreach {i j k l} $q { puts "'$i' '$j' '$k' '$l'" } } Example: option echo on ls c:/temp/newdir ls c:/temp/newdir/ *.tcl Note: where the external Windows DIR command is used this requires backslash syntax and does not support Unix/Tcl style forward slash path separators See also: unlink, mkdir, chdir, getcwd
lsearch  Top  
lsearch ?option ...? list pattern Where ?options? are implemented as follows: -glob Default. Use a glob style match v's -exact (see: glob) -exact Make an exact match (case-sensitive) v's -glob matching -nocase Make a case-insensitive comparison -inline Return the value rather than the list index position -start N Start processing at list index item offset N An array base 0 value corresponding to [string index] where 0 is the first item in the list, 1 the 2nd etc... This offset will apply to the pre-sorted input list Values <0 are ignored and 0 assumed -not Invert the search. Return items which don't match 'list' Typically this will return a well-formed Tcl list -all Return a list of all items matching the search pattern of the first item. Output may be modified by -inline -sort Sort the input list before comparing (non-standard) -sorted Ignored. Ticol does not optimise sorted list searches -increasing Ignored. Used with -sort only - otherwise ignored -decreasing Ignored. Used with sort only - otherwise ignored -ascii Ignored. Ticol is ANSI-only lsearch matches the pattern argument to the list to find a match. If no match is found then -1 is returned If all matching style options are omitted then the default matching style is -glob. If more than one matching style is specified, the last matching style given takes precedence Sub-list matching is not yet supported Examples: lsearch {ba ze fi eo cu pa le ri} fred # => -1 lsearch {ba ze fi eo cu pa le ri} * # => ba lsearch -inline {ba ze fi eo cu pa le ri} * # => 0 lsearch -not {ba ze fi eo cu pa le ri} * # => -1 lsearch -all -not {ba ze fi eo cu pa le ri} * # => {} lsearch -inline -all -not {ba ze fi eo cu pa le ri} * # => {} lsearch {ba ze fi eo cu pa le ri} ?o # => 3 lsearch -inline {ba ze fi eo cu pa le ri} ?o # => eo lsearch -inline -all {ba ze fi eo cu pa le ri} ?e # => ze le lsearch -inline -glob -all {ba ze fi eo cu pa le ri} ?e # => ze le lsearch -inline -all -not {ba ze fi eo cu pa le ri} ?e # => ba fi eo cu pa ri lsearch -all -not {ba ze fi eo cu pa le ri} ?e # => 0 2 3 4 5 7 lsearch -glob -all -not {ba ze fi eo cu pa le ri} ?e # => 0 2 3 4 5 7 lsearch -exact -nocase {{a b c} {d e f}} {D E F} # => 1 lsearch -exact -nocase {{a b c} {d e f}} {p q r} # => -1 # Not found/-1 lsearch -exact -sorted -inline -start 4 {b z f e c p l r} {p} # => p lsearch -exact -sorted -start 4 {b z f e c p l r} {p} # => 2 lsearch -inline -list -exact\ -not -start 0 {a "Hello there" x y z} {x} # => "a {Hello there} y z" lsearch -exact -inline -all -not {a c b c a b c} c # => a b a b lsearch -exact -all -not {a c b c a b c} c # => 0 2 4 5 lsearch -exact -inline -all {a c b c a b c} c # => c c c lsearch -exact -all {a c b c a b c} c # => 1 3 6 lsearch -exact -all -start 2 {a c b c a b c} c # => 3 6 Note that [lsearch] does not 'eval' it's arguments... lsearch -all -inline {$qbf} * # => $qbf (correct) lsearch -all -inline {list $qbf} * # => list $qbf (correct) lsearch -all -inline "$qbf" * # => quick brown ... lsearch -all -nocase -inline $qbf t* # => The the See also: list, lappend, lindex
lset  Top  
lset target-variable source-variable|source-string A Proccrustean command. Inserts a source string or variable into the target, left-aligned. [lset] is based on the common BASIC command Any excess length in the source is stripped to fit. Example: set s [makestr 20 *] lset s "hello" puts $s Result: hello*************** Example: (Blank out part of a string) set s "0849 666 616" lset s " " puts "'$s'" Result: ' 666 616' See also: rset, mid, strstr, string
lsort  Top  
lsort list ?-ascending | -descending? ?-nocase? ?-integer? ?-real? Sorts a Tcl list in ascending or descending order, optionally ignoring case, comparing as integer, or comparing as a double value lsort does not support -step. -index, -stride etc. Braced list sub-items are supported lsort will perform a simple sort on a list. e.g. foreach x [lsort [array get env]] {puts $x} Example: set ls [lsort { {{d e m o} 34512} {{c o d e} 54321} {{v e r y} 13254} {{b i g} 12345} {} } ] puts "=$ls=" Result: ={{b i g} 12345} {{c o d e} 54321} {{d e m o} 34512} {{v e r y} 13254}= See also: list
makestr  Top  
makestr length ?char? ?var? makestr length makestr length char makestr length char var makestr length -- var Creates and allocated a string of given length, optionally filled with a specified character. If more than one fill character is passed then only the first character of the fill-string will be used. The default fill character is a space. Don't mix [makestr] with [malloc] for standard Tcl variables. Variables created with [makestr] are standard Ticol variables and will be automatically released Literal numeric fill characters will be used if passed: e.g. [makestr 5 0] => "00000" Low and high order ASCII characters may be passed using [chr N] Examples: makestr 5 [chr 0x21] => "!!!!!" makestr 5 [chr 42] => "*****" makestr 5 [char 0b101011] => "+++++" [makestr] does not accept the value [chr 0] Ticol Tcl does not like null characters within strings. Use [memset] to zeroise the contents of a Tcl string buffer. If variable is specified and a filler-character omitted then a dummy argument then '--' should be used to skip this argument Example: set buf [makestr 10] puts "-'$buf'-" Result: -' '- Example: makestr 10 -- buf puts "-'$buf'-" Result: -' '- Example: set buf [makestr 1024] # Allocate a string buffer of 1024 spaces memset buf [chr 0] 1024 # Set all characters to [chr 0] See also: chr, asc, memset, calldll
malloc, free  Top  
address [malloc byte-count] free address|variable [malloc] allocates memory using the C malloc() function from the heap memory manager. An address to a heap-allocated block of memory is returned This address is freed by a call to [free] using the same address. The address argument or variable value must be > 0 [malloc] and [free] should be used with extreme care and are intended for use only with Ticol structs and for interfacing with [calldll] Don't use [malloc] for standard Tcl variables. Used correctly, [malloc] will be stable and not leak memory. Memory blocks allocated with [malloc] are not automatically freed. You must call [free] on the address returned by [malloc] If [free] is passed the name of a variable then the variable will be reset to "0" on successful free, otherwise you must take care to reset any variables to avoid pointer re-use. Example: set ptr [malloc 10] puts "malloc ptr is $ptr" set source Hello # MUST copy length of string + 1 to copy the NULL char memcpy $ptr [addressofb source] 6 puts "ofaddressb ptr =='[ofaddressb $ptr]'" free $ptr Result: malloc ptr is 33394064 ofaddressb ptr =='Hello' See also: memcpy, memset, calldll
man - Ticol Manual  Top  
The Ticol manual is a simple text file which is formatted using a method which can break the file into easily-accessible sections. Topic markers are phrases which must be prefixed by a dot character and the dot must be the first character on a line The format is as follows --------------------------------------------- .. comment and end of section marker .topic key .another optional topic key .yet another optional key topic title Manual text... ..code <some Tcl code> ..end ..colour <some text ..end ..end (of topic section) --------------------------------------------- Any text following ".." will be ignored See also: ticol
map  Top  
map {token-pair-list} variable|string-literal ?-nocase? string map {token-pair-list} variable|string-literal ?-nocase? Remaps strings using a paired list. The list-pair must have even parity If a variable is given for the last argument then the variable contents will be reassigned. In either case the remapped string is returned If there are no valid mappings then the original input string is returned Mapping is expensive on long strings where no multi-char remaps are found and where a large input-map is given Also implemented as [string map] Examples: puts "Result is: [string map {abc 1 ab 2 a 3 1 0} 1abcaababcabababc]" puts "Should be: 01321221" puts "Result is: [string map {1 0 ab 2 a 3 abc 1} 1abcaababcabababc]" puts "Should be: 02c322c222c" puts "Result is: [string map {1 0 ab 2 a 3 abc 1} frederick]" puts "Should be: frederick" set s "1<2 2>1 2≥2 2≤2" puts "Result is: "[string map -nocase { "<" "<" ">" ">" "≤" "<=" "≥" ">=" } $s] puts "Should be: 1<2 2>1 2>=2 2<=2" See also: map, apply, string
max, min  Top  
value [max x y] value [min x y] Return the maxima or minima of two numeric values either double or integer. String arguments are not accepted. Either a double or integer value is returned These commands are also available as expression functions max() and min() You can also access these in command-style using [funct max x y] and [funct min x y] Example: puts [max 3 7] puts [max 3.0 7.0] puts [max foo bar] # Invalid string literals Results: 7 7.000000000000000 0 See also: functions, math
mid (Set String Middle)  Top  
integer [mid variable string|variable startpos ?length?] Set the middle of a variable to a portion of a 2nd variable or string literal If the length parameter is omitted then the entire source string will be copied to the target (or as much as will fit) Example: set q $qbf puts [mid q cat 17 3] puts $q Results: 3 The quick brown cat jumps over the lazy dog See also: mids, left, right, rset, lset, strstr, string
mids (Return a String Midsection)  Top  
string [mids string|variable start length] Return a mid-section of a string 'start' is a base 1 index value. The length argument is optional. If omitted then the entire string from 'start' will be returned Use [index <string> n] instead of [mids <string> n 1] Example: if {eq [mids $data $i 2] "/*" } { incr i 2 set in_comment $true } Example: puts [mids "hello world" 7] Result: world Example: puts [mids "hello world" 2 4] Result: ello Example: set s "Hello" puts [mids $s 3 2] Result: ll See also: mid, left, right, rset, lset, strstr, string, index
mkdir  Top  
bool [mkdir path] bool [md path] Create a directory (folder) See also: unlink, file, ls
md5  Top  
string [md5 string] Return the 32-character MD5 value of a string Example: puts [md5 $qbf] Result: 9e107d9d372bb6826bd81d3542a419d6 Example: MD5 hash-based random number generator set seed $pi # Could instead use [clock] set counter 0 # Global/static counter option expression on # Use expressions for flow-control proc hashrnd {lo hi} { # Hash-generated random number upvar seed # Not recursive. No level given upvar counter incr counter set r [md5 [+ $counter $seed]] # Get an MD5 value set q "0x" # Not a typo. Literal 0x prefix append q [mids r [% $counter 24] 8] # Slice a section of the MD5 return [expr "$q % (($hi-$lo)+1)+$lo"] # Evaluate as hexadecimal } option expression on for {set i 0} { $i < 10000} {incr i} { puts "hashrnd 10..10000:\t[hashrnd 10 10000]" } See also: md5 batch example, md5_file, protection, MD5 Verification, upvar, append
MD5 Batch Example  Top  
This is a simple batch file which will run a Ticol script depending on a successful MD5 check. You will need to know the MD5 signature in advance and if the signature changed then you would need to update the script @echo OFF set FILE=hello.tcx set MD5=C7A37A87B4E6B7D311C0BF430844B94A for /F "tokens=*" %%i in ('ticol.exe /md5 %FILE%') do ( set RESULT=%%i ) rem echo DEBUG: MD5 result is: %RESULT% if /I %MD5% equ %RESULT% ( hello.tcx ) else ( echo MD5 failure. Cannot execute %FILE% echo MD5 is: ticol.exe /md5:%FILE% /crlf echo Should be: echo %MD5% ) See also: md5
md5_file  Top  
string [md5_file filename] Return a 32-bit MD5 hex-value for a given filename. Performance is reasonable even on large ISO images. This should match the MD5 of any external MD5 EXE program Example: puts [md5_file ticol.exe] Result: 82bef32153657dc25dc439a3b500a614 See also: md5, protection, MD5 Verification
MD5 Verification  Top  
The following skeleton batch file may be used to generate a mechanism to test encrypted Ticol TCX files before execution. This method requires that the MD5 value be entered into the batch script ---------------------------------------------------------- @echo OFF set FILE=hello.tcx for /F "tokens=*" %%i in ('ticol.exe /md5 %FILE%') do ( set RESULT=%%i ) rem echo DEBUG: MD5 result is: %RESULT% if /I 314ebb9f13a413ab4419fc9d5691011d equ %RESULT% ( ticol.exe hello.tcx ) else ( echo MD5 failure. Cannot execute %FILE% ) ---------------------------------------------------------- See also: md5, md5_file
mean  Top  
double [mean value ?value? ...] Calculate the arithmetic mean of a series of values and return the result as a floating point value. Individual values and the total are evaluated as floating point doubles with a double return (double 64 bit signed 1.7E +/- 308 (15 digits of precision)) Example: puts [mean 1.2 19.8 22.7 4343 40.5 19.4 222] Result: 666.942857142857060 See also: math functions, big mean
mem_used  Top  
integer [mem_used ?pid?] Show the memory used by the current Ticol process or any other process in bytes This will be the same amount of memory as displayed in Task manager for "mem usage". This can be used to track application memory use for fault- finding etc. There should be initial memory allocation as routines are set-up, but this should not continually increase. The underlying memory- manager may also fluctuate but the usage trend should remain broadly stable Error returns: On error mem_used returns a negative value indicating one of the following: -1 Can't load PSPAPI.DLL -2 Can't get procaddress for "GetProcessMemoryInfo" -3 Can't open given Process ID (usually insufficient permissions) Example: set memstart [mem_used] set last 0 set this 0 set iters 0 while {1} { # command to check ######################## some-valid-tcl-function ########################################### set this [mem_used] if {!= $last $this} { # Next line ends with a line-continuation character... puts "Leaked [/ [- $this $memstart] 1024] Kb\tTotal used: \ [comma [/ $this 1024]] Kb\t$iters iteration(s)" } set last $this incr iters } See also: Ticol, debugging
memcpy  Top  
memcpy target-address source-address byte-count ?-t? [memcpy] calls the standard "C" memcpy() routine to copy a block of memory from one location to another. [memcpy] can take a dereferenced struct member name as the target, or an address of a block of memory allocated by [malloc]. The copied block may not be null-terminated and therefore may not be safely printable. [memcpy], [malloc] and [free] should be used with extreme care and are intended for use only with Ticol structs and for interfacing with [calldll] [addressofb] can be used to return the binary/byte address of the allocated buffer in a Ticol variable (similar to StrPtr() in Visual BASIC) [ofaddresb] is used to dereference a Ticol variable which stores a memory address Example: set ptr [malloc 10] puts "malloc ptr is $ptr" set source Hello memcpy $ptr [addressofb source] 6 # MUST copy length of string + 1 to copy the NULL char puts "ofaddressb ptr =='[ofaddressb $ptr]'" free $ptr Result: malloc ptr is 33394064 ofaddressb ptr =='Hello' If the -t argument is used then a null terminator will be substituted for the last byte copied. Thus x1 byte of the source is discarded Example: set a [malloc 256] # Allocate a large buffer set s "hello" # Set a standard Tcl variable memcpy $a [addressofb s] 5 -t # Copy 5 bytes. Make the last byte NULL puts "a is '[ofaddressb $a]'" # Print the binary data at address a Result: a is 'hell' See also: malloc, free, memset
memset  Top  
memset varName characterNumber length [memset] may be used to format or zeroise buffers such as those created using [makestr] when interfacing with external DLLs using calldll* [set] will copy only the usable part of a string, not the full, allocated buffer size. Thus using [set] with [makestr] and [chr 0] could create an under-sized target buffer string and cause instability with [calldll] [memset] will clear memory only up to the allocated length of the string it will not clear/set the internal/terminating null character of any string It is allowable to call memset with a calculated address offset Avoid using memset with Tcl variables other than via calldll* Example: set buf [makestr 1024 " "] # Creates a buffer of 1024 spaces memset buf 0 1024 puts "'$buf'" Result '' # Buffer has been allocated to 1024 chars but set to [chr 0] Example: set ptr [malloc 200] memset $ptr x 10 memset [+ $ptr 5] "q" 2 # Write to offset ptr + 5 puts $ptr Result: xxxxxqqxxx See also: calldll, malloc, free, memcpy, makestr
Some Common Mistakes  Top  
Here are some of the most common mistakes when first using Tcl. Particularly when coming from a C/C++ background: Failure to Use [option expression off] -------------------------------------- When using non-expression (Tcl command format) arguments to flow-control Using 'VB' Style Variable Syntax -------------------------------- Using var$ instead of $var Example: set i 0 for {[> i$ 10]} { ... # Wrong set i 0 for {[> $i 10]} { ... # Correct Failure to Use [upvar] for [proc] Arguments ------------------------------------------- When passing by name (by reference) rather than by value, you must use [upvar] to create a reference to the variable. If a [proc] is called by another [proc] then [upvar] giving no level reference is sufficient as each [proc] call is one level higher than the next. Example: proc foo x { # Wrong. The variable won't be referenced return [* $x 1] } proc foo x { # Correct upvar x return [* $x 1] } proc foo x { # Correct (using an alternate local variable) upvar x y return [* $y 1] } Failure to clear/delete variables or procs ------------------------------------------ A conflicting proc or variable exists somewhere else in the code, possibly within an external file. It is good practise to clear procs and variables as soon as you have finished within them, particularly when working in the global (root) scope. This can be done safely using: undef procname -nocomplain unset variablename -nocomplain [clear] will clear all locally created variables A useful shortcut scriptlet is as follows: This will remove all single letter variables 'a' to 'z'. The {*} will cause each list element to be passed to [unset] as a separate argument: unset {*}[split [range a-z]] -nocomplain Failure to Evaluate [proc] Returns ---------------------------------- Example: return * $i $i Should be: return [* $i $i] Reason: [*] is a command which must be evaluated. The first example, instead, supplied 3 invalid arguments to the [return] command. i.e. [return * $i $i]. Square brackets cause an advance recursive evaluation, thus, if i was set to 3 then [return [* $i $i]] would be interpreted as [return 9] Using [static] where [set] is required ---------------------------------------- # In root-level scope static foo 23 assert $foo {== $_ 23} -v # PASS static foo 11 assert $foo {== $_ 11} -v # FAIL set foo 11 assert $foo {== $_ 11} -v # PASS Incorrect Options Setting with [for] etc. ---------------------------------------- Example: variable not found after [for] loop initiation Should be: for {[set i 0]} ... or option expression off for {set i 0} ... or: TICOL.INI -> ForInitAllowsExpression=FALSE for {set i 0} ... Reason: Standard Tcl forces the first (intitator) statement of a [for] loop to be a Tcl command (via [eval]). Ticol Tcl allows the first command to be an expression if configured in TICOL.INI using: ForInitAllowsExpression=<boolean> Incorrect [option expression] Setting ------------------------------------- Example: option expression on if {file exists test.tcl} { ... } Should be: if {[file exists test_enum.tcx]} { or option expression off if {file exists test.tcl} { ... } Reason: If option expression is on, either by command or INI config file, then the arguments to flow-control commands such as [if], [for] etc. will be interpreted as math expressions. If this is the case any command must be evaluate (called) by wrapping in square brackets. -- Example: option expression off for {set i 0} {$i < 10} {incr i} { ...} Should be: option expression off for {set i 0} {< $i 10} {incr i} { ...} or: option expression on for {[set i 0]} {< $i 10} {incr i} { ...} Reason: With option expression off, arguments to flow-control commands such as [for], [while] etc. will not be evaluated in "expression format" but in [eval] format. The command expression in the first argument will have no effect With 'option expression on' '{set i 0}' is not a valid expression Misplaced End of Line Brace Characters -------------------------------------- C/C++ and C# programmers may inadvertently assume that the following brace style can be used with Tcl. It cannot. Opening braces mark delayed expansion wrappers for commands. CRLFs are valid within delayed brace wrappers but not within argument tails outside curly braces Example: (wrong - opening brace must be on same line) if {== $i 10} { puts "i is 10" } else { puts "i is not 10" } Should be: (correct - opening brace on same line) if {== $i 10} { puts "i is 10" } else { puts "i is not 10" } or if {== $i 10} {puts "i is 10"} else {puts "i is not 10"} Reason. The first expression is "C++"-like but illegal. The CRLF marks the termination of the command [for] and it is prematurely truncated Failure to Separate Commands by Whitespace ------------------------------------------ Example: option expression on for{set i 0}{$i < 10}{incr i}{ ...} Should be: option expression on for {set i 0} {$i < 10} {incr i} { ...} Reason: Tcl is a discrete, command-based language. Spaces are required between commands and grouped arguments (those wrapped in braces) Failure to Protect Strings With Double Quotes --------------------------------------------- Strings need not be wrapped in double-quotes but faiure to do so leaves a path open for frustrating errors. e.g. puts [ftp $hostname ls /tools/* -u admin -p xxxxx] Should be: puts "[ftp $hostname ls /tools/*.zip -u admin -p xxxxx]" Since the unquoted '/*' in '/*.zip' will be interpreted as a long comment start. Quoting will prevent this. Misplaced Double Quotes ----------------------- If an extra, unescaped double quote is embedded in a properly quoted string then this error may be issued: "Empty file preprocessing source file" Possibly with a preprocessor line number. Work backwards from the line number to check for strings with embedded/unescaped double quotes Incorrect Delimiting of Command Arguments ----------------------------------------- Bad example: puts The quick brown fox jumps over the lazy dog Should be: puts "The quick brown fox jumps over the lazy dog" or: puts {The quick brown fox jumps over the lazy dog} or: puts Thequickbrownfoxjumpsoverthelazydog Reason: Arguments to Tcl commands such as [puts] must be either wrapped in double- quotes (where appropriate) or grouped using curly-braces. The first example instead supplies 9 independent and invalid arguments to [puts]. Arguments are also implicitly grouped if there is no intervening whitespace, thus an argument which contains no whitespace need neither be braced or quoted Using [else if] Instead of [elseif] ----------------------------------- Example: (wrong) if {[rnd 0 1]} { puts "True" } else if {[== [rnd 2 3] 3] } puts "Three" } Example: (correct) if {[rnd 0 1]} { puts "True" } elseif {[== [rnd 2 3] 3] } puts "Three" } Reason: There is no [else if] sub-command Using [then] Within [if] ----------------------------------- Example: (wrong) if {[rnd 0 1]} then { puts "True" } Example: (correct) if {[rnd 0 1] { puts "True" } Reason: There is no [then] command in the Ticol [if] statement See also: optimisation, performance
movefile  Top  
bool [movefile sourcefile targetfolder ?-y?] If target is specified as a foldername, ensure it ends with a trailing '\' character or it will be assumed to be a new filename [movefile] can rename files as well as move them Forward-slash characters '/' may be used as path separators to avoid false escape issues with '\' characters Examples: movefile test.txt test\\ # Move into subfolder 'test' movefile test.txt test/ # Move into subfolder 'test' movefile test.txt test.dat # Rename file as test.dat See also: copyfile, file
msgbox  Top  
msgbox message ?title | -? ?flags? Displays a standard Windows messagebox dialogue A title is optional and may be omitted or specified as blank using the '-" placeholder in order to supply a flag value with no title. msgbox returns Windows-standard numeric return-codes Return values: yes 6 no 7 Flag values: 0x0 MB_OK The message box contains one push button: OK This is the default 0x1 MB_OKCANCEL The message box contains two push buttons: OK and Cancel 0x2 MB_ABORTRETRYIGNORE The message box contains three push buttons: Abort, Retry, and Ignore 0x3 MB_YESNOCANCEL The message box contains three push buttons: Yes, No, and Cancel 0x4 MB_YESNO The message box contains two push buttons: Yes and No 0x5 MB_RETRYCANCEL The message box contains two push buttons: Retry and Cancel 0x6 MB_CANCELTRYCONTINUE The message box contains three push buttons: Cancel, Try Again, Continue Use this message box type instead of MB_ABORTRETRYIGNORE 0x10 MB_ICONSTOP A stop-sign icon appears in the message box 0x10 MB_ICONERROR A stop-sign icon appears in the message box. 0x10 MB_ICONHAND A stop-sign icon appears in the message box. To indicate the default button, specify one of the following values 0x20 MB_ICONQUESTION A question-mark icon appears in the message box. The question-mark message icon is no longer recommended because it does not clearly represent a specific type of message and because the phrasing of a message as a question could apply to any message type. In addition, users can confuse the message symbol question mark with Help information. Therefore, do not use this question mark message symbol in your message boxes. The system continues to support its inclusion only for backward compatibility. 0x30 MB_ICONWARNING An exclamation-point icon appears in the message box. 0x40 MB_ICONINFORMATION An icon consisting of a lowercase letter i in a circle appears in the message box. 0x40 MB_ICONASTERISK An icon consisting of a lowercase letter i in a circle appears in the message box. 0x0 MB_DEFBUTTON1 The first button is the default button. MB_DEFBUTTON1 is the default unless MB_DEFBUTTON2, MB_DEFBUTTON3, or MB_DEFBUTTON4 is specified. 0x100 MB_DEFBUTTON2 The second button is the default button. 0x200 MB_DEFBUTTON3 The third button is the default button. 0x300 MB_DEFBUTTON4 The fourth button is the default button. To indicate the modality of the dialog box, specify one of the following values. 0x0 MB_APPLMODAL The user must respond to the message box before continuing work in the window identified by the hWnd parameter. However, the user can move to the windows of other threads and work in those windows Depending on the hierarchy of windows in the application, the user may be able to move to other windows within the thread. All child windows of the parent of the message box are automatically disabled, but pop-up windows are not MB_APPLMODAL is the default if neither MB_SYSTEMMODAL nor MB_TASKMODAL is specified 0x1000 MB_SYSTEMMODAL Same as MB_APPLMODAL except that the message box has the WS_EX_TOPMOST style. Use system-modal message boxes to notify the user of serious, potentially damaging errors that require immediate attention (for example, running out of memory). This flag has no effect on the user's ability to interact with windows other than those associated with hWnd 0x2000 MB_TASKMODAL Same as MB_APPLMODAL except that all the top-level windows belonging to the current thread are disabled if the hWnd parameter is NULL. Use this flag when the calling application or library does not have a window handle available but still needs to prevent input to other windows in the calling thread without suspending other threads. 0x4000 MB_HELP (Not actively supported) Adds a Help button to the message box. When the user clicks the Help button or presses F1, the system sends a WM_HELP message to the owner You can use [enum] to set these const values as follows: enum { MB_OK MB_OKCANCEL MB_ABORTRETRYIGNORE MB_YESNOCANCEL MB_YESNO MB_RETRYCANCEL MB_CANCELTRYCONTINUE MB_DEFBUTTON1 = 0 MB_ICONSTOP = 0x10 MB_ICONERROR = 0x10 MB_ICONHAND = 0x10 MB_ICONQUESTION = 0x20 MB_ICONWARNING = 0x30 MB_ICONINFORMATION = 0x40 MB_ICONASTERISK = 0x40 MB_DEFBUTTON1 = 0 MB_DEFBUTTON2 = 0x100 MB_DEFBUTTON3 = 0x200 MB_DEFBUTTON4 = 0x300 MB_APPLMODAL = 0 MB_SYSTEMMODAL = 0x1000 MB_TASKMODAL = 0x2000 MB_HELP = 0x4000 } Example: msgbox "Yes or no" "Question" [| 4 32] Result: 7 Example: option autoexec off option escape on msgbox [join [split $qbf " "] "\n"] "Choose" 36 Result: Messagebox which displays each word on new line with Yes, No buttons See also: box, getfileopen, getfilesave, enum
Multiple Commands  Top  
As with C/C++, multiple commands may be separated using an intervening semi-colon (;) This is particularly useful when calling Ticol from the Windows console Example: set a 22;set b 7.0;set p [expr $a/$b];puts "Pi is $p" Command line example: # Run with no autoexec ticol.exe ; "set a 22;set b 7.0;set p [expr $a/$b];puts {Pi is $p}" /na See also: syntax, Tcl, Ticol
Namespaces and Scope  Top  
Ticol, as a minimal Tcl implementation, does not support full Tcl namespaces However they may be emulated by prefixing procedure and variable names with namespace tag value and double-colon. You will need to use the full, emulated namespace name of the procedure when calling as a namespace context cannot be set Care should be taken to avoid misinterpretation of namespaces by adjacent variables or punctuation in strings. This may require enclosing the tag value in curly-braces. Note that the double-colon 'namespace' scope prefix should not be confused with global scope use (e.g. '::var' and '$::var') If you wish to use colons adjacent to variables you must enclose the variable name in braces ... Example: set s "I am a pretty string" puts "${s}::Punctuated::By colons" # Correct puts "$s::Punctuated::By colons" # Incorrect Result: I am a pretty string::Punctuated::By colons eval: No variable 's::Punctuated::By' in the current scope Here is a demonstration of procedure and variable namespace emulation: Example: set local::a 12345 # We will overwrite this using the proc proc math::div {x y} { # Example divide procedure upvar local::a a set a "div was called" if {!= $y 0} { [/ $x $y] } else { return 0 -code error } } set a [math::div 22 7.0] puts $a puts "\$local::a=$local::a (Should say \"div was called\")" Result: 3.142857142857143 $local::a=div was called (Should say "div was called") Example: An example of scoped variable use set scope fred set ${scope}::j 0 ++ ${scope}::j puts "fred is $fred::j" Result: fred is 1 This example of scoped variable use using pseudo-namespaces is more complex in that the nested-resolution of an indirect scope variable (fred) and subsequent dereference is problematic without the use if [set] to dereference since the outer '$' reference will be evaluated before the inner reference unless a [command] is used [set] can echo or 'dereference' a variable as well as set it Example: option expression on set scope fred for {set ${scope}::j 0} {[set ${scope}::j] < 500} {++ ${scope}::j} { set q [set ${scope}::j] if {[is_mod $q 100]} { puts "${scope}::j is $q" } } Results: fred::j is 0 fred::j is 100 fred::j is 200 fred::j is 300 fred::j is 400 See also: proc
Multi Line Commands  Top  
Providing that a newline is not encountered before an opening brace or bracket, the contents of a command or expression can be spread across multiple lines. This is normal for braced multiline expressions but is also true for commands which are enclosed in square brackets Example: # Single-line command puts [eval "/ 22.0 7.0"] # Multi-line command puts [ eval "/ 22.0 7.0" ] See also: command separator
Networking Commands  Top  
See the info command for various commands for querying the local network External DLLs such as ping32.dll may be dynamically linked-to and used See also: info, ping, ftp, dns, arp, dhcp
new  Top  
new sourceobject newobject Create a new and empty instance of an object. Source/template objects have no special designation. Any handled object can be used as the source template. Currently, [new] detects and handles only structs For structs, the total binary struct size, field count, field names and field widths are copied. Field names will be distinguished (decorated) with the name prefix of the struct parent variable name Structs are binary-compatible and may be used with [calldll_*] and passed to the Windows API and other DLLs. Each Tcl field variable is mapped to a binary-offset in the struct's data-block [new] is not implemented for arrays, standard variables or other data types as it would serve no useful purpose Manual deletion of objects created using [new] is not required. Garbage collection is automatic Example: struct s {{field1 10} {field2 20}} # Create a source struct struct set s.field1 Hello # Assign some data struct set s.field2 World new s s_new # Copy s as s_new dump s_new # Display debug info Results: (Displays a blank struct) var type is 3 v->val is 36811792 struct 's_new' level 0 (0x231b430) data @36811792 (0x231b410) 30 byte(s), 2 member(s) + 1:'s_new->s_new.field1' => 36811792 (0x231b410) 10 byte(s) + 2:'s_new->s_new.field2' => 36811802 (0x231b41a) 20 byte(s) Address 0 1 2 3 4 5 6 7 8 9 A B C D E F ASCII -------- ----------------------- ----------------------- ---------------- 0231b410 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 ................ 0231b420 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 ................ * Var 0::'s_new' has no parents See also: struct, set
newline  Top  
newline ?count? Prints a new line to the console. Equivalent to [puts ""] or [printf "\r\n"] The default is to issue one newline (CRLF pair). An optional argument may specify the number of new lines to print [newline] offers no particular performance advantage but may make code easier to read See also: puts
not (Bitwise and Logical)  Top  
integer [! expression] integer [! string] integer [~ expression] The '!' operator returns a logical true/false as 1 or 0. [!] will also operate on non-numeric strings as a test for an empty string. An empty string or empty list will return true (1), otherwise false. Standard number detection rules apply. Anything which is not a valid number will be interpreted as a string The bitwise not '~' operator performs a bit-inversion on the expression and returns the result Example Returns puts [expr "!(-12 -3)" ] 0 puts [expr "! $true" ] 0 puts [expr "! $false" ] 1 puts [expr "! -12 -3" ] -3 puts [expr "~(-12 -3)" ] 14 puts [~ 0] -1 puts [~ 1] -2 puts [! Hello] 0 puts [!] 0 puts [! ""] 1 puts [! {}] 1 Example: set s {} if {! $s} { puts "s is empty" } Result: s is empty Example: set s Hello if {! $s} { puts "s is empty" } else { puts "s is not empty" } Result: s is not empty Example: set ip_address if {! $ip_address} { puts "ip_address is empty" } else { puts "\$ip_address is not empty" } Result: $ip_address is not empty See also: expr
now  Top  
double [now ?-ctime?] Returns the current date/time as a VB-compatible 8-byte double value or, if the -ctime argument is used, as a C/Unix long integer Example: puts [now] # VB data format puts [now -ctime] # C/C++ data format Result: 42933.993946759263000 1500331879 [double_to_ctime] can also convert... Example: clock format [now -ctime] clock format [double_to_ctime [now]] Result: Tue Mar 03 22:57:35 2015 Tue Mar 03 22:57:36 2015 See also: double_to_ctime, ctime_to_double, date, time, clock
Number Formats  Top  
Number formats understood by various commands including [eval] and [expr] are as follows: Type Format Signed? Bytes Interpretation ------------------------------------------------------------------- decimal integer ?+|-0..9? signed 8 64-bit decimal float ?+|-0..9.NN? signed 8 64-bit double hexadecimal 0x?0..9|A..F? unsigned 8 64-bit octal 0o?0..7? unsigned 8 64-bit binary 0b?0|1? unsigned 8 64-bit All numbers are evaluated as 64-bit wherever possible. Conversion to floating point is automatic where necessary for real numbers. Floating point conversion is handled as an 8 byte double which has a precision of 15 decimal places. Tcl v9 octal number identifiers are implemented, which require 0oNN format See: http://wiki.tcl.tk/498 Real numbers are converted on the following format basis: [whitespace] [sign] [digits] [.digits] [ {d | D | e | E }[sign]digits] All Tcl numbers are stored internally as strings and converted in real time Casts are possible to coerce and convert between number types and conversion routines are available See also: cast, type, math, expr, eval, functions, ticol inttooct, intothex, inttobin
open, file open  Top  
handle [open filename mode] handle [file open filename mode] Returns an integer handle to the open file if successful, otherwise 0 The mode parameter is a string made up of character flags r, w, a and + and works in the same way as for C/C++. [try...catch] can be used to detect exceptions opening invalid files r read mode w write mode a append mode + update mode Example: set fp [open "filename" r] close fp Example: set fp [open "input.txt" w+] puts $fp "test" close $fp set fp [open "input.txt" r] set data [read $fp] puts $data close $fp Example: try { set fp [open "nosuch.txt" w+] } catch { puts "File not found" } Result: File not found Example: set filename "licence.txt" try { set fp [open $filename "rb"] } catch { die "Can't open $filename" } set line 0 while {! [file eof $fp]} { file gets $fp s puts $s ++ line } close $fp See also: file gets, file eof, close, gets
dll_close  Top  
handle [dll_open dllname] dll_close handle Loads a DLL by name and returns a handle to the loaded DLL file. This handle can then be used to call the calldll* series functions Note that handle variables should be set to zero after a call to dll_close Example: set handle [dll_open mydll.dll] set s [calldllstr handle some_string_function] dll_close $handle See also: dll_open, calldll
option (Runtime Configuration Options)  Top  
Programmatically set various Ticol configuration options at runtime option autoexec ?on|off|push|pop? option breakpoint ?on|off|push|pop? option echo ?on|off|push|pop? option escape ?on|off|push|pop? option expression ?on|off|push|pop? option preprocessor ?on|off|push|pop? option stacktrace ?on|off|push|pop? Note that using Ticol as a manual Windows CLI shell requires that "C"-like escape characters be correctly processed. Thus if autoexec is ON then C-escapes will not be interpreted but passed-through literally. Thus paths such as "\first\second\third" will not encounter an embedded \t tab character A script cannot change the current state of the CLI settings. These will be restored after a [run] command To use C-like escape sequences at the CLI use the following: option autoexec off option escapes on Autoexec should be OFF when running Tcl scripts. Use [exec] or [spawn] to launch programs safely option ------ option with no arguments displays the current full status: Subcommand Arg Comment ----------------------------------------------------------------------- autoexec on: Autoexec unknown (disables CLI C-like escapes if ON) echo off: Echo command and error results escape off: C-like escapes. (Disabled in CLI by autoexec) expression on: Flow control uses [expr] preprocessor on: Macro preprocessor push and pop ------------ The push and pop options save or restore the current setting push may be combined with on or off. e.g. [option echo push off] This is useful for procedures which may need to alter the global setting temporarily then restore it to its prior condition on exit Only one save level is currently supported Combined commands ----------------- Combined commands are possible which save and set a setting Example: proc foo {} { option expression push on # ... some proc code option pop } Command Arg Comment ------------------------------------------ autoexec on: Autoexec unknown echo off: Echo command and error results escape off: C-like escapes expression off: Flow control uses eval PreProcessor on: Macro PreProcessor stacktrace on: Debug error stacktrace (when enabled) breakpoint on Debug breakpoints (when enabled) via [halt] option <command> ---------------- Returns the current status as either 'on' or 'off' e.g. 'option echo' -> 'on' option autoexec --------------- Turns the automatic execution of Windows programs on or off If turned off then this enables the Tcl [unknown] feature If turned on then this will disable "C" escape characters in the CLI See: help unknown option echo ----------- Turns the Command Line Interpreter (CLI) results echo on or off The [catch] command requires option echo off for effective use If you prefer to see error messages within program output as well as command output, enable option echo within the INI configuration file Without [option echo off] all console output could be echoed twice option escape ------------- Turns processing "C"-like escape characters such as \t, \n etc. on or off If turned on will disable autoexec since backslashes can no longer be safely passed to Windows See: help escape option expression ----------------- Turn on or off the implicit use of the [expr] command when evaluating while, for and if flow-control statements In an interpreter, expression handling is more complex and far-slower than using native Tcl commands but expressions may be more convenient to use. Thus a method is offered of switching between the two formats Caution: When set to "on", expr with infix operators will be used instead of the default eval which uses prefix operators Strings should always be wrapped in double-quotes. In particular strings containing math symbols will be interpreted as a math expression with option expression on Example: option expression on if {file exists test/} { # BAD. [file] not an expresion if {[file exists "test/"]} { # CORRECT (e.g. + 2 2). Enabling [expr] will cause prefix expressions to fail as the first term (here, '+') will be evaluated incorrectly Thus: if {== $s 123} will be interpreted as if {expr "== $a 123"} with option expression ON and will therefore fail. The behaviour can be overridden using a bracketed argument: if {[== $a 123]} or by toggling option expression off then on again If the 2nd argument is omitted the current status will be displayed and returned. The command affects the conditional tests of for, while and if commands [option expression] is less efficient than [eval] (default) due to the text-processing overheads of the expression-handler. Time-critical code should use prefix notation and [option expression off] With [option expression on] both infix and prefix expression styles may be used. The overhead of selecting between the two styles is trivial This option is also configured in ticol.ini [config] as UseEval=<Boolean> Infix expression example: option expression on - Uses infix [expr] for initialiser and test for {[set i 0]} { $i < 10 } {incr i} { puts $i } while { $i < 10 } { puts $i; incr i } if { $i < 10 } { puts $i } elseif { $i > 5 } { break } Prefix expression example: option expression off - (Default): Used prefix [eval] for init and tests for {set i 0} {< $i 10} {incr i} {puts $i} while {< $i 10} { puts $i; incr i } if { < $i 10 } { puts $i } elseif { > $i 5 } { break } Option expression problems: option expression on if {file exists some.tcl} {... # FAILS ('file' interpreted as a var) option expression off if {file exists some.tcl} {... # WORKS OK ('file' is a command) option expression on if {[file exists some.tcl]} {... # WORKS OK (context is enforced) Note that with option expression off, if you use the form below then [eval] will be called twice. This will slow down performance slightly option expression off if {[proc $x]} { ... # [eval] is called twice option expression off if {proc $x} { ... # [eval] is called once See also: flow-control, for, while, if, configuration option preprocessor ------------------- Turns on or off the source-code Macro PreProcessor The default is ON and is also applied to CLI commands option stacktrace ----------------- Turns on or off the debugging stacktrace for fatal errors The default is OFF and this option is also configurable in TICOL.INI This shows the execution stack-trace when a fatal error is displayed. The first 256 characters of each command name or parameter will be shown If option echo is OFF then no stacktrace (or error message) is shown This can help track down the sequence of errors should a bug occur Tracing the execution stack will slow down Ticol slightly so should be enabled only during script debugging Example: Execution is proc level1->proc level2->puts (invalid [puts] argument count) Error stack trace: puts: Invalid stream handle In: puts x y z In: level2 x In: level1 10 option breakpoint ----------------- See: option breakpoint See also: option breakpoint
option breakpoint, halt, resume  Top  
option breakpoint ----------------- option breakpoint ?on|off? Enables conditional and non-conditional breakpoint handling. Execution will halt prior to each command call. When a [halt] instruction is encounterd you have the option to single-step to further commands, view the execution stack, resume execution (turn off breakpoints) or to quit the script [option breakpoint on] will also enable the stack trace on errors Example: option stacktrace on # Enable stacktracing option breakpoint on # Enable breakpoints watch add handle # Watch variable $handle halt # Halt and enter the debugger set handle [dll_open "sqlite3.dll"] # Code continues... resume # Resume non-debug execution halt ---- The [halt] and [resume] commands may be called conditionally within flow- control statements. [halt] and [resume] only have effect with the /BP command line argument or with [option breakpoint on], otherwise they are ignored Example: if {== $i 10} { halt } # Halt and debug if i is 10 Enabling breakpoints will also enable stacktrace which provides breakpoint trace information Once breakpoints are activated, execution will stop at the first [halt] command. You need at least one [halt] command in your script. If breakpoints are not enabled any [halt] command within code will be ignored. You may have any number of [halt] instructions in a Ticol script, however you should remove them in any final release due to a small performance cost When a [resume] command is encountered any previous [halt] instruction will be cancelled and normal script execution will resume until another [halt] is encountered Breakpoints may be enabled immediately in a script by using [option breakpoint on] followed by [halt] The command which is pending is shown along with the current command-count You may also enable breakpoints from the Windows command line using the argument: ticol.exe /BP The following menu options are displayed for breakpoints: Info Shows the execution stack Trace Shows the execution stack and steps to the next command Next Steps to the next command without showing the stack Resume Halts debugging and resumes normal execution until another [halt] command is encountered, in which case the debugger is re-entered Vars Show variables in the current execution level Watch Toggle configured watches on/off Quit Exits the current code. Returns to the O/S unless launched from the CLI, in which case control is returned to the CLI Example: Breakpoint stack item Near local line 1: At: / 10 0 At: if == $y $b error "Error generated by error" "Info for error" 401 [- $line 1] else return [/ $y $b] At: Div x At: level2 10 At: level1 10 (142): Breakpoint at [/]:Info Trace Next Watch(OFF) Resume Quit Using Stack Trace to Analyse GPFs --------------------------------- If they occur, GPFs can be analysed by re-running the script with the command-line argument /ST to enable stack-tracing. When the GPF is triggered the stack place will show the command stack and which command triggered the GPF. This may be useful when using [calldll*] commands. /ST will not trace into plugin libs The debugger stack will trace the last 100 events See also: watch, halt, array, arrays, upvar, global, ticol.ini, debugging See: help PreProcessor See also: watch, at_exit, cli, autoexec, unknown, autoexec.tcl
Passing Variables to Procedures by Name (by Reference)  Top  
Variables may be passed to a procedure by name (often called passing by reference) within procedures using [upvar]. The variable name is passed in the proc argument and [upvar] is used to create a reference to the parent variable. Whilst this passes a variable name it emulates 'passing by reference' since the name is a reference to a variable in another stack frame level Pass by value foo $var # Dereference and pass the value Pass by reference/name foo var # Pass the variable name The proc argument should be a different name tag value to the referenced variable (see example below) Passing by name offers more flexibility than passing by value Example: array set colours { 1 red 2 green 3 blue 4 white } proc list_by_key {var} { puts "list_by_key: Listing $var" # Upvar is required as all we have here is a name upvar $var # Upvar is required for pass by name foreach key [lsort [array names $var]] { puts "Key: '$key $colours($key)'" } } puts "Listing colours() sorted by key" list_by_key colours # Pass the variable name 'colours' (reference) Result: Listing array colours() sorted by key list_by_key: Listing colours Key: '1 red' Key: '2 green' Key: '3 blue' Key: '4 white' See also: pass by value, proc, variables, passing by value
Passing Variables to Procedures by Value  Top  
Variables may be passed to a procedure by value within procedures The variable is de-referenced in the procedure call by prefixing with a dollar sign. Discussion: Passing by value has limitations. Complex objects such as stacks, structs or arrays cannot be passed by value to a proc; these must be passed by name. Simple objects such as strings, integers or real numbers may be freely passed by value The value will be passed via the proc argument variable. This argument variable must still be de-referenced using a dollar sign Example: set s "Hello world" set i 123456789 set f $pi proc print_arg {value} { puts "Argument is: $value" } puts "Print argument passed by value" print_arg $s # Pass the variable by value Result: Argument is: Hello world Argument is: 123456789 Argument is: 3.14159265358979323 See also: pass by name, pass by reference, proc, variables
Returning Struct Variables from Procedures  Top  
Ticol structs were written to offer a binary interface with external DLLs via the calldll_* library. However they may be used internally and within Ticol procs. Returning values from Ticol procs via structs is possible but using them in this way isn't as easy as using them in C/C++ etc. Discussion: Within procedures, abstract/complex data types such as struct and stack require a field de-reference using [struct item] to get a reference to the field variable from the struct variable. Simple types don't require this Outside of procedures and where the struct variable is 'in scope' access to the variable field member requires [ofaddress struct.member] to retrieve the struct member address and dereference it back to a variable reference. This is because Ticol structs emulate C/C++ structs by mapping Tcl variables to address-offsets in a block of memory space. Each field member variable has a value which stores the memory address of the field. Where struct members hold a reference (name) of a variable in another scope such as root/level 1, it will be necessary to use [set] and the scoping prefix or [upvar] to manipulate that variable. Where a struct member field contains a literal variable and is therefore passed by value, no such complex indirect reference is necessary Example: Here, a struct with member field 's.i' is passed in var 's'. s.i contains the name of a variable in global scope. It is echoed using [set] as the '$' dereference will be evaluated too late... puts "struct s.i: '[set ::[struct item $value ${s}.i]]'" Here, struct 's' member field 's.f' contains a literal double value puts "struct s.f: '[struct item $value ${s}.f]'" Variables which reference a struct member in struct.member format will require the use of curved braces to isolate the struct name so that it may be dereferenced separately from the trailing field name, i.e. ${struct}.member v's $struct.member Example Code: proc ret_val {value} { upvar $value textcolor green if {[eq [type $value] stack]} { puts "ret_val: Stack: '[stack item $value 0]'" # Show stack top stack push $value "s1 Stack item return" # Return stack val } elseif {[eq [type $value] array]} { textcolor red puts "ret_val: Array: [array item $value 1]" array set $value 1 "Ret-array" # Return array item } elseif {[eq [type $value] struct]} { textcolor cyan puts "ret_val: Struct $value item(s):" array set ::[struct item $value ${value}.a] 1 "a1" struct set ::${value}.f "f2" struct set ::${value}.i "i3" # ADTs require a field dereference using [struct item] stack push ::[struct item $value ${value}.k] "k4" # Simple variables do not require field dereference struct set ::${value}.r "r5" struct set ::${value}.s "s6" } else { # Set literal var puts "ret_val: String or number $value is '[set $value]'" set $value "sn4" } textcolor } struct ts { # Test struct: holding various data types a 20 # Array f 40 # Double/Float Literal i 20 # Integer Literal k 20 # Stack Reference r 20 # String Reference s 256 # String Literal * 256 bytes } # // ASSIGN // set i 123456789 struct set ts.i 123456789 # By value set f $pi # Use const pi struct set ts.f f # By reference set s "Hello I am s" # Simple var set r "Hello string" struct set ts.r r struct set ts.s "Hello literal string" set a(1) "This is array item 1" struct set ts.a a stack create stk 200 stack push stk "Hello stack inbound" struct set ts.k stk # // CALL // ret_val s # Pass a variable by name textcolor yellow puts "Returned string literal is:\t'$s'" ret_val r # Pass a variable by name textcolor yellow puts "Returned string reference is:\t'$r'" ret_val i # Pass a variable by name textcolor yellow puts "Returned integer literal is:\t'$i'" ret_val f # Pass a variable by name textcolor yellow puts "Returned float literal is:\t'$i'" ret_val a # Pass an array by name textcolor yellow puts "Returned array a(1) is:\t\t'$a(1)'" ret_val stk # Pass a stack by name textcolor yellow puts "Returned stack is:\t\t'[stack pop stk]'" # // Struct Translation and Returns // newline ret_val ts textcolor yellow # Structs with name references require [ofaddress] # Global values which were set can be addressed directly puts "Returned stack is:\t\t'[ofaddress ts.i]'" puts "a(1) is '$a(1)'" puts "a(1) is '[set a(1)]'" puts "ts.a '[array item [ofaddress ts.a] 1]'" puts "ts.f '[ofaddress ts.f]' ($ts.f)" puts "ts.i '[ofaddress ts.i]' ($ts.i)" puts "ts.k '[stack pop [ofaddress ts.k]]'" puts "ts.r '[ofaddress ts.r]' ($ts.r)" puts "ts.s '[ofaddress ts.s]' ($ts.s)" # END # See also: pass by value, pass by name
pause  Top  
Temporarily halt execution with a prompt pause ?string? See also: exit
Using Ticol as a Web CGI Application Back-End  Top  
Using Ticol Directly -------------------- Ticol can be used directly as a CGI application. It will not be as fast or efficient as PHP etc. It wil automatically detect if running in CGI mode by checking for enviroment variable HTTP_HOST. If no script argument is given then it will try to display an HTML file called 'ticol.htm' in the same folder Using PHP --------- PHP can be used within an HTML web page to launch a Ticol Tcl CGI back-end script with the aid of some PHP as follows: HTML code: -- Snip -- Snip -- Snip -- Snip -- Snip -- Snip -- Snip -- Snip <!DOCTYPE html> <html> <body> <?php function print_procedure ($arg) { echo exec("ticol.exe test.tcl"); } $script_name='test.tcl'; print_procedure($script_name); ?> </body> </html> -- Snip -- Snip -- Snip -- Snip -- Snip -- Snip -- Snip -- Snip Tcl script: -- Snip -- Snip -- Snip -- Snip -- Snip -- Snip -- Snip -- Snip set a 10 set b 20 set c [expr $a + $b] return c -- Snip -- Snip -- Snip -- Snip -- Snip -- Snip -- Snip -- Snip If the Tcl output spans multiple lines it can be captured into a PHP array as follows: PHP Code: -- Snip -- Snip -- Snip -- Snip -- Snip -- Snip -- Snip -- Snip $array = array(); function print_procedure ($arg) { echo exec("ticol.exe test.tcl",$array); } -- Snip -- Snip -- Snip -- Snip -- Snip -- Snip -- Snip -- Snip See also: cgi debugging, html, http, Ticol
CGI Script Debugging  Top  
Debugging CGI scripts can be problematic. The main problem with CGI scripts is that errors may result in a fatal server "500" error and generate no useful output to aid diagnosis. However, there are a number of things you can try to locate the source of any elusive bug First of all you should look at the server's error.log and access.log files Add this code as the first line of any CGI script during development to guarantee errors are visible and don't trigger a "500" error puts "Content-type: text/html\r\n\r\n" Run the CGI script in console mode using the /CD (CGI Debug) argument. Then place a halt command near the suspected cause and run the script from the command-line using the /BP (Breakpoint) argument and single-step execution Enable the following parameters in TICOL.INI during CGI code development [config] Debug=True CGIDebug=True these values will create additional output and also send early HTTP headers back to the browser See also: cgi
pid, tid (Process and Thread ID)  Top  
integer [pid] integer [tid] Return the interpreter's process ID (PID) or thread ID (TID) Example: puts "PID is [pid]" puts "TID is [tid]" Result: PID is 616 TID is 33456 See also: info, username
Comparing Ticol/Tcl With PHP  Top  
Tcl is similar in appearance to PHP, Java, Javascript and other C-like languages in its use of curly braces and with similar language constructs. However, Tcl is a command-based language which has minimal syntax. This makes it easily extensible Ticol has extended the Tcl language to add various useful commands. Here is a brief summary of the differences between standard Tcl and PHP Item Tcl PHP Ticol ----------------------------------------------------------------------- Release date 1988 1994 2015 Easy to learn Yes Yes Yes Reference variables prefixed with $ Yes Yes Yes Variables are always prefixed with a $ No Yes Yes Braced flow-control constructs Yes Yes Yes Intended mainly for web-development No Yes No Can be byte-precompiled (not Ticol) Yes Yes No Literal strings must be quoted always No Yes No C-like for statement No Yes Yes Suitable for web CGI application? Yes Yes Yes Natural expression math format always? No Yes Yes (Tcl can use prefix notation: "+ 1 1") Associative arrays Yes Yes Yes Standard (downwards) variable inheritance No (upvar) Yes No New flow control constructs possible? Yes No Yes Suitable for desktop application? Yes (Tk) No No Usable as a general IT script language Yes No Yes Usable as an O/S shell? Yes No Yes See also: Ticol, Tcl
play_wav, stop_wav  Top  
play_wav filename?.wav? ?-loop? stop_wav Plays a Windows WAV file, optionally looping playback. Playback can be halted after a fixed period by calling sleep, followed by stop_wav If play_wav is immediately followed by stop_wav the file will not be audible Example: puts "Played WAV? :"[bool [play_wav ".\\sample.wav"]] sleep 4000 # Allow sufficient time to play stop_wav # Halt playback See also: beep
Ticol ICMP Ping Plugin  Top  
To load, use: lib ticol_ping ?-verbose? ?-nocomplain? string [ping hostname ?timeout-ms? ?-list?] string [ping ipv4-address ?timeout-ms? ?-list?] string [ip_from_host hostname] Can ping either a hostname or an IPV4 address. The default timeout period is 4000 ms but this may be specified as an optional 2nd argument. By default the IPV4 address of the pinged node is returned but a list may be returned by appending the -list argument. In which case a list containing the IPV4 host address and round-trip response time in ms will be returned. All versions of Windows are supported from Windows NT4/2K to Server 2016 Example: set hostname "localhost" set i 1; while {$i < 11} { set r [ping $hostname -list] printf "%3i\t%s\t%i ms\r\n" $i [lindex $r 0] [lindex $r 1] incr i sleep 1000 } The command [ip_from_host] will perform a hostname DNS lookup to return the IPV4 address Example: puts [ip_from_host www.google.com] Result: Example: puts [ip_from_host www.google.com -list] Result: 301 See also: plugins, lib
Ticol External Plugins  Top  
Plugins are external modules which can be loaded to add additional functionality to Ticol. A small number of plugins are supplied: Some of the plugins are new or experimental Title Lib DLL Description Help Topic ------------------------------------------------------------------------- ARP ticol_arp.dll ARP and RARP commands See: arp Big Numbers ticol_bignum.dll Arbitrary precision math See: big math Call DLL ticol_calldll.dll Call an external DLL See: calldll CArray ticol_carray.dll C-Like fixed arrays See: carray CPU ticol_cpu.dll Basic CPU information See: cpu CRC ticol_crc.dll CRC calculation See: crc DHCP ticol_dhcp.dll DHCP commands See: dhcp DNS ticol_dns.dll DNS lookup See: dns Event Logging ticol_event.dll Windows Event Logging See: event FTP ticol_ftp.dll A simple FTP client See: ftp Highlight ticol_highlight.dll HTML code highlighting See: highlight INI ticol_ini.dll INI file handling See: ini Linked List ticol_list.dll Binary Linked Lists See: linkedlist Miscellaneous ticol_misc.dll Misc routines See: misc Ping ticol_ping.dll Simple ICMP ping See: ping R2D ticol_r2d.dll Roman to decimal convert See: r2d REG ticol_reg.dll Simple registry services See: reg RLE ticol_rle.dll Simple RLE compression See: rle RTF ticol_rtf.dll Simple RTF text output See: rtf Service ticol_svc.dll Windows service query See: service SMTP Email ticol_mail.dll SMTP emailer See: mail SQLite ticol_sqlite.dll SQLite 3 plugin See: sql Variant ticol_variant.dll Variants for calldll See: variant XBase ticol_xbase.dll Dbase 3/4 Database See: xbase ZIP ticol_zip.dll Simple ZIP package See: zip See: lib interface - for information about how to write plugins in C/C++ See also: lib, Ticol, lib interface
Miscellaneous Routines Plugin  Top  
A plugin containing miscellaneous useful routines To load, use: lib ticol_misc ?-verbose? ?-nocomplain? Command and Syntax # Comments ip_match mask ip-address # Match an IP address to a mask (wildcards ok) # Returns a boolean 1/0 cidr_match mask ip-address # Match an IP address to a CIDR mask ?.?.?.?/N # address / bitmask # Returns a boolean 1/0 is_mac mac-address ?-f? # Checks if string is a formatted MAC address # Returns a boolean 1/0 is_mouse_present # Returns a boolean 1/0 is_networked # Returns a boolean 1/0 is_safe_mode # Returns a boolean 1/0 monitorcount # Returns a count of connected monitors rot13 string # Perform rot-13 transformation on string # and return the result (source is unchanged) volume serial X: # Return the serial of a disk as a hex value volume filesystem X: # Return the file system type of a disk volume wallpaper get # Get the path+filename of the wallpaper wallpaper set file ?align? # Set the current wallpaper with alignment... # -centre, -tile, -stretch (returns a boolean) Examples: IP match can use wildcards * or ? to represent octets or individual digits octets may be omitted from the right-hand end of the IP address mask puts [ip_match 192.168.3.*] puts [ip_match 192.168.3.*] puts [ip_match 10.*] Results: 1 0 1 Example: CIDR (Classless Inter-Domain Routing) [cidr_match] requires a full IP address with a bitmask value /N where N specifies significant bits from the left hand end of the IP address puts [cidr_match] puts [cidr_match] Result: 1 0 Example: puts [is_mac abcdefgh] # Too short + invalid characters puts [is_mac 001122aabbcc] # Valid unformatted MAC puts [is_mac 00-11-22-aa-bb-cc -f] # Check valid formatted MAC Result: 0 1 1 Example: puts [rot13 "Hello world"] Result: Uryyb jbeyq Example: puts [volume serial c:] Result: A1B2C3D4 Example: puts [volume filesystem c:] Result: NTFS See also: long_to_ip, ip_to_long, Plugins
Ticol Registry Plugin (ANSI)  Top  
To load, use: lib ticol_reg ?-verbose? ?-nocomplain? Path/Key arguments must be supplied in Tcl "backslash-escaped" format. The result (if string or list) will be returned in the same "backslash- escaped" format. Only ANSI strings are supported by [reg]. Unicode/MBCS strings are not supported Supported in Windows 2k/XP or higher Syntax: reg <command> path ?value? ?-type? Use either 'reg' or 'registry' reg get "HKEY_VALUE\\path" keyname ?-binary var? ?-type? for [reg get] the default type is -auto reg set "HKEY_VALUE\\path" keyname value ?-binary var? ?-type? for [reg set] the default type is -string reg del "HKEY_VALUE\\path" keyname ?value? if ?value? is omitted then the entire subkey and values are deleted reg type "HKEY_VALUE\\path" keyname Where the optional '-type' argument is one of: -auto (default) -dword Store a 32-bit HEX value -qword Store a 64-bit HEX value -list Decompose/reassemble a Tcl list (REG_MULTI_SZ) -multiline Stores/retrieves CRLF delimited text as REG_MULTI_SZ -string Stores/retrieves a Tcl list as REG_SZ The type argument must be the last item in the command Binary strings cannot be passed via the Tcl command line. Instead, for [reg set] and [reg get] an argument reference to the variable-name is passed using "-binary varname" and any preceding variable argument is ignored If DWORD or QWORD values are supplied with HEX values, they must include a leading 0x - e.g. 0xffffffff Example: puts [bool [reg set HKEY_CURRENT_USER\\Console ColorTable06 \ 0x00508dfc -dword] puts [inttohex [reg get HKEY_CURRENT_USER\\Console \ ColorTable06 -dword]] puts [reg get HKEY_CURRENT_USER\\Console ColorTable06 -dword]] Result: True 0x508dfc 5279228 Where types are mixed between binary and non-binary, strings will be truncated at the first null character Example: (Sets partial string) binary set a \xfe\xffhello\x21\x00\x22world\x02\xff\xfe -length 16 reg set HKEY_CURRENT_USER\\Software\\Ticol BINDATA -binary a reg get HKEY_CURRENT_USER\\Software\\Ticol BINDATA -binary b puts [binary tohex b] puts [reg get HKEY_CURRENT_USER\\Software\\Ticol BINDATA] Result: feff68656c6c6f210022776f726c6402 hello! Note that -multiline and -string affect the interpretation of sent/returned Tcl data. Both types are stored as REG_MULTI_SZ but will be encoded or decoded as appropriate. You can store in Tcl list format and retrieve as a CRLF-delimited multi-line string (and vice-versa) Example: (Using line-wrap, where a space is added after the \) puts "Country: '[reg get {HKEY_CURRENT_USER\\Control\ Panel\\international} sCountry]'" Result: 'United Kingdom' Example: (from https://www.tcl.tk/man/tcl8.4/TclCmd/registry.htm#M9) set ext .tcl # Read the type name set type [registry get HKEY_CLASSES_ROOT\\$ext {}] # Work out where to look for the command set path HKEY_CLASSES_ROOT\\$type\\Shell\\Open\\command # Read the command set command [registry get $path {}] puts "Filetype \"$ext\" opens with $command" Example: reg set HKEY_CURRENT_USER\\Software\\Ticol TestValue "Hello world" -string puts [reg get HKEY_CURRENT_USER\\Software\\Ticol TestValue] puts [reg type HKEY_CURRENT_USER\\Software\\Ticol TestValue] puts [bool [reg del HKEY_CURRENT_USER\\Software\\Ticol TestValue]] Results: Hello world REG_SZ true See also: plugins, calldll
sql  Top  
A plugin which offers rudimentary ANSI SQLite 3 database capability To load, use: lib ticol_sql ?-verbose? ?-nocomplain? handle [sql open database_file] variant [sql query handle querystring] sql close handle sql free variant|variant-address To run a query you must first use [sql open] to obtain a database handle This handle is passed to [sql query]. You should close the handle using [sql close] after you have finished querying the database SQL queries return a VARIANT object. It is vital that this is freed by a call to [sql free] using either the dereferenced variable ($var) or name (var) and this must be called before the variable goes out of scope. Do NOT use [varray unset var] to release structures returned by this plugin (see example below) The returned VARIANT table may be manipulated using the [varray] commands If a database file does not exist then [sql open] will create it Example: set handle [sql open c:\\path\\to\\my.db] Example; set v [sql query $handle "SELECT * from Customers"] Example: sql free v Example: sql close $handle Full Example: lib ticol_sqlite.dll -verbose newline set handle [sql open ".\\albums.db"] if { $handle } { # Null is not returned for file not found set v [sql query $handle "SELECT * from Artists"] set rows [varray count $v] set cols [varray count $v 2] puts "Retrieved table has $rows row(s) and $columns col(s)" sql free v # Ensure [sql free] is used sql close $handle } else { die "Can't open SQL database" } Result: lib: Loaded command 'sql' lib: Loaded ticol_sqlite.dll - 1 command(s)' Retrieved table has 183 row(s) including header, and 2 column(s) See also: varray, plugins
Ticol CRC32 Plugin  Top  
To load, use: lib ticol_crc ?-verbose? ?-nocomplain? value [crc value ?-decimal? ?-noprefix?] value [file_crc filename ?-decimal? ?-noprefix?] Extends [file] by adding: [file crc filename] into the namespace Calculates the 32-bit CRC checksum of an ANSI string or file and is tested on files up to 10Gb in size By default a hex value is returned, prefixed with "0x" unless -noprefix is used. A decimal value can be returned by appending the argument -decimal [file_crc] will calculate the CRC for a file. This is quite efficient even on fairly large files of up to 1Gb. The maximum file size is 4Gb as this is the largest which may be accommodated by the 32-bit integer range Example: puts [crc $qbf] Result: 0x414fa339 Example: puts [file_crc VS97PRO3.ISO] Result: 0x22ffdfcc See also: plugins
Ticol DHCP Plugin (Simple DHCP commands)  Top  
To load, use: lib ticol_dhcp ?-verbose? ?-nocomplain? bool [dhcp enabled adapter_index] bool [dhcp release adapter_index ?-verbose?] bool [dhcp renew adapter_index ?-verbose?] double [dhcp start] double [dhcp end] The [dhcp] plugin offers extra commands which may be used to query and/or renew a workstation's IP address Windows has a concept of an adapter index within an array of adapters. We iterate from 0 to adapter_max-1 but we must use the adapter index value to manipulate it via [dhcp] as adapters may be unplugged or inserted, thus rendering the actual, live array 'sparse'. The required 'adapter_index' value is obtained from [info adapter_index N] where N iterated from 0 to [info adapter_count]-1 [dhcp start] and [dhcp end] return the DHCP lease start and expiry dates as a double value. These double return lease date values can be converted to a readable date format using the [date] command Once the adapter is unbound from TCP/IP it will no longer be discoverable using its index value. [info adapter_index N] should be used to retrieve the current index value for an adapter which we handle via an index of 0..N from [info adapter_count] The [info] command provides a number of arguments which are useful for handling DHCP requests and querying adapter properties Notes: An undefined date is returned in the "C" epoch as 0 or 1970/01/01 00:00:00, which is interpreted in the Ticol (VB) date scheme as 25569.0 Example: option expression off for {set i 0} {< $i [info adapter_count]} {++ i} { if {dhcp enabled $i} { puts "ID:[info adapter_id $i]" puts "Index: [info adapter_index $i]" # Show the current DHCP server and lease dates puts "DHCP Server =[info dhcp_server $i]" puts "DHCP Lease Start=[date [dhcp start $i]]" puts "DHCP Lease End =[date [dhcp end $i]]" if {> [dhcp end $i] 25569.0} { # If more recent than 1970/01/01 set index [info adapter_index $i] textcolor magenta puts "Renewing $i (index $index)" puts "Released?\t[bool [dhcp release [info adapter_index $i]]]" puts "Renewed?\t[bool [dhcp renew [info adapter_index $i]]]" # Show the new DHCP server and lease dates puts "DHCP Server =[info dhcp_server $i]" puts "DHCP Lease Start=[date [dhcp start $i]]" puts "DHCP Lease End =[date [dhcp end $i]]" textcolor newline break } newline } } See also: plugins, dns, info
Ticol DNS Plugin (Simple DNS / Reverse DNS lookups)  Top  
To load, use: lib ticol_dns ?-verbose? ?-nocomplain? list [dns hostname|ipv4-address ?-mx?] string [rdns ipv4-address] Performs a DNS or reverse DNS lookup on the hostname or IP address argument. [dns] returns a list containing the IPV4 address(es) of the host. More than one item may be returned. [rdns] returns the hostname matching a given IP address if that address has an associated record Examples: lib ticol_dns puts [dns yahoo.com] puts [dns yahoo.com -mx] foreach x [dns yahoo.com] { puts $x } puts [rdns] puts [rdns] Results: mta6.am0.yahoodns.net mta7.am0.yahoodns.net mta5.am0.yahoodns.net google-public-dns-a.google.com snoopy See also: plugins
Ticol FTP Plugin (Simple FTP Client)  Top  
To load, use: lib ticol_ftp ?-verbose? ?-nocomplain? ftp hostname get|put|ls filepathspec ?-u username? ?-p password? ?-t targetpath? ?-pasv? ?-overwrite? ?-port port? ?-v? ftp hostname|exists size filespec ?filespec...? ?-u username? ?-p password? ?-port port? ?-pasv? ftp ls: Accepts one filename. Returns a list containing the contents relating to the filespec ftp size: Accepts multiple filenames. Will return a list containing the discovered filenames and their sizes. Example: ftp localhost size /tools/zip-7100a80516.zip /tools/netdiag.zip Result: {/tools/zip-7100a80516.zip 1292683} {/tools/netdiag.zip 661806} ftp exists: Accepts multiple filenames. Will return a list containing the supplied filenames and a boolean 1 or 0 depending if the file exists or not. Example: ftp localhost exists /tools/zip-7100a80516.zip /nosuchfile.zip Result: {/tools/zip-7100a80516.zip 1} {/nosuchfile.zip 0} See also: plugins
Ticol XBase - A Simple Dbase III/IV Plugin  Top  
To load, use: lib ticol_xbase ?-verbose? ?-nocomplain? handle [xbase open] long [xbase create {tcl-list}] bool [xbase close handle] string [xbase info handle] long [xbase count handle] string [xbase get handle N] # record is base 1 short [xbase fieldcount handle] string [xbase fieldname handle N] # field is base 0 long [xbase fieldsize handle N] # field is base 0 string [xbase field handle N] # field is base 0 bool [xbase set handle field value] # field is base 0 bool [xbase put handle ?record?] # record is base 1 bool [xbase delete handle record] # record is base 1 bool [xbase undelete handle record] # record is base 1 bool [xbase is_deleted handle record] # record is base 1 bool [xbase pack handle] bool [xbase setver handle integer] bool [xbase binary set handle integer value] bool [xbase binary field handle N] bool [xbase index handle index_name ?field_number?] A basic XBase/Dbase plugin to handle Dbase III/IV files (and equivalents) This plugin offers simple manipulation of generic XBase database files. [xbase] can handle DBF files produced by OpenOffice, Excel or XBase programs No advanced features are offered such as memo fields or indexing Note that record indices are "base 1" values, whilst field indices are the same as arrays (base 0) [xbase open] will return a handle to an open database. This must be saved and re-used for other xbase commands [xbase create] requires a Tcl list argument of field specifiers as follows: {field_name length type ?decimals?} where field_name can be no longer than 11 characters and type is one of: 'C' - Char 'D' - Date 'L' - Logical 'M' - Memo 'N' - Numerical The Ticol [xbase] lib doesn't enforce data-typing on field-write. However, it will create files which are compatible with the XBase format. Memo fields are unsupported and will be treated as text. It is up to the programmer to write code which enforces data types as necessary XBase error codes: enum { DBERROR_SUCCESS # 0 DBERROR_ALREADY_OPEN # 1 DBERROR_FILE_NOT_FOUND # 2 DBERROR_OPEN_FAIL # 3 DBERROR_INVALID_PARAM # 4 DBERROR_UNKNOWN_OPEN_MODE # 5 DBERROR_VERSION # 6 DBERROR_HEADER_LEN # 7 DBERROR_RECORD_LEN # 8 DBERROR_FIELD_COUNT # 9 DBERROR_FIELD_LEN # 10 DBERROR_MEMORY # 11 DBERROR_SEEK_FAIL # 12 DBERROR_DISK_SPACE # 13 DBERROR_FILE_EXISTS # 14 DBERROR_EXCEPTION # 15 DBERROR_UNHANDLED # 16 } [struct] may be used to write binary data [xbase create] returns 0 for success or an error code > 0. On success, [xbase create] returns a handle to an open file Example: set handle [xbase create {{Name 30 C} {Address 40 C} {Phone 20 C}}] [xbase close] Closes a database and previously opened handle. It destroys all resources associated with that handle. It returns a boolean 1 if the handle is valid and the database was closed successfully [xbase info] returns a Tcl list containing the following: record-count field-count {{fieldname length type} ... } [xbase count] returns a count of the number of records in an open xbase database file [xbase get] retrieves a record from an open database. The record must exist If the record is retrieved then the whole record buffer is returned. Use [xbase field] to retrieve individual field values. The record index value is a "base 1" value with the first record being 1 [xbase fieldcount] returns a count of the number of fields in an open xbase database [xbase fieldname] returns the field name for a given xbase field and takes a base 0 index value [xbase fieldsize] returns the size of an allocated field in an existing database file. It takes a base 0 index value [xbase field] returns individual field data for an open xbase database at the position of the current record (see [xbase get]). [xbase field] takes a base 0 index value [xbase set] set the value of a given xbase database field. The index value is array base 0 and the first field is 0. [xbase set] does not actually flush (write) the record to disk file (See [xbase put]). [xbase set] returns a boolean success return value [xbase put] writes the pending values in the record buffer to disk file. If a record number is omitted then data is written to the current record. The record index value is a "base 1" value, [xbase put] returns a boolean success return value [xbase delete] does not physically delete a record. The XBase convention is to tag a hidden field with a delete flag. Likewise [xbase undelete]. The command [xbase is_deleted] can be used to test whether a record is deleted or not [xbase pack] will 'pack' a database, removing all deleted records and truncating the file as required. This may be a slow process [xbase setver] will set the version flag field according to the integer value passed. Use of this command is not recommended other than for experimental use. Common version values are as follows: In this value, bits 0-2 indicate version number: 3 for dBASE Level 5, 4 for dBASE Level 7. Bit 3 and bit 7 indicate presence of a dBASE IV or dBASE for Windows memo file and bits 4-6 indicate the presence of a dBASE IV SQL table; bit 7 indicates the presence of any .DBT memo file (either a dBASE III PLUS type or a dBASE IV or dBASE for Windows memo file) The default value is 0x03 [xbase binary] is able to write data with embedded NULL (0x00) characters to and from database fields. Note that strings with embedded NULLs will be truncated at the first NULL with most Ticol commands. You can use commands such as [binary] to manipulate binary fields (See: binary) Indexes ------- Standard XBase database indexes are not provided [xbase index] provides built-in indexing using Ticol associative arrays It is trivial to write one's own routines to use the efficient Ticol associative arrays to index an XBase database file by using the subscript as the record key value and the array value as the stored record number value. A proc could be provided to match on partial index key matches. Duplicate index key entry cases would need to be handled to avoid collision. This is the method used by [xbase index] set rc [xbase count $handle] for {set i 1} {<= $i %rc} {++ i} { xbase get $handle $i set text [string left [xbase field $handle 0] 20] # Field 0 set index(text) $i # Usual subscript/value assignment inverted } set search "Hello world" puts [xbase get $handle [string left $index($search) 20]] See: xbase_index.tcl Combined Read Database Example ------------------------------ option expression off lib ticol_xbase -verbose set filename "employee.dbf" set handle [xbase open $filename] set rc [xbase count $handle] set field_count [xbase fieldcount $handle] puts "------------------------------------------------------" puts [xbase info $handle] puts "------------------------------------------------------" for {set i 1} {< $i 10} {++ i} { xbase get $handle $i printf "-- Record %4i -------------------------------------\r\n" $i textcolor yellow for {set j 0} {< $j $field_count} {++ j} { printf "%4i '%10s\t%-44.44s'\r\n" $j\ [xbase fieldname $j $handle]\ [xbase field $j $handle] } textcolor puts "----------------------------------------------------" } xbase close $handle Results # 29 records # 11 fields ------------------------------------------------------------------ 29 11 {{SUPPLR_ID C 10} {COMPANY C 36} {CONTACT C 25} {CON_TITLE C 25} {ADDRESS C 42} {CITY C 13} {REGION C 11} {ZIP_CODE C 10} {COU NTRY C 12} {PHONE C 15} {FAX C 15}} -- Record 5 --------------------------------------------------- 0 ' EMPLOY_ID 666 ' 1 ' LAST_NAME Buchanan ' 2 'FIRST_NAME B. L. ' 3 ' EMP_TITLE Sales Manager ' 4 ' BIRTHDATE 19611008 ' 5 ' HIRE_DATE 19911123 ' 6 ' ADDRESS 14 Garrett Hill ' 7 ' CITY London ' 8 ' REGION ' 9 ' ZIP_CODE ' 10 ' COUNTRY UK ' 11 'HOME_PHONE (711) 555-4848 ' 12 ' EXTENSION 3453 ' 13 ' NOTES B. L. (Bruce) Buchanan graduated from St. ' 14 'REPORTS_TO 333 ' ------------------------------------------------------------------ See: xbase_inspect.tcl Create Database Example ----------------------- option expression off lib ticol_xbase.dll set handle [xbase create new "{Name 30} {Address 40} {Phone 10}" -y] set info [xbase info $handle] # Get database info puts "Info Info: $info" puts "Info Records:\t[lindex $info 0]" puts "Info Fields: \t[lindex $info 1]" puts "Info Structure: [lindex $info 2]" foreach {x} [lindex $info 2] { # Iterate fields puts "'$x'" } newline set rc [xbase count $handle] # Get record count puts "Database record count for new.dbf is: $rc" # set handle field value xbase set $handle 0 "Biffa Bacon" xbase set $handle 1 "49 Letsby Avenue" xbase set $handle 2 "(0123) 4567890" xbase put $handle 10 # Write to record 10 newline set i 10 xbase get $handle $i # Get the record set field_count [xbase fieldcount $handle] for {set j 0} {< $j $field_count} {++ j} { # Iterate fields printf "%4i %-10s\t\[%s\]\r\n" $j\ [xbase fieldname $j $handle]\ [xbase field $j $handle] } xbase close $handle Results: Info Info: 0 3 {{NAME C 30} {ADDRESS C 40} {PHONE C 10}} Info Records: 0 Info Fields: 3 Info Structure: {NAME C 30} {ADDRESS C 40} {PHONE C 10} 'NAME C 30' 'ADDRESS C 40' 'PHONE C 10' 0 NAME [Biffa Bacon ] 1 ADDRESS [49 Letsby Avenue ] 2 PHONE [(0123) 456] See: xbase_man_create.tcl See also: plugins
Ticol ZIP Plugin  Top  
To load, use: lib ticol_zip ?-verbose? ?-nocomplain? integer [zip {filespec list} ?-name filename??.zip?? ?-r? ?-p password? ?-verbose? ?-y?] If '-name' is omitted then a ZIP file with a random filename will be created. The filespec-list may contain multiple wildcard filespecs. These will be expanded automatically. The filename is returned in the results list if -r is specified then any given folders will be searched recursively and this will apply to all filespecs given. The resulting ZIP file may be encrypted using relatively weak but standard ZIP encryption To overwrite existing files use '-y' (yes) [zip] returns a list containing the ZIP filename, size of the ZIP file in bytes and a count of the number of files successfully added to the ZIP and any error code (in that order) The ZIP module, ticolzip.dll, is based on the InfoZIP code 2.3 and thus AES encryption is not supported. The library supports password protection using ZIPCrypt deflate only. You should not use this plugin to create ZIP files which require high levels of encryption security Example: set result [zip {*.tcl} -r -password secret] # ZIP recursively puts "ZIP filename is [lindex $r 0]" See also: plugins, lib, Ticol, big numbers, mail
Ticol Windows Service Query Plugin  Top  
A plugin to query Windows services and retrieve their status To load, use: lib ticol_svc ?-verbose? ?-nocomplain? service <registered-service-name> ?-verbose? The command must be run with sufficient access rights See: is_elevated, elevate The following codes or verbose status messages are returned: Code Verbose Comments --------------------------------------------------------------------------- 0 Running The service is installed and running normally 1 Stopped The service is installed + in a stopped state 2 Stopping The service is installed and running 3 Not found The requested service was not found 4 No error Reserved 5 Can't load advapi32.dll Cannot load the required system DLL 6 Can't locate export Wrong version of advapi32.dll QueryServiceStatusEx Can't locate function in the DLL 7 OpenSCManager failed Could not open the SCM. Check access rights 8 Unknown service status An unknown service status was returned 9 Unhandled error Unhandled error This offers a simple method of querying Windows services. Only services with ANSI names are supported. Services typically have two names, an actual registered service name and a display name. This command requires the registered service name Service actions are not yet supported Example: "Branch Cache" service name is "PeerDistSvc" "DNS Client" service name is "Dnscache" "DHCP Client" service name is "Dhcp" "Distributed Link Tracking Client" is "trkwks" NET START will show the display name, not the registered service name The true name may be obtained from the Windows Service Control Manager (SCM) via Start->Run->services.msc Services which have spaces in their registered name must be enclosed in quotes Example: lib ticol_svc puts [service "FileZilla Server"] puts [service "FileZilla Server" -verbose] puts [service "Nosuch App"] puts [service "Nosuch App" -verbose] Result: 0 Running 3 Not found See also: plugins, lib, Ticol, big numbers, zip
Ticol SMTP Mail Plugin  Top  
This is a simple SMTP emailer plugin which exposes the following command: To load, use: lib ticol_mail ?-verbose? ?-nocomplain? sendmail smtp_server from_address {to_list} ?-subject {subject}? ?-body {message body}? ?-u username? ?-p password? ?-port port_value? ?-a {attachment list}? ?-cc {cc list}? ?-bcc {bcc list}? ?-priority <0..9>? ?-dsn? ?-nc? ?-debug? Arguments should be braced, especially as indicated sendmail returns the SMTP error code. 250 usually indicates success. See SMTP documentation for more information The first 4 arguments to sendmail are mandatory and positional. The remainder are optional and may be supplied in any order If a username/password is given then SMTP authentication will be attempted This is a simple SMTP client and SSL/TLS is not supported. Note that SMTP sends passwords in plain text where there is no complex authentication A copyright and source of origin signature is added to all emails unless the -nc (no copyright) argument is passed. Useful debugging information can be displayed using -debug Multiple unlimited attachments are supported, but these are not expanded from wildcards. Wildcards, if found, are ignored. ls filespec var -list may be used to expand wildcard filespecs. Concatenate using [append] not [lappend] Example: set smtp_server smtp.example.com set from admin@example.com set to [list recipient1@example.com admin@example.com] set subject "This is a test email sent at [date]" set body_text "Hi there, this is a nice email - $qbf" sendmail $smtp_server $from $to -subject $subject -body $body_text The mail module, ticolmail.dll, is not based on 3rd party code and was written by the author of Ticol See also: plugins, lib, Ticol, big numbers, zip
Ticol Big Integer Math Plugin  Top  
Large precision integer math To load, use: lib ticol_bignum ?-verbose? ?-nocomplain? This module adds large-precision signed-integer number commands. Standard Ticol math uses 64-bit integer values. Numbers up to 6500 digits are handled (subject to recursive stack memory limits. Since these digits are strings they can be easily interfaced into databases and files This is an integer library which takes only integer values. [fdiv] can return float format results. Binary operations such as [big &] will generally operate only on positive integers as integers of arbitrary width have no fixed position for a sign flag. Some operations will allow emulation of fixed-bit-width integers but without sign value. Whilst it is possible to combine math operations on several big numbers note that calculation speeds of big math are relatively slow and inefficient, particularly for division. Calculations may need to be restructured to compensate for this. Division involving numbers with hundreds or thousands of digits may take many minutes to compute For binary values, there is no fixed bit-width so, again, calculating negative values is a problem due to the unfixed bit-width for 2's compliment. Therefore negative binary numbers are not handled rather than round up to the next highest power of 8 and lose performance. For more information ... See: http://www.codeproject.com/Tips/1079637/Twos-Complement-for-Unusual-Integer-Sizes Float values can be handled by multiplying by a precision factor of say 15, performing math such as division and then dividing back down afterwards or shifting as a string and inserting a decimal point Values are truncated, not rounded up or down. Ticol natively uses prefix notation for commands, not infix, so the syntax is: [big <operator> value ?value?] Example: puts [big / 22 7.0] Where 'operator' is one of the following integer-only operators: + a b Addition - a b Subtraction * a b Multiplication / a b Division. Note is truncated, not rounded up or down % a b Modulo division (remainder after integer division) ++ a Increment -- a Decrement == a b Equivalence != a b Difference < a b Less-than > a b Greater-than <= a b Less-than or equal to >= a b Greater-than or equal to & a b ?N? Bitwise AND (result optionally restricted to N bits) | a b ?N? Bitwise OR (result optionally restricted to N bits) || a b Logical OR ^ a b Bitwise XOR ~ a Unsigned bitwise NOT (May not return valid bit-width results) ! a Logical NOT += a b Add (Requires Ticol variable name Lvalue without $) -= a b Sub " *= a b Mul " /= a b Div " &= a b BitAnd " (result optionally restricted to N bits) |= a b ?N? BitOr " (result optionally restricted to N bits) ^= a b BitXor " << a b ?N? Shift a left by b bits ?bitwidth N? (mul by power of 2) (result optionally restricted to N bits) >> a b ?N? Shift a right by b bits ?bitwidth N? (div by power of 2) (result optionally restricted to N bits) ** a b a to the power of b abs a Absolute value (remove sign) bintoint a ?-noprefix? Convert binary string to big integer (0b prefix optional) debug on|off Turn on the trace for "/" and "fdiv" (see graph) div2 a Rapid division by 2 (faster than [big / x 2] div10 a b Rapid division by 10 (faster than [big / x 10] fact a Factorial (1..1000) fdiv a b Return floating point division of two big numbers Precision is 18 digits after the decimal point fib a Fibonacci number (1..30000) fmod a b Remainder after float division graph Display a coloured graph of a big number using the standard IEEE electrical colour code. Note that orange may appear as khaki on some systems is resolved using a registry tweak. See: console colours inttobin a ?-noprefix? Convert from unsigned big positive integer to binary string. Use [big abs] to ensure +ve input value is_even a Returns boolean true (1) if number is even max a b Maximum of two big integers mean ... Mean value of a sequence of integers (returns a float) Precision is 18 digits after the decimal point min a b Minimum of two big integers mul2 a Rapid multiplication by 2 (faster than [big * x 2] pow a b a to the power of b (alias for **) pow2 a Raise 2 to the power of x (faster than [big pow 2 n]) rnd lo hi Random number between range lo and hi sqrt a Integer square root Two command offer big floating point operations, [big mean] and [big fdiv] Usage with conditional expression statements and [option expression on] RIGHT if { [big == $n 0]} { ... # Expression enclosed in square brackets WRONG if { big == $n 0} { ... # Expression has not been enclosed in [] RIGHT while { [big < $n 100]} { ..# Expression enclosed in square brackets WRONG while { big < $n 100} { ... # Expression has not been enclosed in [] Usage with conditional expression statements and [option expression off] RIGHT if { big == $n 0 } { ... # Expression enclosed in square brackets RIGHT if { [big == $n 0]} { ... # Expression has not been enclosed in [] RIGHT while { big < $n 100} { ... # Expression has not been enclosed in [] RIGHT while { [big < $n 100]} { ..# Expression enclosed in square brackets Examples: Result lib ticol_bignum # (Loads the library) big % -793455062 -139725649 # -94826817 big / 123456789012345678567890 987654321 # 124999998873437 big * 101020280607085690 181818 # 18367305379419105984420 big inttobin [big << 7 24] # 111000000000000000000000000 big fdiv 423423423437 23 # 18409714062.478260869565217391 big mean 1234567 987654321 23 7 # 247222229.50000000000000 set a 12345; puts [big += a 1000] # 13345 Example: option expression on proc fac n { if {$n <= 1} { return 1 } else { return [big * $n [fac [big - $n 1]]] } } set s {} for {set i 1} {$i < 40} {incr i} { set f [fac $i] append s [format "|%4s| %50s|%5s|\n" $i $f [string length $f]] } puts "+----+---------------------------------------------------+-----+" puts "| n| Factorial n | Len |" puts "+----+---------------------------------------------------+-----+" puts $s -nonewline puts "+----+---------------------------------------------------+-----+" puts "| 39| 20397882081197443358640281739902897356800000000| |" puts "| | See: http://www.rpbridge.net/7z78.htm | |" puts "+----+---------------------------------------------------+-----+" Result: +----+---------------------------------------------------+-----+ | n| Factorial n | Len | +----+---------------------------------------------------+-----+ | 1| 1| 1| | 2| 2| 1| | 3| 6| 1| | 4| 24| 2| | 5| 120| 3| | 6| 720| 3| | 7| 5040| 4| | 8| 40320| 5| | 9| 362880| 6| | 10| 3628800| 7| | 11| 39916800| 8| | 12| 479001600| 9| | 13| 6227020800| 10| | 14| 87178291200| 11| | 15| 1307674368000| 13| | 16| 20922789888000| 14| | 17| 355687428096000| 15| | 18| 6402373705728000| 16| | 19| 121645100408832000| 18| | 20| 2432902008176640000| 19| | 21| 51090942171709440000| 20| | 22| 1124000727777607680000| 22| | 23| 25852016738884976640000| 23| | 24| 620448401733239439360000| 24| | 25| 15511210043330985984000000| 26| | 26| 403291461126605635584000000| 27| | 27| 10888869450418352160768000000| 29| | 28| 304888344611713860501504000000| 30| | 29| 8841761993739701954543616000000| 31| | 30| 265252859812191058636308480000000| 33| | 31| 8222838654177922817725562880000000| 34| | 32| 263130836933693530167218012160000000| 36| | 33| 8683317618811886495518194401280000000| 37| | 34| 295232799039604140847618609643520000000| 39| | 35| 10333147966386144929666651337523200000000| 41| | 36| 371993326789901217467999448150835200000000| 42| | 37| 13763753091226345046315979581580902400000000| 44| | 38| 523022617466601111760007224100074291200000000| 45| | 39| 20397882081197443358640281739902897356800000000| 47| +----+---------------------------------------------------+-----+ | 39| 20397882081197443358640281739902897356800000000| | | | See: http://www.rpbridge.net/7z78.htm| | +----+---------------------------------------------------+-----+ Notes: See: modulo sign for a discussion of how Tcl interprets signs with % as sign usage in Tcl differs from that in other languages See also: plugins, lib, Ticol, zip, mail
Modulo Sign (Discussion)  Top  
integer [% value] integer [big % value] Modulo [%] and [big %] follow C/C++ expression rules in that the sign is set to the same as the dividend. This may change in future versions if there is a convincing reason to change ActiveTcl states that: "The remainder will always have the same sign as the divisor and an absolute value smaller than the absolute value of the divisor. This differs from other languages as follows: a b => r Visual BASIC 5 (sign same as dividend) ------------------------------------------------- + + => + + - => + - + => - - - => - C++ (sign same as dividend) -------------------------------------------------- + + => + + - => + - + => - - - => - a b => r ActiveState Tcl (sign same as divisor) -------------------------------------------------- + + => + + - => - - + => + - - => - a b => r Ticol Tcl [%] (sign same as dividend) -------------------------------------------------- + + => + + - => + - + => - - - => - a b => r Ticol Tcl [big %] (sign same as dividend) -------------------------------------------------- + + => + + - => + - + => - - - => - Test Cases: Divided Divisor Result ---------------------------------- C/C++ mod % sign usage ---------------------------------- 123423 % 2323 = 304 + 123423 % -2323 = 304 + -123423 % 2323 = -304 - -123423 % -2323 = -304 - Ticol Tcl mod % sign usage ------------------------------ 123423 % 2323 = 304 + 123423 % -2323 = 304 + -123423 % 2323 = -304 - -123423 % -2323 = -304 - Ticol Tcl mod big % sign usage ------------------------------ 123423 % 2323 = 304 + 123423 % -2323 = 304 + -123423 % 2323 = -304 - -123423 % -2323 = -304 - Common pitfalls --------------- "When either a or n is negative, the naive definition breaks down and programming languages differ in how these values are defined" (Wikipedia) "When the result of a modulo operation has the sign of the dividend, it can lead to surprising mistakes. For example, to test if an integer is odd, one might be inclined to test if the remainder by 2 is equal to 1: bool is_odd(int n) { return n % 2 == 1; } But in a language where modulo has the sign of the dividend, that is incorrect, because when n (the dividend) is negative and odd, n mod 2 returns -1, and the function returns false. One correct alternative is to test that it is not 0 (because remainder 0 is the same regardless of the signs): bool is_odd(int n) { return n % 2 != 0; } Or, by understanding in the first place that for any odd number, the modulo remainder may be either 1 or -1: bool is_odd(int n) { return n % 2 == 1 || n % 2 == -1; } See: https://en.wikipedia.org/wiki/Modulo_operation See also: mod, big mod, math
Ticol Macro PreProcessor (MPP)  Top  
The Ticol Macro Preprocesor or MPP is used to enhance the flexibility of Tcl comments, to add C-like conditional blocks and to preprocess static aspects of a source script in order to speed up execution The MPP runs when a file is executed or loaded from the command-line and the Ticol Command Line Interface (CLI). Ticol is optimised for small script files of under about 100Kb and some runtime processing is offloaded to the MPP Ticol will be slower to load larger files The PreProcessor completely strips all Tcl and "C"-style comments and superfluous whitespace from a file as well as making basic syntax checks for mismatched brackets, braces and double quotes It not only performs useful substitution and conditional execution but when combined with [calc] it will pre-solve any constant expressions and perform as much computation on the source file before runtime (See: calc) Enhanced C-like macro commands are processed by the PreProcessor. These include conditional #define, #ifdef, #else, #endif blocks as well as macro variables. For more information see: help macro C-like const escape sequences within strings, such as \t or \n, are translated by the MPP. Tcl non-const escape sequences such as \$ will be evaluated 'on-the-fly' (see: escape, unescape) Const hexadecimal, octal and binary numbers such as 0x123, 0o123 or 0b111 are translated to decimal by the MPP. Values which are not to be translated must be supplied as quoted strings. Other than escape sequences, string contents are not processed. If you don't want this to happen, wrap the const values in double-quotes The PreProcessor may be disabled on the command-line with the /NP argument or from the CLI using: option preprocessor off Scripts can be run the MPP disabled using /NP, but they must not include macro blocks "C" style comments or other non-standard aspects of Tcl syntax The PreProcessor is not applied to direct CLI console input, only to scripts Include files are not supported by the MPP A special/reserved variable 'NDEBUG' is used to globally disable the [assert] command (case is insignificant). For more information see: assert For more details of macro commands etc. See macro For an example of a good macro system for standard Tcl, see 'Sugar' http://wiki.tcl.tk/11156 See also: cli, macro, debugging, escape, unescape, assert
Preset Global Variables and Constants  Top  
The following constants or variables are preset on loading Ticol: Variable Type Description or Example ---------------------------------------------------------------------- ::env() Array Const array of Windows environment variables Subscripts are converted to upper-case indices are case-sensitive in Tcl ::argv() Array Const array of command line arguments ::exe_name Const C:\VC5\MyProjects\picol\Release\ticol.exe ::false Const 0 ::true Const 1 ::eof Const -1 ::qbf Const The quick brown fox jumps over the lazy dog ::euler Const 2.71828182845904523 ::pi Const 3.14159265358979323 ::theta Const 1.61803398874989484 ::NAN Const -1.#IND00000000000 ::win64 Const Boolean. Whether Windows is 64-bit or not ::tcl_cli Const Boolean. Set to 1 if running from the CLI ::tcl_date Const Ticol compilation date/time ::tcl_threaded Const Boolean. Set to 1 if threaded compile of Ticol ::tcl_version Const Ticol version ::tcl_precision Const 2. Set in TICOL.INI ::errorCode Var Tcl error code sent to a the console ::errorLine Var May be preset using the #__LINE__ macro ::errorMsg Var Error message generated by a Ticol error Fatal exceptions generate no errorMsg variable ::errorInfo Var Additional information Environment variables may be set as individual constants. This depends on the Windows version in use Use the command [vars -const] to display all known constants on loading See also: argv, global variable, global, upvar
Print Functions  Top  
See the following topics: puts Simple print output format Format strings for output with puts printf Formatted print similar to C's printf() newline Output a new line textcolor Set the colour of the text output See also: Ticol
printf  Top  
integer [printf format-string|literal ?arg? ...] Print command and wrapper for [format]. Calls [format] and outputs the result after unescaping backslash escape sequences [printf] emulates the C/C++ printf function. [printf] returns the count of (escaped) characters output to the console [printf string args] is functionally identical to [puts [format string args]] Line Endings: [printf] issues no standard Windows CRLF pairs (0x0d,0x0a) or \r\n If you wish to print newlines you must append suitable \r\n escape character sequences within a supplied string argument Example: printf "%s %li 0x%x %3.2f\n" "Hello" 12345 987654 $pi Result: Hello 12345 0xf1206 3.14 Example: (Source: https://www.tcl.tk/man/tcl8.4/TclCmd/format.htm) puts "+-------------------------+" puts "| 64-bit printf demo |" set sep +-[string repeat - $w1]-+-[string repeat - $w2]-+ printf "$sep\r\n" printf "| %-*s | %-*s |\r\n" $w1 "Index" $w2 "Power" printf "$sep\r\n" # Print the contents of the table option expression on set p 1 for {set i 0} {$i<=30} {incr i} { printf "| %*d | %*I64i |\r\n" $w1 $i $w2 $p set p [expr "wide($p) * 3"] } printf "$sep\r\n" Result: +-------------------------+ | 64-bit printf demo | +-------+-----------------+ | Index | Power | +-------+-----------------+ | 0 | 1 | | 1 | 3 | | 2 | 9 | | 3 | 27 | | 4 | 81 | | 5 | 243 | | 6 | 729 | | 7 | 2187 | | 8 | 6561 | | 9 | 19683 | | 10 | 59049 | | 11 | 177147 | | 12 | 531441 | | 13 | 1594323 | | 14 | 4782969 | | 15 | 14348907 | | 16 | 43046721 | | 17 | 129140163 | | 18 | 387420489 | | 19 | 1162261467 | | 20 | 3486784401 | | 21 | 10460353203 | | 22 | 31381059609 | | 23 | 94143178827 | | 24 | 282429536481 | | 25 | 847288609443 | | 26 | 2541865828329 | | 27 | 7625597484987 | | 28 | 22876792454961 | | 29 | 68630377364883 | | 30 | 205891132094649 | +-------+-----------------+ Note: The big math plugin module can be used to extend the number range (See: big math) See: format and format string for more details See also: echo, puts, format, format string
procs (info procs) ?glob-pattern?  Top  
Returns a Tcl list of user-defined procedures. These will also be included in the [commands] list. Example: option echo on procs procs c??e procs t*n set env(temp) # Escaped puts $env(temp) # Unescaped Result: cube rainbow square testmean cube testmean C:\\Users\\Administrator\\AppData\\Local\\Temp # Escaped C:\Users\Admin\AppData\Local\Temp # Unescaped Use: option echo on to display directly to the console See also: commands, functions, info
Passing Structs to a Procedure By Name  Top  
Although Ticol structs are designed primarily to facilitate communication with external DLL routines they can also be used internally within script procedures (procs) Due to the non-binary nature of Tcl, dealing with structs is not as easy or as transparent as when using a language such as C or C++. A struct may contain direct instances of simple Tcl variables such as string, list, integer or double as well as references to complex abstract data types such as Array, Stack or Struct To pass a struct to a proc you will need to pass it by name value (See: pass by name) With Tcl procedures any variable passed by name will need to be referenced either via the global '::' scope prefix or a local alias created using [upvar]. Each referenced struct field requires either a variable aliased using [upvar] or '::' or a command which can make use of the struct variable itself such as [struct item] or [array item] Once you have created a local reference to the struct you can also, if necessary create member field references using [upvar] Struct member fields can be read as well as written back to and the original struct members are updated when the proc exits Structs may contain references to other structs but as this can get rather complex it is best avoided Example: proc print_arg {value} { upvar $value textcolor green if {[eq [type $value] stack]} { puts "Stack: '[stack item $value 0]'" } elseif {[eq [type $value] array]} { puts "Array: [array item $value 1]" } elseif {[eq [type $value] struct]} { textcolor cyan puts "Struct $value item(s):" puts "i: '[set ::[struct item $value ${value}.i]]'" puts "f: '[set ::[struct item $value ${value}.f]]'" puts "r: '[set ::[struct item $value ${value}.r]]'" puts "s: '[struct item $value ${value}.s]'" puts "a: '[array item ::[struct item $value ${value}.a] 1]'" puts "k: '[stack item ::[struct item $value ${value}.k] 0]'" } else { puts "String or number $value is [set $value]" } textcolor } struct ts { # Test struct: holding various data types a 20 # Array k 20 # Stack i 20 # Integer Literal f 40 # Double/Float Literal s 256 # String Literal r 20 # String Reference } set i 123456789 struct set ts.i i set f $pi struct set ts.f f set r "Hello string" struct set ts.r r struct set ts.s "Hello literal string" #puts "check: [ofaddress ts.s]" # Debug check set a(1) "This is array item 1" struct set ts.a a stack create stk 200 stack push stk "Hello stack" struct set ts.k stk print_arg s # Pass a variable by name print_arg i # Pass a variable by name print_arg f # Pass a variable by name print_arg a # Pass a variable by name print_arg stk # Pass a stack by name newline print_arg ts # Pass a struct by name See also: struct, proc, calling by name
pointers  Top  
Access to pointers is not a native feature of Tcl. A modest level of pointer manipulation can be carried out in Ticol in order to facilitate the marshalling of data using structs or binary values via a [calldll] call The key commands are: struct, setb and ofaddressb struct test {f 4} # Declare struct with member 'f' of 4 bytes width # The struct will have 4 bytes of memory allocated struct setb f 4321 # Set the struct member field to binary value 4321 puts $f # Show the memory address pointed to by member 'f' puts [ofaddressb f] # Dereference the struct pointer to get the value struct unset test # Delete See also: calldll, addressofb, addressof, ofaddress
puts  Top  
puts ?stream|stdout? string ?-nonewline? puts ?-nonewline? ?stream|stdout? string Print a string to the console with a trailing newline by default To enhance performance [puts] returns a NULL value ("") rather than allocate and return the supplied string merely to be discarded in most cases Buffered output is configured for stdout by default. This may be disabled using the /NB (no buffer) argument when you launch Ticol. However this may result in no output under certain conditions until a program exits. If your code produces delayed output then you may also use the [flush] command at critical locations in order to force output Line endings: [puts] issues a standard Windows CRLF pair (0x0d,0x0a) or \r\n Use: option echo on to display command returns directly to the console without using [puts] or [printf] Alternatives: Use: set varname with [option echo on] to display unescaped the variable contents Use with [gotoxy]: If using [puts] with absolute screen coordinates via [gotoxy] you should use the -nonewline argument if possible to avoid screen scrolling issues Example: option expression off for {set i 0} {< $i 10} {++ i} { gotoxy 5 5 puts "I am at 5,5" -nonewline } [puts] examples: Example: puts "Hello from Tcl" -nonewline set a "Hello World" puts stdout $a set fp [open "test.txt" wb] puts $fp # Display the file handle (4582320) puts fp "Hello file" close fp Example: (Source: https://www.tcl.tk/man/tcl8.4/TclCmd/format.htm) puts "+-------------------------+" puts "| 64-bit integer printf |" set sep +-[string repeat - $w1]-+-[string repeat - $w2]-+ puts $sep puts [format "| %-*s | %-*s |" $w1 "Index" $w2 "Power"] puts $sep # Print the contents of the table option expression on set p 1 for {set i 0} {$i<=30} {incr i} { puts [format "| %*d | %*I64i |" $w1 $i $w2 $p] set p [expr "wide($p) * 3"] } puts $sep Result: +-------------------------+ | 64-bit integer printf | +-------+-----------------+ | Index | Power | +-------+-----------------+ | 0 | 1 | | 1 | 3 | | 2 | 9 | | 3 | 27 | | 4 | 81 | | 5 | 243 | | 6 | 729 | | 7 | 2187 | | 8 | 6561 | | 9 | 19683 | | 10 | 59049 | | 11 | 177147 | | 12 | 531441 | | 13 | 1594323 | | 14 | 4782969 | | 15 | 14348907 | | 16 | 43046721 | | 17 | 129140163 | | 18 | 387420489 | | 19 | 1162261467 | | 20 | 3486784401 | | 21 | 10460353203 | | 22 | 31381059609 | | 23 | 94143178827 | | 24 | 282429536481 | | 25 | 847288609443 | | 26 | 2541865828329 | | 27 | 7625597484987 | | 28 | 22876792454961 | | 29 | 68630377364883 | | 30 | 205891132094649 | +-------+-----------------+ See also: echo, format, printf, set, file open, pause
qbf  Top  
A test constant defined as: "The quick brown fox jumps over the lazy dog" See also: preset globals, const, vars
Decimal to Roman Conversion Plugin  Top  
Roman to decimal conversion. The maximum value which can be converted from decimal is 10000. Values above this will thrown a Tcl exception To load, use: lib ticol_r2d?.dll? ?-verbose? ?-nocomplain? Commands: string [decimal_to_roman integer] integer [roman_to_decimal roman-value] Examples: lib ticol_r2d puts [decimal_to_roman 1776] puts [roman_to_decimal MDCCLXXVI] puts [roman_to_decimal [decimal_to_roman 1776]] Results: MDCCLXXVI 1776 1776 See also; plugins
RTF Output Plugin  Top  
Simple conversion of plain text, outputting to an RTF file To load, use: lib ticol_rtf?.dll? ?-verbose? ?-nocomplain? Commands: rtf write filename text ?-y? ?-font name? ?-fs N? ?-rtf? Where: -y Overwrite any existing file -font Name of the font (as it appears in Windows) e.g. "Courier New" or "Tahoma" May be repeated to define multiple fonts Each font will be registered as: \f0, \f1 etc. The first font will be the default (font 0) \f0 -fs Default font size in points e.g. -fs 10 for 10 point May be repeated to define multiple fonts (see -font) -rtf Specifies that the text will be supplied in RTF format (excluding headers). This allows custom RTF codes to be inserted into the body and resolve clashes with single- backslash Ticol escape codes. If -rtf is omitted and RTF escape-codes given then the codes will be mis-transformed on output If -rtf is omitted then \\ codes will not be escaped If -rtf used then \\ codes will require [unescape \\x] Thus you can use "\par [unescape \\b\\fs20]" -rtf where this would otherwise embed "\f" (formfeed) and "\b" (backspace) -colourtable <rtf-code> (excluding CRLF) Example: -colourtable "\{\colortbl ;\\red255\\green0\\blue0;\}" The internal default is: {\\colortbl ;\ \\red255\\green0\\blue0;\ \\red0\\green255\\blue0;\ \\red0\\green0\\blue255;} Example: rtf write test.rtf $qbf -y -font "Courier New" -fs 12 Notes: RTF commands may be entered into the text string Since backslash sequences can be complex in Tcl, inserting backslash sequences correctly can sometimes be problematic, you may use [chr 92] to avoid complications. e.g. for "\f0 use" "[chr 92]f0" Where there are conflicts with C++/Tcl escape sequences, literal RTF command characters present in the source-text may need to be escaped. e.g. (where $q contains our text) Remember to use the -rtf argument when calling [rtf write]: [string replace $q "{" "\{"] # Curly braces [string replace $q [unescape "\\"] [unescape "\\\\"]] # Backslashes or (within source file): append s [unescape "\\page\\f1\\fs32\\b "] append s $q append s [unescape "\\b0\\fs18\\f0 \r\n\r\n\\par "] Due to backslash translation issues, RTF backslash commands should ideally be executed from source files not the CLI. CLI use would require: option escape on, option autoexec off Example: lib ticol_rtf # Load the plugin library rtf write testrtf.rtf "[unescape \\fs32\\b] $qbf [\\b0]" -rtf -y @ start testrtf.rtf # Display the final RTF text A More Complex Example: # Write a complex RTF document # This demonstrates a multi-line string with line-continuation chars # and trailing comments after multi-line string continuations set ct "{\\colortbl ;\ # Start custom colour table \\red255\\green0\\blue0;\ # 1: Red \\red0\\green255\\blue0;\ # 2: Green \\red0\\green0\\blue255;\ # 3: Blue \\red255\\green255\\blue0;\ # 4: Yellow (for highlighting) \\red128\\green0\\blue255;}" # 5: Violet lib ticol_rtf # Load the plugin library # Write the body text rtf write $filename "The \ul quick\ulnone [unescape \\super\\cf1] \ brown [unescape \\cf0\\nosupersub\\f1] fox \ [unescape \\f0\\fs32\\b\\highlight4\\f2] \ jumps\par over [unescape \\f0\\highlight0] the \ [unescape \\fs64] \ la\cf5 z\cf0 y [unescape \\fs20\\b0] dog!"\ -rtf -y -colourtable [unescape $ct]\ -font Tahoma -font "Courier New" -font "Segoe Script" @ type testrtf.rtf # Display the raw RTF code @ start testrtf.rtf # Display the final RTF text Demo Script: A demo script is included with Ticol which will convert this man file to RTF which is called man_to_rtf.tcl Useful commands include: readfile, append See also: plugins, chr, unescape, Google search re: RTF control codes
randomstr  Top  
string [randomstr length ?style?] Create a random string of characters in varying formats and of a given length Style values (where style is a positive integer): 0 Mixed upper/lower case 1 Upper case letters 2 Lower case letters 3 Numbers (0..9) 4 Upper/lower case letters and numbers (0..9) 5 Binary data in the range 0x00..0xFF 6 Hexadecimal numbers 0..9, A..F (capitals) 7 Binary string (even bias) 8 Binary string with bias to 0 9 Binary string with bias to 1 10 Hexadecimal numbers 0..9, A..F (lower-case) 11 Printable ASCII characters 33 to 127 except 96 12 All hexadecimal characters (upper/lower case) 13 Octal characters (0..7) 14 Password style 0..9, a..z, A..Z . - % # 15 Safe-readable (confusing characters avoided) 16 Alphanumeric upper-case 0..9, A.,Z You may define an [enum] to hold the const values enum { RANDOM_STYLE_MIXED RANDOM_STYLE_LOWER RANDOM_STYLE_UPPER RANDOM_STYLE_NUMBERS RANDOM_STYLE_ALL RANDOM_STYLE_BINSTR RANDOM_STYLE_HEX RANDOM_STYLE_BINARY RANDOM_STYLE_BINARYBIAS0 RANDOM_STYLE_BINARYBIAS1 RANDOM_STYLE_HEX_LOWER RANDOM_STYLE_PRINTABLE RANDOM_STYLE_HEXALL RANDOM_STYLE_OCTAL RANDOM_STYLE_PASSWORD RANDOM_STYLE_SAFE RANDOM_STYLE_ALNUM_UPPER RANDOM_STYLE_MAX } Example: # Display a row of 20 chars of each type of random string option expression off for {set i 0} {< $i
17} {++ i} {printf "%2i:[randomstr 20 $i]\r\n" $i
} Result: 0:YAscKInuJAjvYtxkPpNr 1:qawbgcfcehedfewghkpc 2:SRLQMENLFPKMLDADKSPL 3:31183734177678368924 4:Ukwj71Pk9LvrBwjbO3p9 5:/,-'??t- 6:5991668E260A498F6BA5 7:11001000110111001000 8:00100100011011010000 9:00011010111111111110 10:8173dc3d3a0df1533a19 11:>eMTb_L'ADs9_4U;E,$p 12:6E646D5D826C3d5063C6 13:34575216245752571651 14::lGf#M5f#V:UbXM3xcHr 15:fyU2A1JkmS7dpEx6MpJJ 16:SF8NIL3J35Y7OH1729CM See also: rnd, randomise
range  Top  
string [range charset ?charset? ...] range returns a string of characters generated from 'charset' where charset is a hyphenated pair of characters: e.g. A-Z or 0-9 Any character pair can be selected in the printable ANSI character set Multiple character sets are accepted and descending ranges (Z-A) are accepted If the RValue of a character pair is absent then 255 is assumed: e.g. "X-" A range character may be specified using the [asc] command... e.g. puts [range [chr 26]-c] Examples: puts [range 0-9 z-w F-J] puts [range 9-0 Z-A] Results: 0123456789zyxwFGHIJ 9876543210ZYXWVUTSRQPONMLKJIHGFEDCBA See also: string, randomstr
read  Top  
read filenum ?bytes? Read data from an open file stream, as opened with the [open] command Example: set fp [open "input.txt" r] set data [read $fp] puts $data close $fp See also: open, file, readfile
readfile  Top  
readfile filename ?varname | -? ?-array? ?-max N? Reads data from a file in binary mode, optionally passing into a variable Where a variable is specified, readfile returns the count of bytes, otherwise the read-in data block is returned The filename should be given unescaped if it contains backslash characters Certain variables such as $argv() are stored in escaped format. Direct user input routines may store an unescaped string which may be passed directly Example: readfile [unescape $argv(1)] a -array Alternately, Unix-style forward slashes '/' may be used If -max is specified combined with -array, then this will limit the maximum number of lines, otherwise it will limit the total number of bytes read-in If the -array argument is given then the file will be written to a Tcl array with an integer subscript of index base 0. The return value in this case will be the number of lines in the array. You can use [array walk arrayName] to inspect the array or [for] to iterate it efficiently Varname may be omitted by specifying a - sign. This will allow a byte-count to be specified without specifying a variable. Example: puts [readfile autoexec.bat q] Result: 1031 Example: puts [readfile autoexec.bat q -max 200] Result 200 Example: # Read autoexec.tcl to an array variable option expression on readfile autoexec.tcl a -array for {set i 0} {$i < [array size a]} {incr i} {puts $i:$a($i)} Result: <prints out file the contents> See also: read, file
Recursion and Issues Arising  Top  
Recursion and recursive proc calls should be controlled to avoid excessive nesting, otherwise the interpreter will run out of memory. Well-designed routines should not need to recurse deeply The maximum command/proc recursion depth is set to 5000. If secondary command calls are nested then this level may be significantly lower and may result in a non-fatal exception error Additionally, the breakpoint debugger stack will track only the first 100 command calls, after which no further traces will be stored Example: # This routine will trigger a recursion-depth exception proc foo {} { set ::highest_level [max $::highest_level [info level]] puts $::highest_level foo # Uncontrolled recursive call } foo # Start a Stack Overflow See also: proc
regex  Top  
regex (regular expressions) are not supported See: scan
reserved variables  Top  
Ticol reserves a number of variables for internal use These values are protected against deletion by [clear] and [run] argv const string argv0 const string argc const integer eof const integer env array euler const float exe_name const string false const integer NAN const string pi const float qbf const string tcl_date const string tcl_precision const integer tcl_version const string theta const float this undefined. Defined dynamically during evaluation true const integer win64 const integer See also: $this
rename  Top  
bool [rename oldname newname] Rename a procedure (proc). This may be used to temporarily 'hide' or replace an existing procedure. Example: proc square {x} { * $x $x } rename square skware puts [skware 10] Result: 100 See also: undef, file rename, ren
return  Top  
return value ?-code number|nmemonic? or: return -code number|nmemonic value [return] exits a procedure or block of code. [return] may optionally return an error code to the calling routine. There are limits to the use of [return] and it does not behave in the same way as with other languages such as C/C++ [return] will exit all nested procedures and unwind the call-stack down to proc level 0 (the root invocation level) Example: proc level_p {} { puts "in level_p" proc level_q {} { puts "in level_q" proc level_r {} { puts "In level_r" return $::true } level_r } level_q return $::false } puts [bool [level_p]] Results: True [return] will return a code value of 2 (return) for all levels > level 0 At level 0 [return] will return code 0 (ok) Return Code Values: ------------------------ Number Mnemonic ------------------------ 0 ok 1 error 2 return 3 break 4 continue ------------------------ The standard return codes can be overridden using the '-code' argument. This allows Tcl procedures to be written which extend the language and interact with system codes Whilst [return] can be used to exit structured control commands such as [if], [for], [while], [do] etc., results may be unexpected, although you may use the following to exit control structures: return -code break [return] will exit a control structure and if the code is passed back to nesting level 0 then the script will exit Example: # Will exit the script puts "I will now exit" return 23 puts "I cannot be seen" Example: ([return] cannot be used with control block) # This code will exit the for loop and script when $i == 5 for {} {[< $i 10]} {++ i} { if {[== $i 5]} { return $i puts "I will not be printed if i==5" } } Example: ([return] cannot be used with control block) # Does not exit using return at level 0 # Will iterate for 10 loops set i 0 while {[< $i 10]} { ++ i return } Executing a [return] command from a root-level flow-control block structure such as [if] will not terminate the script, if you wish to do this then use a '-code exit' argument. Example: set a [rnd 0 100] if {== a 10} {return 23 -code exit} Result: Script is exited with 22 if random value is 10 Example: goto_block { start { set i 0 while {< $i 10} { if {== $i 5} {return $i} incr i } } } puts "i is $i" Result i is 5 Using [return] with a code "ok" or 0 is the only way to return a string- literal from [eval] without it being interpreted as a command: Example: set x "Hello" puts [eval "return $x -code ok"] Result: Hello See also: break, continue, stop, exit, if, while, foreach
replacechar  Top  
integer [replacechar variable search replace] Performs an in-situ replace of characters specified by 'search' with 'replace'. Because [replacechar] opreates on a variable name it avoids the need for internal and external copy-reassignment which makes it more efficient with very large strings [replacechar] currently accepts only simple variables (not array type) Use [string replace] to replace characters within strings Only the first character of the 'search' and 'replace' arguments are significant. Each of these arguments must either be a string or a character representation of an integer using [chr] [replacechar] should be used in preference to [string replace] with reassignment when replacing single characters [replacechar] takes a variable name as it's first argument, not a string this also avoids dereference and copy A count of the number of characters replaced is returned Example: set s [readfile ticol.man] replacechar s "\t" " " Example: set s [readfile ticol.man] replacechar t1 [chr 0x09] [chr 0x20] See also: string replace
rewind  Top  
bool [rewind handle] Rewind the file stream pointer for a given file handle. The handle must have been opened using [open] or [file open] See also: tell, seek, open, file
right, string right  Top  
string [right variable n] string [string right variable n] Return the rightmost 'n' characters of a string If n < 1 then an empty string will be returned If n >= length of 'variable' then the whole string will be returned Example: puts [right $qbf 3] Result: dog See also: left, mid
rnd  Top  
integer [rnd low high] Return a random number between 'low' and 'high' Example: rnd 10 200 Result: 42 The big math library can return larger random numbers (See: big) See also: rand, srand, randomstr, math
round  Top  
double [round number ?places?] Correct rounding to a given number of decimal places [round] and round() follow PHP's PHP_ROUND_HALF_UP which rounds values up to 'places' decimal places away from zero, when it is half way there. Making 1.5 into 2 and -1.5 into -2 Example: puts [round [expr "22.0/7"] 3] Result: 3.143 Example: puts [round 1.5 0] Result: 2 Example: puts [round -1.5 0] Result: -2 See also: math, format
rset  Top  
string [rset target-variable source-variable | source-string] Insert source string or variable into the target, right-aligned [rset] is based on the common BASIC command and is most usefully used in combination with [makestr] Example: set s [makestr 20 *] rset s "hello" puts $s Result: ***************hello Example: (Blank out part of a string) set s "0849 666 616" rset s [string repeat * 7] puts "'$s'" Result: 0849 ******* See also: makestr, lset, mid, strstr, string
run - (Tcl script)  Top  
run filename?.tcl? ?argument? ?argument...? run filename.tcx ?-password password? ?argument? ?argument...? run # Pre-loaded script (arguments are not allowed) See also: [clearprocs] Run a Tcl file from the CLI interpreter shell. [source] is the standard Tcl command and this is aliased as [run] in Ticol [run filename] will load and run the specified filename and this form will accept arguments. It will also decrypt and run obfuscated TCX files [run] will internally call [clear]. If you wish to keep existing variables use [eval] instead. Use [clearprocs] to clear any currently defined procedures For threaded compiles of Ticol, [run] is not allowed whilst threads are active as it will clear all variables and procedures If a path is not given to the script then Ticol will look for the script in the current directory Use [run] without an argument if the file has already been loaded using [load]. Arguments cannot be specified [run] and [source] must NOT be used to chain from one script to another. Use [eval] instead Note that TCX protected files which are encoded with the /C:PASSWORD argument will require the password to be specified using a '-password password' argument. Files encrypted using other methods will be self-decrypting using automatic credentials. This password may be a phrase, user-name, MAC address, workstation or Ticol version. The resulting TCX file will be locked accordingly [eval] may also be used to execute a non-obfuscated or obfuscated Ticol script file (without arguments) Use [dump] to display non-encrypted (obfuscated) loaded source code to the console and optionally to a Tcl variable The [run] command will clear the user-level variable table including non- system level consts and will reset the interpreter command count To call a child script and return to the parent use [eval scriptname] To run a script in elevated mode, use: [elevate scriptname] Example: ticol> run test.tcl ticol> dump Result: test.tcl is executed The script is displayed See also: clearprocs, eval, load, dump, exit
Running Scripts  Top  
Scripts may be run in a number of ways, either with or without arguments Example: ticol.exe # Load the CLI load myscript # Load the script dump # Inspect it run # Run it (no args allowed) Example: ticol.exe # Load the CLI run myscript arg1 arg2 # Run script from CLI with args Example: ticol.exe # Load the CLI eval myscript.tcl arg1 arg2 # Run using eval Example: ticol.exe myscript arg1 arg2 # Run from Windows CLI See also: load, run, eval
scan  Top  
string [scan string format-mask ?variable?...] [scan] parses a string using conversion specifiers in the style of C sscanf This command parses substrings from an input string in a fashion similar to the ANSI C sscanf function and returns a count of the number of conversions successfully performed or -1 if the end of the input string is reached before any conversions have been performed The string parameter is the input to be parsed and the format parameter indicates how to parse it, using % conversion specifiers. Each variable is a name of a new variable to be created or set When a substring is scanned from string that matches a conversion specifier, the substring is assigned to the corresponding variable. If no variables are specified, then scan works in an inline manner, returning the data that would otherwise be stored in the variables as a list. In the inline case, an empty string is returned when the end of the input string is reached before any conversions have been performed. printf style alignment and precision values are not supported by [scan] e.g. %-.2s. Width values are; e.g. %2s An asterisk (*) following the percent sign indicates that the value is to be discarded and not stored in a variable The use of %$ is unsupported Example: puts [scan "hello there 1 $pi 12" {%s %*s %i %4f %2x} s t p q] puts $s,$t,$p,$q Result: hello,1,3.140000,12 Example: set ip scan $ip %d.%d.%d.%d o1 o2 o3 o4 vars o* Result: o1 12 o2 34 o3 56 o4 78 Example: # Scan an ISO date into [date] format scan 20161122 %4i%2i%2i y m d puts "$y/$m/$d" Result: 2016/11/22 See also: format, printf
screen  Top  
screen width | height | attribute | curx | cury Note that Windows 10 can dynamically resize the console window and may auto-resize a console if you drag it from one monitor to another on a multiple-monitor system. This may cause screen formatting to become misaligned You can query [screen width] to check for a resized console window See [console] for specific console functions Query screen metrics Example: puts [screen width],[screen height] Result 80,25 See also: console, gotoxy, box, msgbox