Include <config.h> instead of "config.h".
[bpt/emacs.git] / src / eval.c
index 572410e..1b05bf0 100644 (file)
@@ -1,5 +1,5 @@
 /* Evaluator for GNU Emacs Lisp interpreter.
-   Copyright (C) 1985, 1986, 1987, 1992 Free Software Foundation, Inc.
+   Copyright (C) 1985, 1986, 1987, 1993 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -18,11 +18,9 @@ along with GNU Emacs; see the file COPYING.  If not, write to
 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 
-#include "config.h"
+#include <config.h>
 #include "lisp.h"
-#ifdef HAVE_X_WINDOWS
-#include "xterm.h"
-#endif
+#include "blockinput.h"
 
 #ifndef standalone
 #include "commands.h"
@@ -51,6 +49,24 @@ struct backtrace
 
 struct backtrace *backtrace_list;
 
+/* This structure helps implement the `catch' and `throw' control
+   structure.  A struct catchtag contains all the information needed
+   to restore the state of the interpreter after a non-local jump.
+
+   Handlers for error conditions (represented by `struct handler'
+   structures) just point to a catch tag to do the cleanup required
+   for their jumps.
+
+   catchtag structures are chained together in the C calling stack;
+   the `next' member points to the next outer catchtag.
+
+   A call like (throw TAG VAL) searches for a catchtag whose `tag'
+   member is TAG, and then unbinds to it.  The `val' member is used to
+   hold VAL while the stack is unwound; `val' is returned as the value
+   of the catch form.
+
+   All the other members are concerned with restoring the interpreter
+   state.  */
 struct catchtag
   {
     Lisp_Object tag;
@@ -115,9 +131,13 @@ Lisp_Object Vdebug_on_error;
    is handled by the command loop's error handler. */
 int debug_on_quit;
 
-/* Nonzero means we are trying to enter the debugger.
-   This is to prevent recursive attempts.  */
-int entering_debugger;
+/* The value of num_nonmacro_input_chars as of the last time we
+   started to enter the debugger.  If we decide to enter the debugger
+   again when this is still equal to num_nonmacro_input_chars, then we
+   know that the debugger itself has an error, and we should just
+   signal the error instead of entering an infinite loop of debugger
+   invocations.  */
+int when_entered_debugger;
 
 Lisp_Object Vdebugger;
 
@@ -143,7 +163,7 @@ init_eval ()
   Vquit_flag = Qnil;
   debug_on_next_call = 0;
   lisp_eval_depth = 0;
-  entering_debugger = 0;
+  when_entered_debugger = 0;
 }
 
 Lisp_Object
@@ -155,7 +175,7 @@ call_debugger (arg)
   if (specpdl_size + 40 > max_specpdl_size)
     max_specpdl_size = specpdl_size + 40;
   debug_on_next_call = 0;
-  entering_debugger = 1;
+  when_entered_debugger = num_nonmacro_input_chars;
   return apply1 (Vdebugger, arg);
 }
 
@@ -504,6 +524,7 @@ See also the function `interactive'.")
   if (!NILP (Vpurify_flag))
     defn = Fpurecopy (defn);
   Ffset (fn_name, defn);
+  LOADHIST_ATTACH (fn_name);
   return fn_name;
 }
 
@@ -525,6 +546,7 @@ and the result should be a form to be evaluated instead of the original.")
   if (!NILP (Vpurify_flag))
     defn = Fpurecopy (defn);
   Ffset (fn_name, defn);
+  LOADHIST_ATTACH (fn_name);
   return fn_name;
 }
 
@@ -560,6 +582,7 @@ If INITVALUE is missing, SYMBOL's value is not set.")
        tem = Fpurecopy (tem);
       Fput (sym, Qvariable_documentation, tem);
     }
+  LOADHIST_ATTACH (sym);
   return sym;
 }
 
@@ -591,6 +614,7 @@ it would override the user's choice.")
        tem = Fpurecopy (tem);
       Fput (sym, Qvariable_documentation, tem);
     }
+  LOADHIST_ATTACH (sym);
   return sym;
 }
 
@@ -722,7 +746,8 @@ until TEST returns nil.")
 
   test = Fcar (args);
   body = Fcdr (args);
-  while (tem = Feval (test), !NILP (tem))
+  while (tem = Feval (test),
+        (!EQ (Vmocklisp_arguments, Qt) ? XINT (tem) : !NILP (tem)))
     {
       QUIT;
       Fprogn (body);
@@ -743,6 +768,7 @@ definitions to shadow the loaded ones for use in file byte-compilation.")
      register Lisp_Object form;
      Lisp_Object env;
 {
+  /* With cleanups from Hallvard Furuseth.  */
   register Lisp_Object expander, sym, def, tem;
 
   while (1)
@@ -751,42 +777,23 @@ definitions to shadow the loaded ones for use in file byte-compilation.")
         in case it expands into another macro call.  */
       if (XTYPE (form) != Lisp_Cons)
        break;
-      sym = XCONS (form)->car;
-      /* Detect  ((macro lambda ...) ...)  */
-      if (XTYPE (sym) == Lisp_Cons
-         && EQ (XCONS (sym)->car, Qmacro))
-       {
-         expander = XCONS (sym)->cdr;
-         goto explicit;
-       }
-      if (XTYPE (sym) != Lisp_Symbol)
-       break;
+      /* Set SYM, give DEF and TEM right values in case SYM is not a symbol. */
+      def = sym = XCONS (form)->car;
+      tem = Qnil;
       /* Trace symbols aliases to other symbols
         until we get a symbol that is not an alias.  */
-      while (1)
+      while (XTYPE (def) == Lisp_Symbol)
        {
          QUIT;
+         sym = def;
          tem = Fassq (sym, env);
          if (NILP (tem))
            {
              def = XSYMBOL (sym)->function;
-             if (XTYPE (def) == Lisp_Symbol && !EQ (def, Qunbound))
-               sym = def;
-             else
-               break;
-           }
-         else
-           {
-#if 0  /* This is turned off because it caused an element (foo . bar)
-         to have the effect of defining foo as an alias for the macro bar.
-         That is inconsistent; bar should be a function to expand foo.  */
-             if (XTYPE (tem) == Lisp_Cons
-                 && XTYPE (XCONS (tem)->cdr) == Lisp_Symbol)
-               sym = XCONS (tem)->cdr;
-             else
-#endif
-               break;
+             if (!EQ (def, Qunbound))
+               continue;
            }
+         break;
        }
       /* Right now TEM is the result from SYM in ENV,
         and if TEM is nil then DEF is SYM's function definition.  */
@@ -801,12 +808,16 @@ definitions to shadow the loaded ones for use in file byte-compilation.")
          if (EQ (XCONS (def)->car, Qautoload))
            {
              /* Autoloading function: will it be a macro when loaded?  */
-             tem = Fcar (Fnthcdr (make_number (4), def));
-             if (NILP (tem))
+             tem = Fnth (make_number (4), def);
+             if (EQ (XCONS (tem)->car, Qt)
+                 || EQ (XCONS (tem)->car, Qmacro))
+               /* Yes, load it and try again.  */
+               {
+                 do_autoload (def, sym);
+                 continue;
+               }
+             else
                break;
-             /* Yes, load it and try again.  */
-             do_autoload (def, sym);
-             continue;
            }
          else if (!EQ (XCONS (def)->car, Qmacro))
            break;
@@ -818,7 +829,6 @@ definitions to shadow the loaded ones for use in file byte-compilation.")
          if (NILP (expander))
            break;
        }
-    explicit:
       form = apply1 (expander, XCONS (form)->cdr);
     }
   return form;
@@ -876,26 +886,41 @@ internal_catch (tag, func, arg)
   return c.val;
 }
 
-/* Discard from the catchlist all catch tags back through CATCH.
-   Before each catch is discarded, unbind all special bindings
-   made within that catch.  Also, when discarding a catch that
-   corresponds to a condition handler, discard that handler.
+/* Unwind the specbind, catch, and handler stacks back to CATCH, and
+   jump to that CATCH, returning VALUE as the value of that catch.
 
-   At the end, restore some static info saved in CATCH.
+   This is the guts Fthrow and Fsignal; they differ only in the way
+   they choose the catch tag to throw to.  A catch tag for a
+   condition-case form has a TAG of Qnil.
 
-   This is used for correct unwinding in Fthrow and Fsignal,
-   before doing the longjmp that actually destroys the stack frames
-   in which these handlers and catches reside.  */
+   Before each catch is discarded, unbind all special bindings and
+   execute all unwind-protect clauses made above that catch.  Unwind
+   the handler stack as we go, so that the proper handlers are in
+   effect for each unwind-protect clause we run.  At the end, restore
+   some static info saved in CATCH, and longjmp to the location
+   specified in the
+
+   This is used for correct unwinding in Fthrow and Fsignal.  */
 
 static void
-unbind_catch (catch)
+unwind_to_catch (catch, value)
      struct catchtag *catch;
+     Lisp_Object value;
 {
   register int last_time;
 
+  /* Save the value in the tag.  */
+  catch->val = value;
+
+  /* Restore the polling-suppression count.  */
+  set_poll_suppress_count (catch->poll_suppress_count);
+
   do
     {
       last_time = catchlist == catch;
+
+      /* Unwind the specpdl stack, and then restore the proper set of
+         handlers.  */
       unbind_to (catchlist->pdlcount, Qnil);
       handlerlist = catchlist->handlerlist;
       catchlist = catchlist->next;
@@ -905,6 +930,8 @@ unbind_catch (catch)
   gcprolist = catch->gcpro;
   backtrace_list = catch->backlist;
   lisp_eval_depth = catch->lisp_eval_depth;
+  
+  _longjmp (catch->jmp, 1);
 }
 
 DEFUN ("throw", Fthrow, Sthrow, 2, 2, 0,
@@ -921,16 +948,7 @@ Both TAG and VALUE are evalled.")
        for (c = catchlist; c; c = c->next)
          {
            if (EQ (c->tag, tag))
-             {
-               /* Restore the polling-suppression count.  */
-               if (c->poll_suppress_count > poll_suppress_count)
-                 abort ();
-               while (c->poll_suppress_count < poll_suppress_count)
-                 start_polling ();
-               c->val = val;
-               unbind_catch (c);
-               _longjmp (c->jmp, 1);
-             }
+             unwind_to_catch (c, val);
          }
       tag = Fsignal (Qno_catch, Fcons (tag, Fcons (val, Qnil)));
     }
@@ -985,10 +1003,21 @@ See also the function `signal' for more info.")
   Lisp_Object val;
   struct catchtag c;
   struct handler h;
-  register Lisp_Object tem;
+  register Lisp_Object var, bodyform, handlers;
 
-  tem = Fcar (args);
-  CHECK_SYMBOL (tem, 0);
+  var      = Fcar (args);
+  bodyform = Fcar (Fcdr (args));
+  handlers = Fcdr (Fcdr (args));
+  CHECK_SYMBOL (var, 0);
+
+  for (val = handlers; ! NILP (val); val = Fcdr (val))
+    {
+      Lisp_Object tem;
+      tem = Fcar (val);
+      if ((!NILP (tem)) &&
+         (!CONSP (tem) || (XTYPE (XCONS (tem)->car) != Lisp_Symbol)))
+       error ("Invalid condition handler", tem);
+    }
 
   c.tag = Qnil;
   c.val = Qnil;
@@ -1003,28 +1032,23 @@ See also the function `signal' for more info.")
       if (!NILP (h.var))
         specbind (h.var, Fcdr (c.val));
       val = Fprogn (Fcdr (Fcar (c.val)));
+
+      /* Note that this just undoes the binding of h.var; whoever
+        longjumped to us unwound the stack to c.pdlcount before
+        throwing. */
       unbind_to (c.pdlcount, Qnil);
       return val;
     }
   c.next = catchlist;
   catchlist = &c;
-  h.var = Fcar (args);
-  h.handler = Fcdr (Fcdr (args));
-  
-  for (val = h.handler; ! NILP (val); val = Fcdr (val))
-    {
-      tem = Fcar (val);
-      if ((!NILP (tem)) &&
-         (!CONSP (tem) || (XTYPE (XCONS (tem)->car) != Lisp_Symbol)))
-       error ("Invalid condition handler", tem);
-    }
   
+  h.var = var;
+  h.handler = handlers;
   h.next = handlerlist;
-  h.poll_suppress_count = poll_suppress_count;
   h.tag = &c;
   handlerlist = &h;
 
-  val = Feval (Fcar (Fcdr (args)));
+  val = Feval (bodyform);
   catchlist = c.next;
   handlerlist = h.next;
   return val;
@@ -1056,7 +1080,6 @@ internal_condition_case (bfun, handlers, hfun)
   catchlist = &c;
   h.handler = handlers;
   h.var = Qnil;
-  h.poll_suppress_count = poll_suppress_count;
   h.next = handlerlist;
   h.tag = &c;
   handlerlist = &h;
@@ -1114,21 +1137,21 @@ See also the function `condition-case'.")
        return debugger_value;
 #else
       if (EQ (clause, Qlambda))
-       error ("Returning a value from an error is no longer supported");
+       {
+         /* We can't return values to code which signalled an error, but we
+            can continue code which has signalled a quit.  */
+         if (EQ (sig, Qquit))
+           return Qnil;
+         else
+           error ("Cannot return from the debugger in an error");
+       }
 #endif
 
       if (!NILP (clause))
        {
          struct handler *h = handlerlist;
-         /* Restore the polling-suppression count.  */
-         if (h->poll_suppress_count > poll_suppress_count)
-           abort ();
-         while (h->poll_suppress_count < poll_suppress_count)
-           start_polling ();
          handlerlist = allhandlers;
-         unbind_catch (h->tag);
-         h->tag->val = Fcons (clause, Fcons (sig, data));
-         _longjmp (h->tag->jmp, 1);
+         unwind_to_catch (h->tag, Fcons (clause, Fcons (sig, data)));
        }
     }
 
@@ -1146,32 +1169,21 @@ static int
 wants_debugger (list, conditions)
      Lisp_Object list, conditions;
 {
-  static int looking = 0;
-
-  if (looking)
-    {
-      /* We got an error while looking in LIST.  */
-      looking = 0;
-      return 1;
-    }
-
   if (NILP (list))
     return 0;
   if (! CONSP (list))
     return 1;
 
-  looking = 1;
-  while (!NILP (conditions))
+  while (CONSP (conditions))
     {
-      Lisp_Object tem;
-      tem = Fmemq (XCONS (conditions)->car, list);
-      if (! NILP (tem))
-       {
-         looking = 0;
+      Lisp_Object this, tail;
+      this = XCONS (conditions)->car;
+      for (tail = list; CONSP (tail); tail = XCONS (tail)->cdr)
+       if (EQ (XCONS (tail)->car, this))
          return 1;
-       }
       conditions = XCONS (conditions)->cdr;
     }
+  return 0;
 }
 
 /* Value of Qlambda means we have called debugger and user has continued.
@@ -1192,9 +1204,10 @@ find_handler_clause (handlers, conditions, sig, data, debugger_value_ptr)
     {
       if (wants_debugger (Vstack_trace_on_error, conditions))
        internal_with_output_to_temp_buffer ("*Backtrace*", Fbacktrace, Qnil);
-      if (!entering_debugger
-         && ((EQ (sig, Qquit) && debug_on_quit)
-             || wants_debugger (Vdebug_on_error, conditions)))
+      if ((EQ (sig, Qquit)
+          ? debug_on_quit
+          : wants_debugger (Vdebug_on_error, conditions))
+         && when_entered_debugger < num_nonmacro_input_chars)
        {
          int count = specpdl_ptr - specpdl;
          specbind (Qdebug_on_error, Qnil);
@@ -1302,13 +1315,16 @@ DEFUN ("autoload", Fautoload, Sautoload, 2, 5, 0,
 FUNCTION is a symbol; FILE is a file name string to pass to `load'.\n\
 Third arg DOCSTRING is documentation for the function.\n\
 Fourth arg INTERACTIVE if non-nil says function can be called interactively.\n\
-Fifth arg MACRO if non-nil says the function is really a macro.\n\
+Fifth arg TYPE indicates the type of the object:\n\
+   nil or omitted says FUNCTION is a function,\n\
+   `keymap' says FUNCTION is really a keymap, and\n\
+   `macro' or t says FUNCTION is really a macro.\n\
 Third through fifth args give info about the real definition.\n\
 They default to nil.\n\
 If FUNCTION is already defined other than as an autoload,\n\
 this does nothing and returns nil.")
-  (function, file, docstring, interactive, macro)
-     Lisp_Object function, file, docstring, interactive, macro;
+  (function, file, docstring, interactive, type)
+     Lisp_Object function, file, docstring, interactive, type;
 {
 #ifdef NO_ARG_ARRAY
   Lisp_Object args[4];
@@ -1327,7 +1343,7 @@ this does nothing and returns nil.")
   args[0] = file;
   args[1] = docstring;
   args[2] = interactive;
-  args[3] = macro;
+  args[3] = type;
 
   return Ffset (function, Fcons (Qautoload, Flist (4, &args[0])));
 #else /* NO_ARG_ARRAY */
@@ -1363,7 +1379,7 @@ do_autoload (fundef, funname)
      Lisp_Object fundef, funname;
 {
   int count = specpdl_ptr - specpdl;
-  Lisp_Object fun, val;
+  Lisp_Object fun, val, queue, first, second;
 
   fun = funname;
   CHECK_SYMBOL (funname, 0);
@@ -1372,14 +1388,31 @@ do_autoload (fundef, funname)
   record_unwind_protect (un_autoload, Vautoload_queue);
   Vautoload_queue = Qt;
   Fload (Fcar (Fcdr (fundef)), Qnil, noninteractive ? Qt : Qnil, Qnil);
+
+  /* Save the old autoloads, in case we ever do an unload. */
+  queue = Vautoload_queue;
+  while (CONSP (queue))
+    {
+      first = Fcar (queue);
+      second = Fcdr (first);
+      first = Fcar (first);
+
+      /* Note: This test is subtle.  The cdr of an autoload-queue entry
+        may be an atom if the autoload entry was generated by a defalias
+        or fset. */
+      if (CONSP (second))
+         Fput(first, Qautoload, (Fcdr (second)));
+
+      queue = Fcdr (queue);
+    }
+
   /* Once loading finishes, don't undo it.  */
   Vautoload_queue = Qt;
   unbind_to (count, Qnil);
 
   fun = Findirect_function (fun);
 
-  if (XTYPE (fun) == Lisp_Cons
-      && EQ (XCONS (fun)->car, Qautoload))
+  if (!NILP (Fequal (fun, fundef)))
     error ("Autoloading failed to define function %s",
           XSYMBOL (funname)->name->data);
 }
@@ -1534,6 +1567,11 @@ DEFUN ("eval", Feval, Seval, 1, 1, 0,
          val = (*XSUBR (fun)->function) (argvals[0], argvals[1], argvals[2],
                                          argvals[3], argvals[4], argvals[5]);
          goto done;
+       case 7:
+         val = (*XSUBR (fun)->function) (argvals[0], argvals[1], argvals[2],
+                                         argvals[3], argvals[4], argvals[5],
+                                         argvals[6]);
+         goto done;
 
        default:
          /* Someone has created a subr that takes more arguments than
@@ -1695,18 +1733,18 @@ call0 (fn)
   RETURN_UNGCPRO (Ffuncall (1, &fn));
 }
 
-/* Call function fn with argument arg */
+/* Call function fn with 1 argument arg1 */
 /* ARGSUSED */
 Lisp_Object
-call1 (fn, arg)
-     Lisp_Object fn, arg;
+call1 (fn, arg1)
+     Lisp_Object fn, arg1;
 {
   struct gcpro gcpro1;
 #ifdef NO_ARG_ARRAY
   Lisp_Object args[2];  
 
   args[0] = fn;
-  args[1] = arg;
+  args[1] = arg1;
   GCPRO1 (args[0]);
   gcpro1.nvars = 2;
   RETURN_UNGCPRO (Ffuncall (2, args));
@@ -1717,18 +1755,18 @@ call1 (fn, arg)
 #endif /* not NO_ARG_ARRAY */
 }
 
-/* Call function fn with arguments arg, arg1 */
+/* Call function fn with 2 arguments arg1, arg2 */
 /* ARGSUSED */
 Lisp_Object
-call2 (fn, arg, arg1)
-     Lisp_Object fn, arg, arg1;
+call2 (fn, arg1, arg2)
+     Lisp_Object fn, arg1, arg2;
 {
   struct gcpro gcpro1;
 #ifdef NO_ARG_ARRAY
   Lisp_Object args[3];
   args[0] = fn;
-  args[1] = arg;
-  args[2] = arg1;
+  args[1] = arg1;
+  args[2] = arg2;
   GCPRO1 (args[0]);
   gcpro1.nvars = 3;
   RETURN_UNGCPRO (Ffuncall (3, args));
@@ -1739,19 +1777,19 @@ call2 (fn, arg, arg1)
 #endif /* not NO_ARG_ARRAY */
 }
 
-/* Call function fn with arguments arg, arg1, arg2 */
+/* Call function fn with 3 arguments arg1, arg2, arg3 */
 /* ARGSUSED */
 Lisp_Object
-call3 (fn, arg, arg1, arg2)
-     Lisp_Object fn, arg, arg1, arg2;
+call3 (fn, arg1, arg2, arg3)
+     Lisp_Object fn, arg1, arg2, arg3;
 {
   struct gcpro gcpro1;
 #ifdef NO_ARG_ARRAY
   Lisp_Object args[4];
   args[0] = fn;
-  args[1] = arg;
-  args[2] = arg1;
-  args[3] = arg2;
+  args[1] = arg1;
+  args[2] = arg2;
+  args[3] = arg3;
   GCPRO1 (args[0]);
   gcpro1.nvars = 4;
   RETURN_UNGCPRO (Ffuncall (4, args));
@@ -1762,6 +1800,81 @@ call3 (fn, arg, arg1, arg2)
 #endif /* not NO_ARG_ARRAY */
 }
 
+/* Call function fn with 4 arguments arg1, arg2, arg3, arg4 */
+/* ARGSUSED */
+Lisp_Object
+call4 (fn, arg1, arg2, arg3, arg4)
+     Lisp_Object fn, arg1, arg2, arg3, arg4;
+{
+  struct gcpro gcpro1;
+#ifdef NO_ARG_ARRAY
+  Lisp_Object args[5];
+  args[0] = fn;
+  args[1] = arg1;
+  args[2] = arg2;
+  args[3] = arg3;
+  args[4] = arg4;
+  GCPRO1 (args[0]);
+  gcpro1.nvars = 5;
+  RETURN_UNGCPRO (Ffuncall (5, args));
+#else /* not NO_ARG_ARRAY */
+  GCPRO1 (fn);
+  gcpro1.nvars = 5;
+  RETURN_UNGCPRO (Ffuncall (5, &fn));
+#endif /* not NO_ARG_ARRAY */
+}
+
+/* Call function fn with 5 arguments arg1, arg2, arg3, arg4, arg5 */
+/* ARGSUSED */
+Lisp_Object
+call5 (fn, arg1, arg2, arg3, arg4, arg5)
+     Lisp_Object fn, arg1, arg2, arg3, arg4, arg5;
+{
+  struct gcpro gcpro1;
+#ifdef NO_ARG_ARRAY
+  Lisp_Object args[6];
+  args[0] = fn;
+  args[1] = arg1;
+  args[2] = arg2;
+  args[3] = arg3;
+  args[4] = arg4;
+  args[5] = arg5;
+  GCPRO1 (args[0]);
+  gcpro1.nvars = 6;
+  RETURN_UNGCPRO (Ffuncall (6, args));
+#else /* not NO_ARG_ARRAY */
+  GCPRO1 (fn);
+  gcpro1.nvars = 6;
+  RETURN_UNGCPRO (Ffuncall (6, &fn));
+#endif /* not NO_ARG_ARRAY */
+}
+
+/* Call function fn with 6 arguments arg1, arg2, arg3, arg4, arg5, arg6 */
+/* ARGSUSED */
+Lisp_Object
+call6 (fn, arg1, arg2, arg3, arg4, arg5, arg6)
+     Lisp_Object fn, arg1, arg2, arg3, arg4, arg5, arg6;
+{
+  struct gcpro gcpro1;
+#ifdef NO_ARG_ARRAY
+  Lisp_Object args[7];
+  args[0] = fn;
+  args[1] = arg1;
+  args[2] = arg2;
+  args[3] = arg3;
+  args[4] = arg4;
+  args[5] = arg5;
+  args[6] = arg6;
+  GCPRO1 (args[0]);
+  gcpro1.nvars = 7;
+  RETURN_UNGCPRO (Ffuncall (7, args));
+#else /* not NO_ARG_ARRAY */
+  GCPRO1 (fn);
+  gcpro1.nvars = 7;
+  RETURN_UNGCPRO (Ffuncall (7, &fn));
+#endif /* not NO_ARG_ARRAY */
+}
+
 DEFUN ("funcall", Ffuncall, Sfuncall, 1, MANY, 0,
   "Call first argument as a function, passing remaining arguments to it.\n\
 Thus, (funcall 'cons 'x 'y) returns (x . y).")
@@ -1865,6 +1978,12 @@ Thus, (funcall 'cons 'x 'y) returns (x . y).")
                                          internal_args[2], internal_args[3],
                                          internal_args[4], internal_args[5]);
          goto done;
+       case 7:
+         val = (*XSUBR (fun)->function) (internal_args[0], internal_args[1],
+                                         internal_args[2], internal_args[3],
+                                         internal_args[4], internal_args[5],
+                                         internal_args[6]);
+         goto done;
 
        default:
 
@@ -2025,9 +2144,11 @@ grow_specpdl ()
        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));
-         max_specpdl_size *= 2;
        }
     }
   specpdl_size *= 2;
@@ -2177,8 +2298,6 @@ Output stream used is value of `standard-output'.")
   extern Lisp_Object Vprint_level;
   struct gcpro gcpro1;
 
-  entering_debugger = 0;
-
   XFASTINT (Vprint_level) = 3;
 
   tail = Qnil;
@@ -2336,8 +2455,7 @@ See also variable `debug-on-quit'.");
 
   DEFVAR_BOOL ("debug-on-quit", &debug_on_quit,
     "*Non-nil means enter debugger if quit is signaled (C-G, for example).\n\
-Does not apply if quit is handled by a `condition-case'.\n\
-A non-nil value is equivalent to a `debug-on-error' value containing `quit'.");
+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,