Function: backtrace--locals
backtrace--locals is a function defined in eval.c.
Signature
(backtrace--locals NFRAMES &optional BASE)
Documentation
Return names and values of local variables of a stack frame.
NFRAMES and BASE specify the activation frame to use, as in backtrace-frame.
Source Code
// Defined in /usr/src/emacs/src/eval.c
{
union specbinding *frame = get_backtrace_frame (nframes, base);
union specbinding *prevframe
= get_backtrace_frame (make_fixnum (XFIXNAT (nframes) - 1), base);
ptrdiff_t distance = specpdl_ptr - frame;
Lisp_Object result = Qnil;
eassert (distance >= 0);
if (!backtrace_p (prevframe))
error ("Activation frame not found!");
if (!backtrace_p (frame))
error ("Activation frame not found!");
/* The specpdl entries normally contain the symbol being bound along with its
`old_value', so it can be restored. The new value to which it is bound is
available in one of two places: either in the current value of the
variable (if it hasn't been rebound yet) or in the `old_value' slot of the
next specpdl entry for it.
`backtrace_eval_unrewind' happens to swap the role of `old_value'
and "new value", so we abuse it here, to fetch the new value.
It's ugly (we'd rather not modify global data) and a bit inefficient,
but it does the job for now. */
backtrace_eval_unrewind (distance);
/* Grab values. */
{
union specbinding *tmp = prevframe;
for (; tmp > frame; tmp--)
{
switch (tmp->kind)
{
case SPECPDL_LET:
case SPECPDL_LET_DEFAULT:
case SPECPDL_LET_LOCAL:
{
Lisp_Object sym = specpdl_symbol (tmp);
Lisp_Object val = specpdl_old_value (tmp);
if (EQ (sym, Qinternal_interpreter_environment))
{
Lisp_Object env = val;
for (; CONSP (env); env = XCDR (env))
{
Lisp_Object binding = XCAR (env);
if (CONSP (binding))
result = Fcons (Fcons (XCAR (binding),
XCDR (binding)),
result);
}
}
else
result = Fcons (Fcons (sym, val), result);
}
break;
case SPECPDL_UNWIND:
case SPECPDL_UNWIND_ARRAY:
case SPECPDL_UNWIND_PTR:
case SPECPDL_UNWIND_INT:
case SPECPDL_UNWIND_INTMAX:
case SPECPDL_UNWIND_EXCURSION:
case SPECPDL_UNWIND_VOID:
case SPECPDL_BACKTRACE:
#ifdef HAVE_MODULES
case SPECPDL_MODULE_RUNTIME:
case SPECPDL_MODULE_ENVIRONMENT:
#endif
break;
default:
emacs_abort ();
}
}
}
/* Restore values from specpdl to original place. */
backtrace_eval_unrewind (-distance);
return result;
}