]> code.delx.au - gnu-emacs/blobdiff - src/eval.c
(fontset_ref): Remove unused variable `i'.
[gnu-emacs] / src / eval.c
index ad01cb4f0219ceb186b002713d28008c5d3a295e..8d8b9b14d42b78502184b9c12816e0a05a41ac81 100644 (file)
@@ -32,17 +32,17 @@ Boston, MA 02111-1307, USA.  */
 /* Putting it in lisp.h makes cc bomb out! */
 
 struct backtrace
-  {
-    struct backtrace *next;
-    Lisp_Object *function;
-    Lisp_Object *args; /* Points to vector of args. */
-    int nargs;         /* Length of vector.
+{
+  struct backtrace *next;
+  Lisp_Object *function;
+  Lisp_Object *args;   /* Points to vector of args. */
+  int nargs;           /* Length of vector.
                           If nargs is UNEVALLED, args points to slot holding
                           list of unevalled args */
-    char evalargs;
-    /* Nonzero means call value of debugger when done with this operation. */
-    char debug_on_exit;
-  };
+  char evalargs;
+  /* Nonzero means call value of debugger when done with this operation. */
+  char debug_on_exit;
+};
 
 struct backtrace *backtrace_list;
 
@@ -64,20 +64,21 @@ struct backtrace *backtrace_list;
 
    All the other members are concerned with restoring the interpreter
    state.  */
+
 struct catchtag
-  {
-    Lisp_Object tag;
-    Lisp_Object val;
-    struct catchtag *next;
-    struct gcpro *gcpro;
-    jmp_buf jmp;
-    struct backtrace *backlist;
-    struct handler *handlerlist;
-    int lisp_eval_depth;
-    int pdlcount;
-    int poll_suppress_count;
-    struct byte_stack *byte_stack;
-  };
+{
+  Lisp_Object tag;
+  Lisp_Object val;
+  struct catchtag *next;
+  struct gcpro *gcpro;
+  jmp_buf jmp;
+  struct backtrace *backlist;
+  struct handler *handlerlist;
+  int lisp_eval_depth;
+  int pdlcount;
+  int poll_suppress_count;
+  struct byte_stack *byte_stack;
+};
 
 struct catchtag *catchlist;
 
@@ -95,6 +96,7 @@ Lisp_Object Qdebug_on_error;
 /* This holds either the symbol `run-hooks' or nil.
    It is nil at an early stage of startup, and when Emacs
    is shutting down.  */
+
 Lisp_Object Vrun_hooks;
 
 /* Non-nil means record all fset's and provide's, to be undone
@@ -105,24 +107,31 @@ Lisp_Object Vrun_hooks;
 Lisp_Object Vautoload_queue;
 
 /* Current number of specbindings allocated in specpdl.  */
+
 int specpdl_size;
 
 /* Pointer to beginning of specpdl.  */
+
 struct specbinding *specpdl;
 
 /* Pointer to first unused element in specpdl.  */
+
 struct specbinding *specpdl_ptr;
 
 /* Maximum size allowed for specpdl allocation */
+
 int max_specpdl_size;
 
 /* Depth in Lisp evaluations and function calls.  */
+
 int lisp_eval_depth;
 
 /* Maximum allowed depth in Lisp evaluations and function calls.  */
+
 int max_lisp_eval_depth;
 
 /* Nonzero means enter debugger before next function call */
+
 int debug_on_next_call;
 
 /* Non-zero means debuffer may continue.  This is zero when the
@@ -133,24 +142,30 @@ int debugger_may_continue;
 
 /* List of conditions (non-nil atom means all) which cause a backtrace
    if an error is handled by the command loop's error handler.  */
+
 Lisp_Object Vstack_trace_on_error;
 
 /* List of conditions (non-nil atom means all) which enter the debugger
    if an error is handled by the command loop's error handler.  */
+
 Lisp_Object Vdebug_on_error;
 
 /* List of conditions and regexps specifying error messages which
    do not enter the debugger even if Vdebug_on_errors says they should.  */
+
 Lisp_Object Vdebug_ignored_errors;
 
 /* Non-nil means call the debugger even if the error will be handled.  */
+
 Lisp_Object Vdebug_on_signal;
 
 /* Hook for edebug to use.  */
+
 Lisp_Object Vsignal_hook_function;
 
 /* Nonzero means enter debugger if a quit signal
    is handled by the command loop's error handler. */
+
 int debug_on_quit;
 
 /* The value of num_nonmacro_input_events as of the last time we
@@ -159,10 +174,22 @@ int debug_on_quit;
    know that the debugger itself has an error, and we should just
    signal the error instead of entering an infinite loop of debugger
    invocations.  */
+
 int when_entered_debugger;
 
 Lisp_Object Vdebugger;
 
+/* The function from which the last `signal' was called.  Set in
+   Fsignal.  */
+
+Lisp_Object Vsignaling_function;
+
+/* Set to non-zero while processing X events.  Checked in Feval to
+   make sure the Lisp interpreter isn't called from a signal handler,
+   which is unsafe because the interpreter isn't reentrant.  */
+
+int handling_signal;
+
 void specbind (), record_unwind_protect ();
 
 Lisp_Object run_hook_with_args ();
@@ -213,6 +240,11 @@ call_debugger (arg)
   if (specpdl_size + 40 > max_specpdl_size)
     max_specpdl_size = specpdl_size + 40;
   
+#ifdef HAVE_X_WINDOWS
+  if (display_busy_cursor_p)
+    cancel_busy_cursor ();
+#endif
+
   debug_on_next_call = 0;
   when_entered_debugger = num_nonmacro_input_events;
 
@@ -619,7 +651,8 @@ If SYMBOL is buffer-local, its default value is what is set;\n\
  buffer-local values are not affected.\n\
 INITVALUE and DOCSTRING are optional.\n\
 If DOCSTRING starts with *, this variable is identified as a user option.\n\
- This means that M-x set-variable and M-x edit-options recognize it.\n\
+ This means that M-x set-variable recognizes it.\n\
+ See also `user-variable-p'.\n\
 If INITVALUE is missing, SYMBOL's value is not set.")
   (args)
      Lisp_Object args;
@@ -840,7 +873,7 @@ DEFUN ("macroexpand", Fmacroexpand, Smacroexpand, 1, 2, 0,
 If FORM is not a macro call, it is returned unchanged.\n\
 Otherwise, the macro is expanded and the expansion is considered\n\
 in place of FORM.  When a non-macro-call results, it is returned.\n\n\
-The second optional arg ENVIRONMENT species an environment of macro\n\
+The second optional arg ENVIRONMENT specifies an environment of macro\n\
 definitions to shadow the loaded ones for use in file byte-compilation.")
   (form, environment)
      Lisp_Object form;
@@ -1093,7 +1126,8 @@ See also the function `signal' for more info.")
   Lisp_Object val;
   struct catchtag c;
   struct handler h;
-  register Lisp_Object var, bodyform, handlers;
+  register Lisp_Object bodyform, handlers;
+  volatile Lisp_Object var;
 
   var      = Fcar (args);
   bodyform = Fcar (Fcdr (args));
@@ -1167,10 +1201,14 @@ internal_condition_case (bfun, handlers, hfun)
   struct catchtag c;
   struct handler h;
 
+#if 0 /* Can't do this check anymore because realize_basic_faces has
+        to BLOCK_INPUT, and can call Lisp.  What's really needed is a
+        flag indicating that we're currently handling a signal.  */
   /* Since Fsignal resets this to 0, it had better be 0 now
      or else we have a potential bug.  */
   if (interrupt_input_blocked != 0)
     abort ();
+#endif
 
   c.tag = Qnil;
   c.val = Qnil;
@@ -1238,6 +1276,50 @@ internal_condition_case_1 (bfun, arg, handlers, hfun)
   handlerlist = h.next;
   return val;
 }
+
+
+/* Like internal_condition_case but call HFUN with NARGS as first,
+   and ARGS as second argument.  */
+
+Lisp_Object
+internal_condition_case_2 (bfun, nargs, args, handlers, hfun)
+     Lisp_Object (*bfun) ();
+     int nargs;
+     Lisp_Object *args;
+     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;
+  c.byte_stack = byte_stack_list;
+  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) (nargs, args);
+  catchlist = c.next;
+  handlerlist = h.next;
+  return val;
+}
+
 \f
 static Lisp_Object find_handler_clause ();
 
@@ -1265,8 +1347,9 @@ See also the function `condition-case'.")
   Lisp_Object string;
   Lisp_Object real_error_symbol;
   extern int display_busy_cursor_p;
+  struct backtrace *bp;
 
-  immediate_quit = 0;
+  immediate_quit = handling_signal = 0;
   if (gc_in_progress || waiting_for_input)
     abort ();
 
@@ -1279,7 +1362,7 @@ See also the function `condition-case'.")
 
 #ifdef HAVE_X_WINDOWS
   if (display_busy_cursor_p)
-    Fx_hide_busy_cursor (Qt);
+    cancel_busy_cursor ();
 #endif
 
   /* This hook is used by edebug.  */
@@ -1288,9 +1371,29 @@ See also the function `condition-case'.")
 
   conditions = Fget (real_error_symbol, Qerror_conditions);
 
+  /* Remember from where signal was called.  Skip over the frame for
+     `signal' itself.  If a frame for `error' follows, skip that,
+     too.  */
+  Vsignaling_function = Qnil;
+  if (backtrace_list)
+    {
+      bp = backtrace_list->next;
+      if (bp && bp->function && EQ (*bp->function, Qerror))
+       bp = bp->next;
+      if (bp && bp->function)
+       Vsignaling_function = *bp->function;
+    }
+
   for (; handlerlist; handlerlist = handlerlist->next)
     {
       register Lisp_Object clause;
+      
+      if (lisp_eval_depth + 20 > max_lisp_eval_depth)
+       max_lisp_eval_depth = lisp_eval_depth + 20;
+  
+      if (specpdl_size + 40 > max_specpdl_size)
+       max_specpdl_size = specpdl_size + 40;
+  
       clause = find_handler_clause (handlerlist->handler, conditions,
                                    error_symbol, data, &debugger_value);
 
@@ -1378,8 +1481,8 @@ skip_debugger (conditions, data)
   int first_string = 1;
   Lisp_Object error_message;
 
-  for (tail = Vdebug_ignored_errors; CONSP (tail);
-       tail = XCDR (tail))
+  error_message = Qnil;
+  for (tail = Vdebug_ignored_errors; CONSP (tail); tail = XCDR (tail))
     {
       if (STRINGP (XCAR (tail)))
        {
@@ -1388,6 +1491,7 @@ skip_debugger (conditions, data)
              error_message = Ferror_message_string (data);
              first_string = 0;
            }
+         
          if (fast_string_match (XCAR (tail), error_message) >= 0)
            return 1;
        }
@@ -1395,8 +1499,7 @@ skip_debugger (conditions, data)
        {
          Lisp_Object contail;
 
-         for (contail = conditions; CONSP (contail);
-              contail = XCDR (contail))
+         for (contail = conditions; CONSP (contail); contail = XCDR (contail))
            if (EQ (XCAR (tail), XCAR (contail)))
              return 1;
        }
@@ -1451,7 +1554,7 @@ find_handler_clause (handlers, conditions, sig, data, debugger_value_ptr)
 
       if (wants_debugger (Vstack_trace_on_error, conditions))
        {
-#ifdef __STDC__
+#ifdef PROTOTYPES
          internal_with_output_to_temp_buffer ("*Backtrace*",
                                               (Lisp_Object (*) (Lisp_Object)) Fbacktrace,
                                               Qnil);
@@ -1550,9 +1653,10 @@ error (m, a1, a2, a3)
 
   string = build_string (buffer);
   if (allocated)
-    free (buffer);
+    xfree (buffer);
 
   Fsignal (Qerror, Fcons (string, Qnil));
+  abort ();
 }
 \f
 DEFUN ("commandp", Fcommandp, Scommandp, 1, 1, 0,
@@ -1646,6 +1750,11 @@ this does nothing and returns nil.")
           && EQ (XCAR (XSYMBOL (function)->function), Qautoload)))
     return Qnil;
 
+  if (NILP (Vpurify_flag))
+    /* Only add entries after dumping, because the ones before are
+       not useful and else we get loads of them from the loaddefs.el.  */
+    LOADHIST_ATTACH (Fcons (Qautoload, function));
+
 #ifdef NO_ARG_ARRAY
   args[0] = file;
   args[1] = docstring;
@@ -1734,6 +1843,7 @@ do_autoload (fundef, funname)
           XSYMBOL (funname)->name->data);
   UNGCPRO;
 }
+
 \f
 DEFUN ("eval", Feval, Seval, 1, 1, 0,
   "Evaluate FORM and return its value.")
@@ -1745,9 +1855,7 @@ DEFUN ("eval", Feval, Seval, 1, 1, 0,
   struct backtrace backtrace;
   struct gcpro gcpro1, gcpro2, gcpro3;
 
-  /* Since Fsignal resets this to 0, it had better be 0 now
-     or else we have a potential bug.  */
-  if (interrupt_input_blocked != 0)
+  if (handling_signal)
     abort ();
   
   if (SYMBOLP (form))
@@ -2032,7 +2140,7 @@ Thus, (apply '+ 1 2 '(3 4)) returns 10.")
 
 enum run_hooks_condition {to_completion, until_success, until_failure};
 
-DEFUN ("run-hooks", Frun_hooks, Srun_hooks, 1, MANY, 0,
+DEFUN ("run-hooks", Frun_hooks, Srun_hooks, 0, MANY, 0,
   "Run each hook in HOOKS.  Major mode functions use this.\n\
 Each argument should be a symbol, a hook variable.\n\
 These symbols are processed in the order specified.\n\
@@ -2642,31 +2750,35 @@ funcall_lambda (fun, nargs, arg_vector)
      int nargs;
      register Lisp_Object *arg_vector;
 {
-  Lisp_Object val, tem;
-  register Lisp_Object syms_left;
-  Lisp_Object numargs;
-  register Lisp_Object next;
+  Lisp_Object val, syms_left, next;
   int count = specpdl_ptr - specpdl;
-  register int i;
-  int optional = 0, rest = 0;
-
-  specbind (Qmocklisp_arguments, Qt);   /* t means NOT mocklisp! */
+  int i, optional, rest;
 
-  XSETFASTINT (numargs, nargs);
+  if (NILP (Vmocklisp_arguments))
+    specbind (Qmocklisp_arguments, Qt);   /* t means NOT mocklisp! */
 
   if (CONSP (fun))
-    syms_left = Fcar (Fcdr (fun));
+    {
+      syms_left = XCDR (fun);
+      if (CONSP (syms_left))
+       syms_left = XCAR (syms_left);
+      else
+       return Fsignal (Qinvalid_function, Fcons (fun, Qnil));
+    }
   else if (COMPILEDP (fun))
     syms_left = XVECTOR (fun)->contents[COMPILED_ARGLIST];
-  else abort ();
+  else
+    abort ();
 
-  i = 0;
-  for (; !NILP (syms_left); syms_left = Fcdr (syms_left))
+  i = optional = rest = 0;
+  for (; CONSP (syms_left); syms_left = XCDR (syms_left))
     {
       QUIT;
-      next = Fcar (syms_left);
+      
+      next = XCAR (syms_left);
       while (!SYMBOLP (next))
        next = Fsignal (Qinvalid_function, Fcons (fun, Qnil));
+      
       if (EQ (next, Qand_rest))
        rest = 1;
       else if (EQ (next, Qand_optional))
@@ -2677,21 +2789,22 @@ funcall_lambda (fun, nargs, arg_vector)
          i = nargs;
        }
       else if (i < nargs)
-       {
-         tem = arg_vector[i++];
-         specbind (next, tem);
-       }
+       specbind (next, arg_vector[i++]);
       else if (!optional)
-       return Fsignal (Qwrong_number_of_arguments, Fcons (fun, Fcons (numargs, Qnil)));
+       return Fsignal (Qwrong_number_of_arguments,
+                       Fcons (fun, Fcons (make_number (nargs), Qnil)));
       else
        specbind (next, Qnil);
     }
 
-  if (i < nargs)
-    return Fsignal (Qwrong_number_of_arguments, Fcons (fun, Fcons (numargs, Qnil)));
+  if (!NILP (syms_left))
+    return Fsignal (Qinvalid_function, Fcons (fun, Qnil));
+  else if (i < nargs)
+    return Fsignal (Qwrong_number_of_arguments,
+                   Fcons (fun, Fcons (make_number (nargs), Qnil)));
 
   if (CONSP (fun))
-    val = Fprogn (Fcdr (Fcdr (fun)));
+    val = Fprogn (XCDR (XCDR (fun)));
   else
     {
       /* If we have not actually read the bytecode string
@@ -2702,6 +2815,7 @@ funcall_lambda (fun, nargs, arg_vector)
                        XVECTOR (fun)->contents[COMPILED_CONSTANTS],
                        XVECTOR (fun)->contents[COMPILED_STACK_DEPTH]);
     }
+  
   return unbind_to (count, val);
 }
 
@@ -2756,36 +2870,55 @@ specbind (symbol, value)
   Lisp_Object ovalue;
 
   CHECK_SYMBOL (symbol, 0);
-
-  ovalue = find_symbol_value (symbol);
-
   if (specpdl_ptr == specpdl + specpdl_size)
     grow_specpdl ();
-  specpdl_ptr->func = 0;
-  specpdl_ptr->old_value = ovalue;
-
-  if (BUFFER_LOCAL_VALUEP (XSYMBOL (symbol)->value)
-      || SOME_BUFFER_LOCAL_VALUEP (XSYMBOL (symbol)->value)
-      || BUFFER_OBJFWDP (XSYMBOL (symbol)->value))
-    {
-      Lisp_Object buffer;
-      /* For a local variable, record both the symbol and which
-        buffer's value we are saving.  */
-      buffer = Fcurrent_buffer ();
-      /* If the variable is not local in this buffer,
-        we are saving the global value, so restore that.  */
-      if (NILP (Flocal_variable_p (symbol, buffer)))
-       buffer = Qnil;
-      specpdl_ptr->symbol = Fcons (symbol, buffer);
+
+  /* The most common case is that a non-constant symbol with a trivial
+     value.  Make that as fast as we can.  */
+  if (!MISCP (XSYMBOL (symbol)->value)
+      && !EQ (symbol, Qnil)
+      && !EQ (symbol, Qt)
+      && !(XSYMBOL (symbol)->name->data[0] == ':'
+          && EQ (XSYMBOL (symbol)->obarray, initial_obarray)
+          && !EQ (value, symbol)))
+    {
+      specpdl_ptr->symbol = symbol;
+      specpdl_ptr->old_value = XSYMBOL (symbol)->value;
+      specpdl_ptr->func = NULL;
+      ++specpdl_ptr;
+      XSYMBOL (symbol)->value = value;
     }
   else
-    specpdl_ptr->symbol = symbol;
+    {
+      ovalue = find_symbol_value (symbol);
+      specpdl_ptr->func = 0;
+      specpdl_ptr->old_value = ovalue;
 
-  specpdl_ptr++;
-  if (BUFFER_OBJFWDP (ovalue) || KBOARD_OBJFWDP (ovalue))
-    store_symval_forwarding (symbol, ovalue, value);
-  else
-    set_internal (symbol, value, 0, 1);
+      if (BUFFER_LOCAL_VALUEP (XSYMBOL (symbol)->value)
+         || SOME_BUFFER_LOCAL_VALUEP (XSYMBOL (symbol)->value)
+         || BUFFER_OBJFWDP (XSYMBOL (symbol)->value))
+       {
+         Lisp_Object current_buffer, binding_buffer;
+         /* For a local variable, record both the symbol and which
+            buffer's value we are saving.  */
+         current_buffer = Fcurrent_buffer ();
+         binding_buffer = current_buffer;
+         /* If the variable is not local in this buffer,
+            we are saving the global value, so restore that.  */
+         if (NILP (Flocal_variable_p (symbol, binding_buffer)))
+           binding_buffer = Qnil;
+         specpdl_ptr->symbol
+           = Fcons (symbol, Fcons (binding_buffer, current_buffer));
+       }
+      else
+       specpdl_ptr->symbol = symbol;
+
+      specpdl_ptr++;
+      if (BUFFER_OBJFWDP (ovalue) || KBOARD_OBJFWDP (ovalue))
+       store_symval_forwarding (symbol, ovalue, value);
+      else
+       set_internal (symbol, value, 0, 1);
+    }
 }
 
 void
@@ -2810,24 +2943,28 @@ unbind_to (count, value)
   struct gcpro gcpro1;
 
   GCPRO1 (value);
-
   Vquit_flag = Qnil;
 
   while (specpdl_ptr != specpdl + count)
     {
       --specpdl_ptr;
+      
       if (specpdl_ptr->func != 0)
        (*specpdl_ptr->func) (specpdl_ptr->old_value);
       /* Note that a "binding" of nil is really an unwind protect,
         so in that case the "old value" is a list of forms to evaluate.  */
       else if (NILP (specpdl_ptr->symbol))
        Fprogn (specpdl_ptr->old_value);
+      /* If the symbol is a list, it is really
+        (SYMBOL BINDING_BUFFER . CURRENT_BUFFER)
+        and it indicates we bound a variable that has
+        buffer-local bindings.  */
       else if (CONSP (specpdl_ptr->symbol))
        {
          Lisp_Object symbol, buffer;
 
          symbol = XCAR (specpdl_ptr->symbol);
-         buffer = XCDR (specpdl_ptr->symbol);
+         buffer = XCAR (XCDR (specpdl_ptr->symbol));
 
          /* Handle restoring a default value.  */
          if (NILP (buffer))
@@ -2837,12 +2974,21 @@ unbind_to (count, value)
            set_internal (symbol, specpdl_ptr->old_value, XBUFFER (buffer), 1);
        }
       else
-        set_internal (specpdl_ptr->symbol, specpdl_ptr->old_value, 0, 1);
+       {
+         /* If variable has a trivial value (no forwarding), we can
+            just set it.  No need to check for constant symbols here,
+            since that was already done by specbind.  */
+         if (!MISCP (XSYMBOL (specpdl_ptr->symbol)->value))
+           XSYMBOL (specpdl_ptr->symbol)->value = specpdl_ptr->old_value;
+         else
+           set_internal (specpdl_ptr->symbol, specpdl_ptr->old_value, 0, 1);
+       }
     }
-  if (NILP (Vquit_flag) && quitf) Vquit_flag = Qt;
+  
+  if (NILP (Vquit_flag) && quitf)
+    Vquit_flag = Qt;
 
   UNGCPRO;
-
   return value;
 }
 \f
@@ -2966,7 +3112,7 @@ Output stream used is value of `standard-output'.")
   return Qnil;
 }
 
-DEFUN ("backtrace-frame", Fbacktrace_frame, Sbacktrace_frame, 1, 1, "",
+DEFUN ("backtrace-frame", Fbacktrace_frame, Sbacktrace_frame, 1, 1, NULL,
   "Return the function and arguments NFRAMES up from current execution point.\n\
 If that frame has not evaluated the arguments yet (or is a special form),\n\
 the value is (nil FUNCTION ARG-FORMS...).\n\
@@ -3003,6 +3149,7 @@ If NFRAMES is more than the number of frames, the value is nil.")
       return Fcons (Qt, Fcons (*backlist->function, tem));
     }
 }
+
 \f
 void
 syms_of_eval ()
@@ -3134,6 +3281,8 @@ still determine whether to handle the particular condition.");
 
   staticpro (&Vautoload_queue);
   Vautoload_queue = Qnil;
+  staticpro (&Vsignaling_function);
+  Vsignaling_function = Qnil;
 
   defsubr (&Sor);
   defsubr (&Sand);