changeset 50919:bbe405e5721e

(specpdl_ptr): Declare volatile. (unbind_to): Copy the whole binding and decrement specpdl_ptr before doing the work of unbinding it.
author Richard M. Stallman <rms@gnu.org>
date Fri, 09 May 2003 14:01:12 +0000
parents d1b8ac33a632
children 997593980303
files src/eval.c
diffstat 1 files changed, 20 insertions(+), 14 deletions(-) [+]
line wrap: on
line diff
--- a/src/eval.c	Fri May 09 13:58:38 2003 +0000
+++ b/src/eval.c	Fri May 09 14:01:12 2003 +0000
@@ -117,7 +117,7 @@
 
 /* Pointer to first unused element in specpdl.  */
 
-struct specbinding *specpdl_ptr;
+volatile struct specbinding *specpdl_ptr;
 
 /* Maximum size allowed for specpdl allocation */
 
@@ -3070,10 +3070,16 @@
 
   while (specpdl_ptr != specpdl + count)
     {
-      --specpdl_ptr;
-
-      if (specpdl_ptr->func != 0)
-	(*specpdl_ptr->func) (specpdl_ptr->old_value);
+      /* Copy the binding, and decrement specpdl_ptr, before we do
+	 the work to unbind it.  We decrement first
+	 so that an error in unbinding won't try to unbind
+	 the same entry again, and we copy the binding first
+	 in case more bindings are made during some of the code we run.  */
+
+      struct specbinding this_binding = *--specpdl_ptr;
+
+      if (this_binding.func != 0)
+	(*this_binding.func) (this_binding.old_value);
       /* If the symbol is a list, it is really (SYMBOL WHERE
 	 . CURRENT-BUFFER) where WHERE is either nil, a buffer, or a
 	 frame.  If WHERE is a buffer or frame, this indicates we
@@ -3081,29 +3087,29 @@
 	 binding.  WHERE nil means that the variable had the default
 	 value when it was bound.  CURRENT-BUFFER is the buffer that
          was current when the variable was bound.  */
-      else if (CONSP (specpdl_ptr->symbol))
+      else if (CONSP (this_binding.symbol))
 	{
 	  Lisp_Object symbol, where;
 
-	  symbol = XCAR (specpdl_ptr->symbol);
-	  where = XCAR (XCDR (specpdl_ptr->symbol));
+	  symbol = XCAR (this_binding.symbol);
+	  where = XCAR (XCDR (this_binding.symbol));
 
 	  if (NILP (where))
-	    Fset_default (symbol, specpdl_ptr->old_value);
+	    Fset_default (symbol, this_binding.old_value);
 	  else if (BUFFERP (where))
-	    set_internal (symbol, specpdl_ptr->old_value, XBUFFER (where), 1);
+	    set_internal (symbol, this_binding.old_value, XBUFFER (where), 1);
 	  else
-	    set_internal (symbol, specpdl_ptr->old_value, NULL, 1);
+	    set_internal (symbol, this_binding.old_value, NULL, 1);
 	}
       else
 	{
 	  /* 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 (SYMBOL_VALUE (specpdl_ptr->symbol)))
-	    SET_SYMBOL_VALUE (specpdl_ptr->symbol, specpdl_ptr->old_value);
+	  if (!MISCP (SYMBOL_VALUE (this_binding.symbol)))
+	    SET_SYMBOL_VALUE (this_binding.symbol, this_binding.old_value);
 	  else
-	    set_internal (specpdl_ptr->symbol, specpdl_ptr->old_value, 0, 1);
+	    set_internal (this_binding.symbol, this_binding.old_value, 0, 1);
 	}
     }