Merge changes from emacs-23 branch.
[bpt/emacs.git] / src / eval.c
index 6b74f5b..89d353c 100644 (file)
@@ -1,7 +1,7 @@
 /* Evaluator for GNU Emacs Lisp interpreter.
    Copyright (C) 1985, 1986, 1987, 1993, 1994, 1995, 1999, 2000, 2001,
-                 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
-                 Free Software Foundation, Inc.
+                2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+                Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -26,6 +26,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include "commands.h"
 #include "keyboard.h"
 #include "dispextern.h"
+#include "frame.h"             /* For XFRAME.  */
 
 #if HAVE_X_WINDOWS
 #include "xterm.h"
@@ -62,7 +63,6 @@ Lisp_Object Qand_rest, Qand_optional;
 Lisp_Object Qdebug_on_error;
 Lisp_Object Qdeclare;
 Lisp_Object Qdebug;
-extern Lisp_Object Qinteractive_form;
 
 /* This holds either the symbol `run-hooks' or nil.
    It is nil at an early stage of startup, and when Emacs
@@ -165,23 +165,11 @@ int handling_signal;
 
 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;
-
-#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
+static Lisp_Object funcall_lambda (Lisp_Object, int, Lisp_Object*);
+static void unwind_to_catch (struct catchtag *, Lisp_Object) NO_RETURN;
 \f
 void
-init_eval_once ()
+init_eval_once (void)
 {
   specpdl_size = 50;
   specpdl = (struct specbinding *) xmalloc (specpdl_size * sizeof (struct specbinding));
@@ -194,7 +182,7 @@ init_eval_once ()
 }
 
 void
-init_eval ()
+init_eval (void)
 {
   specpdl_ptr = specpdl;
   catchlist = 0;
@@ -213,8 +201,7 @@ init_eval ()
 /* unwind-protect function used by call_debugger.  */
 
 static Lisp_Object
-restore_stack_limits (data)
-     Lisp_Object data;
+restore_stack_limits (Lisp_Object data)
 {
   max_specpdl_size = XINT (XCAR (data));
   max_lisp_eval_depth = XINT (XCDR (data));
@@ -224,8 +211,7 @@ restore_stack_limits (data)
 /* Call the Lisp debugger, giving it argument ARG.  */
 
 Lisp_Object
-call_debugger (arg)
-     Lisp_Object arg;
+call_debugger (Lisp_Object arg)
 {
   int debug_while_redisplaying;
   int count = SPECPDL_INDEX ();
@@ -281,8 +267,7 @@ call_debugger (arg)
 }
 
 void
-do_debug_on_call (code)
-     Lisp_Object code;
+do_debug_on_call (Lisp_Object code)
 {
   debug_on_next_call = 0;
   backtrace_list->debug_on_exit = 1;
@@ -298,8 +283,7 @@ DEFUN ("or", For, Sor, 0, UNEVALLED, 0,
 The remaining args are not evalled at all.
 If all args return nil, return nil.
 usage: (or CONDITIONS...)  */)
-     (args)
-     Lisp_Object args;
+  (Lisp_Object args)
 {
   register Lisp_Object val = Qnil;
   struct gcpro gcpro1;
@@ -323,8 +307,7 @@ DEFUN ("and", Fand, Sand, 0, UNEVALLED, 0,
 The remaining args are not evalled at all.
 If no arg yields nil, return the last arg's value.
 usage: (and CONDITIONS...)  */)
-     (args)
-     Lisp_Object args;
+  (Lisp_Object args)
 {
   register Lisp_Object val = Qt;
   struct gcpro gcpro1;
@@ -349,8 +332,7 @@ Returns the value of THEN or the value of the last of the ELSE's.
 THEN must be one expression, but ELSE... can be zero or more expressions.
 If COND yields nil, and there are no ELSE's, the value is nil.
 usage: (if COND THEN ELSE...)  */)
-     (args)
-     Lisp_Object args;
+  (Lisp_Object args)
 {
   register Lisp_Object cond;
   struct gcpro gcpro1;
@@ -374,8 +356,7 @@ If no clause succeeds, cond returns nil.
 If a clause has one element, as in (CONDITION),
 CONDITION's value if non-nil is returned from the cond-form.
 usage: (cond CLAUSES...)  */)
-     (args)
-     Lisp_Object args;
+  (Lisp_Object args)
 {
   register Lisp_Object clause, val;
   struct gcpro gcpro1;
@@ -402,8 +383,7 @@ usage: (cond CLAUSES...)  */)
 DEFUN ("progn", Fprogn, Sprogn, 0, UNEVALLED, 0,
        doc: /* Eval BODY forms sequentially and return value of last one.
 usage: (progn BODY...)  */)
-     (args)
-     Lisp_Object args;
+  (Lisp_Object args)
 {
   register Lisp_Object val = Qnil;
   struct gcpro gcpro1;
@@ -425,8 +405,7 @@ DEFUN ("prog1", Fprog1, Sprog1, 1, UNEVALLED, 0,
 The value of FIRST is saved during the evaluation of the remaining args,
 whose values are discarded.
 usage: (prog1 FIRST BODY...)  */)
-     (args)
-     Lisp_Object args;
+  (Lisp_Object args)
 {
   Lisp_Object val;
   register Lisp_Object args_left;
@@ -443,7 +422,7 @@ usage: (prog1 FIRST BODY...)  */)
   do
     {
       if (!(argnum++))
-        val = Feval (Fcar (args_left));
+       val = Feval (Fcar (args_left));
       else
        Feval (Fcar (args_left));
       args_left = Fcdr (args_left);
@@ -459,8 +438,7 @@ DEFUN ("prog2", Fprog2, Sprog2, 2, UNEVALLED, 0,
 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;
+  (Lisp_Object args)
 {
   Lisp_Object val;
   register Lisp_Object args_left;
@@ -479,7 +457,7 @@ usage: (prog2 FORM1 FORM2 BODY...)  */)
   do
     {
       if (!(argnum++))
-        val = Feval (Fcar (args_left));
+       val = Feval (Fcar (args_left));
       else
        Feval (Fcar (args_left));
       args_left = Fcdr (args_left);
@@ -499,8 +477,7 @@ The second VAL is not computed until after the first SYM is set, and so on;
 each VAL can use the new value of variables set earlier in the `setq'.
 The return value of the `setq' form is the value of the last VAL.
 usage: (setq [SYM VAL]...)  */)
-     (args)
-     Lisp_Object args;
+  (Lisp_Object args)
 {
   register Lisp_Object args_left;
   register Lisp_Object val, sym;
@@ -528,8 +505,7 @@ usage: (setq [SYM VAL]...)  */)
 DEFUN ("quote", Fquote, Squote, 1, UNEVALLED, 0,
        doc: /* Return the argument, without evaluating it.  `(quote x)' yields `x'.
 usage: (quote ARG)  */)
-     (args)
-     Lisp_Object args;
+  (Lisp_Object args)
 {
   if (!NILP (Fcdr (args)))
     xsignal2 (Qwrong_number_of_arguments, Qquote, Flength (args));
@@ -541,8 +517,7 @@ DEFUN ("function", Ffunction, Sfunction, 1, UNEVALLED, 0,
 In byte compilation, `function' causes its argument to be compiled.
 `quote' cannot do that.
 usage: (function ARG)  */)
-     (args)
-     Lisp_Object args;
+  (Lisp_Object args)
 {
   if (!NILP (Fcdr (args)))
     xsignal2 (Qwrong_number_of_arguments, Qfunction, Flength (args));
@@ -567,7 +542,7 @@ To test whether your function was called with `call-interactively',
 either (i) add an extra optional argument and give it an `interactive'
 spec that specifies non-nil unconditionally (such as \"p\"); or (ii)
 use `called-interactively-p'.  */)
-     ()
+  (void)
 {
   return (INTERACTIVE && interactive_p (1)) ? Qt : Qnil;
 }
@@ -593,8 +568,7 @@ function-modifying features.  Instead of using this, it is sometimes
 cleaner to give your function an extra optional argument whose
 `interactive' spec specifies non-nil unconditionally (\"p\" is a good
 way to do this), or via (not (or executing-kbd-macro noninteractive)).  */)
-     (kind)
-     Lisp_Object kind;
+  (Lisp_Object kind)
 {
   return ((INTERACTIVE || !EQ (kind, intern ("interactive")))
          && interactive_p (1)) ? Qt : Qnil;
@@ -608,8 +582,7 @@ way to do this), or via (not (or executing-kbd-macro noninteractive)).  */)
     called is a built-in.  */
 
 int
-interactive_p (exclude_subrs_p)
-     int exclude_subrs_p;
+interactive_p (int exclude_subrs_p)
 {
   struct backtrace *btp;
   Lisp_Object fun;
@@ -656,8 +629,7 @@ DEFUN ("defun", Fdefun, Sdefun, 2, UNEVALLED, 0,
 The definition is (lambda ARGLIST [DOCSTRING] BODY...).
 See also the function `interactive'.
 usage: (defun NAME ARGLIST [DOCSTRING] BODY...)  */)
-     (args)
-     Lisp_Object args;
+  (Lisp_Object args)
 {
   register Lisp_Object fn_name;
   register Lisp_Object defn;
@@ -700,8 +672,7 @@ The elements can look like this:
        Set NAME's `doc-string-elt' property to ELT.
 
 usage: (defmacro NAME ARGLIST [DOCSTRING] [DECL] BODY...)  */)
-     (args)
-     Lisp_Object args;
+  (Lisp_Object args)
 {
   register Lisp_Object fn_name;
   register Lisp_Object defn;
@@ -719,8 +690,8 @@ usage: (defmacro NAME ARGLIST [DOCSTRING] [DECL] BODY...)  */)
       tail = XCDR (tail);
     }
 
-  while (CONSP (Fcar (tail))
-        && EQ (Fcar (Fcar (tail)), Qdeclare))
+  if (CONSP (Fcar (tail))
+      && EQ (Fcar (Fcar (tail)), Qdeclare))
     {
       if (!NILP (Vmacro_declaration_function))
        {
@@ -759,32 +730,50 @@ or of the variable at the end of the chain of aliases, if BASE-VARIABLE is
 itself an alias.  If NEW-ALIAS is bound, and BASE-VARIABLE is not,
 then the value of BASE-VARIABLE is set to that of NEW-ALIAS.
 The return value is BASE-VARIABLE.  */)
-     (new_alias, base_variable, docstring)
-     Lisp_Object new_alias, base_variable, docstring;
+  (Lisp_Object new_alias, Lisp_Object base_variable, Lisp_Object docstring)
 {
   struct Lisp_Symbol *sym;
 
   CHECK_SYMBOL (new_alias);
   CHECK_SYMBOL (base_variable);
 
-  if (SYMBOL_CONSTANT_P (new_alias))
+  sym = XSYMBOL (new_alias);
+
+  if (sym->constant)
+    /* Not sure why, but why not?  */
     error ("Cannot make a constant an alias");
 
-  sym = XSYMBOL (new_alias);
+  switch (sym->redirect)
+    {
+    case SYMBOL_FORWARDED:
+      error ("Cannot make an internal variable an alias");
+    case SYMBOL_LOCALIZED:
+      error ("Don't know how to make a localized variable an alias");
+    }
+
   /* http://lists.gnu.org/archive/html/emacs-devel/2008-04/msg00834.html
-     If n_a is bound, but b_v is not, set the value of b_v to n_a.
-     This is for the sake of define-obsolete-variable-alias and user
-     customizations.  */
-  if (NILP (Fboundp (base_variable)) && !NILP (Fboundp (new_alias)))
-    XSYMBOL(base_variable)->value = sym->value;
-  sym->indirect_variable = 1;
-  sym->value = base_variable;
+     If n_a is bound, but b_v is not, set the value of b_v to n_a,
+     so that old-code that affects n_a before the aliasing is setup
+     still works.  */
+  if (NILP (Fboundp (base_variable)))
+    set_internal (base_variable, find_symbol_value (new_alias), Qnil, 1);
+
+  {
+    struct specbinding *p;
+
+    for (p = specpdl_ptr - 1; p >= specpdl; p--)
+      if (p->func == NULL
+         && (EQ (new_alias,
+                 CONSP (p->symbol) ? XCAR (p->symbol) : p->symbol)))
+       error ("Don't know how to make a let-bound variable an alias");
+  }
+
+  sym->redirect = SYMBOL_VARALIAS;
+  SET_SYMBOL_ALIAS (sym, XSYMBOL (base_variable));
   sym->constant = SYMBOL_CONSTANT_P (base_variable);
   LOADHIST_ATTACH (new_alias);
-  if (!NILP (docstring))
-    Fput (new_alias, Qvariable_documentation, docstring);
-  else
-    Fput (new_alias, Qvariable_documentation, Qnil);
+  /* Even if docstring is nil: remove old docstring.  */
+  Fput (new_alias, Qvariable_documentation, docstring);
 
   return base_variable;
 }
@@ -812,8 +801,7 @@ load a file defining variables, with this form or with `defconst' or
 for these variables.  \(`defconst' and `defcustom' behave similarly in
 this respect.)
 usage: (defvar SYMBOL &optional INITVALUE DOCSTRING)  */)
-     (args)
-     Lisp_Object args;
+  (Lisp_Object args)
 {
   register Lisp_Object sym, tem, tail;
 
@@ -885,8 +873,7 @@ If SYMBOL has a local binding, then this form sets the local binding's
 value.  However, you should normally not make local bindings for
 variables defined with this form.
 usage: (defconst SYMBOL INITVALUE [DOCSTRING])  */)
-     (args)
-     Lisp_Object args;
+  (Lisp_Object args)
 {
   register Lisp_Object sym, tem;
 
@@ -912,8 +899,7 @@ usage: (defconst SYMBOL INITVALUE [DOCSTRING])  */)
 
 /* Error handler used in Fuser_variable_p.  */
 static Lisp_Object
-user_variable_p_eh (ignore)
-     Lisp_Object ignore;
+user_variable_p_eh (Lisp_Object ignore)
 {
   return Qnil;
 }
@@ -935,8 +921,7 @@ A variable is a user variable if
 \(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;
+  (Lisp_Object variable)
 {
   Lisp_Object documentation;
 
@@ -944,35 +929,35 @@ chain of symbols.  */)
       return Qnil;
 
   /* If indirect and there's an alias loop, don't check anything else.  */
-  if (XSYMBOL (variable)->indirect_variable
+  if (XSYMBOL (variable)->redirect == SYMBOL_VARALIAS
       && NILP (internal_condition_case_1 (lisp_indirect_variable, variable,
-                                          Qt, user_variable_p_eh)))
+                                         Qt, user_variable_p_eh)))
     return Qnil;
 
   while (1)
     {
       documentation = Fget (variable, Qvariable_documentation);
       if (INTEGERP (documentation) && XINT (documentation) < 0)
-        return Qt;
+       return Qt;
       if (STRINGP (documentation)
-          && ((unsigned char) SREF (documentation, 0) == '*'))
-        return Qt;
+         && ((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;
+         && 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;
+         || (!NILP (Fget (variable, intern ("custom-autoload")))))
+       return Qt;
 
-      if (!XSYMBOL (variable)->indirect_variable)
-        return Qnil;
+      if (!(XSYMBOL (variable)->redirect == SYMBOL_VARALIAS))
+       return Qnil;
 
       /* An indirect variable?  Let's follow the chain.  */
-      variable = XSYMBOL (variable)->value;
+      XSETSYMBOL (variable, SYMBOL_ALIAS (XSYMBOL (variable)));
     }
 }
 \f
@@ -983,8 +968,7 @@ Each element of VARLIST is a symbol (which is bound to nil)
 or a list (SYMBOL VALUEFORM) (which binds SYMBOL to the value of VALUEFORM).
 Each VALUEFORM can refer to the symbols already bound by this VARLIST.
 usage: (let* VARLIST BODY...)  */)
-     (args)
-     Lisp_Object args;
+  (Lisp_Object args)
 {
   Lisp_Object varlist, val, elt;
   int count = SPECPDL_INDEX ();
@@ -1020,8 +1004,7 @@ Each element of VARLIST is a symbol (which is bound to nil)
 or a list (SYMBOL VALUEFORM) (which binds SYMBOL to the value of VALUEFORM).
 All the VALUEFORMs are evalled before any symbols are bound.
 usage: (let VARLIST BODY...)  */)
-     (args)
-     Lisp_Object args;
+  (Lisp_Object args)
 {
   Lisp_Object *temps, tem;
   register Lisp_Object elt, varlist;
@@ -1076,8 +1059,7 @@ DEFUN ("while", Fwhile, Swhile, 1, UNEVALLED, 0,
 The order of execution is thus TEST, BODY, TEST, BODY and so on
 until TEST returns nil.
 usage: (while TEST BODY...)  */)
-     (args)
-     Lisp_Object args;
+  (Lisp_Object args)
 {
   Lisp_Object test, body;
   struct gcpro gcpro1, gcpro2;
@@ -1104,9 +1086,7 @@ in place of FORM.  When a non-macro-call results, it is returned.
 
 The second optional arg ENVIRONMENT specifies an environment of macro
 definitions to shadow the loaded ones for use in file byte-compilation.  */)
-     (form, environment)
-     Lisp_Object form;
-     Lisp_Object environment;
+  (Lisp_Object form, Lisp_Object environment)
 {
   /* With cleanups from Hallvard Furuseth.  */
   register Lisp_Object expander, sym, def, tem;
@@ -1184,8 +1164,7 @@ 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...)  */)
-     (args)
-     Lisp_Object args;
+  (Lisp_Object args)
 {
   register Lisp_Object tag;
   struct gcpro gcpro1;
@@ -1201,10 +1180,7 @@ usage: (catch TAG BODY...)  */)
    This is how catches are done from within C code. */
 
 Lisp_Object
-internal_catch (tag, func, arg)
-     Lisp_Object tag;
-     Lisp_Object (*func) ();
-     Lisp_Object arg;
+internal_catch (Lisp_Object tag, Lisp_Object (*func) (Lisp_Object), Lisp_Object arg)
 {
   /* This structure is made part of the chain `catchlist'.  */
   struct catchtag c;
@@ -1249,9 +1225,7 @@ internal_catch (tag, func, arg)
    This is used for correct unwinding in Fthrow and Fsignal.  */
 
 static void
-unwind_to_catch (catch, value)
-     struct catchtag *catch;
-     Lisp_Object value;
+unwind_to_catch (struct catchtag *catch, Lisp_Object value)
 {
   register int last_time;
 
@@ -1269,7 +1243,7 @@ unwind_to_catch (catch, value)
       last_time = catchlist == catch;
 
       /* Unwind the specpdl stack, and then restore the proper set of
-         handlers.  */
+        handlers.  */
       unbind_to (catchlist->pdlcount, Qnil);
       handlerlist = catchlist->handlerlist;
       catchlist = catchlist->next;
@@ -1280,8 +1254,8 @@ unwind_to_catch (catch, value)
   /* 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  */
+        The catch must remain in effect during that delicate
+        state. --lorentey  */
   x_fully_uncatch_errors ();
 #endif
 #endif
@@ -1303,8 +1277,7 @@ unwind_to_catch (catch, value)
 DEFUN ("throw", Fthrow, Sthrow, 2, 2, 0,
        doc: /* Throw to the catch for TAG and return VALUE from it.
 Both TAG and VALUE are evalled.  */)
-     (tag, value)
-     register Lisp_Object tag, value;
+  (register Lisp_Object tag, Lisp_Object value)
 {
   register struct catchtag *c;
 
@@ -1324,8 +1297,7 @@ If BODYFORM completes normally, its value is returned
 after executing the UNWINDFORMS.
 If BODYFORM exits nonlocally, the UNWINDFORMS are executed anyway.
 usage: (unwind-protect BODYFORM UNWINDFORMS...)  */)
-     (args)
-     Lisp_Object args;
+  (Lisp_Object args)
 {
   Lisp_Object val;
   int count = SPECPDL_INDEX ();
@@ -1359,14 +1331,13 @@ instead of a single condition name.  Then it handles all of them.
 When a handler handles an error, control returns to the `condition-case'
 and it executes the handler's BODY...
 with VAR bound to (ERROR-SYMBOL . SIGNAL-DATA) from the error.
-(If VAR is nil, the handler can't access that information.)
+\(If VAR is nil, the handler can't access that information.)
 Then the value of the last BODY form is returned from the `condition-case'
 expression.
 
 See also the function `signal' for more info.
 usage: (condition-case VAR BODYFORM &rest HANDLERS)  */)
-     (args)
-     Lisp_Object args;
+  (Lisp_Object args)
 {
   register Lisp_Object bodyform, handlers;
   volatile Lisp_Object var;
@@ -1382,9 +1353,8 @@ usage: (condition-case VAR BODYFORM &rest HANDLERS)  */)
    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;
+internal_lisp_condition_case (volatile Lisp_Object var, Lisp_Object bodyform,
+                             Lisp_Object handlers)
 {
   Lisp_Object val;
   struct catchtag c;
@@ -1416,7 +1386,7 @@ internal_lisp_condition_case (var, bodyform, handlers)
   if (_setjmp (c.jmp))
     {
       if (!NILP (h.var))
-        specbind (h.var, c.val);
+       specbind (h.var, c.val);
       val = Fprogn (Fcdr (h.chosen_clause));
 
       /* Note that this just undoes the binding of h.var; whoever
@@ -1451,10 +1421,8 @@ internal_lisp_condition_case (var, bodyform, handlers)
    but allow the debugger to run if that is enabled.  */
 
 Lisp_Object
-internal_condition_case (bfun, handlers, hfun)
-     Lisp_Object (*bfun) ();
-     Lisp_Object handlers;
-     Lisp_Object (*hfun) ();
+internal_condition_case (Lisp_Object (*bfun) (void), Lisp_Object handlers,
+                        Lisp_Object (*hfun) (Lisp_Object))
 {
   Lisp_Object val;
   struct catchtag c;
@@ -1498,11 +1466,8 @@ internal_condition_case (bfun, handlers, hfun)
 /* Like internal_condition_case but call BFUN with ARG as its argument.  */
 
 Lisp_Object
-internal_condition_case_1 (bfun, arg, handlers, hfun)
-     Lisp_Object (*bfun) ();
-     Lisp_Object arg;
-     Lisp_Object handlers;
-     Lisp_Object (*hfun) ();
+internal_condition_case_1 (Lisp_Object (*bfun) (Lisp_Object), Lisp_Object arg,
+                          Lisp_Object handlers, Lisp_Object (*hfun) (Lisp_Object))
 {
   Lisp_Object val;
   struct catchtag c;
@@ -1543,17 +1508,64 @@ internal_condition_case_1 (bfun, arg, handlers, hfun)
   return val;
 }
 
+/* Like internal_condition_case_1 but call BFUN with ARG1 and ARG2 as
+   its arguments.  */
+
+Lisp_Object
+internal_condition_case_2 (Lisp_Object (*bfun) (Lisp_Object, Lisp_Object),
+                          Lisp_Object arg1,
+                          Lisp_Object arg2,
+                          Lisp_Object handlers,
+                          Lisp_Object (*hfun) (Lisp_Object))
+{
+  Lisp_Object val;
+  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;
+  c.handlerlist = handlerlist;
+  c.lisp_eval_depth = lisp_eval_depth;
+  c.pdlcount = SPECPDL_INDEX ();
+  c.poll_suppress_count = poll_suppress_count;
+  c.interrupt_input_blocked = interrupt_input_blocked;
+  c.gcpro = gcprolist;
+  c.byte_stack = byte_stack_list;
+  if (_setjmp (c.jmp))
+    {
+      return (*hfun) (c.val);
+    }
+  c.next = catchlist;
+  catchlist = &c;
+  h.handler = handlers;
+  h.var = Qnil;
+  h.next = handlerlist;
+  h.tag = &c;
+  handlerlist = &h;
+
+  val = (*bfun) (arg1, arg2);
+  catchlist = c.next;
+  handlerlist = h.next;
+  return val;
+}
 
 /* Like internal_condition_case but call BFUN with NARGS as first,
    and ARGS as second argument.  */
 
 Lisp_Object
-internal_condition_case_2 (bfun, nargs, args, handlers, hfun)
-     Lisp_Object (*bfun) ();
-     int nargs;
-     Lisp_Object *args;
-     Lisp_Object handlers;
-     Lisp_Object (*hfun) ();
+internal_condition_case_n (Lisp_Object (*bfun) (int, Lisp_Object*),
+                          int nargs,
+                          Lisp_Object *args,
+                          Lisp_Object handlers,
+                          Lisp_Object (*hfun) (Lisp_Object))
 {
   Lisp_Object val;
   struct catchtag c;
@@ -1595,8 +1607,8 @@ internal_condition_case_2 (bfun, nargs, args, handlers, hfun)
 }
 
 \f
-static Lisp_Object find_handler_clause P_ ((Lisp_Object, Lisp_Object,
-                                           Lisp_Object, Lisp_Object));
+static Lisp_Object find_handler_clause (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.
@@ -1612,16 +1624,13 @@ See Info anchor `(elisp)Definition of signal' for some details on how this
 error message is constructed.
 If the signal is handled, DATA is made available to the handler.
 See also the function `condition-case'.  */)
-     (error_symbol, data)
-     Lisp_Object error_symbol, data;
+  (Lisp_Object error_symbol, Lisp_Object data)
 {
   /* 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;
-  extern int gc_in_progress;
-  extern int waiting_for_input;
   Lisp_Object string;
   Lisp_Object real_error_symbol;
   struct backtrace *bp;
@@ -1725,8 +1734,7 @@ See also the function `condition-case'.  */)
    Used for anything but Qquit (which can return from Fsignal).  */
 
 void
-xsignal (error_symbol, data)
-     Lisp_Object error_symbol, data;
+xsignal (Lisp_Object error_symbol, Lisp_Object data)
 {
   Fsignal (error_symbol, data);
   abort ();
@@ -1735,29 +1743,25 @@ xsignal (error_symbol, data)
 /* Like xsignal, but takes 0, 1, 2, or 3 args instead of a list.  */
 
 void
-xsignal0 (error_symbol)
-     Lisp_Object error_symbol;
+xsignal0 (Lisp_Object error_symbol)
 {
   xsignal (error_symbol, Qnil);
 }
 
 void
-xsignal1 (error_symbol, arg)
-     Lisp_Object error_symbol, arg;
+xsignal1 (Lisp_Object error_symbol, Lisp_Object arg)
 {
   xsignal (error_symbol, list1 (arg));
 }
 
 void
-xsignal2 (error_symbol, arg1, arg2)
-     Lisp_Object error_symbol, arg1, arg2;
+xsignal2 (Lisp_Object error_symbol, Lisp_Object arg1, Lisp_Object arg2)
 {
   xsignal (error_symbol, list2 (arg1, arg2));
 }
 
 void
-xsignal3 (error_symbol, arg1, arg2, arg3)
-     Lisp_Object error_symbol, arg1, arg2, arg3;
+xsignal3 (Lisp_Object error_symbol, Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3)
 {
   xsignal (error_symbol, list3 (arg1, arg2, arg3));
 }
@@ -1766,9 +1770,7 @@ xsignal3 (error_symbol, arg1, arg2, arg3)
    If ARG is not a genuine list, make it a one-element list.  */
 
 void
-signal_error (s, arg)
-     char *s;
-     Lisp_Object arg;
+signal_error (const char *s, Lisp_Object arg)
 {
   Lisp_Object tortoise, hare;
 
@@ -1797,8 +1799,7 @@ signal_error (s, arg)
    a list containing one of CONDITIONS.  */
 
 static int
-wants_debugger (list, conditions)
-     Lisp_Object list, conditions;
+wants_debugger (Lisp_Object list, Lisp_Object conditions)
 {
   if (NILP (list))
     return 0;
@@ -1822,8 +1823,7 @@ wants_debugger (list, conditions)
    according to debugger-ignored-errors.  */
 
 static int
-skip_debugger (conditions, data)
-     Lisp_Object conditions, data;
+skip_debugger (Lisp_Object conditions, Lisp_Object data)
 {
   Lisp_Object tail;
   int first_string = 1;
@@ -1860,8 +1860,7 @@ skip_debugger (conditions, data)
    SIG and DATA describe the signal, as in find_handler_clause.  */
 
 static int
-maybe_call_debugger (conditions, sig, data)
-     Lisp_Object conditions, sig, data;
+maybe_call_debugger (Lisp_Object conditions, Lisp_Object sig, Lisp_Object data)
 {
   Lisp_Object combined_data;
 
@@ -1897,8 +1896,8 @@ maybe_call_debugger (conditions, sig, data)
    a second error here in case we're handling specpdl overflow.  */
 
 static Lisp_Object
-find_handler_clause (handlers, conditions, sig, data)
-     Lisp_Object handlers, conditions, sig, data;
+find_handler_clause (Lisp_Object handlers, Lisp_Object conditions,
+                    Lisp_Object sig, Lisp_Object data)
 {
   register Lisp_Object h;
   register Lisp_Object tem;
@@ -1987,13 +1986,10 @@ find_handler_clause (handlers, conditions, sig, data)
   return Qnil;
 }
 
-/* dump an error message; called like printf */
 
-/* VARARGS 1 */
+/* dump an error message; called like vprintf */
 void
-error (m, a1, a2, a3)
-     char *m;
-     char *a1, *a2, *a3;
+verror (const char *m, va_list ap)
 {
   char buf[200];
   int size = 200;
@@ -2003,15 +1999,12 @@ error (m, a1, a2, a3)
   int allocated = 0;
   Lisp_Object string;
 
-  args[0] = a1;
-  args[1] = a2;
-  args[2] = a3;
-
   mlen = strlen (m);
 
   while (1)
     {
-      int used = doprnt (buffer, size, m, m + mlen, 3, args);
+      int used;
+      used = doprnt (buffer, size, m, m + mlen, ap);
       if (used < size)
        break;
       size *= 2;
@@ -2030,6 +2023,19 @@ error (m, a1, a2, a3)
 
   xsignal1 (Qerror, string);
 }
+
+
+/* dump an error message; called like printf */
+
+/* VARARGS 1 */
+void
+error (const char *m, ...)
+{
+  va_list ap;
+  va_start (ap, m);
+  verror (m, ap);
+  va_end (ap);
+}
 \f
 DEFUN ("commandp", Fcommandp, Scommandp, 1, 2, 0,
        doc: /* Non-nil if FUNCTION makes provisions for interactive calling.
@@ -2046,8 +2052,7 @@ Also, a symbol satisfies `commandp' if its function definition does so.
 
 If the optional argument FOR-CALL-INTERACTIVELY is non-nil,
 then strings and vectors are not accepted.  */)
-     (function, for_call_interactively)
-     Lisp_Object function, for_call_interactively;
+  (Lisp_Object function, Lisp_Object for_call_interactively)
 {
   register Lisp_Object fun;
   register Lisp_Object funcar;
@@ -2111,11 +2116,8 @@ Third through fifth args give info about the real definition.
 They default to nil.
 If FUNCTION is already defined other than as an autoload,
 this does nothing and returns nil.  */)
-     (function, file, docstring, interactive, type)
-     Lisp_Object function, file, docstring, interactive, type;
+  (Lisp_Object function, Lisp_Object file, Lisp_Object docstring, Lisp_Object interactive, Lisp_Object type)
 {
-  Lisp_Object args[4];
-
   CHECK_SYMBOL (function);
   CHECK_STRING (file);
 
@@ -2131,16 +2133,18 @@ this does nothing and returns nil.  */)
     LOADHIST_ATTACH (Fcons (Qautoload, function));
   else
     /* We don't want the docstring in purespace (instead,
-       Snarf-documentation should (hopefully) overwrite it).  */
-    docstring = make_number (0);
+       Snarf-documentation should (hopefully) overwrite it).
+       We used to use 0 here, but that leads to accidental sharing in
+       purecopy's hash-consing, so we use a (hopefully) unique integer
+       instead.  */
+    docstring = make_number (XHASH (function));
   return Ffset (function,
                Fpurecopy (list5 (Qautoload, file, docstring,
                                  interactive, type)));
 }
 
 Lisp_Object
-un_autoload (oldqueue)
-     Lisp_Object oldqueue;
+un_autoload (Lisp_Object oldqueue)
 {
   register Lisp_Object queue, first, second;
 
@@ -2167,8 +2171,7 @@ un_autoload (oldqueue)
    FUNDEF is the autoload definition (a list).  */
 
 void
-do_autoload (fundef, funname)
-     Lisp_Object fundef, funname;
+do_autoload (Lisp_Object fundef, Lisp_Object funname)
 {
   int count = SPECPDL_INDEX ();
   Lisp_Object fun;
@@ -2193,7 +2196,7 @@ do_autoload (fundef, funname)
      the function.  We do this in the specific case of autoloading
      because autoloading is not an explicit request "load this file",
      but rather a request to "call this function".
-     
+
      The value saved here is to be restored into Vautoload_queue.  */
   record_unwind_protect (un_autoload, Vautoload_queue);
   Vautoload_queue = Qt;
@@ -2214,8 +2217,7 @@ do_autoload (fundef, funname)
 \f
 DEFUN ("eval", Feval, Seval, 1, 1, 0,
        doc: /* Evaluate FORM and return its value.  */)
-     (form)
-     Lisp_Object form;
+  (Lisp_Object form)
 {
   Lisp_Object fun, val, original_fun, original_args;
   Lisp_Object funcar;
@@ -2292,7 +2294,7 @@ DEFUN ("eval", Feval, Seval, 1, 1, 0,
       if (XSUBR (fun)->max_args == UNEVALLED)
        {
          backtrace.evalargs = 0;
-         val = (*XSUBR (fun)->function) (args_left);
+         val = (XSUBR (fun)->function.aUNEVALLED) (args_left);
          goto done;
        }
 
@@ -2319,7 +2321,7 @@ DEFUN ("eval", Feval, Seval, 1, 1, 0,
          backtrace.args = vals;
          backtrace.nargs = XINT (numargs);
 
-         val = (*XSUBR (fun)->function) (XINT (numargs), vals);
+         val = (XSUBR (fun)->function.aMANY) (XINT (numargs), vals);
          UNGCPRO;
          SAFE_FREE ();
          goto done;
@@ -2344,40 +2346,40 @@ DEFUN ("eval", Feval, Seval, 1, 1, 0,
       switch (i)
        {
        case 0:
-         val = (*XSUBR (fun)->function) ();
+         val = (XSUBR (fun)->function.a0) ();
          goto done;
        case 1:
-         val = (*XSUBR (fun)->function) (argvals[0]);
+         val = (XSUBR (fun)->function.a1) (argvals[0]);
          goto done;
        case 2:
-         val = (*XSUBR (fun)->function) (argvals[0], argvals[1]);
+         val = (XSUBR (fun)->function.a2) (argvals[0], argvals[1]);
          goto done;
        case 3:
-         val = (*XSUBR (fun)->function) (argvals[0], argvals[1],
-                                         argvals[2]);
+         val = (XSUBR (fun)->function.a3) (argvals[0], argvals[1],
+                                           argvals[2]);
          goto done;
        case 4:
-         val = (*XSUBR (fun)->function) (argvals[0], argvals[1],
-                                         argvals[2], argvals[3]);
+         val = (XSUBR (fun)->function.a4) (argvals[0], argvals[1],
+                                           argvals[2], argvals[3]);
          goto done;
        case 5:
-         val = (*XSUBR (fun)->function) (argvals[0], argvals[1], argvals[2],
-                                         argvals[3], argvals[4]);
+         val = (XSUBR (fun)->function.a5) (argvals[0], argvals[1], argvals[2],
+                                           argvals[3], argvals[4]);
          goto done;
        case 6:
-         val = (*XSUBR (fun)->function) (argvals[0], argvals[1], argvals[2],
-                                         argvals[3], argvals[4], argvals[5]);
+         val = (XSUBR (fun)->function.a6) (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]);
+         val = (XSUBR (fun)->function.a7) (argvals[0], argvals[1], argvals[2],
+                                           argvals[3], argvals[4], argvals[5],
+                                           argvals[6]);
          goto done;
 
        case 8:
-         val = (*XSUBR (fun)->function) (argvals[0], argvals[1], argvals[2],
-                                         argvals[3], argvals[4], argvals[5],
-                                         argvals[6], argvals[7]);
+         val = (XSUBR (fun)->function.a8) (argvals[0], argvals[1], argvals[2],
+                                           argvals[3], argvals[4], argvals[5],
+                                           argvals[6], argvals[7]);
          goto done;
 
        default:
@@ -2427,9 +2429,7 @@ DEFUN ("apply", Fapply, Sapply, 2, MANY, 0,
 Then return the value FUNCTION returns.
 Thus, (apply '+ 1 2 '(3 4)) returns 10.
 usage: (apply FUNCTION &rest ARGUMENTS)  */)
-     (nargs, args)
-     int nargs;
-     Lisp_Object *args;
+  (int nargs, Lisp_Object *args)
 {
   register int i, numargs;
   register Lisp_Object spread_arg;
@@ -2492,7 +2492,7 @@ usage: (apply FUNCTION &rest ARGUMENTS)  */)
       gcpro1.nvars = 1 + numargs;
     }
 
-  bcopy (args, funcall_args, nargs * sizeof (Lisp_Object));
+  memcpy (funcall_args, args, nargs * sizeof (Lisp_Object));
   /* Spread the last arg we got.  Its first element goes in
      the slot that it used to occupy, hence this value of I.  */
   i = nargs - 1;
@@ -2513,8 +2513,8 @@ usage: (apply FUNCTION &rest ARGUMENTS)  */)
 /* Run hook variables in various ways.  */
 
 enum run_hooks_condition {to_completion, until_success, until_failure};
-static Lisp_Object run_hook_with_args P_ ((int, Lisp_Object *,
-                                          enum run_hooks_condition));
+static Lisp_Object run_hook_with_args (int, Lisp_Object *,
+                                      enum run_hooks_condition);
 
 DEFUN ("run-hooks", Frun_hooks, Srun_hooks, 0, MANY, 0,
        doc: /* Run each hook in HOOKS.
@@ -2531,9 +2531,7 @@ hook; they should use `run-mode-hooks' instead.
 Do not use `make-local-variable' to make a hook variable buffer-local.
 Instead, use `add-hook' and specify t for the LOCAL argument.
 usage: (run-hooks &rest HOOKS)  */)
-     (nargs, args)
-     int nargs;
-     Lisp_Object *args;
+  (int nargs, Lisp_Object *args)
 {
   Lisp_Object hook[1];
   register int i;
@@ -2562,9 +2560,7 @@ as that may change.
 Do not use `make-local-variable' to make a hook variable buffer-local.
 Instead, use `add-hook' and specify t for the LOCAL argument.
 usage: (run-hook-with-args HOOK &rest ARGS)  */)
-     (nargs, args)
-     int nargs;
-     Lisp_Object *args;
+  (int nargs, Lisp_Object *args)
 {
   return run_hook_with_args (nargs, args, to_completion);
 }
@@ -2584,9 +2580,7 @@ However, if they all return nil, we return nil.
 Do not use `make-local-variable' to make a hook variable buffer-local.
 Instead, use `add-hook' and specify t for the LOCAL argument.
 usage: (run-hook-with-args-until-success HOOK &rest ARGS)  */)
-     (nargs, args)
-     int nargs;
-     Lisp_Object *args;
+  (int nargs, Lisp_Object *args)
 {
   return run_hook_with_args (nargs, args, until_success);
 }
@@ -2605,9 +2599,7 @@ Then we return nil.  However, if they all return non-nil, we return non-nil.
 Do not use `make-local-variable' to make a hook variable buffer-local.
 Instead, use `add-hook' and specify t for the LOCAL argument.
 usage: (run-hook-with-args-until-failure HOOK &rest ARGS)  */)
-     (nargs, args)
-     int nargs;
-     Lisp_Object *args;
+  (int nargs, Lisp_Object *args)
 {
   return run_hook_with_args (nargs, args, until_failure);
 }
@@ -2621,10 +2613,7 @@ usage: (run-hook-with-args-until-failure HOOK &rest ARGS)  */)
    except that it isn't necessary to gcpro ARGS[0].  */
 
 static Lisp_Object
-run_hook_with_args (nargs, args, cond)
-     int nargs;
-     Lisp_Object *args;
-     enum run_hooks_condition cond;
+run_hook_with_args (int nargs, Lisp_Object *args, enum run_hooks_condition cond)
 {
   Lisp_Object sym, val, ret;
   struct gcpro gcpro1, gcpro2, gcpro3;
@@ -2704,10 +2693,7 @@ run_hook_with_args (nargs, args, cond)
    except that it isn't necessary to gcpro ARGS[0].  */
 
 Lisp_Object
-run_hook_list_with_args (funlist, nargs, args)
-     Lisp_Object funlist;
-     int nargs;
-     Lisp_Object *args;
+run_hook_list_with_args (Lisp_Object funlist, int nargs, Lisp_Object *args)
 {
   Lisp_Object sym;
   Lisp_Object val;
@@ -2749,8 +2735,7 @@ run_hook_list_with_args (funlist, nargs, args)
 /* Run the hook HOOK, giving each function the two args ARG1 and ARG2.  */
 
 void
-run_hook_with_args_2 (hook, arg1, arg2)
-     Lisp_Object hook, arg1, arg2;
+run_hook_with_args_2 (Lisp_Object hook, Lisp_Object arg1, Lisp_Object arg2)
 {
   Lisp_Object temp[3];
   temp[0] = hook;
@@ -2762,8 +2747,7 @@ run_hook_with_args_2 (hook, arg1, arg2)
 \f
 /* Apply fn to arg */
 Lisp_Object
-apply1 (fn, arg)
-     Lisp_Object fn, arg;
+apply1 (Lisp_Object fn, Lisp_Object arg)
 {
   struct gcpro gcpro1;
 
@@ -2771,7 +2755,6 @@ apply1 (fn, arg)
   if (NILP (arg))
     RETURN_UNGCPRO (Ffuncall (1, &fn));
   gcpro1.nvars = 2;
-#ifdef NO_ARG_ARRAY
   {
     Lisp_Object args[2];
     args[0] = fn;
@@ -2779,15 +2762,11 @@ apply1 (fn, arg)
     gcpro1.var = args;
     RETURN_UNGCPRO (Fapply (2, args));
   }
-#else /* not NO_ARG_ARRAY */
-  RETURN_UNGCPRO (Fapply (2, &fn));
-#endif /* not NO_ARG_ARRAY */
 }
 
 /* Call function fn on no arguments */
 Lisp_Object
-call0 (fn)
-     Lisp_Object fn;
+call0 (Lisp_Object fn)
 {
   struct gcpro gcpro1;
 
@@ -2798,11 +2777,9 @@ call0 (fn)
 /* Call function fn with 1 argument arg1 */
 /* ARGSUSED */
 Lisp_Object
-call1 (fn, arg1)
-     Lisp_Object fn, arg1;
+call1 (Lisp_Object fn, Lisp_Object arg1)
 {
   struct gcpro gcpro1;
-#ifdef NO_ARG_ARRAY
   Lisp_Object args[2];
 
   args[0] = fn;
@@ -2810,21 +2787,14 @@ call1 (fn, arg1)
   GCPRO1 (args[0]);
   gcpro1.nvars = 2;
   RETURN_UNGCPRO (Ffuncall (2, args));
-#else /* not NO_ARG_ARRAY */
-  GCPRO1 (fn);
-  gcpro1.nvars = 2;
-  RETURN_UNGCPRO (Ffuncall (2, &fn));
-#endif /* not NO_ARG_ARRAY */
 }
 
 /* Call function fn with 2 arguments arg1, arg2 */
 /* ARGSUSED */
 Lisp_Object
-call2 (fn, arg1, arg2)
-     Lisp_Object fn, arg1, arg2;
+call2 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2)
 {
   struct gcpro gcpro1;
-#ifdef NO_ARG_ARRAY
   Lisp_Object args[3];
   args[0] = fn;
   args[1] = arg1;
@@ -2832,21 +2802,14 @@ call2 (fn, arg1, arg2)
   GCPRO1 (args[0]);
   gcpro1.nvars = 3;
   RETURN_UNGCPRO (Ffuncall (3, args));
-#else /* not NO_ARG_ARRAY */
-  GCPRO1 (fn);
-  gcpro1.nvars = 3;
-  RETURN_UNGCPRO (Ffuncall (3, &fn));
-#endif /* not NO_ARG_ARRAY */
 }
 
 /* Call function fn with 3 arguments arg1, arg2, arg3 */
 /* ARGSUSED */
 Lisp_Object
-call3 (fn, arg1, arg2, arg3)
-     Lisp_Object fn, arg1, arg2, arg3;
+call3 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3)
 {
   struct gcpro gcpro1;
-#ifdef NO_ARG_ARRAY
   Lisp_Object args[4];
   args[0] = fn;
   args[1] = arg1;
@@ -2855,21 +2818,15 @@ call3 (fn, arg1, arg2, arg3)
   GCPRO1 (args[0]);
   gcpro1.nvars = 4;
   RETURN_UNGCPRO (Ffuncall (4, args));
-#else /* not NO_ARG_ARRAY */
-  GCPRO1 (fn);
-  gcpro1.nvars = 4;
-  RETURN_UNGCPRO (Ffuncall (4, &fn));
-#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;
+call4 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3,
+       Lisp_Object arg4)
 {
   struct gcpro gcpro1;
-#ifdef NO_ARG_ARRAY
   Lisp_Object args[5];
   args[0] = fn;
   args[1] = arg1;
@@ -2879,21 +2836,15 @@ call4 (fn, arg1, arg2, arg3, 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;
+call5 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3,
+       Lisp_Object arg4, Lisp_Object arg5)
 {
   struct gcpro gcpro1;
-#ifdef NO_ARG_ARRAY
   Lisp_Object args[6];
   args[0] = fn;
   args[1] = arg1;
@@ -2904,21 +2855,15 @@ call5 (fn, arg1, arg2, arg3, arg4, 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;
+call6 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3,
+       Lisp_Object arg4, Lisp_Object arg5, Lisp_Object arg6)
 {
   struct gcpro gcpro1;
-#ifdef NO_ARG_ARRAY
   Lisp_Object args[7];
   args[0] = fn;
   args[1] = arg1;
@@ -2930,11 +2875,27 @@ call6 (fn, arg1, arg2, arg3, arg4, arg5, 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 */
+}
+
+/* Call function fn with 7 arguments arg1, arg2, arg3, arg4, arg5, arg6, arg7 */
+/* ARGSUSED */
+Lisp_Object
+call7 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3,
+       Lisp_Object arg4, Lisp_Object arg5, Lisp_Object arg6, Lisp_Object arg7)
+{
+  struct gcpro gcpro1;
+  Lisp_Object args[8];
+  args[0] = fn;
+  args[1] = arg1;
+  args[2] = arg2;
+  args[3] = arg3;
+  args[4] = arg4;
+  args[5] = arg5;
+  args[6] = arg6;
+  args[7] = arg7;
+  GCPRO1 (args[0]);
+  gcpro1.nvars = 8;
+  RETURN_UNGCPRO (Ffuncall (8, args));
 }
 
 /* The caller should GCPRO all the elements of ARGS.  */
@@ -2944,9 +2905,7 @@ DEFUN ("funcall", Ffuncall, Sfuncall, 1, MANY, 0,
 Return the value that function returns.
 Thus, (funcall 'cons 'x 'y) returns (x . y).
 usage: (funcall FUNCTION &rest ARGUMENTS)  */)
-     (nargs, args)
-     int nargs;
-     Lisp_Object *args;
+  (int nargs, Lisp_Object *args)
 {
   Lisp_Object fun, original_fun;
   Lisp_Object funcar;
@@ -3009,14 +2968,14 @@ usage: (funcall FUNCTION &rest ARGUMENTS)  */)
 
       if (XSUBR (fun)->max_args == MANY)
        {
-         val = (*XSUBR (fun)->function) (numargs, args + 1);
+         val = (XSUBR (fun)->function.aMANY) (numargs, args + 1);
          goto done;
        }
 
       if (XSUBR (fun)->max_args > numargs)
        {
          internal_args = (Lisp_Object *) alloca (XSUBR (fun)->max_args * sizeof (Lisp_Object));
-         bcopy (args + 1, internal_args, numargs * sizeof (Lisp_Object));
+         memcpy (internal_args, args + 1, numargs * sizeof (Lisp_Object));
          for (i = numargs; i < XSUBR (fun)->max_args; i++)
            internal_args[i] = Qnil;
        }
@@ -3025,44 +2984,44 @@ usage: (funcall FUNCTION &rest ARGUMENTS)  */)
       switch (XSUBR (fun)->max_args)
        {
        case 0:
-         val = (*XSUBR (fun)->function) ();
+         val = (XSUBR (fun)->function.a0) ();
          goto done;
        case 1:
-         val = (*XSUBR (fun)->function) (internal_args[0]);
+         val = (XSUBR (fun)->function.a1) (internal_args[0]);
          goto done;
        case 2:
-         val = (*XSUBR (fun)->function) (internal_args[0], internal_args[1]);
+         val = (XSUBR (fun)->function.a2) (internal_args[0], internal_args[1]);
          goto done;
        case 3:
-         val = (*XSUBR (fun)->function) (internal_args[0], internal_args[1],
-                                         internal_args[2]);
+         val = (XSUBR (fun)->function.a3) (internal_args[0], internal_args[1],
+                                           internal_args[2]);
          goto done;
        case 4:
-         val = (*XSUBR (fun)->function) (internal_args[0], internal_args[1],
-                                         internal_args[2], internal_args[3]);
+         val = (XSUBR (fun)->function.a4) (internal_args[0], internal_args[1],
+                                           internal_args[2], internal_args[3]);
          goto done;
        case 5:
-         val = (*XSUBR (fun)->function) (internal_args[0], internal_args[1],
-                                         internal_args[2], internal_args[3],
-                                         internal_args[4]);
+         val = (XSUBR (fun)->function.a5) (internal_args[0], internal_args[1],
+                                           internal_args[2], internal_args[3],
+                                           internal_args[4]);
          goto done;
        case 6:
-         val = (*XSUBR (fun)->function) (internal_args[0], internal_args[1],
-                                         internal_args[2], internal_args[3],
-                                         internal_args[4], internal_args[5]);
+         val = (XSUBR (fun)->function.a6) (internal_args[0], internal_args[1],
+                                           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]);
+         val = (XSUBR (fun)->function.a7) (internal_args[0], internal_args[1],
+                                           internal_args[2], internal_args[3],
+                                           internal_args[4], internal_args[5],
+                                           internal_args[6]);
          goto done;
 
        case 8:
-         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], internal_args[7]);
+         val = (XSUBR (fun)->function.a8) (internal_args[0], internal_args[1],
+                                           internal_args[2], internal_args[3],
+                                           internal_args[4], internal_args[5],
+                                           internal_args[6], internal_args[7]);
          goto done;
 
        default:
@@ -3105,9 +3064,7 @@ usage: (funcall FUNCTION &rest ARGUMENTS)  */)
 }
 \f
 Lisp_Object
-apply_lambda (fun, args, eval_flag)
-     Lisp_Object fun, args;
-     int eval_flag;
+apply_lambda (Lisp_Object fun, Lisp_Object args, int eval_flag)
 {
   Lisp_Object args_left;
   Lisp_Object numargs;
@@ -3156,10 +3113,7 @@ apply_lambda (fun, args, eval_flag)
    FUN must be either a lambda-expression or a compiled-code object.  */
 
 static Lisp_Object
-funcall_lambda (fun, nargs, arg_vector)
-     Lisp_Object fun;
-     int nargs;
-     register Lisp_Object *arg_vector;
+funcall_lambda (Lisp_Object fun, int nargs, register Lisp_Object *arg_vector)
 {
   Lisp_Object val, syms_left, next;
   int count = SPECPDL_INDEX ();
@@ -3228,8 +3182,7 @@ funcall_lambda (fun, nargs, arg_vector)
 DEFUN ("fetch-bytecode", Ffetch_bytecode, Sfetch_bytecode,
        1, 1, 0,
        doc: /* If byte-compiled OBJECT is lazy-loaded, fetch it now.  */)
-     (object)
-     Lisp_Object object;
+  (Lisp_Object object)
 {
   Lisp_Object tem;
 
@@ -3251,7 +3204,7 @@ DEFUN ("fetch-bytecode", Ffetch_bytecode, Sfetch_bytecode,
 }
 \f
 void
-grow_specpdl ()
+grow_specpdl (void)
 {
   register int count = SPECPDL_INDEX ();
   if (specpdl_size >= max_specpdl_size)
@@ -3268,89 +3221,120 @@ grow_specpdl ()
   specpdl_ptr = specpdl + count;
 }
 
+/* specpdl_ptr->symbol is a field which describes which variable is
+   let-bound, so it can be properly undone when we unbind_to.
+   It can have the following two shapes:
+   - SYMBOL : if it's a plain symbol, it means that we have let-bound
+     a symbol that is not buffer-local (at least at the time
+     the let binding started).  Note also that it should not be
+     aliased (i.e. when let-binding V1 that's aliased to V2, we want
+     to record V2 here).
+   - (SYMBOL WHERE . BUFFER) : this means that it is a let-binding for
+     variable SYMBOL which can be buffer-local.  WHERE tells us
+     which buffer is affected (or nil if the let-binding affects the
+     global value of the variable) and BUFFER tells us which buffer was
+     current (i.e. if WHERE is non-nil, then BUFFER==WHERE, otherwise
+     BUFFER did not yet have a buffer-local value).  */
+
 void
-specbind (symbol, value)
-     Lisp_Object symbol, value;
+specbind (Lisp_Object symbol, Lisp_Object value)
 {
-  Lisp_Object valcontents;
+  struct Lisp_Symbol *sym;
+
+  eassert (!handling_signal);
 
   CHECK_SYMBOL (symbol);
+  sym = XSYMBOL (symbol);
   if (specpdl_ptr == specpdl + specpdl_size)
     grow_specpdl ();
 
-  /* The most common case is that of a non-constant symbol with a
-     trivial value.  Make that as fast as we can.  */
-  valcontents = SYMBOL_VALUE (symbol);
-  if (!MISCP (valcontents) && !SYMBOL_CONSTANT_P (symbol))
+ start:
+  switch (sym->redirect)
     {
+    case SYMBOL_VARALIAS:
+      sym = indirect_variable (sym); XSETSYMBOL (symbol, sym); goto start;
+    case SYMBOL_PLAINVAL:
+      /* The most common case is that of a non-constant symbol with a
+        trivial value.  Make that as fast as we can.  */
       specpdl_ptr->symbol = symbol;
-      specpdl_ptr->old_value = valcontents;
+      specpdl_ptr->old_value = SYMBOL_VAL (sym);
       specpdl_ptr->func = NULL;
       ++specpdl_ptr;
-      SET_SYMBOL_VALUE (symbol, value);
-    }
-  else
-    {
-      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)
-         || BUFFER_OBJFWDP (valcontents))
-       {
-         Lisp_Object where, current_buffer;
-
-         current_buffer = Fcurrent_buffer ();
-
-         /* For a local variable, record both the symbol and which
-            buffer's or frame's value we are saving.  */
-         if (!NILP (Flocal_variable_p (symbol, Qnil)))
-           where = current_buffer;
-         else if (BUFFER_LOCAL_VALUEP (valcontents)
-                  && XBUFFER_LOCAL_VALUE (valcontents)->found_for_frame)
-           where = XBUFFER_LOCAL_VALUE (valcontents)->frame;
-         else
-           where = Qnil;
-
-         /* We're not using the `unused' slot in the specbinding
-            structure because this would mean we have to do more
-            work for simple variables.  */
-         specpdl_ptr->symbol = Fcons (symbol, Fcons (where, current_buffer));
-
-         /* If SYMBOL is a per-buffer variable which doesn't have a
-            buffer-local value here, make the `let' change the global
-            value by changing the value of SYMBOL in all buffers not
-            having their own value.  This is consistent with what
-            happens with other buffer-local variables.  */
-         if (NILP (where)
-             && BUFFER_OBJFWDP (valcontents))
-           {
-             ++specpdl_ptr;
-             Fset_default (symbol, value);
-             return;
-           }
-       }
+      if (!sym->constant)
+       SET_SYMBOL_VAL (sym, value);
       else
-       specpdl_ptr->symbol = symbol;
-
-      specpdl_ptr++;
-      /* 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);
+       set_internal (symbol, value, Qnil, 1);
+      break;
+    case SYMBOL_LOCALIZED:
+      if (SYMBOL_BLV (sym)->frame_local)
+       error ("Frame-local vars cannot be let-bound");
+    case SYMBOL_FORWARDED:
+      {
+       Lisp_Object ovalue = find_symbol_value (symbol);
+       specpdl_ptr->func = 0;
+       specpdl_ptr->old_value = ovalue;
+
+       eassert (sym->redirect != SYMBOL_LOCALIZED
+                || (EQ (SYMBOL_BLV (sym)->where,
+                        SYMBOL_BLV (sym)->frame_local ?
+                        Fselected_frame () : Fcurrent_buffer ())));
+
+       if (sym->redirect == SYMBOL_LOCALIZED
+           || BUFFER_OBJFWDP (SYMBOL_FWD (sym)))
+         {
+           Lisp_Object where, cur_buf = Fcurrent_buffer ();
+
+           /* For a local variable, record both the symbol and which
+              buffer's or frame's value we are saving.  */
+           if (!NILP (Flocal_variable_p (symbol, Qnil)))
+             {
+               eassert (sym->redirect != SYMBOL_LOCALIZED
+                        || (BLV_FOUND (SYMBOL_BLV (sym))
+                            && EQ (cur_buf, SYMBOL_BLV (sym)->where)));
+               where = cur_buf;
+             }
+           else if (sym->redirect == SYMBOL_LOCALIZED
+                    && BLV_FOUND (SYMBOL_BLV (sym)))
+             where = SYMBOL_BLV (sym)->where;
+           else
+             where = Qnil;
+
+           /* We're not using the `unused' slot in the specbinding
+              structure because this would mean we have to do more
+              work for simple variables.  */
+           /* FIXME: The third value `current_buffer' is only used in
+              let_shadows_buffer_binding_p which is itself only used
+              in set_internal for local_if_set.  */
+           eassert (NILP (where) || EQ (where, cur_buf));
+           specpdl_ptr->symbol = Fcons (symbol, Fcons (where, cur_buf));
+
+           /* If SYMBOL is a per-buffer variable which doesn't have a
+              buffer-local value here, make the `let' change the global
+              value by changing the value of SYMBOL in all buffers not
+              having their own value.  This is consistent with what
+              happens with other buffer-local variables.  */
+           if (NILP (where)
+               && sym->redirect == SYMBOL_FORWARDED)
+             {
+               eassert (BUFFER_OBJFWDP (SYMBOL_FWD (sym)));
+               ++specpdl_ptr;
+               Fset_default (symbol, value);
+               return;
+             }
+         }
+       else
+         specpdl_ptr->symbol = symbol;
+
+       specpdl_ptr++;
+       set_internal (symbol, value, Qnil, 1);
+       break;
+      }
+    default: abort ();
     }
 }
 
 void
-record_unwind_protect (function, arg)
-     Lisp_Object (*function) P_ ((Lisp_Object));
-     Lisp_Object arg;
+record_unwind_protect (Lisp_Object (*function) (Lisp_Object), Lisp_Object arg)
 {
   eassert (!handling_signal);
 
@@ -3363,9 +3347,7 @@ record_unwind_protect (function, arg)
 }
 
 Lisp_Object
-unbind_to (count, value)
-     int count;
-     Lisp_Object value;
+unbind_to (int count, Lisp_Object value)
 {
   Lisp_Object quitf = Vquit_flag;
   struct gcpro gcpro1, gcpro2;
@@ -3392,7 +3374,7 @@ unbind_to (count, value)
         bound a variable that had a buffer-local or frame-local
         binding.  WHERE nil means that the variable had the default
         value when it was bound.  CURRENT-BUFFER is the buffer that
-         was current when the variable was bound.  */
+        was current when the variable was bound.  */
       else if (CONSP (this_binding.symbol))
        {
          Lisp_Object symbol, where;
@@ -3402,21 +3384,23 @@ unbind_to (count, value)
 
          if (NILP (where))
            Fset_default (symbol, this_binding.old_value);
-         else if (BUFFERP (where))
-           set_internal (symbol, this_binding.old_value, XBUFFER (where), 1);
-         else
-           set_internal (symbol, this_binding.old_value, NULL, 1);
+         /* If `where' is non-nil, reset the value in the appropriate
+            local binding, but only if that binding still exists.  */
+         else if (BUFFERP (where)
+                  ? !NILP (Flocal_variable_p (symbol, where))
+                  : !NILP (Fassq (symbol, XFRAME (where)->param_alist)))
+           set_internal (symbol, this_binding.old_value, where, 1);
        }
+      /* If variable has a trivial value (no forwarding), we can
+        just set it.  No need to check for constant symbols here,
+        since that was already done by specbind.  */
+      else if (XSYMBOL (this_binding.symbol)->redirect == SYMBOL_PLAINVAL)
+       SET_SYMBOL_VAL (XSYMBOL (this_binding.symbol),
+                       this_binding.old_value);
       else
-       {
-         /* If variable has a trivial value (no forwarding), we can
-            just set it.  No need to check for constant symbols here,
-            since that was already done by specbind.  */
-         if (!MISCP (SYMBOL_VALUE (this_binding.symbol)))
-           SET_SYMBOL_VALUE (this_binding.symbol, this_binding.old_value);
-         else
-           set_internal (this_binding.symbol, this_binding.old_value, 0, 1);
-       }
+       /* NOTE: we only ever come here if make_local_foo was used for
+          the first time on this var within this let.  */
+       Fset_default (this_binding.symbol, this_binding.old_value);
     }
 
   if (NILP (Vquit_flag) && !NILP (quitf))
@@ -3429,8 +3413,7 @@ unbind_to (count, value)
 DEFUN ("backtrace-debug", Fbacktrace_debug, Sbacktrace_debug, 2, 2, 0,
        doc: /* Set the debug-on-exit flag of eval frame LEVEL levels down to FLAG.
 The debugger is entered when that frame exits, if the flag is non-nil.  */)
-     (level, flag)
-     Lisp_Object level, flag;
+  (Lisp_Object level, Lisp_Object flag)
 {
   register struct backtrace *backlist = backtrace_list;
   register int i;
@@ -3451,13 +3434,12 @@ The debugger is entered when that frame exits, if the flag is non-nil.  */)
 DEFUN ("backtrace", Fbacktrace, Sbacktrace, 0, 0, "",
        doc: /* Print a trace of Lisp function calls currently active.
 Output stream used is value of `standard-output'.  */)
-     ()
+  (void)
 {
   register struct backtrace *backlist = backtrace_list;
   register int i;
   Lisp_Object tail;
   Lisp_Object tem;
-  extern Lisp_Object Vprint_level;
   struct gcpro gcpro1;
 
   XSETFASTINT (Vprint_level, 3);
@@ -3516,8 +3498,7 @@ A &rest arg is represented as the tail of the list ARG-VALUES.
 FUNCTION is whatever was supplied as car of evaluated list,
 or a lambda expression for macro calls.
 If NFRAMES is more than the number of frames, the value is nil.  */)
-     (nframes)
-     Lisp_Object nframes;
+  (Lisp_Object nframes)
 {
   register struct backtrace *backlist = backtrace_list;
   register int i;
@@ -3546,7 +3527,7 @@ If NFRAMES is more than the number of frames, the value is nil.  */)
 
 \f
 void
-mark_backtrace ()
+mark_backtrace (void)
 {
   register struct backtrace *backlist;
   register int i;
@@ -3565,7 +3546,7 @@ mark_backtrace ()
 }
 
 void
-syms_of_eval ()
+syms_of_eval (void)
 {
   DEFVAR_INT ("max-specpdl-size", &max_specpdl_size,
              doc: /* *Limit on number of Lisp variable bindings and `unwind-protect's.