Index: eval.c
===================================================================
RCS file: /sources/emacs/emacs/src/eval.c,v
retrieving revision 1.310
diff -u -b -r1.310 eval.c
--- eval.c	24 Mar 2009 16:37:25 -0000	1.310
+++ eval.c	12 Jun 2009 21:25:13 -0000
@@ -31,6 +31,8 @@
 #include "xterm.h"
 #endif
 
+#include <stdio.h>		/* For fprintf.  */
+
 /* This definition is duplicated in alloc.c and keyboard.c */
 /* Putting it in lisp.h makes cc bomb out! */
 
@@ -3295,6 +3297,7 @@
   valcontents = SYMBOL_VALUE (symbol);
   if (!MISCP (valcontents) && !SYMBOL_CONSTANT_P (symbol))
     {
+      /* Case 1 */
       specpdl_ptr->symbol = symbol;
       specpdl_ptr->old_value = valcontents;
       specpdl_ptr->func = NULL;
@@ -3304,7 +3307,7 @@
   else
     {
       Lisp_Object ovalue = find_symbol_value (symbol);
-      specpdl_ptr->func = 0;
+      specpdl_ptr->func = 0; /* Fix-me: Are NULL === 0? */
       specpdl_ptr->old_value = ovalue;
 
       valcontents = XSYMBOL (symbol)->value;
@@ -3319,11 +3322,14 @@
 	  /* For a local variable, record both the symbol and which
 	     buffer's or frame's value we are saving.  */
 	  if (!NILP (Flocal_variable_p (symbol, Qnil)))
+            /* Case 2 */
 	    where = current_buffer;
 	  else if (BUFFER_LOCAL_VALUEP (valcontents)
 		   && XBUFFER_LOCAL_VALUE (valcontents)->found_for_frame)
+            /* Case 3 */
 	    where = XBUFFER_LOCAL_VALUE (valcontents)->frame;
 	  else
+            /* Case 4 */
 	    where = Qnil;
 
 	  /* We're not using the `unused' slot in the specbinding
@@ -3397,6 +3403,7 @@
       this_binding = *--specpdl_ptr;
 
       if (this_binding.func != 0)
+        /* From record_unwind_protect */
 	(*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
@@ -3413,21 +3420,72 @@
 	  where = XCAR (XCDR (this_binding.symbol));
 
 	  if (NILP (where))
+            {
+              /* Case 4 in specbind */
+              /* We should reset default value.  (Note: The default
+                 value is either let bound or global.) */
 	    Fset_default (symbol, this_binding.old_value);
+              //printf ("unbind_to: Fset_default where=nil %s\n", SDATA (SYMBOL_NAME (symbol)));
+            }
 	  else if (BUFFERP (where))
+            {
+              /* Case 2 in specbind */
+              /* We should reset buffer local binding, but only if it
+                 is buffer local now or will be when set. */
+              if (!NILP (Flocal_variable_p (symbol, where)) ||
+                  !NILP (Flocal_variable_if_set_p (symbol, where)))
+                {
 	    set_internal (symbol, this_binding.old_value, XBUFFER (where), 1);
+                  //printf ("unbind_to: set_internal in buffer %s\n", SDATA (SYMBOL_NAME (symbol)));
+                }
+            }
 	  else
+              /* Case 3 in specbind */
+              /* Fix-me: This is the frame local case.  I believe it
+                 is broken, but I do not know if it is worth fixing it
+                 since frame local variable are obsolete, or?
+
+                 Note: I do not understand NULL buf arg here, but I
+                 assume that NULL === 0 here because set_internal
+                 checks for 0 and does things like buf->value. */
 	    set_internal (symbol, this_binding.old_value, NULL, 1);
 	}
       else
 	{
+          /* Case 1 in specbind */
 	  /* 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 (this_binding.symbol)))
+            {
+              /* Fix-me: I do not understand this case.  I assume that
+                 if we are here the variable had no buffer local
+                 binding in specbind so that we should set the default
+                 value.  Can SET_SYMBOL_VALUE be used even if the
+                 variable now have a buffer local value?  Doesn't it
+                 erase a buffer local binding that has been done after
+                 specbind?  Can Fset_default be used in that case?
+                 How can we test if make-variable-buffer-local has
+                 been done? */
 	    SET_SYMBOL_VALUE (this_binding.symbol, this_binding.old_value);
+              //printf ("unbind_to: SET_SYMBOL_VALUE %s\n", SDATA (SYMBOL_NAME (this_binding.symbol)));
+            }
 	  else
+            /* Fix-me: I do not understand why set_internal were used
+               here.  Could the variable have had a buffer local
+               binding in specbind if we are here?  Should not just
+               Fset_default be called here? */
+            if (0) //(NILP (Flocal_variable_p (this_binding.symbol, Qnil)))
+              {
 	    set_internal (this_binding.symbol, this_binding.old_value, 0, 1);
+                //printf ("unbind_to: set_internal 0 %s\n", SDATA (SYMBOL_NAME (this_binding.symbol)));
+              }
+            else
+              {
+                /* Set the default value since we had no buffer local binding before. */
+                Fset_default (this_binding.symbol, this_binding.old_value);
+                //printf ("unbind_to: Fset_default no need %s\n", SDATA (SYMBOL_NAME (this_binding.symbol)));
+              }
 	}
     }
 
