(Fmap_charset_chars): Fix docstring.
[bpt/emacs.git] / lisp / emacs-lisp / debug.el
CommitLineData
c0274f38
ER
1;;; debug.el --- debuggers and related commands for Emacs
2
14769773 3;; Copyright (C) 1985, 1986, 1994 Free Software Foundation, Inc.
9750e079 4
e5167999 5;; Maintainer: FSF
e9571d2a 6;; Keywords: lisp, tools, maint
e5167999 7
0231f2dc
JB
8;; This file is part of GNU Emacs.
9
10;; GNU Emacs is free software; you can redistribute it and/or modify
11;; it under the terms of the GNU General Public License as published by
e5167999 12;; the Free Software Foundation; either version 2, or (at your option)
0231f2dc
JB
13;; any later version.
14
15;; GNU Emacs is distributed in the hope that it will be useful,
16;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18;; GNU General Public License for more details.
19
20;; You should have received a copy of the GNU General Public License
b578f267
EN
21;; along with GNU Emacs; see the file COPYING. If not, write to the
22;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23;; Boston, MA 02111-1307, USA.
0231f2dc 24
e41b2db1
ER
25;;; Commentary:
26
27;; This is a major mode documented in the Emacs manual.
28
e5167999 29;;; Code:
0231f2dc 30
666b9413
SE
31(defgroup debugger nil
32 "Debuggers and related commands for Emacs."
33 :prefix "debugger-"
34 :group 'debug)
8c1cd093 35
666b9413
SE
36(defcustom debugger-mode-hook nil
37 "*Hooks run when `debugger-mode' is turned on."
38 :type 'hook
cd32a7ba
DN
39 :group 'debugger
40 :version "20.3")
8c1cd093 41
63ca439e
GM
42(defcustom debugger-batch-max-lines 40
43 "*Maximum lines to show in debugger buffer in a noninteractive Emacs.
44When the debugger is entered and Emacs is running in batch mode,
45if the backtrace text has more than this many lines,
46the middle is discarded, and just the beginning and end are displayed."
47 :type 'integer
48 :group 'debugger
49 :version "21.1")
0231f2dc 50
666b9413
SE
51(defcustom debug-function-list nil
52 "List of functions currently set for debug on entry."
53 :type '(repeat function)
54 :group 'debugger)
55
56(defcustom debugger-step-after-exit nil
57 "Non-nil means \"single-step\" after the debugger exits."
58 :type 'boolean
59 :group 'debugger)
2eeeb0d2
RS
60
61(defvar debugger-value nil
62 "This is the value for the debugger to return, when it returns.")
63
64(defvar debugger-old-buffer nil
65 "This is the buffer that was current when the debugger was entered.")
66
25c58854
RS
67(defvar debugger-previous-backtrace nil
68 "The contents of the previous backtrace (including text properties).
69This is to optimize `debugger-make-xrefs'.")
70
cf1c8cd9 71(defvar debugger-outer-match-data)
80ddb8ed
RS
72(defvar debugger-outer-load-read-function)
73(defvar debugger-outer-overriding-local-map)
29e2b496 74(defvar debugger-outer-overriding-terminal-local-map)
35cf010d
RS
75(defvar debugger-outer-track-mouse)
76(defvar debugger-outer-last-command)
77(defvar debugger-outer-this-command)
78(defvar debugger-outer-unread-command-char)
79(defvar debugger-outer-unread-command-events)
0359db82 80(defvar debugger-outer-unread-post-input-method-events)
35cf010d
RS
81(defvar debugger-outer-last-input-event)
82(defvar debugger-outer-last-command-event)
83(defvar debugger-outer-last-nonmenu-event)
84(defvar debugger-outer-last-event-frame)
85(defvar debugger-outer-standard-input)
86(defvar debugger-outer-standard-output)
bf90c2c0 87(defvar debugger-outer-inhibit-redisplay)
35cf010d
RS
88(defvar debugger-outer-cursor-in-echo-area)
89
0231f2dc
JB
90;;;###autoload
91(setq debugger 'debug)
92;;;###autoload
93(defun debug (&rest debugger-args)
2512acba 94 "Enter debugger. To return, type \\<debugger-mode-map>`\\[debugger-continue]'.
0231f2dc
JB
95Arguments are mainly for use when this is called from the internals
96of the evaluator.
97
98You may call with no args, or you may pass nil as the first arg and
99any other args you like. In that case, the list of args after the
100first will be printed into the backtrace buffer."
73e78cf1 101 (interactive)
63ca439e
GM
102 (unless noninteractive
103 (message "Entering debugger..."))
0231f2dc 104 (let (debugger-value
0231f2dc
JB
105 (debug-on-error nil)
106 (debug-on-quit nil)
107 (debugger-buffer (let ((default-major-mode 'fundamental-mode))
36363ac1 108 (get-buffer-create "*Backtrace*")))
0231f2dc
JB
109 (debugger-old-buffer (current-buffer))
110 (debugger-step-after-exit nil)
111 ;; Don't keep reading from an executing kbd macro!
efcf38c7 112 (executing-kbd-macro nil)
35cf010d
RS
113 ;; Save the outer values of these vars for the `e' command
114 ;; before we replace the values.
cf1c8cd9 115 (debugger-outer-match-data (match-data))
80ddb8ed
RS
116 (debugger-outer-load-read-function load-read-function)
117 (debugger-outer-overriding-local-map overriding-local-map)
29e2b496
RS
118 (debugger-outer-overriding-terminal-local-map
119 overriding-terminal-local-map)
35cf010d
RS
120 (debugger-outer-track-mouse track-mouse)
121 (debugger-outer-last-command last-command)
122 (debugger-outer-this-command this-command)
123 (debugger-outer-unread-command-char unread-command-char)
124 (debugger-outer-unread-command-events unread-command-events)
0359db82
KH
125 (debugger-outer-unread-post-input-method-events
126 unread-post-input-method-events)
35cf010d
RS
127 (debugger-outer-last-input-event last-input-event)
128 (debugger-outer-last-command-event last-command-event)
129 (debugger-outer-last-nonmenu-event last-nonmenu-event)
130 (debugger-outer-last-event-frame last-event-frame)
131 (debugger-outer-standard-input standard-input)
132 (debugger-outer-standard-output standard-output)
bf90c2c0 133 (debugger-outer-inhibit-redisplay inhibit-redisplay)
35cf010d 134 (debugger-outer-cursor-in-echo-area cursor-in-echo-area))
9d07cf38
RS
135 ;; Set this instead of binding it, so that `q'
136 ;; will not restore it.
6c2599ed 137 (setq overriding-terminal-local-map nil)
35cf010d
RS
138 ;; Don't let these magic variables affect the debugger itself.
139 (let ((last-command nil) this-command track-mouse
b2ecc630 140 (unread-command-char -1) unread-command-events
0359db82 141 unread-post-input-method-events
35cf010d
RS
142 last-input-event last-command-event last-nonmenu-event
143 last-event-frame
80ddb8ed
RS
144 overriding-local-map
145 load-read-function
c7387861
RS
146 ;; If we are inside a minibuffer, allow nesting
147 ;; so that we don't get an error from the `e' command.
f0ee2336
AS
148 (enable-recursive-minibuffers
149 (or enable-recursive-minibuffers (> (minibuffer-depth) 0)))
35cf010d 150 (standard-input t) (standard-output t)
bf90c2c0 151 inhibit-redisplay
35cf010d
RS
152 (cursor-in-echo-area nil))
153 (unwind-protect
154 (save-excursion
155 (save-window-excursion
156 (pop-to-buffer debugger-buffer)
35cf010d 157 (debugger-mode)
63ca439e
GM
158 (debugger-setup-buffer debugger-args)
159 (when noninteractive
160 ;; If the backtrace is long, save the beginning
161 ;; and the end, but discard the middle.
162 (when (> (count-lines (point-min) (point-max))
163 debugger-batch-max-lines)
164 (goto-char (point-min))
165 (forward-line (/ 2 debugger-batch-max-lines))
166 (let ((middlestart (point)))
167 (goto-char (point-max))
168 (forward-line (- (/ 2 debugger-batch-max-lines)
169 debugger-batch-max-lines))
170 (delete-region middlestart (point)))
171 (insert "...\n"))
172 (goto-char (point-min))
173 (message (buffer-string))
174 (kill-emacs))
175 (if (eq (car debugger-args) 'debug)
176 ;; Skip the frames for backtrace-debug, byte-code, and debug.
177 (backtrace-debug 3 t))
35cf010d 178 (debugger-reenable)
0231f2dc 179 (message "")
35cf010d
RS
180 (let ((inhibit-trace t)
181 (standard-output nil)
182 (buffer-read-only t))
183 (message "")
614710af
RS
184 ;; Make sure we unbind buffer-read-only in the right buffer.
185 (save-excursion
186 (recursive-edit)))))
36363ac1
KH
187 ;; Kill or at least neuter the backtrace buffer, so that users
188 ;; don't try to execute debugger commands in an invalid context.
189 (if (get-buffer-window debugger-buffer 'visible)
190 ;; Still visible despite the save-window-excursion? Maybe it
191 ;; it's in a pop-up frame. It would be annoying to delete and
192 ;; recreate it every time the debugger stops, so instead we'll
193 ;; erase it but leave it visible.
194 (save-excursion
195 (set-buffer debugger-buffer)
196 (erase-buffer)
197 (fundamental-mode))
198 (kill-buffer debugger-buffer))
17b3e87b 199 (set-match-data debugger-outer-match-data)))
35cf010d
RS
200 ;; Put into effect the modified values of these variables
201 ;; in case the user set them with the `e' command.
80ddb8ed
RS
202 (setq load-read-function debugger-outer-load-read-function)
203 (setq overriding-local-map debugger-outer-overriding-local-map)
29e2b496
RS
204 (setq overriding-terminal-local-map
205 debugger-outer-overriding-terminal-local-map)
35cf010d
RS
206 (setq track-mouse debugger-outer-track-mouse)
207 (setq last-command debugger-outer-last-command)
208 (setq this-command debugger-outer-this-command)
209 (setq unread-command-char debugger-outer-unread-command-char)
210 (setq unread-command-events debugger-outer-unread-command-events)
0359db82
KH
211 (setq unread-post-input-method-events
212 debugger-outer-unread-post-input-method-events)
35cf010d
RS
213 (setq last-input-event debugger-outer-last-input-event)
214 (setq last-command-event debugger-outer-last-command-event)
215 (setq last-nonmenu-event debugger-outer-last-nonmenu-event)
216 (setq last-event-frame debugger-outer-last-event-frame)
217 (setq standard-input debugger-outer-standard-input)
218 (setq standard-output debugger-outer-standard-output)
bf90c2c0 219 (setq inhibit-redisplay debugger-outer-inhibit-redisplay)
14769773 220 (setq cursor-in-echo-area debugger-outer-cursor-in-echo-area)
0231f2dc
JB
221 (setq debug-on-next-call debugger-step-after-exit)
222 debugger-value))
223\f
63ca439e
GM
224(defun debugger-setup-buffer (debugger-args)
225 "Initialize the `*Backtrace*' buffer for entry to the debugger.
226That buffer should be current already."
227 (setq buffer-read-only nil)
228 (erase-buffer)
229 (set-buffer-multibyte nil)
230 (let ((standard-output (current-buffer))
231 (print-escape-newlines t)
232 (print-level 8)
233 (print-length 50))
234 (backtrace))
235 (goto-char (point-min))
236 (delete-region (point)
237 (progn
238 (search-forward "\n debug(")
239 (forward-line 1)
240 (point)))
241 (insert "Debugger entered")
242 ;; lambda is for debug-on-call when a function call is next.
243 ;; debug is for debug-on-entry function called.
244 (cond ((memq (car debugger-args) '(lambda debug))
245 (insert "--entering a function:\n")
246 (if (eq (car debugger-args) 'debug)
247 (progn
248 (delete-char 1)
249 (insert ?*)
250 (beginning-of-line))))
251 ;; Exiting a function.
252 ((eq (car debugger-args) 'exit)
253 (insert "--returning value: ")
254 (setq debugger-value (nth 1 debugger-args))
255 (prin1 debugger-value (current-buffer))
256 (insert ?\n)
257 (delete-char 1)
258 (insert ? )
259 (beginning-of-line))
260 ;; Debugger entered for an error.
261 ((eq (car debugger-args) 'error)
262 (insert "--Lisp error: ")
263 (prin1 (nth 1 debugger-args) (current-buffer))
264 (insert ?\n))
265 ;; debug-on-call, when the next thing is an eval.
266 ((eq (car debugger-args) t)
267 (insert "--beginning evaluation of function call form:\n"))
268 ;; User calls debug directly.
269 (t
270 (insert ": ")
271 (prin1 (if (eq (car debugger-args) 'nil)
272 (cdr debugger-args) debugger-args)
273 (current-buffer))
cc1bde62 274 (insert ?\n)))
27bde5f0
RS
275 ;; After any frame that uses eval-buffer,
276 ;; insert a line that states the buffer position it's reading at.
277 (save-excursion
278 (while (re-search-forward "^ eval-buffer(" nil t)
279 (end-of-line)
280 (insert (format "\n ;;; Reading at buffer position %d"
281 (with-current-buffer (nth 2 (backtrace-frame (debugger-frame-number)))
65fe45f2 282 (point))))))
cc1bde62
SS
283 (debugger-make-xrefs))
284
285(defun debugger-make-xrefs (&optional buffer)
25c58854 286 "Attach cross-references to symbol names in the `*Backtrace*' buffer."
cc1bde62
SS
287 (interactive "b")
288 (save-excursion
289 (set-buffer (or buffer (current-buffer)))
25c58854
RS
290 (setq buffer (current-buffer))
291 (let ((buffer-read-only nil)
292 (old-end 1) (new-end 1))
293 ;; If we saved an old backtrace, find the common part
294 ;; between the new and the old.
295 ;; Compare line by line, starting from the end,
296 ;; because that's the part that is likely to be unchanged.
297 (if debugger-previous-backtrace
298 (let (old-start new-start (all-match t))
299 (goto-char (point-max))
300 (with-temp-buffer
301 (insert debugger-previous-backtrace)
302 (while (and all-match (not (bobp)))
303 (setq old-end (point))
304 (forward-line -1)
305 (setq old-start (point))
306 (with-current-buffer buffer
307 (setq new-end (point))
308 (forward-line -1)
309 (setq new-start (point)))
310 (if (not (zerop
311 (compare-buffer-substrings
312 (current-buffer) old-start old-end
313 buffer new-start new-end)))
314 (setq all-match nil))))
315 ;; Now new-end is the position of the start of the
316 ;; unchanged part in the current buffer, and old-end is
317 ;; the position of that same text in the saved old
318 ;; backtrace. But we must subtract 1 since strings are
319 ;; indexed in origin 0.
320
321 ;; Replace the unchanged part of the backtrace
322 ;; with the text from debugger-previous-backtrace,
323 ;; since that already has the proper xrefs.
324 ;; With this optimization, we only need to scan
325 ;; the changed part of the backtrace.
326 (delete-region new-end (point-max))
327 (goto-char (point-max))
328 (insert (substring debugger-previous-backtrace (1- old-end)))
329 ;; Make the unchanged part of the backtrace inaccessible
330 ;; so it won't be scanned.
331 (narrow-to-region (point-min) new-end)))
332
333 ;; Scan the new part of the backtrace, inserting xrefs.
334 (goto-char (point-min))
335 (while (progn
336 (skip-syntax-forward "^w_")
337 (not (eobp)))
338 (let* ((beg (point))
339 (end (progn (skip-syntax-forward "w_") (point)))
340 (sym (intern-soft (buffer-substring-no-properties
341 beg end)))
342 (file (and sym (symbol-file sym))))
25c58854
RS
343 (when file
344 (goto-char beg)
345 ;; help-xref-button needs to operate on something matched
346 ;; by a regexp, so set that up for it.
347 (re-search-forward "\\(\\(\\sw\\|\\s_\\)+\\)")
f27b0335
RS
348 (help-xref-button 1 'help-function-def sym file)))
349 (forward-line 1))
25c58854
RS
350 (widen))
351 (setq debugger-previous-backtrace (buffer-string))))
63ca439e 352\f
0231f2dc
JB
353(defun debugger-step-through ()
354 "Proceed, stepping through subexpressions of this expression.
355Enter another debugger on next entry to eval, apply or funcall."
356 (interactive)
357 (setq debugger-step-after-exit t)
358 (message "Proceeding, will debug on next eval or call.")
359 (exit-recursive-edit))
360
361(defun debugger-continue ()
362 "Continue, evaluating this expression without stopping."
363 (interactive)
094e0928
GM
364 (unless debugger-may-continue
365 (error "Cannot continue"))
0231f2dc
JB
366 (message "Continuing.")
367 (exit-recursive-edit))
368
369(defun debugger-return-value (val)
370 "Continue, specifying value to return.
371This is only useful when the value returned from the debugger
372will be used, such as in a debug on exit from a frame."
373 (interactive "XReturn value (evaluated): ")
374 (setq debugger-value val)
375 (princ "Returning " t)
376 (prin1 debugger-value)
377 (exit-recursive-edit))
378
379(defun debugger-jump ()
380 "Continue to exit from this frame, with all debug-on-entry suspended."
381 (interactive)
27bde5f0 382 (debugger-frame)
0231f2dc
JB
383 ;; Turn off all debug-on-entry functions
384 ;; but leave them in the list.
385 (let ((list debug-function-list))
386 (while list
387 (fset (car list)
388 (debug-on-entry-1 (car list) (symbol-function (car list)) nil))
389 (setq list (cdr list))))
390 (message "Continuing through this frame")
391 (exit-recursive-edit))
392
393(defun debugger-reenable ()
394 "Turn all debug-on-entry functions back on."
395 (let ((list debug-function-list))
396 (while list
397 (or (consp (symbol-function (car list)))
398 (debug-convert-byte-code (car list)))
399 (fset (car list)
400 (debug-on-entry-1 (car list) (symbol-function (car list)) t))
401 (setq list (cdr list)))))
402
403(defun debugger-frame-number ()
404 "Return number of frames in backtrace before the one point points at."
405 (save-excursion
406 (beginning-of-line)
407 (let ((opoint (point))
408 (count 0))
27bde5f0
RS
409 (while (not (eq (cadr (backtrace-frame count)) 'debug))
410 (setq count (1+ count)))
0231f2dc
JB
411 (goto-char (point-min))
412 (if (or (equal (buffer-substring (point) (+ (point) 6))
413 "Signal")
414 (equal (buffer-substring (point) (+ (point) 6))
415 "Return"))
416 (progn
417 (search-forward ":")
418 (forward-sexp 1)))
419 (forward-line 1)
420 (while (progn
421 (forward-char 2)
422 (if (= (following-char) ?\()
423 (forward-sexp 1)
424 (forward-sexp 2))
425 (forward-line 1)
426 (<= (point) opoint))
65fe45f2
RS
427 (if (looking-at " *;;;")
428 (forward-line 1))
0231f2dc
JB
429 (setq count (1+ count)))
430 count)))
431
0231f2dc
JB
432(defun debugger-frame ()
433 "Request entry to debugger when this frame exits.
434Applies to the frame whose line point is on in the backtrace."
435 (interactive)
fa5b1b57
RS
436 (save-excursion
437 (beginning-of-line)
438 (if (looking-at " *;;;\\|[a-z]")
439 (error "This line is not a function call")))
0231f2dc 440 (beginning-of-line)
27bde5f0 441 (backtrace-debug (debugger-frame-number) t)
0231f2dc
JB
442 (if (= (following-char) ? )
443 (let ((buffer-read-only nil))
444 (delete-char 1)
445 (insert ?*)))
446 (beginning-of-line))
447
448(defun debugger-frame-clear ()
c519f68f 449 "Do not enter debugger when this frame exits.
0231f2dc
JB
450Applies to the frame whose line point is on in the backtrace."
451 (interactive)
fa5b1b57
RS
452 (save-excursion
453 (beginning-of-line)
454 (if (looking-at " *;;;\\|[a-z]")
455 (error "This line is not a function call")))
0231f2dc 456 (beginning-of-line)
27bde5f0 457 (backtrace-debug (debugger-frame-number) nil)
0231f2dc
JB
458 (if (= (following-char) ?*)
459 (let ((buffer-read-only nil))
460 (delete-char 1)
461 (insert ? )))
462 (beginning-of-line))
463
8c1cd093
KH
464
465
466(put 'debugger-env-macro 'lisp-indent-function 0)
467(defmacro debugger-env-macro (&rest body)
468 "Run BODY in original environment."
6c2599ed
SS
469 `(save-excursion
470 (if (null (buffer-name debugger-old-buffer))
471 ;; old buffer deleted
472 (setq debugger-old-buffer (current-buffer)))
473 (set-buffer debugger-old-buffer)
474 (let ((load-read-function debugger-outer-load-read-function)
475 (overriding-terminal-local-map
476 debugger-outer-overriding-terminal-local-map)
477 (overriding-local-map debugger-outer-overriding-local-map)
478 (track-mouse debugger-outer-track-mouse)
479 (last-command debugger-outer-last-command)
480 (this-command debugger-outer-this-command)
481 (unread-command-char debugger-outer-unread-command-char)
482 (unread-command-events debugger-outer-unread-command-events)
483 (unread-post-input-method-events
484 debugger-outer-unread-post-input-method-events)
485 (last-input-event debugger-outer-last-input-event)
486 (last-command-event debugger-outer-last-command-event)
487 (last-nonmenu-event debugger-outer-last-nonmenu-event)
488 (last-event-frame debugger-outer-last-event-frame)
489 (standard-input debugger-outer-standard-input)
490 (standard-output debugger-outer-standard-output)
491 (inhibit-redisplay debugger-outer-inhibit-redisplay)
492 (cursor-in-echo-area debugger-outer-cursor-in-echo-area))
493 (set-match-data debugger-outer-match-data)
494 (prog1 (progn ,@body)
495 (setq debugger-outer-match-data (match-data))
496 (setq debugger-outer-load-read-function load-read-function)
497 (setq debugger-outer-overriding-terminal-local-map
498 overriding-terminal-local-map)
499 (setq debugger-outer-overriding-local-map overriding-local-map)
500 (setq debugger-outer-track-mouse track-mouse)
501 (setq debugger-outer-last-command last-command)
502 (setq debugger-outer-this-command this-command)
503 (setq debugger-outer-unread-command-char unread-command-char)
504 (setq debugger-outer-unread-command-events unread-command-events)
505 (setq debugger-outer-unread-post-input-method-events
506 unread-post-input-method-events)
507 (setq debugger-outer-last-input-event last-input-event)
508 (setq debugger-outer-last-command-event last-command-event)
509 (setq debugger-outer-last-nonmenu-event last-nonmenu-event)
510 (setq debugger-outer-last-event-frame last-event-frame)
511 (setq debugger-outer-standard-input standard-input)
512 (setq debugger-outer-standard-output standard-output)
513 (setq debugger-outer-inhibit-redisplay inhibit-redisplay)
514 (setq debugger-outer-cursor-in-echo-area cursor-in-echo-area)
515 ))))
8c1cd093 516
0231f2dc 517(defun debugger-eval-expression (exp)
8782c06b
RS
518 "Eval an expression, in an environment like that outside the debugger."
519 (interactive
520 (list (read-from-minibuffer "Eval: "
521 nil read-expression-map t
522 'read-expression-history)))
8c1cd093 523 (debugger-env-macro (eval-expression exp)))
0231f2dc
JB
524\f
525(defvar debugger-mode-map nil)
cc1bde62 526(unless debugger-mode-map
0231f2dc
JB
527 (let ((loop ? ))
528 (setq debugger-mode-map (make-keymap))
529 (suppress-keymap debugger-mode-map)
530 (define-key debugger-mode-map "-" 'negative-argument)
531 (define-key debugger-mode-map "b" 'debugger-frame)
532 (define-key debugger-mode-map "c" 'debugger-continue)
533 (define-key debugger-mode-map "j" 'debugger-jump)
534 (define-key debugger-mode-map "r" 'debugger-return-value)
535 (define-key debugger-mode-map "u" 'debugger-frame-clear)
536 (define-key debugger-mode-map "d" 'debugger-step-through)
537 (define-key debugger-mode-map "l" 'debugger-list-functions)
538 (define-key debugger-mode-map "h" 'describe-mode)
539 (define-key debugger-mode-map "q" 'top-level)
540 (define-key debugger-mode-map "e" 'debugger-eval-expression)
8c1cd093
KH
541 (define-key debugger-mode-map " " 'next-line)
542 (define-key debugger-mode-map "R" 'debugger-record-expression)
f27b0335 543 (define-key debugger-mode-map "\C-m" 'help-follow)
cc1bde62 544 (define-key debugger-mode-map [mouse-2] 'push-button)
8c1cd093
KH
545 ))
546
547
666b9413
SE
548(defcustom debugger-record-buffer "*Debugger-record*"
549 "*Buffer name for expression values, for \\[debugger-record-expression]."
550 :type 'string
cd32a7ba
DN
551 :group 'debugger
552 :version "20.3")
8c1cd093
KH
553
554(defun debugger-record-expression (exp)
555 "Display a variable's value and record it in `*Backtrace-record*' buffer."
556 (interactive
557 (list (read-from-minibuffer
558 "Record Eval: "
559 nil
560 read-expression-map t
561 'read-expression-history)))
562 (let* ((buffer (get-buffer-create debugger-record-buffer))
563 (standard-output buffer))
564 (princ (format "Debugger Eval (%s): " exp))
565 (princ (debugger-eval-expression exp))
566 (terpri))
567
568 (with-current-buffer (get-buffer debugger-record-buffer)
569 (save-excursion
570 (forward-line -1)
571 (message
572 (buffer-substring (point) (progn (end-of-line) (point)))))))
0231f2dc
JB
573
574(put 'debugger-mode 'mode-class 'special)
575
576(defun debugger-mode ()
577 "Mode for backtrace buffers, selected in debugger.
578\\<debugger-mode-map>
579A line starts with `*' if exiting that frame will call the debugger.
580Type \\[debugger-frame] or \\[debugger-frame-clear] to set or remove the `*'.
581
582When in debugger due to frame being exited,
583use the \\[debugger-return-value] command to override the value
584being returned from that frame.
585
586Use \\[debug-on-entry] and \\[cancel-debug-on-entry] to control
587which functions will enter the debugger when called.
588
589Complete list of commands:
590\\{debugger-mode-map}"
8c1cd093 591 (kill-all-local-variables)
0231f2dc
JB
592 (setq major-mode 'debugger-mode)
593 (setq mode-name "Debugger")
594 (setq truncate-lines t)
595 (set-syntax-table emacs-lisp-mode-syntax-table)
8c1cd093
KH
596 (use-local-map debugger-mode-map)
597 (run-hooks 'debugger-mode-hook))
0231f2dc
JB
598\f
599;;;###autoload
600(defun debug-on-entry (function)
601 "Request FUNCTION to invoke debugger each time it is called.
2512acba
RS
602If you tell the debugger to continue, FUNCTION's execution proceeds.
603This works by modifying the definition of FUNCTION,
0231f2dc
JB
604which must be written in Lisp, not predefined.
605Use \\[cancel-debug-on-entry] to cancel the effect of this command.
2512acba 606Redefining FUNCTION also cancels it."
0231f2dc
JB
607 (interactive "aDebug on entry (to function): ")
608 (debugger-reenable)
f9e899b6
KH
609 ;; Handle a function that has been aliased to some other function.
610 (if (symbolp (symbol-function function))
611 (fset function `(lambda (&rest debug-on-entry-args)
612 (apply ',(symbol-function function)
613 debug-on-entry-args))))
0231f2dc
JB
614 (if (subrp (symbol-function function))
615 (error "Function %s is a primitive" function))
616 (or (consp (symbol-function function))
617 (debug-convert-byte-code function))
618 (or (consp (symbol-function function))
619 (error "Definition of %s is not a list" function))
620 (fset function (debug-on-entry-1 function (symbol-function function) t))
621 (or (memq function debug-function-list)
622 (setq debug-function-list (cons function debug-function-list)))
623 function)
624
625;;;###autoload
626(defun cancel-debug-on-entry (&optional function)
627 "Undo effect of \\[debug-on-entry] on FUNCTION.
628If argument is nil or an empty string, cancel for all functions."
10a4c11f
JB
629 (interactive
630 (list (let ((name
631 (completing-read "Cancel debug on entry (to function): "
632 ;; Make an "alist" of the functions
633 ;; that now have debug on entry.
634 (mapcar 'list
635 (mapcar 'symbol-name
636 debug-function-list))
637 nil t nil)))
638 (if name (intern name)))))
0231f2dc
JB
639 (debugger-reenable)
640 (if (and function (not (string= function "")))
641 (progn
642 (fset function
643 (debug-on-entry-1 function (symbol-function function) nil))
644 (setq debug-function-list (delq function debug-function-list))
645 function)
646 (message "Cancelling debug-on-entry for all functions")
647 (mapcar 'cancel-debug-on-entry debug-function-list)))
648
649(defun debug-convert-byte-code (function)
650 (let ((defn (symbol-function function)))
651 (if (not (consp defn))
652 ;; Assume a compiled code object.
653 (let* ((contents (append defn nil))
654 (body
655 (list (list 'byte-code (nth 1 contents)
656 (nth 2 contents) (nth 3 contents)))))
657 (if (nthcdr 5 contents)
658 (setq body (cons (list 'interactive (nth 5 contents)) body)))
659 (if (nth 4 contents)
c8c76dd3
RS
660 ;; Use `documentation' here, to get the actual string,
661 ;; in case the compiled function has a reference
662 ;; to the .elc file.
663 (setq body (cons (documentation function) body)))
0231f2dc
JB
664 (fset function (cons 'lambda (cons (car contents) body)))))))
665
666(defun debug-on-entry-1 (function defn flag)
667 (if (subrp defn)
668 (error "%s is a built-in function" function)
669 (if (eq (car defn) 'macro)
670 (debug-on-entry-1 function (cdr defn) flag)
671 (or (eq (car defn) 'lambda)
672 (error "%s not user-defined Lisp function" function))
673 (let (tail prec)
674 (if (stringp (car (nthcdr 2 defn)))
675 (setq tail (nthcdr 3 defn)
676 prec (list (car defn) (car (cdr defn))
677 (car (cdr (cdr defn)))))
678 (setq tail (nthcdr 2 defn)
679 prec (list (car defn) (car (cdr defn)))))
680 (if (eq flag (equal (car tail) '(debug 'debug)))
681 defn
682 (if flag
683 (nconc prec (cons '(debug 'debug) tail))
684 (nconc prec (cdr tail))))))))
685
686(defun debugger-list-functions ()
687 "Display a list of all the functions now set to debug on entry."
688 (interactive)
689 (with-output-to-temp-buffer "*Help*"
690 (if (null debug-function-list)
691 (princ "No debug-on-entry functions now\n")
692 (princ "Functions set to debug on entry:\n\n")
693 (let ((list debug-function-list))
694 (while list
695 (prin1 (car list))
696 (terpri)
697 (setq list (cdr list))))
698 (princ "Note: if you have redefined a function, then it may no longer\n")
89961ff8
KH
699 (princ "be set to debug on entry, even if it is in the list."))
700 (save-excursion
701 (set-buffer standard-output)
702 (help-mode))))
c0274f38 703
896546cd
RS
704(provide 'debug)
705
c0274f38 706;;; debug.el ends here