aboutsummaryrefslogtreecommitdiffstats
path: root/src/eval.c
diff options
context:
space:
mode:
authorRichard M. Stallman <[email protected]>2005-06-25 14:37:47 +0000
committerRichard M. Stallman <[email protected]>2005-06-25 14:37:47 +0000
commit9f5903bb77b7f1f1e7a6598b3c496961e0ee02ea (patch)
treebeed15f824cc18d2b0eaf9a4604fcd6181ccf485 /src/eval.c
parent7bbae30c23e8fc44bc3202c5e30ac593baca659b (diff)
(call_debugger): Take full care of extending stack limits
to make space for the debugger, and restore the change afterward. Bind debug-on-error to nil. (restore_stack_limits): New subroutine. (Fsignal): Extend specpdl bound along with eval depth bound, for calling edebug. Don't do either one, for calling debugger. (find_handler_clause): Don't bind debug-on-error here. Don't unbind anything either. Temporarily advance max_specpdl_size for calling internal_with_output_to_temp_buffer. (grow_specpdl): Don't alter max_specpdl_size before signaling an error. (syms_of_eval) <max-specpdl-size>: Doc fix.
Diffstat (limited to 'src/eval.c')
-rw-r--r--src/eval.c71
1 files changed, 48 insertions, 23 deletions
diff --git a/src/eval.c b/src/eval.c
index 8ad289fd51..c33021da7b 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -227,6 +227,18 @@ init_eval ()
when_entered_debugger = -1;
}
+/* unwind-protect function used by call_debugger. */
+
+static Lisp_Object
+restore_stack_limits (data)
+ Lisp_Object data;
+{
+ max_specpdl_size = XINT (XCAR (data));
+ max_lisp_eval_depth = XINT (XCDR (data));
+}
+
+/* Call the Lisp debugger, giving it argument ARG. */
+
Lisp_Object
call_debugger (arg)
Lisp_Object arg;
@@ -234,12 +246,22 @@ call_debugger (arg)
int debug_while_redisplaying;
int count = SPECPDL_INDEX ();
Lisp_Object val;
+ int old_max = max_specpdl_size;
- if (lisp_eval_depth + 20 > max_lisp_eval_depth)
- max_lisp_eval_depth = lisp_eval_depth + 20;
+ /* Temporarily bump up the stack limits,
+ so the debugger won't run out of stack. */
- if (specpdl_size + 40 > max_specpdl_size)
- max_specpdl_size = specpdl_size + 40;
+ max_specpdl_size += 1;
+ record_unwind_protect (restore_stack_limits,
+ Fcons (make_number (old_max),
+ make_number (max_lisp_eval_depth)));
+ max_specpdl_size = old_max;
+
+ if (lisp_eval_depth + 40 > max_lisp_eval_depth)
+ max_lisp_eval_depth = lisp_eval_depth + 40;
+
+ if (SPECPDL_INDEX () + 100 > max_specpdl_size)
+ max_specpdl_size = SPECPDL_INDEX () + 100;
#ifdef HAVE_X_WINDOWS
if (display_hourglass_p)
@@ -256,6 +278,7 @@ call_debugger (arg)
specbind (intern ("debugger-may-continue"),
debug_while_redisplaying ? Qnil : Qt);
specbind (Qinhibit_redisplay, Qnil);
+ specbind (Qdebug_on_error, Qnil);
#if 0 /* Binding this prevents execution of Lisp code during
redisplay, which necessarily leads to display problems. */
@@ -1533,7 +1556,16 @@ See also the function `condition-case'. */)
/* This hook is used by edebug. */
if (! NILP (Vsignal_hook_function)
&& ! NILP (error_symbol))
- call2 (Vsignal_hook_function, error_symbol, data);
+ {
+ /* Edebug takes care of restoring these variables when it exits. */
+ if (lisp_eval_depth + 20 > max_lisp_eval_depth)
+ max_lisp_eval_depth = lisp_eval_depth + 20;
+
+ if (SPECPDL_INDEX () + 40 > max_specpdl_size)
+ max_specpdl_size = SPECPDL_INDEX () + 40;
+
+ call2 (Vsignal_hook_function, error_symbol, data);
+ }
conditions = Fget (real_error_symbol, Qerror_conditions);
@@ -1555,12 +1587,6 @@ See also the function `condition-case'. */)
{
register Lisp_Object clause;
- if (lisp_eval_depth + 20 > max_lisp_eval_depth)
- max_lisp_eval_depth = lisp_eval_depth + 20;
-
- if (specpdl_size + 40 > max_specpdl_size)
- max_specpdl_size = specpdl_size + 40;
-
clause = find_handler_clause (handlerlist->handler, conditions,
error_symbol, data, &debugger_value);
@@ -1673,7 +1699,11 @@ skip_debugger (conditions, data)
= SIG is nil, and DATA is (SYMBOL . REST-OF-DATA).
This is for memory-full errors only.
- Store value returned from debugger into *DEBUGGER_VALUE_PTR. */
+ Store value returned from debugger into *DEBUGGER_VALUE_PTR.
+
+ We need to increase max_specpdl_size temporarily around
+ anything we do that can push on the specpdl, so as not to get
+ a second error here in case we're handling specpdl overflow. */
static Lisp_Object
find_handler_clause (handlers, conditions, sig, data, debugger_value_ptr)
@@ -1691,7 +1721,6 @@ find_handler_clause (handlers, conditions, sig, data, debugger_value_ptr)
|| !NILP (Vdebug_on_signal)) /* This says call debugger even if
there is a handler. */
{
- int count = SPECPDL_INDEX ();
int debugger_called = 0;
Lisp_Object sig_symbol, combined_data;
/* This is set to 1 if we are handling a memory-full error,
@@ -1713,6 +1742,7 @@ find_handler_clause (handlers, conditions, sig, data, debugger_value_ptr)
if (wants_debugger (Vstack_trace_on_error, conditions))
{
+ max_specpdl_size++;
#ifdef PROTOTYPES
internal_with_output_to_temp_buffer ("*Backtrace*",
(Lisp_Object (*) (Lisp_Object)) Fbacktrace,
@@ -1721,6 +1751,7 @@ find_handler_clause (handlers, conditions, sig, data, debugger_value_ptr)
internal_with_output_to_temp_buffer ("*Backtrace*",
Fbacktrace, Qnil);
#endif
+ max_specpdl_size--;
}
if (! no_debugger
&& (EQ (sig_symbol, Qquit)
@@ -1729,7 +1760,6 @@ find_handler_clause (handlers, conditions, sig, data, debugger_value_ptr)
&& ! skip_debugger (conditions, combined_data)
&& when_entered_debugger < num_nonmacro_input_events)
{
- specbind (Qdebug_on_error, Qnil);
*debugger_value_ptr
= call_debugger (Fcons (Qerror,
Fcons (combined_data, Qnil)));
@@ -1739,7 +1769,7 @@ find_handler_clause (handlers, conditions, sig, data, debugger_value_ptr)
if (EQ (handlers, Qerror))
{
if (debugger_called)
- return unbind_to (count, Qlambda);
+ return Qlambda;
return Qt;
}
}
@@ -3019,13 +3049,8 @@ grow_specpdl ()
if (max_specpdl_size < 400)
max_specpdl_size = 400;
if (specpdl_size >= max_specpdl_size)
- {
- if (!NILP (Vdebug_on_error))
- /* Leave room for some specpdl in the debugger. */
- max_specpdl_size = specpdl_size + 100;
- Fsignal (Qerror,
- Fcons (build_string ("Variable binding depth exceeds max-specpdl-size"), Qnil));
- }
+ Fsignal (Qerror,
+ Fcons (build_string ("Variable binding depth exceeds max-specpdl-size"), Qnil));
}
specpdl_size *= 2;
if (specpdl_size > max_specpdl_size)
@@ -3333,7 +3358,7 @@ syms_of_eval ()
{
DEFVAR_INT ("max-specpdl-size", &max_specpdl_size,
doc: /* *Limit on number of Lisp variable bindings & unwind-protects.
-If Lisp code tries to make more than this many at once,
+If Lisp code tries to increase the total number past this amount,
an error is signaled.
You can safely use a value considerably larger than the default value,
if that proves inconveniently small. However, if you increase it too far,