In most shells (sh, csh, tcsh, bash) I can add -vx to the options
and swee what the commands being executed are, and what happens
after expansion. This activity of expansion and substitution is
fundamental to getting Tcl code correct. Is there a way to get
tclsh to do this (manual page suggests No -- tclsh takes no options)
or is there a tcl wrapper that does this using tcl to execute the
input it has processed and displayed?
I'm imagining something line [rough charcoal sketch, pseudocode really]:
# open the supplied tcl file
set infile [open [lindex $argv 0]]
while { not [file eof $infile]} {
# Read a line
set command [read $infile]
# keep reading till we have a complete command
while { not [ info complete $command] ) {
set command "$command\n[read $infile]"
}
# display the command
puts $command
# display what it is like substituted.
set scommand [subst command]
puts $scommand
# do the subst and execution in one.
eval $command
}
But that won't do the recursive expansions of [...] so you can see what
they are. So what should I be looking for? I've not used Tcl for a
while (as you can tell from my pseudocode :-)) and would find a tool
of that sort useful.
Thank you,
Hugh
Sounds like an execution enterstep trace to me. Consider the third
example at http://www.tcl.tk/man/tcl8.5/TclCmd/trace.htm#M30 and
whether that can be adapted to give you the info that you want.
Donal.
> Hugh Sasse wrote:
> > In most shells (sh, csh, tcsh, bash) I can add -vx to the options
> > and swee what the commands being executed are, and what happens
> > after expansion. This activity of expansion and substitution is
> > fundamental to getting Tcl code correct. Is there a way to get
[...]
>
> Sounds like an execution enterstep trace to me. Consider the third
> example at http://www.tcl.tk/man/tcl8.5/TclCmd/trace.htm#M30 and
> whether that can be adapted to give you the info that you want.
>
> Donal.
>
That's got me much nearer I think. The bit about
"Setting an enterstep trace on a command name that does not refer to a procedure will not result in an error and is simply ignored."
doesn't seem to be true, because if the command picked up is proc it seems
to complain.
<quote file="verbose_tcl.tcl">
# open the supplied tcl file
# Not sure how to get args into activetcl.
# set infile [open [lindex $argv 0]]
set infile [ open toy_example.tcl "r"]
set outfile [open verbose_tcl.log "w"]
# This prints the "before" and "after" substitution
proc filter_and_print {command} {
global outfile
# display the command
puts outfile $command
# display what it is like substituted.
set scommand [subst command]
puts outfile $scommand
}
while { ! [eof $infile]} {
# Read a line
set command [read $infile]
# keep reading till we have a complete command
while { ! [ info complete $command] } {
set command "$command\n[read $infile]"
}
set procedure [lindex [split "$command" "\s+"] 0]
# catch needed because "proc" causes this to choke
catch {trace add execution $procedure enterstep filter_and_print}
eval $command
catch {trace remove execution $procedure enterstep filter_and_print}
}
close $infile
close $outfile
</quote>
<quote file="toy_example.tcl">
proc story { char story } {
return {[format {$story} {$char} ]}
}
proc example {} {
story {Story} {Once upon a time there was a %s
about a [ story {really contrived example program} {%s of a horrendous sort} ].}
}
puts [example]
</quote>
I'm getting some wierdness with activetcl which means I get a window up,
like wish with no args. Running under cygwin:
hgs@Q2P14HGS /cygdrive/c/Documents and Settings/hgs/My Documents/brains/hgs/prog
s/tk
17:14:20$ ./verbose_tcl.tcl
./verbose_tcl.tcl: line 4: $'\r': command not found
./verbose_tcl.tcl: line 7: $'\r': command not found
./verbose_tcl.tcl: line 9: proc: command not found
./verbose_tcl.tcl: line 10: global: command not found
./verbose_tcl.tcl: line 12: puts: command not found
./verbose_tcl.tcl: line 13: $'\r': command not found
./verbose_tcl.tcl: line 16: puts: command not found
./verbose_tcl.tcl: line 17: $'}\r': command not found
./verbose_tcl.tcl: line 18: $'\r': command not found
./verbose_tcl.tcl: line 19: $'\r': command not found
./verbose_tcl.tcl: line 40: syntax error: unexpected end of file
hgs@Q2P14HGS /cygdrive/c/Documents and Settings/hgs/My Documents/brains/hgs/prog
s/tk
17:20:11$
which I'm pretty sure is a DOS/Unix line endings issue, but pasting
it in here hasn't givem me a load of ctrl-Ms. Surely \r is
whitespace for unix/cygwin tcl, but apparently not.
Anyway, does anything obviously wrong with verbose_tcl.tcl come to mind?
I'm now in the position of needing to debug a script written to help me
debug other scripts... :-)
Hugh
One problem I see is that you are using [read], when it appears you
just want to read one line. You need [gets] for one line reads.
Another problem is your use a global 'outfile', but in your [puts
outfile $command], outfile is just a string, not the value of the
outfile.
It looks like you are trying to do something complicated, but making
basic mistakes.
I have written a very simple proc for creating tclsh examples. For
debugging you can just use this proc before a regular command, so you
only have to print out the ones you are interested in.
Here is the proc:
proc ::% { args } {
puts "% $args"
if {[catch {
puts [uplevel "$args"]
} err ]} {
global errorInfo
puts $errorInfo
}
}
Then you just add a '%' before any command you want to print out:
% set a b
% set r $a
If you sourced a file that contained these lines, you would get:
% set a b
b
% set r b
b
But it looks more like what you want is a real debugger, and try out
simpler examples, your home grown debugger will only obscure what you
are trying to do.
The easiest way to step through/debug a script is to open it up in an
editor, and then copy/paste each command into a shell script.
Also, see http://wiki.tcl.tk/21071 which does approximately what he
was originally looking for (and shows that he'd tangled himself up
into a horrible mess).
Donal.
[...]
> >
> > I'm getting some wierdness with activetcl which means I get a window up,
> > like wish with no args. Running under cygwin:
> >
> > hgs@Q2P14HGS /cygdrive/c/Documents and Settings/hgs/My Documents/brains/hgs/prog
> > s/tk
> > 17:14:20$ ./verbose_tcl.tcl
[...]
> > ./verbose_tcl.tcl: line 19: $'\r': command not found
> > ./verbose_tcl.tcl: line 40: syntax error: unexpected end of file
> >
> > hgs@Q2P14HGS /cygdrive/c/Documents and Settings/hgs/My Documents/brains/hgs/prog
> > s/tk
> > 17:20:11$
> >
> > which I'm pretty sure is a DOS/Unix line endings issue, but pasting
> > it in here hasn't givem me a load of ctrl-Ms. Surely \r is
> > whitespace for unix/cygwin tcl, but apparently not.
> >
> > Anyway, does anything obviously wrong with verbose_tcl.tcl come to mind?
> > I'm now in the position of needing to debug a script written to help me
> > debug other scripts... :-)
> >
> > Hugh
>
> One problem I see is that you are using [read], when it appears you
> just want to read one line. You need [gets] for one line reads.
Thanks.
>
> Another problem is your use a global 'outfile', but in your [puts
> outfile $command], outfile is just a string, not the value of the
> outfile.
Ah, right. I've not used Tcl for some years, so I keep writing as if
I don't need $ to reference vars. Thank you.
>
> It looks like you are trying to do something complicated, but making
> basic mistakes.
:-) The thing giving me the most trouble is keeping the substitutions
straight in my head. They are simple and regular, but then so are
YACC grammars, and keeping track of shift and reduce seems to be
difficult as well.
>
> I have written a very simple proc for creating tclsh examples. For
> debugging you can just use this proc before a regular command, so you
> only have to print out the ones you are interested in.
>
> Here is the proc:
>
> proc ::% { args } {
> puts "% $args"
> if {[catch {
> puts [uplevel "$args"]
> } err ]} {
> global errorInfo
> puts $errorInfo
> }
> }
>
> Then you just add a '%' before any command you want to print out:
>
> % set a b
> % set r $a
>
> If you sourced a file that contained these lines, you would get:
>
> % set a b
> b
> % set r b
> b
>
Thanks, that will be useful.
> But it looks more like what you want is a real debugger, and try out
> simpler examples, your home grown debugger will only obscure what you
> are trying to do.
Especially when it has its own bugs.
>
> The easiest way to step through/debug a script is to open it up in an
> editor, and then copy/paste each command into a shell script.
>
this is difficult and somewhat error prone when loops and long inputs are
involved.
Thank you,
Hugh
Well, that was a contrived example, which just did format with args
reversed as a way to get layers of quoting in, but does demonstrate
that my real application is even more munged than that. Hopefully
I'll be able to straighten things out now. Thank you.
>
> Donal.
>
Use the Tclx extension that has the cmdtrace command. You will see all
the commands exectuted
in all their gory detail includes options to limit or expand detail
and shows what level you
are executing in. The best part is that it shows you the command and
variables then the command and the variable values then the result so
when an error happens you'll see the value of variables.
Carl