+DEFUN ("buffer-local-value", Fbuffer_local_value,
+ Sbuffer_local_value, 2, 2, 0,
+ doc: /* Return the value of VARIABLE in BUFFER.
+If VARIABLE does not have a buffer-local binding in BUFFER, the value
+is the default binding of variable. */)
+ (symbol, buffer)
+ register Lisp_Object symbol;
+ register Lisp_Object buffer;
+{
+ register struct buffer *buf;
+ register Lisp_Object result;
+
+ CHECK_SYMBOL (symbol);
+ CHECK_BUFFER (buffer);
+ buf = XBUFFER (buffer);
+
+ /* Look in local_var_list */
+ result = Fassoc (symbol, buf->local_var_alist);
+ if (NILP (result))
+ {
+ int offset, idx;
+ int found = 0;
+
+ /* Look in special slots */
+ for (offset = PER_BUFFER_VAR_OFFSET (name);
+ offset < sizeof (struct buffer);
+ /* sizeof EMACS_INT == sizeof Lisp_Object */
+ offset += (sizeof (EMACS_INT)))
+ {
+ idx = PER_BUFFER_IDX (offset);
+ if ((idx == -1 || PER_BUFFER_VALUE_P (buf, idx))
+ && SYMBOLP (PER_BUFFER_SYMBOL (offset))
+ && EQ (PER_BUFFER_SYMBOL (offset), symbol))
+ {
+ result = PER_BUFFER_VALUE (buf, offset);
+ found = 1;
+ break;
+ }
+ }
+
+ if (!found)
+ result = Fdefault_value (symbol);
+ }
+ else
+ {
+ Lisp_Object valcontents;
+ Lisp_Object current_alist_element;
+
+ /* What binding is loaded right now? */
+ valcontents = SYMBOL_VALUE (symbol);
+ current_alist_element
+ = XCAR (XBUFFER_LOCAL_VALUE (valcontents)->cdr);
+
+ /* The value of the currently loaded binding is not
+ stored in it, but rather in the realvalue slot.
+ Store that value into the binding it belongs to
+ in case that is the one we are about to use. */
+
+ Fsetcdr (current_alist_element,
+ do_symval_forwarding (XBUFFER_LOCAL_VALUE (valcontents)->realvalue));
+
+ /* Now get the (perhaps updated) value out of the binding. */
+ result = XCDR (result);
+ }
+
+ if (EQ (result, Qunbound))
+ return Fsignal (Qvoid_variable, Fcons (symbol, Qnil));
+
+ return result;
+}
+