P. 1
TcL Fundamentals 1Day Course with Answers

TcL Fundamentals 1Day Course with Answers

|Views: 33|Likes:
This contains the material of an intensive basic course designed to be given in one full day. It assumes some experience in a modern programming language such as BASIC, C, or C++.

Topics: Language syntax, data types, arithmetic, language operators and expressions, basic variables (strings, lists, and arrays), quoting, inline execution, control constructs, script-writing, and basic file I/O.

The attendee will learn everything necessary to write simple, stand-alone Tcl scripts such as those applicable to the use of modern EDA tools.

No advanced Tcl, graphical programming in Tk, or Tcl extension writing is included.
This contains the material of an intensive basic course designed to be given in one full day. It assumes some experience in a modern programming language such as BASIC, C, or C++.

Topics: Language syntax, data types, arithmetic, language operators and expressions, basic variables (strings, lists, and arrays), quoting, inline execution, control constructs, script-writing, and basic file I/O.

The attendee will learn everything necessary to write simple, stand-alone Tcl scripts such as those applicable to the use of modern EDA tools.

No advanced Tcl, graphical programming in Tk, or Tcl extension writing is included.

More info:

Categories:Types, Research
Published by: John Michael Williams on Feb 22, 2013
Copyright:Traditional Copyright: All rights reserved
List Price: $5.00 Buy Now

Availability:

Read on Scribd mobile: iPhone, iPad and Android.
See more
See less

12/29/2013

$5.00

USD

pdf

text

original

Sections

  • Agenda
  • Workshop Organization and Topics
  • Schedule
  • References
  • Introduction
  • TcL Language Basics
  • Simplicity Takes Precedence
  • No reserved word
  • Standard scripting procedures all are lower-case
  • All statements are one line
  • One-character blocking tokens
  • Declared names are alphanumeric
  • Blanks are separators
  • Statements = semicolons
  • One comment token
  • Data Types
  • Variables
  • Strings
  • Lists
  • Arrays
  • Variable Name Conflicts
  • Quoting
  • Inline Execution
  • String Concatenation
  • Arithmetic
  • string Commands -- trim
  • Basic Command Review
  • Lab 1: Simple TcL Scripts
  • Program Structure
  • Procedures
  • Declaration
  • Return value
  • Arguments
  • Procedures and Global Variables
  • The TcL Stack Frame
  • Control Constructs
  • if
  • switch
  • foreach
  • while
  • source Command
  • A Few string Commands
  • string length
  • string index
  • string first
  • string range
  • string replace
  • Basic File I/O
  • glob
  • file
  • open
  • close
  • gets id
  • puts id
  • fconfigure
  • Examples of file I/O
  • Scripting Overview
  • Lab 2: TcL Programming
  • Index

TcL Script Writing Fundamentals

Textbook with Lab Exercises for a Silicon Valley Technical Institute Workshop

by John Michael Williams
jmmwill@comcast.net 2010-09-24

Copyright © 2010, John Michael Williams.
Licensed free to Silicon Valley Technical Institute for training-course use. All other rights reserved.

J. M. Williams

2010-09-24

TcL Workshop

1

Table of Contents
Agenda ............................................................................................................................ 3
Workshop Organization and Topics ....................................................................................3 Schedule ..............................................................................................................................4

References....................................................................................................................... 4 Introduction .................................................................................................................... 5
TcL .......................................................................................................................................5

TcL Language Basics ...................................................................................................... 6
Simplicity Takes Precedence ...............................................................................................7 No reserved word.....................................................................................................7 Standard scripting procedures all are lower-case...................................................7 All statements are one line .....................................................................................7 One-character blocking tokens................................................................................8 Declared names are alphanumeric..........................................................................8 Blanks are separators .............................................................................................8 Statements = semicolons .........................................................................................8 One comment token.................................................................................................8 Data Types...........................................................................................................................9 Variables..............................................................................................................................9 Strings .....................................................................................................................9 Lists .........................................................................................................................11 Arrays ......................................................................................................................12 Variable Name Conflicts .....................................................................................................14 Quoting ................................................................................................................................14 Inline Execution ..................................................................................................................16 String Concatenation ..........................................................................................................17 Arithmetic ...........................................................................................................................18 string Commands -- trim .....................................................................................................19 Basic Command Review ......................................................................................................20

Lab 1: Simple TcL Scripts.............................................................................................. 21 Program Structure .......................................................................................................... 22
Procedures ...........................................................................................................................22 Declaration ..............................................................................................................22 Return value ............................................................................................................23 Arguments ...............................................................................................................24 Procedures and Global Variables ........................................................................................25 The TcL Stack Frame ..........................................................................................................27 Control Constructs ..............................................................................................................30 if...............................................................................................................................30 switch.......................................................................................................................31 for ............................................................................................................................33 foreach .....................................................................................................................34 while ........................................................................................................................35 source Command .................................................................................................................35 A Few string Commands .....................................................................................................37 string length ............................................................................................................37 string index .............................................................................................................37 string first ...............................................................................................................37 string range .............................................................................................................38 string replace...........................................................................................................38 Basic File I/O .......................................................................................................................39

J. M. Williams

2010-09-24

TcL Workshop

2

glob ..........................................................................................................................39 file ............................................................................................................................40 open .........................................................................................................................41 close .........................................................................................................................42 gets id ......................................................................................................................42 puts id......................................................................................................................42 eof ............................................................................................................................43 fconfigure.................................................................................................................43 Examples of file I/O .................................................................................................44

Scripting Overview ......................................................................................................... 46 Lab 2: TcL Programming ............................................................................................... 47 Index ............................................................................................................................... 50

J. M. Williams

2010-09-24

TcL Workshop

3

Agenda
Workshop Organization and Topics
Operation of a computer, including a cell phone or other pocket device, is discouraged during lecture. Please defer such activities for breaks or lab periods. Communication tends to prevent learning. During lecture, please stop the presentation with a question when something is unclear to you. Please save in-depth questions or observations for lab. Classroom lecturing will be alternated with hands-on lab work. The two labs in the workshop will be of progressive difficulty, ending in the implementation of scripts which can accept invocation options and read or write to disc files. The lab exercises will be performed on computers running Linux. The TcL shell and other runtime software will be provided preinstalled. On-disc answers for all lab exercises are provided; TcL user and reference manuals will be available online during the labs. We use ActiveState® ActiveTcl in this workshop; this is available precompiled for Linux and other operating systems and can be downloaded free from the Internet for home or business use. TcL command help files are installed with the software. Help may be set up for access either by the traditional Linux man command (which has been done for this Workshop) or, using a web browser, by a tree of HTML files. The precompiled Windows releases include .chm help. Lectures are based on slides taken from this Textbook; it should be convenient to follow topics in each lecture by paging through the Textbook. However, not everything in the lectures will be in the slides or the Textbook. Topics of the Workshop syntax -- operators and expressions data types variables control constructs procedures and return values script-writing guidelines quoting inline execution string manipulation lists and arrays arithmetic basic file I/O

J. M. Williams

2010-09-24

TcL Workshop

4

Schedule
Times are approximate, except lunch. Breaks (not shown) will follow each lecture.
Time 9:00 - 10:00 10:00 - 11:00 11:00 - 12:00 12:00 - 12:30 12:30 - 13:00 13:00 - 14:00 14:00 - 15:00 15:00 - 15:15 15:15 - 17:30 Topic Introduction; Language Basics Data Types and Basic Commands Lab 1: Simple Scripts Lunch (provided) Lab 1 (concluded) Program Structure; Procedures Control Constructs; File I/O Script-Writing Overview Lab 2: TcL Programming

References
Anonymous. ActiveTcl User Guide. http://www.activestate.com (2005-12-24). See the documentation with the ActiveState ActiveTcl 8.5.7 release; the HTML help menu in Linux or Unix, or the Windows chm help, comes with a tutorial. Anonymous. TcL Developer Exchange. http://www.tcl.tk/ (2006-06-06). If you are interested in object-orientation, see http://www.tcl.tk/about/oo.html. Flynt, Clif. TclTutor. Interactive tutorial; good review of basics. Available online or for download at http://www.msen.com/~clif/Tcl.html (2006-06-09). Johnson, Ray. Tcl Style Guide. Sun Microsystems, ca. 1997. Especially valuable for Tk programs or multiple-file programs larger than scripts. http://www.tcl.tk/doc/styleGuide.pdf (2006-06-30). Welch, Brent B., Jones, Ken, and Hobbs, Jeffrey. Practical Programming in Tcl/Tk (4th ed.). Upper Saddle River, New Jersey: Prentice-Hall, 2003.

J. M. Williams

2010-09-24

TcL Workshop

5

Introduction
This is an intensive, one-day workshop which presents the basic features of TcL (Tool Command Language). It is assumed that the attendee has working experience or coursework in a modern programming language such as C. The attendee will learn everything necessary to write simple TcL scripts. The most essential features of the console, or text terminal, functionality of TcL will be presented. The content will include variables, procedures, control constructs such as loops and program branches, and the use of data structures such as lists and arrays. The attendee will learn how to access the filing system to read and write text files from a TcL script. At the end of this Workshop, the attendee should be able to use TcL for scripting within popular EDA tools, and to write simple stand-alone scripts. • An advanced, one-day workshop in TcL is offered by SVTI for those wanting to study the language in greater detail or wanting to develop greater mastery of TcL as a text-based programming language. • A one-day workshop in graphical programming using the TcL GUI development library, Tk, also is available at SVTI. We begin with some context.

TcL
TcL was designed for implementation inside the command-line environment of complex EDA tools. To encourage incorporation into tool shells, TcL syntax is extremely simple; thus, a TcL parser is easy to develop and render bug-free, an important benefit to EDA tool vendors. In contrast with other languages, the TcL elementary data object is a character, not a byte or other minimum memory allocation unit. A TcL script is immune to core dumps or segmentation faults. We should mention here that the accurate name of the language is Tcl, not "TcL"; however, in modern typefaces, the lower-case letter L looks very much like the numeral 1; to avoid ambiguity, we capitalize the L throughout this book. Who knows what Tc1 would be? Of course, ease of implementation in a tool implies ease of implementation in an operating-system shell. A TcL shell has been ported to Unix, Linux, Windows, and Mac and in these contexts has been given functionality equal to that of perl. As we shall see, there is some resemblance of TcL syntax to that of C or C++. TcL includes some object-oriented features which we shall describe later in the workshop. A little TcL nomenclature is in order here, before we get into details:

J. M. Williams

2010-09-24

TcL Workshop

6

tclsh. A tcl shell. This is a text-based command interpreter which can be invoked in any commonly encountered operating system and used either interactively, to run individual TcL commands, or noninteractively, to execute a TcL script. We shall invoke tclsh to run our scripts in all our lab exercises. Tk. A name for the collection of library elements and functions behind the TcL language as extended to graphical applications. Tk essentially is a GUI development kit. We shall not study Tk in this workshop.

wish. A windowing TcL shell. This is the built-in command interpreter used to run graphical applications written in TcL, using Tk features. It is used to create, maintain, and manipulate windows. We could run our TcL scripts in wish, but it is more complex than tclsh, and we shall not use it in this workshop. tkcon. A Tk console. This is an independently developed TcL script which uses Tk to overlay wish with a menu system and debugging facilities. Tkcon includes interactive colorized syntax, like vim. Tkcon itself is a TcL script run by invoking tclsh; so, tkcon is not a good choice as a noninteractive script interpreter. Recent Linux releases of TcL no longer include tkcon, probably because the universally available vim text editor provides the same text syntax colorization.

TcL Language Basics
All current implementations of TcL make it an interpreted scripting language. This means that execution is one line at a time and is slower than for compiled programs in C or C++. It also means that TcL is portable to any operating system which includes a TcL shell; and, TcL syntax being rather simple, such shells are implemented easily and are likely to be freer of bugs than other kinds of ported shell. TcL is not a typed language. All TcL data elements are ASCII characters (possibly with an underlying unicode implementation). In TcL, as for a Linux or Unix shell language, everything is a string. However, things are not that simple, because TcL has built-in procedures which make for specially structured string data, including content-addressable arrays and lists. Because the language includes such powerful access constructs, we can refer accurately to "data types" in an untyped language. Even so, the reduction of all data to string data means that it is not inaccurate to say that TcL is perfectly polymorphic in its fundamental objects. Data typing might be considered an anachronism. In ancient times, compilers were very primitive and could not be depended upon to determine a proper amount of memory storage for a given data object, usually a simple variable or a pointer. Thus, the programmer had to tell the compiler how to allocate memory for everything. The instructions were burdensome and sometimes inconsistent. A plethora of integers, floating-point formats, and more complex types were developed; these made it possible to tell the compiler how to make room for data. A flexible variety of types entailed

TcL nevertheless comes with a builtin set of excellent error handling routines and explicit and helpful messages. you can be sure not to create a conflict if you always declare your own names with at least one upper-case letter. we shall assume that the procedures provided with the usual releases of TcL are reserved. brackets. and your program crashed! All this is unnecessary in TcL: The user never has to be concerned about where in memory the computer is going to store program data. . quotes. Williams 2010-09-24 TcL Workshop 7 fewer concerns about details of storage. Examples are whitespace. These characters should be avoided in a declared identifier of a proc or a variable. which is to say. Therefore. Because the language is interpreted. The user may declare a new procedure (proc) to replace any common procedure such as set or puts. no compiler-created object names or offsets. However.J. but. All statements are one line We use the word command hereafter interchangeably with the more accurate word. However. protected. braces. In a scripting language. By contrast with words. Miss your string length. Even strings in the old languages had to be declared of a certain length (number of bytes or characters). a statement is something that makes some sort of change. TcL source code lines can be identified by number in a stack dump. in this workshop. any "line" may be continued with an escape character (backslash. fatal errors are met with a simple "stack dump" in plain text. or in plain C system calls). "Strongly typed" languages might as well have been called "monomorphically picky" languages. '\') to another line. There is no such thing as a segmentation fault. some single characters. dollar sign. No addresses. making it easy for the user to correct any common mistake. Simplicity Takes Precedence No reserved word Consistent with its simplicity. from redefinition. We therefore shall discuss such procedures as though they were fixed features of the language. In a programming language. Standard scripting procedures all are lower-case All procedures in the usual TcL release are named entirely in lower case (as in verilog. so this is not a limitation in practice. quoted ends-ofline are ignored. parentheses. if not quoted or escaped. M. and. Every command in TcL must be on a single line. percent sign. are treated as tokens and can not be used except according to TcL syntax. statement. TcL has no reserved word or keyword content. and the semicolon. commands are run to effect statements. at the cost of increased memorization and more specialized syntax.

for example. any printable character is legal. This just means that TcL is very forgiving of a forgotten semicolon. or. M. Like "//" in C++. Unlike these other languages. there is only one way to insert a comment in a TcL script. omission makes the code less portable among operating systems with different NL tokens. TcL requires that a comment begin only where a new command name is allowed. this line-comment token means that everything from its location to the next NL is a comment and will be ignored by the TcL interpreter. Statements = semicolons Every command in TcL should be terminated with a semicolon. and it can lead to erroneous interpretation of comments. It is not a good practice purposely to omit the semicolons. For example. with a '#'. Some built-in procedures accept optional syntax. a NL (new line. an if with an else on a subsequent text line will be illegal unless the if's line end is escaped or quoted. as in C or C++. Declared names are alphanumeric A user-declared name should be limited to include only alpha characters. Williams 2010-09-24 TcL Workshop 8 A common error of beginners (and experts) in TcL is to overlook line continuation when a command is complex.J. One comment token Finally. Blanks are separators TcL almost everywhere uses whitespace (blanks or tabs) as word separators. The language is case-sensitive. put a comment only after the semicolon in a command. only on its own new line. So. better. However. One-character blocking tokens Blocking of multiple statements is done by braces ('{' and '}'). and separated strings are words. The same braces are used for strong quoting of strings. end-of-line) character is allowed to substitute for a semicolon in TcL in many contexts. We shall see examples of such commands later. one just separates the three words with blanks: procX41 A1 A2. However. such as the words then or else in a branching if statement. and numerals. . to call a procedure named procX41 and provide it with two arguments A1 and A2. the underscore ('_'). This is consistent with the idea that everything is a string. There are no begin or end words.

the interactive shell interpreter. For example. However. Variable values are expressed by $variable_name. there is no syntactical distinction. Choice of a type is based on the work foreseen in accessing the data with minimum programming effort. the TcL interpreter would issue an informative error message and stop. this can be useful for debugging messages or for user interaction. Because everything in TcL is a string. set NewVar "$NewVar1 $NewVar2". . Strings A plain string variable contains just a vector (ordered set) of characters (chars). All data in TcL are assemblies of strings. and arrays. Type just tclsh to start the interactive shell. declarations are optional. Two preexisting variable values can be stored in NewVar by. lists. Williams 2010-09-24 TcL Workshop 9 Data Types We shall organize our presentation as though there were three distinct TcL data types: strings. Any command assigning a value to a variable creates a new variable if the one named does not exist already. Both are run as tclsh. Variable names variable_name are created when first assigned. and the script file interpreter. Variables are assigned by name and expressed by preceding the name with '$'. for example the sorting of short strings.J. the context determines which one. the language provides options to force either numerical or textual evaluation. In the few ambiguous cases. In general. a clever TcL writer can achieve any goal using any available type. lists. set NewVar 1. we may refer to three basic types of TcL variable: Plain strings. M. the difference is just convenience. and arrays. The puts ("put string") procedure may be used to print the value of any such variable to the screen. Because numerical values have no unique syntax. creates a variable named NewVar storing a string "1". any command using the value of a nonexistent variable causes an error which generally will abort a script. If either NewVar1 or NewVar2 had not been created previously. Variables Variables are treated as representing text or numerical values depending on context. give it a file name to start the noninteractive shell. There are two different TcL interpreters.

which always are open by default. redirection of output to a file might be possible by '>' or '>>'. # This causes a pause until a CR is entered. There also is an always-open stderr stream.. Corresponding to puts to the screen. Get ready for a lab! to the screen (TcL shell console window or invoking OS shell window). For example. However. it is possible to modify stored strings arbitrarily. because terminal I/O typically is buffered. it presents itself in the invoking console window. flush stdout. a plain variable is assigned a value by the set procedure and may be printed to the screen by the puts procedure. it only can execute TcL commands. puts -nonewline "Enter the value: ". Williams 2010-09-24 TcL Workshop 10 When the interactive interpreter is invoked. Redirection of output by '>' or similar tokens is illegal. In TcL. not to any interactive shell. would print. for formatting strings. From here on. without flush. TcL channels called stdout and stdin. the script-interpreting TcL shell is not a system shell. the screen or terminal I/O is associated with a standard output stream and a standard input stream. and. primarily when numerical . The flush procedure is required by default. Typical interactive script input then goes as follows: .J. This procedure accepts format specifiers the same way as does printf in C++. This interpreter may overlay TcL functionality onto a normal shell. The default for puts is to print to stdout.. to read input. however.. the interactive TcL interpreter displays a default shell prompt of some kind. These streams are accessed by two predefined. then. in this window. This would be illegal in a script: puts $Message > Logfile.. Interactively. gets stdin Ans. TcL includes a special procedure. . no message would appear before input could be entered. and. gets requires that stdin be named explicitly. M.. set Message "Get ready for a lab!". there is gets from the screen (console input). Either way. puts $Message.. unless explicitly stated otherwise. all explanations in this book will refer only to the TcL script interpreter. Just as in Linux or Unix. format. (script uses $Ans value) . By calling format inline. ordinary OS commands may possibly be run as well as TcL commands.

set String " The important words ". Inline execution in TcL uses bracket tokens. and the end word. we would view the 0-th character to be 'a'. "hij". set Message "Get ready for a lab!". Williams 2010-09-24 TcL Workshop 11 values are involved. it may be addressed by the special name. to avoid a syntax error. "abc" and "defghij". the same string may be viewed as a list of two words. in TcL. an especially useful one is string trim. . The first word in a list is numbered 0. puts $Message. In TcL. It consists of 11 characters. rather than the backquote ('`') of Linux or Unix shells (unlike these systems. The quotes (") make the string literals single words. For example. Lists A list is just a string used in certain commands according to the string's word organization. puts $Message."]. Windows has no inline execution). The last word in a list is numbered 0 or some greater integer."]. string trim $String would return "The important words". We shall study a few of the many string subprocedures later.J. As a string. lists and strings are interchangeable. and so on through the 10th. which removes leading and trailing whitespace characters from a string. The substrings (words) of a string are the elements of a list and can be addressed numerically by an index integer. > Get ready for a lab! set Message [format "%s %s" $Message "And bring your textbook. %. This procedure also can add newline and other special characters to a string. end. > Get ready for a lab! And bring your textbook. after. the 1st to be 'b'. '[' and ']'. On the other hand. and $ are tokens in TcL and can be identified and treated specially even when not separated by blanks from adjacent text. M. counting the blank between 'c' and 'd'. a list is a vector of words. but it would consist now of three words (list elements). One-dimensional ordering is assumed. ]. For now. The [. just as a string is a vector of chars. it just depends on how one accesses a string. the string still would be 11 characters long. so. at least one blank must separate each of the six words above. which would be 'j'. For example. "abc". "def". Consider this string: "abc defghij". If the 'g' were replaced by a blank. However. The TcL interpreter sees the second set command this way: word 1 set word 2 Message word 3 [format word 4 "%s %s" word 5 $Message word 6 "And bring your textbook.

"What a list!" puts [lindex $MyString 2]. # Retrieve element 1. # The internal quotes are escaped. However. > 7 # Total of 7 elements. > a b c d e f puts [lindex $MyList 1]. \"What a list!\"". and its elements are the words of that string. # Now there are 5 elements. \"What a list!\"". its entire contents can be printed by puts. will work as well with plain strings as with strings created as lists. puts [lindex $MyString 2]. puts $MyString. > He said. > "What # An escaped quote is just a char in a word. the access to list elements is dynamic. a TcL list might be referred to as an array. two-element lists. puts $MyList. Williams 2010-09-24 TcL Workshop 12 TcL lists are defined by list procedures. puts $MyList. The pairs in an array are unordered. use split: set MyString "He said. > What a list! set MyList [split $MyString]. In other languages. Arrays A TcL array differs from a list in that its elements are paired strings. Examples of a list stored in a variable: set MyList [list a b c]. As shown above. > a b c lappend MyList e f. Also. puts $MyList. which is to say. M. > What a list! To create a list from a string. the first . a TcL list truly is a string. puts [lindex $MyList 2]. Within each pair. {a b c e f}. > a b c e f # OOPS! Forgot d! set MyList [linsert $MyList 3 d]. it simply is by internal quoting or by interpretively counting the numerical positions during modification or retrieval. puts [llength $NumList]. > b The number of elements in a list may be obtained by the llength procedure: set NumList [list 3 4 5 6 8 23 57]. not structural. Quoted words in a string are just one word: set MyString "He said. The list command exists only to simplify creation of a list containing quoted words. such as lindex.J. All list commands. allowing individual access to each word as a list element. # The new list is initialized with 3 elements.

> Warning Error Using array get without any name will return an entire array as a list with an even number of elements. to convert it to a plain string with no internal structure. Here is an example of two common.} Notice the strong quoting automatically provided in the lists returned. # The value as a string. All array access is through lists. > wrong # args: should be "array set arrayName list" # array set MessageArray [list "Error" "$ErrorMessage" "Warning" "$WarningMessage"].".} puts [array get MessageArray Warning]. Williams 2010-09-24 TcL Workshop 13 string is the array element name. This list is strongly quoted. basic array commands: set ErrorMessage "Error: Please correct before continuing. # The name as a string. The strong quoting must be removed to treat the returned values as plain strings.". which returns the string element indexed at a given list offset: set N [lindex [array get MessageArray Warning] 0]. > Warning # set V [lindex [array get MessageArray Warning] 1]. thus. but the order of the elements generally will be arbitrary. there is a fourth special command. The elements in the list will be paired correctly as {name value}. and. to return all the element names: set Names [array names MessageArray]. M. > Warning: Your input may be incorrect. array set Array1 [list 1 A 2 B 3 C 4 D 5 "a b c"]. When reading out an array element. One way is to use lindex. TcL arrays necessarily are associative. Array elements must be accessed by element name. puts $Names. both the name and the value can be returned as a two-element list. > Error {Error: Please correct before continuing. > Warning {Warning: Your input may be incorrect. and the second is the array element value. puts $N. For example. array names. puts [array get Array1]. set WarningMessage "Warning: Your input may be incorrect. puts $V. puts [array get MessageArray Error]. Each array element is a two-element TcL list. and that the command array get returns a copy of the name along with the stored value. one of the list access commands must be used. > 4 D 5 {a b c} 1 A 2 B 3 C .J. To aid access by name. array set MessageArray "Error" "$ErrorMessage" "Warning" "$WarningMessage".

# Plain string variable x created. > Second. they allow a command or string word to be continued on multiple lines. however. Quoting Quoting is perhaps the most difficult aspect of TcL. # ERROR! array set x [list 1 2]. In addition. this is a rare example of type-checking in a typeless language. it can not be used for a plain string or list variable. set y 1. Strong quotes prevent variable substitution. set x 2. Both strong and weak quotes create a single (string) word. C shell. Williams 2010-09-24 TcL Workshop 14 There is a simpler syntax for array access to single elements. puts "$MyArray(B). However: . or. as it is in other untyped languages such as Bourne shell. Likewise. '\') may be used to strong-quote a single character. once a name has been created in an array-specific command. Variable Name Conflicts Once a name has been created in a command specific to a plain string or list variable. There are two fundamentally different quotes in TcL: Braces create strong quoting. It is important to understand how many words result from a given quoting. list and plain-string commands may be used indiscriminately and interchangeably on string or list data. it can not be reused for an array variable. double-quotes create weak quoting.J. the escape character (backslash. Examples: set x 1. To reuse a variable name as in the examples above. bash shell. weak quotes allow it. or awk. • • • Both strong and weak quotes conceal NL's from the interpreter. Instead of array get. use an unset command to delete the name first. use parentheses to access values stored in an array: array set MyArray [list "A" "First" "B" "Second" "C" "Third"]. array set y [list]. and what happens inside the quotes when the command is read by the TcL interpreter.". # ERROR! Array commands are picky and exclusive. # No problem: String value replaced. # Empty array y created. M.

the interpreter strips off the quotes and proceeds with variable substitution and inline command execution as though the quotes never had been there. for { set i 0. quotes can not be nested. } { $i <= 10 } \ { set i [expr $i + 1]. This other string consists of two doublequote characters. an initialization word. however. Also. it is strongly quoted. } { lappend MySquares [expr $i * $i]. However.J. for. a continuation test expression word. perhaps unexpectedly. > x = 7 puts {x = $x}. the TcL for loop is a procedure requiring four words as arguments. Once the words and command lines have been identified. with abc between them: {"abc"}. variable substitution and inline command execution can occur within any of them. > 0 1 4 9 16 25 36 49 64 81 100 If the test expression had been weakly quoted. must be followed by: 1. which is the way to do arithmetic in TcL: set x 7. # Strong quotes = no variable substitution. puts "x = $x". a loop update word. The complexity arises when using quotes with TcL procedure calls. > 7 + 12 = [expr 7 + 12] So far. When the interpreter encounters a procedure call. } puts "$MySquares". A typical for loop would be. $i would not have been available for loop control. For example. and. > 7 + 12 = 19 puts {7 + 12 = [expr 7 + 12]}. M. but only after the loop is running. weak quotes allow it. . # Strong quotes = no inline command. Each of these for loop words should be delimited by strong quotes. and to ignore NL's (if any) inside the quotes. a body of one or more commands to be executed so long as the loop is continued. variable substitution or command execution may have been done before procedure execution. it would have been substituted away. 3. it is weakly quoted. > x = $x # puts "7 + 12 = [expr 7 + 12]". 2. 4. if the quotes were weak. this seems simple enough. This string consists of two brace characters with abc between them: "{abc}". it uses the quotes (usually strong quotes) to determine which word is which. we demonstrate the expr procedure. Williams 2010-09-24 TcL Workshop 15 • Strong quotes prevent inline command execution. As an example of quoting. The procedure name.

Because everything is a string in TcL. . inline execution within weakly quoted strings will be commonplace in complex scripts. notice the backslash which quotes the NL and allows the command to continue past the line with "for" on it. This almost never should be the case with for. in the way that an inline command is parsed. This should be a syntax error: puts [format "%s = %d" "The result" $N]. Conversely. In TcL. Enclosing the command in weak quotes should make it legal but doesn't seem to work: puts "[format "%s = %d" "The result" $N]". inline execution is indicated by open and close brackets ('[' and ']'). Inline Execution We already have seen several examples of inline execution. such as switch or foreach. } { $i <= 10 } { set i [expr $i + 1]. and.Line 2. weak quoting often may be required for other controls. } { lappend MySquares [expr $i * $i]. } { $i <= 10 } { set i [expr $i + 1]. } { lappend MySquares [expr $i * $i]. This permits nesting of inline commands without need for escapes or quotes. escaping the NL (using '\') within an multiline inline command may not work: puts [format "%s = %d" \ "The result" $N]. any expression in brackets must be a legal TcL command. M. } The next would be an error. The following way of quoting the NL would work as well. for { set i 0. because every TcL command must reside on one line: for { set i 0. There is some inconsistency in recent TcL releases. It is possible to embed a '[' character in a string by strong quotes (see example below). It is applied to any procedure declaration. The NL is not quoted. However.Line 1. The strong-quote-stripping effect also occurs for user-declared procedures. the TcL interpreter uses the declaration of a procedure to determine how many words to expect when the procedure is called.J. should you use weak quotes on a command word. the value returned by that command will be substituted for the command by the inline execution. <-. Note: The '"' tokens in an inline command are not parsed until the command is run. Furthermore. which usually requires an explicit variable expression ($i). } <-. Only if you want a command word to undergo variable substitution or inline execution. Williams 2010-09-24 TcL Workshop 16 Also. and between Windows and Linux. as we shall see later in the workshop.

it allows format conversion of strings or variables.1f B=%0. For a very long inline command. set V3 "and string3". This command not only concatenates strings. average=7. Notice how the long format-specification word is stored in $Fmt to avoid breaking the inline command: set A "10". set C "4. puts $ResultVar.5.1 C=4. avg=%0." puts $ConcatV.1f C=%0. set V1 "Here is string1". set ResultVar [ format "%s %03d is %04d or %04x in hex. set ConcatV "$V1 $V2 $V3. for portability. set Intro "Ten times the decimal number". Here are two concatenation examples including arithmetic. A+B+C=$Sum. A+B+C=23. For example. puts $Formatted.83333333333.J.1f.}. A more flexible but more complex way is to use the format command.]. set Formatted [format "$Fmt" $A $B $C $Sum $Avg]. Inline executions may be nested to any depth. set Avg [expr $Sum/3. # set Fmt {A=%0. store the words separately in variables and concatenate them before running the command. set B "9." $Intro $N [expr 10*$N] [expr 10*$N] ]. Here is a typical example (the long set ResultVar inline command is on one line but is displayed wrapping to the next line): set N 142. puts "ResultVar=\[$ResultVar\]. don't break an inline command.0 B=9.1".1 C=4. Williams 2010-09-24 TcL Workshop 17 Therefore. > Ten times the decimal number 142 is 1420 or 058c in hex. # set Plain "A=$A B=$B C=$C.".4.1f. > Here is string1 and string2 and string3. set Sum [expr ($A + $B) + $C].2f. average=$Avg.".4.0]. M. A+B+C=%0. puts $Plain.5.4". The special benefit of format is the control it allows when numerical results are expressed. String Concatenation The simplest way to concatenate strings is to store them in variables and enclose the variables in weak quotes. > A=10 B=9. set V2 "and string2". > ResultVar=[Ten times the decimal number 142 is 1420 or 058c in hex. A+B+C=23.83. > A=10. . average=7.

The expr command is very versatile and can evaluate logical. the quotes inside an inline command are not parsed until the command is interpreted (run).00]. and integer bitwise or shift expressions. puts "R + 1 = [expr $R + 1] and R + 1. The only other arithmetic command is incr. random integers. *. For example: set R 4. set Pi 3. various roundings.1416. trigonometric and hyperbolic functions and their inverses.". and / available.2656.00 = [expr $R + 1. it may print integer expressions automatically with one decimal place precision to ensure that the string will be taken to be numerical.00 = 5. exponentials. such quotes actually effectively are nested to one level. so complex expressions must be operated upon by user-defined procedures combining their components. > Area of a circle of radius 4 = 50. Arithmetic The main command in TcL for arithmetic is expr. -. So. The expr operators for mathematics are very numerous: Not only are the basic arithmetic binary operators. power functions. logarithms. relational. Parentheses may be used for grouping complicated subexpressions. > R + 1 = 5 and R + 1. .0. but expr also can evaluate expressions of absolute value. and others.". It composes numerical expressions in float format. puts "Area of a circle of radius $R = [expr $Pi * ($R*$R)]. M. square roots.J. we have seen a few examples of it already. Williams 2010-09-24 TcL Workshop 18 Although quotes can not be nested. We'll see later how to write our own shorthand procedures which accept a variable name rather than an expression of its value. which increments a variable. incr x is identical to set x [expr $x+1]. The expr command does not include any complex arithmetic. +.

' '. . the outermost one or more. Optionally. # Escapes to prevent inline execution.J. because the last '_' would have been protected by the 'H'. Williams 2010-09-24 TcL Workshop 19 string Commands -. set String [string trim $String]. set Name [string trim $MacroName {_ H}]. set String " There is an invisible TAB in front. puts "\[$String\]. so. and trailing blanks. in the set was trimmed. or all. any char set may be trimmed. "ARG_ALL_". 8. these three will be trimmed: set MacroName __ARG_ALL_H.trim We mentioned string trim before. the quotes include '_'. puts "\[$String\]. > ARG_ALL In older releases of TcL. the v. because in TcL it is very handy to know when whitespace has been removed: For this.4 result would have been.". M. and 'H'. > [ There is an invisible TAB in front. ].".]. and trailing blanks. ". 8. > [There is an invisible TAB in front. and trailing blanks. current (v. use string trim. puts $Name.5) versions trim until an untrimmable char is met. only one char. In the next example. # List the chars to trim. any of. Thus.

Convert string values to various numerical formats. Return the number of elements in a list. Loop over a range of values. Your lab setup has put the TcL man pages before the system ones. you can use man command for help on any of these commands. M. Put (print) the value of a string by default to the screen. Split up a string of words into a list. Remove leading and trailing chars (default = blanks). Express a list of all names in an arrray. Express a list element by its numerical offset in the list. executing commands for each. Express an arithmetical or logical result. so. Force the stdout channel to empty its string buffer now. refer to an element by name N. We'll now do a lab to gain some experience with the use of the basic commands. Assign one or more name-value list pairs to an array. Wait for input and copy an input string. Append one or more new list elements at the end of a list. express the value stored under name N. In array Array. Express one or more name-value pairs in an array. . Assign a list from zero or more words. we have seen examples of all the most basic commands: set unset puts gets stdin flush stdout format string trim expr incr for list split lappend lindex linsert llength array set array get array names Array(N) $Array(N) Assign a value to a plain string variable. Williams 2010-09-24 TcL Workshop 20 Basic Command Review At this point. Increment a variable by name. Remove a variable. In array Array.J. Insert one or more new list elements at a specified offset.

Store the three numbers in variables before anything else. in all our lab exercises. Williams 2010-09-24 TcL Workshop 21 Lab 1: Simple TcL Scripts We recommend the enhanced vi text editor. Use file names ending in . and each format for the sum. stdin and stdout. Write a script which prints a message of some kind and prompts to exit. M. 3. % tclsh scriptFilename 1. the script should prompt the user to enter four numbers. vim. even if renamed. Write a TcL script which. You will have to deal with the TcL special I/O channels. 4.J." 7. Create a different TcL script file for each of the following exercises. this is the usual extension for a TcL script file. Finally. but by storing it in a variable before printing it. 2. in your printed message. 5. 8. Write a script which announces its (file) name correctly. which always holds the script file name. There is a special variable TcL variable. 6. Modify your previous answer so that the prompt does not feed a NL. After the fourth number is entered. You'll get a help menu giving all the detail you want on the expr command. "Here I am!". open a shell window and type man expr. and report results in decimal and hex before terminating. It acts like vi in command mode but behaves more like emacs (or any other mouse-aware editor) in text-insert mode. " ' and \. Write a TcL script which adds three numbers. each one on its own line. Be sure to report the three numbers.tcl. and 7. the script should compute the sum of the four. thus the cursor will stay on the same screen line as the prompt. . and the product of the four. To begin the lab. log in and change to your Lab01 directory. without use of variables. try looking through the man pages for other TcL commands. Test each script by invoking. and may be invoked with TcL-specific colorized syntax highlighting. When the user hits CR ("carriage return" = NL key). the script should terminate. This editor is based on emacs. Write a TcL script which prints the same characters as in Step 6 or 7 and then prints them individually. "Some special characters in TcL are: % $ # @ & [ ] { } ( ) : . 3. to accomplish this correctly. $argv0. Repeat the message in 6. If time permits. prints to the screen the message. Write a TcL script which prints to the screen the message. and prints the sum to the screen in decimal and hexadecimal format. Invoke vim in text mode by typing vi or vim on a shell command line. After giving its name. 5. vim -g brings up the editor in a new graphical window with its own menu system. is freer than vi of window-system related bugs. until the user enters a CR.

Furthermore. Avoid this kind of reassignment in script writing. M. proc names are visible everywhere and can not be restricted to local use. A proc may be called by another proc. object-oriented programming. However. because the embedded proc must be debugged in the exact context of the caller. this is not good design and may make for confusing and error-prone results. It is allowed to declare a proc inside another proc. This sequential reassignment of the name is allowed in TcL and occurs silently. Always declare all procs in a script before the first one is run. The same proc name may be declared more than once in the same script. but. the last declaration is the one used in a runtime statement. optionally can return a value either through the return procedure or by means of linked or global variables. and the statements to be executed in the other: proc DeclaredName { argument list } { statements } Either or both of the last two words may be empty. which increases the need for debugging. It is allowed to intersperse proc declarations with runtime statements at the script level. Declaration A TcL proc is declared by giving its name and two other words. usually. very like a C function. Thus. This is poor design in a script even of ordinary complexity.J. unlike variables. but. The runtime involving the call of a proc must follow its declaration. an argument list in the first word. at least one statement (command) is included in the second word. once correctly written. because. embedded procs may be somewhat useful in programming of a very large script if embedded in a namespace. procs may be declared anywhere in a TcL script. Encapsulated in a namespace. Williams 2010-09-24 TcL Workshop 22 Program Structure Procedures There is no distinction in TcL between a procedure and a function: There is just one proc construct which. . making for inefficient multiplication of effort during the implementation of a script of ordinary size. TcL may be adapted to a semblance of encapsulated. a local proc may be declared and called somewhat the same way as a method in a C++ class. an embedded proc may be difficult to reuse in any other context. the calls are part of the declarations of those other procs. With this one restriction.

the value may be used either for status (as in a C system call) or for use as data. set tmpI [expr [lindex $A 3] + [lindex $B 3] ].". Williams 2010-09-24 TcL Workshop 23 However. } # Sum of 2 complex numbers. set I2 2. A and B must be 4-element lists: proc cxSum { A B } { set tmpR [expr [lindex $A 1] + [lindex $B 1] ].". there are no reference or pointer types in TcL. Concatenation of a variable name and a plain string can be done with strong quotes and has the same appearance as the same concatenation in the bash shell: puts "The sum of $R1+${I1}j and $R2+${I2}j is $Sum(R) + $Sum(I)j. M. for the proc name expression (and arguments. if it does not. set R2 7. Never declare a proc inside another proc. . } # Runtime: set R1 5. it must be in a list format suitable for use in an array. this kind of programming generally is wasted time and effort for scripting and thus is beyond the subject matter of the present workshop.J. # Use array for simple access: array set Sum [cxSum $Num1 $Num2]. A proc need not return a value explicitly. If a proc does return a value. set I1 3. So. set Num2 [makeCx $R2 $I2]. set Num1 [makeCx $R1 $I1]. Such values should be transferred in list format (or by a linked array variable. the value of the proc is that of the last statement executed in the proc. When the return is to be assigned to an array variable. A return value must be a string. puts "The sum of $R1+j$I1 and $R2+j$I2 is $Sum(R) + j$Sum(I). Return value Execution of return in a proc terminates the proc and substitutes the returned value. return [list R $tmpR I $tmpI]. if any. Complex sum example: # Create a 4-element list suitable for cxSum() or array use: proc makeCx { R I } { return [list R $R I $I]. The value of an array variable can not be returned. > The sum of 5+j3 and 7+j2 is 12 + j5.. > The sum of 5+3j and 7+2j is 12 + 5j. later). if any) in the context in which the proc was called.

The arguments actually passed will be assigned to the first ones formally declared. Any formal argument to a proc may be declared with a default value. # formal2 has a default. there are two exceptions: When formal argument defaults are declared. the number of actual arguments may be greater than the number of formals. > wrong # args: should be "productDef A ?B? ?C?" • Declaration of a variable number of arguments. an error will result. This is the same as in C. } puts [productDef 5 7 9]. there is no way explicitly to name the formal to which a given actual value should be assigned. and the defaults will be assigned as the leftover actuals. Example: proc productDef { A {B 2} {C 1} } { return [expr $A * $B * $C]. Calling in TcL is by position.J. > 35 puts [productDef 5]. defaulted formals must be used only for all formals. whether or not they are defaulted. any number of reals may be passed to follow the ones named explicitly by using the word args in the declaration. • Declaration of argument defaults. or only for those at the end of the formal argument declarations. Therefore. However. only: In a proc call. Williams 2010-09-24 TcL Workshop 24 Arguments Each argument in the call of a procedure ("actual argument") must take the place of a word ("formal argument") named in the declaration of the procedure. the first being the name of the formal and the second being its default value: proc name { formal1 {formal2 def} . M.} { statements }.. when the formal args argument is declared. If a proc is called with a number of actual arguments greater or less than the number of formal arguments. The syntax for defaults is just to replace the name of the formal with a two-element list. The args variable captures the list of all actual words (even if none) passed in or after its formal position. > 10 puts [productDef]. The name args must be the last formal. the number of actual arguments may be less than the number of formals. > 315 puts [productDef 5 7]. provided there are enough omitted arguments with a default assigned. . Whether or not the formals in a proc declaration are assigned defaults.. the proc then may be called with fewer actual arguments.

proc productArgs { A args } \ { set Prod $A. A procedure declared inside another procedure also is global. } puts [productArgs 5 7 9]. . } return $Prod.J. multiple-module TcL program. using the word global. such a variable is visible to any procedure run in the same script. Procedures and Global Variables The procedure names declared in the script are global and accessible anywhere. not at the script level. foreach {Num} $args { set Prod [expr $Prod*$Num]. Thus. A global variable is one declared at the script level or in a procedure with the word global. For very large programs. proc names can be encapsulated by means of namespace delarations. > 315 puts [productArgs 5 7]. but it limits the size and complexity of a large. Once declared. > wrong # args: should be "productArgs A args" Notice that the args construct in this second example would allow productArgs() to work with any number greater than zero of actual input arguments. Williams 2010-09-24 TcL Workshop 25 For example. This permits any procedure to call any other procedure. M. > 35 puts [productArgs 5]. The TcL we shall study today can not support C++-like classes. The global variable keyword may be used only inside a proc declaration. stack framing applies to variables but not to procedures. This is no problem for scripting. regardless of where either is declared. because methods (proc's) can not be encapsulated. > 5 puts [productArgs]. but only provided that that procedure also declares the variable for itself.

Omission of either "global x. puts [incr1 I]. Williams 2010-09-24 TcL Workshop 26 For example. . puts "x=$x". # *L for Local link. } set I 5. > 6 puts [incr1 I].". set IntInL [expr $IntInL + 1]. the variable maintains its value so long as the caller in which it is located has not terminated. It is wise not to attempt a link in a proc declaration except to a variable named in the argument list when the proc is to be called.J. calledProc. This limitation implies that the caller always will be able to accommodate to variables which may be modified by the called proc in ways unforeseeable by the caller: The caller always will know the names of the variables passed. > 7 Because the script itself is the caller of incr1() in this example. } # callerProc. proc callerProc { } { global x. the value of $IntInL is stored at the script level in $I and persists between incr1() invocations -. rather than being passed by the entire value stored. When the called proc terminates. set x [expr 5*12]. > x=60 # puts "The global x=\[$x\]. they are like pointers in C or C++ in that they allow an argument ("parameter" in compiled languages) to be passed by name when a proc is called." declaration causes the puts in calledProc() to fail.in fact. } proc calledProc { } { global x. A linked variable is one used while a certain procedure is running but which stores its value in a caller's stack frame. The incr command mentioned previously could be implemented in TcL using a linked variable this way: proc incr1 { IntegerIn } \ { upvar $IntegerIn IntInL. > The global x=[60]. it persists until the script terminates. M. Linked variables are created by the TcL upvar command.

A stack consists of a sequence of stack frames holding variables local to each running TcL procedure (proc). this occurs when the procedure defining their stack frame again begins to run. calledProc x. reusable procs.J. > MyX=61 > MyX=62 A global variable declared only in one proc persists like an upvar'ed variable. proc callerProc { } \ {set x [expr 5*12]. currently running proc can access only its own frame. or which should persist over successive proc calls. Wherever possible. calledProc x. not globals. only on the script. Global variables are more error-prone than linked variables. A new frame is created for every proc call. except that it does not depend on a caller's stack frame. puts "MyX=$MyX". Variables in other frames become accessible when they are popped off the stack. should be used for storage which must be accessible to other proc's. set MyX [expr $MyX + 1]. M. The TcL Stack Frame The TcL interpreter emulates compiled code to the extent of maintaining a stack. not $x. Williams 2010-09-24 TcL Workshop 27 As another example. this makes for more portable. linked variables. # Just the name x. } proc calledProc { MyVar } \ {upvar $MyVar MyX. . } callerProc. a proc called multiple times gets a different stack frame each time. A big advantage to linked variables passed in the argument list is that the called proc can be designed and debugged without knowing the name of the linked variable being passed. The one.

and $Count. } proc getInput { } \ { puts -nonewline "Enter some words: ". Classically. getInput prompts for input and then calls findWords on the input. $StringIn. set Count [llength $WordList]. One way to accomplish this would be a script file as follows: proc findWords { StringIn } \ { set WordList [split $StringIn]. gets stdin InputVar. because they were pushed onto the stack in a different frame when getFirstWord was called.J. and the script exits. return $First. When findWords terminates. . findWords resumes execution. this thus is in the getInput stack frame. flush stdout. the findWords stack frame is bigger than that of getInput. Thus. The script above is executed by the call to getInput. Williams 2010-09-24 TcL Workshop 28 For example. a program goes through a compilation (in "compile time") and then is executed (in "run time"). exit. The findWords procedure in turn fiddles with the input and then calls getFirstWord. but getFirstWord has no access to findWords' $Word or $Count. After getFirstWord terminates by returning the first word. $Word. $InputVar. While getInput is running. While getFirstWord is running. } proc getFirstWord { List } { set First [lindex $List 0]. set WordList [list $WordList]. it has access to a copy of findWords' $WordList in the form of $List. findWords $InputVar. as a result. it also has access to $WordList. declarations often are distinguished from the execution sequence of commands by calling the latter the "runtime" of the script. it only has access to one variable. counts the number of words. } # # Runtime: getInput. the first word=$Word". puts "The list contains $Count words. suppose we wanted someone to enter some text and then have a script count the words in the text as well as print the first word. it in turn terminates getInput. M. set Word [getFirstWord $WordList]. and reports the result to the screen. it has access to a copy of $InputVar in the form of its calling argument. As seen from its declaration. While findWords is running. This terminology also can be useful for an interpreted language such as TcL.

M. there is just the script running. Variables in the OS environment will be discussed later. Williams 2010-09-24 TcL Workshop 29 Representation of a TcL calling stack. it is pushed down onto the stack while getInput runs. getInput is pushed down onto the stack while findWords is running with a copy of getInput's $InputVar. only the script again remains. However. and linked variables. global variables. There are three exceptions to this statement: Procedure names. greyed-out frames are inacccessible. The runtime sequence is by the numbers at left: Variables in dotted. every procedure has access to the copied values of the arguments passed when the procedure is called. then. Each procedure thus has its own set of local variables in its runtime stack frame. The preceding discussion is a little oversimplified. and it has no access to any other variable in the script. By the end of the run. . but. First. for small TcL scripts entirely in the default namespace.J. it is correct to say that it is stack framing that permits the name isolation necessary to any significant structured programming.

The commands may include any legal runtime statement. optionally. The expression implicitly calls expr and can be any logical or relational expression. depending on the value of an expression.J. if { expression } { commands } { other_commands } The if permits optional then and else words to precede a block of commands: if { expression } then { commands } else { other_commands } For consistency with C. commands are run. The expression also can be the value returned by a statement such as expr or returned by a call to a user-declared proc. >=. There need not be an other_commands word. eq and ne. if The if is used to execute one of a few alternative blocks of commands. by plain quoting. then rarely is used. . Newline escapes may be by backslashes. if present. There are two special operators. multiline commands must be escaped in blocks. Because every TcL command must be on a single line. using >. The documentation for expr lists these expressions. and because multiple lines of commands so often are involved. if { expression } { commands } { other_commands } If expression is true. The basic syntax is. other_commands are run. Williams 2010-09-24 TcL Workshop 30 Control Constructs TcL includes control constructs typical of a modern programming language. ||. &&. and other typical operators as in C. ==. equality or inequality. M. if { expression } \ { commands } \ { other_commands } or. including control constructs. otherwise. which compare strings and express. There also is an optional elseif word which almost never is used but which is equivalent to "else {if" (see below). respectively.

.0". } } Example of numerical versus string compare: # Only the first message is printed: set x "1.$y] > 10 } \ { puts "x=$x is too big!". The syntax is.".".. default { default_commands } } Notice that expression should not be in a strongly-quoted block. If the last alternative is the word default. if { $x == $y } \ { puts "They are equal numerically. there is no "fall-through" from a matching alternative to the ones below it. constant string. only one alternative will be run. to select a block of statements to be run. switch expression \ { alt1 alt2 . set y "1". M. unlike the C++ switch. Both of the expression to be switched upon and the alternative expressions may be variables. } \ else { puts "x=$x is out of bounds. Unlike the control expression for the for loop explained previously.".".". A switch may be used to return a value or. } if { $x eq $y } \ { puts "They are equal strings. } \ else { if { $x < 10 } \ { puts "x=$x is borderline. which depended upon an unevaluated $variable_name expression. Williams 2010-09-24 TcL Workshop 31 Example of simple if: if { [expr $x .J. { alt1_commands } { alt2_commands } . } switch The switch statement is very similar to the one of the same name in C++. However. a strongly quoted expression will not work in a switch unless it is intentionally a literal. } With two alternative branches: if { $x < 0 } \ { puts "x=$x is OK. return. more frequently. it will match if nothing else did.

Chapter 11. Usually. to check ranges of values. it is best simply to use an if. When invoked as switch -exact expression { . This is the default when no option has been given. M. anchor the following pattern to the beginning of the string.. match none or at most 1 of the preceding atom. there is considerable flexibility in switch. a switch may be run on the final.. match any one of the set of chars in brackets ('^' complements set). match exactly 1 or more of the preceding atom. }. for ranges of values. Williams 2010-09-24 TcL Workshop 32 Because the alternatives can be values of variables. examples of these wildcards are: . anchor the preceding pattern to the end of the string. match any number. of the preceding atom (so a* means 0 or more 'a' chars).. -regexp. the expression must exactly match the alternative to be run. There is further flexibility in switch because of the matching options allowed. switch will attempt pattern-matching on the alternatives. The switch -regexp option causes matching to be attempted on the assumption that the alternatives (not expression) might include certain characters used to compose regular expressions. . or character strings of one or more chars grouped in parentheses.. there is no way to use switch as a substitute for a multiple-branch if when the choices must be relational. including none.. -glob.. then. * ? + [ab. but.] ^ $ match any one char. one must generate numerical values to represent the relational ranges. To adapt switch to this use. et al.J. or Welch. using filename wildcard characters in the expression or the alternative (or both).. However. including no character at all match any one char [chars] match any one of the chars in the brackets \x match literally the char x. }. Such a basis is called an atom. resolved numerical value. and -regexp: -exact. These wildcards are: * ? match anything. -glob. Regular expressions are based on single characters. These are -exact. Use the help system. for details on this complicated topic. When invoked as switch -glob expression { . even if it is a TcL token.

complicated text action. Typical use of a switch is in a lookup table or state machine model. } "*egetab*" { puts "Please specify the vegetable: ". break and continue. which are useful with looping commands. M. This causes the loop to terminate.. no word which already is capitalized should be processed. There is a regexp command which does a regular expression match of a pattern against any substring of a string and works the same way as the switch -regexp just presented. if the control evaluates false.. However. Also. suppose our script is capitalizing the first 5. It is advisable to use the -glob option whenever feasible. For example. if we ever find a word beginning with '_'. > Please specify the kind of meat: for This is the first looping command we shall discuss. we already have presented syntax and examples of for loops in the section Quoting in the earlier language basics presentation. we should terminate the capitalization. .. it immediately causes the control expression for the innermost running loop command to be set false and that control expression to be read.J. > Please begin by choosing meat or vegetable: doChoice "Meat". Williams 2010-09-24 TcL Workshop 33 The -glob patterns and -regexp patterns use mutually exclusive syntax. . If break is executed in a loop.000 words in a list and then performing some other. This causes the loop either to terminate. } } } doChoice "Onions". There are two special procedures. it is simpler and easier to read in the script. it immediately causes the control expression for the innermost loop command to be updated to its next value and (re)read. If continue is executed. However. } default { puts "Please begin by choosing meat or vegetable: ".. or to continue to its next turn. . Example: Use wildcards to avoid capitalization or pluralization issues: proc doChoice { Choice } \ { switch -glob "$Choice" \ { "*eat*" { puts "Please specify the kind of meat: ".

and the commands executed. the control expression should not be quoted strongly unless it is a literal constant... foreach The foreach procedure defines an iterator.42 . foreach { variable_name } value_list { commands } The variable named will be set successively. (other commands. The simplest syntax is. As might be expected. foreach {N} "$Numbers" { puts -nonewline [format " %0. For example. } } . As for switch. } . foreach {N M} "$Numbers" { puts -nonewline [format "%d->%0. } > 68->2.24 8. if so. the variable will be set to each of them. other for loop commands . and the commands then will be executed. The variable_name above may be replaced by a list of variable names. we could use continue and break as follows: for {set i 1. set Numbers [list 5 68 12 34 55 59 64]..83 7. after break or 5000 words) .. For example. once to each value (element) in the value_list list. } \ { set WordV $WordArray($i).J. the list of variables will be set in order to a corresponding list of value_list elements. No matter what the value_list elements stand for.24 34->3.} {$i<=5000} {set i [expr $i+1]. Williams 2010-09-24 TcL Workshop 34 Given this.25 3. and each will be processed.. } > 2. both break and continue may be used for special control of foreach. The list will be traversed in the order of its elements. set Numbers [list 5 68 12 34 55 59 64]..2f" [expr sqrt($N)]].68 8. M. if { [regexp {^\[A-Z\]} "$WordV"] } { continue.42 7.46 5.46 59->7. } \ else { if { [regexp {^_} "$WordV"] } { break.2f " $M [expr sqrt($N)]].00 An iterator exemplifies the string-based polymorphism of TcL.. until the list is exhausted..

while does not depend on such information.} > U A.J. so that commands will run at least once. Whereas for or foreach assumes some known. finite number of turns in the loop. for and foreach. # Check for eof before printing anything: while { ![eof $ReadHandle] }\ { puts $Line. set Letters1 [list A B C D E F]. X D. so also is the foreach iterator loop control by name. Like the other repetitive commands. So long as expression is true. while The while command evaluates a logical or relational expression using the same operators as are available to if or expr. not necessarily numerical index. V B. it is used interactively in the TcL shell to run TcL commands from a file without invoking a new instance of the TcL interpreter. Y E. not necessarily by number as in a typical for loop. therefore. foreach {L1} "$Letters1" {L2} "$Letters2" {puts -nonewline "$L2 $L1. Just as an array is accessed by name. . ". The syntax is typical of modern programming languages: while { expression } { commands } A while loop does not presume anything about the number of times it should be run. it is especially useful for file I/O. the commands are executed and then expression is reevaluated. Z F. here we open a 3-line file and print it to the screen: set ReadHandle [open $FileName r]. For example. gets $ReadHandle Line. For example. because the length of a file usually can not be predicted from inside the script. Almost always. The while command generally requires that expression be initialized before the while. Williams 2010-09-24 TcL Workshop 35 It also is possible to designate pairs of variable_name lists with value_lists for more complicated problems. M. # The output (second two lines are from the while loop): > line_1 > line_2 > line_3 source Command This command provides a way to execute TcL residing in a file separate from the currently-running script file. W C. while responds as expected to break or continue. } close $ReadHandle. gets $ReadHandle Line. set Letters2 [list U V W X Y Z].

our sourceing script or shell could see the SourceFileVar variable.tcl > ScriptOK doSomething. Williams 2010-09-24 TcL Workshop 36 The syntax simply is. Suppose we have a file named SourceFile.tcl. proc doSomething { } \ { set Result "OK". # (stuff) return $Result. The sourced commands run as though inside a TcL proc declared and executed in the sourceing context. a return statement executed at the file level in the filename runtime will terminate its execution and return the result to the sourceing script or shell. > OK doSomethingElse. variables in the sourced file at the file level are visible in the sourceing script or shell. the returned string. here are some results: # These are in an INTERACTIVE TcL shell: source SourceFile. puts [doSomething]. In an interactive TcL shell. Not entirely consistent with stack-based encapsulation. > can't read "Result": no such variable Note that although variables set in a proc are not visible outside of it. the declared procs in the sourced file have become part of the interactive shell (or script) environment. # (stuff) return $FullResult. Also. The file filename must contain only TcL and may include declarations or anything else legal in a TcL script. return "ScriptOK". If the sourced file includes a runtime. . If we ran this file in another script by source SourceFile. whice prints variable and return values automatically. } doSomethingElse.J.tcl containing this: set SourceFileVar "File Variable!". this visibility greatly adds to the utility of the source command. source filename. "ScriptOK". M. just as though the sourced file were itself a declared TcL proc. however. } proc doSomethingElse { } \ { set FullResult "FullOK". > FullOK puts $SourceFileVar > File Variable! puts $Result. would be printed.

The syntax is just to provide a string (variable or literal) followed by a number giving the index (offset from the first char. Use string range (below) to extract a range of several contiguous chars.J.". it almost always will be best to copy its contents directly into the script and not use source at all. Williams 2010-09-24 TcL Workshop 37 It probably is not a good idea to design a script with source commands to implement significant functionality. to obtain the next char following "twang" in a string. . does add flexibility to TcL programming.} \ { puts -nonewline " [string index $String $i]". M. using a script to source one file (or a very few of them) which may be varied in content. one char at a time.} {$i<[string length $String]} {incr i. set String "My string is twangier than yours!". > The next char is i. management of multiple files creates unnecessary risk of error. copying out the char at the index. A Few string Commands Here are a few essential subcommands of the important string command. For example. see the online help for more information. set Ix [string first "twang" $String]. perhaps generated automatically or otherwise under external control. to double-space the chars in a string. For example. } > M y s t r i n g i s t w a n g i e r t h a n y o u r s ! string first This command searches for the first occurrence of the given substring in a string and returns the index of the first char in that substring. for {set i 0. See the example of the for loop in string index below. If the sourced file is not likely to vary. which is at 0) of the char to copy out. However. It returns -1 if the substring does not occur in the string. puts "The next char is [string index $String [expr $Ix+5]]. which is used to analyze or modify strings on a word or character level: string length This command just returns the length in chars of a string (or list). string index This command treats a string as a vector and indexes into it. set String "My string is twangier than yours!". There also is a complementary string last command.

but not the exclamation point. Williams 2010-09-24 TcL Workshop 38 string range This works the same way as string index. set Ix2 [expr $Ix2-1]. to copy out everything after "is". set String "My string is twangier than yours!". puts [string range $String $Ix1 $Ix2]. M. except that the two numbers given are used to as the indices (inclusive) determining a range (substring) of chars to copy out. > My string is stronger than anyones! . except that an optional final agrument can be a string which replaces the substring in the range given. The keyword end may be used as in string range. puts [string replace $String $Ix1 $Ix2 "stronger than anyones"]. For example. set Ix2 [string first "!" $String]. this saves the effort of using string length. For example. the range given is removed from the string. set Ix1 [string first "is" $String]. > twangier than yours string replace This works the same way as string range. The keyword end may be used to refer to the index of the final char in a string.J. set Ix1 [expr $Ix1+2]. using the same initial arguments as for the above string range example. otherwise.

c = Unix char special. ?. glob does not sort its output. in a directory with many entries. For complete details.. s = socket. Restrict matching to one or more types specified as: -types list b = Unix block special. its output viewed in a text window is a cloud of blankseparated file names -.J. Williams 2010-09-24 TcL Workshop 39 Basic File I/O In almost all contexts. -tails Only return the last component of a matching pathname. Only one of these is allowed in a glob command. "\k". -directory | -path -path introduces a path prefix which syntactically must be completed by a pattern. It gets its name because. f = plain file. unlike ls. The main options are: -nocomplain Suppress error on empty pattern match. refer to the online help. glob This command may be used with filename wildcards to list the contents of a directory. It returns a string similar to that of the Unix ls command. [ ] for character alternation. which natively uses '\' to separate pathname elements. l = symlink. The syntax is. Several examples follow for this important command. The wildcarding patterns are the same as in the C shell or bash shell: *. glob options pattern1 pattern2 . The default is -directory. and { } for pattern or name alternation. d = directory. p = pipe.somewhat reminiscent of a glob of jello dropped in your lap. M. -directory introduces a directory (pathname) at which pattern matching should be attempted. Such pathnames will be interpreted correctly in scripts run in Windows.. glob * > Lab02 Lab01 doc bin TcLman TcLbin glob /bin > /bin . Any single character k may be literalized by escaping it with '\' thus. Notice that. directory pathnames are best entered in a TcL script with Unix or Linux '/' separators.

addins {Driver Cache} security ..... glob -directory C:/WinNT -tails -type d * > system32 system repair inf Help Fonts ... omitted . and the acceptance of ':' and '/' as path separators... /var/log/ksyms... omitted . file The file command..?" glob -path /bin * > /bin glob -path /bin /* > /bin/tracepath /bin/ping /bin/ping6 /bin/dnsdomainname . /bin/awk /bin/basename . no matter what kind. /bin/csh /bin/aumix-minimal glob -path /var/log /* > /var/log/messages /var/log/lastlog /var/log/secure /var/log/maillog /var/log/spooler /var/log/wtmp /var/log/vbox /var/log/cups .. /var/log/ksyms. In Windows. omitted . omitted . /bin/csh /bin/aumix-minimal glob -directory /bin a* > /bin/awk /bin/ash...6 Here is an example of standardization of pathnames.... omitted .6 glob -directory /var/log -tails -types d * > vbox cups gdm samba uucp sa Examples of the sometimes-difficult -path option: glob -path /bin > wrong # args: should be "glob ?switches? name ?name .. like the string command.... .static /bin/ash /bin/arch /bin/aumix-minimal glob -directory /bin -tails a* > awk ash.... has numerous optional subcommands. Williams 2010-09-24 TcL Workshop 40 glob -directory /bin * > /bin/tracepath /bin/ping /bin/ping6 /bin/dnsdomainname . Returns true ('1') if the PathName. file exists. we shall introduce only a few of them here.5 /var/log/ksyms.. M...5 /var/log/ksyms. USB2 Temp java In this last. omitted .. omitted . exists.static ash arch aumix-minimal glob -directory /var/log * > /var/log/messages /var/log/lastlog /var/log/secure /var/log/maillog /var/log/spooler /var/log/wtmp /var/log/vbox /var/log/cups ......J. /bin/awk /bin/basename .. Call as file exists PathName. notice the automatic quoting of names which included blanks ("Driver Cache"). omitted .

if the PathName exists. this is the default. whether to a hard disc. to memory. PathName must exist for read access. A new file is created. Returns true ('1') if the user has write permission for that file. so a handle is conceived as opened on a communication channel of some kind. false ('0') if not. We prefer the more specific term. false ('0') if not. end for a) and may be understood as a pointer . which is restricted to disc file I/O. if the PathName exists. Upon open. and returns that handle into a variable which may be used to access the file. or if the file does not exist. or file handle. See the online documentation for details and other options. Examples of the next commands are held to the end. blockSpecial. or. Returns true ('1') if the user has read permission for that file. including ones allowing both read and write (editting) on the same handle. characterSpecial. or socket. Returns a string reporting the type of file as one of file.J. or to another computer. file writable. Williams 2010-09-24 TcL Workshop 41 file readable. because it is more accurate for our scripting coursework. A new file is created. link. to a serial port. append access. If PathName is a directory. Call as file writable PathName. If access_type is omitted. The remaining commands here are used to access the contents of a file. it returns an error. file type. The file is not modified. The documentation is meant to generalize over file I/O and pipe or socket (network) I/O. If the PathName does not exist. The open command assigns a file to a "channel ID". fifo. write access. "file handle". Call as file type PathName. so that they might be shown used together. It should be mentioned that the TcL documentation refers to a "channel ID" where we prefer the term. open returns an error. or if the file does not exist. Call as file readable PathName. open Syntax: open PathName access_type The access_type may be one of: r w a read access. M. the file is not modified and the handle is initialized to the end of the file. directory. or an error is returned. the handle is initialized in the file (beginning for r or w. or. "file handle". it is truncated to 0 length. The rationale is similar to "stream" I/O in C++ programming.

gets id Syntax: gets FileHandle VarName This is the same gets command which we used on the stdin file handle in our first lab. if string was multiline). gets and puts. They are named. When the -nonewline option is used. which must have been opened in a writing mode. whether the string included one or not. There is no defaulted FileHandle for gets. puts does not add a NL to the string. TcL provides three predefined file handles which always are open. to copy the string. The gets command uses FileHandle. . The FileHandle value then is updated to the end of the new line (or lines. and these standard ports therefore can not be redirected. close Syntax: close FileHandle The close command deallocates a file handle ("channel ID") previously allocated to a file. The FileHandle value then is advanced to the next line in the file. so there is no piping between commands within the TcL interpreter. It automatically flushes data. Like a Unix or Linux shell. Williams 2010-09-24 TcL Workshop 42 which is moved automatically by any access command which is used to copy data to or from the file. TcL has no "running process" construct (it is not an operating system). puts id Syntax: puts ?-nonewline? ?FileHandle? string This is the same puts command which we used for screen output in our first lab. into the file at the FileHandle position. both of which are lineoriented and are the same ones we have used for screen or console I/O. including its NL character. which may be stored in a variable. M. and stderr (screen standard error).J. if there was buffered data waiting to be transferred. into the variable named by VarName. which must have been opened in a reading mode. A NL character is added to the end of the string. the handle (channel ID) must be named explicitly in the command. to copy the current line in the file. The puts command uses FileHandle. stdout (screen standard output). We shall study only the two access commands. stdin (console standard input).

Williams 2010-09-24 TcL Workshop 43 If FileHandle is omitted. or. and. none: Immediately flush every transferred string. This is the tclsh default. if you use fconfigure. format must be called on string for '%' specifiers or numerical format conversions. perhaps. On reading. Unix or Linux gets LF. the NL is platformspecific: sockets get CRLF. it modifies that behavior. This does not prevent puts from adding its own NL. If called on anything not a previously opened handle. If there is anything readable remaining. by gets FileHandle. fconfigure Syntax: fconfigure FileHandle ?option1 option1_value? . eof returns an error. The two most commonly useful options and their values are: full: Use the entire system buffer (configurable by the fconfigure -buffersize option). If FileHandle and string are omitted. Most likely. Apple gets CR. otherwise. However. flush for each NL. On writing.. binary: Do not translate or interpret anything. puts "" or puts {}. for example. it returns false ('0'). M. transfer each char in the string literally. eof Syntax: eof FileHandle The eof command returns true ('1') when called on a handle which has been opened for reading and which has no data available to read. If called with an option and value. The fconfigure command reports the current behavior of an open handle. -translation auto: This is the default. -translation binary. An eof can return true normally only if called on a FileHandle which has been read already to its end. CR. Windows gets CRLF. the default is stdout to the screen. Escaped special characters such as '\n' for NL or '\t' for TAB are interpreted by puts accurately. you will use it to effect -buffering none. eof will remain false. . -buffering line: Buffer only incomplete lines.J. puts generates an error.. any NL representation (LF. or CRLF) is recognized as an input line termination. A bare NL may be written to the screen using.

" . puts $Fa $NewLine. } readFile NewFile. return. If a certain file exists. Open a file and read its contents to the screen: proc readFile { Fname } \ {if {[file exists $Fname]==0} \ { puts "No such file: $Fname.txt $Line 2. gets $Fr Line. } close $Fr. puts $Fw $LineIn. create it and write the line into it: proc appendNew { Fname NewLine } \ {set Fa [open $Fname a]. Williams 2010-09-24 TcL Workshop 44 See the online documentation for details and other available fconfigure options. M. } appendNew NewFile.txt "Appended a line here. Examples of file I/O 1. } set Line "This is a \n two-line file. writeLine NewFile. append a line to it. close $Fw.". close $Fa.J. while { ![eof $Fr] } \ { puts "$Line". gets $Fr Line.txt 3.". if it doesn't exist. } # set Fr [open $Fname r]. Create a new file and write a line into it: proc writeLine { Fname LineIn } \ {set Fw [open $Fname w].

} close $Fa. close $Fw. } copyFile NewFile. On a serious error. Williams 2010-09-24 TcL Workshop 45 4. The return just pops the caller off the stack. foreach {f} "$DirList" { puts $Fa [join $f]. or for early finish. M. .J. set Fw [open $NewFname w]. fconfigure $Fw -translation binary. gets $Fr Line. set DirList [lsort [glob -directory $Dir *]].". Reopen the copy just made and append a listing of /bin into it: proc addDirListToFile { Fname Dir} \ { set Fa [open $Fname a]. Open a file and copy it exactly to a new file: proc copyFile { OldFname NewFname } \ {if { [file exists $OldFname] == 0 } \ { puts "No such file: $OldFname.txt NewNewFile. while { ![eof $Fr] } \ { puts $Fw "$Line".txt 5. } close $Fr. fconfigure $Fr -translation binary. return.txt /bin Notice in these examples that return might be invoked by a proc to terminate itself before all commands had been run. use exit to terminate the entire script immediately. } addDirListToFile NewNewFile. # gets $Fr Line. Some sort of error handling has to be included whenever first attempting to open a file for read. } set Fr [open $OldFname r].

M. Don't doubt it: Forgetting happens! And tricky details go first! 4. 5. You may wish to try out these suggestions in the next lab. 3. Write a brief comment for it before starting any proc. Williams 2010-09-24 TcL Workshop 46 Scripting Overview Here are a few suggestions for approaching any script: 1. Decide clearly what you want to do. as you change things. Put runtime last. Start your script file with a comment describing what you have decided. Locate all proc declarations near the start of your script. Understand the problem before trying any TcL. 2. Your comments will help keep you from getting confused when you try to revise or reuse your work later. 6. or adding new ones. Don't be shy of revising your comments. . Collect functional units or repeated operations into TcL proc's. where it can take advantage of any of your declarations.J.

each time printing the returned string. which prints the list obtained from dirList to the screen. one file per line. declare a TcL proc dirList which accepts a directory name as its one argument and returns a string. Your completed script runtime should consist of four lines. Using split will break the string at all blanks! Step 2. preceded by your proc declarations: set some_variable [dirList directory_name1]. set some_variable [dirList directory_name2]. If you try this in Windows. Call dirList on /bin and then on /sbin. When you invoke tclsh. should be assigned near the top of the file. not subdirectories. one file name per line. Verify your new script by running it. Be careful about blanks in file names. Any reasonable script design will work. Step 1. print the number of each file in the list just before its name. . hard-coded into the script. Modify your script of Step 2 to declare a second proc. The directory names. use C:/WinNT/system32 (the usual location of your 32-bit system folder) instead of /bin. where they can be found easily and possibly modified. pipe its output to more if you want to be able to page through the output.J. which might foul the output if you tried this in Windows or on an Apple. In a new script. listPrint. M. listPrint directory_name1 $some_variable. as in the previous step. Williams 2010-09-24 TcL Workshop 47 Lab 2: TcL Programming Do this lab in your Lab02 directory. Write a script which creates a string containing the names of all files in /bin. identifying the directory by name. containing a sorted file list from that directory. Only include names of ordinary files. Starting from 0. Step 3. listPrint directory_name2 $some_variable. but the flowchart here shows a good one. Sort the string and print it to the screen.

In this case. Write a script which collects all names of files in some directory. Write a new script which does the same as in the previous Step but modifies listPrint to accept not a variable's contents but the name of a variable containing the required data. string index. Williams 2010-09-24 TcL Workshop 48 Step 4. set DirName1 [lindex $argv 0]. . In the previous Step. Modify your script of Step 3 so you can pass it invocation arguments. . listPrint DirName VarName. Then. and. another to create the array. and puts them in a TcL array. to obtain the first letter (string index $string 0). Any practical script would include an initial check of the number of input arguments. Additional requirements: To complete this Step 6 lab exercise. (rest of script) . listPrint $DirName1 [dirList $DirName1]. listPrint $DirName2 [dirList $DirName2]. you may write. a third to print the output. but it should call listPrint as. Use the command. If you reuse your dirList() proc. each array value should be a list of all /bin commands beginning with that letter and sorted alphabetically. run the script to obtain the usual output. You may find it useful to check for the correct number of invocation arguments before assigning the directory names from $argv. Each array name should be a letter of the alphabet.. Make changes so that you can invoke tclsh on your script with the two directory_name values as script arguments and obtain the directory names in the script as the first two elements in the $argv list. not as listPrint $DirName $VarName. M. set DirName2 [lindex $argv 1]. Your new script should produce exactly the same output as the one in Step 3 or 4. Step 6. such as /bin. you must use at least three procs of your own: One to collect and sort the initial list...J. Step 5.. be sure to remove any remaining line numbering. listPrint accepted the values in a list as words to print. probably followed in this case by a quick verification of whether they named actual directories.

For example.. For the first time in this Workshop. The glob command and the various list commands also preserve elements by quoting as necessary.J. or parentheses into the array. Your implementation may be any way that works for you. split and some other commands will treat every blank as a word boundary and may confuse some elements. this Step 6 script is of some programming complexity. but below is a reasonable flowchart for the proc which creates your array. If you use array get.ICO HEXVIEW. Notice how the file name. Williams 2010-09-24 TcL Workshop 49 Your script should end by printing the names of all the files. no matter how long.. the strong quotes will be added by the TcL interpreter. it can be useful to express the runtime as a flow chart or state machine diagram. depending on what you are trying to do with them. "Help Workshop. because list elements in an array automatically are quoted. The file names all should be listed on one line.log". However..log}} The example line is taken from a Windows run. M.INI {Help Workshop.. here named makeArray: And that's it: End of the Workshop! Good luck with your TcL scripting! . is preserved intact by strong quotes. last_letter_of_the_alphabet_found { sorted_list_of_file_names }. collected alphabetically in this format: first_letter_of_the_alphabet_found { sorted_list_of_file_names } . one line might be printed as. When the programming is even a little complicated. . H {HELP. to compose the output. which contains a blank.

24 puts.......................................... array.. 13...............................12..........30 elseif...... 8 stderr .......8 TcL.................................30 tk library..........20 upvar ........................ 20.......................13 array get ...............................................12 array elements ............ 28.............................. 20 source (a file) ....................37 string length .....28 semicolon..7 token..... 20...37 string range .................. file I/O ...........................................................15 foreach .. arithmetic...........18.................7. 28 for loop ................35.........34 TcL............ 20 array set....... 11........ plain string.......................25...........................33 default....17 continue .......15.................5 TcL.....................................41 close.....................................33 regexp........................................ 9............................... declaration ... 18..... 20 gets....................41 file type ............... reserved words....... 20 switch ......... blocking................. stack dump....13...................41 flush ......................................8 TcL..7 TcL.................... 20............. 43 eq operator ............11......................... 38 string last.................. polymorphic..........................................24 proc............ return value ......9 string command..................................................................... untyped ..........................32 global variable .....45 expr ....................32 return.... 20 array names .35 split ......... 17.............. Williams 2010-09-24 TcL Workshop 50 Index args........................30 end............ 22............................... 14....10................................... 16.9 tclsh......42 command...........................13.. call .27....7........................43 channel id....................37..10......... returning value ......................43..... vs...................12......................................................................................................10.......30 open ....9 TcL.....38 string trim.................................................. 19.........12 llength ......20 list command... varying arg list .................................... quoting.................................................. in switch..........J.........................................23 array.....................................6 TcL....... 20 linked variable ..............................................7 command words ............. 28...... 21 then ...................................................................................39 glob........28..................... 23 array.............13.......................... 20.................10... 42 glob .........................37 string index ............... types.................................11 list...................24 arithmetic........................................14 break ......................... polymorphism.... 31 TcL (intro).........8 set command .......................... variables.6 token ............. 34 format.....26 proc.................................9..... 20 fconfigure.........................................16.................................. 36 statement .... 20................ 20...................31 else.................................. 49 References..................................41 file writable........ complex........38 string replace.....41 proc ...28 concatenation ...................6 .......11....................................26 while .....................................................8 unset.............23 proc............ 45 file command ............................... 20..........................30 exit ................................. 42 quotes........ legal names ........ 16 lappend ........................4 regexp command..16...................... 29. 20 lindex....... string index index... math operations ..............22 proc... 45 run time.............................. 28 stack frame.................8............................18 TcL...........14 TcL.................... arguments........11 list............38 eof ...................10 stdout ........ arg defaults....6.......6 tkcon ...... 27 if procedure............... 20 list structure ........ 11 compile time ...6 TcL...................... indexing..... in switch .................................................40 file exists......... 14..................................................................................................................12.......26 linsert ..................33 buffer....................12.................... 20 ne operator ..10 stdin ........... M..................15................................................. comment ........ vs.........................................................30 incr ........................................................41 file readable ...24 proc.7 TcL................. 33 for.................. 27 proc names........18 TcL...........37 string first.........................12.10 string .........................................23 array......... 26 inline execution...... global ...25 proc....................11 string commands .......................................35 wish...... quoting..... switch...............................................40 file handle ...

" $Sum $Sum]. gets stdin x3. flush stdout. one at a time:". Simple message: puts "Here I am!". they are stored in variables first: set n3 3. However. gets stdin Ans. puts -nonewline " Fourth number: ". ========================================== # Lab01 Ans 1. for instructional purposes. gets stdin x2. because the default mode for terminal I/O # is buffered: # puts -nonewline "CR to exit: ". puts [format "$n3 + $n5 + $n7 = hex %x or decimal %d. ========================================== # Lab01 Ans 2: Because the numbers will be referenced at least # twice each. ========================================== # Lab01 Ans 4: The -nonewline option keeps the cursor on the last # output line. puts -nonewline " Second number: ". flush stdout. gets stdin x1. all the answers for this course are appended here.Fundamentals Course Lab Answers Because Scribd can not support a single download which includes multiple files. # . gets stdin x4. # # Obtain inputs: # puts " --------------------------------------Please enter four numbers. gets stdin Ans. # set Sum [expr $n3 + $n5 + $n7]. no message will appear until screen # output is flushed. They may be saved to individual files. ========================================== # Lab01 Ans 5_1: This is one of two reasonable answers to #5. flush stdout. set n7 7. # This answer prompts separately for the four numbers: # puts " script=$argv0. set n5 5. puts -nonewline " First number: ". ". puts -nonewline " Third number: ". flush stdout. flush stdout. # ========================================== # Lab01 Ans 3: Simple prompt for input: puts "CR to exit: ".

# # Do calculations: # set Sum [expr $x1 + $x2 + $x3 + $x4]. }. # End of script. set x4 [lindex $AnsList 3]." $Sum $Sum] [format "The product $x1*$x2*$x3*$x4 is %d in decimal or %x in hex. puts "$Msg". set Prod [expr $x1 * $x2 * $x3 * $x4]. flush stdout. set x2 [lindex $AnsList 1].# Do calculations: # set Sum [expr $x1 + $x2 + $x3 + $x4]. puts $Msg. set Prod [expr $x1 * $x2 * $x3 * $x4]. ========================================== # Lab01 Ans 7 Two puts ways shown: # set Msg { Some special characters in TcL are: % $ # @ & [ ] { } ( ) : . # # Report results: # puts " [format "The sum $x1+$x2+$x3+$x4 is %d in decimal or %x in hex. ". " ' and \. set x3 [lindex $AnsList 2]." $Prod $Prod] ". # puts " script=$argv0. ========================================== # Lab01 Ans 8: # A for loop is most compact. gets stdin Ans. ========================================== # Lab01 Ans 5_2: # This is the second of two reasonable answers to #5. but each line could be . " ' and \. ========================================== # Lab01 Ans 6: puts { Some special characters in TcL are: % $ # @ & [ ] { } ( ) : . # End of script." $Sum $Sum] [format "The product $x1*$x2*$x3*$x4 is %d in decimal or %x in hex. # set AnsList [split $Ans]." $Prod $Prod] ". }. # This answer prompts for all four numbers in # one input and uses TcL list procedures to disentangle # the numbers entered. # set x1 [lindex $AnsList 0]. # # Obtain inputs: # puts -nonewline " --------------------------------------Please enter four numbers separated by blanks: ". # # Report results: # puts " [format "The sum $x1+$x2+$x3+$x4 is %d in decimal or %x in hex.

puts "Split CharList=\[$CharList\]. set DirName "C:/WinNT/system32".} {$i<[llength $CharList]} {set i [expr $i+1]. ========================================== This ends Lab01." $i $Char]. # Sort the string in ASCII code order and print it to the # screen. } \ { puts [format "File %04d: %s" $i [lindex $FileList $i] ]. # Prevent all tokens for llength: set CharList [split $CharList]. . The Lab02 answers follow: ========================================== # # Lab02 Step01: # Write a script which creates a string containing the names # of all files in /bin." } # set DirName "/bin". they are # accessed by using TcL list procedures: # set CharList "\% \$ \# \@ \& \[ \] \{ \} \( \) \: \. use # C:/WinNT/system32 (the usual location of your 32-bit system # folder) instead of /bin. declare a TcL proc dirList() which accepts # a directory name as its one argument and returns a string. # # End script. # # Print one name per line: puts "Begin $Dir file listing:" for {set i 0. containing a sorted file list # from that directory: # # Assuming Linux: # set DirName1 "/bin". \" \' \\".} {$i < [llength $FileList]} {set i [expr $i+1]. } puts "". puts [format " char %02d=\[%s\]. printFiles $DirName.} \ { set Char [lindex $CharList $i]. ========================================== # # Lab02 Step02: # In this Step. # puts " Some TcL special characters are \[$CharList\] ". # set DirName2 "/sbin". If you try this in Windows. one file name per line: # proc printFiles { Dir } \ { set FileList [glob -types f -tails -directory $Dir *]. # After storing the characters in a variable. set FileList [lsort $FileList]. # as in the previous step.# printed explicitly (unrolled).\n" # puts "The individual characters are:" for {set i 0. } puts "End of $Dir file listing.

# Assuming Windows: set DirName1 "C:/WinNT". set Max [llength $FileList]. set DirName2 "C:/WinNT/system32". set FileList [lsort $FileList]." # # End script. # # Print one name per line (format adds the NL's): for {set i 0. } \ { append FileListLines \ [format "File %04d: %s\n" $i [lindex $FileList $i] ]. } # # Runtime: # set OutVar [dirList $DirName1]. } # return $FileListLines. use a new proc to print # the output. set DirName1 "C:/WinNT". # set DirName2 "/sbin". ========================================== # # Lab02 Step03: # In this Step.} {$i < $Max} {set i [expr $i+1]. containing a sorted file list # from that directory. } # . # as in the previous step. # # ------------------------------------------------------------------------------------------# dirList() returns the enumerated. set DirName2 "C:/WinNT/system32". declare a TcL proc dirList() which accepts # a directory name as its one argument and returns a string. set Max [llength $FileList]. puts "\n\nBegin $DirName2 file listing:" puts "$OutVar". puts "\n\nBegin $DirName1 file listing:" puts "$OutVar". puts "End of $DirName2 file listing. 1-lined list # of file names in the directory named: # ------------------------------------------------------------------------------------------proc dirList { Dir } \ { set FileList [glob -types f -tails -directory $Dir *]. # proc dirList { Dir } \ { set FileList [glob -types f -tails -directory $Dir *]. # # Print one name per line (format adds the NL's): for {set i 0. # # set DirName1 "/bin". # Different from the previous Step. set FileList [lsort $FileList]." # set OutVar [dirList $DirName2].} {$i < $Max} {set i [expr $i+1]. } \ { append FileListLines \ [format "File %04d: %s\n" $i [lindex $FileList $i] ]. puts "End of $DirName1 file listing.

set DirName2 [lindex $argv 1]. # # End script." } # # Runtime: # set OutVar [dirList $DirName1]. ========================================== # # Lab02 Step04: # In this Step. } \ { append FileListLines \ [format "File %04d: %s\n" $i [lindex $FileList $i] ]. } return $FileListLines. set Max [llength $FileList].return $FileListLines. } # # ------------------------------------------------------------------------------------------# listPrint() prints the dirList() list to the screen. declare a TcL proc dirList() and # another one. # # Print one name per line (format adds the NL's): for {set i 0. Please call as: $argv0 dirpathname1 dirpathname2 ". set FileList [lsort $FileList]. # if { $argc < 2 } \ { puts " Invocation error. listPrint $DirName1 $OutVar. listPrint $DirName2 $OutVar. to do the main processing. call the script with invocation arguments to # supply the directory names. # # ------------------------------------------------------------------------------------------# dirList() returns the enumerated. 1-lined list # of file names in the directory named: # ------------------------------------------------------------------------------------------proc dirList { Dir } \ { set FileList [glob -types f -tails -directory $Dir *]. set OutVar [dirList $DirName2]. } set DirName1 [lindex $argv 0]. puts "End of $Dir file listing. } # # ------------------------------------------------------------------------------------------# listPrint() prints the dirList() list to the screen. # ------------------------------------------------------------------------------------------proc listPrint { Dir List } \ { puts "\n\nBegin $Dir file listing:" puts "$List". listPrint(). # As in previous steps.} {$i < $Max} {set i [expr $i+1]. # ------------------------------------------------------------------------------------------proc listPrint { Dir List } \ . exit.

to do the main processing. upvar $List List_L. } # # ------------------------------------------------------------------------------------------# listPrint() prints the dirList() list to the screen. call the script with invocation arguments to # supply the directory names. # # End script. } return $FileListLines. listPrint(). 1-lined list # of file names in the directory named: # ------------------------------------------------------------------------------------------proc dirList { Dir } \ { set FileList [glob -types f -tails -directory $Dir *]. in this Step. exit. set FileList [lsort $FileList]. listPrint $DirName2 [dirList $DirName2].{ puts "\n\nBegin $Dir file listing:" puts "$List". # puts "\n\nBegin $Dir_L file listing:" . declare a TcL proc dirList() and # another one. # As in previous steps. # # ------------------------------------------------------------------------------------------# dirList() returns the enumerated. set Max [llength $FileList]. listPrint parameters are passed # by reference. # However. # # Print one name per line (format adds the NL's): for {set i 0. set DirName2 [lindex $argv 1].} {$i < $Max} {set i [expr $i+1]. ========================================== # # Lab02 Step05: # In this Step. # Variables named *_L are local references to passed # real parameters." } # # Runtime: # listPrint $DirName1 [dirList $DirName1]. # ------------------------------------------------------------------------------------------proc listPrint { Dir List } \ { upvar $Dir Dir_L. Please call as: $argv0 dirpathname1 dirpathname2 ". } \ { append FileListLines \ [format "File %04d: %s\n" $i [lindex $FileList $i] ]. not by value: # if { $argc < 2 } \ { puts " Invocation error. } set DirName1 [lindex $argv 0]. puts "End of $Dir file listing.

puts "End of $Dir_L file listing. . set Flist2 [dirList $DirName2]. exit -2. # -------------------------------------------------proc checkInvoke { ArgV0 ArgV } \ { if { [expr [llength $ArgV] != 1] } \ { puts " Invocation error. } # if { ![file isdirectory $ArgV] } \ { puts " Invocation error." } # # Runtime: # set Flist1 [dirList $DirName1]. we change the format of the data storage # from that of a string or list to that of an array. # # End script. Please call as: $ArgV0 dirpathname ". $ArgV must be a directory path. set Max [llength $FileList]. # Must call as checkInvoke $argv0 $argv on any call. # Call makeArray() to convert the list to an array. 1-lined list # of sorted file names in the directory passed: # -------------------------------------------------proc dirList { Dir } \ { set FileList [glob -nocomplain -types f -tails -directory $Dir *]. # listPrint DirName1 Flist1. # # Design: # Call dirList() to return a sorted list. exit -1. # ########################################################### # Procedure declarations: ########################################################### # -------------------------------------------------# checkInvoke() Verifies that a word has been supplied # when the script is invoked. listPrint DirName2 Flist2. ========================================== # ======================================================= # Lab02 Step06 (first approach): # In this Step.puts "$List_L". } } # # -------------------------------------------------# dirList() returns the enumerated. ". # Call arrayPrint() to print the result.

# Or. if any: set FnameList [array get FileArrayL $CurChar1]. # Add this name: lappend FnameList $CurFname. # The list already has been sorted by ASCII code. # puts " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ $Dir_L contains: ". } # return FileArray. } # # -------------------------------------------------# makeArray() accepts the dirList() list and uses it # to create the array to be returned. set OutputLine "$Letter {$Array_L($Letter)}".# # Print one name per line (format adds the NL's): set FileListLines {}. # for {set i 0. upvar $Farray Array_L. # Prevent empty-dir error. # -------------------------------------------------proc arrayPrint { Dir Farray } \ { upvar $Dir Dir_L. # set FileList [lsort [array names Array_L]]. } # # -------------------------------------------------# arrayPrint() prints the dirList() array to the screen.} {$i < $Max} {set i [expr $i+1]. # foreach { Letter } "$FileList" \ { set OutputLine [array get Array_L $Letter]. . # -------------------------------------------------proc makeArray { FListVarName ArrayVarName } \ { upvar $FListVarName FlistL. # Put the augmented list of names into the array: array set FileArrayL [list $CurChar1 $FnameList]. # Get its first char: set CurChar1 [string index $CurFname 0]. # Variables named *_L are local references to passed # real parameters. } return $FileListLines. # Get the previous name list. # Remove the array name string: set FnameList [lindex $FnameList 1]. # foreach { ListElement } "$FlistL" \ { # Get the file name: set CurFname [string trim [join "$ListElement"]]. } \ { lappend FileListLines [lindex $FileList $i]. upvar $ArrayVarName FileArrayL.

} puts " End of $Dir_L file listing. Please call as: $ArgV0 dirpathname ". # presumed to be a valid directory path: checkInvoke $argv0 $argv. # # Init empty array: array set Farray [list]. # # Fill the array: makeArray Flist Farray. # set DirName [lindex $argv 0].puts " $OutputLine". # # Design: # Call dirList() to return a sorted list. # Must call as checkInvoke $argv0 $argv on any call. # Call makeArray() to convert the list to an array. ========================================== # # Lab02 Step06 (alternative approach): # In this Step. } # if { ![file isdirectory $ArgV] } \ . # # Return the list: set Flist [dirList $DirName]. # # End script. # Call arrayPrint() to print the result. # -------------------------------------------------proc checkInvoke { ArgV0 ArgV } \ { if { [expr [llength $ArgV] != 1] } \ { puts " Invocation error. " } # ########################################################### # Runtime: ########################################################### # # Verify a word on the script invocation line. exit -1. we change the format of the data storage # from that of a string or list to that of an array. # # Print the array: arrayPrint DirName Farray. # ########################################################### # Procedure declarations: ########################################################### # -------------------------------------------------# checkInvoke() Verifies that a word has been supplied # when the script is invoked.

array set FileArray [list "$FileL1" "$LnameList"]. }\ else { lappend LnameList $CurLname. # foreach { ListElement } "$Flist" \ { set CurLname [string trim [join "$ListElement"]]. # set Flist [lsort $Flist].{ puts " Invocation error. # Or. # The list is already sorted by ASCII code. # # Each array element name $FileL1 is the first letter # in the file name. set FileL1 $CurL1. # # Print one name per line (format adds the NL's): for {set i 0.} {$i < $Max} {set i [expr $i+1]. # Reinit it. upvar $ArrayVarName FileArray. } # if {$CurType eq "New"} \ { set FileArray($FileL1) $LnameList. # Increment the name. } \ { lappend FileListLines [lindex $FileList $i]. # set FileL1 { }. set CurL1 [string index $CurLname 0]. and each array element value # $LnameList is a list of file names beginning with # $FileL1. } # # -------------------------------------------------# makeArray() accepts the dirList() list and uses it # to create the array to be returned. $ArgV must be a directory path. set Max [llength $FileList]. ". } return $FileListLines. set LnameList [list]. # Init with empty list. # Init with a blank (very low ASCII code). 1-lined list # of sorted file names in the directory passed: # -------------------------------------------------proc dirList { Dir } \ { set FileList [glob -types f -tails -directory $Dir *]. exit -2. } } # # -------------------------------------------------# dirList() returns the enumerated. if {$FileL1 eq $CurL1} \ { set CurType "Same". # -------------------------------------------------proc makeArray { FListVarName ArrayVarName } \ { upvar $FListVarName Flist. set LnameList [list $CurLname]. } } . # The iterator requires a sorted list. } \ else { set CurType "New".

set OutputLine "$Letter {$Array_L($Letter)}". # set FileList [lsort [array names Array_L]].# # Add last element: set FileArray($CurL1) $LnameList. # # Get rid of the initializing empty name: array unset FileArray { }. # set DirName [lindex $argv 0]. upvar $Farray Array_L. # # Fill the array: makeArray Flist Farray. } # # -------------------------------------------------# arrayPrint() prints the dirList() array to the screen. # puts " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ $Dir_L contains: ". " } # ########################################################### # Runtime: ########################################################### # # Verify a word on the script invocation line. } puts " End of $Dir_L file listing. # presumed to be a valid directory path: checkInvoke $argv0 $argv. # return FileArray. puts " $OutputLine". # -------------------------------------------------proc arrayPrint { Dir Farray } \ { upvar $Dir Dir_L. # # Print the array: arrayPrint DirName Farray. # Variables named *_L are local references to passed # real parameters. # # Init empty array: array set Farray [list]. . # Or. # foreach { Letter } "$FileList" \ { set OutputLine [array get Array_L $Letter]. # # Return the list: set Flist [dirList $DirName].

. # # This ends the answers for the Basic course.# # End script.

You're Reading a Free Preview

Download
scribd
/*********** DO NOT ALTER ANYTHING BELOW THIS LINE ! ************/ var s_code=s.t();if(s_code)document.write(s_code)//-->