Let the debugger continue to the normal handler.

* src/eval.c (maybe_call_debugger): Declare before new use.
(find_handler_clause): Don't call debugger any more.
Ignore Vstack_trace_on_error.
Use XCAR/XCDR.
(syms_of_eval): Remove Vstack_trace_on_error.
(Fsignal): Only modify handlerlist when we know we need to do it.
Call the debugger when necessary.
* src/globals.h (Vstack_trace_on_error): Remove.

Fixes: debbugs:7825
This commit is contained in:
Stefan Monnier 2011-01-26 15:02:07 -05:00
parent 6608a7d8fb
commit e7f7fbaa11
5 changed files with 67 additions and 117 deletions

View file

@ -692,6 +692,11 @@ sc.el, x-menu.el, rnews.el, rnewspost.el
* Lisp changes in Emacs 24.1
** Removed the stack-trace-on-error variable.
Also the debugger can now "continue" from an error, which means it will jump
to the error handler as if the debugger had not been invoked instead of
jumping all the way to the top-level.
** New function `read-char-choice' reads a restricted set of characters,
discarding any inputs not inside the set.

View file

@ -166,12 +166,6 @@ Leaving \"Default\" unchecked is equivalent with specifying a default of
(max-mini-window-height limits
(choice (const :tag "quarter screen" nil)
number) "23.1")
(stack-trace-on-error debug
(choice (const :tag "off")
(repeat :menu-tag "When"
:value (nil)
(symbol :format "%v"))
(const :tag "always" t)))
(debug-on-error debug
(choice (const :tag "off")
(repeat :menu-tag "When"

View file

@ -1,3 +1,15 @@
2011-01-26 Stefan Monnier <monnier@iro.umontreal.ca>
Let the debugger continue to the normal handler (bug#7825).
* eval.c (maybe_call_debugger): Declare before new use.
(find_handler_clause): Don't call debugger any more.
Ignore Vstack_trace_on_error.
Use XCAR/XCDR.
(syms_of_eval): Remove Vstack_trace_on_error.
(Fsignal): Only modify handlerlist when we know we need to do it.
Call the debugger when necessary.
* globals.h (Vstack_trace_on_error): Remove.
2011-01-26 Chong Yidong <cyd@stupidchicken.com>
* font.c (font_parse_fcname): Rewrite GTK font name parser.

View file

@ -1557,6 +1557,8 @@ internal_condition_case_n (Lisp_Object (*bfun) (int, Lisp_Object*),
static Lisp_Object find_handler_clause (Lisp_Object, Lisp_Object,
Lisp_Object, Lisp_Object);
static int maybe_call_debugger (Lisp_Object conditions, Lisp_Object sig,
Lisp_Object data);
DEFUN ("signal", Fsignal, Ssignal, 2, 2, 0,
doc: /* Signal an error. Args are ERROR-SYMBOL and associated DATA.
@ -1577,10 +1579,12 @@ See also the function `condition-case'. */)
/* When memory is full, ERROR-SYMBOL is nil,
and DATA is (REAL-ERROR-SYMBOL . REAL-DATA).
That is a special case--don't do this in other situations. */
register struct handler *allhandlers = handlerlist;
Lisp_Object conditions;
Lisp_Object string;
Lisp_Object real_error_symbol;
Lisp_Object real_error_symbol
= (NILP (error_symbol) ? Fcar (data) : error_symbol);
register Lisp_Object clause = Qnil;
struct handler *h;
struct backtrace *bp;
immediate_quit = handling_signal = 0;
@ -1588,11 +1592,6 @@ See also the function `condition-case'. */)
if (gc_in_progress || waiting_for_input)
abort ();
if (NILP (error_symbol))
real_error_symbol = Fcar (data);
else
real_error_symbol = error_symbol;
#if 0 /* rms: I don't know why this was here,
but it is surely wrong for an error that is handled. */
#ifdef HAVE_WINDOW_SYSTEM
@ -1631,49 +1630,49 @@ See also the function `condition-case'. */)
Vsignaling_function = *bp->function;
}
for (; handlerlist; handlerlist = handlerlist->next)
for (h = handlerlist; h; h = h->next)
{
register Lisp_Object clause;
clause = find_handler_clause (handlerlist->handler, conditions,
clause = find_handler_clause (h->handler, conditions,
error_symbol, data);
if (EQ (clause, Qlambda))
{
/* We can't return values to code which signaled an error, but we
can continue code which has signaled a quit. */
if (EQ (real_error_symbol, Qquit))
return Qnil;
else
error ("Cannot return from the debugger in an error");
}
if (!NILP (clause))
{
Lisp_Object unwind_data;
struct handler *h = handlerlist;
handlerlist = allhandlers;
if (NILP (error_symbol))
unwind_data = data;
else
unwind_data = Fcons (error_symbol, data);
h->chosen_clause = clause;
unwind_to_catch (h->tag, unwind_data);
}
break;
}
if (/* Don't run the debugger for a memory-full error.
(There is no room in memory to do that!) */
!NILP (error_symbol)
&& (!NILP (Vdebug_on_signal)
/* If no handler is present now, try to run the debugger. */
|| NILP (clause)
/* Special handler that means "print a message and run debugger
if requested". */
|| EQ (h->handler, Qerror)))
{
int debugger_called
= maybe_call_debugger (conditions, error_symbol, data);
/* We can't return values to code which signaled an error, but we
can continue code which has signaled a quit. */
if (debugger_called && EQ (real_error_symbol, Qquit))
return Qnil;
}
handlerlist = allhandlers;
/* If no handler is present now, try to run the debugger,
and if that fails, throw to top level. */
find_handler_clause (Qerror, conditions, error_symbol, data);
if (catchlist != 0)
Fthrow (Qtop_level, Qt);
if (!NILP (clause))
{
Lisp_Object unwind_data
= (NILP (error_symbol) ? data : Fcons (error_symbol, data));
h->chosen_clause = clause;
unwind_to_catch (h->tag, unwind_data);
}
else
{
if (catchlist != 0)
Fthrow (Qtop_level, Qt);
}
if (! NILP (error_symbol))
data = Fcons (error_symbol, data);
string = Ferror_message_string (data);
fatal ("%s", SDATA (string), 0);
}
@ -1848,63 +1847,24 @@ find_handler_clause (Lisp_Object handlers, Lisp_Object conditions,
Lisp_Object sig, Lisp_Object data)
{
register Lisp_Object h;
register Lisp_Object tem;
int debugger_called = 0;
int debugger_considered = 0;
/* t is used by handlers for all conditions, set up by C code. */
if (EQ (handlers, Qt))
return Qt;
/* Don't run the debugger for a memory-full error.
(There is no room in memory to do that!) */
if (NILP (sig))
debugger_considered = 1;
/* error is used similarly, but means print an error message
and run the debugger if that is enabled. */
if (EQ (handlers, Qerror)
|| !NILP (Vdebug_on_signal)) /* This says call debugger even if
there is a handler. */
if (EQ (handlers, Qerror))
return Qt;
for (h = handlers; CONSP (h); h = XCDR (h))
{
if (!NILP (sig) && wants_debugger (Vstack_trace_on_error, conditions))
{
max_lisp_eval_depth += 15;
max_specpdl_size++;
if (noninteractive)
Fbacktrace ();
else
internal_with_output_to_temp_buffer
("*Backtrace*",
(Lisp_Object (*) (Lisp_Object)) Fbacktrace,
Qnil);
max_specpdl_size--;
max_lisp_eval_depth -= 15;
}
Lisp_Object handler = XCAR (h);
Lisp_Object condit, tem;
if (!debugger_considered)
{
debugger_considered = 1;
debugger_called = maybe_call_debugger (conditions, sig, data);
}
/* If there is no handler, return saying whether we ran the debugger. */
if (EQ (handlers, Qerror))
{
if (debugger_called)
return Qlambda;
return Qt;
}
}
for (h = handlers; CONSP (h); h = Fcdr (h))
{
Lisp_Object handler, condit;
handler = Fcar (h);
if (!CONSP (handler))
continue;
condit = Fcar (handler);
condit = XCAR (handler);
/* Handle a single condition name in handler HANDLER. */
if (SYMBOLP (condit))
{
@ -1918,15 +1878,9 @@ find_handler_clause (Lisp_Object handlers, Lisp_Object conditions,
Lisp_Object tail;
for (tail = condit; CONSP (tail); tail = XCDR (tail))
{
tem = Fmemq (Fcar (tail), conditions);
tem = Fmemq (XCAR (tail), conditions);
if (!NILP (tem))
{
/* This handler is going to apply.
Does it allow the debugger to run first? */
if (! debugger_considered && !NILP (Fmemq (Qdebug, condit)))
maybe_call_debugger (conditions, sig, data);
return handler;
}
return handler;
}
}
}
@ -1943,7 +1897,6 @@ verror (const char *m, va_list ap)
EMACS_INT size = 200;
int mlen;
char *buffer = buf;
char *args[3];
int allocated = 0;
Lisp_Object string;
@ -3523,14 +3476,6 @@ before making `inhibit-quit' nil. */);
Qdebug = intern_c_string ("debug");
staticpro (&Qdebug);
DEFVAR_LISP ("stack-trace-on-error", Vstack_trace_on_error,
doc: /* *Non-nil means errors display a backtrace buffer.
More precisely, this happens for any error that is handled
by the editor command loop.
If the value is a list, an error only means to display a backtrace
if one of its condition symbols appears in the list. */);
Vstack_trace_on_error = Qnil;
DEFVAR_LISP ("debug-on-error", Vdebug_on_error,
doc: /* *Non-nil means enter debugger if an error is signaled.
Does not apply to errors handled by `condition-case' or those

View file

@ -434,10 +434,6 @@ struct emacs_globals
continue the interrupted redisplay. */
int f_debugger_may_continue;
/* List of conditions (non-nil atom means all) which cause a backtrace
if an error is handled by the command loop's error handler. */
Lisp_Object f_Vstack_trace_on_error;
/* List of conditions (non-nil atom means all) which enter the debugger
if an error is handled by the command loop's error handler. */
Lisp_Object f_Vdebug_on_error;
@ -2326,8 +2322,6 @@ extern struct emacs_globals globals;
globals.f_Vsource_directory
#define Vspecial_event_map \
globals.f_Vspecial_event_map
#define Vstack_trace_on_error \
globals.f_Vstack_trace_on_error
#define Vstandard_display_table \
globals.f_Vstandard_display_table
#define Vstandard_input \