*** empty log message ***
[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)
dc64809a 305 "Attach cross-references to function 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
dc64809a 356 (goto-char (+ (point) 2))
25c58854
RS
357 (skip-syntax-forward "^w_")
358 (not (eobp)))
359 (let* ((beg (point))
360 (end (progn (skip-syntax-forward "w_") (point)))
361 (sym (intern-soft (buffer-substring-no-properties
362 beg end)))
654359e2 363 (file (and sym (symbol-file sym 'defun))))
25c58854
RS
364 (when file
365 (goto-char beg)
366 ;; help-xref-button needs to operate on something matched
367 ;; by a regexp, so set that up for it.
dc64809a
LK
368 (re-search-forward "\\(\\sw\\|\\s_\\)+")
369 (help-xref-button 0 'help-function-def sym file)))
f27b0335 370 (forward-line 1))
25c58854
RS
371 (widen))
372 (setq debugger-previous-backtrace (buffer-string))))
63ca439e 373\f
0231f2dc
JB
374(defun debugger-step-through ()
375 "Proceed, stepping through subexpressions of this expression.
376Enter another debugger on next entry to eval, apply or funcall."
377 (interactive)
378 (setq debugger-step-after-exit t)
9b54d453
LK
379 (setq debugger-jumping-flag t)
380 (add-hook 'post-command-hook 'debugger-reenable)
0231f2dc
JB
381 (message "Proceeding, will debug on next eval or call.")
382 (exit-recursive-edit))
383
384(defun debugger-continue ()
385 "Continue, evaluating this expression without stopping."
386 (interactive)
094e0928
GM
387 (unless debugger-may-continue
388 (error "Cannot continue"))
0231f2dc
JB
389 (message "Continuing.")
390 (exit-recursive-edit))
391
392(defun debugger-return-value (val)
393 "Continue, specifying value to return.
394This is only useful when the value returned from the debugger
395will be used, such as in a debug on exit from a frame."
396 (interactive "XReturn value (evaluated): ")
397 (setq debugger-value val)
398 (princ "Returning " t)
399 (prin1 debugger-value)
400 (exit-recursive-edit))
401
402(defun debugger-jump ()
403 "Continue to exit from this frame, with all debug-on-entry suspended."
404 (interactive)
27bde5f0 405 (debugger-frame)
b6b77a90
LK
406 (setq debugger-jumping-flag t)
407 (add-hook 'post-command-hook 'debugger-reenable)
0231f2dc
JB
408 (message "Continuing through this frame")
409 (exit-recursive-edit))
410
411(defun debugger-reenable ()
b6b77a90
LK
412 "Turn all debug-on-entry functions back on.
413This function is put on `post-command-hook' by `debugger-jump' and
414removes itself from that hook."
415 (setq debugger-jumping-flag nil)
416 (remove-hook 'post-command-hook 'debugger-reenable))
0231f2dc
JB
417
418(defun debugger-frame-number ()
419 "Return number of frames in backtrace before the one point points at."
420 (save-excursion
421 (beginning-of-line)
422 (let ((opoint (point))
423 (count 0))
27bde5f0
RS
424 (while (not (eq (cadr (backtrace-frame count)) 'debug))
425 (setq count (1+ count)))
449808f7
LK
426 ;; Skip implement-debug-on-entry frame.
427 (when (eq 'implement-debug-on-entry (cadr (backtrace-frame (1+ count))))
439368ed 428 (setq count (1+ count)))
0231f2dc 429 (goto-char (point-min))
439368ed
LK
430 (when (looking-at "Debugger entered--\\(Lisp error\\|returning value\\):")
431 (goto-char (match-end 0))
432 (forward-sexp 1))
0231f2dc
JB
433 (forward-line 1)
434 (while (progn
435 (forward-char 2)
436 (if (= (following-char) ?\()
437 (forward-sexp 1)
438 (forward-sexp 2))
439 (forward-line 1)
440 (<= (point) opoint))
65fe45f2
RS
441 (if (looking-at " *;;;")
442 (forward-line 1))
0231f2dc
JB
443 (setq count (1+ count)))
444 count)))
445
0231f2dc
JB
446(defun debugger-frame ()
447 "Request entry to debugger when this frame exits.
448Applies to the frame whose line point is on in the backtrace."
449 (interactive)
fa5b1b57
RS
450 (save-excursion
451 (beginning-of-line)
452 (if (looking-at " *;;;\\|[a-z]")
453 (error "This line is not a function call")))
0231f2dc 454 (beginning-of-line)
27bde5f0 455 (backtrace-debug (debugger-frame-number) t)
0231f2dc
JB
456 (if (= (following-char) ? )
457 (let ((buffer-read-only nil))
458 (delete-char 1)
459 (insert ?*)))
460 (beginning-of-line))
461
462(defun debugger-frame-clear ()
c519f68f 463 "Do not enter debugger when this frame exits.
0231f2dc
JB
464Applies to the frame whose line point is on in the backtrace."
465 (interactive)
fa5b1b57
RS
466 (save-excursion
467 (beginning-of-line)
468 (if (looking-at " *;;;\\|[a-z]")
469 (error "This line is not a function call")))
0231f2dc 470 (beginning-of-line)
27bde5f0 471 (backtrace-debug (debugger-frame-number) nil)
0231f2dc
JB
472 (if (= (following-char) ?*)
473 (let ((buffer-read-only nil))
474 (delete-char 1)
475 (insert ? )))
476 (beginning-of-line))
477
8c1cd093
KH
478(put 'debugger-env-macro 'lisp-indent-function 0)
479(defmacro debugger-env-macro (&rest body)
480 "Run BODY in original environment."
6c2599ed
SS
481 `(save-excursion
482 (if (null (buffer-name debugger-old-buffer))
483 ;; old buffer deleted
484 (setq debugger-old-buffer (current-buffer)))
485 (set-buffer debugger-old-buffer)
486 (let ((load-read-function debugger-outer-load-read-function)
487 (overriding-terminal-local-map
488 debugger-outer-overriding-terminal-local-map)
489 (overriding-local-map debugger-outer-overriding-local-map)
490 (track-mouse debugger-outer-track-mouse)
491 (last-command debugger-outer-last-command)
492 (this-command debugger-outer-this-command)
6c2599ed
SS
493 (unread-command-events debugger-outer-unread-command-events)
494 (unread-post-input-method-events
495 debugger-outer-unread-post-input-method-events)
496 (last-input-event debugger-outer-last-input-event)
497 (last-command-event debugger-outer-last-command-event)
498 (last-nonmenu-event debugger-outer-last-nonmenu-event)
499 (last-event-frame debugger-outer-last-event-frame)
500 (standard-input debugger-outer-standard-input)
501 (standard-output debugger-outer-standard-output)
502 (inhibit-redisplay debugger-outer-inhibit-redisplay)
503 (cursor-in-echo-area debugger-outer-cursor-in-echo-area))
504 (set-match-data debugger-outer-match-data)
12cf32ce
RS
505 (prog1
506 (let ((save-ucc (with-no-warnings unread-command-char)))
507 (unwind-protect
508 (progn
509 (with-no-warnings
c4fbcb01 510 (setq unread-command-char debugger-outer-unread-command-char))
12cf32ce
RS
511 (prog1 (progn ,@body)
512 (with-no-warnings
c4fbcb01 513 (setq debugger-outer-unread-command-char unread-command-char))))
12cf32ce 514 (with-no-warnings
c4fbcb01 515 (setq unread-command-char save-ucc))))
6c2599ed
SS
516 (setq debugger-outer-match-data (match-data))
517 (setq debugger-outer-load-read-function load-read-function)
518 (setq debugger-outer-overriding-terminal-local-map
519 overriding-terminal-local-map)
520 (setq debugger-outer-overriding-local-map overriding-local-map)
521 (setq debugger-outer-track-mouse track-mouse)
522 (setq debugger-outer-last-command last-command)
523 (setq debugger-outer-this-command this-command)
6c2599ed
SS
524 (setq debugger-outer-unread-command-events unread-command-events)
525 (setq debugger-outer-unread-post-input-method-events
526 unread-post-input-method-events)
527 (setq debugger-outer-last-input-event last-input-event)
528 (setq debugger-outer-last-command-event last-command-event)
529 (setq debugger-outer-last-nonmenu-event last-nonmenu-event)
530 (setq debugger-outer-last-event-frame last-event-frame)
531 (setq debugger-outer-standard-input standard-input)
532 (setq debugger-outer-standard-output standard-output)
533 (setq debugger-outer-inhibit-redisplay inhibit-redisplay)
534 (setq debugger-outer-cursor-in-echo-area cursor-in-echo-area)
535 ))))
8c1cd093 536
0231f2dc 537(defun debugger-eval-expression (exp)
8782c06b
RS
538 "Eval an expression, in an environment like that outside the debugger."
539 (interactive
540 (list (read-from-minibuffer "Eval: "
541 nil read-expression-map t
542 'read-expression-history)))
8c1cd093 543 (debugger-env-macro (eval-expression exp)))
0231f2dc 544\f
78d54dee
SM
545(defvar debugger-mode-map
546 (let ((map (make-keymap)))
547 (set-keymap-parent map button-buffer-map)
548 (suppress-keymap map)
549 (define-key map "-" 'negative-argument)
550 (define-key map "b" 'debugger-frame)
551 (define-key map "c" 'debugger-continue)
552 (define-key map "j" 'debugger-jump)
553 (define-key map "r" 'debugger-return-value)
554 (define-key map "u" 'debugger-frame-clear)
555 (define-key map "d" 'debugger-step-through)
556 (define-key map "l" 'debugger-list-functions)
557 (define-key map "h" 'describe-mode)
558 (define-key map "q" 'top-level)
559 (define-key map "e" 'debugger-eval-expression)
560 (define-key map " " 'next-line)
561 (define-key map "R" 'debugger-record-expression)
562 (define-key map "\C-m" 'help-follow)
563 (define-key map [mouse-2] 'push-button)
564 map))
8c1cd093 565
666b9413
SE
566(defcustom debugger-record-buffer "*Debugger-record*"
567 "*Buffer name for expression values, for \\[debugger-record-expression]."
568 :type 'string
cd32a7ba
DN
569 :group 'debugger
570 :version "20.3")
8c1cd093
KH
571
572(defun debugger-record-expression (exp)
573 "Display a variable's value and record it in `*Backtrace-record*' buffer."
574 (interactive
575 (list (read-from-minibuffer
576 "Record Eval: "
577 nil
578 read-expression-map t
579 'read-expression-history)))
580 (let* ((buffer (get-buffer-create debugger-record-buffer))
581 (standard-output buffer))
582 (princ (format "Debugger Eval (%s): " exp))
583 (princ (debugger-eval-expression exp))
584 (terpri))
585
586 (with-current-buffer (get-buffer debugger-record-buffer)
587 (save-excursion
588 (forward-line -1)
589 (message
590 (buffer-substring (point) (progn (end-of-line) (point)))))))
0231f2dc
JB
591
592(put 'debugger-mode 'mode-class 'special)
593
594(defun debugger-mode ()
595 "Mode for backtrace buffers, selected in debugger.
596\\<debugger-mode-map>
597A line starts with `*' if exiting that frame will call the debugger.
598Type \\[debugger-frame] or \\[debugger-frame-clear] to set or remove the `*'.
599
600When in debugger due to frame being exited,
601use the \\[debugger-return-value] command to override the value
602being returned from that frame.
603
604Use \\[debug-on-entry] and \\[cancel-debug-on-entry] to control
605which functions will enter the debugger when called.
606
607Complete list of commands:
608\\{debugger-mode-map}"
8c1cd093 609 (kill-all-local-variables)
0231f2dc
JB
610 (setq major-mode 'debugger-mode)
611 (setq mode-name "Debugger")
612 (setq truncate-lines t)
613 (set-syntax-table emacs-lisp-mode-syntax-table)
8c1cd093 614 (use-local-map debugger-mode-map)
78d54dee 615 (run-mode-hooks 'debugger-mode-hook))
0231f2dc 616\f
449808f7
LK
617;; When you change this, you may also need to change the number of
618;; frames that the debugger skips.
619(defun implement-debug-on-entry ()
620 "Conditionally call the debugger.
621A call to this function is inserted by `debug-on-entry' to cause
622functions to break on entry."
623 (if (or inhibit-debug-on-entry debugger-jumping-flag)
624 nil
625 (funcall debugger 'debug)))
626
0231f2dc
JB
627;;;###autoload
628(defun debug-on-entry (function)
629 "Request FUNCTION to invoke debugger each time it is called.
2512acba
RS
630If you tell the debugger to continue, FUNCTION's execution proceeds.
631This works by modifying the definition of FUNCTION,
0231f2dc
JB
632which must be written in Lisp, not predefined.
633Use \\[cancel-debug-on-entry] to cancel the effect of this command.
2512acba 634Redefining FUNCTION also cancels it."
0231f2dc 635 (interactive "aDebug on entry (to function): ")
f9e899b6 636 ;; Handle a function that has been aliased to some other function.
7473b6ad
SM
637 (if (and (subrp (symbol-function function))
638 (eq (cdr (subr-arity (symbol-function function))) 'unevalled))
639 (error "Function %s is a special form" function))
640 (if (or (symbolp (symbol-function function))
641 (subrp (symbol-function function)))
642 ;; Create a wrapper in which we can then add the necessary debug call.
f9e899b6 643 (fset function `(lambda (&rest debug-on-entry-args)
7473b6ad 644 ,(interactive-form (symbol-function function))
f9e899b6
KH
645 (apply ',(symbol-function function)
646 debug-on-entry-args))))
0231f2dc
JB
647 (or (consp (symbol-function function))
648 (debug-convert-byte-code function))
649 (or (consp (symbol-function function))
650 (error "Definition of %s is not a list" function))
449808f7 651 (fset function (debug-on-entry-1 function t))
0231f2dc 652 (or (memq function debug-function-list)
6836bb69 653 (push function debug-function-list))
0231f2dc
JB
654 function)
655
656;;;###autoload
657(defun cancel-debug-on-entry (&optional function)
658 "Undo effect of \\[debug-on-entry] on FUNCTION.
659If argument is nil or an empty string, cancel for all functions."
10a4c11f
JB
660 (interactive
661 (list (let ((name
662 (completing-read "Cancel debug on entry (to function): "
cafbc9a5 663 (mapcar 'symbol-name debug-function-list)
10a4c11f
JB
664 nil t nil)))
665 (if name (intern name)))))
0231f2dc
JB
666 (if (and function (not (string= function "")))
667 (progn
449808f7 668 (let ((f (debug-on-entry-1 function nil)))
7473b6ad
SM
669 (condition-case nil
670 (if (and (equal (nth 1 f) '(&rest debug-on-entry-args))
671 (eq (car (nth 3 f)) 'apply))
672 ;; `f' is a wrapper introduced in debug-on-entry.
673 ;; Get rid of it since we don't need it any more.
674 (setq f (nth 1 (nth 1 (nth 3 f)))))
675 (error nil))
676 (fset function f))
0231f2dc
JB
677 (setq debug-function-list (delq function debug-function-list))
678 function)
679 (message "Cancelling debug-on-entry for all functions")
680 (mapcar 'cancel-debug-on-entry debug-function-list)))
681
682(defun debug-convert-byte-code (function)
683 (let ((defn (symbol-function function)))
684 (if (not (consp defn))
685 ;; Assume a compiled code object.
686 (let* ((contents (append defn nil))
687 (body
688 (list (list 'byte-code (nth 1 contents)
689 (nth 2 contents) (nth 3 contents)))))
690 (if (nthcdr 5 contents)
691 (setq body (cons (list 'interactive (nth 5 contents)) body)))
692 (if (nth 4 contents)
c8c76dd3
RS
693 ;; Use `documentation' here, to get the actual string,
694 ;; in case the compiled function has a reference
695 ;; to the .elc file.
696 (setq body (cons (documentation function) body)))
0231f2dc
JB
697 (fset function (cons 'lambda (cons (car contents) body)))))))
698
449808f7
LK
699(defun debug-on-entry-1 (function flag)
700 (let* ((defn (symbol-function function))
701 (tail defn))
a29cf450
SM
702 (if (subrp tail)
703 (error "%s is a built-in function" function)
704 (if (eq (car tail) 'macro) (setq tail (cdr tail)))
705 (if (eq (car tail) 'lambda) (setq tail (cdr tail))
706 (error "%s not user-defined Lisp function" function))
707 ;; Skip the docstring.
708 (when (and (stringp (cadr tail)) (cddr tail))
709 (setq tail (cdr tail)))
710 ;; Skip the interactive form.
711 (when (eq 'interactive (car-safe (cadr tail)))
712 (setq tail (cdr tail)))
449808f7 713 (unless (eq flag (equal (cadr tail) '(implement-debug-on-entry)))
a29cf450
SM
714 ;; Add/remove debug statement as needed.
715 (if flag
449808f7 716 (setcdr tail (cons '(implement-debug-on-entry) (cdr tail)))
a29cf450
SM
717 (setcdr tail (cddr tail))))
718 defn)))
0231f2dc
JB
719
720(defun debugger-list-functions ()
721 "Display a list of all the functions now set to debug on entry."
722 (interactive)
78d54dee
SM
723 (require 'help-mode)
724 (help-setup-xref '(debugger-list-functions) (interactive-p))
725 (with-output-to-temp-buffer (help-buffer)
726 (with-current-buffer standard-output
727 (if (null debug-function-list)
728 (princ "No debug-on-entry functions now\n")
729 (princ "Functions set to debug on entry:\n\n")
730 (dolist (fun debug-function-list)
731 (make-text-button (point) (progn (prin1 fun) (point))
732 'type 'help-function
733 'help-args (list fun))
734 (terpri))
735 (terpri)
736 (princ "Note: if you have redefined a function, then it may no longer\n")
737 (princ "be set to debug on entry, even if it is in the list.")))))
c0274f38 738
896546cd
RS
739(provide 'debug)
740
78d54dee 741;; arch-tag: b6ec7047-f801-4103-9c63-d69322db9d3b
c0274f38 742;;; debug.el ends here