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