In previous lessons we discussed how the return
command could be used to return
a value from a proc. In Tcl, a proc may return a value, but
it always returns a status.
When a Tcl command or procedure encounters an error during its
execution, the global variable errorInfo
is set, and an error condition
is generated. If you have proc a
that called proc b
that called
c
that called d
, if d
generates an error, the "call stack" will unwind. Since d
generates an error, c
will not
complete execution cleanly, and will have to pass the error up
to b
, and in turn on to a
. Each procedure adds some information
about the problem to the report. For instance:
proc a {} { b } proc b {} { c } proc c {} { d } proc d {} { some_command } a
Produces the following output:
invalid command name "some_command" while executing "some_command" (procedure "d" line 2) invoked from within "d" (procedure "c" line 2) invoked from within "c" (procedure "b" line 2) invoked from within "b" (procedure "a" line 2) invoked from within "a" (file "errors.tcl" line 16)
This actually occurs when any exception condition occurs,
including break
and continue
. The break
and continue
commands normally occur within a
loop of some sort, and the loop command catches the exception
and processes it properly, meaning that it either stops
executing the loop, or continues on to the next instance of the
loop without executing the rest of the loop body.
It is possible to "catch" errors and exceptions with the catch
command, which runs some code, and
catches any errors that code happens to generate. The
programmer can then decide what to do about those errors and act
accordingly, instead of having the whole application come to a
halt.
For example, if an open
call
returns an error, the user could be prompted to provide another
file name.
A Tcl proc can also generate an error status condition. This
can be done by specifying an error return with an option to the
return
command, or by using the
error
command. In either case, a
message will be placed in errorInfo
, and the proc will generate an
error.
error
message
?info?
?code?
Generates an error condition and forces the Tcl call stack to unwind, with error information being added at each step.
If info
or code
are provided, the errorInfo and
errorCode variables are initialized with these values.
catch
script
?varName?
Evaluates and executes script
. The
return value of catch is the status return of the Tcl
interpreter after it executes script
If there are no errors in script
, this value is 0. Otherwise it is
1.
If varName
is supplied, the value
returned by script
is placed in
varName
if the script successfully
executes. If not, the error is placed in varName
.
return
?-code code?
?-errorinfo info?
?-errorcode errorcode?
?value?
-code
code
code
must be one of:
ok
- Normal status returnerror
- Proc returns error statusreturn
- Normal returnbreak
- Proc returns break statuscontinue
- Proc returns continue statusbreak
, error
, and continue
.
-errorinfo
info
info
will be the first string in
the errorInfo
variable.
-errorcode
errorcode
errorCode
to errorcode
.
value
value
will be the
value returned by this proc.
errorInfo
errorInfo
is a global variable
that contains the error information from commands that have
failed.
errorCode
errorCode
is a global variable
that contains the error code from command that failed. This
is meant to be in a format that is easy to parse with a
script, so that Tcl scripts can examine the contents of this
variable, and decide what to do accordingly.
proc errorproc {x} { if {$x > 0} { error "Error generated by error" "Info String for error" $x } } catch errorproc puts "after bad proc call: ErrorCode: $errorCode" puts "ERRORINFO:\n$errorInfo\n" set errorInfo ""; catch {errorproc 0} puts "after proc call with no error: ErrorCode: $errorCode" puts "ERRORINFO:\n$errorInfo\n" catch {errorproc 2} puts "after error generated in proc: ErrorCode: $errorCode" puts "ERRORINFO:\n$errorInfo\n" proc returnErr { x } { return -code error -errorinfo "Return Generates This" -errorcode "-999" } catch {returnErr 2} puts "after proc that uses return to generate an error: ErrorCode: $errorCode" puts "ERRORINFO:\n$errorInfo\n" proc withError {x} { set x $a } catch {withError 2} puts "after proc with an error: ErrorCode: $errorCode" puts "ERRORINFO:\n$errorInfo\n" catch {open [file join no_such_directory no_such_file] r} puts "after an error call to a nonexistent file:" puts "ErrorCode: $errorCode" puts "ERRORINFO:\n$errorInfo\n"