Previous: Simple Special Forms, Up: Evaluation; Stack Frames; Bindings [Contents][Index]
struct catchtag
{
Lisp_Object tag;
Lisp_Object val;
struct catchtag *next;
struct gcpro *gcpro;
jmp_buf jmp;
struct backtrace *backlist;
int lisp_eval_depth;
int pdlcount;
};
catch is a Lisp function that places a catch around a body of
code. A catch is a means of non-local exit from the code. When a catch
is created, a tag is specified, and executing a throw to this tag
will exit from the body of code caught with this tag, and its value will
be the value given in the call to throw. If there is no such
call, the code will be executed normally.
Information pertaining to a catch is held in a struct catchtag,
which is placed at the head of a linked list pointed to by
catchlist. internal_catch() is passed a C function to
call (Fprogn() when Lisp catch is called) and arguments to
give it, and places a catch around the function. Each struct
catchtag is held in the stack frame of the internal_catch()
instance that created the catch.
internal_catch() is fairly straightforward. It stores into the
struct catchtag the tag name and the current values of
backtrace_list, lisp_eval_depth, gcprolist, and the
offset into the specpdl array, sets a jump point with _setjmp()
(storing the jump point into the struct catchtag), and calls the
function. Control will return to internal_catch() either when
the function exits normally or through a _longjmp() to this jump
point. In the latter case, throw will store the value to be
returned into the struct catchtag before jumping. When it’s
done, internal_catch() removes the struct catchtag from
the catchlist and returns the proper value.
Fthrow() goes up through the catchlist until it finds one with
a matching tag. It then calls unbind_catch() to restore
everything to what it was when the appropriate catch was set, stores the
return value in the struct catchtag, and jumps (with
_longjmp()) to its jump point.
unbind_catch() removes all catches from the catchlist until it
finds the correct one. Some of the catches might have been placed for
error-trapping, and if so, the appropriate entries on the handlerlist
must be removed (see “errors”). unbind_catch() also restores
the values of gcprolist, backtrace_list, and
lisp_eval, and calls unbind_to() to undo any specbindings
created since the catch.
Previous: Simple Special Forms, Up: Evaluation; Stack Frames; Bindings [Contents][Index]