Replace bcopy, bzero, bcmp by memcpy, memmove, memset, memcmp
[bpt/emacs.git] / src / eval.c
index 184455f..47c46fc 100644 (file)
@@ -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"
@@ -169,19 +170,19 @@ 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;
+static Lisp_Object funcall_lambda (Lisp_Object, int, Lisp_Object*);
+static void unwind_to_catch (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));
+Lisp_Object apply1 (Lisp_Object fn, Lisp_Object arg) __attribute__((noinline));
+Lisp_Object call2 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2) __attribute__((noinline));
 #endif
 \f
 void
-init_eval_once ()
+init_eval_once (void)
 {
   specpdl_size = 50;
   specpdl = (struct specbinding *) xmalloc (specpdl_size * sizeof (struct specbinding));
@@ -194,7 +195,7 @@ init_eval_once ()
 }
 
 void
-init_eval ()
+init_eval (void)
 {
   specpdl_ptr = specpdl;
   catchlist = 0;
@@ -213,8 +214,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 +224,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 +280,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;
@@ -608,8 +606,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;
@@ -770,11 +767,8 @@ The return value is BASE-VARIABLE.  */)
   sym = XSYMBOL (new_alias);
 
   if (sym->constant)
-    if (sym->redirect == SYMBOL_VARALIAS)
-      sym->constant = 0;       /* Reset.  */
-    else
-      /* Not sure why.  */
-      error ("Cannot make a constant an alias");
+    /* Not sure why, but why not?  */
+    error ("Cannot make a constant an alias");
 
   switch (sym->redirect)
     {
@@ -789,7 +783,7 @@ The return value is BASE-VARIABLE.  */)
      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), NULL, 1);
+    set_internal (base_variable, find_symbol_value (new_alias), Qnil, 1);
 
   {
     struct specbinding *p;
@@ -934,8 +928,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;
 }
@@ -1221,10 +1214,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;
@@ -1269,9 +1259,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;
 
@@ -1402,9 +1390,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;
@@ -1471,10 +1458,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;
@@ -1518,11 +1503,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;
@@ -1563,17 +1545,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;
@@ -1615,8 +1644,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.
@@ -1745,8 +1774,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 ();
@@ -1755,29 +1783,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));
 }
@@ -1786,9 +1810,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 (char *s, Lisp_Object arg)
 {
   Lisp_Object tortoise, hare;
 
@@ -1817,8 +1839,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;
@@ -1842,8 +1863,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;
@@ -1880,8 +1900,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;
 
@@ -1917,8 +1936,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;
@@ -2134,8 +2153,6 @@ this does nothing and returns nil.  */)
      (function, file, docstring, interactive, type)
      Lisp_Object function, file, docstring, interactive, type;
 {
-  Lisp_Object args[4];
-
   CHECK_SYMBOL (function);
   CHECK_STRING (file);
 
@@ -2151,16 +2168,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;
 
@@ -2187,8 +2206,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;
@@ -2213,7 +2231,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;
@@ -2312,7 +2330,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.a1) (args_left);
          goto done;
        }
 
@@ -2338,7 +2356,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.am) (XINT (numargs), vals);
          UNGCPRO;
          goto done;
        }
@@ -2362,40 +2380,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:
@@ -2511,7 +2529,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;
@@ -2528,8 +2546,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.
@@ -2636,10 +2654,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;
@@ -2719,10 +2734,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;
@@ -2764,8 +2776,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;
@@ -2777,8 +2788,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;
 
@@ -2797,8 +2807,7 @@ apply1 (fn, arg)
 
 /* Call function fn on no arguments */
 Lisp_Object
-call0 (fn)
-     Lisp_Object fn;
+call0 (Lisp_Object fn)
 {
   struct gcpro gcpro1;
 
@@ -2809,8 +2818,7 @@ 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;
   Lisp_Object args[2];
@@ -2825,8 +2833,7 @@ call1 (fn, arg1)
 /* 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;
   Lisp_Object args[3];
@@ -2841,8 +2848,7 @@ call2 (fn, arg1, arg2)
 /* 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;
   Lisp_Object args[4];
@@ -2858,8 +2864,8 @@ call3 (fn, arg1, arg2, arg3)
 /* 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;
   Lisp_Object args[5];
@@ -2876,8 +2882,8 @@ call4 (fn, arg1, arg2, arg3, arg4)
 /* 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;
   Lisp_Object args[6];
@@ -2895,8 +2901,8 @@ call5 (fn, arg1, arg2, arg3, arg4, arg5)
 /* 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;
   Lisp_Object args[7];
@@ -2915,8 +2921,8 @@ call6 (fn, arg1, arg2, arg3, arg4, arg5, arg6)
 /* Call function fn with 7 arguments arg1, arg2, arg3, arg4, arg5, arg6, arg7 */
 /* ARGSUSED */
 Lisp_Object
-call7 (fn, arg1, arg2, arg3, arg4, arg5, arg6, arg7)
-     Lisp_Object fn, arg1, arg2, arg3, arg4, arg5, arg6, arg7;
+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];
@@ -3005,14 +3011,14 @@ usage: (funcall FUNCTION &rest ARGUMENTS)  */)
 
       if (XSUBR (fun)->max_args == MANY)
        {
-         val = (*XSUBR (fun)->function) (numargs, args + 1);
+         val = (XSUBR (fun)->function.am) (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;
        }
@@ -3021,44 +3027,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:
@@ -3101,9 +3107,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;
@@ -3150,10 +3154,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 ();
@@ -3245,7 +3246,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)
@@ -3262,9 +3263,23 @@ 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)
 {
   struct Lisp_Symbol *sym;
 
@@ -3290,10 +3305,13 @@ specbind (symbol, value)
          if (!sym->constant)
            SET_SYMBOL_VAL (sym, value);
          else
-           set_internal (symbol, value, 0, 1);
+           set_internal (symbol, value, Qnil, 1);
          break;
        }
-    case SYMBOL_LOCALIZED: case SYMBOL_FORWARDED:
+    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;
@@ -3330,6 +3348,7 @@ specbind (symbol, value)
            /* 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
@@ -3350,7 +3369,7 @@ specbind (symbol, value)
          specpdl_ptr->symbol = symbol;
 
        specpdl_ptr++;
-       set_internal (symbol, value, 0, 1);
+       set_internal (symbol, value, Qnil, 1);
        break;
       }
     default: abort ();
@@ -3358,9 +3377,7 @@ specbind (symbol, value)
 }
 
 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);
 
@@ -3373,9 +3390,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;
@@ -3412,27 +3427,23 @@ unbind_to (count, value)
 
          if (NILP (where))
            Fset_default (symbol, this_binding.old_value);
-         else if (BUFFERP (where))
-           if (!NILP (Flocal_variable_p (symbol, where)))
-             set_internal (symbol, this_binding.old_value, XBUFFER (where), 1);
-           /* else if (!NILP (Fbuffer_live_p (where)))
-             error ("Unbinding local %s to global!", symbol); */
-            else
-              ;
-         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 (XSYMBOL (this_binding.symbol)->redirect == SYMBOL_PLAINVAL)
-           SET_SYMBOL_VAL (XSYMBOL (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))
@@ -3562,7 +3573,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;
@@ -3581,7 +3592,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.