Hai’s Blog

April 23, 2009

Debugging Tcl script with puts

Filed under: Programming, Tcl — Hai @ 8:40 pm

Using puts is the one of the oldest, yet effective debugging technique. For example:

puts "before calling myproc"
puts "myvar = $myvar"
myproc myvar
puts "after calling myproc"
puts "myvar = $myvar"

This technique is good, but it has at least two problems:

  1. To turn off debugging output, I either have to delete or comment out tens if not hundreds of puts lines like those above. To turn them back on, I have to reverse the process for that many lines.
  2. This is not a problem, but I found myself using puts to display value of a variable quite often, therefore it would be nice if I can streamline that process

To answer both questions, I created the following code snippet which I paste at the beginning of my script:

# Output debug only when the user set the environment variable
# DEBUG=1. In Bash:
#     $ export DEBUG=1
# In csh and tclsh:
#     # setenv DEBUG 1
if {[info exists env(DEBUG)] && $env(DEBUG)} {
    proc dbg {msg} { puts $msg }
    proc dbgVar {varName} {
        upvar 1 $varName varValue
        dbg "$varName = '$varValue'"
    }
} else {
    proc dbg {msg} {}
    proc dbgVar {varName} {}
}

Now, the original block of code would become:

dbg "before calling myproc"
dbg "myvar = $myvar"
myproc myvar; # Now call myproc, which modifies myvar
dbg "after calling myproc"
dbgVar myvar

Here is the instruction for turning debuggin on or off:

	$ export DEBUG=1 # Debug on  for sh and bash
	$ unset DEBUG    # Debug off for sh and bash

	# setenv DEBUG 1 # Debug on  for csh and tcsh
	# unsetenv DEBUG # Debug off for csh and tcsh

Now, I don’t have to go over my code to comment or uncomment lines after lines of code to turn on/off debugging output. I also have at my disposal a simple way to display the value of a variable. Life is good.

In the future, I will probably put this snippet into a package to further streamline the process.

Boolean logic in Tcl

Filed under: Programming, Tcl — Hai @ 8:04 pm

Many people who write Tcl script get confused when it comes to boolean logic, especially within if, while construct. To clear up some of these confusions, let’s take a look at the following interactive session:

	(tcl) 66 % # What is true?
	(tcl) 66 % set var -1
	-1
	(tcl) 67 % string is true $var
	0
	(tcl) 68 % # So, -1 is not considered a token for true. Let see now:
	(tcl) 68 % if {$var} {puts "$var is true"}
	-1 is true
	(tcl) 69 % # It seems the expression in the if statement only care if var is zero or not
	(tcl) 69 % # Try a couple of other tokens:
	(tcl) 69 % string is true yes
	1
	(tcl) 70 % string is true no
	0
	(tcl) 71 % string is false no
	1
	(tcl) 72 % # So yes=true, no=false, so far so good
	(tcl) 72 % set var yes
	yes
	(tcl) 73 % if {$var} {puts "$var is true"}
	yes is true
	(tcl) 74 % set var neither
	neither
	(tcl) 75 % if {$var} {puts "$var is true"}
	expected boolean value but got "neither"
	(tcl) 76 % # Now that is the behavior I expected
	(tcl) 76 % set var no
	no
	(tcl) 77 % if {!$var} {puts "$var is false"}
	no is false
	(tcl) 78 % # Worked as expected
	(tcl) 78 %

Normally, Tcl defines true as 1 and false as 0, but as line 68 shows, Tcl considers any non-zero numerical value as true, not just 1.

Lines 69-77: Tcl’s boolean vocabulary also extends to other tokens such as true/false, y/n, yes/no, and on/off. These tokens are case insensitive, which means Yes, yes, and YES are the same.

Line 74-75: If Tcl does not understand a token, it will flag as an error.

Here are the summary points:

  1. For numeric values 0=false and non-zero=true
  2. For non numeric values, Tcl understands true/false, yes/no, y/n, and on/off. The language might understand more tokens than that, but those are the ones I tested.
  3. Anything other than 1 and 2 will raise an error

Blog at WordPress.com.