Previous: , Up: Evaluation; Stack Frames; Bindings   [Contents][Index]


15.4 Catch and Throw

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: , Up: Evaluation; Stack Frames; Bindings   [Contents][Index]