Mercurial > emacs
comparison lisp/gud.el @ 2581:839d67a1dc58
Set no-byte-compile local variable t to work around a byte-compiler bug.
(gud-def, global-map): Move C-x C-a commands to global map. Restore
original C-x SPC global binding.
author | Eric S. Raymond <esr@snark.thyrsus.com> |
---|---|
date | Sun, 25 Apr 1993 22:26:45 +0000 |
parents | 17a6b6d079cf |
children | e1277aec1738 |
comparison
equal
deleted
inserted
replaced
2580:a66f7ed76416 | 2581:839d67a1dc58 |
---|---|
1 ;;; gud.el --- Grand Unified Debugger mode for gdb, sdb, or dbx under Emacs | 1 ;;; gud.el --- Grand Unified Debugger mode for gdb, sdb, or dbx under Emacs |
2 | 2 |
3 ;; Author: Eric S. Raymond <esr@snark.thyrsus.com> | 3 ;; Author: Eric S. Raymond <esr@snark.thyrsus.com> |
4 ;; Version: 1.2 | 4 ;; Version: 1.3 |
5 ;; Keywords: unix, tools | 5 ;; Keywords: unix, tools |
6 | 6 |
7 ;; Copyright (C) 1992 Free Software Foundation, Inc. | 7 ;; Copyright (C) 1992 Free Software Foundation, Inc. |
8 | 8 |
9 ;; This file is part of GNU Emacs. | 9 ;; This file is part of GNU Emacs. |
28 ;; It was later rewritten by rms. Some ideas were due to Masanobu. | 28 ;; It was later rewritten by rms. Some ideas were due to Masanobu. |
29 ;; Grand Unification (sdb/dbx support) by Eric S. Raymond <esr@thyrsus.com> | 29 ;; Grand Unification (sdb/dbx support) by Eric S. Raymond <esr@thyrsus.com> |
30 ;; The overloading code was then rewritten by Barry Warsaw <bwarsaw@cen.com>, | 30 ;; The overloading code was then rewritten by Barry Warsaw <bwarsaw@cen.com>, |
31 ;; who also hacked the mode to use comint.el. | 31 ;; who also hacked the mode to use comint.el. |
32 | 32 |
33 ;; This code will not work under Emacs 18. It relies on Emacs 19's | |
34 ;; minor-mode-keymap support and the find-tag-noselect entry point of etags. | |
35 | |
36 ;;; Code: | 33 ;;; Code: |
37 | 34 |
38 (require 'comint) | 35 (require 'comint) |
39 (require 'etags) | 36 (require 'etags) |
40 | 37 |
41 ;; ====================================================================== | 38 ;; ====================================================================== |
42 ;; minor-mode machinery for C buffers visited by GUD | 39 ;; GUD commands must be visible in C buffers visited by GUD |
43 | 40 |
44 (defvar gud-key-prefix "\C-x\C-a" | 41 (defvar gud-key-prefix "\C-x\C-a" |
45 "Prefix of all GUD minor-mode commands valid in C buffers.") | 42 "Prefix of all GUD commands valid in C buffers.") |
46 | 43 |
47 (defvar gud-minor-mode nil) | 44 (global-set-key (concat gud-key-prefix "\C-l") 'gud-refresh) |
48 (or (assq 'gud-minor-mode minor-mode-alist) | 45 (global-set-key "\C-x " 'gud-break) ;; backward compatibility hack |
49 (setq minor-mode-alist | |
50 (cons '(gud-minor-mode " GUD") minor-mode-alist))) | |
51 | |
52 (defvar gud-mode-map nil) | |
53 (if gud-mode-map | |
54 nil | |
55 (setq gud-mode-map (make-sparse-keymap)) | |
56 (define-key gud-mode-map gud-key-prefix (make-sparse-keymap)) | |
57 (define-key gud-mode-map (concat gud-key-prefix "\C-l") 'gud-refresh) | |
58 ) | |
59 | |
60 (or (assq 'gud-minor-mode minor-mode-map-alist) | |
61 (setq minor-mode-map-alist | |
62 (cons | |
63 (cons 'gud-minor-mode gud-mode-map) | |
64 minor-mode-map-alist))) | |
65 | |
66 (defun gud-minor-mode (&optional enable) | |
67 "GUD minor mode is enabled in C buffers visited due to a GUD stop at | |
68 breakpoint. All GUD-specific commands defined in GUD major mode will work, | |
69 but they get their current file and current line number from the context of | |
70 this buffer." | |
71 (interactive "P") | |
72 (setq gud-minor-mode | |
73 (if (null enable) (not gud-minor-mode) | |
74 (> (prefix-numeric-value enable) 0))) | |
75 ) | |
76 | 46 |
77 ;; ====================================================================== | 47 ;; ====================================================================== |
78 ;; the overloading mechanism | 48 ;; the overloading mechanism |
79 | 49 |
80 (defun gud-overload-functions (gud-overload-alist) | 50 (defun gud-overload-functions (gud-overload-alist) |
102 ;; user defined ones. | 72 ;; user defined ones. |
103 | 73 |
104 ;; A macro call like (gud-def FUNC NAME KEY DOC) expands to a form | 74 ;; A macro call like (gud-def FUNC NAME KEY DOC) expands to a form |
105 ;; which defines FUNC to send the command NAME to the debugger, gives | 75 ;; which defines FUNC to send the command NAME to the debugger, gives |
106 ;; it the docstring DOC, and binds that function to KEY in the GUD | 76 ;; it the docstring DOC, and binds that function to KEY in the GUD |
107 ;; major mode. The function is also bound in the GUD minor-mode | 77 ;; major mode. The function is also bound in the global keymap with the |
108 ;; keymap. If a numeric prefix argument is given to FUNC, it gets | 78 ;; GUD prefix. |
109 ;; sent after NAME. | |
110 | 79 |
111 (defmacro gud-def (func cmd key &optional doc) | 80 (defmacro gud-def (func cmd key &optional doc) |
112 "Define FUNC to be a command sending STR and bound to KEY, with | 81 "Define FUNC to be a command sending STR and bound to KEY, with |
113 optional doc string DOC. Certain %-escapes in the string arguments | 82 optional doc string DOC. Certain %-escapes in the string arguments |
114 are interpreted specially if present. These are: | 83 are interpreted specially if present. These are: |
117 %l number of current source line | 86 %l number of current source line |
118 %e text of the C lvalue or function-call expression surrounding point. | 87 %e text of the C lvalue or function-call expression surrounding point. |
119 %a text of the hexadecimal address surrounding point | 88 %a text of the hexadecimal address surrounding point |
120 %p prefix argument to the command (if any) as a number | 89 %p prefix argument to the command (if any) as a number |
121 | 90 |
122 The `current' source file is the file of the current buffer (if we're in a | 91 The `current' source file is the file of the current buffer (if |
123 C file with gud-minor-mode active) or the source file current at the last | 92 we're in a C file) or the source file current at the last break or |
124 break or step (if we're in the GUD buffer). | 93 step (if we're in the GUD buffer). |
125 The `current' line is that of the current buffer (if we're in a source | 94 The `current' line is that of the current buffer (if we're in a |
126 file with gud-minor-mode active) or the source line number at the last | 95 source file) or the source line number at the last break or step (if |
127 break or step (if we're in the GUD buffer)." | 96 we're in the GUD buffer)." |
128 (list 'progn | 97 (list 'progn |
129 (list 'defun func '(arg) | 98 (list 'defun func '(arg) |
130 (or doc "") | 99 (or doc "") |
131 '(interactive "p") | 100 '(interactive "p") |
132 (list 'gud-call cmd 'arg)) | 101 (list 'gud-call cmd 'arg)) |
133 (if key | 102 (if key |
134 (list 'define-key | 103 (progn |
135 'gud-mode-map | 104 (list 'define-key |
136 (concat gud-key-prefix key) | 105 '(current-local-map) |
137 (list 'quote func))))) | 106 (concat "\C-c" key) |
107 (list 'quote func)) | |
108 (list 'global-set-key | |
109 (concat gud-key-prefix key) | |
110 (list 'quote func)) | |
111 )))) | |
138 | 112 |
139 ;; Where gud-display-frame should put the debugging arrow. This is | 113 ;; Where gud-display-frame should put the debugging arrow. This is |
140 ;; set by the marker-filter, which scans the debugger's output for | 114 ;; set by the marker-filter, which scans the debugger's output for |
141 ;; indications of the current program counter. | 115 ;; indications of the current program counter. |
142 (defvar gud-last-frame nil) | 116 (defvar gud-last-frame nil) |
200 (gud-overload-functions '((gud-debugger-startup . gud-gdb-debugger-startup) | 174 (gud-overload-functions '((gud-debugger-startup . gud-gdb-debugger-startup) |
201 (gud-marker-filter . gud-gdb-marker-filter) | 175 (gud-marker-filter . gud-gdb-marker-filter) |
202 (gud-find-file . gud-gdb-find-file) | 176 (gud-find-file . gud-gdb-find-file) |
203 )) | 177 )) |
204 | 178 |
179 (gud-common-init args) | |
180 | |
205 (gud-def gud-break "break %f:%l" "b" "Set breakpoint at current line.") | 181 (gud-def gud-break "break %f:%l" "b" "Set breakpoint at current line.") |
206 (gud-def gud-tbreak "tbreak %f:%l" "t" "Set breakpoint at current line.") | 182 (gud-def gud-tbreak "tbreak %f:%l" "t" "Set breakpoint at current line.") |
207 (gud-def gud-remove "clear %l" "d" "Remove breakpoint at current line") | 183 (gud-def gud-remove "clear %l" "d" "Remove breakpoint at current line") |
208 (gud-def gud-step "step %p" "s" "Step one source line with display.") | 184 (gud-def gud-step "step %p" "s" "Step one source line with display.") |
209 (gud-def gud-stepi "stepi %p" "i" "Step one instruction with display.") | 185 (gud-def gud-stepi "stepi %p" "i" "Step one instruction with display.") |
211 (gud-def gud-cont "cont" "r" "Continue with display.") | 187 (gud-def gud-cont "cont" "r" "Continue with display.") |
212 (gud-def gud-finish "finish" "f" "Finish executing current function.") | 188 (gud-def gud-finish "finish" "f" "Finish executing current function.") |
213 (gud-def gud-up "up %p" "<" "Up N stack frames (numeric arg).") | 189 (gud-def gud-up "up %p" "<" "Up N stack frames (numeric arg).") |
214 (gud-def gud-down "down %p" ">" "Down N stack frames (numeric arg).") | 190 (gud-def gud-down "down %p" ">" "Down N stack frames (numeric arg).") |
215 (gud-def gud-print "print %e" "p" "Evaluate C expression at point.") | 191 (gud-def gud-print "print %e" "p" "Evaluate C expression at point.") |
216 | |
217 (gud-common-init args) | |
218 | 192 |
219 (setq comint-prompt-regexp "^(.*gdb[+]?) *") | 193 (setq comint-prompt-regexp "^(.*gdb[+]?) *") |
220 (run-hooks 'gdb-mode-hook) | 194 (run-hooks 'gdb-mode-hook) |
221 ) | 195 ) |
222 | 196 |
265 ;;;###autoload | 239 ;;;###autoload |
266 (defun sdb (args) | 240 (defun sdb (args) |
267 "Run sdb on program FILE in buffer *gud-FILE*. | 241 "Run sdb on program FILE in buffer *gud-FILE*. |
268 The directory containing FILE becomes the initial working directory | 242 The directory containing FILE becomes the initial working directory |
269 and source-file directory for your debugger." | 243 and source-file directory for your debugger." |
270 | |
271 (interactive "sRun sdb (like this): sdb ") | 244 (interactive "sRun sdb (like this): sdb ") |
272 | |
273 (if (and gud-sdb-needs-tags | 245 (if (and gud-sdb-needs-tags |
274 (not (and (boundp 'tags-file-name) (file-exists-p tags-file-name)))) | 246 (not (and (boundp 'tags-file-name) (file-exists-p tags-file-name)))) |
275 (error "The sdb support requires a valid tags table to work.")) | 247 (error "The sdb support requires a valid tags table to work.")) |
276 (gud-overload-functions '((gud-debugger-startup . gud-sdb-debugger-startup) | 248 (gud-overload-functions '((gud-debugger-startup . gud-sdb-debugger-startup) |
277 (gud-marker-filter . gud-sdb-marker-filter) | 249 (gud-marker-filter . gud-sdb-marker-filter) |
278 (gud-find-file . gud-sdb-find-file) | 250 (gud-find-file . gud-sdb-find-file) |
279 )) | 251 )) |
252 | |
253 (gud-common-init args) | |
280 | 254 |
281 (gud-def gud-break "%l b" "b" "Set breakpoint at current line.") | 255 (gud-def gud-break "%l b" "b" "Set breakpoint at current line.") |
282 (gud-def gud-tbreak "%l c" "t" "Set temporary breakpoint at current line.") | 256 (gud-def gud-tbreak "%l c" "t" "Set temporary breakpoint at current line.") |
283 (gud-def gud-remove "%l d" "d" "Remove breakpoint at current line") | 257 (gud-def gud-remove "%l d" "d" "Remove breakpoint at current line") |
284 (gud-def gud-step "s %p" "s" "Step one source line with display.") | 258 (gud-def gud-step "s %p" "s" "Step one source line with display.") |
285 (gud-def gud-stepi "i %p" "i" "Step one instruction with display.") | 259 (gud-def gud-stepi "i %p" "i" "Step one instruction with display.") |
286 (gud-def gud-next "S %p" "n" "Step one line (skip functions).") | 260 (gud-def gud-next "S %p" "n" "Step one line (skip functions).") |
287 (gud-def gud-cont "c" "r" "Continue with display.") | 261 (gud-def gud-cont "c" "r" "Continue with display.") |
288 (gud-def gud-print "%e/" "p" "Evaluate C expression at point.") | 262 (gud-def gud-print "%e/" "p" "Evaluate C expression at point.") |
289 | |
290 (gud-common-init args) | |
291 | 263 |
292 (setq comint-prompt-regexp "\\(^\\|\n\\)\\*") | 264 (setq comint-prompt-regexp "\\(^\\|\n\\)\\*") |
293 (run-hooks 'sdb-mode-hook) | 265 (run-hooks 'sdb-mode-hook) |
294 ) | 266 ) |
295 | 267 |
321 (gud-overload-functions '((gud-debugger-startup . gud-dbx-debugger-startup) | 293 (gud-overload-functions '((gud-debugger-startup . gud-dbx-debugger-startup) |
322 (gud-marker-filter . gud-dbx-marker-filter) | 294 (gud-marker-filter . gud-dbx-marker-filter) |
323 (gud-find-file . gud-dbx-find-file) | 295 (gud-find-file . gud-dbx-find-file) |
324 )) | 296 )) |
325 | 297 |
298 (gud-common-init args) | |
299 | |
326 (gud-def gud-break "stop at \"%f\":%l" | 300 (gud-def gud-break "stop at \"%f\":%l" |
327 "b" "Set breakpoint at current line.") | 301 "b" "Set breakpoint at current line.") |
328 (gud-def gud-remove "clear %l" "d" "Remove breakpoint at current line") | 302 (gud-def gud-remove "clear %l" "d" "Remove breakpoint at current line") |
329 (gud-def gud-step "step %p" "s" "Step one line with display.") | 303 (gud-def gud-step "step %p" "s" "Step one line with display.") |
330 (gud-def gud-stepi "stepi %p" "i" "Step one instruction with display.") | 304 (gud-def gud-stepi "stepi %p" "i" "Step one instruction with display.") |
332 (gud-def gud-cont "cont" "r" "Continue with display.") | 306 (gud-def gud-cont "cont" "r" "Continue with display.") |
333 (gud-def gud-up "up %p" "<" "Up (numeric arg) stack frames.") | 307 (gud-def gud-up "up %p" "<" "Up (numeric arg) stack frames.") |
334 (gud-def gud-down "down %p" ">" "Down (numeric arg) stack frames.") | 308 (gud-def gud-down "down %p" ">" "Down (numeric arg) stack frames.") |
335 (gud-def gud-print "print %e" "p" "Evaluate C expression at point.") | 309 (gud-def gud-print "print %e" "p" "Evaluate C expression at point.") |
336 | 310 |
337 (gud-common-init args) | |
338 (setq comint-prompt-regexp "^[^)]*dbx) *") | 311 (setq comint-prompt-regexp "^[^)]*dbx) *") |
339 | |
340 (run-hooks 'dbx-mode-hook) | 312 (run-hooks 'dbx-mode-hook) |
341 ) | 313 ) |
342 | 314 |
343 ;; | 315 ;; |
344 ;; End of debugger-specific information | 316 ;; End of debugger-specific information |
396 | 368 |
397 After startup, the following commands are available in both the GUD | 369 After startup, the following commands are available in both the GUD |
398 interaction buffer and any source buffer GUD visits due to a breakpoint stop | 370 interaction buffer and any source buffer GUD visits due to a breakpoint stop |
399 or step operation: | 371 or step operation: |
400 | 372 |
401 \\{gud-mode-map} | |
402 | |
403 \\[gud-break] sets a breakpoint at the current file and line. In the | 373 \\[gud-break] sets a breakpoint at the current file and line. In the |
404 GUD buffer, the current file and line are those of the last breakpoint or | 374 GUD buffer, the current file and line are those of the last breakpoint or |
405 step. In a source buffer, they are the buffer's file and current line. | 375 step. In a source buffer, they are the buffer's file and current line. |
406 | 376 |
407 \\[gud-remove] removes breakpoints on the current file and line. | 377 \\[gud-remove] removes breakpoints on the current file and line. |
445 (comint-mode) | 415 (comint-mode) |
446 (setq major-mode 'gud-mode) | 416 (setq major-mode 'gud-mode) |
447 (setq mode-name "Debugger") | 417 (setq mode-name "Debugger") |
448 (setq mode-line-process '(": %s")) | 418 (setq mode-line-process '(": %s")) |
449 (use-local-map (copy-keymap comint-mode-map)) | 419 (use-local-map (copy-keymap comint-mode-map)) |
450 (define-key (current-local-map) | |
451 gud-key-prefix (lookup-key gud-mode-map gud-key-prefix)) | |
452 (define-key (current-local-map) | |
453 "\C-c" (lookup-key gud-mode-map gud-key-prefix)) | |
454 (make-local-variable 'gud-last-frame) | 420 (make-local-variable 'gud-last-frame) |
455 (setq gud-last-frame nil) | 421 (setq gud-last-frame nil) |
456 (make-local-variable 'comint-prompt-regexp) | 422 (make-local-variable 'comint-prompt-regexp) |
457 (make-local-variable 'gud-delete-prompt-marker) | 423 (make-local-variable 'gud-delete-prompt-marker) |
458 (setq gud-delete-prompt-marker (make-marker)) | 424 (setq gud-delete-prompt-marker (make-marker)) |
533 (defun gud-sentinel (proc msg) | 499 (defun gud-sentinel (proc msg) |
534 (cond ((null (buffer-name (process-buffer proc))) | 500 (cond ((null (buffer-name (process-buffer proc))) |
535 ;; buffer killed | 501 ;; buffer killed |
536 ;; Stop displaying an arrow in a source file. | 502 ;; Stop displaying an arrow in a source file. |
537 (setq overlay-arrow-position nil) | 503 (setq overlay-arrow-position nil) |
538 (setq gud-minor-mode nil) | |
539 (set-process-buffer proc nil)) | 504 (set-process-buffer proc nil)) |
540 ((memq (process-status proc) '(signal exit)) | 505 ((memq (process-status proc) '(signal exit)) |
541 ;; Stop displaying an arrow in a source file. | 506 ;; Stop displaying an arrow in a source file. |
542 (setq gud-minor-mode nil) | |
543 (setq overlay-arrow-position nil) | 507 (setq overlay-arrow-position nil) |
544 ;; Fix the mode line. | 508 ;; Fix the mode line. |
545 (setq mode-line-process | 509 (setq mode-line-process |
546 (concat ": " | 510 (concat ": " |
547 (symbol-name (process-status proc)))) | 511 (symbol-name (process-status proc)))) |
586 | 550 |
587 (defun gud-display-line (true-file line) | 551 (defun gud-display-line (true-file line) |
588 (let* ((buffer (gud-find-file true-file)) | 552 (let* ((buffer (gud-find-file true-file)) |
589 (window (display-buffer buffer)) | 553 (window (display-buffer buffer)) |
590 (pos)) | 554 (pos)) |
555 (if (equal buffer (current-buffer)) | |
556 nil | |
557 (setq buffer-read-only nil)) | |
591 (save-excursion | 558 (save-excursion |
592 (set-buffer buffer) | 559 (set-buffer buffer) |
593 (make-local-variable 'gud-minor-mode) | 560 (setq buffer-read-only t) |
594 (setq gud-minor-mode t) | |
595 (save-restriction | 561 (save-restriction |
596 (widen) | 562 (widen) |
597 (goto-line line) | 563 (goto-line line) |
598 (setq pos (point)) | 564 (setq pos (point)) |
599 (setq overlay-arrow-string "=>") | 565 (setq overlay-arrow-string "=>") |
605 (goto-char pos)))) | 571 (goto-char pos)))) |
606 (set-window-point window overlay-arrow-position))) | 572 (set-window-point window overlay-arrow-position))) |
607 | 573 |
608 ;;; The gud-call function must do the right thing whether its invoking | 574 ;;; The gud-call function must do the right thing whether its invoking |
609 ;;; keystroke is from the GUD buffer itself (via major-mode binding) | 575 ;;; keystroke is from the GUD buffer itself (via major-mode binding) |
610 ;;; or a C buffer in GUD minor mode. In the former case, we want to | 576 ;;; or a C buffer. In the former case, we want to supply data from |
611 ;;; supply data from gud-last-frame. Here's how we do it: | 577 ;;; gud-last-frame. Here's how we do it: |
612 | 578 |
613 (defun gud-format-command (str arg) | 579 (defun gud-format-command (str arg) |
614 (let ((minor (not (eq (current-buffer) gud-comint-buffer)))) | 580 (let ((insource (not (eq (current-buffer) gud-comint-buffer)))) |
615 (if (string-match "\\(.*\\)%f\\(.*\\)" str) | 581 (if (string-match "\\(.*\\)%f\\(.*\\)" str) |
616 (progn | 582 (progn |
617 (setq str (concat | 583 (setq str (concat |
618 (substring str (match-beginning 1) (match-end 1)) | 584 (substring str (match-beginning 1) (match-end 1)) |
619 (if minor | 585 (if insource |
620 (buffer-file-name) | 586 (buffer-file-name) |
621 (car gud-last-frame)) | 587 (car gud-last-frame)) |
622 (substring str (match-beginning 2) (match-end 2)))))) | 588 (substring str (match-beginning 2) (match-end 2)))))) |
623 (if (string-match "\\(.*\\)%l\\(.*\\)" str) | 589 (if (string-match "\\(.*\\)%l\\(.*\\)" str) |
624 (progn | 590 (progn |
625 (setq str (concat | 591 (setq str (concat |
626 (substring str (match-beginning 1) (match-end 1)) | 592 (substring str (match-beginning 1) (match-end 1)) |
627 (if minor | 593 (if insource |
628 (save-excursion | 594 (save-excursion |
629 (beginning-of-line) | 595 (beginning-of-line) |
630 (save-restriction (widen) | 596 (save-restriction (widen) |
631 (1+ (count-lines 1 (point))))) | 597 (1+ (count-lines 1 (point))))) |
632 (cdr gud-last-frame)) | 598 (cdr gud-last-frame)) |
849 ) | 815 ) |
850 (t nil)) | 816 (t nil)) |
851 ) | 817 ) |
852 ) | 818 ) |
853 | 819 |
820 ;;; There appears to be a bug in the byte compiler somewhere near macro | |
821 ;;; handling that (a) generates a spurious message about gud-key-prefix | |
822 ;;; when the global-set-key clause in gud-def is compiled, (b) generates | |
823 ;;; incorrect bytecode for gud-def. The symptom of this incorrectness | |
824 ;;; is that loading gud.elc brings in a compiled gud-def that doesn't | |
825 ;;; properly perform both global (C-x C-a) and local (C-c) bindings. | |
826 ;;; The workaround is to always load from source. Consequently, we try | |
827 ;;; to disable byte-compilation here. | |
828 ;;; | |
829 ;;; Local Variables: | |
830 ;;; no-byte-compile: t | |
831 ;;; End: | |
832 | |
854 ;;; gud.el ends here | 833 ;;; gud.el ends here |