# HG changeset patch # User Jim Blandy # Date 717143010 0 # Node ID ab2d88e2505bda524d8a11cbcd710beaf068c82c # Parent 7c4519722020aba31c9047a2ff1d18475087865e * eval.c (unbind_catch): Do the long-jump here. Take a VALUE argument, which specifies the value to return to the catch, or the data to give to the condition handler. Renamed to unwind_to_catch, to reflect new role. (Fsignal, Fthrow): Removed code to set catch tag value and do the long-jump; this is taken care of by unwind_to_catch. diff -r 7c4519722020 -r ab2d88e2505b src/eval.c --- a/src/eval.c Tue Sep 22 05:19:09 1992 +0000 +++ b/src/eval.c Tue Sep 22 06:23:30 1992 +0000 @@ -879,23 +879,32 @@ return c.val; } -/* Discard from the catchlist all catch tags back through CATCH. - Before each catch is discarded, unbind all special bindings - made within that catch. Also, when discarding a catch that - corresponds to a condition handler, discard that handler. +/* Unwind the specbind, catch, and handler stacks back to CATCH, and + jump to that CATCH, returning VALUE as the value of that catch. + + This is the guts Fthrow and Fsignal; they differ only in the way + they choose the catch tag to throw to. A catch tag for a + condition-case form has a TAG of Qnil. - At the end, restore some static info saved in CATCH. + Before each catch is discarded, unbind all special bindings and + execute all unwind-protect clauses made above that catch. Unwind + the handler stack as we go, so that the proper handlers are in + effect for each unwind-protect clause we run. At the end, restore + some static info saved in CATCH, and longjmp to the location + specified in the - This is used for correct unwinding in Fthrow and Fsignal, - before doing the longjmp that actually destroys the stack frames - in which these handlers and catches reside. */ + This is used for correct unwinding in Fthrow and Fsignal. */ static void -unbind_catch (catch) +unwind_to_catch (catch, value) struct catchtag *catch; + Lisp_Object value; { register int last_time; + /* Save the value in the tag. */ + catch->val = value; + /* Restore the polling-suppression count. */ if (catch->poll_suppress_count > poll_suppress_count) abort (); @@ -917,6 +926,8 @@ gcprolist = catch->gcpro; backtrace_list = catch->backlist; lisp_eval_depth = catch->lisp_eval_depth; + + _longjmp (catch->jmp, 1); } DEFUN ("throw", Fthrow, Sthrow, 2, 2, 0, @@ -933,11 +944,7 @@ for (c = catchlist; c; c = c->next) { if (EQ (c->tag, tag)) - { - c->val = val; - unbind_catch (c); - _longjmp (c->jmp, 1); - } + unwind_to_catch (c, val); } tag = Fsignal (Qno_catch, Fcons (tag, Fcons (val, Qnil))); } @@ -1140,9 +1147,7 @@ { struct handler *h = handlerlist; handlerlist = allhandlers; - unbind_catch (h->tag); - h->tag->val = Fcons (clause, Fcons (sig, data)); - _longjmp (h->tag->jmp, 1); + unwind_to_catch (h->tag, Fcons (clause, Fcons (sig, data))); } } @@ -1195,9 +1200,10 @@ { if (wants_debugger (Vstack_trace_on_error, conditions)) internal_with_output_to_temp_buffer ("*Backtrace*", Fbacktrace, Qnil); - if (when_entered_debugger < num_nonmacro_input_chars - && (EQ (sig, Qquit) ? debug_on_quit - : wants_debugger (Vdebug_on_error, conditions))) + if ((EQ (sig, Qquit) + ? debug_on_quit + : wants_debugger (Vdebug_on_error, conditions)) + && when_entered_debugger < num_nonmacro_input_chars) { int count = specpdl_ptr - specpdl; specbind (Qdebug_on_error, Qnil);