changeset 38276:93bcc7200a67

(specbind): If SYMBOL has a frame-local binding, record the frame on the binding stack. Change format of entries for local bindings on the binding stack to '(SYMBOL . WHERE)'. (unbind_to): Handle unbinding a frame-local variable.
author Gerd Moellmann <gerd@gnu.org>
date Tue, 03 Jul 2001 15:30:06 +0000
parents 7ea4cdf2b1dc
children b4dc62568f31
files src/eval.c
diffstat 1 files changed, 37 insertions(+), 29 deletions(-) [+]
line wrap: on
line diff
--- a/src/eval.c	Tue Jul 03 15:28:40 2001 +0000
+++ b/src/eval.c	Tue Jul 03 15:30:06 2001 +0000
@@ -2923,35 +2923,42 @@
     }
   else
     {
+      Lisp_Object valcontents;
+      
       ovalue = find_symbol_value (symbol);
       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))
+      valcontents = XSYMBOL (symbol)->value;
+
+      if (BUFFER_LOCAL_VALUEP (valcontents)
+	  || SOME_BUFFER_LOCAL_VALUEP (valcontents)
+	  || BUFFER_OBJFWDP (valcontents))
 	{
-	  Lisp_Object current_buffer, binding_buffer;
+	  Lisp_Object where;
 	  
 	  /* 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));
+	     buffer's or frame's value we are saving.  */
+	  if (!NILP (Flocal_variable_p (symbol, Qnil)))
+	    where = Fcurrent_buffer ();
+	  else if (!BUFFER_OBJFWDP (valcontents)
+		   && XBUFFER_LOCAL_VALUE (valcontents)->found_for_frame)
+	    where = XBUFFER_LOCAL_VALUE (valcontents)->frame;
+	  else
+	    where = Qnil;
+
+	  /* We're not using the `unused' slot in the specbinding
+	     structure because this would mean we have to do more
+	     work for simple variables.  */
+	  specpdl_ptr->symbol = Fcons (symbol, where);
 
 	  /* If SYMBOL is a per-buffer variable which doesn't have a
 	     buffer-local value here, make the `let' change the global
 	     value by changing the value of SYMBOL in all buffers not
 	     having their own value.  This is consistent with what
 	     happens with other buffer-local variables.  */
-	  if (NILP (binding_buffer)
-	      && BUFFER_OBJFWDP (XSYMBOL (symbol)->value))
+	  if (NILP (where)
+	      && BUFFER_OBJFWDP (valcontents))
 	    {
 	      ++specpdl_ptr;
 	      Fset_default (symbol, value);
@@ -2996,30 +3003,31 @@
   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.  BINDING_BUFFER nil means that the
-	 variable had the default value when it was bound.  */
+      /* If the symbol is a list, it is really (SYMBOL . WHERE) where
+	 WHERE is either nil, a buffer, or a frame.  If WHERE is a
+	 buffer or frame, this indicates we bound a variable that had
+	 a buffer-local or frmae-local binding..  WHERE nil means that
+	 the variable had the default value when it was bound.  */
       else if (CONSP (specpdl_ptr->symbol))
 	{
-	  Lisp_Object symbol, buffer;
+	  Lisp_Object symbol, where;
 
 	  symbol = XCAR (specpdl_ptr->symbol);
-	  buffer = XCAR (XCDR (specpdl_ptr->symbol));
-
-	  /* Handle restoring a default value.  */
-	  if (NILP (buffer))
+	  where = XCDR (specpdl_ptr->symbol);
+
+	  if (NILP (where))
 	    Fset_default (symbol, specpdl_ptr->old_value);
-	  /* Handle restoring a value saved from a live buffer.  */
-	  else
-	    set_internal (symbol, specpdl_ptr->old_value, XBUFFER (buffer), 1);
+	  else if (BUFFERP (where))
+	    set_internal (symbol, specpdl_ptr->old_value, XBUFFER (where), 1);
+	  else 
+	    set_internal (symbol, specpdl_ptr->old_value, NULL, 1);
 	}
       else
 	{