Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

return -code behavior in catch

Status
Not open for further replies.

davidbessire

Programmer
Jan 9, 2007
3
US
If the script i use in a catch:
a. is not wrapped in "proc"; and,
b. ends with "return"
Then:
catch considers this an error (i.e. not TCL_OK).

This feature is documented in the Tcl/Tk man pages and in Welch.

As an example of the behavior, consider:

% proc bar { } { return }
% catch { bar }
0
% catch { return }
2

Question: How do you write code that employs Tcl's dynamic script construction & execution capabilities without risking this spurious error? This behavior prevents writing something like ...

if { [catch {
# complicated script with several return paths
} error] } {
# report error
}

... unless you convert the script into a procedure. Otherwise, *any* return from the script via "return" will trigger error handling (even "return -code 0"). Procs using "catch" and "uplevel" to run untrusted & potentially buggy scripts (perhaps as part of new control structures) may generate spurious stack traces.

Any way to avoid the inelegance below?

set failed [catch {$code} error]
if { $failed == 1 } {
# handle TCL_ERROR
} elseif { $failed == 2 } {
# handle TCL_RETURN
} elseif { $failed == 3 } {
# handle TCL_BREAK
} elseif { $failed == 4 } {
# handle TCL_CONTINUE
}

Thanks,
davidbessire
 
That's how i thought it would work, too, but it doesn't (as i noted in the original post):

% catch { return -code 0 }
2
% catch { return -code ok }
2

That's in Tcl 8.3 (Windows) and 8.4 (Linux). 'catch' directly receives the return code from 'return' (TCL_RETURN == 2) which is considered an error in the usual 'if { [catch ...] }' idiom. Try it yourself.

i'm not necessarily claiming this is a bug in Tcl, but it does limit what you can do with catch.

-db
 
[red]That's how i thought it would work, too, but it doesn't (as i noted in the original post):

% catch { return -code 0 }
2
% catch { return -code ok }
2[/red]"

It does.
In your examples there is no error thrown so you get the normal return code of the command.
Here 2 means you trapped a return command with no returned value (no matter the code you gave to the -code option of return).

The general scheme for using catch and return -code is:

Code:
  proc errored {} { some error }
  proc test {} \
  {
    set rc [catch \
    {
      errored
    } result]
    return -code $code $result
  }
  test
Try changing the errored proc to see what happens.
Try changing the code given to return to see what happens.

All that is explaned in the pages I indicated you.

ulis
 
But you've wrapped that code in a proc.

As i wrote earlier:

If the script i use in a catch:
** a. is not wrapped in "proc" ; and,
b. ends with "return"
Then:
catch considers this an error (i.e. not TCL_OK).

The point being, code like:

proc runit { script } {
if { [catch {
eval $script
} error] } {
error "Caught an error" $::errorInfo $error
}
}

(a common idiom; see Welch) fails when used with anything ending with "return", no matter the -code value specified:

% runit {
if { 1 } {
return -code ok
}
}
Caught an error
%

At my work, there's lots of code like this and i don't feel like removing all of it.

i asked if there was any was to avoid the inelegance of testing for every possible return value. The answer is "No"; see Ousterhout section 12.4, where he does exactly this.

Thanks for the responses. Have a pleasant evening.





 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top