/* Pointer to first unused element in specpdl. */
-struct specbinding *specpdl_ptr;
+volatile struct specbinding *specpdl_ptr;
/* Maximum size allowed for specpdl allocation */
Lisp_Object val;
int count = SPECPDL_INDEX ();
- record_unwind_protect (0, Fcdr (args));
+ record_unwind_protect (Fprogn, Fcdr (args));
val = Feval (Fcar (args));
return unbind_to (count, val);
}
struct backtrace *bp;
immediate_quit = handling_signal = 0;
+ abort_on_gc = 0;
if (gc_in_progress || waiting_for_input)
abort ();
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);
+ /* 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;
+ 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
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);
}
}