Re: retrieving line number in case of error - "simple debugger"
Available news archives: comp.lang.tcl - comp.lang.python - comp.security.firewalls - sci.crypt - comp.lang.php - comp.lang.javascript
Google
 
Web news.hping.org


comp.lang.tcl archive

Re: retrieving line number in case of error - "simple debugger"

From: Wojciech Kocjan <hceicjow.backward@kocjan.org>
Date: Thu Sep 29 2005 - 19:50:21 CEST

Bryan Oakley napisaƂ(a):
> set lineno 0
> foreach line [split $script \n] {
> if {![info exists command]} {
> set command $line
> } else {
> append command \n $line
> }
> incr lineno
> if {[info complete $command]} {
> if {[catch $command err]} {
> puts "error on line $lineno: $err"
> }
> unset command
> }
> }

That one's actually tricky.

(zoro) 55 % info complete "puts \\"
1
(zoro) 56 % eval "puts \\
x"
x

So this would not get parsed correctly. The other tricky thing is:

(zoro) 57 % eval "puts \\\\
x"

Since it's the opposite. The moral of the story is that \\ at the end of
a line are a PITA in this case. I think it is much safer to do info
complete and check for an even number of \ at the end (0 is also even
for me :-). But there's probably still some other issue (or issues) that
do not make it work... Anyway, here's "info complete on steroids" :-)

proc checkIfReallyComplete {line} {
     if {![info complete $line]} {
         return false
     }
     set count 0
     while {[string index $line end-$count] == "\\"} {
         incr count
     }
     if {$count % 2} {
         return false
     } else {
         return true
     }
}

> So, perhaps the answer to your question is "info complete" and "catch".
> That is, you can use [info complete] to know if a line or lines of
> user-entered text is a complete command, and "catch" to execute the
> command and to retrieve the result.

I no longer believe in [info complete]. Well, it would be great if Tcl
would have [info complete -strict] or something, that would actually
check what the interpreter would do. For now, I guess most people could
live with the equivalent above.

But, assuming he would have a proc called checkIfReallyComplete (or
something), then it would be much better to:

set realcode ""
set script [.text get 1.0 end-1c]
set lineno 0
foreach line [split $script \n] {
     if {![info exists command]} {
         set command $line
     } else {
         append command \n $line
     }
     incr lineno
     if {[checkIfReallyComplete $command]} {
         append realcode [list set ::lineNumber $lineno] \n $command \n
     }
}
if {[catch $realcode]} {
     puts "Error in $::lineNumber $::errorInfo"
}

And even better, this would allow storing the "debugable" version of the
script.

Then we would probably come up with a problem with control statements
like for/foreach/while/if and would have to emulate those (preferably at
"parser" level). Well then we will have custom control statements... (ie
expect command from expect or tcom::foreach). I think this is a messy
situation. Well, not to mention considering namespaces while parsing (ie :

namespace eval tcom {
     foreach ....
}

is not quite obvious. Especially with the following "crude" code:

set ns tcom
namespace eval $ns {
     foreach ....
}

Then there's metaprogramming ;-)

I wonder if an universal parser could be produced this way - one that
would return return something similar to command tree so that everyone
could debug it the way they want to (GUI, logging, whatever).

Just my 2 cents in this matter. If anybody wants to pursue this, I would
love to see the results. I wanted to, but got scared by the problems
above. Anyway, for a plain Tcl script, those problems do not really
exist :-) So just reparsing using info complete + for/foreach/while/if
would easily debug 90% of the scripts.

-- 
WK
Received on Sat Oct 15 03:53:42 2005