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