(evaporate_overlays): Overlay is in car, not cdr.
[bpt/emacs.git] / src / eval.c
index 445ff08..f5631c3 100644 (file)
@@ -1,5 +1,5 @@
 /* Evaluator for GNU Emacs Lisp interpreter.
-   Copyright (C) 1985, 1986, 1987, 1992 Free Software Foundation, Inc.
+   Copyright (C) 1985, 1986, 1987, 1993, 1994 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -18,7 +18,7 @@ along with GNU Emacs; see the file COPYING.  If not, write to
 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 
-#include "config.h"
+#include <config.h>
 #include "lisp.h"
 #include "blockinput.h"
 
@@ -149,9 +149,11 @@ extern Lisp_Object ml_apply (); /* Apply a mocklisp function to unevaluated argu
 init_eval_once ()
 {
   specpdl_size = 50;
-  specpdl = (struct specbinding *) malloc (specpdl_size * sizeof (struct specbinding));
+  specpdl = (struct specbinding *) xmalloc (specpdl_size * sizeof (struct specbinding));
   max_specpdl_size = 600;
   max_lisp_eval_depth = 200;
+
+  Vrun_hooks = Qnil;
 }
 
 init_eval ()
@@ -163,7 +165,8 @@ init_eval ()
   Vquit_flag = Qnil;
   debug_on_next_call = 0;
   lisp_eval_depth = 0;
-  when_entered_debugger = 0;
+  /* This is less than the initial value of num_nonmacro_input_chars.  */
+  when_entered_debugger = -1;
 }
 
 Lisp_Object
@@ -377,7 +380,7 @@ whose values are discarded.")
 }
 
 DEFUN ("prog2", Fprog2, Sprog2, 2, UNEVALLED, 0,
-  "(prog1 X Y BODY...): eval X, Y and BODY sequentially; value from Y.\n\
+  "(prog2 X Y BODY...): eval X, Y and BODY sequentially; value from Y.\n\
 The value of Y is saved during the evaluation of the remaining args,\n\
 whose values are discarded.")
   (args)
@@ -390,7 +393,7 @@ whose values are discarded.")
 
   val = Qnil;
 
-  if (NILP(args))
+  if (NILP (args))
     return Qnil;
 
   args_left = args;
@@ -405,7 +408,7 @@ whose values are discarded.")
        Feval (Fcar (args_left));
       args_left = Fcdr (args_left);
     }
-  while (!NILP(args_left));
+  while (!NILP (args_left));
 
   UNGCPRO;
   return val;
@@ -413,8 +416,12 @@ whose values are discarded.")
 
 DEFUN ("setq", Fsetq, Ssetq, 0, UNEVALLED, 0,
   "(setq SYM VAL SYM VAL ...): set each SYM to the value of its VAL.\n\
-The SYMs are not evaluated.  Thus (setq x y) sets x to the value of y.\n\
-Each SYM is set before the next VAL is computed.")
+The symbols SYM are variables; they are literal (not evaluated).\n\
+The values VAL are expressions; they are evaluated.\n\
+Thus, (setq x (1+ y)) sets `x' to the value of `(1+ y)'.\n\
+The second VAL is not computed until after the first SYM is set, and so on;\n\
+each VAL can use the new value of variables set earlier in the `setq'.\n\
+The return value of the `setq' form is the value of the last VAL.")
   (args)
      Lisp_Object args;
 {
@@ -746,7 +753,8 @@ until TEST returns nil.")
 
   test = Fcar (args);
   body = Fcdr (args);
-  while (tem = Feval (test), !NILP (tem))
+  while (tem = Feval (test),
+        (!EQ (Vmocklisp_arguments, Qt) ? XINT (tem) : !NILP (tem)))
     {
       QUIT;
       Fprogn (body);
@@ -808,8 +816,7 @@ definitions to shadow the loaded ones for use in file byte-compilation.")
            {
              /* Autoloading function: will it be a macro when loaded?  */
              tem = Fnth (make_number (4), def);
-             if (EQ (XCONS (tem)->car, Qt)
-                 || EQ (XCONS (tem)->car, Qmacro))
+             if (EQ (tem, Qt) || EQ (tem, Qmacro))
                /* Yes, load it and try again.  */
                {
                  do_autoload (def, sym);
@@ -912,10 +919,7 @@ unwind_to_catch (catch, value)
   catch->val = value;
 
   /* Restore the polling-suppression count.  */
-  if (catch->poll_suppress_count > poll_suppress_count)
-    abort ();
-  while (catch->poll_suppress_count < poll_suppress_count)
-    start_polling ();
+  set_poll_suppress_count (catch->poll_suppress_count);
 
   do
     {
@@ -992,6 +996,9 @@ A handler is applicable to an error\n\
 if CONDITION-NAME is one of the error's condition names.\n\
 If an error happens, the first applicable handler is run.\n\
 \n\
+The car of a handler may be a list of condition names\n\
+instead of a single condition name.\n\
+\n\
 When a handler handles an error,\n\
 control returns to the condition-case and the handler BODY... is executed\n\
 with VAR bound to (SIGNALED-CONDITIONS . SIGNAL-DATA).\n\
@@ -1016,8 +1023,10 @@ See also the function `signal' for more info.")
     {
       Lisp_Object tem;
       tem = Fcar (val);
-      if ((!NILP (tem)) &&
-         (!CONSP (tem) || (XTYPE (XCONS (tem)->car) != Lisp_Symbol)))
+      if (! (NILP (tem)
+            || (CONSP (tem)
+                && (SYMBOLP (XCONS (tem)->car)
+                    || CONSP (XCONS (tem)->car)))))
        error ("Invalid condition handler", tem);
     }
 
@@ -1032,8 +1041,8 @@ See also the function `signal' for more info.")
   if (_setjmp (c.jmp))
     {
       if (!NILP (h.var))
-        specbind (h.var, Fcdr (c.val));
-      val = Fprogn (Fcdr (Fcar (c.val)));
+        specbind (h.var, c.val);
+      val = Fprogn (Fcdr (h.chosen_clause));
 
       /* Note that this just undoes the binding of h.var; whoever
         longjumped to us unwound the stack to c.pdlcount before
@@ -1076,7 +1085,7 @@ internal_condition_case (bfun, handlers, hfun)
   c.gcpro = gcprolist;
   if (_setjmp (c.jmp))
     {
-      return (*hfun) (Fcdr (c.val));
+      return (*hfun) (c.val);
     }
   c.next = catchlist;
   catchlist = &c;
@@ -1092,12 +1101,49 @@ internal_condition_case (bfun, handlers, hfun)
   return val;
 }
 
+Lisp_Object
+internal_condition_case_1 (bfun, arg, handlers, hfun)
+     Lisp_Object (*bfun) ();
+     Lisp_Object arg;
+     Lisp_Object handlers;
+     Lisp_Object (*hfun) ();
+{
+  Lisp_Object val;
+  struct catchtag c;
+  struct handler h;
+
+  c.tag = Qnil;
+  c.val = Qnil;
+  c.backlist = backtrace_list;
+  c.handlerlist = handlerlist;
+  c.lisp_eval_depth = lisp_eval_depth;
+  c.pdlcount = specpdl_ptr - specpdl;
+  c.poll_suppress_count = poll_suppress_count;
+  c.gcpro = gcprolist;
+  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) (arg);
+  catchlist = c.next;
+  handlerlist = h.next;
+  return val;
+}
+\f
 static Lisp_Object find_handler_clause ();
 
 DEFUN ("signal", Fsignal, Ssignal, 2, 2, 0,
-  "Signal an error.  Args are SIGNAL-NAME, and associated DATA.\n\
+  "Signal an error.  Args are ERROR-SYMBOL and associated DATA.\n\
 This function does not return.\n\n\
-A signal name is a symbol with an `error-conditions' property\n\
+An error symbol is a symbol with an `error-conditions' property\n\
 that is a list of condition names.\n\
 A handler for any of those names will get to handle this signal.\n\
 The symbol `error' should normally be one of them.\n\
@@ -1105,8 +1151,8 @@ The symbol `error' should normally be one of them.\n\
 DATA should be a list.  Its elements are printed as part of the error message.\n\
 If the signal is handled, DATA is made available to the handler.\n\
 See also the function `condition-case'.")
-  (sig, data)
-     Lisp_Object sig, data;
+  (error_symbol, data)
+     Lisp_Object error_symbol, data;
 {
   register struct handler *allhandlers = handlerlist;
   Lisp_Object conditions;
@@ -1123,13 +1169,13 @@ See also the function `condition-case'.")
   TOTALLY_UNBLOCK_INPUT;
 #endif
 
-  conditions = Fget (sig, Qerror_conditions);
+  conditions = Fget (error_symbol, Qerror_conditions);
 
   for (; handlerlist; handlerlist = handlerlist->next)
     {
       register Lisp_Object clause;
       clause = find_handler_clause (handlerlist->handler, conditions,
-                                   sig, data, &debugger_value);
+                                   error_symbol, data, &debugger_value);
 
 #if 0 /* Most callers are not prepared to handle gc if this returns.
         So, since this feature is not very useful, take it out.  */
@@ -1142,25 +1188,32 @@ See also the function `condition-case'.")
        {
          /* We can't return values to code which signalled an error, but we
             can continue code which has signalled a quit.  */
-         if (EQ (sig, Qquit))
+         if (EQ (error_symbol, Qquit))
            return Qnil;
          else
-       error ("Returning a value from an error is no longer supported");
+           error ("Cannot return from the debugger in an error");
        }
 #endif
 
       if (!NILP (clause))
        {
+         Lisp_Object unwind_data;
          struct handler *h = handlerlist;
+
          handlerlist = allhandlers;
-         unwind_to_catch (h->tag, Fcons (clause, Fcons (sig, data)));
+         if (EQ (data, memory_signal_data))
+           unwind_data = memory_signal_data;
+         else
+           unwind_data = Fcons (error_symbol, data);
+         h->chosen_clause = clause;
+         unwind_to_catch (h->tag, unwind_data);
        }
     }
 
   handlerlist = allhandlers;
   /* If no handler is present now, try to run the debugger,
      and if that fails, throw to top level.  */
-  find_handler_clause (Qerror, conditions, sig, data, &debugger_value);
+  find_handler_clause (Qerror, conditions, error_symbol, data, &debugger_value);
   Fthrow (Qtop_level, Qt);
 }
 
@@ -1198,7 +1251,6 @@ find_handler_clause (handlers, conditions, sig, data, debugger_value_ptr)
 {
   register Lisp_Object h;
   register Lisp_Object tem;
-  register Lisp_Object tem1;
 
   if (EQ (handlers, Qt))  /* t is used by handlers for all conditions, set up by C code.  */
     return Qt;
@@ -1223,12 +1275,30 @@ find_handler_clause (handlers, conditions, sig, data, debugger_value_ptr)
     }
   for (h = handlers; CONSP (h); h = Fcdr (h))
     {
-      tem1 = Fcar (h);
-      if (!CONSP (tem1))
+      Lisp_Object handler, condit;
+
+      handler = Fcar (h);
+      if (!CONSP (handler))
        continue;
-      tem = Fmemq (Fcar (tem1), conditions);
-      if (!NILP (tem))
-        return tem1;
+      condit = Fcar (handler);
+      /* Handle a single condition name in handler HANDLER.  */
+      if (SYMBOLP (condit))
+       {
+         tem = Fmemq (Fcar (handler), conditions);
+         if (!NILP (tem))
+           return handler;
+       }
+      /* Handle a list of condition names in handler HANDLER.  */
+      else if (CONSP (condit))
+       {
+         while (CONSP (condit))
+           {
+             tem = Fmemq (Fcar (condit), conditions);
+             if (!NILP (tem))
+               return handler;
+             condit = XCONS (condit)->cdr;
+           }
+       }
     }
   return Qnil;
 }
@@ -1239,12 +1309,42 @@ find_handler_clause (handlers, conditions, sig, data, debugger_value_ptr)
 void
 error (m, a1, a2, a3)
      char *m;
+     char *a1, *a2, *a3;
 {
   char buf[200];
-  sprintf (buf, m, a1, a2, a3);
+  int size = 200;
+  int mlen;
+  char *buffer = buf;
+  char *args[3];
+  int allocated = 0;
+  Lisp_Object string;
+
+  args[0] = a1;
+  args[1] = a2;
+  args[2] = a3;
+
+  mlen = strlen (m);
 
   while (1)
-    Fsignal (Qerror, Fcons (build_string (buf), Qnil));
+    {
+      int used = doprnt (buf, size, m, m + mlen, 3, args);
+      if (used < size)
+       break;
+      size *= 2;
+      if (allocated)
+       buffer = (char *) xrealloc (buffer, size);
+      else
+       {
+         buffer = (char *) xmalloc (size);
+         allocated = 1;
+       }
+    }
+
+  string = build_string (buf);
+  if (allocated)
+    free (buffer);
+
+  Fsignal (Qerror, Fcons (string, Qnil));
 }
 \f
 DEFUN ("commandp", Fcommandp, Scommandp, 1, 1, 0,
@@ -1391,7 +1491,6 @@ do_autoload (fundef, funname)
   Vautoload_queue = Qt;
   Fload (Fcar (Fcdr (fundef)), Qnil, noninteractive ? Qt : Qnil, Qnil);
 
-#ifdef UNLOAD
   /* Save the old autoloads, in case we ever do an unload. */
   queue = Vautoload_queue;
   while (CONSP (queue))
@@ -1399,11 +1498,15 @@ do_autoload (fundef, funname)
       first = Fcar (queue);
       second = Fcdr (first);
       first = Fcar (first);
-      if (!EQ (second, Qnil))
-         Fput(first, Qautoload, (Fcdr (second)));
+
+      /* Note: This test is subtle.  The cdr of an autoload-queue entry
+        may be an atom if the autoload entry was generated by a defalias
+        or fset. */
+      if (CONSP (second))
+       Fput (first, Qautoload, (Fcdr (second)));
+
       queue = Fcdr (queue);
     }
-#endif /* UNLOAD */
 
   /* Once loading finishes, don't undo it.  */
   Vautoload_queue = Qt;
@@ -1411,8 +1514,7 @@ do_autoload (fundef, funname)
 
   fun = Findirect_function (fun);
 
-  if (XTYPE (fun) == Lisp_Cons
-      && EQ (XCONS (fun)->car, Qautoload))
+  if (!NILP (Fequal (fun, fundef)))
     error ("Autoloading failed to define function %s",
           XSYMBOL (funname)->name->data);
 }
@@ -1733,18 +1835,18 @@ call0 (fn)
   RETURN_UNGCPRO (Ffuncall (1, &fn));
 }
 
-/* Call function fn with argument arg */
+/* Call function fn with 1 argument arg1 */
 /* ARGSUSED */
 Lisp_Object
-call1 (fn, arg)
-     Lisp_Object fn, arg;
+call1 (fn, arg1)
+     Lisp_Object fn, arg1;
 {
   struct gcpro gcpro1;
 #ifdef NO_ARG_ARRAY
   Lisp_Object args[2];  
 
   args[0] = fn;
-  args[1] = arg;
+  args[1] = arg1;
   GCPRO1 (args[0]);
   gcpro1.nvars = 2;
   RETURN_UNGCPRO (Ffuncall (2, args));
@@ -1755,18 +1857,18 @@ call1 (fn, arg)
 #endif /* not NO_ARG_ARRAY */
 }
 
-/* Call function fn with arguments arg, arg1 */
+/* Call function fn with 2 arguments arg1, arg2 */
 /* ARGSUSED */
 Lisp_Object
-call2 (fn, arg, arg1)
-     Lisp_Object fn, arg, arg1;
+call2 (fn, arg1, arg2)
+     Lisp_Object fn, arg1, arg2;
 {
   struct gcpro gcpro1;
 #ifdef NO_ARG_ARRAY
   Lisp_Object args[3];
   args[0] = fn;
-  args[1] = arg;
-  args[2] = arg1;
+  args[1] = arg1;
+  args[2] = arg2;
   GCPRO1 (args[0]);
   gcpro1.nvars = 3;
   RETURN_UNGCPRO (Ffuncall (3, args));
@@ -1777,19 +1879,19 @@ call2 (fn, arg, arg1)
 #endif /* not NO_ARG_ARRAY */
 }
 
-/* Call function fn with arguments arg, arg1, arg2 */
+/* Call function fn with 3 arguments arg1, arg2, arg3 */
 /* ARGSUSED */
 Lisp_Object
-call3 (fn, arg, arg1, arg2)
-     Lisp_Object fn, arg, arg1, arg2;
+call3 (fn, arg1, arg2, arg3)
+     Lisp_Object fn, arg1, arg2, arg3;
 {
   struct gcpro gcpro1;
 #ifdef NO_ARG_ARRAY
   Lisp_Object args[4];
   args[0] = fn;
-  args[1] = arg;
-  args[2] = arg1;
-  args[3] = arg2;
+  args[1] = arg1;
+  args[2] = arg2;
+  args[3] = arg3;
   GCPRO1 (args[0]);
   gcpro1.nvars = 4;
   RETURN_UNGCPRO (Ffuncall (4, args));
@@ -1800,6 +1902,81 @@ call3 (fn, arg, arg1, arg2)
 #endif /* not NO_ARG_ARRAY */
 }
 
+/* Call function fn with 4 arguments arg1, arg2, arg3, arg4 */
+/* ARGSUSED */
+Lisp_Object
+call4 (fn, arg1, arg2, arg3, arg4)
+     Lisp_Object fn, arg1, arg2, arg3, arg4;
+{
+  struct gcpro gcpro1;
+#ifdef NO_ARG_ARRAY
+  Lisp_Object args[5];
+  args[0] = fn;
+  args[1] = arg1;
+  args[2] = arg2;
+  args[3] = arg3;
+  args[4] = arg4;
+  GCPRO1 (args[0]);
+  gcpro1.nvars = 5;
+  RETURN_UNGCPRO (Ffuncall (5, args));
+#else /* not NO_ARG_ARRAY */
+  GCPRO1 (fn);
+  gcpro1.nvars = 5;
+  RETURN_UNGCPRO (Ffuncall (5, &fn));
+#endif /* not NO_ARG_ARRAY */
+}
+
+/* Call function fn with 5 arguments arg1, arg2, arg3, arg4, arg5 */
+/* ARGSUSED */
+Lisp_Object
+call5 (fn, arg1, arg2, arg3, arg4, arg5)
+     Lisp_Object fn, arg1, arg2, arg3, arg4, arg5;
+{
+  struct gcpro gcpro1;
+#ifdef NO_ARG_ARRAY
+  Lisp_Object args[6];
+  args[0] = fn;
+  args[1] = arg1;
+  args[2] = arg2;
+  args[3] = arg3;
+  args[4] = arg4;
+  args[5] = arg5;
+  GCPRO1 (args[0]);
+  gcpro1.nvars = 6;
+  RETURN_UNGCPRO (Ffuncall (6, args));
+#else /* not NO_ARG_ARRAY */
+  GCPRO1 (fn);
+  gcpro1.nvars = 6;
+  RETURN_UNGCPRO (Ffuncall (6, &fn));
+#endif /* not NO_ARG_ARRAY */
+}
+
+/* Call function fn with 6 arguments arg1, arg2, arg3, arg4, arg5, arg6 */
+/* ARGSUSED */
+Lisp_Object
+call6 (fn, arg1, arg2, arg3, arg4, arg5, arg6)
+     Lisp_Object fn, arg1, arg2, arg3, arg4, arg5, arg6;
+{
+  struct gcpro gcpro1;
+#ifdef NO_ARG_ARRAY
+  Lisp_Object args[7];
+  args[0] = fn;
+  args[1] = arg1;
+  args[2] = arg2;
+  args[3] = arg3;
+  args[4] = arg4;
+  args[5] = arg5;
+  args[6] = arg6;
+  GCPRO1 (args[0]);
+  gcpro1.nvars = 7;
+  RETURN_UNGCPRO (Ffuncall (7, args));
+#else /* not NO_ARG_ARRAY */
+  GCPRO1 (fn);
+  gcpro1.nvars = 7;
+  RETURN_UNGCPRO (Ffuncall (7, &fn));
+#endif /* not NO_ARG_ARRAY */
+}
+
 DEFUN ("funcall", Ffuncall, Sfuncall, 1, MANY, 0,
   "Call first argument as a function, passing remaining arguments to it.\n\
 Thus, (funcall 'cons 'x 'y) returns (x . y).")
@@ -2096,8 +2273,7 @@ specbind (symbol, value)
     grow_specpdl ();
   specpdl_ptr->symbol = symbol;
   specpdl_ptr->func = 0;
-  ovalue = XSYMBOL (symbol)->value;
-  specpdl_ptr->old_value = EQ (ovalue, Qunbound) ? Qunbound : Fsymbol_value (symbol);
+  specpdl_ptr->old_value = ovalue = find_symbol_value (symbol);
   specpdl_ptr++;
   if (XTYPE (ovalue) == Lisp_Buffer_Objfwd)
     store_symval_forwarding (symbol, ovalue, value);
@@ -2234,6 +2410,7 @@ Output stream used is value of `standard-output'.")
       if (backlist->nargs == UNEVALLED)
        {
          Fprin1 (Fcons (*backlist->function, *backlist->args), Qnil);
+         write_string ("\n", -1);
        }
       else
        {
@@ -2258,8 +2435,8 @@ Output stream used is value of `standard-output'.")
                  Fprin1 (backlist->args[i], Qnil);
                }
            }
+         write_string (")\n", -1);
        }
-      write_string (")\n", -1);
       backlist = backlist->next;
     }
 
@@ -2288,7 +2465,7 @@ If N is more than the number of frames, the value is nil.")
   CHECK_NATNUM (nframes, 0);
 
   /* Find the frame requested.  */
-  for (i = 0; i < XFASTINT (nframes); i++)
+  for (i = 0; backlist && i < XFASTINT (nframes); i++)
     backlist = backlist->next;
 
   if (!backlist)
@@ -2320,7 +2497,7 @@ if that proves inconveniently small.");
 
   DEFVAR_LISP ("quit-flag", &Vquit_flag,
     "Non-nil causes `eval' to abort, unless `inhibit-quit' is non-nil.\n\
-Typing C-G sets `quit-flag' non-nil, regardless of `inhibit-quit'.");
+Typing C-g sets `quit-flag' non-nil, regardless of `inhibit-quit'.");
   Vquit_flag = Qnil;
 
   DEFVAR_LISP ("inhibit-quit", &Vinhibit_quit,
@@ -2379,7 +2556,7 @@ See also variable `debug-on-quit'.");
   Vdebug_on_error = Qnil;
 
   DEFVAR_BOOL ("debug-on-quit", &debug_on_quit,
-    "*Non-nil means enter debugger if quit is signaled (C-G, for example).\n\
+    "*Non-nil means enter debugger if quit is signaled (C-g, for example).\n\
 Does not apply if quit is handled by a `condition-case'.");
   debug_on_quit = 0;
 
@@ -2404,7 +2581,6 @@ If due to `eval' entry, one arg, t.");
   DEFVAR_LISP ("run-hooks", &Vrun_hooks,
     "Set to the function `run-hooks', if that function has been defined.\n\
 Otherwise, nil (in a bare Emacs without preloaded Lisp code).");
-  Vrun_hooks = Qnil;
 
   staticpro (&Vautoload_queue);
   Vautoload_queue = Qnil;