]> code.delx.au - gnu-emacs/blobdiff - src/eval.c
Merge from emacs--rel--22
[gnu-emacs] / src / eval.c
index 37c245234fc9c1e18789810869a52c581b1bffa2..b69eea44c75c2ecb7d23c9a4f2fa8f03a0be8be4 100644 (file)
@@ -1,12 +1,12 @@
 /* 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.
 
 GNU Emacs is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
+the Free Software Foundation; either version 3, or (at your option)
 any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
@@ -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! */
 
@@ -93,6 +97,7 @@ Lisp_Object Qinhibit_quit, Vinhibit_quit, Vquit_flag;
 Lisp_Object Qand_rest, Qand_optional;
 Lisp_Object Qdebug_on_error;
 Lisp_Object Qdeclare;
+Lisp_Object Qdebug;
 
 /* This holds either the symbol `run-hooks' or nil.
    It is nil at an early stage of startup, and when Emacs
@@ -197,7 +202,18 @@ 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
 \f
 void
 init_eval_once ()
@@ -207,7 +223,7 @@ init_eval_once ()
   specpdl_ptr = specpdl;
   /* Don't forget to update docs (lispref node "Local Variables").  */
   max_specpdl_size = 1000;
-  max_lisp_eval_depth = 300;
+  max_lisp_eval_depth = 400;
 
   Vrun_hooks = Qnil;
 }
@@ -316,7 +332,7 @@ DEFUN ("or", For, Sor, 0, UNEVALLED, 0,
        doc: /* Eval args until one of them yields non-nil, then return that value.
 The remaining args are not evalled at all.
 If all args return nil, return nil.
-usage: (or CONDITIONS ...)  */)
+usage: (or CONDITIONS...)  */)
      (args)
      Lisp_Object args;
 {
@@ -341,7 +357,7 @@ DEFUN ("and", Fand, Sand, 0, UNEVALLED, 0,
        doc: /* Eval args until one of them yields nil, then return nil.
 The remaining args are not evalled at all.
 If no arg yields nil, return the last arg's value.
-usage: (and CONDITIONS ...)  */)
+usage: (and CONDITIONS...)  */)
      (args)
      Lisp_Object args;
 {
@@ -420,7 +436,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 ...)  */)
+usage: (progn BODY...)  */)
      (args)
      Lisp_Object args;
 {
@@ -517,7 +533,7 @@ Thus, (setq x (1+ y)) sets `x' to the value of `(1+ y)'.
 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 SYM VAL ...)  */)
+usage: (setq [SYM VAL]...)  */)
      (args)
      Lisp_Object args;
 {
@@ -525,7 +541,7 @@ usage: (setq SYM VAL SYM VAL ...)  */)
   register Lisp_Object val, sym;
   struct gcpro gcpro1;
 
-  if (NILP(args))
+  if (NILP (args))
     return Qnil;
 
   args_left = args;
@@ -550,6 +566,8 @@ usage: (quote ARG)  */)
      (args)
      Lisp_Object args;
 {
+  if (!NILP (Fcdr (args)))
+    xsignal2 (Qwrong_number_of_arguments, Qquote, Flength (args));
   return Fcar (args);
 }
 
@@ -561,6 +579,8 @@ usage: (function ARG)  */)
      (args)
      Lisp_Object args;
 {
+  if (!NILP (Fcdr (args)))
+    xsignal2 (Qwrong_number_of_arguments, Qfunction, Flength (args));
   return Fcar (args);
 }
 
@@ -1161,7 +1181,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...)  */)
@@ -1260,7 +1280,11 @@ unwind_to_catch (catch, value)
 #if HAVE_X_WINDOWS
   /* 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  */
   x_fully_uncatch_errors ();
+#endif
 #endif
 
   byte_stack_list = catch->byte_stack;
@@ -1331,14 +1355,15 @@ if CONDITION-NAME is one of the error's condition names.
 If an error happens, the first applicable handler is run.
 
 The car of a handler may be a list of condition names
-instead of a single condition name.
+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 the handler BODY... is executed
-with VAR bound to (SIGNALED-CONDITIONS . SIGNAL-DATA).
-VAR may be nil; then you do not get access to the signal information.
+When a handler handles an error, control returns to the `condition-case'
+and it executes the handler's BODY...
+with VAR bound to (SIGNALED-CONDITIONS . SIGNAL-DATA) from the error.
+(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.
 
-The value of the last BODY form is returned from the condition-case.
 See also the function `signal' for more info.
 usage: (condition-case VAR BODYFORM &rest HANDLERS)  */)
      (args)
@@ -1572,8 +1597,7 @@ 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,
-                                           Lisp_Object *));
+                                           Lisp_Object, Lisp_Object));
 
 DEFUN ("signal", Fsignal, Ssignal, 2, 2, 0,
        doc: /* Signal an error.  Args are ERROR-SYMBOL and associated DATA.
@@ -1599,7 +1623,6 @@ See also the function `condition-case'.  */)
   Lisp_Object conditions;
   extern int gc_in_progress;
   extern int waiting_for_input;
-  Lisp_Object debugger_value;
   Lisp_Object string;
   Lisp_Object real_error_symbol;
   struct backtrace *bp;
@@ -1657,7 +1680,7 @@ See also the function `condition-case'.  */)
       register Lisp_Object clause;
 
       clause = find_handler_clause (handlerlist->handler, conditions,
-                                   error_symbol, data, &debugger_value);
+                                   error_symbol, data);
 
       if (EQ (clause, Qlambda))
        {
@@ -1688,7 +1711,7 @@ See also the function `condition-case'.  */)
   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, error_symbol, data, &debugger_value);
+  find_handler_clause (Qerror, conditions, error_symbol, data);
   if (catchlist != 0)
     Fthrow (Qtop_level, Qt);
 
@@ -1771,7 +1794,7 @@ signal_error (s, arg)
 }
 
 
-/* Return nonzero iff LIST is a non-nil atom or
+/* Return nonzero if LIST is a non-nil atom or
    a list containing one of CONDITIONS.  */
 
 static int
@@ -1840,72 +1863,54 @@ skip_debugger (conditions, data)
     = SIG is nil, and DATA is (SYMBOL . REST-OF-DATA).
        This is for memory-full errors only.
 
-   Store value returned from debugger into *DEBUGGER_VALUE_PTR.
-
    We need to increase max_specpdl_size temporarily around
    anything we do that can push on the specpdl, so as not to get
    a second error here in case we're handling specpdl overflow.  */
 
 static Lisp_Object
-find_handler_clause (handlers, conditions, sig, data, debugger_value_ptr)
+find_handler_clause (handlers, conditions, sig, data)
      Lisp_Object handlers, conditions, sig, data;
-     Lisp_Object *debugger_value_ptr;
 {
   register Lisp_Object h;
   register Lisp_Object tem;
+  int debugger_called = 0;
+  int debugger_considered = 0;
 
-  if (EQ (handlers, Qt))  /* t is used by handlers for all conditions, set up by C code.  */
+  /* t is used by handlers for all conditions, set up by C code.  */
+  if (EQ (handlers, Qt))
     return Qt;
+
+  /* Don't run the debugger for a memory-full error.
+     (There is no room in memory to do that!)  */
+  if (NILP (sig))
+    debugger_considered = 1;
+
   /* error is used similarly, but means print an error message
      and run the debugger if that is enabled.  */
   if (EQ (handlers, Qerror)
       || !NILP (Vdebug_on_signal)) /* This says call debugger even if
                                      there is a handler.  */
     {
-      int debugger_called = 0;
-      Lisp_Object sig_symbol, combined_data;
-      /* This is set to 1 if we are handling a memory-full error,
-        because these must not run the debugger.
-        (There is no room in memory to do that!)  */
-      int no_debugger = 0;
-
-      if (NILP (sig))
-       {
-         combined_data = data;
-         sig_symbol = Fcar (data);
-         no_debugger = 1;
-       }
-      else
-       {
-         combined_data = Fcons (sig, data);
-         sig_symbol = sig;
-       }
-
-      if (wants_debugger (Vstack_trace_on_error, conditions))
+      if (!NILP (sig) && wants_debugger (Vstack_trace_on_error, conditions))
        {
          max_specpdl_size++;
-#ifdef PROTOTYPES
+    #ifdef PROTOTYPES
          internal_with_output_to_temp_buffer ("*Backtrace*",
                                               (Lisp_Object (*) (Lisp_Object)) Fbacktrace,
                                               Qnil);
-#else
+    #else
          internal_with_output_to_temp_buffer ("*Backtrace*",
                                               Fbacktrace, Qnil);
-#endif
+    #endif
          max_specpdl_size--;
        }
-      if (! no_debugger
-         && (EQ (sig_symbol, Qquit)
-             ? debug_on_quit
-             : wants_debugger (Vdebug_on_error, conditions))
-         && ! skip_debugger (conditions, combined_data)
-         && when_entered_debugger < num_nonmacro_input_events)
+
+      if (!debugger_considered)
        {
-         *debugger_value_ptr
-           = call_debugger (Fcons (Qerror,
-                                   Fcons (combined_data, Qnil)));
-         debugger_called = 1;
+         debugger_considered = 1;
+         debugger_called = maybe_call_debugger (conditions, sig, data);
        }
+
       /* If there is no handler, return saying whether we ran the debugger.  */
       if (EQ (handlers, Qerror))
        {
@@ -1914,6 +1919,7 @@ find_handler_clause (handlers, conditions, sig, data, debugger_value_ptr)
          return Qt;
        }
     }
+
   for (h = handlers; CONSP (h); h = Fcdr (h))
     {
       Lisp_Object handler, condit;
@@ -1932,18 +1938,55 @@ find_handler_clause (handlers, conditions, sig, data, debugger_value_ptr)
       /* Handle a list of condition names in handler HANDLER.  */
       else if (CONSP (condit))
        {
-         while (CONSP (condit))
+         Lisp_Object tail;
+         for (tail = condit; CONSP (tail); tail = XCDR (tail))
            {
-             tem = Fmemq (Fcar (condit), conditions);
+             tem = Fmemq (Fcar (tail), conditions);
              if (!NILP (tem))
-               return handler;
-             condit = XCDR (condit);
+               {
+                 /* This handler is going to apply.
+                    Does it allow the debugger to run first?  */
+                 if (! debugger_considered && !NILP (Fmemq (Qdebug, condit)))
+                   maybe_call_debugger (conditions, sig, data);
+                 return handler;
+               }
            }
        }
     }
+
   return Qnil;
 }
 
+/* Call the debugger if calling it is currently enabled for CONDITIONS.
+   SIG and DATA describe the signal, as in find_handler_clause.  */
+
+int
+maybe_call_debugger (conditions, sig, data)
+     Lisp_Object conditions, sig, data;
+{
+  Lisp_Object combined_data;
+
+  combined_data = Fcons (sig, data);
+
+  if (
+      /* Don't try to run the debugger with interrupts blocked.
+        The editing loop would return anyway.  */
+      ! INPUT_BLOCKED_P
+      /* Does user wants to enter debugger for this kind of error?  */
+      && (EQ (sig, Qquit)
+         ? debug_on_quit
+         : wants_debugger (Vdebug_on_error, conditions))
+      && ! skip_debugger (conditions, combined_data)
+      /* rms: what's this for? */
+      && when_entered_debugger < num_nonmacro_input_events)
+    {
+      call_debugger (Fcons (Qerror, Fcons (combined_data, Qnil)));
+      return 1;
+    }
+
+  return 0;
+}
+
 /* dump an error message; called like printf */
 
 /* VARARGS 1 */
@@ -2008,42 +2051,49 @@ then strings and vectors are not accepted.  */)
 {
   register Lisp_Object fun;
   register Lisp_Object funcar;
+  Lisp_Object if_prop = Qnil;
 
   fun = function;
 
-  fun = indirect_function (fun);
-  if (EQ (fun, Qunbound))
+  fun = indirect_function (fun); /* Check cycles. */
+  if (NILP (fun) || EQ (fun, Qunbound))
     return Qnil;
 
+  /* Check an `interactive-form' property if present, analogous to the
+     function-documentation property. */
+  fun = function;
+  while (SYMBOLP (fun))
+    {
+      Lisp_Object tmp = Fget (fun, intern ("interactive-form"));
+      if (!NILP (tmp))
+       if_prop = Qt;
+      fun = Fsymbol_function (fun);
+    }
+
   /* Emacs primitives are interactive if their DEFUN specifies an
      interactive spec.  */
   if (SUBRP (fun))
-    {
-      if (XSUBR (fun)->prompt)
-       return Qt;
-      else
-       return Qnil;
-    }
+    return XSUBR (fun)->intspec ? Qt : if_prop;
 
   /* Bytecode objects are interactive if they are long enough to
      have an element whose index is COMPILED_INTERACTIVE, which is
      where the interactive spec is stored.  */
   else if (COMPILEDP (fun))
     return ((ASIZE (fun) & PSEUDOVECTOR_SIZE_MASK) > COMPILED_INTERACTIVE
-           ? Qt : Qnil);
+           ? Qt : if_prop);
 
   /* Strings and vectors are keyboard macros.  */
-  if (NILP (for_call_interactively) && (STRINGP (fun) || VECTORP (fun)))
-    return Qt;
+  if (STRINGP (fun) || VECTORP (fun))
+    return (NILP (for_call_interactively) ? Qt : Qnil);
 
   /* Lists may represent commands.  */
   if (!CONSP (fun))
     return Qnil;
   funcar = XCAR (fun);
   if (EQ (funcar, Qlambda))
-    return Fassq (Qinteractive, Fcdr (XCDR (fun)));
+    return !NILP (Fassq (Qinteractive, Fcdr (XCDR (fun)))) ? Qt : if_prop;
   if (EQ (funcar, Qautoload))
-    return Fcar (Fcdr (Fcdr (XCDR (fun))));
+    return !NILP (Fcar (Fcdr (Fcdr (XCDR (fun))))) ? Qt : if_prop;
   else
     return Qnil;
 }
@@ -2128,7 +2178,7 @@ do_autoload (fundef, funname)
      Lisp_Object fundef, funname;
 {
   int count = SPECPDL_INDEX ();
-  Lisp_Object fun, queue, first, second;
+  Lisp_Object fun;
   struct gcpro gcpro1, gcpro2, gcpro3;
 
   /* This is to make sure that loadup.el gives a clear picture
@@ -2147,21 +2197,7 @@ do_autoload (fundef, funname)
   /* Value saved here is to be restored into Vautoload_queue.  */
   record_unwind_protect (un_autoload, Vautoload_queue);
   Vautoload_queue = Qt;
-  Fload (Fcar (Fcdr (fundef)), Qnil, noninteractive ? Qt : Qnil, Qnil, Qt);
-
-  /* Save the old autoloads, in case we ever do an unload.  */
-  queue = Vautoload_queue;
-  while (CONSP (queue))
-    {
-      first = XCAR (queue);
-      second = Fcdr (first);
-      first = Fcar (first);
-
-      if (SYMBOLP (first) && CONSP (second) && EQ (XCAR (second), Qautoload))
-       Fput (first, Qautoload, (XCDR (second)));
-
-      queue = XCDR (queue);
-    }
+  Fload (Fcar (Fcdr (fundef)), Qnil, Qt, Qnil, Qt);
 
   /* Once loading finishes, don't undo it.  */
   Vautoload_queue = Qt;
@@ -3584,6 +3620,9 @@ before making `inhibit-quit' nil.  */);
   Qand_optional = intern ("&optional");
   staticpro (&Qand_optional);
 
+  Qdebug = intern ("debug");
+  staticpro (&Qdebug);
+
   DEFVAR_LISP ("stack-trace-on-error", &Vstack_trace_on_error,
               doc: /* *Non-nil means errors display a backtrace buffer.
 More precisely, this happens for any error that is handled