If you have big scripts and many procs which will call each other and you don`t know really which proc got called by another one you can use this.
Code: Select all
# strace (original by Elven http://tclhelp.net/forum/viewtopic.php?t=96)
# usage:
# putlog [strace]
proc strace { {args ""} } {
if { [info level] == 1 } {
return "strace: got called directly by the interpreter (e.g.: .tcl on the partyline)."
}
set ret {}
set r [catch {expr [info level] - 1} l]
if {$r} { return {""} }
while {$l > -1} {
incr l -1
lappend ret [info level $l]
}
set ret [lremove $ret [lindex $ret [expr [llength $ret] - 2]]]
set last [lrange $ret end end]
set ret [lreplace $ret end end]
eval lappend last $ret
set while_protection 0
while { [llength $last] != 0 } {
set x [lindex $last end]
set last [lremove $last $x]
if { $x == "" } {
break
}
set x [lindex [split $x] 0]
lappend newlist $x
incr while_protection
if { $while_protection > 100 } {
putlog "strace: breaking loop, to many executions (>100)."
break
}
}
set newlist [join [split $newlist] " --> "]
return $newlist
}
Examaple for what this proc can be used for:
Code: Select all
proc test_a args { test_b 2 2 2 }
proc test_b args { test_c 3 3 3 }
proc test_c args { test_d 4 4 4 }
proc test_d args { test_e 5 5 5 }
proc test_e args { putlog "procname: test_e: strace: [strace]" }
type: .tcl test_e
This will show you which proc got called first, which second, etc...
--
Tcl error: invalid command name "s"
Yeah nice :/ You have many procs and don`t know which script cause this error... How can you find more fast? (
http://www.tcl.tk/man/tcl8.5/TclCmd/unknown.htm)
Code: Select all
if { [info command unknown_new] == "" } {
rename unknown unknown_new
}
proc unknown { args } {
set command [join [lrange [split $args] 0 0]]
set arg [join [lrange [split $args] 1 end]]
putlog "WARNING: unknown command: $command (arguments: $arg) | Lastbind: $::lastbind"
uplevel #1 [list unknown_new $args]
}
Another nice tcl feature is the errorInfo varibale. I wonder that so less people know it.
Code: Select all
bind dcc n|- e dcc:errorinfo
proc dcc:errorinfo { handle idx text } {
putlog $::lastbind
putlog $::errorInfo
}
This will show a multi line traceback to the last error. If you read this you will know what you have to do to prevent this error.
The ugly point is, errorInfo shows always the last error. So, if you use catch and a error has been caused it will show that error last, so be fast
.
thom\mey showed me a nice way to handle that.
Code: Select all
trace add variable ::errorInfo write logerr
proc logerr { args } {
if { [set utm [utimerexists errorlog]] != "" } { return }
utimer 1 errorlog
}
proc errorlog { } {
set fs [open errorlog.txt a]
regsub -all -- {\n|\s+} $::errorInfo { } error
putlog $::errorInfo
puts $fs "\n"
puts $fs "[clock format [clock seconds] -format "%d/%m/%y@%H:%M.%S>"] : $::errorInfo"
close $fs
}
Well, in some case this will create a big error errorlog.txt. I don`t know... Do you want this? But the putlog works nice for me.