|
|
1.1 root 1: ;; Debuggers and related commands for Emacs
2: ;; Copyright (C) 1985 Richard M. Stallman.
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 (generate-new-buffer "*Backtrace*"))
38: debugger-step-after-exit)
39: (unwind-protect
40: (save-excursion
41: (save-window-excursion
42: (pop-to-buffer debugger-buffer)
43: (erase-buffer)
44: (let ((standard-output (current-buffer))
45: (print-length 50))
46: (backtrace))
47: (goto-char (point-min))
48: (debugger-mode)
49: (delete-region (point)
50: (progn
51: (forward-sexp 8)
52: (forward-line 1)
53: (point)))
54: (cond ((memq (car debugger-args) '(lambda debug))
55: (insert "Entering:\n")
56: (if (eq (car debugger-args) 'debug)
57: (progn
58: (backtrace-debug 4 t)
59: (delete-char 1)
60: (insert ?*)
61: (beginning-of-line))))
62: ((eq (car debugger-args) 'exit)
63: (insert "Return value: ")
64: (setq debugger-value (nth 1 debugger-args))
65: (prin1 debugger-value (current-buffer))
66: (insert ?\n)
67: (delete-char 1)
68: (insert ? )
69: (beginning-of-line))
70: ((eq (car debugger-args) 'error)
71: (insert "Signalling: ")
72: (prin1 (nth 1 debugger-args) (current-buffer))
73: (insert ?\n))
74: ((eq (car debugger-args) t)
75: (insert "Beginning evaluation of function call form:\n"))
76: (t
77: (prin1 (if (eq (car debugger-args) 'nil)
78: (cdr debugger-args) debugger-args)
79: (current-buffer))
80: (insert ?\n)))
81: (message "")
82: (let ((inhibit-trace t)
83: (standard-output nil)
84: (buffer-read-only t))
85: (message "")
86: (recursive-edit))))
87: ;; So that users do not try to execute debugger commands
88: ;; in an invalid context
89: (kill-buffer debugger-buffer)
90: (store-match-data debugger-match-data))
91: (setq debug-on-next-call debugger-step-after-exit)
92: debugger-value))
93:
94: (defun debugger-step-through ()
95: "Proceed, stepping through subexpressions of this expression.
96: Enter another debugger on next entry to eval, apply or funcall."
97: (interactive)
98: (setq debugger-step-after-exit t)
99: (message "Proceding, will debug on next eval or call.")
100: (exit-recursive-edit))
101:
102: (defun debugger-continue ()
103: "Continue, evaluating this expression without stopping."
104: (interactive)
105: (message "Continuing.")
106: (exit-recursive-edit))
107:
108: (defun debugger-return-value (val)
109: "Continue, specifying value to return.
110: This is only useful when the value returned from the debugger
111: will be used, such as in a debug on exit from a frame."
112: (interactive "XReturn value (evaluated): ")
113: (setq debugger-value val)
114: (princ "Returning " t)
115: (prin1 debugger-value)
116: (exit-recursive-edit))
117:
118: (defun debugger-frame-number ()
119: "Return number of frames in backtrace before the one point points at."
120: (save-excursion
121: (beginning-of-line)
122: (let ((opoint (point))
123: (count 0))
124: (goto-char (point-min))
125: (if (or (equal (buffer-substring (point) (+ (point) 6))
126: "Signal")
127: (equal (buffer-substring (point) (+ (point) 6))
128: "Return"))
129: (progn
130: (search-forward ":")
131: (forward-sexp 1)))
132: (forward-line 1)
133: (while (progn
134: (forward-char 2)
135: (if (= (following-char) ?\()
136: (forward-sexp 1)
137: (forward-sexp 2))
138: (forward-line 1)
139: (<= (point) opoint))
140: (setq count (1+ count)))
141: count)))
142:
143: ;; Chosen empirically to account for all the frames
144: ;; that will exist when debugger-frame is called
145: ;; within the first one that appears in the backtrace buffer.
146: ;; Assumes debugger-frame is called from a key;
147: ;; will be wrong if it is called with Meta-x.
148: (defconst debugger-frame-offset 8 "")
149:
150: (defun debugger-frame ()
151: "Request entry to debugger when this frame exits.
152: Applies to the frame whose line point is on in the backtrace."
153: (interactive)
154: (beginning-of-line)
155: (let ((level (debugger-frame-number)))
156: (backtrace-debug (+ level debugger-frame-offset) t))
157: (if (= (following-char) ? )
158: (let ((buffer-read-only nil))
159: (delete-char 1)
160: (insert ?*)))
161: (beginning-of-line))
162:
163: (defun debugger-frame-clear ()
164: "Do not enter to debugger when this frame exits.
165: Applies to the frame whose line point is on in the backtrace."
166: (interactive)
167: (beginning-of-line)
168: (let ((level (debugger-frame-number)))
169: (backtrace-debug (+ level debugger-frame-offset) nil))
170: (if (= (following-char) ?*)
171: (let ((buffer-read-only nil))
172: (delete-char 1)
173: (insert ? )))
174: (beginning-of-line))
175:
176: ;; These two function names are equivalent except that
177: ;; debugger-eval-expression is not normally disabled.
178: (fset 'debugger-eval-expression 'eval-expression)
179:
180: (defvar debugger-mode-map nil)
181: (if debugger-mode-map
182: nil
183: (let ((loop ? ))
184: (setq debugger-mode-map (make-keymap))
185: (suppress-keymap debugger-mode-map)
186: (define-key debugger-mode-map "-" 'negative-argument)
187: (define-key debugger-mode-map "b" 'debugger-frame)
188: (define-key debugger-mode-map "c" 'debugger-continue)
189: (define-key debugger-mode-map "r" 'debugger-return-value)
190: (define-key debugger-mode-map "u" 'debugger-frame-clear)
191: (define-key debugger-mode-map "d" 'debugger-step-through)
192: (define-key debugger-mode-map "h" 'describe-mode)
193: (define-key debugger-mode-map "q" 'top-level)
194: (define-key debugger-mode-map "e" 'debugger-eval-expression)
195: (define-key debugger-mode-map " " 'next-line)))
196:
197: (defun debugger-mode ()
198: "Mode for backtrace buffers, selected in debugger.
199: \\{debugger-mode-map}
200: For the r command, when in debugger due to frame being exited,
201: the value specified here will be used as the value of that frame.
202:
203: Note lines starting with * are frames that will
204: enter debugger when exited."
205: (kill-all-local-variables)
206: (setq major-mode 'debugger-mode)
207: (setq mode-name "Debugger")
208: (setq truncate-lines t)
209: (set-syntax-table lisp-mode-syntax-table)
210: (use-local-map debugger-mode-map))
211:
212: (defun debug-on-entry (function)
213: "Request FUNCTION to invoke debugger each time it is called.
214: If the user continues, FUNCTION's execution proceeds.
215: Works by modifying the definition of FUNCTION,
216: which must be written in Lisp, not predefined."
217: (interactive "aDebug on entry (to function): ")
218: (let ((defn (symbol-function function)))
219: (if (eq (car defn) 'macro)
220: (fset function (cons 'macro (debug-on-entry-1 function (cdr defn) t)))
221: (fset function (debug-on-entry-1 function defn t))))
222: function)
223:
224: (defun cancel-debug-on-entry (function)
225: "Undoes effect of debug-on-entry on FUNCTION."
226: (interactive "aCancel debug on entry (to function): ")
227: (let ((defn (symbol-function function)))
228: (if (eq (car defn) 'macro)
229: (fset function (cons 'macro (debug-on-entry-1 function (cdr defn)) nil))
230: (fset function (debug-on-entry-1 function defn nil))))
231: function)
232:
233: (defun debug-on-entry-1 (function defn flag)
234: (or (eq (car defn) 'lambda)
235: (error "%s not user-defined Lisp function." function))
236: (let (tail prec)
237: (if (stringp (car (nthcdr 2 defn)))
238: (setq tail (nthcdr 3 defn)
239: prec (list (car defn) (car (cdr defn)) (car (cdr (cdr defn)))))
240: (setq tail (nthcdr 2 defn)
241: prec (list (car defn) (car (cdr defn)))))
242: (if (eq flag (equal (car tail) '(debug 'debug)))
243: nil
244: (if flag
245: (nconc prec (cons '(debug 'debug) tail))
246: (nconc prec (cdr tail))))))
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.