program!) The most common suitable places are inside a @code{progn} or
an implicit @code{progn} (@pxref{Sequencing}).
+ If you don't know exactly where in the source code you want to put
+the debug statement, but you want to display a backtrace when a
+certain message is displayed, you can set @code{debug-on-message} to a
+regular expression matching the desired message.
+
@node Using Debugger
@subsection Using the Debugger
*** Set `debug-on-event' to enter the debugger on events like SIGUSR1.
This can be useful when `inhibit-quit' is set.
+*** Set `debug-on-message' to enter the debugger when a certain
+message is displayed in the echo area. This can be useful when trying
+to work out which code is doing something.
+
** The new function `server-eval-at' allows evaluation of Lisp forms on
named Emacs server instances.
+2012-09-04 Lars Ingebrigtsen <larsi@gnus.org>
+
+ * eval.c (call_debugger): Make the function non-static so that we
+ can call it from set_message.
+
+ * xdisp.c (set_message): Implement the new variable `debug-on-message'.
+ (syms_of_xdisp): Defvar it and `inhibit-debug-on-message'.
+
2012-09-04 Paul Eggert <eggert@cs.ucla.edu>
Give more-useful info on a fatal error (Bug#12328).
extern _Noreturn void verror (const char *, va_list)
ATTRIBUTE_FORMAT_PRINTF (1, 0);
extern Lisp_Object un_autoload (Lisp_Object);
+extern Lisp_Object call_debugger (Lisp_Object arg);
extern void init_eval_once (void);
extern Lisp_Object safe_call (ptrdiff_t, Lisp_Object, ...);
extern Lisp_Object safe_call1 (Lisp_Object, Lisp_Object);
Lisp_Object Qcenter;
static Lisp_Object Qmargin, Qpointer;
static Lisp_Object Qline_height;
+Lisp_Object Qinhibit_debug_on_message;
/* These setters are used only in this file, so they can be private. */
static inline void
return 0;
}
-
/* Set the current message to a substring of S or STRING.
If STRING is a Lisp string, set the message to the first NBYTES
set_message (const char *s, Lisp_Object string,
ptrdiff_t nbytes, int multibyte_p)
{
+ ptrdiff_t count = SPECPDL_INDEX ();
+
message_enable_multibyte
= ((s && multibyte_p)
|| (STRINGP (string) && STRING_MULTIBYTE (string)));
(intptr_t) s, string, nbytes, multibyte_p);
message_buf_print = 0;
help_echo_showing_p = 0;
+
+ if (NILP (Vinhibit_debug_on_message) &&
+ STRINGP (Vdebug_on_message) &&
+ fast_string_match (Vdebug_on_message, string) >= 0) {
+ specbind (Qinhibit_debug_on_message, Qt);
+ call_debugger (Fcons (Qerror, Fcons (string, Qnil)));
+ }
+
+ unbind_to (count, Qnil);
}
Vglyphless_char_display = Fmake_char_table (Qglyphless_char_display, Qnil);
Fset_char_table_extra_slot (Vglyphless_char_display, make_number (0),
Qempty_box);
+
+ DEFVAR_LISP ("debug-on-message", Vdebug_on_message,
+ doc: /* If non-nil, debug if a message matching this regexp is displayed. */);
+ Vdebug_on_message = Qnil;
+
+ DEFVAR_LISP ("inhibit-debug-on-message", Vinhibit_debug_on_message,
+ doc: /* If non-nil, inhibit `debug-on-message' from entering the debugger. */);
+ Vinhibit_debug_on_message = Qnil;
+ DEFSYM(Qinhibit_debug_on_message, "inhibit-debug-on-message");
}