Tcl is a scripting language which is designed to be embedded in applications. It can be embedded in applications that present command-line interfaces (the Tornado shell, for example) as well as in those that do not (such as the browser). Almost any program can benefit from the inclusion of such a language, because it provides a way for users to combine the program's features in new and unforeseen ways to meet their own needs. Many programs implement a command-line interface that is unique to the particular application. However, application-specific command line interfaces often have weak languages. Tcl holds some promise of unifying application command languages. This has an additional benefit: the more programs use a common language, the easier it is for everyone to learn to use each additional program that incorporates the language.
To encourage widespread adoption, John Ousterhout (the creator of Tcl) has placed the language and its implementation in the public domain.
Tk is often mentioned in conjunction with Tcl. Tk is a graphics library that extends Tcl with graphical-interface facilities. Tornado does not currently use Tk, but you may find Tk useful for your own Tcl applications.
Tcl represents all data as ordinary text strings. As you might expect, the string-handling features of Tcl are particularly strong. However, Tcl also provides a full complement of C-like arithmetic operators to manipulate strings that represent numbers.
The examples in the following sections exhibit some of the fundamental mechanisms of the Tcl language, in order to provide some of the flavor of working in Tcl. However, this is only an introduction.
For documentation on all Tcl interfaces in Tornado (as well as on C interfaces), see the Tornado API Programmer's Guide from Wind River.
For the Tcl language itself, the following generally available books are helpful:
The last examples use curly braces to delimit list items, yielding "lists of lists." This powerful technique, especially combined with recursive command substitution (see C.2.4 Command Substitution), can provide a little of the flavor of Lisp in Tcl programs.
Tcl arrays are all associative arrays, using a parenthesized key to select or define a particular element of an array: arrayName(keyString). The keyString may in fact represent a number, giving the effect of ordinary indexed arrays. The following are some examples of expressions involving Tcl arrays:
The last example selects from a list of lists (defined among the examples in C.2.2 Lists in Tcl). This and the previous example show that you can nest Tcl command substitutions readily. The Tcl interpreter substitutes the most deeply nested command, then continues substituting recursively until it can evaluate the outermost command.
Procedure definition in Tcl is straightforward, and resembles many other languages. The command proc builds a procedure from its arguments, which give the procedure name, a list of its arguments, and a sequence of statements for the procedure body. In the body, the return command specifies the result of the procedure. For example, the following defines a procedure to compute the square of a number:
proc square {i} {
return [expr $i * $i]
}
If a procedure's argument list ends with the word args, the result is a procedure that can be called with any number of arguments. All trailing arguments are captured in a list $args. For example, the following procedure calculates the sum of all its arguments:
proc sum {args} {
set accum 0
foreach item $args {
incr accum $item
}
return $accum
}
Defined Tcl procedures are called by name, and can be used just like any other Tcl command. The following examples illustrate some possibilities:
The technique illustrated by the last example--constructing a procedure name "on the fly"--is used extensively by Tornado tools to group a set of related procedures. The effect is similar to what can be achieved with function pointers in C.
For example, in Tornado tools, events are represented in Tcl as structured strings. The first element of the string is the name of the event. Tcl scripts that handle events can search for the appropriate procedure to handle a particular event by mapping the event name to a procedure name, and calling that procedure if it exists. The following Tcl script demonstrates this approach:
proc shEventDispatch {event} {
set handlerProc "[lindex $event 0]_Handler"
if {[info procs $handlerProc] != ""} {
$handlerProc $event
} {
#event has no handler--do nothing.
}
}
Tcl provides all the popular control structures: conditionals (if), loops (while, for, and foreach), case statements (switch), and explicit variable-scope control (global, upvar, and uplevel variable declarations). By using these facilities, you can even define your own control structures. While there is nothing mysterious about these facilities, more detailed descriptions are beyond the scope of this summary. For detailed information, see the books cited at the beginning of C.2 Introduction to Tcl.
Every Tcl procedure, whether built-in or script, normally returns a string. Tcl procedures may signal an error instead: in a defined procedure, this is done with the error command. This starts a process called unwinding. When a procedure signals an error, it passes to its caller a string containing information about the error. Control is passed to the calling procedure. If that procedure did not provide for this possibility by using the Tcl catch command, control is passed to its caller in turn. This recursive unwinding continues until the top level, the Tcl interpreter, is reached.
As control is passed along, any procedure can catch the error and take one of two actions: signal another error and provide error information, or work around the error and return as usual, ending the unwinding process.
At each unwinding step, the Tcl interpreter adds a description of the current execution context to the Tcl variable errorInfo. After unwinding ends, you can display errorInfo to trace error information. Another variable, errorCode, may contain diagnostic information, such as an operating system dependent error code returned by a system call.
Tcl is designed to integrate with C applications. The Tcl interpreter itself is distributed as a library, ready to link with other applications. The core of the Tcl integration strategy is to allow each application to add its own commands to the Tcl language. This is accomplished primarily through the subroutine Tcl_CreateCommand( ) in the Tcl interpreter library, which associates a new Tcl command name and a pointer to an application-specific routine. For more details, consult the Tcl books cited at the beginning of C.2 Introduction to Tcl.