Merge from emacs--rel--22
[bpt/emacs.git] / src / eval.c
index ee73655..7f5f58a 100644 (file)
@@ -202,6 +202,8 @@ 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;
 
@@ -539,7 +541,7 @@ usage: (setq [SYM VAL]...)  */)
   register Lisp_Object val, sym;
   struct gcpro gcpro1;
 
-  if (NILP(args))
+  if (NILP (args))
     return Qnil;
 
   args_left = args;
@@ -564,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);
 }
 
@@ -575,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);
 }
 
@@ -1037,10 +1043,10 @@ usage: (let VARLIST BODY...)  */)
   GCPRO2 (args, *temps);
   gcpro2.nvars = 0;
 
-  for (argnum = 0; !NILP (varlist); varlist = Fcdr (varlist))
+  for (argnum = 0; CONSP (varlist); varlist = XCDR (varlist))
     {
       QUIT;
-      elt = Fcar (varlist);
+      elt = XCAR (varlist);
       if (SYMBOLP (elt))
        temps [argnum++] = Qnil;
       else if (! NILP (Fcdr (Fcdr (elt))))
@@ -1052,9 +1058,9 @@ usage: (let VARLIST BODY...)  */)
   UNGCPRO;
 
   varlist = Fcar (args);
-  for (argnum = 0; !NILP (varlist); varlist = Fcdr (varlist))
+  for (argnum = 0; CONSP (varlist); varlist = XCDR (varlist))
     {
-      elt = Fcar (varlist);
+      elt = XCAR (varlist);
       tem = temps[argnum++];
       if (SYMBOLP (elt))
        specbind (elt, tem);
@@ -1274,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;
@@ -1587,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.
@@ -1614,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;
@@ -1672,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))
        {
@@ -1703,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);
 
@@ -1855,75 +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
-         /* 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))
-         && ! 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))
        {
@@ -1932,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;
@@ -1950,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 */
@@ -2026,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;
 }
@@ -2172,7 +2204,7 @@ do_autoload (fundef, funname)
      The 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);
+  Fload (Fcar (Fcdr (fundef)), Qnil, Qt, Qnil, Qt);
 
   /* Once loading finishes, don't undo it.  */
   Vautoload_queue = Qt;
@@ -3260,7 +3292,6 @@ specbind (symbol, value)
       valcontents = XSYMBOL (symbol)->value;
 
       if (BUFFER_LOCAL_VALUEP (valcontents)
-         || SOME_BUFFER_LOCAL_VALUEP (valcontents)
          || BUFFER_OBJFWDP (valcontents))
        {
          Lisp_Object where, current_buffer;
@@ -3271,7 +3302,7 @@ specbind (symbol, value)
             buffer's or frame's value we are saving.  */
          if (!NILP (Flocal_variable_p (symbol, Qnil)))
            where = current_buffer;
-         else if (!BUFFER_OBJFWDP (valcontents)
+         else if (BUFFER_LOCAL_VALUEP (valcontents)
                   && XBUFFER_LOCAL_VALUE (valcontents)->found_for_frame)
            where = XBUFFER_LOCAL_VALUE (valcontents)->frame;
          else