Tcl Manual

download Tcl Manual

of 30

Transcript of Tcl Manual

  • 7/31/2019 Tcl Manual

    1/30

    Bonus Chapter A

    Tcl: Tool Command LanguageIn this chapter, well take a look at an exciting development in the Linux world: an extensible, embeddableprogramming language that is taking the community by storm. Tcl (pronounced tickle) has beendeveloped by John Ousterhout and others over a number of years and is now maintained by Scriptics(http://www.scriptics.com). It has become a popular choice of programming language for a diverse range ofapplications, ranging from fast prototype tools through extension languages to industrial controlapplications. Tcl is also available on other platforms, including Microsoft Windows and Apple MacOS.

    Well take a look at some of the key features of Tcl, including its extensibility and its use as the interactiveinterface to new applications, and youll also see some of the extensions and applications that have beencreated. Some of the things well be covering in this chapter are

    Tcl commands and control structures

    Quoting and substitution

    Strings and lists in Tcl

    Input and output

    Tcl extensions and applications

    A Tcl OverviewWe begin our look at Tcl with the basics: how to write and execute Tcl programs and the features of thelanguage.

    Our First Tcl Program

    To see how Tcl programs are created and executed, lets write a very simple Hello World program,hello.tcl.Heres the source of such a program:

    set s "Hello World"puts $s

    Tcl is an interpreted language, and Tcl programs are often referred to as scripts. In this respect, Tcl and theUNIX shell have a lot in common. In fact, Tcl scripts need to be executed by a Tcl shell, called tclsh.

    Lets run our sample script using tclsh. Note that running a Tcl program this way requires only file readpermission.

    $ tclsh hello.tcl

  • 7/31/2019 Tcl Manual

    2/30

    Hello World$

    As with other Linux command interpreters, we can run tclsh and it will prompt us for Tcl commands toexecute immediately. We could have just as well typed in the two lines directly:

    $ tclsh% set s "Hello World"Hello World%puts $s

    Hello World

    Notice that tclsh prompts with % and executes our commands as soon as they are typed. It keeps readinglines until it gets a complete command. We can use the source command to make tclsh take commandsfrom a file. Lets make Tcl read our program again:

    % source hello.tclHello World% exit$

    The exit command causes the Tcl shell to end and returns us to the UNIX shell. We can turn our scriptinto a UNIX program by specifying which interpreter to use on the first line, just as we did for the UNIXshell. Save the program in a file, hello2.tcl:

    #!/usr/bin/tclsh

    set s "Hello World - 2"puts $s

    Now, if we make this script executable, we can run it in the usual way. The location of the Tcl shell,tclsh, may vary from system to system. In this case, it has been installed in /usr/bin.

    Generally, you can use the whereis or which command to show where tclsh islocated within the search path.

    $ chmod +x hello2.tcl$ ./hello2.tcl

    Hello World - 2$

    Tcl CommandsIn general, all Tcl commands take the same form. They begin with a keyword and are followed by zero ormore arguments. A command is usually terminated by the end of the line, although you can use abackslash (\) at the end of the line to extend a long command over multiple lines.

    Quoting and variable substitution (to which well come shortly) take place first. Then the resultingcommand is executed. Some of these commands cause a result to be produced; others cause furthercommands to be stored for later execution, such as when procedures are defined or loops are encountered.

    Because of the fairly simple syntax, Tcl is easy to learn and simple to extend. However, it does mean thatsome operations, such as assignment and calculations, can seem a little awkward at first.

    You can place multiple Tcl commands on the same line if you separate them with semicolons.

    In this chapter, when we look at the syntax of Tcl commands, well use a notation like this:

  • 7/31/2019 Tcl Manual

    3/30

    command argument1 argument2 ?option1??option2?

    This means that the (fictitious) Tcl command, command, takes two mandatory arguments, plus someoptional arguments that may be used to change its behavior. Youll find this type of syntax used in theofficial Tcl/Tk documentation.

    Variables and ValuesTcl deals essentially with strings and groups of strings. Most values can be dealt with as strings, andwhere necessary, Tcl will automatically convert between types, for example to perform arithmetic onnumbers. To assign to a variable, creating the variable if necessary, we use the set command. You canfollow the rest of this section as a walk-through example in the Tcl shell.

    $ tclsh% set a 123123% set hello therethere%

    Variable names are case-sensitive and can be any length. Special characters (such as whitespace) invariable names and values need to be quoted, which you do by enclosing the name or value in doublequotes. As in the UNIX shell, you need to take care with quoting. Well learn more about different quotingmethods in Tcl shortly.

    % set "hello there" "fare well"fare well%

    To examine the current value of a variable, use the set command again, but this time dont give it a valueargument.

    % set hellothere% set "hello there"fare well%

    When using Tcl interactively like this, the interpreter prints the result of each command. In the case of theset command, we see the variables new value printed after an assignment, or the variables presentvalue if no new value is given. This is because the set command itself returns the current value of the

    variable.

    To use the value of a variable in another command, we prefix its name with a $, just as we do in the UNIXshell. In our example program, we assigned a string to the variable s and then used it in the putscommand, which wrote it to the screen, by referring to it as $s. You can use braces to quote variablenames that contain spaces.

    %puts $a123%puts [expr $a + $a]246%puts ${hello there}fare well%

    To use the result of one command in another, we place the command in square brackets, as in the second

    example above. This causes the Tcl interpreter to execute the command and return a result that is used inits place. This is very like the way we use $(command) in the UNIX shell. In the same example, we use theexpr command, which evaluates a Tcl expression and returns the result.

  • 7/31/2019 Tcl Manual

    4/30

    We can remove a variable from the Tcl interpreter by using unset.

    % unset a%puts $acan't read "a": no such variable

    Quoting and Substitution

    As it is in the UNIX shell, quoting is crucial in Tcl, and there are a number of different quoting andsubstitution mechanisms in Tcl that you need to understand.

    Variable SubstitutionIn a Tcl command, a variable is replaced with its value whenever its name appears preceded by a dollarsign, $. This is the mechanism we would use to pass parameters to commands and store or use generalpurpose values.

    % set apple 55% set orange $apple5%

    Command SubstitutionA command contained within square brackets, [], is executed and replaced with its result.

    % set pear [expr $orange + 1]6%

    Backslash Substitution

    We use a backslash, \, to turn off the special meaning of the following character. We can use it to createvariables and values with unusual characters (say, dollar signs) in them.

    A backslash at the end of a line is used as a continuation marker. (It negates the special meaning of thenewline character.)

    % set fred \$apple

    $apple% set lemon [expr $pear \+ 1]7%

    String QuotingWe use double quotes to create strings containing white space and other special characters. However, as itdoes in the Linux shell, this type of quoting allows substitutions to take place. Variables will be substitutedwith their values when referenced inside double quoted strings.

    % set joe "Our fruits are orange: $orange, and pear: $pear"Our fruits are orange: 5, and pear: 6%

    Brace QuotingAnother form of quoting, using braces, {}, doesnt allow variable substitutions and creates a verbatimgroup of strings. Similar to the use of single quotes in the Linux shell, braces prevent substitution.

  • 7/31/2019 Tcl Manual

    5/30

  • 7/31/2019 Tcl Manual

    6/30

    \$word backslash $word

    If the results contain further variable references or nested commands, these are not expanded. Thisconsistency means that the execution of a Tcl command is predictable. However, you do need to carefullyconsider your choice of quoting method. Lets try to make it clearer with an example or two.

    % set age 3535

    % set str {I'm $age years old}I'm $age years old% set cmd {puts "$str"}puts "$str"%

    These assignments set up two levels of indirection. The variable cmd refers to the variable str, which, inturn, refers to the variable age, which has the value 35. If we wish to use cmd to get at the value of age,we must arrange for additional substitutions.We can gain additional rounds of substitutions using eval or explicitly by calling the subst command,which is implemented in Tcl versions 7.4 and above. The eval command takes its arguments, gathersthem together as a single string, and then passes this string to the Tcl interpreter, which executes it.

    % eval $cmdI'm $age years old%

    The value of cmdthe command puts"$str"is executed. The string, str, has the value I'm$ageyearsold. If we want to expand this string before performing the puts command, we need to usesubst. The subst command performs variable, command, and backslash substitutions on strings andthen returns the newly formed string. The difference is that the argument to eval must be a command,which is executed. subst performs substitution but doesnt evaluate the result.

    % subst $cmdputs "I'm $age years old"%

    Here, the subst command returns a valid command, which will output a string containing the currentvalue of age at the time it is evaluated.

    % eval [subst $cmd]

    I'm 35 years old%

    The control of substitution and execution makes Tcl a very powerful tool. Because the eval command canexecute an arbitrary string, Tcl programs can communicate and pass commands for execution to oneanother. You can use this technique to develop Tcl debuggers in Tcl itself which control the execution ofother Tcl programs. You can also use it in Internet programming, where a server application may wish tosend a program to the client for execution, or may generate a Tcl script on the fly.

    CommentsTcl programs may contain comments. Comments act almost as if they were a Tcl command with the name#, which has no effect. This means that, unlike some similar languages, we can continue across many lines

    by ending each line with a trailing backslash. One peculiarity is that semicolons are not significant incomments, so they can continue after one.

    # This is a comment

  • 7/31/2019 Tcl Manual

    7/30

    set a 123 ; # This is a trailing comment, note the semicolon is needed to separate it\but the comment continues onto this line; and this is still comment

    Calculation

    Tcl provides a command, expr, to perform arithmetic calculations. This is because the Tcl interpreter itselfdoesnt contain mathematical functions; rather it relies on additional functionality provided bycommands. Although Tcl can perform limited arithmetic, such as that required for loop termination, thebulk of calculation is carried out by expr.

    The expr command takes one or more arguments and calculates a result. The arguments may beoperands, operators, and parentheses. Operands may be specified as numbers (integers or floating point),logical expressions, strings that will be converted to numeric values (including substitutions), variablereferences, and nested commands.

    Examples are

    % expr 5 + 510% set a 55% set b 66

    % expr $a+$b11% expr 2*"$a.$b"11.2% expr 3*(1+[string length "hello"])18%

    Valid operators for expr are listed below, in decreasing order of precedence. Comparison operatorsproduce 1 for true, 0 for false.

    Operator Precedence Description

    - + ~ ! Unary minus and plus, bitwise NOT, logicalNOT.

    * / % Multiply, divide, remainder.

    + - Add, subtract.

    > Shift left, shift right (both signed).

    < > = Less than, greater than, less than or equal, greaterthan or equal.

    == != Equal, not equal.

    & Bitwise AND.

    ^ Bitwise XOR.

    | Bitwise OR.

    && Logical AND.

    || Logical OR.

  • 7/31/2019 Tcl Manual

    8/30

    cond?yes:no Ternary conditional, as in C. If cond is nonzero,return the value of yes, else return the value ofno.

    As an example of the last operator, consider the following:

    % set k "foo"foo% set result [expr {($k == "foo") ? "pass" : "fail"}]pass%

    Tcl also supports the following mathematical functions in expressions, each of which invokes the mathlibrary function of the same name:

    acos asin atan atan2

    ceil cos cosh exp

    floor fmod hypot log

    log10 pow sin sinh

    sqrt tan tanh

    Because the construct,

    set a [expr $a + 1]

    occurs so often, the incr command was introduced. By default, it increments a variables value by 1. Itcan also be given an explicit increment.

    % set a 55% incr a6% incr a 511% set a11%

    Control StructuresTcl supports a wide range of control structures for program flow, including conditionals, loops, andselections.

    ifif expr1 ?then? body1if expr1 ?then? body1 ?else? body2if expr1 ?then? body1 elseif expr2 ?then? body2 ?elseif?...?else??bodyN?

    The if command evaluates expr1 in the same way as expr. If the result is a Boolean true (a nonzeronumeric value, or a string with the value true or yes), body1 is executed and its value returned.Otherwise, the process repeats with the next elseif clause if there is one (there may be zero). If none of

    the expressions evaluate to a Boolean true, the else clause (if present) is executed and its resultreturned. If no body is executed, the if command returns an empty string. A Boolean false would berepresented by numeric zero or the string values false or no.

  • 7/31/2019 Tcl Manual

    9/30

    The body sections need to be single items: a single word or a bracketed command. Note that the thenand else keywords are not necessary, but make things easier to read. Its recommended practice to buildthe construct like this:

    if {expr1} {body1

    } else {body2

    }

    The reason for the odd layout of braces, especially having the brace and else on the same line, is to makesure the interpreter knows that theres more coming. Without it, we have a complete if statement. Tclwould execute it, assume the next line started with the command else, and give you a syntax error.

    switchswitch?options? stringpatternbody ?pattern body ...?switch?options? string{pattern body ?pattern body ...?}

    The Tcl switch command is the direct analog of the Linux shell case statement and the C switch(which works only on integer values). The given string is compared in turn with each of the patterns.(See the later sections on matching.) When a match is found, the associated body is executed and its resultreturned. A pattern of default acts as a catchall, matching all strings not matched by any other pattern.

    Options control the matching technique to be used. These may be

    switch option Description

    -exact Match the string to the pattern exactly.

    -glob Use glob (shell-style) matching (as in UNIX filename matching).

    -regexp Use regular expression matching as in the UNIX egrep utility.

    -- An option used to mark the end of options, in case a string starts with ahyphen.

    You can use the two different ways of specifying the patterns and bodies to gain fine control over

    substitutions in the arguments toswitch

    . Placing patterns and bodies in braces{}

    has two effects: Itprevents substitutions, and it allows you to spread the patterns and bodies over several lines withouthaving to quote the end of lines with backslashes.

    Heres an example well meet again later that illustrates how switch can be used to process programarguments:

    foreach arg $argv {switch -glob -- $arg {

    -v {set VerboseFlag true}-f* {set FileToRead [string range $arg 2 end]}-h {puts stderr $Usage; exit 1}default {error "bad argument: $arg\n$Usage"; exit 1}

    }}

    forfor starttestnextbody

  • 7/31/2019 Tcl Manual

    10/30

    The Tcl for statement is very similar to the for statement in C. The start, next, and body argumentsmust be Tcl command strings, and test must yield a Boolean expression. The for command executes thestart string and then repeatedly evaluates the test expression. If it yields a Boolean true value, thebody string is executed. If a break command is encountered in the body, the loop is terminatedimmediately. A continue command in the body causes the for loop to be restarted. Each time the loopis completed, the next expression is evaluated.

    % set n 55% set result 11% for {set i $n} {$i} {incr i -1} {

    set result [expr $result * $i]}% set result120

    You may recognize this as calculating a factorial. Well see a little later how to create a Tcl procedure toperform this function.

    whilewhile testbody

    The while command acts in a similar way to the while statement in C. It repeatedly evaluates the teststring and executes the Tcl command body until test yields a Boolean false value. As with the forcommand, a break or continue command causes the loop to be terminated or restarted, respectively. Asan example, this code emulates the Linux cat command on the file foo. See the section on input andoutput for more about file handling.

    % set fd [open "foo" "r"]file3% while {[gets $fd line] != -1} {

    puts "$line"}

    % close $fd

    Error Handling

    When the Tcl interpreter encounters an error, it usually prints a message and halts. This is not always thedesired result from within a program, so Tcl provides a facility to raise and trap errors and to recover fromthem.

    errorerror message ?info? ?code?

    The error command generates an error and terminates execution unless the error is caught or trapped.The message, message, is provided as an indication to the application as to what went wrong. It isprinted if the interpreter default error action is taken.

    If present, the info argument is added to the global variable errorInfo. This variable accumulatesinformation about command nesting when errors occur. As each Tcl command unwinds, it adds toerrorInfo to provide a stack trace. Similarly, the code argument is intended to add machine-readableinformation to the global variable errorCode. Refer to the Tcl documentation for further details.

  • 7/31/2019 Tcl Manual

    11/30

    catchcatch script ?varname?

    The catch command evaluates the given script, trapping any errors that occur. If present, the variablevarname will be set to the return value of the script or any error message returned.

    Heres an example taken from the Tcl program, concord, that well see later:

    if [catch {set Input [open $FileToRead r]} res ] {puts stderr "$res"

    If the attempt to open the input file fails, the program can carry on, rather than stopping with an error.catch is extremely useful in this regard, as there are many instances of programs that would not runsuccessfully without trapping the error in this fashion.

    String Operations

    As Tcl is essentially a string-based language interpreter, its no surprise that it provides a rich set ofcommands for manipulating strings and string values.

    The main string manipulation command is string. It takes one option and a number of arguments,

    depending on the operation required.

    stringstring optionarg ?arg?

    The options (and associated arguments) to string are given below. Where a string index is used orreturned, it is always base zero; that is, the first character is given an index of 0, the second an index of 1,and so on.

    first, last, compare

    string first string1 string2string last string1 string2string compare string1 string2

    first and last search for the appropriate occurrence of string1 in string2 and return the index into

    string2 of the start of the match found, or 1 if string1 doesn't occur in string2.

    % string first "o" "foobar"1% string last "o" "foobar"2

    compare performs a character-by-character comparison. Returns -1, 0, or 1 if string1 is less than, equalto, or greater than string2, in the same way as strcmp in C.

    % string compare "foo" "bar"1

    index

    string index string num

    index returns a single character from string. The character at index position num is returned, where thefirst character is deemed to be index 0.

  • 7/31/2019 Tcl Manual

    12/30

    % string index "ABC" 1B

    length

    string length string

    length returns the length of string.

    % string length "ABC"

    3

    match

    string matchpattern string

    match returns 1 if string matches pattern, 0 otherwise. The matching performed is similar to that ofthe Linux shell, where so-called globmatching is used in filename expansion.

    % string match "*B*" "ABC"1% string match "*B*" "ZZZ"0

    range

    string range string first last

    range returns a substring of string from index position first (starting at zero) to last, which may bethe keyword end to specify the end of the string.

    % string range "ABCDEF" 3 endDEF

    tolower, toupper

    string tolower stringstring toupper string

    These arguments return a string made from the characters of string converted to the appropriate case.

    % string tolower "ABC"abc% string toupper "abc"

    ABC

    trim, trimleft, trimright

    string trimstring ?chars?string trimleft string?chars?string trimright string ?chars?

    These arguments return a substring of string, but with certain characters from the set chars removed.trim removes leading and trailing characters, while trimleft and trimright remove leading andtrailing characters, respectively. If chars is not specified, white space is removed.

    % string trim "foobar" "for"ba% string trimleft "foobar" "for"bar% string trimright "foobar" "for"

    fooba

    wordstart, wordend

    string wordstart string index

  • 7/31/2019 Tcl Manual

    13/30

    string wordend string index

    These return the index in string of the first character of/after the word containing the position index.

    % string wordstart "Tcl is Cool" 54% string wordend "Tcl is Cool" 56

    Glob MatchingIn the stringmatch and the switch -glob commands, a form of pattern matching is used. Thisinvolves wild cards that will be familiar to you if youve used the Linux shell, as they are the same as thoseused for the shell case statement and for matching filenames.

    For a string to match a pattern, they must be identical, except for special sequences that may appear in thepattern. These are

    * Matches any sequence of characters.

    ? Matches any single character.

    [] Matches any character in a set.

    \ Matches the otherwise special

    character ; e.g. \* matches a*.

    regexp and regsub Matching

    In the regexp and regsub commands that well meet a little later and the -regexp option of the switchcommand, patterns are used to match strings. These patterns may contain complex matches, specified byregular expressions, which will be familiar to you if youve used the egrep utility or the ed/vi/emacseditors.

    For a string to match a regular expression, they must be identical, with the exception of special sequencesthat may occur in the pattern specifier. These are

    . Matches any character.

    * Indicates zero or more matches of the previous item.

    + Indicates one or more matches of the previous item.

    | Indicates a choice between two expressions.

    [] Matches any character in a set.

    ^ Matches the start of the string.

    $ Matches the end of the string.

    \ Matches the otherwise special character ; e.g.,\* matches a *.

    You can identify submatches in the regular expression by surrounding them in parentheses, (). You canuse these for extracting submatches in a match or for substitutions in regsub.

  • 7/31/2019 Tcl Manual

    14/30

    appendappend varname ?value value ?

    The append command adds the value arguments to the end of the current value of the variablevarname. This is more efficient than an equivalent assignment if the argument values are longwhy copya string and throw the original away when you can just add to the original?Given,

    % seta"This is: "This is:% set b"a long string"a long string

    the following two Tcl fragments are equivalent (giving "Thisis: alongstring"), but the second canbe more efficient:

    % set a $a$b% append a $b

    regexpregexp?options? expression string ?match??submatch submatch ?

    The regexp command uses regular expressions to look for a match in string. It returns 1 if it finds amatch, 0 otherwise. The expression is of a form given above for regexp matching. If the regularexpression is found in the string, the variable match is set to the part of the string that matches theexpression. The optional submatch variables are set to the parts of the string that match parenthesizedsubmatches in the expression. This example looks for a number starting with a 3:

    % regexp {3[0-9]*} 31121% regexp {3[0-9]*} 51120

    these can also be written

    % regexp 3\[0-9]* 31121% regexp 3\[0-9]* 51120

    Note that we have to use braces or backslashes to prevent Tcl from interpreting the square bracket as thestart of a command. Options that may be used to control the matching are

    -nocase Causes the match to be case-insensitive.

    -indices Causes the submatch variables to be set topairs of indices delimiting the match substrings.

    regsubregsub ?options? expression string subst varname

    The regsub command matches string against a given regular expression and writes a new string to thevariable varname. The new string is a copy of the subst argument with substitutions carried out. Theseare as follows:

  • 7/31/2019 Tcl Manual

    15/30

    &or\0 is replaced by the matching string.

    \1,,\9 is replaced by the first, , ninth submatch (parenthesized subexpression).This example changes a leading 3 to a 5:

    % regsub {3([0-9]*)} 3112 {5\1} res1% set res5112

    Try It OutString Matching and Substitution

    Heres an example of string matching and substitution:

    % set date1 "Wednesday August 11 1999"Wednesday August 11 1999% set date2 "Saturday April 1 2000"Saturday April 1 2000% set weekend "(Saturday|Sunday)"(Saturday|Sunday)% regexp $weekend $date10% regexp $weekend $date2 day1%puts $daySaturday% set parsedate "(\[A-Z]\[a-z]+) +(\[A-Z]\[a-z]+) +(\[0-9]+) +(\[0-9]+)"

    ([A-Z][a-z]+) +([A-Z][a-z]+) +([0-9]+) +([0-9]+)% regexp $parsedate $date2 date day month dom year1%puts "$date breaks into $day, $month, $dom, $year"Saturday April 1 2000 breaks into Saturday, April, 1, 2000% regsub $parsedate $date2 {\4 \2 \3} newdate1%puts $newdate2000 April 1%

    How It Works

    Several calls to regexp are shown, matching dates to days in the weekend and extracting informationfrom a date. A substitution is used to reorder the format of the date. The variable parsedate is set to anexpression that describes a value date. It uses several key forms:

    [A-Z][a-z]+matches a capitalized word of two or more letters, such as the day ormonth name.

    + matches a sequence of one or more spaces, as occurs between date elements.

    [0-9]+ matches a decimal number, such as the dates year number.

    Note that when you use backslashes or square brackets in matches or substitutions, you need to protectthem against expansion when theyre inside double quotes. Alternatively, using braces prevents allexpansions.

    Arrays

    Arrays are special variables accessed with an index in parentheses following the array name. You cantmanipulate arrays as an entity by using their name alone.

    Tcl supports a form of array known as an associativearray. This powerful concept is implemented byallowing arrays with arbitrary indices; that is, arrays can use strings to address their elements. This allowsus to store information about general objects in an array, using the object itself as the array index. Anexample will make things clearer.

  • 7/31/2019 Tcl Manual

    16/30

    When were dealing with associative arrays, indices and elements are often referred toinstead as keys and values.

    % set myarray(0) 123123%puts $myarraycan't read "myarray": variable is array%puts $myarray(0)123%

    Array indices are not limited to numeric values, but its sensible to limit them to either numbers or a stringwithout spaces or special characters, as quoting and variable substitution can become difficult. A commontechnique is to employ a variable to contain the value of the index and set the variable to the desired value.This eliminates the difficulties with special characters.

    % set myarray(orange) 11% set myarray(apple) jimjim%

    arrayarray optionarrayname ?arg arg ?

    Arrays may be manipulated by the array command, which takes a number of options. The options toarray (and associated arguments) are given here.

    exists

    arrayexists arrayname

    This returns 1 if arrayname is an array, 0 otherwise.

    get

    array get arrayname ?pattern?

    This returns a list of pairs of elements containing array indices and associated values. If the optionalpattern is given, it returns only the array elements whose indices match the (glob style) pattern.

    names

    array names arrayname ?pattern?

    This returns a list of array index names, optionally only those that match pattern.

    set

    array setarraynamelist

    This sets the elements of the array arrayname. The list must be like the one returned by get, with aseries of indices and their values.

    size

    array size arrayname

  • 7/31/2019 Tcl Manual

    17/30

    This returns the size of an array.

    % array exists myarray1% array size myarray3% array names myarrayorange 0 apple% array get myarrayorange 1 0 123 apple jim%

    We can also perform a search of arrays element-by-element with array command options startsearch,anymore, nextelement, and donesearch. See the Tcl documentation for further details.

    Lists

    In addition to strings and arrays, Tcl also has full support for lists. These are groups of Tcl objects,numbers, strings, and other lists that can be grouped together and manipulated. Tcl allows lists to becreated, added to, converted to and from strings, and used for controlling loops. Well outline a number oflist manipulation commands below.

    The syntax for Tcl lists is the brace group. In fact, weve already seen lists in action with the bodies forloops.

    % set mylist {bob {1 2 3 {4 5}} fred}bob {1 2 3 {4 5}} fred

    This assignment has created a list of three elements. The second element is itself a list of four elements.Notice that Tcl displays braces around lists only when necessary, to show the correct structure. As witharrays and strings, list elements can be accessed by position with an index, starting from zero.

    If you have a need for an array, but will only be using numeric indices, you should consider using a listinstead. They can often prove to be more efficient than the more general arrays.

    listlist?arg arg arg ?

    We can create lists programmatically in a number of ways, but perhaps the easiest is with the listcommand. list takes all of its arguments and creates a list, each element of which is a copy of anargument. If no arguments are given, list produces an empty list.

    We need to add braces and backslashes as necessary, so that the original arguments may be extractedusing lindex (see below) and the list can be evaluated by eval (if the first argument is the name of acommand).

    % set elist [list puts "Hello World"]puts {Hello World}% eval $elistHello World

    splitsplitstring ?delimiters?

  • 7/31/2019 Tcl Manual

    18/30

    The split command is used to create a list from a string. By default, split creates a list containing thedistinct words (delimited by white space) in string. The optional delimiters argument is a list ofcharacters used to determine the places to split the string. If the delimiters list is empty, rather thanomitted altogether, all characters in the string are individually included as list elements.

    % split "hello there jim"hello there jim% split "hi there everyone" {e}{hi th} r { } v ryon {}

    Notice that the delimiters dont appear in the list, but that empty elements will be created if there areadjacent delimiters in the string.

    When youre using split, you should take care with backslash substitutions: \$ will be converted to a $,not a \ and a $. In other words, to get \ included as an element in a list, you have to use \\. To include theliteral $foo, you need to use \$foo.

    joinjoin list ?delimiter?

    The join command is the opposite of split. It creates a string by recursively joining together elementsof a list. It uses the optional delimiter string (if there is one) to separate elements. It defaults to a space.

    % join {1 2 fred {bill bob} 37} ","1,2,fred,bill bob,37%

    concatconcat?arg arg arg ?

    The concat command takes several arguments, treats them as lists, and concatenates them. If you supplyno arguments, youll get an empty result, not an error. When it joins lists, concat will effectively strip offone level of braces so that top-level members of list arguments become top-level members of the resultinglist.

    Arguments have leading and trailing spaces removed. Each list element is separated by a single space.

    % concat {1 2} {3 {4 5} 6} 7 8

    1 2 3 {4 5} 6 7 8

    lappendlappend listvar ?arg arg arg ?

    We can use the lappend command to add further elements to a list. Its more efficient than creating a newlist with, for example, concat.

    Each of the arguments to lappend is added as a list element to the existing list listvar. Each elementadded is separated by a single space. Note that, unlike concat, no level of braces is removed; eachargument is added as is.

    % set alist {1 2 3 {4 5}}1 2 3 {4 5}

    % lappend alist 6 {7 8}1 2 3 {4 5} 6 {7 8}%

  • 7/31/2019 Tcl Manual

    19/30

    lindexlindex listindex

    We use the lindex command to retrieve an element at position index from a list. The list elements arenumbered starting from zero. If the requested element is not in the list, an empty string is returned. Wecan use the keyword end in place of an index to refer to the last element in the list.

    % set alist {1 2 3 {4 5}}

    1 2 3 {4 5}% lindex $alist 34 5%

    linsertlinsert list index arg ?arg arg ?

    We can use the linsert command to insert elements into a list. The new list created by linsertcompriseslist, with the arg arguments inserted just after the element referred to by index. If index iszero (or negative), the new elements are placed at the beginning of the new list. If the index is greater thanor equal to the length of the list, or is the keyword end, the new elements are added at the end of the list.Notice that the original list is not itself affected by the linsert command.

    % set alist {{4 5}}{4 5}

    % linsert $alist 0 1 2 31 2 3 {4 5}% linsert [linsert $alist 0 1 2 3] end {6 7 8}1 2 3 {4 5} {6 7 8}%

    llengthllength list

    We can obtain the length of a list by the llength command, which returns a string containing a decimalnumber corresponding to the length of the list list. An empty list returns a length of zero.

    % llength hello1% llength "1 2 3"3% llength {a b {c d}}3

    Note that Tcl will try to interpret many different arguments as lists automatically, in which case quotedand unquoted strings and brace groups are all treated as lists. Each word within a string is interpretedas an individual element.

    lrangelrange list first last

    A consecutive subset of a list may be extracted by the lrange command. The elements in positions firstthrough last in the list list are extracted, and a new list with just those elements is returned.

    % set alist {1 2 3 {4 5} 6 7 8}

    1 2 3 {4 5} 6 7 8% lrange $alist 2 43 {4 5} 6%

  • 7/31/2019 Tcl Manual

    20/30

    lreplacelreplacelist first last ?arg arg arg ?

    We can replace elements in a list by the lreplace command. The elements in positions first throughlast in the list list are replaced with the given arguments. Elements are deleted and new ones inserted.The element in position first must exist, although the number of elements to be deleted and the numberto be inserted need not be the same. We can use the keyword end for first or last to specify the lastelement in the list.

    % set alist {1 2 3 {4 5} 6 7 8}1 2 3 {4 5} 6 7 8% lreplace $alist 2 end bill {bob joe}1 2 bill {bob joe}%

    lsearchlsearch ?option? list pattern

    We can use lsearchto search a list for elements that match a pattern. The options are-exact, -glob (the default), and -regexp, which determine the type of matching to be undertaken. Seethe section on strings above for more details of Tcl matching.

    The given list is searched for elements that match the specified pattern. The index of the firstmatching element is returned, or -1 if no such element is found.

    % lsearch {apple pear banana orange} b*2

    lsortlsort?option? list

    We can use the lsort command to sort a list according to a number of criteria. The default action is forthe elements of the list to be sorted into ascending alphabetical order by ASCII collating sequence, whichis the order of alphanumeric characters, plus punctuation. As far as the computers concerned, its thenumerical order of the byte values of the characters. For example,

    % lsort {apple pear banana orange}apple banana orange pear

    The options to lsort that change the type of sort performed include the following:

    lsort option Description

    -ascii Normal string comparison, the default.

    -integer Elements are converted to integers and compared.

    -real Elements are converted to floating point and compared.

    -increasing Sorts in ascending order.

    -decreasing Sorts in descending order.

    -command Use command as a sort function. This must be aprocedure taking two list elements as arguments andreturning an integer less than zero, zero, or greater than

  • 7/31/2019 Tcl Manual

    21/30

    zero depending on whether the first element is to beconsidered smaller, equal, or larger than the second.

    foreachforeach varname list body

    We can use foreach to separately evaluate or use each element in a list. The command assigns to

    varname each element of the list argument in turn and executes body. Heres an example:

    % foreach i {1 2 3 bill bob joe} {puts "i is $i "

    }i is 1i is 2i is 3i is billi is bobi is joe%

    This is a simplification of the foreach command; in the general case, foreach can take a list of variablenames and a number of lists. In this case, the lists are traversed at the same time. Each time around theloop, each of the variables is assigned for the next element in the corresponding list.

    % foreach {a b} {1 2 3 4 5 6} {puts "a is $a, b is $b"}a is 1, b is 2a is 3, b is 4a is 5, b is 6% foreach a {1 2 3} b {4 5 6} {puts "a is $a, b is $b"}a is 1, b is 4a is 2, b is 5a is 3, b is 6%

    A break or continue command in a foreach body has the same effect as in a for command. If abreak command is encountered in the body, the loop is terminated immediately. A continue commandin the body skips the remainder of the loop for the present iteration.

    A foreach loop in conjunction with array names makes for a useful way to scan an array:

    % set myarray(orange) 1

    1% set myarray(apple) 22% set myarray(banana) 33% foreach fruit [array names myarray] { puts "fruit is $fruit" }fruit is orangefruit is applefruit is banana%

    Procedures

    Procedures in Tcl are similar to those of other languages, but with some interesting differences.Procedures are introduced to the Tcl interpreter with the proc command. We must define all procedureswith proc before they can be called.

    proc name args body

  • 7/31/2019 Tcl Manual

    22/30

    The proc command defines the procedurename. It stores the body (a list of executable commands) to berun when the procedure is called. Arguments passed to the procedure when it is executed are substitutedfor the list of variables, args.

    Procedures exit when the last command in the body is executed. The value of a procedure is the value ofthe last command executed. We can prematurely terminate procedures with the return command.

    return?option? ?string?

    The optional value string is returned as the value of the enclosing procedure. If string is omitted, anempty string is returned. We can specify the action taken when a procedure needs to return an error byone of several options to return. See the Tcl documentation for details.

    Try It OutProcedures

    Heres a simple procedure for calculating a factorial:

    %proc fact {n} {set result 1while {$n > 1} {

    set result [expr $result * $n]set n [expr $n - 1]

    }return $result

    }% fact 75040

    How It Works

    The procedure fact builds up the required factorial by iteration. Note that the procedure uses a localvariable: result. As we dont need to declare variables before they are first used in Tcl, all new variablesencountered in Tcl procedures are assumed to be local; that is, new variables created inside a Tclprocedure dont exist outside of the procedure.

    upvarupvar?level? oldname newname

    To gain access to a global variable, we must use the command upvar, which allows access to variables at ahigher level in the call stack. At its simplest, it allows a procedure to use a variable declared in anenclosing scope (possibly the procedure that called it), or a global variable.

    The upvar command creates a new variable, newname, within the procedure. Accesses and assignmentsto it are equivalent to using the variable oldname, which exists outside the procedure. We can use thelevel argument to determine precisely which stack frame the oldname variable is from.

    The most common case is simply to provide access to global variables with

    upvar variable variable

    Here is an example of the proper use of upvar:

    % set result 11%proc badset2 {} {

    set result 2}

  • 7/31/2019 Tcl Manual

    23/30

    %badset22% set result1%proc goodset2 {} {

    upvar result resultset result 2

    }% goodset22% set result

    2%

    Input and Output

    Tcl provides a sophisticated system for input and output. In this section, well cover some of the basicfacilities. Refer to the Tcl documentation for further details.

    openopen filename ?access? ?permissions?

    The open command establishes a connection to a file or a command pipeline. It combines the functionalityof fopen and popen in C.

    open returns a channel identifier (the Tcl equivalent of a file stream) that can be used in future calls toother input and output commands like gets, puts, and close. Standard streams are automaticallyavailable to Tcl programs as stdin, stdout, and stderr.

    If present, the access argument determines how the file is to be opened. Its a string value and takes thesame values as the modes used by fopen in C:

    access modes Description

    r Opens filename for reading. The file must exist. This is the default.

    r+ Opens filename for reading and writing. The file must exist.

    w Opens filename for writing. The file will be created or truncated.

    w+ Opens filename for writing and reading. The file will be created ortruncated.

    a Opens filename for writing. New data will be written at the end of the file.

    a+ Opens filename for reading and writing. The initial file position is set tothe end of the file.

    Alternatively, we can set the access modes using a Tcl list of POSIX flags, including RDONLY, WRONLY,RDWR, APPEND, CREAT, EXCL, NOCTTY, NONBLOCK, and TRUNC.

    The permissions argument, if present, is an integer value (default octal 666) used to set the initialpermissions on any file created by the call to open.

    If the filename argument has a pipe symbol (|) as its first character, its treated as a command pipeline.The Linux command is executed and its output made available for reading via the returned channelidentifier.

  • 7/31/2019 Tcl Manual

    24/30

    closeclose channelID

    The close command closes the channel given by channelID, which must have been obtained from aprevious call to open (or in Tcl 7.5 or later, socket). The channel is the equivalent of a C file descriptor.

    readread?-nonewline?channel?bytes?

    The read command reads all of the input available (or, if bytes is set, a specified number of bytes) on achannel identifier.

    If the -nonewline option is specified, read doesnt return the last character in the input if its a newline.The read command translates end of line sequences into single newlines.

    getsgets channel ?varname?

    The gets command reads the first line of input and stores it in a variable varname if this has beenspecified. Each subsequent use of gets on a channel results in the next line of data being read, stoppingwhen an end of file character is found. The value returned by gets is the number of characters read into

    varname, -1 on error, or the string itself if varname is not specified.

    % set myfile [open "|date" r]file3% gets $myfile fred28% close $myfile% set fredWed Aug 11 15:03:35 BST 1999

    putsputs?-nonewline??channel?string

    The puts command writes output to a channel (defaults to the standard output). The string is written tothe channel followed by a newline, unless the option -nonewlineis specified. New lines are translated to

    end of line sequences automatically.

    Note that Tcl performs internal buffering, so output from puts may not appear in an output fileimmediately. We can force output with the flush command. Refer to the Tcl documentation forinformation beyond this simple example:

    % open "fred.txt" wfile3%puts file3 "Hello World"% close file3% open "fred.txt" rfile3% gets file3Hello World% close file3%

    formatformat formatstring ?arg arg arg ?

  • 7/31/2019 Tcl Manual

    25/30

    The format command is the Tcl equivalent of the C library function sprintf and shares manyconversion specifiers. In fact, sprintf is used in the implementation of format.

    The format command generates a formatted string. Refer to the Tcl manual page (man format) or the Clibrary documentation for printf/sprintf for details of conversion specifiers.

    scanscan string formatstring var ?var var ?

    The scan command is the Tcl equivalent of the C library function sscanf. The variables specified asarguments are set to values extracted from string, according to conversion specifiers given informatstring. As with format above, the implementation of scan is very similar to the ANSI Csscanf, and readers are directed to the C library documentation for further details of conversionspecifiers.

    filefile option name ?arg arg ?

    File manipulations are carried out in Tcl by the file command. It accepts a number of options forchanging and inspecting file characteristics. Options used by the file command follow.

    atime, mtimefile atime namefile mtime name

    These return a string describing the last access time/modified time of the files name.

    dirname

    file dirname name

    This returns the directory part of the files name, that is, all the characters before the last / character.

    % file dirname "/bin/fred.txt"/bin

    exists, executablefile executable namefile exists name

    These return 1 if the file exists/is executable, 0 otherwise.

    % file exists "fred.txt"1% file executable "fred.txt"0

    extension, rootname

    file extension namefile rootnamename

    These return the file extension (part of name after last dot)/file root name (part up to last dot).

    % file extension "fred.txt".txt

  • 7/31/2019 Tcl Manual

    26/30

    isdirectory, isfile

    file isdirectory namefile isfile name

    These return 1 if name refers to a directory/regular file, 0 otherwise.

    owned

    file owned name

    This returns 1 if the file is owned by the current user, 0 otherwise.

    readable, writeable

    file readable namefile writeable name

    These return 1 if the file is readable/writeable, 0otherwise.

    size

    file size name

    This returns the file size, in bytes.

    Depending on the operating system that youre using, you have other options available. These includeoptions to retrieve the result of a stat or lstat system call in a Tcl array. Refer to the system-specific Tcldocumentation for details.

    A Tcl ProgramHeres a sample program to demonstrate some Tcl features. It generates a list of the frequencies of wordusage in a text file. It might form part of a concordance.

    Try It OutA Concordance Program

    1. Type in the listing, concord.tcl, below. We begin by specifying the shell to run under and

    initializing some variables.#!/usr/bin/tclsh

    set VerboseFlag falseset FileToRead "-"set Usage "Usage: concord \[-v] \[-f]"

    2. Remembering that argv is the program arguments array, parse the command line arguments.Set FileToRead and give help.

    foreach arg $argv {switch -glob -- $arg {

    -v {set VerboseFlag true}-f* {set FileToRead [string range $arg 2 end]}-h {puts stderr $Usage; exit 1}default {error "bad argument: $arg\n$Usage"; exit 1}

    }}

  • 7/31/2019 Tcl Manual

    27/30

    3. Set the default input source to the standard input. If a file has been specified, open it safely.

    set Input stdin

    if {$FileToRead != "-"} {if [catch {set Input [open $FileToRead r]} res ] {

    puts stderr "$res"exit 1

    }}

    4. Initialize the word and line counters. Then read each line in the input, split the line according topunctuation, and increment a concordance array.

    set NumberOfLines 0set NumberOfWords 0

    while {[gets $Input line] >= 0} {incr NumberOfLinesset words [split $line " \t.,\{\}\(\)\[\]\;\""]foreach word $words {

    if {[info exists concord("$word")]} {incr concord("$word")

    } else {set concord("$word") 1

    }incr NumberOfWords

    }}

    5. Output a summary, then all the words found, then each word accompanied by its count.

    puts stdout [format "File contained %d/%d words/lines\n" \$NumberOfWords $NumberOfLines]

    puts stdout [array names concord]

    foreach word [array names concord] {puts "$word: $concord($word)"

    }

    Lets try this program out on a text file, such as its own source code. When we run the program with thecommands,

    $ chmod +x concord.tcl$ ./concord.tcl -fconcord.tcl

    we get output like this (edited for brevity):

    File contained 404/48 words/lines

    {"$Input"} {"if"} {"exists"} {"%d/%d"} {"$word:"} {"--"} {"error"} {"$words"}{"$FileToRead"} {"info"} {"set"} {"$argv"} {"contained"} {"NumberOfWords"} {"range"}{"argument:"} {"!="} {"bad"} {"VerboseFlag"} {"Input"} {"catch"} {"cannot"}{"$concord"} {"words"} {"File"} {""} {"0"} {"else"} {"while"} {"-v"} {"word"}{"split"} {"-h"} {"-f"} {"line"} {"concord"} {"format"} {"1"} {"switch"}{"exit"} {"stdin"} {"stdout"} {"\"} {"stderr"} {"$NumberOfLines"} {"default"} {"$arg"}{"\t"} {"$Usage"} {"#!/usr/bin/tclsh"} {"2"} {"open"} {"r"} {"names"} {"-f*"}{"string"} {"$word"} {"$arg\n$Usage"}...

    "names": 2"-f*": 1"string": 1"$word": 4"$arg\n$Usage": 1

  • 7/31/2019 Tcl Manual

    28/30

    "NumberOfLines": 2"arg": 1"$line": 1"incr": 3"puts": 5"Usage": 1"array": 2"Usage:": 1"FileToRead": 2"end": 1"foreach": 3"oops": 1">=": 1"gets": 1"false": 1"-": 2"true": 1"$NumberOfWords": 1"-glob": 1"words/lines\n": 1

    How It Works

    For demonstration purposes, the program prints out the list of words that it found before the frequencylisting. The order of the words in the array is undefined; it depends on the Tcl implementation ofassociative arrays. If we had wanted the output sorted, we could have copied the array elements into a listand used lsort, or we could have piped the output through the UNIX sort program.

    The program works by splitting input lines into individual words, excluding punctuation, and using thesewords as indices to an associative array. This array, concord, is used to collect the word frequencies. Weused a quoted string as an index to the array to prevent possible problems with special charactersoccurring in the words.

    Network SupportWith Tcl 7.5 and later, Tcl has direct support for networking, where previously third-party add-ons wererequired. The flexibility and concise nature of Tcl combined with a network programming paradigm givesTcl an exceptionally wide range of uses. In fact, there are even World Wide Web browsers written entirelyin Tcl. The key command is socket.

    socket hostport

    By default, the socket command opens a SOCK_STREAM connection to the specified computer, host, andservice number, port. It returns a channel identifier that can be used in the normal Tcl input/outputcommands.

    Try It OutSocketssocket

    To demonstrate the use of sockets with Tcl, lets revisit a small example from Chapter 14 to compare.Heres a complete program, socket.c, in Tcl to display the time of day from a networked computer.

    To get this to work properly, replace the hostname tildewith an appropriate systemname on your internal network or, alternatively, use localhost.

    #!/usr/bin/tclsh

    set sockid [socket tilde 13]gets $sockid dateputs "Tilde says the date is: $date"

  • 7/31/2019 Tcl Manual

    29/30

    How It Works

    Tcl (from Version 7.5) has built-in support for Linux networking. This program uses the socketcommand to create a communication path to the host tilde, port 13, which is the daytime service. Itreads a string from the socket connection and prints it.

    Compare this three-line solution with the program from Chapter 15!

    Usinggets here reveals a potential pitfall. An unscrupulous system administratormight configure the daytime service to return an extremely long string that could giveyour machine problems. These kinds of antics have been known to occur on theInternet and are known as Denial of Service attacks.

    Creating a New TclOne of the design objectives of the Tcl language was that it should be embeddable, so that we can includescripts written in Tcl in other command line programs, and even in C. Indeed, that is how Tcl got started,and why it is called Tool Command Language. And, in this respect, it is very similar to Perl.

    Its quite easy to incorporate Tcl into your own command line programs by writing one simple functionthat initializes the Tcl interpreter. You can link your own functions with the Tcl library to create your own

    Tcl interpreter that is tailored to your specific needs.

    The precise mechanism for this is beyond the scope of this chapter. In fact, many Tcl programmers neverhave to create their own interpreters. They find that the basic Tcl system, together with Tcl extensionsprovided by third parties, satisfies all their needs.

    Tcl ExtensionsOver the years, there have been a large number of extensions to Tcl. These most often take the form ofversions of Tcl with additional functionality to serve a particular purpose. Well cover just a few of themhere.

    expectThe expect program is a Tcl interpreter extended with additional functions aimed particularly atautomatic control of interactive programs. We can use it for testing software, because we can writeexpect scripts to send commands to a program, wait for responses, and then react to those responses. Ithas built-in capabilities for timeouts and error recovery. It can run Tcl functions on receipt of a number ofdifferent events.

    expect was created by Don Libes of NIST (National Institute of Standards andTechnology) shortly after the release of Tcl on the Internet. It is the first major programbuilt around Tcl.

    The extension gets its name from the two principal functions it adds. These are send, for sendinginteractive input to a program under test, and expect, for arranging for actions to be taken on receipt ofdifferent responses, or lack of them.

  • 7/31/2019 Tcl Manual

    30/30

    [incr Tcl]

    This extension, the name of which is a pun on C++, adds object-oriented features to Tcl.

    TclX

    TclX is extended Tcl. Its a commonly used extension in the Linux environment, as it contains many

    additional functions that mirror the UNIX system calls. TclX programs enjoy greater low-level access tothe operating system at the expense of a certain amount of portability.

    Graphics

    Many Tcl extensions have been developed to support graphics and additional operations.

    TkA major Tcl extension, also developed by John Ousterhout, is Tk (for Tool Kit). It bestows on Tcl the abilityto create and manipulate graphical user interface objects. Using Tk makes it easy for us to writesophisticated graphical programs.

    Initially developed for The X Window System, Tk (and of course Tcl) now comes in versions for MicrosoftWindows and Apple MacOS, so a Tcl/Tk program has the potential to run unchanged on several differenthardware platforms.

    Well cover the subject of programming with Tk in Chapter B.

    SummaryIn this chapter, weve taken a look at the Tool Command Language, Tcl. Weve seen that its an extensiveand extensible interpreted programming language with support for many high-level programminglanguage features, such as associative arrays and lists.

    Weve briefly covered the fact that Tcl has been extended in many ways to create new interpreters tailoredfor specific application areas.

    In the next chapter we will take a look at Tk, the graphical toolkit for Tcl that has resulted in manyapplications being developed and distributed among the Linux community.