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 (BASE_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;

	  default: break;
	  }
      }
  }

  /* Restore values from specpdl to original place.  */
  backtrace_eval_unrewind (-distance);

  return result;
}