]> code.delx.au - gnu-emacs/blobdiff - src/eval.c
(read_minibuf): Fix 2007-01-30 change.
[gnu-emacs] / src / eval.c
index 30df5f8ea360950a9ba2c612721acfc34cc30cda..6707849a8409394013158d4848bacb4eff89af1f 100644 (file)
@@ -1,6 +1,6 @@
 /* Evaluator for GNU Emacs Lisp interpreter.
    Copyright (C) 1985, 1986, 1987, 1993, 1994, 1995, 1999, 2000, 2001,
-                 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+                 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -28,6 +28,10 @@ Boston, MA 02110-1301, USA.  */
 #include "dispextern.h"
 #include <setjmp.h>
 
+#if HAVE_X_WINDOWS
+#include "xterm.h"
+#endif
+
 /* This definition is duplicated in alloc.c and keyboard.c */
 /* Putting it in lisp.h makes cc bomb out! */
 
@@ -198,6 +202,15 @@ 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;
+
+#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
 \f
 void
 init_eval_once ()
@@ -983,9 +996,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)));
@@ -1032,9 +1043,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;
@@ -1165,7 +1174,7 @@ DEFUN ("catch", Fcatch, Scatch, 1, UNEVALLED, 0,
 TAG is evalled to get the tag to use; it must not be nil.
 
 Then the BODY is executed.
-Within BODY, (throw TAG) with same tag exits BODY and exits this `catch'.
+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...)  */)
@@ -1289,16 +1298,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);
 }
 
 
@@ -1706,6 +1712,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.  */
 
@@ -1830,6 +1908,9 @@ find_handler_clause (handlers, conditions, sig, data, debugger_value_ptr)
          max_specpdl_size--;
        }
       if (! no_debugger
+         /* Don't try to run the debugger with interrupts blocked.
+            The editing loop would return anyway.  */
+         && ! INPUT_BLOCKED_P
          && (EQ (sig_symbol, Qquit)
              ? debug_on_quit
              : wants_debugger (Vdebug_on_error, conditions))
@@ -1920,8 +2001,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,
@@ -2166,7 +2246,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, Qnil);
+
+  /* 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))
     {
@@ -2182,7 +2267,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)
        {
@@ -2285,11 +2370,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);
@@ -2300,7 +2387,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 ();
@@ -2345,7 +2432,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 */
@@ -2824,7 +2914,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;
@@ -2861,11 +2951,15 @@ usage: (funcall FUNCTION &rest ARGUMENTS)  */)
 
   CHECK_CONS_LIST ();
 
- retry:
+  original_fun = args[0];
 
-  fun = args[0];
+ retry:
 
-  fun = Findirect_function (fun, Qnil);
+  /* 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))
     {
@@ -2873,11 +2967,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)
        {
@@ -2949,21 +3043,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 ();
@@ -3039,7 +3135,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);
@@ -3052,8 +3148,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;
@@ -3067,17 +3163,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)));
@@ -3129,8 +3223,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)