Pages

Thursday, August 30, 2012

TCL tips !!


1 Always specify level value for uplevel command.
2 Always specify level value for upvar command.
The uplevel and upvar commands are used to evaluate scripts and link to variables (that is, pass by
reference) in another scope in the call stack. Both commands take an optional level argument, which
can be used to indicate the location in the stack.

1 Use “--” to mark end of $command options.
Tcl commands that take an arbitrary number of hyphenated options before other arguments typically
also accept an optional -- argument indicating the end of the options and the start of other arguments.
These include switch, regexp, and regsub commands.

Commands end with newline or semicolon: \n or ;
In most cases, don’t put more than one command
on a line!
Continuation character is backslash: \
Indent lines that are continued; 4 spaces are recommended
Comment the following string(s) with the pound sign: #

“Glob” special symbols or patterns for matching include:
* 0 or more of any sequence of characters
? any single character
[abc] or [a-c] any one of the characters a, b, or c
{a,b,c} any of the patterns a, b, or c
\x matches the character x

argv—list of arguments passed to interpreter.
puts $argv
argc—argument count.
argv0—name of the script or program that starts the interpreter.

Strings, Lists, Arrays, and Keyed Lists—The Tcl interpreter supports several mechanisms for
storing and retrieving variable data. Each method provides a different way of viewing the contents
of a string and supports its own list of commands for accessing the string. The access methods for
string data include:
String—A string of characters including ascii and special characters. String manipulation
commands allow you to work with blocks of characters (strings) within a string.
List—A space or quote delimited string of words, numbers, or special characters. The list
manipulation commands let you manipulate and query individual elements within the list.
Array—Stores multiple values accessible through a unique index. Arrays provide quick access
to individual string elements.
Keyed List—The Tcl equivalent of a C “struct.” Keyed lists support the definition of complex
data structures that stores a hierarchical view of string data.

lsearch ?mode? Return the element offset of within . Returns ‘-1’
if matches no element within . The optional mode can take the following values:
If unspecified, the default mode is -glob.
Let’s look at some examples:
expect4.1> lsearch {zero one two three four} two
2
expect4.2> lsearch {zero one two three four} tw*
2
expect4.3> lsearch -exact {zero one two three four} tw*
-1
expect4.4>

Array Operations
Arrays—Arrays allow you to group multiple strings together in a single variable that makes it easy
to identify all strings of a particular type or class. You specify an array by providing a variable name
followed by an index enclosed in parentheses (). You can use any symbolic name for the index, but
in many cases you’ll find it useful to use numeric values.
Let’s see some examples:
expect4.1> set my_array(1) value
value
expect4.2> puts $my_array(1)
value
expect4.3> set my_array(index) {another value}
another value
expect4.4> puts $my_array(index)
another value
expect4.5>
Note that since the index string can contain just about any characters, you can easily simulate
multidimensional arrays as in the following example:
for {set i1 0} {$i1 < 10} {incr i1} {
for {set i2 0} {$i2 < 10} {incr i2} {
set array_variable($i1,$i2) "$i1$i2"
}
}
puts $array_variable(3,3)

Keyed List Operations
Keyed lists use a specific format of a nested list to simulate Cstyle structs.
Each “element” is a ‘key/value’ pair, essentially a 2-element list.
Key/value pairs are called “fields”.
keylset ? …?
Set list elements.
keyldel
Delete a keyed list element.
keylget ?? ? | { }?
Get a keyed list element.
keylkeys ??
List the keys in a keyed list.

break and continue are used for control of while, for, and foreach loops.
Example break statement:
while 1{
if 1 break ;# terminate innermost
}
Example continue statement:
foreach var [info commands] {
if {![string match {p*} $var]} {
continue ;# go to top of loop
}
puts $var
}

catch is used to change the actions produced by errors
Example:
if {[catch {set foobar} errmsg]} {
puts “the message output: $errmsg”
}
May take up to two arguments:
A command block to execute.
An optional variable to store error messages within.
Returns:
1 if an error has been caught.
0 otherwise.

The argument can take any of the following values:
Note that you can’t write to a file opened for reading and can’t read a file opened for writing. The
default is “r” for read access.
r Open for reading; file must already exist. This is the default.
r+ Open for reading and writing; file must already exist. It is truncated if written to.
w Open for writing; file is truncated if it exists, otherwise it is created.
w+ Open for reading and writing; file is truncated if it exists, otherwise it is created.
a Open for writing; data appended to end of the file; file is created if it does not exist.
a+ Open for reading and writing; data appended to end of the file; file is created if it does not exist.

Procedure Definition—Tcl procedures are defined through the use of the proc command. This
command accepts three arguments: the procedure name, an argument list, and the body of the
procedure. The argument list names the variables that will be set with the arguments passed during
procedure invocation. This list defines the number of arguments expected by the procedure and the
names by which the procedure will refer to the argument data. The body of the procedure specifies
the Tcl code that implements the procedure.

A procedure can return a value by using the
return command:
return 1 or return $value
If there is no return command, the procedure will
return the value returned by the last command executed in the body.

Passing Arguments by Reference
When arguments are passed by reference, changes to a variable modify the caller’s name space.
Syntax of the upvar command:
upvar ??
By default, is the caller’s stack level, “1”.
upvar [n] ... References the level stacks down
upvar [#n] ... References level ; the global level is #0
Example:
proc myset {varname} {
upvar $varname localvar; set localvar 2
}
set foo 1
myset foo
puts $foo ;# prints 2

Passing Arguments by Reference
Most programming language implement one of two methods for passing argument data: passing by
reference or passing by value. The FORTRAN language passes argument to routines by reference.
This means that rather than passing the contents of a variable, a pointer to the variable is passed to
the routine. If the routine modifies the variable then the contents of the variable in the caller’s name
space is modified.
The Tcl language, like the C language in which it is implemented, passes arguments by value. This
means that rather than passing a pointer to the variable, a copy of the variable’s contents is made in
the procedures namespace. No modifications made to the variable within the body of the procedure
will affect the contents of the variable in the caller’s namespace. This allows you to implement
procedures like the following:
# Print "Hello World" a specified number of times
proc print_hello {count} {
for {} {$count > 0} {incr count -1} {
puts "Hello World"
}
}
set var 2
print_hello $var
# prints Hello World
puts $var
# prints 2

Tcl allows you to pass arguments by reference through the use of the upvar command. The format
of the upvar command is as follows:
upvar ?? ? ...?
The is the name of the variable outside the local scope while is the variable
name that will be used to refer to that variable locally. can be a variable, an array, or an
array element.
Note You will need to use passing by reference to pass array information to a procedure. Array
values can not be passed as procedure arguments. Keyed lists should also be passed by reference.
For example:
# Set a variable in the caller's scope
proc myset {varname} {
upvar 1 $varname localvar
set localvar 2
}
expect4.2> info exists myvar
0
expect4.3> myset myvar
2
expect4.4> info exists myvar
1
expect4.5> puts $myvar
2
Notice that rather than passing the contents of variable “myvar” to “myset”, the name of the variable
is passed. The “myset” procedure then uses the upvar command to map a local variable name,
localvar, to myvar in the callers stack.
The option allows you to specify the level at which the variable exists that you are
referencing. By default, upvar references the callers stack level. You can modify the referenced
levels using two formats:
You’ll typically allow the to default to “1”. The following example produces similar effects
to the global command:
upvar #0 global_var myvar
This maps the local variable “myvar” to the variable “global_var” at global level.
Essentially, upvar aliases a variable in a different scope to a local variable.
Note It’s recommended that you always specify the level, as it can run into problems if the variable
name begins with a digit or # sign. It’s also recommended to use the same variable names for
otherVar and myVar, except that otherVar has underscore before it. This makes it easier to associate
the two variables

Using the “uplevel” command
The uplevel command is used to execute code outside
the scope of a procedure.
Syntax:
uplevel ?? \
?? ...
By default, is the caller’s stack level, “1”.
uplevel [n] ... References the level stacks down
uplevel [#n] ... References level
Returns the result of executing the command.
Examples:
uplevel info vars
uplevel #0 info vars
– Results in an error when executed at the command prompt.

Using the “uplevel” Command
Executing Code Outside Your Scope—The uplevel command can be used to execute code outside
the scope of a procedure. This command accepts a variable number of arguments: an optional level
at which to execute the code and the command to execute with its arguments. uplevel returns the
result from executing the command. For example:
# Show the variable in the caller's stack
uplevel info vars
# Show the variables at global level
uplevel #0 info vars
The “test_config” procedure used to organize test scripts uses the uplevel command to remove its
own stack level as in:
proc test_config {args} {
uplevel eval $args
}

No comments:

Post a Comment