Some built-in Tcl commands (but also user procs) can generate a Tcl error (TCL_ERROR) that can stop the execution of the script if the error is not caught by the program. An example is the file
command that generates a TCL_ERROR when the file cannot be opened.
To do safe programming and catch the TCL_ERROR condition, Tcl has a built-in catch
command that returns 1 when an error is caught and otherwise returns 0. The catch
command can be used on a single command or a set of commands.
The basic syntax of the catch
command is:
catch script [varname]
Where the script
is a single or a set of Tcl commands and varname
is a variable name in which the message explaining the TCL_ERROR is saved.
varname
argument is optional.The catch command is often used as illustrated below:
If {[catch script errorstring]} {
# A low-level TCL_ERROR happened
puts " Error - $errorstring "
} else {
# No TCL_ERROR was generated
puts " The code completed successfully "
}
Example 1 can be made safer using the catch
command to cover the case where the file cannot be opened:
Example 3: Check when a file is opened for read/write (safe version).
if {[file exists $filename]} {
if {[catch { set FH [open $filename r] } errorstring]} {
puts " File $filename could not be opened : $errorstring"
} else {
# The file is opened, do something
# …
close $FH
}
} else {
puts " File $filename does not exist"
}
A Tcl error can also be user generated using the error
command. This can be used, for example, to propagate a TCL_ERROR that is caught with the catch
command to the upper level (bubbling). However, the error
command can be used as well to generate a TCL_ERROR when, for example, a corner case is not supported by the script or an unexpected condition has happened in the code.
For example, the proc below returns the file content or generates a TCL_ERROR when the file cannot be opened:
proc get_file_content { filename } {
if {[catch {
set FH [open $filename r]
set content [read $FH]
close $FH
} errorstring]} {
error " File $filename could not be opened : $errorstring "
}
return $content
}
The proc get_file_content
can be called through a catch
command to catch the potential error:
if {[catch { set content [get_file_content ./myreport.rpt] } errorstring]} {
puts " The following error was generated: $errorstring "
} else {
puts " The content of the file is: $content "
}
Example 2 can also be improved to generate a TCL_ERROR when a wrong condition occurs as shown in Example 4:
Example 4: Check that the Vivado objects are valid. Generate a TCL_ERROR otherwise (revised).
proc get_pin_dir { pinName } {
if {$pinName == {}} {
error " Error - no pin name provided"
}
set pin [get_pins $pinName]
if {$pin == {}} {
error " Error - pin $pinName does not exist"
}
set direction [get_property DIRECTION $pin]
return $direction
}