|
|
BSD 4.2
CHAPTER 10
Exception Handling
10.1. Errset and Error Handler Functions
FRANZ LISP allows the user to handle in a number
of ways the errors which arise during computation.
One way is through the use of the _e_r_r_s_e_t function. If
an error occurs during the evaluation of the _e_r_r_s_e_t's
first argument, then the locus of control will return
to the errset which will return nil (except in special
cases, such as _e_r_r). The other method of error han-
dling is through an error handler function. When an
error occurs, the error handler is called and is given
as an argument a description of the error which just
occurred. The error handler may take one of the fol-
lowing actions:
(1) it could take some drastic action like a _r_e_s_e_t or
a _t_h_r_o_w.
(2) it could, assuming that the error is continuable,
return to the function which noticed the error.
The error handler indicates that it wants to
return a value from the error by returning a list
whose _c_a_r is the value it wants to return.
(3) it could decide not to handle the error and
return a non-list to indicate this fact.
10.2. The Anatomy of an error
Each error is described by a list of these items:
(1) error type - This is a symbol which indicates the
general classification of the error. This clas-
sification may determine which function handles
this error.
(2) unique id - This is a fixnum unique to this
error.
(3) continuable - If this is non-nil then this error
is continuable. There are some who feel that
Exception Handling 10-1
Exception Handling 10-2
every error should be continuable and the reason
that some (in fact most) errors in FRANZ LISP are
not continuable is due to the laziness of the
programmers.
(4) message string - This is a symbol whose print
name is a message describing the error.
(5) data - There may be from zero to three lisp
values which help describe this particular
error. For example, the unbound variable error
contains one datum value, the symbol whose value
is unbound. The list describing that error might
look like:
(ER%misc 0 t |Unbound Variable:| foobar)
10.3. Error handling algorithm
This is the sequence of operations which is done
when an error occurs:
(1) If the symbol ER%all has a non nil value then
this value is the name of an error handler func-
tion. That function is called with a description
of the error. If that function returns (and of
course it may choose not to) and the value is a
list and this error is continuable, then we
return the _c_a_r of the list to the function which
called the error. Presumably the function will
use this value to retry the operation. On the
other hand, if the error handler returns a non
list, then it has chosen not to handle this
error, so we go on to step (2). Something spe-
cial happens before we call the ER%all error
handler which does not happen in any of the other
cases we will describe below. To help insure
that we don't get infinitely recursive errors if
ER%all is set to a bad value, the value of ER%all
is set to nil before the handler is called. Thus
it is the responsibility of the ER%all handler to
`reenable' itself by storing its name in ER%all.
(2) Next the specific error handler for the type of
error which just occurred is called (if one
exists) to see if it wants to handle the error.
The names of the handlers for the specific types
of errors are stored as the values of the symbols
whose names are the types. For example the
handler for miscellaneous errors is stored as the
value of ER%misc. Of course, if ER%misc has a
value of nil, then there is no error handler for
Printed: July 21, 1983
Exception Handling 10-3
this type of error. Appendix B contains list of
all error types. The process of classifying the
errors is not complete and thus most errors are
lumped into the ER%misc category. Just as in
step (1), the error handler function may choose
not to handle the error by returning a non-list,
and then we go to step (3).
(3) Next a check is made to see if there is an _e_r_r_s_e_t
surrounding this error. If so the second argu-
ment to the _e_r_r_s_e_t call is examined. If the
second argument was not given or is non nil then
the error message associated with this error is
printed. Finally the stack is popped to the
context of the _e_r_r_s_e_t and then the _e_r_r_s_e_t returns
nil. If there was no _e_r_r_s_e_t we go to step (4).
(4) If the symbol ER%tpl has a value then it is the
name of an error handler which is called in a
manner similar to that discussed above. If it
chooses not to handle the error, we go to step
(5).
(5) At this point it has been determined that the
user doesn't want to handle this error. Thus the
error message is printed out and a _r_e_s_e_t is done
to send the flow of control to the top-level.
To summarize the error handling system: When an
error occurs, you have two chances to handle it before
the search for an _e_r_r_s_e_t is done. Then, if there is
no _e_r_r_s_e_t, you have one more chance to handle the
error before control jumps to the top level. Every
error handler works in the same way: It is given a
description of the error (as described in the previous
section). It may or may not return. If it returns,
then it returns either a list or a non-list. If it
returns a list and the error is continuable, then the
_c_a_r of the list is returned to the function which
noticed the error. Otherwise the error handler has
decided not to handle the error and we go on to some-
thing else.
10.4. Default aids
There are two standard error handlers which will
probably handle the needs of most users. One of these
is the lisp coded function _b_r_e_a_k-_e_r_r-_h_a_n_d_l_e_r which is
the default value of ER%tpl. Thus when all other
handlers have ignored an error, _b_r_e_a_k-_e_r_r-_h_a_n_d_l_e_r will
take over. It will print out the error message and go
Printed: July 21, 1983
Exception Handling 10-4
into a read-eval-print loop. The other standard error
handler is _d_e_b_u_g-_e_r_r-_h_a_n_d_l_e_r. This handler is
designed to be connected to ER%alland is useful if
your program uses _e_r_r_s_e_t and you want to look at the
error before it is thrown up to the _e_r_r_s_e_t.
10.5. Autoloading
When _e_v_a_l, _a_p_p_l_y or _f_u_n_c_a_l_l are told to call an
undefined function, an ER%undef error is signaled.
The default handler for this error is _u_n_d_e_f-_f_u_n_c-
_h_a_n_d_l_e_r. This function checks the property list of
the undefined function for the indicator autoload. If
present, the value of that indicator should be the
name of the file which contains the definition of the
undefined function. _U_n_d_e_f-_f_u_n_c-_h_a_n_d_l_e_r will load the
file and check if it has defined the function which
caused the error. If it has, the error handler will
return and the computation will continue as if the
error did not occur. This provides a way for the user
to tell the lisp system about the location of commonly
used functions. The trace package sets up an autoload
property to point to /usr/lib/lisp/trace.
10.6. Interrupt processing
The UNIX operating system provides one user
interrupt character which defaults to ^C.[] The user
may select a lisp function to run when an interrupt
occurs. Since this interrupt could occur at any time,
and in particular could occur at a time when the
internal stack pointers were in an inconsistent state,
the processing of the interrupt may be delayed until a
safe time. When the first ^C is typed, the lisp sys-
tem sets a flag that an interrupt has been requested.
This flag is checked at safe places within the inter-
preter and in the _q_l_i_n_k_e_r function. If the lisp sys-
tem doesn't respond to the first ^C, another ^C should
be typed. This will cause all of the transfer tables
to be cleared forcing all calls from compiled code to
go through the _q_l_i_n_k_e_r function where the interrupt
flag will be checked. If the lisp system still
doesn't respond, a third ^C will cause an immediate
interrupt. This interrupt will not necessarily be in
____________________
9 []Actually there are two but the lisp system does not al-
low you to catch the QUIT interrupt.
9 Printed: July 21, 1983
Exception Handling 10-5
a safe place so the user should _r_e_s_e_t the lisp system
as soon as possible.
9
9 Printed: July 21, 1983
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.