/* Evaluator for GNU Emacs Lisp interpreter.
Copyright (C) 1985, 1986, 1987, 1993, 1994, 1995, 1999, 2000, 2001,
- 2002, 2004, 2005 Free Software Foundation, Inc.
+ 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
This file is part of GNU Emacs.
You should have received a copy of the GNU General Public License
along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
#include <config.h>
#include "dispextern.h"
#include <setjmp.h>
+#if HAVE_X_WINDOWS
+#include "xterm.h"
+#endif
+
/* This definition is duplicated in alloc.c and keyboard.c */
/* Putting it in lisp.h makes cc bomb out! */
/* Non-nil means record all fset's and provide's, to be undone
if the file being autoloaded is not fully loaded.
They are recorded by being consed onto the front of Vautoload_queue:
- (FUN . ODEF) for a defun, (OFEATURES . nil) for a provide. */
+ (FUN . ODEF) for a defun, (0 . OFEATURES) for a provide. */
Lisp_Object Vautoload_queue;
/* Pointer to first unused element in specpdl. */
-volatile struct specbinding *specpdl_ptr;
+struct specbinding *specpdl_ptr;
/* Maximum size allowed for specpdl allocation */
Lisp_Object Vmacro_declaration_function;
+extern Lisp_Object Qrisky_local_variable;
static Lisp_Object funcall_lambda P_ ((Lisp_Object, int, Lisp_Object*));
-
+static void unwind_to_catch P_ ((struct catchtag *, Lisp_Object)) NO_RETURN;
+
+#if __GNUC__
+/* "gcc -O3" enables automatic function inlining, which optimizes out
+ the arguments for the invocations of these functions, whereas they
+ expect these values on the stack. */
+Lisp_Object apply1 () __attribute__((noinline));
+Lisp_Object call2 () __attribute__((noinline));
+#endif
+\f
void
init_eval_once ()
{
specpdl_size = 50;
specpdl = (struct specbinding *) xmalloc (specpdl_size * sizeof (struct specbinding));
specpdl_ptr = specpdl;
+ /* Don't forget to update docs (lispref node "Local Variables"). */
max_specpdl_size = 1000;
max_lisp_eval_depth = 300;
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));
+ return Qnil;
+}
+
+/* Call the Lisp debugger, giving it argument ARG. */
+
Lisp_Object
call_debugger (arg)
Lisp_Object 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)
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. */
}
DEFUN ("prog2", Fprog2, Sprog2, 2, UNEVALLED, 0,
- doc: /* Eval X, Y and BODY sequentially; value from Y.
-The value of Y is saved during the evaluation of the remaining args,
-whose values are discarded.
-usage: (prog2 X Y BODY...) */)
+ doc: /* Eval FORM1, FORM2 and BODY sequentially; value from FORM2.
+The value of FORM2 is saved during the evaluation of the
+remaining args, whose values are discarded.
+usage: (prog2 FORM1 FORM2 BODY...) */)
(args)
Lisp_Object args;
{
DEFUN ("interactive-p", Finteractive_p, Sinteractive_p, 0, 0, 0,
doc: /* Return t if the function was run directly by user input.
-This means that the function was called with call-interactively (which
-includes being called as the binding of a key)
+This means that the function was called with `call-interactively'
+\(which includes being called as the binding of a key)
and input is currently coming from the keyboard (not in keyboard macro),
and Emacs is not running in batch mode (`noninteractive' is nil).
DEFUN ("called-interactively-p", Fcalled_interactively_p, Scalled_interactively_p, 0, 0, 0,
- doc: /* Return t if the function using this was called with call-interactively.
+ doc: /* Return t if the function using this was called with `call-interactively'.
This is used for implementing advice and other function-modifying
features of Emacs.
The cleanest way to test whether your function was called with
-`call-interactively', the way to do that is by adding an extra
-optional argument, and making the `interactive' spec specify non-nil
-unconditionally for that argument. (`p' is a good way to do this.) */)
+`call-interactively' is by adding an extra optional argument,
+and making the `interactive' spec specify non-nil unconditionally
+for that argument. (`p' is a good way to do this.) */)
()
{
return interactive_p (1) ? Qt : Qnil;
/* If this isn't a byte-compiled function, there may be a frame at
the top for Finteractive_p. If so, skip it. */
- fun = Findirect_function (*btp->function);
+ fun = Findirect_function (*btp->function, Qnil);
if (SUBRP (fun) && (XSUBR (fun) == &Sinteractive_p
|| XSUBR (fun) == &Scalled_interactively_p))
btp = btp->next;
a special form, ignoring frames for Finteractive_p and/or
Fbytecode at the top. If this frame is for a built-in function
(such as load or eval-region) return nil. */
- fun = Findirect_function (*btp->function);
+ fun = Findirect_function (*btp->function, Qnil);
if (exclude_subrs_p && SUBRP (fun))
return 0;
DEFUN ("defvaralias", Fdefvaralias, Sdefvaralias, 2, 3, 0,
- doc: /* Make SYMBOL a variable alias for symbol ALIASED.
-Setting the value of SYMBOL will subsequently set the value of ALIASED,
-and getting the value of SYMBOL will return the value ALIASED has.
-Third arg DOCSTRING, if non-nil, is documentation for SYMBOL. If it is
-omitted or nil, SYMBOL gets the documentation string of ALIASED, or of the
-variable at the end of the chain of aliases, if ALIASED is itself an alias.
-The return value is ALIASED. */)
- (symbol, aliased, docstring)
- Lisp_Object symbol, aliased, docstring;
+ doc: /* Make NEW-ALIAS a variable alias for symbol BASE-VARIABLE.
+Aliased variables always have the same value; setting one sets the other.
+Third arg DOCSTRING, if non-nil, is documentation for NEW-ALIAS. If it is
+ omitted or nil, NEW-ALIAS gets the documentation string of BASE-VARIABLE,
+ or of the variable at the end of the chain of aliases, if BASE-VARIABLE is
+ itself an alias.
+The return value is BASE-VARIABLE. */)
+ (new_alias, base_variable, docstring)
+ Lisp_Object new_alias, base_variable, docstring;
{
struct Lisp_Symbol *sym;
- CHECK_SYMBOL (symbol);
- CHECK_SYMBOL (aliased);
+ CHECK_SYMBOL (new_alias);
+ CHECK_SYMBOL (base_variable);
- if (SYMBOL_CONSTANT_P (symbol))
+ if (SYMBOL_CONSTANT_P (new_alias))
error ("Cannot make a constant an alias");
- sym = XSYMBOL (symbol);
+ sym = XSYMBOL (new_alias);
sym->indirect_variable = 1;
- sym->value = aliased;
- sym->constant = SYMBOL_CONSTANT_P (aliased);
- LOADHIST_ATTACH (symbol);
+ sym->value = base_variable;
+ sym->constant = SYMBOL_CONSTANT_P (base_variable);
+ LOADHIST_ATTACH (new_alias);
if (!NILP (docstring))
- Fput (symbol, Qvariable_documentation, docstring);
+ Fput (new_alias, Qvariable_documentation, docstring);
else
- Fput (symbol, Qvariable_documentation, Qnil);
+ Fput (new_alias, Qvariable_documentation, Qnil);
- return aliased;
+ return base_variable;
}
DEFUN ("defvar", Fdefvar, Sdefvar, 1, UNEVALLED, 0,
- doc: /* Define SYMBOL as a variable.
+ doc: /* Define SYMBOL as a variable, and return SYMBOL.
You are not required to define a variable in order to use it,
but the definition can supply documentation and an initial value
in a way that tags can recognize.
sym = Fcar (args);
tail = Fcdr (args);
if (!NILP (Fcdr (Fcdr (tail))))
- error ("too many arguments");
+ error ("Too many arguments");
tem = Fdefault_boundp (sym);
if (!NILP (tail))
{
+ if (SYMBOL_CONSTANT_P (sym))
+ {
+ /* For upward compatibility, allow (defvar :foo (quote :foo)). */
+ Lisp_Object tem = Fcar (tail);
+ if (! (CONSP (tem)
+ && EQ (XCAR (tem), Qquote)
+ && CONSP (XCDR (tem))
+ && EQ (XCAR (XCDR (tem)), sym)))
+ error ("Constant symbol `%s' specified in defvar",
+ SDATA (SYMBOL_NAME (sym)));
+ }
+
if (NILP (tem))
Fset_default (sym, Feval (Fcar (tail)));
else
sym = Fcar (args);
if (!NILP (Fcdr (Fcdr (Fcdr (args)))))
- error ("too many arguments");
+ error ("Too many arguments");
tem = Feval (Fcar (Fcdr (args)));
if (!NILP (Vpurify_flag))
tem = Fpurecopy (tem);
Fput (sym, Qvariable_documentation, tem);
}
+ Fput (sym, Qrisky_local_variable, Qt);
LOADHIST_ATTACH (sym);
return sym;
}
+/* Error handler used in Fuser_variable_p. */
+static Lisp_Object
+user_variable_p_eh (ignore)
+ Lisp_Object ignore;
+{
+ return Qnil;
+}
+
DEFUN ("user-variable-p", Fuser_variable_p, Suser_variable_p, 1, 1, 0,
- doc: /* Returns t if VARIABLE is intended to be set and modified by users.
+ doc: /* Return t if VARIABLE is intended to be set and modified by users.
\(The alternative is a variable used internally in a Lisp program.)
-Determined by whether the first character of the documentation
-for the variable is `*' or if the variable is customizable (has a non-nil
-value of `standard-value' or of `custom-autoload' on its property list). */)
+A variable is a user variable if
+\(1) the first character of its documentation is `*', or
+\(2) it is customizable (its property list contains a non-nil value
+ of `standard-value' or `custom-autoload'), or
+\(3) it is an alias for another user variable.
+Return nil if VARIABLE is an alias and there is a loop in the
+chain of symbols. */)
(variable)
Lisp_Object variable;
{
if (!SYMBOLP (variable))
return Qnil;
- documentation = Fget (variable, Qvariable_documentation);
- if (INTEGERP (documentation) && XINT (documentation) < 0)
- return Qt;
- if (STRINGP (documentation)
- && ((unsigned char) SREF (documentation, 0) == '*'))
- return Qt;
- /* If it is (STRING . INTEGER), a negative integer means a user variable. */
- if (CONSP (documentation)
- && STRINGP (XCAR (documentation))
- && INTEGERP (XCDR (documentation))
- && XINT (XCDR (documentation)) < 0)
- return Qt;
- /* Customizable? See `custom-variable-p'. */
- if ((!NILP (Fget (variable, intern ("standard-value"))))
- || (!NILP (Fget (variable, intern ("custom-autoload")))))
- return Qt;
- return Qnil;
+ /* If indirect and there's an alias loop, don't check anything else. */
+ if (XSYMBOL (variable)->indirect_variable
+ && NILP (internal_condition_case_1 (indirect_variable, variable,
+ Qt, user_variable_p_eh)))
+ return Qnil;
+
+ while (1)
+ {
+ documentation = Fget (variable, Qvariable_documentation);
+ if (INTEGERP (documentation) && XINT (documentation) < 0)
+ return Qt;
+ if (STRINGP (documentation)
+ && ((unsigned char) SREF (documentation, 0) == '*'))
+ return Qt;
+ /* If it is (STRING . INTEGER), a negative integer means a user variable. */
+ if (CONSP (documentation)
+ && STRINGP (XCAR (documentation))
+ && INTEGERP (XCDR (documentation))
+ && XINT (XCDR (documentation)) < 0)
+ return Qt;
+ /* Customizable? See `custom-variable-p'. */
+ if ((!NILP (Fget (variable, intern ("standard-value"))))
+ || (!NILP (Fget (variable, intern ("custom-autoload")))))
+ return Qt;
+
+ if (!XSYMBOL (variable)->indirect_variable)
+ return Qnil;
+
+ /* An indirect variable? Let's follow the chain. */
+ variable = XSYMBOL (variable)->value;
+ }
}
\f
DEFUN ("let*", FletX, SletX, 1, UNEVALLED, 0,
if (SYMBOLP (elt))
specbind (elt, Qnil);
else if (! NILP (Fcdr (Fcdr (elt))))
- Fsignal (Qerror,
- Fcons (build_string ("`let' bindings can have only one value-form"),
- elt));
+ signal_error ("`let' bindings can have only one value-form", elt);
else
{
val = Feval (Fcar (Fcdr (elt)));
if (SYMBOLP (elt))
temps [argnum++] = Qnil;
else if (! NILP (Fcdr (Fcdr (elt))))
- Fsignal (Qerror,
- Fcons (build_string ("`let' bindings can have only one value-form"),
- elt));
+ signal_error ("`let' bindings can have only one value-form", elt);
else
temps [argnum++] = Feval (Fcar (Fcdr (elt)));
gcpro2.nvars = argnum;
TAG is evalled to get the tag to use; it must not be nil.
Then the BODY is executed.
-Within BODY, (throw TAG) with same tag exits BODY and exits this `catch'.
+Within BODY, a call to `throw' with the same TAG exits BODY and this `catch'.
If no throw happens, `catch' returns the value of the last BODY form.
If a throw happens, it specifies the value to return from `catch'.
usage: (catch TAG BODY...) */)
}
while (! last_time);
+#if HAVE_X_WINDOWS
+ /* If x_catch_errors was done, turn it off now.
+ (First we give unbind_to a chance to do that.) */
+ x_fully_uncatch_errors ();
+#endif
+
byte_stack_list = catch->byte_stack;
gcprolist = catch->gcpro;
#ifdef DEBUG_GCPRO
{
register struct catchtag *c;
- while (1)
- {
- if (!NILP (tag))
- for (c = catchlist; c; c = c->next)
- {
- if (EQ (c->tag, tag))
- unwind_to_catch (c, value);
- }
- tag = Fsignal (Qno_catch, Fcons (tag, Fcons (value, Qnil)));
- }
+ if (!NILP (tag))
+ for (c = catchlist; c; c = c->next)
+ {
+ if (EQ (c->tag, tag))
+ unwind_to_catch (c, value);
+ }
+ xsignal2 (Qno_catch, tag, value);
}
(args)
Lisp_Object args;
{
- Lisp_Object val;
- struct catchtag c;
- struct handler h;
register Lisp_Object bodyform, handlers;
volatile Lisp_Object var;
var = Fcar (args);
bodyform = Fcar (Fcdr (args));
handlers = Fcdr (Fcdr (args));
+
+ return internal_lisp_condition_case (var, bodyform, handlers);
+}
+
+/* Like Fcondition_case, but the args are separate
+ rather than passed in a list. Used by Fbyte_code. */
+
+Lisp_Object
+internal_lisp_condition_case (var, bodyform, handlers)
+ volatile Lisp_Object var;
+ Lisp_Object bodyform, handlers;
+{
+ Lisp_Object val;
+ struct catchtag c;
+ struct handler h;
+
CHECK_SYMBOL (var);
for (val = handlers; CONSP (val); val = XCDR (val))
struct catchtag c;
struct handler h;
-#if 0 /* We now handle interrupt_input_blocked properly.
- What we still do not handle is exiting a signal handler. */
+ /* Since Fsignal will close off all calls to x_catch_errors,
+ we will get the wrong results if some are not closed now. */
+#if HAVE_X_WINDOWS
+ if (x_catching_errors ())
abort ();
#endif
struct catchtag c;
struct handler h;
+ /* Since Fsignal will close off all calls to x_catch_errors,
+ we will get the wrong results if some are not closed now. */
+#if HAVE_X_WINDOWS
+ if (x_catching_errors ())
+ abort ();
+#endif
+
c.tag = Qnil;
c.val = Qnil;
c.backlist = backtrace_list;
struct catchtag c;
struct handler h;
+ /* Since Fsignal will close off all calls to x_catch_errors,
+ we will get the wrong results if some are not closed now. */
+#if HAVE_X_WINDOWS
+ if (x_catching_errors ())
+ abort ();
+#endif
+
c.tag = Qnil;
c.val = Qnil;
c.backlist = backtrace_list;
/* 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);
{
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);
fatal ("%s", SDATA (string), 0);
}
+/* Internal version of Fsignal that never returns.
+ Used for anything but Qquit (which can return from Fsignal). */
+
+void
+xsignal (error_symbol, data)
+ Lisp_Object error_symbol, data;
+{
+ Fsignal (error_symbol, data);
+ abort ();
+}
+
+/* Like xsignal, but takes 0, 1, 2, or 3 args instead of a list. */
+
+void
+xsignal0 (error_symbol)
+ Lisp_Object error_symbol;
+{
+ xsignal (error_symbol, Qnil);
+}
+
+void
+xsignal1 (error_symbol, arg)
+ Lisp_Object error_symbol, arg;
+{
+ xsignal (error_symbol, list1 (arg));
+}
+
+void
+xsignal2 (error_symbol, arg1, arg2)
+ Lisp_Object error_symbol, arg1, arg2;
+{
+ xsignal (error_symbol, list2 (arg1, arg2));
+}
+
+void
+xsignal3 (error_symbol, arg1, arg2, arg3)
+ Lisp_Object error_symbol, arg1, arg2, arg3;
+{
+ xsignal (error_symbol, list3 (arg1, arg2, arg3));
+}
+
+/* Signal `error' with message S, and additional arg ARG.
+ If ARG is not a genuine list, make it a one-element list. */
+
+void
+signal_error (s, arg)
+ char *s;
+ Lisp_Object arg;
+{
+ Lisp_Object tortoise, hare;
+
+ hare = tortoise = arg;
+ while (CONSP (hare))
+ {
+ hare = XCDR (hare);
+ if (!CONSP (hare))
+ break;
+
+ hare = XCDR (hare);
+ tortoise = XCDR (tortoise);
+
+ if (EQ (hare, tortoise))
+ break;
+ }
+
+ if (!NILP (hare))
+ arg = Fcons (arg, Qnil); /* Make it a list. */
+
+ xsignal (Qerror, Fcons (build_string (s), arg));
+}
+
+
/* Return nonzero iff LIST is a non-nil atom or
a list containing one of CONDITIONS. */
= 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)
|| !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,
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,
internal_with_output_to_temp_buffer ("*Backtrace*",
Fbacktrace, Qnil);
#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)
{
- specbind (Qdebug_on_error, Qnil);
*debugger_value_ptr
= call_debugger (Fcons (Qerror,
Fcons (combined_data, Qnil)));
if (EQ (handlers, Qerror))
{
if (debugger_called)
- return unbind_to (count, Qlambda);
+ return Qlambda;
return Qt;
}
}
if (allocated)
xfree (buffer);
- Fsignal (Qerror, Fcons (string, Qnil));
- abort ();
+ xsignal1 (Qerror, string);
}
\f
DEFUN ("commandp", Fcommandp, Scommandp, 1, 2, 0,
first = XCAR (queue);
second = Fcdr (first);
first = Fcar (first);
- if (EQ (second, Qnil))
- Vfeatures = first;
+ if (EQ (first, make_number (0)))
+ Vfeatures = second;
else
Ffset (first, second);
queue = XCDR (queue);
GCPRO3 (fun, funname, fundef);
/* Preserve the match data. */
- record_unwind_protect (Fset_match_data, Fmatch_data (Qnil, Qnil));
+ record_unwind_save_match_data ();
/* Value saved here is to be restored into Vautoload_queue. */
record_unwind_protect (un_autoload, Vautoload_queue);
second = Fcdr (first);
first = Fcar (first);
- if (CONSP (second) && EQ (XCAR (second), Qautoload))
+ if (SYMBOLP (first) && CONSP (second) && EQ (XCAR (second), Qautoload))
Fput (first, Qautoload, (XCDR (second)));
queue = XCDR (queue);
Vautoload_queue = Qt;
unbind_to (count, Qnil);
- fun = Findirect_function (fun);
+ fun = Findirect_function (fun, Qnil);
if (!NILP (Fequal (fun, fundef)))
error ("Autoloading failed to define function %s",
return form;
QUIT;
- if (consing_since_gc > gc_cons_threshold)
+ if ((consing_since_gc > gc_cons_threshold
+ && consing_since_gc > gc_relative_threshold)
+ ||
+ (!NILP (Vmemory_full) && consing_since_gc > memory_full_cons_threshold))
{
GCPRO1 (form);
Fgarbage_collect ();
if (max_lisp_eval_depth < 100)
max_lisp_eval_depth = 100;
if (lisp_eval_depth > max_lisp_eval_depth)
- error ("Lisp nesting exceeds max-lisp-eval-depth");
+ error ("Lisp nesting exceeds `max-lisp-eval-depth'");
}
original_fun = Fcar (form);
/* At this point, only original_fun and original_args
have values that will be used below */
retry:
- fun = Findirect_function (original_fun);
+
+ /* Optimize for no indirection. */
+ fun = original_fun;
+ if (SYMBOLP (fun) && !EQ (fun, Qunbound)
+ && (fun = XSYMBOL (fun)->function, SYMBOLP (fun)))
+ fun = indirect_function (fun);
if (SUBRP (fun))
{
if (XINT (numargs) < XSUBR (fun)->min_args ||
(XSUBR (fun)->max_args >= 0 && XSUBR (fun)->max_args < XINT (numargs)))
- return Fsignal (Qwrong_number_of_arguments, Fcons (fun, Fcons (numargs, Qnil)));
+ xsignal2 (Qwrong_number_of_arguments, original_fun, numargs);
if (XSUBR (fun)->max_args == UNEVALLED)
{
val = apply_lambda (fun, original_args, 1);
else
{
+ if (EQ (fun, Qunbound))
+ xsignal1 (Qvoid_function, original_fun);
if (!CONSP (fun))
- return Fsignal (Qinvalid_function, Fcons (fun, Qnil));
- funcar = Fcar (fun);
+ xsignal1 (Qinvalid_function, original_fun);
+ funcar = XCAR (fun);
if (!SYMBOLP (funcar))
- return Fsignal (Qinvalid_function, Fcons (fun, Qnil));
+ xsignal1 (Qinvalid_function, original_fun);
if (EQ (funcar, Qautoload))
{
do_autoload (fun, original_fun);
else if (EQ (funcar, Qlambda))
val = apply_lambda (fun, original_args, 1);
else
- return Fsignal (Qinvalid_function, Fcons (fun, Qnil));
+ xsignal1 (Qinvalid_function, original_fun);
}
done:
CHECK_CONS_LIST ();
numargs += nargs - 2;
- fun = indirect_function (fun);
+ /* Optimize for no indirection. */
+ if (SYMBOLP (fun) && !EQ (fun, Qunbound)
+ && (fun = XSYMBOL (fun)->function, SYMBOLP (fun)))
+ fun = indirect_function (fun);
if (EQ (fun, Qunbound))
{
/* Let funcall get the error */
int nargs;
Lisp_Object *args;
{
- Lisp_Object fun;
+ Lisp_Object fun, original_fun;
Lisp_Object funcar;
int numargs = nargs - 1;
Lisp_Object lisp_numargs;
register int i;
QUIT;
- if (consing_since_gc > gc_cons_threshold)
+ if ((consing_since_gc > gc_cons_threshold
+ && consing_since_gc > gc_relative_threshold)
+ ||
+ (!NILP (Vmemory_full) && consing_since_gc > memory_full_cons_threshold))
Fgarbage_collect ();
if (++lisp_eval_depth > max_lisp_eval_depth)
if (max_lisp_eval_depth < 100)
max_lisp_eval_depth = 100;
if (lisp_eval_depth > max_lisp_eval_depth)
- error ("Lisp nesting exceeds max-lisp-eval-depth");
+ error ("Lisp nesting exceeds `max-lisp-eval-depth'");
}
backtrace.next = backtrace_list;
CHECK_CONS_LIST ();
- retry:
+ original_fun = args[0];
- fun = args[0];
+ retry:
- fun = Findirect_function (fun);
+ /* Optimize for no indirection. */
+ fun = original_fun;
+ if (SYMBOLP (fun) && !EQ (fun, Qunbound)
+ && (fun = XSYMBOL (fun)->function, SYMBOLP (fun)))
+ fun = indirect_function (fun);
if (SUBRP (fun))
{
|| (XSUBR (fun)->max_args >= 0 && XSUBR (fun)->max_args < numargs))
{
XSETFASTINT (lisp_numargs, numargs);
- return Fsignal (Qwrong_number_of_arguments, Fcons (fun, Fcons (lisp_numargs, Qnil)));
+ xsignal2 (Qwrong_number_of_arguments, original_fun, lisp_numargs);
}
if (XSUBR (fun)->max_args == UNEVALLED)
- return Fsignal (Qinvalid_function, Fcons (fun, Qnil));
+ xsignal1 (Qinvalid_function, original_fun);
if (XSUBR (fun)->max_args == MANY)
{
val = (*XSUBR (fun)->function) (internal_args[0]);
goto done;
case 2:
- val = (*XSUBR (fun)->function) (internal_args[0],
- internal_args[1]);
+ val = (*XSUBR (fun)->function) (internal_args[0], internal_args[1]);
goto done;
case 3:
val = (*XSUBR (fun)->function) (internal_args[0], internal_args[1],
goto done;
case 4:
val = (*XSUBR (fun)->function) (internal_args[0], internal_args[1],
- internal_args[2],
- internal_args[3]);
+ internal_args[2], internal_args[3]);
goto done;
case 5:
val = (*XSUBR (fun)->function) (internal_args[0], internal_args[1],
val = funcall_lambda (fun, numargs, args + 1);
else
{
+ if (EQ (fun, Qunbound))
+ xsignal1 (Qvoid_function, original_fun);
if (!CONSP (fun))
- return Fsignal (Qinvalid_function, Fcons (fun, Qnil));
- funcar = Fcar (fun);
+ xsignal1 (Qinvalid_function, original_fun);
+ funcar = XCAR (fun);
if (!SYMBOLP (funcar))
- return Fsignal (Qinvalid_function, Fcons (fun, Qnil));
+ xsignal1 (Qinvalid_function, original_fun);
if (EQ (funcar, Qlambda))
val = funcall_lambda (fun, numargs, args + 1);
else if (EQ (funcar, Qautoload))
{
- do_autoload (fun, args[0]);
+ do_autoload (fun, original_fun);
CHECK_CONS_LIST ();
goto retry;
}
else
- return Fsignal (Qinvalid_function, Fcons (fun, Qnil));
+ xsignal1 (Qinvalid_function, original_fun);
}
done:
CHECK_CONS_LIST ();
if (CONSP (syms_left))
syms_left = XCAR (syms_left);
else
- return Fsignal (Qinvalid_function, Fcons (fun, Qnil));
+ xsignal1 (Qinvalid_function, fun);
}
else if (COMPILEDP (fun))
syms_left = AREF (fun, COMPILED_ARGLIST);
QUIT;
next = XCAR (syms_left);
- while (!SYMBOLP (next))
- next = Fsignal (Qinvalid_function, Fcons (fun, Qnil));
+ if (!SYMBOLP (next))
+ xsignal1 (Qinvalid_function, fun);
if (EQ (next, Qand_rest))
rest = 1;
else if (i < nargs)
specbind (next, arg_vector[i++]);
else if (!optional)
- return Fsignal (Qwrong_number_of_arguments,
- Fcons (fun, Fcons (make_number (nargs), Qnil)));
+ xsignal2 (Qwrong_number_of_arguments, fun, make_number (nargs));
else
specbind (next, Qnil);
}
if (!NILP (syms_left))
- return Fsignal (Qinvalid_function, Fcons (fun, Qnil));
+ xsignal1 (Qinvalid_function, fun);
else if (i < nargs)
- return Fsignal (Qwrong_number_of_arguments,
- Fcons (fun, Fcons (make_number (nargs), Qnil)));
+ xsignal2 (Qwrong_number_of_arguments, fun, make_number (nargs));
if (CONSP (fun))
val = Fprogn (XCDR (XCDR (fun)));
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));
- }
+ signal_error ("Variable binding depth exceeds max-specpdl-size", Qnil);
}
specpdl_size *= 2;
if (specpdl_size > max_specpdl_size)
Lisp_Object (*function) P_ ((Lisp_Object));
Lisp_Object arg;
{
+ eassert (!handling_signal);
+
if (specpdl_ptr == specpdl + specpdl_size)
grow_specpdl ();
specpdl_ptr->func = function;
int count;
Lisp_Object value;
{
- int quitf = !NILP (Vquit_flag);
- struct gcpro gcpro1;
+ Lisp_Object quitf = Vquit_flag;
+ struct gcpro gcpro1, gcpro2;
- GCPRO1 (value);
+ GCPRO2 (value, quitf);
Vquit_flag = Qnil;
while (specpdl_ptr != specpdl + count)
}
}
- if (NILP (Vquit_flag) && quitf)
- Vquit_flag = Qt;
+ if (NILP (Vquit_flag) && !NILP (quitf))
+ Vquit_flag = quitf;
UNGCPRO;
return value;
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,
+ doc: /* *Limit on number of Lisp variable bindings and `unwind-protect's.
+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,
Vdebug_ignored_errors = Qnil;
DEFVAR_BOOL ("debug-on-quit", &debug_on_quit,
- doc: /* *Non-nil means enter debugger if quit is signaled (C-g, for example).
-Does not apply if quit is handled by a `condition-case'.
-When you evaluate an expression interactively, this variable
-is temporarily non-nil if `eval-expression-debug-on-quit' is non-nil. */);
+ doc: /* *Non-nil means enter debugger if quit is signaled (C-g, for example).
+Does not apply if quit is handled by a `condition-case'. */);
debug_on_quit = 0;
DEFVAR_BOOL ("debug-on-next-call", &debug_on_next_call,