summaryrefslogtreecommitdiff
path: root/src/eval.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/eval.c')
-rw-r--r--src/eval.c190
1 files changed, 111 insertions, 79 deletions
diff --git a/src/eval.c b/src/eval.c
index 2a5b631f1c9..fbb3a7aad34 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -203,6 +203,8 @@ Lisp_Object Vmacro_declaration_function;
extern Lisp_Object Qrisky_local_variable;
+extern Lisp_Object Qfunction;
+
static Lisp_Object funcall_lambda P_ ((Lisp_Object, int, Lisp_Object*));
static void unwind_to_catch P_ ((struct catchtag *, Lisp_Object)) NO_RETURN;
@@ -540,7 +542,7 @@ usage: (setq [SYM VAL]...) */)
register Lisp_Object val, sym;
struct gcpro gcpro1;
- if (NILP(args))
+ if (NILP (args))
return Qnil;
args_left = args;
@@ -565,6 +567,8 @@ usage: (quote ARG) */)
(args)
Lisp_Object args;
{
+ if (!NILP (Fcdr (args)))
+ xsignal2 (Qwrong_number_of_arguments, Qquote, Flength (args));
return Fcar (args);
}
@@ -576,6 +580,8 @@ usage: (function ARG) */)
(args)
Lisp_Object args;
{
+ if (!NILP (Fcdr (args)))
+ xsignal2 (Qwrong_number_of_arguments, Qfunction, Flength (args));
return Fcar (args);
}
@@ -1038,10 +1044,10 @@ usage: (let VARLIST BODY...) */)
GCPRO2 (args, *temps);
gcpro2.nvars = 0;
- for (argnum = 0; !NILP (varlist); varlist = Fcdr (varlist))
+ for (argnum = 0; CONSP (varlist); varlist = XCDR (varlist))
{
QUIT;
- elt = Fcar (varlist);
+ elt = XCAR (varlist);
if (SYMBOLP (elt))
temps [argnum++] = Qnil;
else if (! NILP (Fcdr (Fcdr (elt))))
@@ -1053,9 +1059,9 @@ usage: (let VARLIST BODY...) */)
UNGCPRO;
varlist = Fcar (args);
- for (argnum = 0; !NILP (varlist); varlist = Fcdr (varlist))
+ for (argnum = 0; CONSP (varlist); varlist = XCDR (varlist))
{
- elt = Fcar (varlist);
+ elt = XCAR (varlist);
tem = temps[argnum++];
if (SYMBOLP (elt))
specbind (elt, tem);
@@ -1275,8 +1281,12 @@ unwind_to_catch (catch, value)
#if HAVE_X_WINDOWS
/* If x_catch_errors was done, turn it off now.
(First we give unbind_to a chance to do that.) */
+#if 0 /* This would disable x_catch_errors after x_connection_closed.
+ * The catch must remain in effect during that delicate
+ * state. --lorentey */
x_fully_uncatch_errors ();
#endif
+#endif
byte_stack_list = catch->byte_stack;
gcprolist = catch->gcpro;
@@ -1588,8 +1598,7 @@ internal_condition_case_2 (bfun, nargs, args, handlers, hfun)
static Lisp_Object find_handler_clause P_ ((Lisp_Object, Lisp_Object,
- Lisp_Object, Lisp_Object,
- Lisp_Object *));
+ Lisp_Object, Lisp_Object));
DEFUN ("signal", Fsignal, Ssignal, 2, 2, 0,
doc: /* Signal an error. Args are ERROR-SYMBOL and associated DATA.
@@ -1615,7 +1624,6 @@ See also the function `condition-case'. */)
Lisp_Object conditions;
extern int gc_in_progress;
extern int waiting_for_input;
- Lisp_Object debugger_value;
Lisp_Object string;
Lisp_Object real_error_symbol;
struct backtrace *bp;
@@ -1673,7 +1681,7 @@ See also the function `condition-case'. */)
register Lisp_Object clause;
clause = find_handler_clause (handlerlist->handler, conditions,
- error_symbol, data, &debugger_value);
+ error_symbol, data);
if (EQ (clause, Qlambda))
{
@@ -1704,7 +1712,7 @@ See also the function `condition-case'. */)
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, &debugger_value);
+ find_handler_clause (Qerror, conditions, error_symbol, data);
if (catchlist != 0)
Fthrow (Qtop_level, Qt);
@@ -1856,75 +1864,54 @@ 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.
-
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)
+find_handler_clause (handlers, conditions, sig, data)
Lisp_Object handlers, conditions, sig, data;
- Lisp_Object *debugger_value_ptr;
{
register Lisp_Object h;
register Lisp_Object tem;
+ int debugger_called = 0;
+ int debugger_considered = 0;
- if (EQ (handlers, Qt)) /* t is used by handlers for all conditions, set up by C code. */
+ /* 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. */
{
- int debugger_called = 0;
- Lisp_Object sig_symbol, combined_data;
- /* This is set to 1 if we are handling a memory-full error,
- because these must not run the debugger.
- (There is no room in memory to do that!) */
- int no_debugger = 0;
-
- if (NILP (sig))
- {
- combined_data = data;
- sig_symbol = Fcar (data);
- no_debugger = 1;
- }
- else
- {
- combined_data = Fcons (sig, data);
- sig_symbol = sig;
- }
-
- if (wants_debugger (Vstack_trace_on_error, conditions))
+ if (!NILP (sig) && wants_debugger (Vstack_trace_on_error, conditions))
{
max_specpdl_size++;
-#ifdef PROTOTYPES
+ #ifdef PROTOTYPES
internal_with_output_to_temp_buffer ("*Backtrace*",
(Lisp_Object (*) (Lisp_Object)) Fbacktrace,
Qnil);
-#else
+ #else
internal_with_output_to_temp_buffer ("*Backtrace*",
Fbacktrace, Qnil);
-#endif
+ #endif
max_specpdl_size--;
}
- if (! no_debugger
- /* Don't try to run the debugger with interrupts blocked.
- The editing loop would return anyway. */
- && ! INPUT_BLOCKED_P
- && (EQ (sig_symbol, Qquit)
- ? debug_on_quit
- : wants_debugger (Vdebug_on_error, conditions))
- && ! skip_debugger (conditions, combined_data)
- && when_entered_debugger < num_nonmacro_input_events)
+
+ if (!debugger_considered)
{
- *debugger_value_ptr
- = call_debugger (Fcons (Qerror,
- Fcons (combined_data, Qnil)));
- debugger_called = 1;
+ 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))
{
@@ -1933,6 +1920,7 @@ find_handler_clause (handlers, conditions, sig, data, debugger_value_ptr)
return Qt;
}
}
+
for (h = handlers; CONSP (h); h = Fcdr (h))
{
Lisp_Object handler, condit;
@@ -1951,18 +1939,55 @@ find_handler_clause (handlers, conditions, sig, data, debugger_value_ptr)
/* Handle a list of condition names in handler HANDLER. */
else if (CONSP (condit))
{
- while (CONSP (condit))
+ Lisp_Object tail;
+ for (tail = condit; CONSP (tail); tail = XCDR (tail))
{
- tem = Fmemq (Fcar (condit), conditions);
+ tem = Fmemq (Fcar (tail), conditions);
if (!NILP (tem))
- return handler;
- condit = XCDR (condit);
+ {
+ /* 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 Qnil;
}
+/* Call the debugger if calling it is currently enabled for CONDITIONS.
+ SIG and DATA describe the signal, as in find_handler_clause. */
+
+int
+maybe_call_debugger (conditions, sig, data)
+ Lisp_Object conditions, sig, data;
+{
+ Lisp_Object combined_data;
+
+ combined_data = Fcons (sig, data);
+
+ if (
+ /* Don't try to run the debugger with interrupts blocked.
+ The editing loop would return anyway. */
+ ! INPUT_BLOCKED_P
+ /* Does user wants to enter debugger for this kind of error? */
+ && (EQ (sig, Qquit)
+ ? debug_on_quit
+ : wants_debugger (Vdebug_on_error, conditions))
+ && ! skip_debugger (conditions, combined_data)
+ /* rms: what's this for? */
+ && when_entered_debugger < num_nonmacro_input_events)
+ {
+ call_debugger (Fcons (Qerror, Fcons (combined_data, Qnil)));
+ return 1;
+ }
+
+ return 0;
+}
+
/* dump an error message; called like printf */
/* VARARGS 1 */
@@ -2027,42 +2052,49 @@ then strings and vectors are not accepted. */)
{
register Lisp_Object fun;
register Lisp_Object funcar;
+ Lisp_Object if_prop = Qnil;
fun = function;
- fun = indirect_function (fun);
- if (EQ (fun, Qunbound))
+ fun = indirect_function (fun); /* Check cycles. */
+ if (NILP (fun) || EQ (fun, Qunbound))
return Qnil;
+ /* Check an `interactive-form' property if present, analogous to the
+ function-documentation property. */
+ fun = function;
+ while (SYMBOLP (fun))
+ {
+ Lisp_Object tmp = Fget (fun, intern ("interactive-form"));
+ if (!NILP (tmp))
+ if_prop = Qt;
+ fun = Fsymbol_function (fun);
+ }
+
/* Emacs primitives are interactive if their DEFUN specifies an
interactive spec. */
if (SUBRP (fun))
- {
- if (XSUBR (fun)->prompt)
- return Qt;
- else
- return Qnil;
- }
+ return XSUBR (fun)->intspec ? Qt : if_prop;
/* Bytecode objects are interactive if they are long enough to
have an element whose index is COMPILED_INTERACTIVE, which is
where the interactive spec is stored. */
else if (COMPILEDP (fun))
return ((ASIZE (fun) & PSEUDOVECTOR_SIZE_MASK) > COMPILED_INTERACTIVE
- ? Qt : Qnil);
+ ? Qt : if_prop);
/* Strings and vectors are keyboard macros. */
- if (NILP (for_call_interactively) && (STRINGP (fun) || VECTORP (fun)))
- return Qt;
+ if (STRINGP (fun) || VECTORP (fun))
+ return (NILP (for_call_interactively) ? Qt : Qnil);
/* Lists may represent commands. */
if (!CONSP (fun))
return Qnil;
funcar = XCAR (fun);
if (EQ (funcar, Qlambda))
- return Fassq (Qinteractive, Fcdr (XCDR (fun)));
+ return !NILP (Fassq (Qinteractive, Fcdr (XCDR (fun)))) ? Qt : if_prop;
if (EQ (funcar, Qautoload))
- return Fcar (Fcdr (Fcdr (XCDR (fun))));
+ return !NILP (Fcar (Fcdr (Fcdr (XCDR (fun))))) ? Qt : if_prop;
else
return Qnil;
}
@@ -2173,7 +2205,7 @@ do_autoload (fundef, funname)
The value saved here is to be restored into Vautoload_queue. */
record_unwind_protect (un_autoload, Vautoload_queue);
Vautoload_queue = Qt;
- Fload (Fcar (Fcdr (fundef)), Qnil, noninteractive ? Qt : Qnil, Qnil, Qt);
+ Fload (Fcar (Fcdr (fundef)), Qnil, Qt, Qnil, Qt);
/* Once loading finishes, don't undo it. */
Vautoload_queue = Qt;
@@ -3232,7 +3264,6 @@ void
specbind (symbol, value)
Lisp_Object symbol, value;
{
- Lisp_Object ovalue;
Lisp_Object valcontents;
CHECK_SYMBOL (symbol);
@@ -3252,16 +3283,13 @@ specbind (symbol, value)
}
else
{
- Lisp_Object valcontents;
-
- ovalue = find_symbol_value (symbol);
+ Lisp_Object ovalue = find_symbol_value (symbol);
specpdl_ptr->func = 0;
specpdl_ptr->old_value = ovalue;
valcontents = XSYMBOL (symbol)->value;
if (BUFFER_LOCAL_VALUEP (valcontents)
- || SOME_BUFFER_LOCAL_VALUEP (valcontents)
|| BUFFER_OBJFWDP (valcontents))
{
Lisp_Object where, current_buffer;
@@ -3272,7 +3300,7 @@ specbind (symbol, value)
buffer's or frame's value we are saving. */
if (!NILP (Flocal_variable_p (symbol, Qnil)))
where = current_buffer;
- else if (!BUFFER_OBJFWDP (valcontents)
+ else if (BUFFER_LOCAL_VALUEP (valcontents)
&& XBUFFER_LOCAL_VALUE (valcontents)->found_for_frame)
where = XBUFFER_LOCAL_VALUE (valcontents)->frame;
else
@@ -3300,10 +3328,14 @@ specbind (symbol, value)
specpdl_ptr->symbol = symbol;
specpdl_ptr++;
- if (BUFFER_OBJFWDP (ovalue) || KBOARD_OBJFWDP (ovalue))
- store_symval_forwarding (symbol, ovalue, value, NULL);
- else
- set_internal (symbol, value, 0, 1);
+ /* We used to do
+ if (BUFFER_OBJFWDP (ovalue) || KBOARD_OBJFWDP (ovalue))
+ store_symval_forwarding (symbol, ovalue, value, NULL);
+ else
+ but ovalue comes from find_symbol_value which should never return
+ such an internal value. */
+ eassert (!(BUFFER_OBJFWDP (ovalue) || KBOARD_OBJFWDP (ovalue)));
+ set_internal (symbol, value, 0, 1);
}
}