proc bp {{s {}}} {
if ![info exists ::bp_skip] {
set ::bp_skip [list]
} elseif {[lsearch -exact $::bp_skip $s]>=0} return
if [catch {info level -1} who] {set who ::}
while 1 {
puts -nonewline "$who/$s> "; flush stdout
gets stdin line
if {$line=="c"} {puts "continuing.."; break}
if {$line=="i"} {set line "info locals"}
catch {uplevel 1 $line} res
puts $res
}
}The idea is that you insert breakpoints, calls to bp, in critical code with an optional string argument (that may be used for distinguishing), like this: proc foo {args} {
set x 1
bp 1
string toupper $args
}
foo bar and grillWhen execution reaches bp, you get a prompt on stdout, giving the calling context and the bp string, like this:foo bar and grill/1> pwd /home/suchenwi/src/roi/test/mr foo bar and grill/1> i args x foo bar and grill/1> set args bar and grill foo bar and grill/1> set args lowercase lowercase foo bar and grill/1> con which you can issue any Tcl command (especially getting or setting variable values in the scope of foo), shorthand commands ("i" for "info locals"; add which others you need), and exit this micro-debugger with "c"(ontinue). Because you modified a local variable, foo's result will be
LOWERCASETo turn off all breakpoints for an application, just say (maybe from inside bp):
proc bp args {}You can disable single breakpoints labeled e.g. x with the commandlappend ::bp_skip xStepping is made easy with the new execution traces from 8.4 - see Steppin' out, but in some situations a micro-debugger like this is good enough. See also debugging
Bits and pieces.. Here's a minimal variable watcher, that logs every change to the specified variables to stdout:
proc watch {args} {
foreach arg $args {
uplevel 1 "trace var $arg w {puts $arg:\[set $arg\] ;#}"
}
}[Incidental remark: Expect builds in lots of interesting debugging capabilities.]
Tkcon has a couple of debugging features like those described above. idebug is like bp above but with a few more bells and whistles, and observe is like watch above. [kpv]
AM It is very easy to extend this minimal debugger to become a mini debugger. To keep the intrusion as small as possible, just handle all debugging commands that you want to implement in a switch statement (rather than the cascading "if") for readability. This way you introduce but a single new command, bp, instead of a handful (but it may be useful to define a few, like watch, as a procedure, so that you can log the variables automatically.One problem remains (one that I would like to solve or see solved!): how to get this to work under Windows - perhaps a solution via a pipe? The reason I am concerned is that I use (want to use) Tcl in an "embedded" mode. I can not use Tk in there, so a solution via Tkcon or console show becomes difficult... - RS: What is the problem? The little one above works only with stdin and stdout, no Tk required; and I've made good use of it debugging our app where a Tcl interpreter is embedded.
See also An error experiment with an even minimaller debugger...

