diff options
| author | Jim Blandy | 1992-09-22 05:17:48 +0000 |
|---|---|---|
| committer | Jim Blandy | 1992-09-22 05:17:48 +0000 |
| commit | 82da7701c884bda5329ca7115d151a5e8c69439c (patch) | |
| tree | 434e9737d593b5e1658629702cf1ab7e5085c023 /src/eval.c | |
| parent | b44895bc92df5e32f03693b7c881bce9fc80b50d (diff) | |
| download | emacs-82da7701c884bda5329ca7115d151a5e8c69439c.tar.gz emacs-82da7701c884bda5329ca7115d151a5e8c69439c.zip | |
* eval.c (Fcondition_case): Rearranged for clarity. Don't worry
about setting h.poll_suppress_count; it's guaranteed to be the
same as c.poll_suppress_count.
(internal_condition_case): Don't worry about
h.poll_suppress_count.
(Fsignal): Use h->tag->poll_suppress_count instead of
h->poll_suppress_count.
* eval.c (Fsignal): It's okay for the debugger to return to the
caller if the caller was signalling a quit.
* eval.c (unbind_catch): Restore the polling suppression count
here, instead of in Fsignal and Fthrow.
(Fthrow, Fsignal): Don't restore the polling suppression count here.
* eval.c (struct catchtag): More documentation.
* eval.c (entering_debugger): Variable renamed
when_entered_debugger, and is now a timestamp based on
num_nonmacro_input_chars.
(init_eval): Initialize when_entered_debugger, not
entering_debugger.
(call_debugger): Set when_entered_debugger to the current value of
num_nonmacro_input_chars.
(find_handler_clause): Don't call debugger unless
num_nonmacro_input_chars is greater than when_entered_debugger;
that way, we won't call the debugger unless the user has had a
chance to take control.
(Fbacktrace): Don't clear entering_debugger here.
Diffstat (limited to 'src/eval.c')
| -rw-r--r-- | src/eval.c | 99 |
1 files changed, 65 insertions, 34 deletions
diff --git a/src/eval.c b/src/eval.c index 2f3d684f469..ca78a065045 100644 --- a/src/eval.c +++ b/src/eval.c | |||
| @@ -51,6 +51,24 @@ struct backtrace | |||
| 51 | 51 | ||
| 52 | struct backtrace *backtrace_list; | 52 | struct backtrace *backtrace_list; |
| 53 | 53 | ||
| 54 | /* This structure helps implement the `catch' and `throw' control | ||
| 55 | structure. A struct catchtag contains all the information needed | ||
| 56 | to restore the state of the interpreter after a non-local jump. | ||
| 57 | |||
| 58 | Handlers for error conditions (represented by `struct handler' | ||
| 59 | structures) just point to a catch tag to do the cleanup required | ||
| 60 | for their jumps. | ||
| 61 | |||
| 62 | catchtag structures are chained together in the C calling stack; | ||
| 63 | the `next' member points to the next outer catchtag. | ||
| 64 | |||
| 65 | A call like (throw TAG VAL) searches for a catchtag whose `tag' | ||
| 66 | member is TAG, and then unbinds to it. The `val' member is used to | ||
| 67 | hold VAL while the stack is unwound; `val' is returned as the value | ||
| 68 | of the catch form. | ||
| 69 | |||
| 70 | All the other members are concerned with restoring the interpreter | ||
| 71 | state. */ | ||
| 54 | struct catchtag | 72 | struct catchtag |
| 55 | { | 73 | { |
| 56 | Lisp_Object tag; | 74 | Lisp_Object tag; |
| @@ -115,9 +133,13 @@ Lisp_Object Vdebug_on_error; | |||
| 115 | is handled by the command loop's error handler. */ | 133 | is handled by the command loop's error handler. */ |
| 116 | int debug_on_quit; | 134 | int debug_on_quit; |
| 117 | 135 | ||
| 118 | /* Nonzero means we are trying to enter the debugger. | 136 | /* The value of num_nonmacro_input_chars as of the last time we |
| 119 | This is to prevent recursive attempts. */ | 137 | started to enter the debugger. If we decide to enter the debugger |
| 120 | int entering_debugger; | 138 | again when this is still equal to num_nonmacro_input_chars, then we |
| 139 | know that the debugger itself has an error, and we should just | ||
| 140 | signal the error instead of entering an infinite loop of debugger | ||
| 141 | invocations. */ | ||
| 142 | int when_entered_debugger; | ||
| 121 | 143 | ||
| 122 | Lisp_Object Vdebugger; | 144 | Lisp_Object Vdebugger; |
| 123 | 145 | ||
| @@ -143,7 +165,7 @@ init_eval () | |||
| 143 | Vquit_flag = Qnil; | 165 | Vquit_flag = Qnil; |
| 144 | debug_on_next_call = 0; | 166 | debug_on_next_call = 0; |
| 145 | lisp_eval_depth = 0; | 167 | lisp_eval_depth = 0; |
| 146 | entering_debugger = 0; | 168 | when_entered_debugger = 0; |
| 147 | } | 169 | } |
| 148 | 170 | ||
| 149 | Lisp_Object | 171 | Lisp_Object |
| @@ -155,7 +177,7 @@ call_debugger (arg) | |||
| 155 | if (specpdl_size + 40 > max_specpdl_size) | 177 | if (specpdl_size + 40 > max_specpdl_size) |
| 156 | max_specpdl_size = specpdl_size + 40; | 178 | max_specpdl_size = specpdl_size + 40; |
| 157 | debug_on_next_call = 0; | 179 | debug_on_next_call = 0; |
| 158 | entering_debugger = 1; | 180 | when_entered_debugger = num_nonmacro_input_chars; |
| 159 | return apply1 (Vdebugger, arg); | 181 | return apply1 (Vdebugger, arg); |
| 160 | } | 182 | } |
| 161 | 183 | ||
| @@ -874,9 +896,18 @@ unbind_catch (catch) | |||
| 874 | { | 896 | { |
| 875 | register int last_time; | 897 | register int last_time; |
| 876 | 898 | ||
| 899 | /* Restore the polling-suppression count. */ | ||
| 900 | if (catch->poll_suppress_count > poll_suppress_count) | ||
| 901 | abort (); | ||
| 902 | while (catch->poll_suppress_count < poll_suppress_count) | ||
| 903 | start_polling (); | ||
| 904 | |||
| 877 | do | 905 | do |
| 878 | { | 906 | { |
| 879 | last_time = catchlist == catch; | 907 | last_time = catchlist == catch; |
| 908 | |||
| 909 | /* Unwind the specpdl stack, and then restore the proper set of | ||
| 910 | handlers. */ | ||
| 880 | unbind_to (catchlist->pdlcount, Qnil); | 911 | unbind_to (catchlist->pdlcount, Qnil); |
| 881 | handlerlist = catchlist->handlerlist; | 912 | handlerlist = catchlist->handlerlist; |
| 882 | catchlist = catchlist->next; | 913 | catchlist = catchlist->next; |
| @@ -903,11 +934,6 @@ Both TAG and VALUE are evalled.") | |||
| 903 | { | 934 | { |
| 904 | if (EQ (c->tag, tag)) | 935 | if (EQ (c->tag, tag)) |
| 905 | { | 936 | { |
| 906 | /* Restore the polling-suppression count. */ | ||
| 907 | if (c->poll_suppress_count > poll_suppress_count) | ||
| 908 | abort (); | ||
| 909 | while (c->poll_suppress_count < poll_suppress_count) | ||
| 910 | start_polling (); | ||
| 911 | c->val = val; | 937 | c->val = val; |
| 912 | unbind_catch (c); | 938 | unbind_catch (c); |
| 913 | _longjmp (c->jmp, 1); | 939 | _longjmp (c->jmp, 1); |
| @@ -966,10 +992,21 @@ See also the function `signal' for more info.") | |||
| 966 | Lisp_Object val; | 992 | Lisp_Object val; |
| 967 | struct catchtag c; | 993 | struct catchtag c; |
| 968 | struct handler h; | 994 | struct handler h; |
| 969 | register Lisp_Object tem; | 995 | register Lisp_Object var, bodyform, handlers; |
| 996 | |||
| 997 | var = Fcar (args); | ||
| 998 | bodyform = Fcar (Fcdr (args)); | ||
| 999 | handlers = Fcdr (Fcdr (args)); | ||
| 1000 | CHECK_SYMBOL (var, 0); | ||
| 970 | 1001 | ||
| 971 | tem = Fcar (args); | 1002 | for (val = handlers; ! NILP (val); val = Fcdr (val)) |
| 972 | CHECK_SYMBOL (tem, 0); | 1003 | { |
| 1004 | Lisp_Object tem; | ||
| 1005 | tem = Fcar (val); | ||
| 1006 | if ((!NILP (tem)) && | ||
| 1007 | (!CONSP (tem) || (XTYPE (XCONS (tem)->car) != Lisp_Symbol))) | ||
| 1008 | error ("Invalid condition handler", tem); | ||
| 1009 | } | ||
| 973 | 1010 | ||
| 974 | c.tag = Qnil; | 1011 | c.tag = Qnil; |
| 975 | c.val = Qnil; | 1012 | c.val = Qnil; |
| @@ -984,28 +1021,23 @@ See also the function `signal' for more info.") | |||
| 984 | if (!NILP (h.var)) | 1021 | if (!NILP (h.var)) |
| 985 | specbind (h.var, Fcdr (c.val)); | 1022 | specbind (h.var, Fcdr (c.val)); |
| 986 | val = Fprogn (Fcdr (Fcar (c.val))); | 1023 | val = Fprogn (Fcdr (Fcar (c.val))); |
| 1024 | |||
| 1025 | /* Note that this just undoes the binding of h.var; whoever | ||
| 1026 | longjumped to us unwound the stack to c.pdlcount before | ||
| 1027 | throwing. */ | ||
| 987 | unbind_to (c.pdlcount, Qnil); | 1028 | unbind_to (c.pdlcount, Qnil); |
| 988 | return val; | 1029 | return val; |
| 989 | } | 1030 | } |
| 990 | c.next = catchlist; | 1031 | c.next = catchlist; |
| 991 | catchlist = &c; | 1032 | catchlist = &c; |
| 992 | h.var = Fcar (args); | ||
| 993 | h.handler = Fcdr (Fcdr (args)); | ||
| 994 | |||
| 995 | for (val = h.handler; ! NILP (val); val = Fcdr (val)) | ||
| 996 | { | ||
| 997 | tem = Fcar (val); | ||
| 998 | if ((!NILP (tem)) && | ||
| 999 | (!CONSP (tem) || (XTYPE (XCONS (tem)->car) != Lisp_Symbol))) | ||
| 1000 | error ("Invalid condition handler", tem); | ||
| 1001 | } | ||
| 1002 | 1033 | ||
| 1034 | h.var = var; | ||
| 1035 | h.handler = handlers; | ||
| 1003 | h.next = handlerlist; | 1036 | h.next = handlerlist; |
| 1004 | h.poll_suppress_count = poll_suppress_count; | ||
| 1005 | h.tag = &c; | 1037 | h.tag = &c; |
| 1006 | handlerlist = &h; | 1038 | handlerlist = &h; |
| 1007 | 1039 | ||
| 1008 | val = Feval (Fcar (Fcdr (args))); | 1040 | val = Feval (bodyform); |
| 1009 | catchlist = c.next; | 1041 | catchlist = c.next; |
| 1010 | handlerlist = h.next; | 1042 | handlerlist = h.next; |
| 1011 | return val; | 1043 | return val; |
| @@ -1037,7 +1069,6 @@ internal_condition_case (bfun, handlers, hfun) | |||
| 1037 | catchlist = &c; | 1069 | catchlist = &c; |
| 1038 | h.handler = handlers; | 1070 | h.handler = handlers; |
| 1039 | h.var = Qnil; | 1071 | h.var = Qnil; |
| 1040 | h.poll_suppress_count = poll_suppress_count; | ||
| 1041 | h.next = handlerlist; | 1072 | h.next = handlerlist; |
| 1042 | h.tag = &c; | 1073 | h.tag = &c; |
| 1043 | handlerlist = &h; | 1074 | handlerlist = &h; |
| @@ -1095,17 +1126,19 @@ See also the function `condition-case'.") | |||
| 1095 | return debugger_value; | 1126 | return debugger_value; |
| 1096 | #else | 1127 | #else |
| 1097 | if (EQ (clause, Qlambda)) | 1128 | if (EQ (clause, Qlambda)) |
| 1129 | { | ||
| 1130 | /* We can't return values to code which signalled an error, but we | ||
| 1131 | can continue code which has signalled a quit. */ | ||
| 1132 | if (EQ (sig, Qquit)) | ||
| 1133 | return Qnil; | ||
| 1134 | else | ||
| 1098 | error ("Returning a value from an error is no longer supported"); | 1135 | error ("Returning a value from an error is no longer supported"); |
| 1136 | } | ||
| 1099 | #endif | 1137 | #endif |
| 1100 | 1138 | ||
| 1101 | if (!NILP (clause)) | 1139 | if (!NILP (clause)) |
| 1102 | { | 1140 | { |
| 1103 | struct handler *h = handlerlist; | 1141 | struct handler *h = handlerlist; |
| 1104 | /* Restore the polling-suppression count. */ | ||
| 1105 | if (h->poll_suppress_count > poll_suppress_count) | ||
| 1106 | abort (); | ||
| 1107 | while (h->poll_suppress_count < poll_suppress_count) | ||
| 1108 | start_polling (); | ||
| 1109 | handlerlist = allhandlers; | 1142 | handlerlist = allhandlers; |
| 1110 | unbind_catch (h->tag); | 1143 | unbind_catch (h->tag); |
| 1111 | h->tag->val = Fcons (clause, Fcons (sig, data)); | 1144 | h->tag->val = Fcons (clause, Fcons (sig, data)); |
| @@ -1162,7 +1195,7 @@ find_handler_clause (handlers, conditions, sig, data, debugger_value_ptr) | |||
| 1162 | { | 1195 | { |
| 1163 | if (wants_debugger (Vstack_trace_on_error, conditions)) | 1196 | if (wants_debugger (Vstack_trace_on_error, conditions)) |
| 1164 | internal_with_output_to_temp_buffer ("*Backtrace*", Fbacktrace, Qnil); | 1197 | internal_with_output_to_temp_buffer ("*Backtrace*", Fbacktrace, Qnil); |
| 1165 | if (!entering_debugger | 1198 | if (when_entered_debugger < num_nonmacro_input_chars |
| 1166 | && (EQ (sig, Qquit) ? debug_on_quit | 1199 | && (EQ (sig, Qquit) ? debug_on_quit |
| 1167 | : wants_debugger (Vdebug_on_error, conditions))) | 1200 | : wants_debugger (Vdebug_on_error, conditions))) |
| 1168 | { | 1201 | { |
| @@ -2158,8 +2191,6 @@ Output stream used is value of `standard-output'.") | |||
| 2158 | extern Lisp_Object Vprint_level; | 2191 | extern Lisp_Object Vprint_level; |
| 2159 | struct gcpro gcpro1; | 2192 | struct gcpro gcpro1; |
| 2160 | 2193 | ||
| 2161 | entering_debugger = 0; | ||
| 2162 | |||
| 2163 | XFASTINT (Vprint_level) = 3; | 2194 | XFASTINT (Vprint_level) = 3; |
| 2164 | 2195 | ||
| 2165 | tail = Qnil; | 2196 | tail = Qnil; |