6
votes

I'm doing eval on the content of file. The file is made out of labels which I parse. Each line has a label, and I have a proc defined for each label, so that the eval succeeds. However, sometimes users add new labels and then the eval command fails, because of unknown command.

Is there a way to prevent Tcl from crashing when trying to eval an unknown command?
Ideally, it should allow me to substitute with my own defined behaviour - such as priting an error and continuing with the eval.


EDIT:

Unfortunately, I can only use Tcl 8.4.
I tried doing the following, as suggested here:

proc handle_unknown_label {cmd args} { ... }

and then:

rename unknown _old_system_unknown
rename handle_unknown_label unknown

catch {set ret [eval $x]} err

rename unknown handle_unknown_label
rename _old_system_unknown unknown

but I still get the same behavior for the eval, and it prints the following errors:

procedure unknown is a protected proc and will not get renamed
procedure unknown is a protected proc and will not get overriden
procedure unknown is a protected proc and will not get renamed
procedure unknown is a protected proc and will not get overriden

2
not applicable but if you are reading a file and evaling it you may as well just source the file instead, no?jk.
in what environment is this Tcl interpreter? I'm not familiar with that "protected proc" error.glenn jackman
@glenn Interesting. So this could be something that was disabled in my firm?Amir Rachum
The only thing that came to mind was that you're boxed into a safe interpreter, but even that does not prevent you from defining an unknown proc. Your Tcl interpreter must be specially built to be extra-paranoid.glenn jackman

2 Answers

3
votes

I think I'm stating the obvious, but eval'ing a file is dangerous: any user can embed [exec whatever they wish] into such a file.

Much better would be to read those "labels" and use a giantic switch or a hash map or whatever to execute a predetermined command. Catching non-existing "labels" also becomes a non-issue.

2
votes

Implement your own command called unknown, which takes as its arguments all the words that make up the command that can't be found and its args:

proc unknown {cmdName args} {
    puts "UNKNOWN COMMAND: $cmdName"
    puts "CALLED WITH ARGUMENTS: $args"
}

That's about all you need to do, though you can get fancier with the use of namespace unknown.