user782642
user782642

Reputation: 221

How can I check that Tcl command didn't throw an exception or error?

I have a following procedure:

proc myexec { args } {
    info_msg "Executing shell command: $args"

    set catch_res [catch  {eval exec $args} res]

    if { $catch_res != 0 } {
        error_msg "Failed in command: $args"
        error_msg "$res"
    }

    return $catch_res
}

It only checks Unix commands and doesn't work with Tcl commands. How can I change this procedure so that it will work with Tcl commands?

For example, if I want to check that the following commands evaluate without error:

set object1 $object2

or

open $filename r

Upvotes: 4

Views: 3570

Answers (2)

Donal Fellows
Donal Fellows

Reputation: 137557

The simplest method is to do this:

proc myeval { args } {
    info_msg "Executing Tcl command: $args"

    set catch_res [catch $args res]

    if { $catch_res != 0 } {
        error_msg "Failed in command: $args"
        error_msg "$res"
    }

    return $res
}

Here, we've replaced catch {eval exec $args} res with catch $args res (plus some cosmetic stuff) which will cause the arguments to be evaluated as a script without further substitution. You'd use it like this:

myeval foo bar $boo

Alternatively, if you're after doing substitutions within the catch as well, you'd be better writing this more complex version:

proc myeval { script } {
    info_msg "Executing Tcl command: [string trim $script]"

    set catch_res [catch [list uplevel 1 $script] res]

    if { $catch_res != 0 } {
        error_msg "Failed in command: [string trim $script]"
        error_msg "$res"
    }

    return $res
}

In this case, you'd call it like this:

myeval {
    foo bar $boo
}

Upvotes: 3

Colin Macleod
Colin Macleod

Reputation: 4372

If you just want to modify this procedure so it runs the arguments passed as a Tcl command instead of as a Unix command, just drop the exec, ie. instead of eval exec $args just do eval $args.

Making a single procedure handle both Tcl and Unix commands is harder, but Tcl already does this for commands you type in tclsh or wish - it looks for a built-in command first and if it doesn't find one it then tries to run it as a Unix command. You can turn on this behaviour in a script by doing set ::tcl_interactive 1 - more details at Tcl Wiki

Upvotes: 1

Related Questions