* doc/lispref/variables.texi (Intro to Buffer-Local): Fix typo
in documentation.
* src/data.c (KBOARD_OBJFWDP): Move to lisp.h.
(kboard_for_bindings): New variable.
(do_symval_forwarding, store_symval_forwarding): Call
kboard_for_bindings rather than retrieving this value directly.
(set_default_internal): New argument WHERE; if valcontents be a
Lisp_Kboard_Objfwd and WHERE be specified, save the binding
there. All callers changed.
* src/eval.c (specpdl_where): Adjust for changes in structure
layout.
(specpdl_kboard): New function.
(do_specbind): Clear let->where.kbd in ordinary SPECPDL_LETs,
and set it to the kboard where the binding will be installed if
binding keyboard forwards.
(specbind, do_one_unbind, specpdl_unrewind): Provide
specpdl_kboard in invocation of set_default_internal.
* src/keyboard.c (delete_kboard): Clean thread specpdls of
references to kboards.
* src/keyboard.h (KBOARD_OBJFWDP): Move from data.c.
* src/lisp.h (union specbinding) <let.where>: Convert into
union of KBOARD and Lisp_Object.
* src/thread.c (all_threads): Export.
* src/thread.h: Adjust correspondingly.
(cherry picked from commit
64cced2c37a9926fe6ff1c6ad9b9540abd47e21c)
values when you visit the file. @xref{File Variables,,, emacs, The
GNU Emacs Manual}.
- A buffer-local variable cannot be made terminal-local
+ A terminal-local variable cannot be made buffer-local
(@pxref{Multiple Terminals}).
@node Creating Buffer-Local
return XFWDTYPE (a) == Lisp_Fwd_Int;
}
static bool
-KBOARD_OBJFWDP (lispfwd a)
-{
- return XFWDTYPE (a) == Lisp_Fwd_Kboard_Obj;
-}
-static bool
OBJFWDP (lispfwd a)
{
return XFWDTYPE (a) == Lisp_Fwd_Obj;
return object;
}
+/* Return the KBOARD to which bindings currently established and values
+ set should apply. */
+
+KBOARD *
+kboard_for_bindings (void)
+{
+ /* We used to simply use current_kboard here, but from Lisp code, its
+ value is often unexpected. It seems nicer to allow constructions
+ like this to work as intuitively expected:
+
+ (with-selected-frame frame
+ (define-key local-function-map "\eOP" [f1]))
+
+ On the other hand, this affects the semantics of last-command and
+ real-last-command, and people may rely on that. I took a quick
+ look at the Lisp codebase, and I don't think anything will break.
+ --lorentey */
+
+ return FRAME_KBOARD (SELECTED_FRAME ());
+}
/* Given the raw contents of a symbol value cell,
return the Lisp value of the symbol.
XBUFFER_OBJFWD (valcontents)->offset);
case Lisp_Fwd_Kboard_Obj:
- /* We used to simply use current_kboard here, but from Lisp
- code, its value is often unexpected. It seems nicer to
- allow constructions like this to work as intuitively expected:
-
- (with-selected-frame frame
- (define-key local-function-map "\eOP" [f1]))
-
- On the other hand, this affects the semantics of
- last-command and real-last-command, and people may rely on
- that. I took a quick look at the Lisp codebase, and I
- don't think anything will break. --lorentey */
- return *(Lisp_Object *)(XKBOARD_OBJFWD (valcontents)->offset
- + (char *)FRAME_KBOARD (SELECTED_FRAME ()));
+ return *(Lisp_Object *) (XKBOARD_OBJFWD (valcontents)->offset
+ + (char *) kboard_for_bindings ());
default: emacs_abort ();
}
}
case Lisp_Fwd_Kboard_Obj:
{
- char *base = (char *) FRAME_KBOARD (SELECTED_FRAME ());
+ char *base = (char *) kboard_for_bindings ();
char *p = base + XKBOARD_OBJFWD (valcontents)->offset;
*(Lisp_Object *) p = newval;
}
&& !PER_BUFFER_VALUE_P (buf, idx))
{
if (let_shadows_buffer_binding_p (sym))
- set_default_internal (symbol, newval, bindflag);
+ set_default_internal (symbol, newval, bindflag,
+ NULL);
else
SET_PER_BUFFER_VALUE_P (buf, idx, 1);
}
void
set_default_internal (Lisp_Object symbol, Lisp_Object value,
- enum Set_Internal_Bind bindflag)
+ enum Set_Internal_Bind bindflag, KBOARD *where)
{
CHECK_SYMBOL (symbol);
struct Lisp_Symbol *sym = XSYMBOL (symbol);
}
}
}
+ else if (KBOARD_OBJFWDP (valcontents))
+ {
+ char *base = (char *) (where ? where
+ : kboard_for_bindings ());
+ char *p = base + XKBOARD_OBJFWD (valcontents)->offset;
+ *(Lisp_Object *) p = value;
+ }
else
set_internal (symbol, value, Qnil, bindflag);
return;
for this variable. */)
(Lisp_Object symbol, Lisp_Object value)
{
- set_default_internal (symbol, value, SET_INTERNAL_SET);
+ set_default_internal (symbol, value, SET_INTERNAL_SET, NULL);
return value;
}
\f
specpdl_where (union specbinding *pdl)
{
eassert (pdl->kind > SPECPDL_LET);
- return pdl->let.where;
+ return pdl->let.where.buf;
+}
+
+static KBOARD *
+specpdl_kboard (union specbinding *pdl)
+{
+ eassert (pdl->kind == SPECPDL_LET);
+ return pdl->let.where.kbd;
}
static Lisp_Object
if (BUFFER_OBJFWDP (SYMBOL_FWD (sym))
&& specpdl_kind (bind) == SPECPDL_LET_DEFAULT)
{
- set_default_internal (specpdl_symbol (bind), value, bindflag);
+ set_default_internal (specpdl_symbol (bind), value, bindflag,
+ NULL);
return;
}
FALLTHROUGH;
specpdl_ptr->let.kind = SPECPDL_LET;
specpdl_ptr->let.symbol = symbol;
specpdl_ptr->let.old_value = SYMBOL_VAL (sym);
+ specpdl_ptr->let.where.kbd = NULL;
break;
case SYMBOL_LOCALIZED:
case SYMBOL_FORWARDED:
specpdl_ptr->let.kind = SPECPDL_LET_LOCAL;
specpdl_ptr->let.symbol = symbol;
specpdl_ptr->let.old_value = ovalue;
- specpdl_ptr->let.where = Fcurrent_buffer ();
+ specpdl_ptr->let.where.buf = Fcurrent_buffer ();
eassert (sym->u.s.redirect != SYMBOL_LOCALIZED
|| (BASE_EQ (SYMBOL_BLV (sym)->where, Fcurrent_buffer ())));
if (NILP (Flocal_variable_p (symbol, Qnil)))
specpdl_ptr->let.kind = SPECPDL_LET_DEFAULT;
}
+ else if (KBOARD_OBJFWDP (SYMBOL_FWD (sym)))
+ {
+ specpdl_ptr->let.where.kbd = kboard_for_bindings ();
+ specpdl_ptr->let.kind = SPECPDL_LET;
+ }
else
specpdl_ptr->let.kind = SPECPDL_LET;
do_one_unbind (union specbinding *this_binding, bool unwinding,
enum Set_Internal_Bind bindflag)
{
+ KBOARD *kbdwhere = NULL;
+
eassert (unwinding || this_binding->kind >= SPECPDL_LET);
switch (this_binding->kind)
{
}
}
/* Come here only if make_local_foo was used for the first time
- on this var within this let. */
+ on this var within this let or the symbol is not a plainval. */
+ kbdwhere = specpdl_kboard (this_binding);
FALLTHROUGH;
case SPECPDL_LET_DEFAULT:
set_default_internal (specpdl_symbol (this_binding),
specpdl_old_value (this_binding),
- bindflag);
+ bindflag, kbdwhere);
break;
case SPECPDL_LET_LOCAL:
{
{
union specbinding *tmp = pdl;
int step = -1;
+ KBOARD *kbdwhere;
+
if (distance < 0)
{ /* It's a rewind rather than unwind. */
tmp += distance - 1;
for (; distance > 0; distance--)
{
tmp += step;
+ kbdwhere = NULL;
+
switch (tmp->kind)
{
/* FIXME: Ideally we'd like to "temporarily unwind" (some of) those
}
}
/* Come here only if make_local_foo was used for the first
- time on this var within this let. */
+ time on this var within this let or the symbol is forwarded. */
+ kbdwhere = specpdl_kboard (tmp);
FALLTHROUGH;
case SPECPDL_LET_DEFAULT:
{
Lisp_Object sym = specpdl_symbol (tmp);
Lisp_Object old_value = specpdl_old_value (tmp);
set_specpdl_old_value (tmp, default_value (sym));
- set_default_internal (sym, old_value, SET_INTERNAL_THREAD_SWITCH);
+ set_default_internal (sym, old_value, SET_INTERNAL_THREAD_SWITCH,
+ kbdwhere);
}
break;
case SPECPDL_LET_LOCAL:
delete_kboard (KBOARD *kb)
{
KBOARD **kbp;
+ struct thread_state *thread;
for (kbp = &all_kboards; *kbp != kb; kbp = &(*kbp)->next_kboard)
if (*kbp == NULL)
emacs_abort ();
}
+ /* Clean thread specpdls of references to this KBOARD. */
+ for (thread = all_threads; thread; thread = thread->next_thread)
+ {
+ union specbinding *p;
+
+ for (p = thread->m_specpdl_ptr; p > thread->m_specpdl;)
+ {
+ p -= 1;
+
+ if (p->kind == SPECPDL_LET
+ && p->let.where.kbd == kb)
+ p->let.where.kbd = NULL;
+ }
+ }
+
wipe_kboard (kb);
xfree (kb);
}
When Emacs goes back to the any-kboard state, it looks at all the KBOARDs
to find those; and it tries processing their input right away. */
-typedef struct kboard KBOARD;
struct kboard
{
KBOARD *next_kboard;
eassert (BUFFER_OBJFWDP (a));
return a.fwdptr;
}
+
+INLINE bool
+KBOARD_OBJFWDP (lispfwd a)
+{
+ return XFWDTYPE (a) == Lisp_Fwd_Kboard_Obj;
+}
+
\f
/* Lisp floating point type. */
struct Lisp_Float
#ifdef HAVE_MODULES
SPECPDL_MODULE_RUNTIME, /* A live module runtime. */
SPECPDL_MODULE_ENVIRONMENT, /* A live module environment. */
-#endif
+#endif /* !HAVE_MODULES */
SPECPDL_LET, /* A plain and simple dynamic let-binding. */
/* Tags greater than SPECPDL_LET must be "subkinds" of LET. */
SPECPDL_LET_LOCAL, /* A buffer-local let-binding. */
SPECPDL_LET_DEFAULT /* A global binding for a localized var. */
};
+/* struct kboard is defined in keyboard.h. */
+typedef struct kboard KBOARD;
+
union specbinding
{
/* Aligning similar members consistently might help efficiency slightly
} unwind_void;
struct {
ENUM_BF (specbind_tag) kind : CHAR_BIT;
- /* `where' is not used in the case of SPECPDL_LET. */
- Lisp_Object symbol, old_value, where;
+ /* `where' is not used in the case of SPECPDL_LET,
+ unless the symbol is forwarded to a KBOARD. */
+ Lisp_Object symbol, old_value;
+ union {
+ /* KBOARD object to which SYMBOL forwards, in the case of
+ SPECPDL_LET. */
+ KBOARD *kbd;
+
+ /* Buffer otherwise. */
+ Lisp_Object buf;
+ } where;
} let;
struct {
ENUM_BF (specbind_tag) kind : CHAR_BIT;
extern AVOID args_out_of_range (Lisp_Object, Lisp_Object);
extern AVOID circular_list (Lisp_Object);
+extern KBOARD *kboard_for_bindings (void);
extern Lisp_Object do_symval_forwarding (lispfwd);
-enum Set_Internal_Bind {
- SET_INTERNAL_SET,
- SET_INTERNAL_BIND,
- SET_INTERNAL_UNBIND,
- SET_INTERNAL_THREAD_SWITCH
-};
+enum Set_Internal_Bind
+ {
+ SET_INTERNAL_SET,
+ SET_INTERNAL_BIND,
+ SET_INTERNAL_UNBIND,
+ SET_INTERNAL_THREAD_SWITCH,
+ };
extern void set_internal (Lisp_Object, Lisp_Object, Lisp_Object,
enum Set_Internal_Bind);
extern void set_default_internal (Lisp_Object, Lisp_Object,
- enum Set_Internal_Bind bindflag);
+ enum Set_Internal_Bind, KBOARD *);
extern Lisp_Object expt_integer (Lisp_Object, Lisp_Object);
extern void syms_of_data (void);
extern void swap_in_global_binding (struct Lisp_Symbol *);
struct thread_state *current_thread = &main_thread.s;
-static struct thread_state *all_threads = &main_thread.s;
+struct thread_state *all_threads = &main_thread.s;
static sys_mutex_t global_lock;
}
extern struct thread_state *current_thread;
+extern struct thread_state *all_threads;
extern void finalize_one_thread (struct thread_state *state);
extern void finalize_one_mutex (struct Lisp_Mutex *);