[comp.emacs] error check

jimb@POGO.GNU.AI.MIT.EDU (Jim Blandy) (04/17/91)

Hints about examining Lisp stuff from GDB:

Don't, if you can possibly avoid it.  :-)

In order to find out what lisp code you're running, find a frame for
Ffuncall.  It takes two arguments: nargs and args.  args[0] is
probably a symbol that is the name of the function being called.

I'll bet you could call the elisp debugger code from gdb to get lisp
backtraces.  I haven't tried this, though.

You could always learn to read bytecode...

It's very helpful to be able to print lisp objects in their readable
form from gdb.  Here is a routine I added to print.c:

    /* The subroutine object for external-debugging-output is kept here
       for the convenience of the debugger.  */
    Lisp_Object Qexternal_debugging_output;

    DEFUN ("external-debugging-output",
	   Fexternal_debugging_output, Sexternal_debugging_output,
	   1, 1, 0, "Write CHARACTER to stderr.\n\
    You can call print while debugging emacs, and pass it this function\n\
    to make it write to the debugging output.\n")
	(Lisp_Object character)
    {
      CHECK_NUMBER (character, 0);
      putc (XINT (character), stderr);

      return character;
    }

And added these declarations to syms_of_print at the bottom of print.c: 

      defsubr (&Sexternal_debugging_output);

      Qexternal_debugging_output = intern ("external-debugging-output");
      staticpro (&Qexternal_debugging_output);

This defines a new lisp output stream that writes on the standard
error output.  Here is a gdb script that uses
external-debugging-output and provides some other things for picking
apart Lisp_Objects:

    # Set up something to print out s-expressions.
    define pr
    set Fprin1 ($, Qexternal_debugging_output)
    echo \n
    end

    document pr
    Print the emacs s-expression which is $.
    Works only when an inferior emacs is executing.
    end

    # Print the type of the Lisp_Object $.
    define xtype
    print (enum Lisp_Type) (($ >> 24) & 0xff)
    p $$
    end

    # Print the pointer component of the Lisp_Object $.
    define xptr
    print (void *) ($ & 0x00ffffff)
    end

    # Treat the Lisp_Object $ as a window ptr.
    define xwindow
    print (struct window *) ($ & 0x00ffffff)
    end

    # Print the Lisp_Object $ as a symbol ptr, and let $ be the
    # struct Lisp_Symbol *.
    define xsymbol
    print (struct Lisp_Symbol *) ($ & 0x00ffffff)
    print &$->name->data
    print $$
    end

    # Print the Lisp_Object $ as a string.
    define xstring
    print *(struct Lisp_String *) ($ & 0x00ffffff)
    print &$.data
    end

    # Print the Lisp_Object $ as a cons.
    define xcons
    print (struct Lisp_Cons *) ($ & 0x00ffffff)
    print *$
    end

    # Don't let abort actually run, as it will make
    # stdio stop working and therefore break the `pr' command as well.
    b abort

These things work with gdb 3.5.  The C stuff is taken from Emacs 19,
so they might need some twiddling to work on your system.

-JimB
--

-Jim Blandy
jimb@ai.mit.edu