|
|
1.1 root 1: ;; Debuggers and related commands for Emacs
2: ;; Copyright (C) 1985, 1986 Free Software Foundation, Inc.
3:
4: ;; This file is part of GNU Emacs.
5:
6: ;; GNU Emacs is distributed in the hope that it will be useful,
7: ;; but WITHOUT ANY WARRANTY. No author or distributor
8: ;; accepts responsibility to anyone for the consequences of using it
9: ;; or for whether it serves any particular purpose or works at all,
10: ;; unless he says so in writing. Refer to the GNU Emacs General Public
11: ;; License for full details.
12:
13: ;; Everyone is granted permission to copy, modify and redistribute
14: ;; GNU Emacs, but only under the conditions described in the
15: ;; GNU Emacs General Public License. A copy of this license is
16: ;; supposed to have been given to you along with GNU Emacs so you
17: ;; can know your rights and responsibilities. It should be in a
18: ;; file named COPYING. Among other things, the copyright notice
19: ;; and this notice must be preserved on all copies.
20:
21:
22: (setq debugger 'debug)
23:
24: (defun debug (&rest debugger-args)
25: "Enter debugger. Returns if user says \"continue\".
26: Arguments are mainly for use when this is called
27: from the internals of the evaluator.
28: You may call with no args, or you may
29: pass nil as the first arg and any other args you like.
30: In that case, the list of args after the first will
31: be printed into the backtrace buffer."
32: (message "Entering debugger...")
33: (let (debugger-value
34: (debugger-match-data (match-data))
35: (debug-on-error nil)
36: (debug-on-quit nil)
37: (debugger-buffer (let ((default-major-mode 'fundamental-mode))
38: (generate-new-buffer "*Backtrace*")))
39: (debugger-old-buffer (current-buffer))
40: (debugger-step-after-exit nil)
41: ;; Don't keep reading from an executing kbd macro!
42: (executing-macro nil)
43: (cursor-in-echo-area nil))
44: (unwind-protect
45: (save-excursion
46: (save-window-excursion
47: (pop-to-buffer debugger-buffer)
48: (erase-buffer)
49: (let ((standard-output (current-buffer))
50: (print-escape-newlines t)
51: (print-length 50))
52: (backtrace))
53: (goto-char (point-min))
54: (debugger-mode)
55: (delete-region (point)
56: (progn
57: (forward-sexp 8)
58: (forward-line 1)
59: (point)))
60: (cond ((memq (car debugger-args) '(lambda debug))
61: (insert "Entering:\n")
62: (if (eq (car debugger-args) 'debug)
63: (progn
64: (backtrace-debug 4 t)
65: (delete-char 1)
66: (insert ?*)
67: (beginning-of-line))))
68: ((eq (car debugger-args) 'exit)
69: (insert "Return value: ")
70: (setq debugger-value (nth 1 debugger-args))
71: (prin1 debugger-value (current-buffer))
72: (insert ?\n)
73: (delete-char 1)
74: (insert ? )
75: (beginning-of-line))
76: ((eq (car debugger-args) 'error)
77: (insert "Signalling: ")
78: (prin1 (nth 1 debugger-args) (current-buffer))
79: (insert ?\n))
80: ((eq (car debugger-args) t)
81: (insert "Beginning evaluation of function call form:\n"))
82: (t
83: (prin1 (if (eq (car debugger-args) 'nil)
84: (cdr debugger-args) debugger-args)
85: (current-buffer))
86: (insert ?\n)))
87: (message "")
88: (let ((inhibit-trace t)
89: (standard-output nil)
90: (buffer-read-only t))
91: (message "")
92: (recursive-edit))))
93: ;; So that users do not try to execute debugger commands
94: ;; in an invalid context
95: (kill-buffer debugger-buffer)
96: (catch 'foo
97: (let ((d debugger-match-data))
98: (while d
99: (and (car d)
100: (null (marker-buffer (car d)))
101: ;; match-data buffer is deleted.
102: (throw 'foo nil))
103: (setq d (cdr d)))
104: (store-match-data debugger-match-data))))
105: (setq debug-on-next-call debugger-step-after-exit)
106: debugger-value))
107:
108: (defun debugger-step-through ()
109: "Proceed, stepping through subexpressions of this expression.
110: Enter another debugger on next entry to eval, apply or funcall."
111: (interactive)
112: (setq debugger-step-after-exit t)
113: (message "Proceding, will debug on next eval or call.")
114: (exit-recursive-edit))
115:
116: (defun debugger-continue ()
117: "Continue, evaluating this expression without stopping."
118: (interactive)
119: (message "Continuing.")
120: (exit-recursive-edit))
121:
122: (defun debugger-return-value (val)
123: "Continue, specifying value to return.
124: This is only useful when the value returned from the debugger
125: will be used, such as in a debug on exit from a frame."
126: (interactive "XReturn value (evaluated): ")
127: (setq debugger-value val)
128: (princ "Returning " t)
129: (prin1 debugger-value)
130: (exit-recursive-edit))
131:
132: (defun debugger-frame-number ()
133: "Return number of frames in backtrace before the one point points at."
134: (save-excursion
135: (beginning-of-line)
136: (let ((opoint (point))
137: (count 0))
138: (goto-char (point-min))
139: (if (or (equal (buffer-substring (point) (+ (point) 6))
140: "Signal")
141: (equal (buffer-substring (point) (+ (point) 6))
142: "Return"))
143: (progn
144: (search-forward ":")
145: (forward-sexp 1)))
146: (forward-line 1)
147: (while (progn
148: (forward-char 2)
149: (if (= (following-char) ?\()
150: (forward-sexp 1)
151: (forward-sexp 2))
152: (forward-line 1)
153: (<= (point) opoint))
154: (setq count (1+ count)))
155: count)))
156:
157: ;; Chosen empirically to account for all the frames
158: ;; that will exist when debugger-frame is called
159: ;; within the first one that appears in the backtrace buffer.
160: ;; Assumes debugger-frame is called from a key;
161: ;; will be wrong if it is called with Meta-x.
162: (defconst debugger-frame-offset 8 "")
163:
164: (defun debugger-frame ()
165: "Request entry to debugger when this frame exits.
166: Applies to the frame whose line point is on in the backtrace."
167: (interactive)
168: (beginning-of-line)
169: (let ((level (debugger-frame-number)))
170: (backtrace-debug (+ level debugger-frame-offset) t))
171: (if (= (following-char) ? )
172: (let ((buffer-read-only nil))
173: (delete-char 1)
174: (insert ?*)))
175: (beginning-of-line))
176:
177: (defun debugger-frame-clear ()
178: "Do not enter to debugger when this frame exits.
179: Applies to the frame whose line point is on in the backtrace."
180: (interactive)
181: (beginning-of-line)
182: (let ((level (debugger-frame-number)))
183: (backtrace-debug (+ level debugger-frame-offset) nil))
184: (if (= (following-char) ?*)
185: (let ((buffer-read-only nil))
186: (delete-char 1)
187: (insert ? )))
188: (beginning-of-line))
189:
190: (defun debugger-eval-expression (exp)
191: (interactive "xEval: ")
192: (save-excursion
193: (if (null (buffer-name debugger-old-buffer))
194: ;; old buffer deleted
195: (setq debugger-old-buffer (current-buffer)))
196: (set-buffer debugger-old-buffer)
197: (eval-expression exp)))
198:
199: (defvar debugger-mode-map nil)
200: (if debugger-mode-map
201: nil
202: (let ((loop ? ))
203: (setq debugger-mode-map (make-keymap))
204: (suppress-keymap debugger-mode-map)
205: (define-key debugger-mode-map "-" 'negative-argument)
206: (define-key debugger-mode-map "b" 'debugger-frame)
207: (define-key debugger-mode-map "c" 'debugger-continue)
208: (define-key debugger-mode-map "r" 'debugger-return-value)
209: (define-key debugger-mode-map "u" 'debugger-frame-clear)
210: (define-key debugger-mode-map "d" 'debugger-step-through)
211: (define-key debugger-mode-map "h" 'describe-mode)
212: (define-key debugger-mode-map "q" 'top-level)
213: (define-key debugger-mode-map "e" 'debugger-eval-expression)
214: (define-key debugger-mode-map " " 'next-line)))
215:
216: (put 'debugger-mode 'mode-class 'special)
217:
218: (defun debugger-mode ()
219: "Mode for backtrace buffers, selected in debugger.
220: \\{debugger-mode-map}
221: For the r command, when in debugger due to frame being exited,
222: the value specified here will be used as the value of that frame.
223:
224: Note lines starting with * are frames that will
225: enter debugger when exited."
226: (kill-all-local-variables)
227: (setq major-mode 'debugger-mode)
228: (setq mode-name "Debugger")
229: (setq truncate-lines t)
230: (set-syntax-table emacs-lisp-mode-syntax-table)
231: (use-local-map debugger-mode-map))
232:
233: (defun debug-on-entry (function)
234: "Request FUNCTION to invoke debugger each time it is called.
235: If the user continues, FUNCTION's execution proceeds.
236: Works by modifying the definition of FUNCTION,
237: which must be written in Lisp, not predefined.
238: Use `cancel-debug-on-entry' to cancel the effect of this command.
239: Redefining FUNCTION also does that."
240: (interactive "aDebug on entry (to function): ")
241: (let ((defn (symbol-function function)))
242: (if (eq (car defn) 'macro)
243: (fset function (cons 'macro (debug-on-entry-1 function (cdr defn) t)))
244: (fset function (debug-on-entry-1 function defn t))))
245: function)
246:
247: (defun cancel-debug-on-entry (function)
248: "Undoes effect of debug-on-entry on FUNCTION."
249: (interactive "aCancel debug on entry (to function): ")
250: (let ((defn (symbol-function function)))
251: (if (eq (car defn) 'macro)
252: (fset function
253: (cons 'macro (debug-on-entry-1 function (cdr defn) nil)))
254: (fset function (debug-on-entry-1 function defn nil))))
255: function)
256:
257: (defun debug-on-entry-1 (function defn flag)
258: (or (eq (car defn) 'lambda)
259: (error "%s not user-defined Lisp function." function))
260: (let (tail prec)
261: (if (stringp (car (nthcdr 2 defn)))
262: (setq tail (nthcdr 3 defn)
263: prec (list (car defn) (car (cdr defn)) (car (cdr (cdr defn)))))
264: (setq tail (nthcdr 2 defn)
265: prec (list (car defn) (car (cdr defn)))))
266: (if (eq flag (equal (car tail) '(debug 'debug)))
267: nil
268: (if flag
269: (nconc prec (cons '(debug 'debug) tail))
270: (nconc prec (cdr tail))))))
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.