proc stepping name {
trace add exec $name enterstep enterStep
trace add exec $name leavestep leaveStep
}
proc noStepping name {
trace remove exec $name enterstep enterStep
trace remove exec $name leavestep leaveStep
}
proc enterStep {cmd _} {uplevel 1 [list bp "before $cmd"]}
proc leaveStep {cmd code result _} {
uplevel 1 [list bp "result ($code):$result<=$cmd"]
}Reusable breakpoint handler from A minimal debuggerproc bp s {
if {[string length $s]>50} {set s [string range $s 0 49]...}
while 1 {
puts -nonewline "$s > "
flush stdout
gets stdin line
if {$line==""} break
catch {uplevel 1 $line} res
puts $res
}
}Testing...if {[file tail [info script]] == [file tail $argv0]} {
proc foo x {
puts "This is foo"
set i 0
while {$i < $x} {
puts "i=$i"
incr i
}
#kaboodle
puts "That was foo"
}
stepping foo
foo 3
}Sample session:before puts {This is foo} >
This is foo
result (0):<=puts {This is foo} >
result (0):<=set i 0 >
before set i 0 >
result (0):0<=set i 0 >
result (0):<=while {$i < $x} {
puts "i... >
before while {$i < $x} {
puts "i=$i"
... >
result (0):<=puts i=0 > info locals
x i
result (0):<=puts i=0 > set x
3
result (0):<=puts i=0 >
before puts i=0 >
i=0
result (0):<=puts i=0 >
result (0):<=incr i >
before incr i >
result (0):1<=incr i >
result (0):<=puts i=1 >
before puts i=1 >
i=1
result (0):<=puts i=1 >
result (0):<=incr i >
before incr i >
result (0):2<=incr i >
result (0):<=puts i=2 >
before puts i=2 > info pa
8.4.1
before puts i=2 >
i=2
result (0):<=puts i=2 >
result (0):<=incr i >
before incr i >
result (0):3<=incr i >
result (0):<=while {$i < $x} {
puts "i... >
result (0):<=puts {That was foo} >
before puts {That was foo} >
That was foo
result (0):<=puts {That was foo} > The early leavestep is indeed a bug, registered at SF (655645). Until it gets fixed, here is a workaround that uses a global variable to suppress calls to leaveStep before the matching enterStep was called:
proc stepping name {
trace add exec $name enterstep enterStep
trace add exec $name leavestep leaveStep
if {![info exists ::Entered]} {set ::Entered ""} ;# Workaround
}
proc enterStep {cmd _} {
set ::Entered $cmd ;# Workaround
uplevel 1 [list bp "before $cmd"]
}
proc leaveStep {cmd code result _} {
if {$cmd eq $::Entered} { ;# Workaround
uplevel 1 [list bp "result ($code):$result<=$cmd"]
}
}AM I have used the above technique to create A basic debugger that works under tclsh and wish, even under Windows.RS A more recent take is under Steppin' out again.

