]> code.delx.au - gnu-emacs/blobdiff - src/eval.c
(GDB Graphical Interface): Shorten node names.
[gnu-emacs] / src / eval.c
index 46ad3f48df6e6fb54e2612a266abd2179f05520c..0d7a6a310383de3b20f56a049952df2ab6fd51a5 100644 (file)
@@ -1,6 +1,6 @@
 /* Evaluator for GNU Emacs Lisp interpreter.
    Copyright (C) 1985, 1986, 1987, 1993, 1994, 1995, 1999, 2000, 2001,
-     2002, 2004, 2005 Free Software Foundation, Inc.
+                 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -103,7 +103,7 @@ Lisp_Object Vrun_hooks;
 /* Non-nil means record all fset's and provide's, to be undone
    if the file being autoloaded is not fully loaded.
    They are recorded by being consed onto the front of Vautoload_queue:
-   (FUN . ODEF) for a defun, (OFEATURES . nil) for a provide.  */
+   (FUN . ODEF) for a defun, (0 . OFEATURES) for a provide.  */
 
 Lisp_Object Vautoload_queue;
 
@@ -117,7 +117,7 @@ struct specbinding *specpdl;
 
 /* Pointer to first unused element in specpdl.  */
 
-volatile struct specbinding *specpdl_ptr;
+struct specbinding *specpdl_ptr;
 
 /* Maximum size allowed for specpdl allocation */
 
@@ -195,15 +195,18 @@ int handling_signal;
 
 Lisp_Object Vmacro_declaration_function;
 
+extern Lisp_Object Qrisky_local_variable;
 
 static Lisp_Object funcall_lambda P_ ((Lisp_Object, int, Lisp_Object*));
-
+static void unwind_to_catch P_ ((struct catchtag *, Lisp_Object)) NO_RETURN;
+\f
 void
 init_eval_once ()
 {
   specpdl_size = 50;
   specpdl = (struct specbinding *) xmalloc (specpdl_size * sizeof (struct specbinding));
   specpdl_ptr = specpdl;
+  /* Don't forget to update docs (lispref node "Local Variables").  */
   max_specpdl_size = 1000;
   max_lisp_eval_depth = 300;
 
@@ -235,6 +238,7 @@ restore_stack_limits (data)
 {
   max_specpdl_size = XINT (XCAR (data));
   max_lisp_eval_depth = XINT (XCDR (data));
+  return Qnil;
 }
 
 /* Call the Lisp debugger, giving it argument ARG.  */
@@ -617,7 +621,7 @@ interactive_p (exclude_subrs_p)
 
   /* If this isn't a byte-compiled function, there may be a frame at
      the top for Finteractive_p.  If so, skip it.  */
-  fun = Findirect_function (*btp->function);
+  fun = Findirect_function (*btp->function, Qnil);
   if (SUBRP (fun) && (XSUBR (fun) == &Sinteractive_p
                      || XSUBR (fun) == &Scalled_interactively_p))
     btp = btp->next;
@@ -638,7 +642,7 @@ interactive_p (exclude_subrs_p)
      a special form, ignoring frames for Finteractive_p and/or
      Fbytecode at the top.  If this frame is for a built-in function
      (such as load or eval-region) return nil.  */
-  fun = Findirect_function (*btp->function);
+  fun = Findirect_function (*btp->function, Qnil);
   if (exclude_subrs_p && SUBRP (fun))
     return 0;
 
@@ -746,8 +750,7 @@ usage: (defmacro NAME ARGLIST [DOCSTRING] [DECL] BODY...)  */)
 
 DEFUN ("defvaralias", Fdefvaralias, Sdefvaralias, 2, 3, 0,
        doc: /* Make NEW-ALIAS a variable alias for symbol BASE-VARIABLE.
-Setting the value of NEW-ALIAS will subsequently set the value of BASE-VARIABLE,
- and getting the value of NEW-ALIAS will return the value BASE-VARIABLE has.
+Aliased variables always have the same value; setting one sets the other.
 Third arg DOCSTRING, if non-nil, is documentation for NEW-ALIAS.  If it is
  omitted or nil, NEW-ALIAS gets the documentation string of BASE-VARIABLE,
  or of the variable at the end of the chain of aliases, if BASE-VARIABLE is
@@ -806,18 +809,6 @@ usage: (defvar SYMBOL &optional INITVALUE DOCSTRING)  */)
   register Lisp_Object sym, tem, tail;
 
   sym = Fcar (args);
-  if (SYMBOL_CONSTANT_P (sym))
-    {
-      /* For updward compatibility, allow (defvar :foo (quote :foo)).  */
-      tem = Fcar (Fcdr (args));
-      if (! (CONSP (tem)
-            && EQ (XCAR (tem), Qquote)
-            && CONSP (XCDR (tem))
-            && EQ (XCAR (XCDR (tem)), sym)))
-       error ("Constant symbol `%s' specified in defvar",
-              SDATA (SYMBOL_NAME (sym)));
-    }
-
   tail = Fcdr (args);
   if (!NILP (Fcdr (Fcdr (tail))))
     error ("Too many arguments");
@@ -825,6 +816,18 @@ usage: (defvar SYMBOL &optional INITVALUE DOCSTRING)  */)
   tem = Fdefault_boundp (sym);
   if (!NILP (tail))
     {
+      if (SYMBOL_CONSTANT_P (sym))
+       {
+         /* For upward compatibility, allow (defvar :foo (quote :foo)).  */
+         Lisp_Object tem = Fcar (tail);
+         if (! (CONSP (tem)
+                && EQ (XCAR (tem), Qquote)
+                && CONSP (XCDR (tem))
+                && EQ (XCAR (XCDR (tem)), sym)))
+           error ("Constant symbol `%s' specified in defvar",
+                  SDATA (SYMBOL_NAME (sym)));
+       }
+
       if (NILP (tem))
        Fset_default (sym, Feval (Fcar (tail)));
       else
@@ -893,6 +896,7 @@ usage: (defconst SYMBOL INITVALUE [DOCSTRING])  */)
        tem = Fpurecopy (tem);
       Fput (sym, Qvariable_documentation, tem);
     }
+  Fput (sym, Qrisky_local_variable, Qt);
   LOADHIST_ATTACH (sym);
   return sym;
 }
@@ -980,9 +984,7 @@ usage: (let* VARLIST BODY...)  */)
       if (SYMBOLP (elt))
        specbind (elt, Qnil);
       else if (! NILP (Fcdr (Fcdr (elt))))
-       Fsignal (Qerror,
-                Fcons (build_string ("`let' bindings can have only one value-form"),
-                       elt));
+       signal_error ("`let' bindings can have only one value-form", elt);
       else
        {
          val = Feval (Fcar (Fcdr (elt)));
@@ -1029,9 +1031,7 @@ usage: (let VARLIST BODY...)  */)
       if (SYMBOLP (elt))
        temps [argnum++] = Qnil;
       else if (! NILP (Fcdr (Fcdr (elt))))
-       Fsignal (Qerror,
-                Fcons (build_string ("`let' bindings can have only one value-form"),
-                       elt));
+       signal_error ("`let' bindings can have only one value-form", elt);
       else
        temps [argnum++] = Feval (Fcar (Fcdr (elt)));
       gcpro2.nvars = argnum;
@@ -1258,6 +1258,12 @@ unwind_to_catch (catch, value)
     }
   while (! last_time);
 
+#if HAVE_X_WINDOWS
+  /* If x_catch_errors was done, turn it off now.
+     (First we give unbind_to a chance to do that.)  */
+  x_fully_uncatch_errors ();
+#endif
+
   byte_stack_list = catch->byte_stack;
   gcprolist = catch->gcpro;
 #ifdef DEBUG_GCPRO
@@ -1280,16 +1286,13 @@ Both TAG and VALUE are evalled.  */)
 {
   register struct catchtag *c;
 
-  while (1)
-    {
-      if (!NILP (tag))
-       for (c = catchlist; c; c = c->next)
-         {
-           if (EQ (c->tag, tag))
-             unwind_to_catch (c, value);
-         }
-      tag = Fsignal (Qno_catch, Fcons (tag, Fcons (value, Qnil)));
-    }
+  if (!NILP (tag))
+    for (c = catchlist; c; c = c->next)
+      {
+       if (EQ (c->tag, tag))
+         unwind_to_catch (c, value);
+      }
+  xsignal2 (Qno_catch, tag, value);
 }
 
 
@@ -1342,15 +1345,28 @@ usage: (condition-case VAR BODYFORM &rest HANDLERS)  */)
      (args)
      Lisp_Object args;
 {
-  Lisp_Object val;
-  struct catchtag c;
-  struct handler h;
   register Lisp_Object bodyform, handlers;
   volatile Lisp_Object var;
 
   var      = Fcar (args);
   bodyform = Fcar (Fcdr (args));
   handlers = Fcdr (Fcdr (args));
+
+  return internal_lisp_condition_case (var, bodyform, handlers);
+}
+
+/* Like Fcondition_case, but the args are separate
+   rather than passed in a list.  Used by Fbyte_code.  */
+
+Lisp_Object
+internal_lisp_condition_case (var, bodyform, handlers)
+     volatile Lisp_Object var;
+     Lisp_Object bodyform, handlers;
+{
+  Lisp_Object val;
+  struct catchtag c;
+  struct handler h;
+
   CHECK_SYMBOL (var);
 
   for (val = handlers; CONSP (val); val = XCDR (val))
@@ -1421,8 +1437,10 @@ internal_condition_case (bfun, handlers, hfun)
   struct catchtag c;
   struct handler h;
 
-#if 0 /* We now handle interrupt_input_blocked properly.
-        What we still do not handle is exiting a signal handler.  */
+  /* Since Fsignal will close off all calls to x_catch_errors,
+     we will get the wrong results if some are not closed now.  */
+#if HAVE_X_WINDOWS
+  if (x_catching_errors ())
     abort ();
 #endif
 
@@ -1467,6 +1485,13 @@ internal_condition_case_1 (bfun, arg, handlers, hfun)
   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;
@@ -1511,6 +1536,13 @@ internal_condition_case_2 (bfun, nargs, args, handlers, hfun)
   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;
@@ -1668,6 +1700,78 @@ See also the function `condition-case'.  */)
   fatal ("%s", SDATA (string), 0);
 }
 
+/* Internal version of Fsignal that never returns.
+   Used for anything but Qquit (which can return from Fsignal).  */
+
+void
+xsignal (error_symbol, data)
+     Lisp_Object error_symbol, data;
+{
+  Fsignal (error_symbol, data);
+  abort ();
+}
+
+/* Like xsignal, but takes 0, 1, 2, or 3 args instead of a list.  */
+
+void
+xsignal0 (error_symbol)
+     Lisp_Object error_symbol;
+{
+  xsignal (error_symbol, Qnil);
+}
+
+void
+xsignal1 (error_symbol, arg)
+     Lisp_Object error_symbol, arg;
+{
+  xsignal (error_symbol, list1 (arg));
+}
+
+void
+xsignal2 (error_symbol, arg1, arg2)
+     Lisp_Object error_symbol, arg1, arg2;
+{
+  xsignal (error_symbol, list2 (arg1, arg2));
+}
+
+void
+xsignal3 (error_symbol, arg1, arg2, arg3)
+     Lisp_Object error_symbol, arg1, arg2, arg3;
+{
+  xsignal (error_symbol, list3 (arg1, arg2, arg3));
+}
+
+/* Signal `error' with message S, and additional arg ARG.
+   If ARG is not a genuine list, make it a one-element list.  */
+
+void
+signal_error (s, arg)
+     char *s;
+     Lisp_Object arg;
+{
+  Lisp_Object tortoise, hare;
+
+  hare = tortoise = arg;
+  while (CONSP (hare))
+    {
+      hare = XCDR (hare);
+      if (!CONSP (hare))
+       break;
+
+      hare = XCDR (hare);
+      tortoise = XCDR (tortoise);
+
+      if (EQ (hare, tortoise))
+       break;
+    }
+
+  if (!NILP (hare))
+    arg = Fcons (arg, Qnil);   /* Make it a list.  */
+
+  xsignal (Qerror, Fcons (build_string (s), arg));
+}
+
+
 /* Return nonzero iff LIST is a non-nil atom or
    a list containing one of CONDITIONS.  */
 
@@ -1882,8 +1986,7 @@ error (m, a1, a2, a3)
   if (allocated)
     xfree (buffer);
 
-  Fsignal (Qerror, Fcons (string, Qnil));
-  abort ();
+  xsignal1 (Qerror, string);
 }
 \f
 DEFUN ("commandp", Fcommandp, Scommandp, 1, 2, 0,
@@ -2008,8 +2111,8 @@ un_autoload (oldqueue)
       first = XCAR (queue);
       second = Fcdr (first);
       first = Fcar (first);
-      if (EQ (second, Qnil))
-       Vfeatures = first;
+      if (EQ (first, make_number (0)))
+       Vfeatures = second;
       else
        Ffset (first, second);
       queue = XCDR (queue);
@@ -2055,7 +2158,7 @@ do_autoload (fundef, funname)
       second = Fcdr (first);
       first = Fcar (first);
 
-      if (CONSP (second) && EQ (XCAR (second), Qautoload))
+      if (SYMBOLP (first) && CONSP (second) && EQ (XCAR (second), Qautoload))
        Fput (first, Qautoload, (XCDR (second)));
 
       queue = XCDR (queue);
@@ -2065,7 +2168,7 @@ do_autoload (fundef, funname)
   Vautoload_queue = Qt;
   unbind_to (count, Qnil);
 
-  fun = Findirect_function (fun);
+  fun = Findirect_function (fun, Qnil);
 
   if (!NILP (Fequal (fun, fundef)))
     error ("Autoloading failed to define function %s",
@@ -2093,7 +2196,10 @@ DEFUN ("eval", Feval, Seval, 1, 1, 0,
     return form;
 
   QUIT;
-  if (consing_since_gc > gc_cons_combined_threshold)
+  if ((consing_since_gc > gc_cons_threshold
+       && consing_since_gc > gc_relative_threshold)
+      ||
+      (!NILP (Vmemory_full) && consing_since_gc > memory_full_cons_threshold))
     {
       GCPRO1 (form);
       Fgarbage_collect ();
@@ -2125,7 +2231,12 @@ DEFUN ("eval", Feval, Seval, 1, 1, 0,
   /* At this point, only original_fun and original_args
      have values that will be used below */
  retry:
-  fun = Findirect_function (original_fun);
+
+  /* Optimize for no indirection.  */
+  fun = original_fun;
+  if (SYMBOLP (fun) && !EQ (fun, Qunbound)
+      && (fun = XSYMBOL (fun)->function, SYMBOLP (fun)))
+    fun = indirect_function (fun);
 
   if (SUBRP (fun))
     {
@@ -2141,7 +2252,7 @@ DEFUN ("eval", Feval, Seval, 1, 1, 0,
 
       if (XINT (numargs) < XSUBR (fun)->min_args ||
          (XSUBR (fun)->max_args >= 0 && XSUBR (fun)->max_args < XINT (numargs)))
-       return Fsignal (Qwrong_number_of_arguments, Fcons (fun, Fcons (numargs, Qnil)));
+       xsignal2 (Qwrong_number_of_arguments, original_fun, numargs);
 
       if (XSUBR (fun)->max_args == UNEVALLED)
        {
@@ -2244,11 +2355,13 @@ DEFUN ("eval", Feval, Seval, 1, 1, 0,
     val = apply_lambda (fun, original_args, 1);
   else
     {
+      if (EQ (fun, Qunbound))
+       xsignal1 (Qvoid_function, original_fun);
       if (!CONSP (fun))
-       return Fsignal (Qinvalid_function, Fcons (fun, Qnil));
-      funcar = Fcar (fun);
+       xsignal1 (Qinvalid_function, original_fun);
+      funcar = XCAR (fun);
       if (!SYMBOLP (funcar))
-       return Fsignal (Qinvalid_function, Fcons (fun, Qnil));
+       xsignal1 (Qinvalid_function, original_fun);
       if (EQ (funcar, Qautoload))
        {
          do_autoload (fun, original_fun);
@@ -2259,7 +2372,7 @@ DEFUN ("eval", Feval, Seval, 1, 1, 0,
       else if (EQ (funcar, Qlambda))
        val = apply_lambda (fun, original_args, 1);
       else
-       return Fsignal (Qinvalid_function, Fcons (fun, Qnil));
+       xsignal1 (Qinvalid_function, original_fun);
     }
  done:
   CHECK_CONS_LIST ();
@@ -2304,7 +2417,10 @@ usage: (apply FUNCTION &rest ARGUMENTS)  */)
 
   numargs += nargs - 2;
 
-  fun = indirect_function (fun);
+  /* Optimize for no indirection.  */
+  if (SYMBOLP (fun) && !EQ (fun, Qunbound)
+      && (fun = XSYMBOL (fun)->function, SYMBOLP (fun)))
+    fun = indirect_function (fun);
   if (EQ (fun, Qunbound))
     {
       /* Let funcall get the error */
@@ -2783,7 +2899,7 @@ usage: (funcall FUNCTION &rest ARGUMENTS)  */)
      int nargs;
      Lisp_Object *args;
 {
-  Lisp_Object fun;
+  Lisp_Object fun, original_fun;
   Lisp_Object funcar;
   int numargs = nargs - 1;
   Lisp_Object lisp_numargs;
@@ -2793,7 +2909,10 @@ usage: (funcall FUNCTION &rest ARGUMENTS)  */)
   register int i;
 
   QUIT;
-  if (consing_since_gc > gc_cons_combined_threshold)
+  if ((consing_since_gc > gc_cons_threshold
+       && consing_since_gc > gc_relative_threshold)
+      ||
+      (!NILP (Vmemory_full) && consing_since_gc > memory_full_cons_threshold))
     Fgarbage_collect ();
 
   if (++lisp_eval_depth > max_lisp_eval_depth)
@@ -2817,11 +2936,15 @@ usage: (funcall FUNCTION &rest ARGUMENTS)  */)
 
   CHECK_CONS_LIST ();
 
- retry:
+  original_fun = args[0];
 
-  fun = args[0];
+ retry:
 
-  fun = Findirect_function (fun);
+  /* Optimize for no indirection.  */
+  fun = original_fun;
+  if (SYMBOLP (fun) && !EQ (fun, Qunbound)
+      && (fun = XSYMBOL (fun)->function, SYMBOLP (fun)))
+    fun = indirect_function (fun);
 
   if (SUBRP (fun))
     {
@@ -2829,11 +2952,11 @@ usage: (funcall FUNCTION &rest ARGUMENTS)  */)
          || (XSUBR (fun)->max_args >= 0 && XSUBR (fun)->max_args < numargs))
        {
          XSETFASTINT (lisp_numargs, numargs);
-         return Fsignal (Qwrong_number_of_arguments, Fcons (fun, Fcons (lisp_numargs, Qnil)));
+         xsignal2 (Qwrong_number_of_arguments, original_fun, lisp_numargs);
        }
 
       if (XSUBR (fun)->max_args == UNEVALLED)
-       return Fsignal (Qinvalid_function, Fcons (fun, Qnil));
+       xsignal1 (Qinvalid_function, original_fun);
 
       if (XSUBR (fun)->max_args == MANY)
        {
@@ -2905,21 +3028,23 @@ usage: (funcall FUNCTION &rest ARGUMENTS)  */)
     val = funcall_lambda (fun, numargs, args + 1);
   else
     {
+      if (EQ (fun, Qunbound))
+       xsignal1 (Qvoid_function, original_fun);
       if (!CONSP (fun))
-       return Fsignal (Qinvalid_function, Fcons (fun, Qnil));
-      funcar = Fcar (fun);
+       xsignal1 (Qinvalid_function, original_fun);
+      funcar = XCAR (fun);
       if (!SYMBOLP (funcar))
-       return Fsignal (Qinvalid_function, Fcons (fun, Qnil));
+       xsignal1 (Qinvalid_function, original_fun);
       if (EQ (funcar, Qlambda))
        val = funcall_lambda (fun, numargs, args + 1);
       else if (EQ (funcar, Qautoload))
        {
-         do_autoload (fun, args[0]);
+         do_autoload (fun, original_fun);
          CHECK_CONS_LIST ();
          goto retry;
        }
       else
-       return Fsignal (Qinvalid_function, Fcons (fun, Qnil));
+       xsignal1 (Qinvalid_function, original_fun);
     }
  done:
   CHECK_CONS_LIST ();
@@ -2995,7 +3120,7 @@ funcall_lambda (fun, nargs, arg_vector)
       if (CONSP (syms_left))
        syms_left = XCAR (syms_left);
       else
-       return Fsignal (Qinvalid_function, Fcons (fun, Qnil));
+       xsignal1 (Qinvalid_function, fun);
     }
   else if (COMPILEDP (fun))
     syms_left = AREF (fun, COMPILED_ARGLIST);
@@ -3008,8 +3133,8 @@ funcall_lambda (fun, nargs, arg_vector)
       QUIT;
 
       next = XCAR (syms_left);
-      while (!SYMBOLP (next))
-       next = Fsignal (Qinvalid_function, Fcons (fun, Qnil));
+      if (!SYMBOLP (next))
+       xsignal1 (Qinvalid_function, fun);
 
       if (EQ (next, Qand_rest))
        rest = 1;
@@ -3023,17 +3148,15 @@ funcall_lambda (fun, nargs, arg_vector)
       else if (i < nargs)
        specbind (next, arg_vector[i++]);
       else if (!optional)
-       return Fsignal (Qwrong_number_of_arguments,
-                       Fcons (fun, Fcons (make_number (nargs), Qnil)));
+       xsignal2 (Qwrong_number_of_arguments, fun, make_number (nargs));
       else
        specbind (next, Qnil);
     }
 
   if (!NILP (syms_left))
-    return Fsignal (Qinvalid_function, Fcons (fun, Qnil));
+    xsignal1 (Qinvalid_function, fun);
   else if (i < nargs)
-    return Fsignal (Qwrong_number_of_arguments,
-                   Fcons (fun, Fcons (make_number (nargs), Qnil)));
+    xsignal2 (Qwrong_number_of_arguments, fun, make_number (nargs));
 
   if (CONSP (fun))
     val = Fprogn (XCDR (XCDR (fun)));
@@ -3085,8 +3208,7 @@ grow_specpdl ()
       if (max_specpdl_size < 400)
        max_specpdl_size = 400;
       if (specpdl_size >= max_specpdl_size)
-       Fsignal (Qerror,
-                Fcons (build_string ("Variable binding depth exceeds max-specpdl-size"), Qnil));
+       signal_error ("Variable binding depth exceeds max-specpdl-size", Qnil);
     }
   specpdl_size *= 2;
   if (specpdl_size > max_specpdl_size)
@@ -3179,6 +3301,8 @@ record_unwind_protect (function, arg)
      Lisp_Object (*function) P_ ((Lisp_Object));
      Lisp_Object arg;
 {
+  eassert (!handling_signal);
+
   if (specpdl_ptr == specpdl + specpdl_size)
     grow_specpdl ();
   specpdl_ptr->func = function;