Update copyright.
[bpt/emacs.git] / lisp / gud.el
CommitLineData
6496f3d2
RS
1;;; gud.el --- Grand Unified Debugger mode for gdb, sdb, dbx, or xdb
2;;; under Emacs
f961a17c 3
ee0155df 4;; Author: Eric S. Raymond <esr@snark.thyrsus.com>
8ba194fc 5;; Maintainer: FSF
f961a17c
ER
6;; Keywords: unix, tools
7
f8c25f1b 8;; Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
13b80a60
ER
9
10;; This file is part of GNU Emacs.
11
12;; GNU Emacs is free software; you can redistribute it and/or modify
13;; it under the terms of the GNU General Public License as published by
24d725c2 14;; the Free Software Foundation; either version 2, or (at your option)
13b80a60
ER
15;; any later version.
16
17;; GNU Emacs is distributed in the hope that it will be useful,
18;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20;; GNU General Public License for more details.
21
22;; You should have received a copy of the GNU General Public License
23;; along with GNU Emacs; see the file COPYING. If not, write to
24;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
25
f961a17c
ER
26;;; Commentary:
27
13b80a60 28;; The ancestral gdb.el was by W. Schelter <wfs@rascal.ics.utexas.edu>
24d725c2 29;; It was later rewritten by rms. Some ideas were due to Masanobu.
f961a17c 30;; Grand Unification (sdb/dbx support) by Eric S. Raymond <esr@thyrsus.com>
13b80a60 31;; The overloading code was then rewritten by Barry Warsaw <bwarsaw@cen.com>,
6496f3d2 32;; who also hacked the mode to use comint.el. Shane Hartman <shane@spr.com>
0e0de659 33;; added support for xdb (HPUX debugger). Rick Sladkey <jrs@world.std.com>
f266485d 34;; wrote the GDB command completion code. Dave Love <d.love@dl.ac.uk>
2291bfaa
RS
35;; added the IRIX kluge, re-implemented the Mips-ish variant and added
36;; a menu.
13b80a60 37
f961a17c
ER
38;;; Code:
39
13b80a60 40(require 'comint)
e8a57935 41(require 'etags)
13b80a60 42
ee0155df 43;; ======================================================================
5b08a462 44;; GUD commands must be visible in C buffers visited by GUD
ee0155df 45
45025813 46(defvar gud-key-prefix "\C-x\C-a"
5b08a462 47 "Prefix of all GUD commands valid in C buffers.")
ee0155df 48
5b08a462 49(global-set-key (concat gud-key-prefix "\C-l") 'gud-refresh)
16776e8d 50(define-key ctl-x-map " " 'gud-break) ;; backward compatibility hack
ee0155df 51
ee97eac3
RS
52(defvar gud-marker-filter nil)
53(put 'gud-marker-filter 'permanent-local t)
54(defvar gud-find-file nil)
55(put 'gud-find-file 'permanent-local t)
56
ee97eac3
RS
57(defun gud-marker-filter (&rest args)
58 (apply gud-marker-filter args))
59
60(defun gud-find-file (file)
61 ;; Don't get confused by double slashes in the name that comes from GDB.
62 (while (string-match "//+" file)
63 (setq file (replace-match "/" t t file)))
64 (funcall gud-find-file file))
9bb4544b
RS
65
66;; Keymap definitions for menu bar entries common to all debuggers and
67;; slots for debugger-dependent ones in sensible places. (Defined here
68;; before use.)
69(defvar gud-menu-map (make-sparse-keymap "Gud") nil)
70(define-key gud-menu-map [refresh] '("Refresh" . gud-refresh))
71(define-key gud-menu-map [remove] '("Remove breakpoint" . gud-remove))
72(define-key gud-menu-map [tbreak] nil) ; gdb, sdb and xdb
73(define-key gud-menu-map [break] '("Set breakpoint" . gud-break))
74(define-key gud-menu-map [up] nil) ; gdb, dbx, and xdb
75(define-key gud-menu-map [down] nil) ; gdb, dbx, and xdb
76(define-key gud-menu-map [print] '("Print expression" . gud-print))
77(define-key gud-menu-map [finish] nil) ; gdb or xdb
78(define-key gud-menu-map [stepi] '("Step instruction" . gud-stepi))
79(define-key gud-menu-map [step] '("Step line" . gud-step))
80(define-key gud-menu-map [next] '("Next line" . gud-next))
81(define-key gud-menu-map [cont] '("Continue" . gud-cont))
575661b1 82\f
ee0155df
ER
83;; ======================================================================
84;; command definition
13b80a60
ER
85
86;; This macro is used below to define some basic debugger interface commands.
f961a17c 87;; Of course you may use `gud-def' with any other debugger command, including
6bde8427
JB
88;; user defined ones.
89
90;; A macro call like (gud-def FUNC NAME KEY DOC) expands to a form
91;; which defines FUNC to send the command NAME to the debugger, gives
ee0155df 92;; it the docstring DOC, and binds that function to KEY in the GUD
5b08a462
ER
93;; major mode. The function is also bound in the global keymap with the
94;; GUD prefix.
ee0155df
ER
95
96(defmacro gud-def (func cmd key &optional doc)
97 "Define FUNC to be a command sending STR and bound to KEY, with
98optional doc string DOC. Certain %-escapes in the string arguments
99are interpreted specially if present. These are:
100
7f359a21
RS
101 %f name (without directory) of current source file.
102 %d directory of current source file.
ee0155df
ER
103 %l number of current source line
104 %e text of the C lvalue or function-call expression surrounding point.
105 %a text of the hexadecimal address surrounding point
106 %p prefix argument to the command (if any) as a number
107
5b08a462
ER
108 The `current' source file is the file of the current buffer (if
109we're in a C file) or the source file current at the last break or
110step (if we're in the GUD buffer).
111 The `current' line is that of the current buffer (if we're in a
112source file) or the source line number at the last break or step (if
113we're in the GUD buffer)."
ee0155df
ER
114 (list 'progn
115 (list 'defun func '(arg)
116 (or doc "")
117 '(interactive "p")
118 (list 'gud-call cmd 'arg))
119 (if key
dd8e46c7
RS
120 (list 'define-key
121 '(current-local-map)
122 (concat "\C-c" key)
123 (list 'quote func)))
124 (if key
125 (list 'global-set-key
2352cbea 126 (list 'concat 'gud-key-prefix key)
dd8e46c7 127 (list 'quote func)))))
13b80a60 128
d840a865
JB
129;; Where gud-display-frame should put the debugging arrow. This is
130;; set by the marker-filter, which scans the debugger's output for
ee0155df 131;; indications of the current program counter.
d840a865
JB
132(defvar gud-last-frame nil)
133
32ab4c10
JB
134;; Used by gud-refresh, which should cause gud-display-frame to redisplay
135;; the last frame, even if it's been called before and gud-last-frame has
136;; been set to nil.
7447c37a 137(defvar gud-last-last-frame nil)
32ab4c10 138
ee0155df
ER
139;; All debugger-specific information is collected here.
140;; Here's how it works, in case you ever need to add a debugger to the mode.
13b80a60
ER
141;;
142;; Each entry must define the following at startup:
143;;
144;;<name>
145;; comint-prompt-regexp
a223b10d 146;; gud-<name>-massage-args
13b80a60 147;; gud-<name>-marker-filter
ee0155df 148;; gud-<name>-find-file
13b80a60 149;;
a223b10d
RM
150;; The job of the massage-args method is to modify the given list of
151;; debugger arguments before running the debugger.
10a4c11f
JB
152;;
153;; The job of the marker-filter method is to detect file/line markers in
154;; strings and set the global gud-last-frame to indicate what display
155;; action (if any) should be triggered by the marker. Note that only
eb8c3be9 156;; whatever the method *returns* is displayed in the buffer; thus, you
10a4c11f
JB
157;; can filter the debugger's output, interpreting some and passing on
158;; the rest.
159;;
ee0155df 160;; The job of the find-file method is to visit and return the buffer indicated
10a4c11f 161;; by the car of gud-tag-frame. This may be a file name, a tag name, or
2291bfaa 162;; something else. It would be good if it also copied the Gud menubar entry.
575661b1 163\f
13b80a60
ER
164;; ======================================================================
165;; gdb functions
166
f6376199
JB
167;;; History of argument lists passed to gdb.
168(defvar gud-gdb-history nil)
169
a223b10d 170(defun gud-gdb-massage-args (file args)
dfbd82a6 171 (cons "-fullname" args))
13b80a60 172
768c29d0
JB
173;; There's no guarantee that Emacs will hand the filter the entire
174;; marker at once; it could be broken up across several strings. We
175;; might even receive a big chunk with several markers in it. If we
176;; receive a chunk of text which looks like it might contain the
177;; beginning of a marker, we save it here between calls to the
178;; filter.
f266485d 179(defvar gud-marker-acc "")
0d29cfe9 180(make-variable-buffer-local 'gud-marker-acc)
768c29d0 181
ee0155df 182(defun gud-gdb-marker-filter (string)
bed6a98d
RS
183 (setq gud-marker-acc (concat gud-marker-acc string))
184 (let ((output ""))
185
186 ;; Process all the complete markers in this chunk.
187 (while (string-match "\032\032\\([^:\n]*\\):\\([0-9]*\\):.*\n"
188 gud-marker-acc)
189 (setq
190
191 ;; Extract the frame position from the marker.
192 gud-last-frame
193 (cons (substring gud-marker-acc (match-beginning 1) (match-end 1))
194 (string-to-int (substring gud-marker-acc
195 (match-beginning 2)
196 (match-end 2))))
197
198 ;; Append any text before the marker to the output we're going
199 ;; to return - we don't include the marker in this text.
200 output (concat output
201 (substring gud-marker-acc 0 (match-beginning 0)))
202
203 ;; Set the accumulator to the remaining text.
204 gud-marker-acc (substring gud-marker-acc (match-end 0))))
205
206 ;; Does the remaining text look like it might end with the
207 ;; beginning of another marker? If it does, then keep it in
208 ;; gud-marker-acc until we receive the rest of it. Since we
209 ;; know the full marker regexp above failed, it's pretty simple to
210 ;; test for marker starts.
211 (if (string-match "\032.*\\'" gud-marker-acc)
212 (progn
213 ;; Everything before the potential marker start can be output.
214 (setq output (concat output (substring gud-marker-acc
215 0 (match-beginning 0))))
216
217 ;; Everything after, we save, to combine with later input.
218 (setq gud-marker-acc
219 (substring gud-marker-acc (match-beginning 0))))
220
221 (setq output (concat output gud-marker-acc)
222 gud-marker-acc ""))
223
224 output))
13b80a60 225
23a3aa0a
RS
226(defun gud-new-keymap (map)
227 "Return a new keymap which inherits from MAP and has name `Gud'."
228 (nconc (make-sparse-keymap "Gud") map))
229
ee0155df 230(defun gud-gdb-find-file (f)
9bb4544b
RS
231 (save-excursion
232 (let ((buf (find-file-noselect f)))
233 (set-buffer buf)
23a3aa0a 234 (use-local-map (gud-new-keymap (current-local-map)))
9bb4544b 235 (define-key (current-local-map) [menu-bar debug]
23a3aa0a 236 (cons "Gud" (gud-new-keymap gud-menu-map)))
9bb4544b
RS
237 (local-set-key [menu-bar debug tbreak]
238 '("Temporary breakpoint" . gud-tbreak))
239 (local-set-key [menu-bar debug finish] '("Finish function" . gud-finish))
240 (local-set-key [menu-bar debug up] '("Up stack" . gud-up))
241 (local-set-key [menu-bar debug down] '("Down stack" . gud-down))
242 buf)))
13b80a60 243
e886137a
KH
244(defvar gdb-minibuffer-local-map nil
245 "Keymap for minibuffer prompting of gdb startup command.")
246(if gdb-minibuffer-local-map
247 ()
248 (setq gdb-minibuffer-local-map (copy-keymap minibuffer-local-map))
249 (define-key
250 gdb-minibuffer-local-map "\C-i" 'comint-dynamic-complete-filename))
251
10a4c11f 252;;;###autoload
a223b10d 253(defun gdb (command-line)
13b80a60
ER
254 "Run gdb on program FILE in buffer *gud-FILE*.
255The directory containing FILE becomes the initial working directory
256and source-file directory for your debugger."
f6376199 257 (interactive
a223b10d 258 (list (read-from-minibuffer "Run gdb (like this): "
f6376199
JB
259 (if (consp gud-gdb-history)
260 (car gud-gdb-history)
a223b10d 261 "gdb ")
e886137a 262 gdb-minibuffer-local-map nil
f6376199 263 '(gud-gdb-history . 1))))
ee0155df 264
ee97eac3
RS
265 (gud-common-init command-line 'gud-gdb-massage-args
266 'gud-gdb-marker-filter 'gud-gdb-find-file)
5b08a462 267
dd8e46c7 268 (gud-def gud-break "break %f:%l" "\C-b" "Set breakpoint at current line.")
2fb419e1 269 (gud-def gud-tbreak "tbreak %f:%l" "\C-t" "Set temporary breakpoint at current line.")
23a3aa0a 270 (gud-def gud-remove "clear %f:%l" "\C-d" "Remove breakpoint at current line")
dd8e46c7
RS
271 (gud-def gud-step "step %p" "\C-s" "Step one source line with display.")
272 (gud-def gud-stepi "stepi %p" "\C-i" "Step one instruction with display.")
273 (gud-def gud-next "next %p" "\C-n" "Step one line (skip functions).")
274 (gud-def gud-cont "cont" "\C-r" "Continue with display.")
275 (gud-def gud-finish "finish" "\C-f" "Finish executing current function.")
ee0155df
ER
276 (gud-def gud-up "up %p" "<" "Up N stack frames (numeric arg).")
277 (gud-def gud-down "down %p" ">" "Down N stack frames (numeric arg).")
dd8e46c7 278 (gud-def gud-print "print %e" "\C-p" "Evaluate C expression at point.")
ee0155df 279
0e0de659 280 (local-set-key "\C-i" 'gud-gdb-complete-command)
2291bfaa
RS
281 (local-set-key [menu-bar debug tbreak] '("Temporary breakpoint" . gud-tbreak))
282 (local-set-key [menu-bar debug finish] '("Finish function" . gud-finish))
283 (local-set-key [menu-bar debug up] '("Up stack" . gud-up))
284 (local-set-key [menu-bar debug down] '("Down stack" . gud-down))
13b80a60 285 (setq comint-prompt-regexp "^(.*gdb[+]?) *")
f54877b2 286 (setq paragraph-start comint-prompt-regexp)
13b80a60
ER
287 (run-hooks 'gdb-mode-hook)
288 )
289
0e0de659
RS
290;; One of the nice features of GDB is its impressive support for
291;; context-sensitive command completion. We preserve that feature
292;; in the GUD buffer by using a GDB command designed just for Emacs.
293
294;; The completion process filter indicates when it is finished.
295(defvar gud-gdb-complete-in-progress)
296
297;; Since output may arrive in fragments we accumulate partials strings here.
298(defvar gud-gdb-complete-string)
299
300;; We need to know how much of the completion to chop off.
301(defvar gud-gdb-complete-break)
302
303;; The completion list is constructed by the process filter.
304(defvar gud-gdb-complete-list)
305
30df2a53
RS
306(defvar gud-comint-buffer nil)
307
0e0de659
RS
308(defun gud-gdb-complete-command ()
309 "Perform completion on the GDB command preceding point.
310This is implemented using the GDB `complete' command which isn't
311available with older versions of GDB."
312 (interactive)
313 (let* ((end (point))
314 (command (save-excursion
315 (beginning-of-line)
316 (and (looking-at comint-prompt-regexp)
317 (goto-char (match-end 0)))
318 (buffer-substring (point) end)))
319 command-word)
320 ;; Find the word break. This match will always succeed.
321 (string-match "\\(\\`\\| \\)\\([^ ]*\\)\\'" command)
322 (setq gud-gdb-complete-break (match-beginning 2)
323 command-word (substring command gud-gdb-complete-break))
ee97eac3
RS
324 ;; Temporarily install our filter function.
325 (let ((gud-marker-filter 'gud-gdb-complete-filter))
326 ;; Issue the command to GDB.
327 (gud-basic-call (concat "complete " command))
328 (setq gud-gdb-complete-in-progress t
329 gud-gdb-complete-string nil
330 gud-gdb-complete-list nil)
331 ;; Slurp the output.
332 (while gud-gdb-complete-in-progress
333 (accept-process-output (get-buffer-process gud-comint-buffer))))
0e0de659
RS
334 ;; Protect against old versions of GDB.
335 (and gud-gdb-complete-list
336 (string-match "^Undefined command: \"complete\""
337 (car gud-gdb-complete-list))
338 (error "This version of GDB doesn't support the `complete' command."))
339 ;; Sort the list like readline.
340 (setq gud-gdb-complete-list
341 (sort gud-gdb-complete-list (function string-lessp)))
342 ;; Remove duplicates.
343 (let ((first gud-gdb-complete-list)
344 (second (cdr gud-gdb-complete-list)))
345 (while second
346 (if (string-equal (car first) (car second))
347 (setcdr first (setq second (cdr second)))
348 (setq first second
349 second (cdr second)))))
fd63b4f4
KH
350 ;; Add a trailing single quote if there is a unique completion
351 ;; and it contains an odd number of unquoted single quotes.
352 (and (= (length gud-gdb-complete-list) 1)
353 (let ((str (car gud-gdb-complete-list))
354 (pos 0)
355 (count 0))
356 (while (string-match "\\([^'\\]\\|\\\\'\\)*'" str pos)
357 (setq count (1+ count)
358 pos (match-end 0)))
359 (and (= (mod count 2) 1)
360 (setq gud-gdb-complete-list (list (concat str "'"))))))
0e0de659
RS
361 ;; Let comint handle the rest.
362 (comint-dynamic-simple-complete command-word gud-gdb-complete-list)))
363
364;; The completion process filter is installed temporarily to slurp the
365;; output of GDB up to the next prompt and build the completion list.
366(defun gud-gdb-complete-filter (string)
367 (setq string (concat gud-gdb-complete-string string))
368 (while (string-match "\n" string)
369 (setq gud-gdb-complete-list
370 (cons (substring string gud-gdb-complete-break (match-beginning 0))
371 gud-gdb-complete-list))
372 (setq string (substring string (match-end 0))))
373 (if (string-match comint-prompt-regexp string)
374 (progn
375 (setq gud-gdb-complete-in-progress nil)
376 string)
377 (progn
378 (setq gud-gdb-complete-string string)
379 "")))
380
575661b1 381\f
13b80a60
ER
382;; ======================================================================
383;; sdb functions
384
f6376199
JB
385;;; History of argument lists passed to sdb.
386(defvar gud-sdb-history nil)
387
ee0155df
ER
388(defvar gud-sdb-needs-tags (not (file-exists-p "/var"))
389 "If nil, we're on a System V Release 4 and don't need the tags hack.")
390
391(defvar gud-sdb-lastfile nil)
392
dfbd82a6 393(defun gud-sdb-massage-args (file args) args)
13b80a60 394
ee0155df 395(defun gud-sdb-marker-filter (string)
7f629252
RS
396 (setq gud-marker-acc
397 (if gud-marker-acc (concat gud-marker-acc string) string))
398 (let (start)
399 ;; Process all complete markers in this chunk
400 (while
401 (cond
402 ;; System V Release 3.2 uses this format
403 ((string-match "\\(^0x\\w* in \\|^\\|\n\\)\\([^:\n]*\\):\\([0-9]*\\):.*\n"
404 gud-marker-acc start)
405 (setq gud-last-frame
406 (cons
407 (substring gud-marker-acc (match-beginning 2) (match-end 2))
408 (string-to-int
409 (substring gud-marker-acc (match-beginning 3) (match-end 3))))))
410 ;; System V Release 4.0 quite often clumps two lines together
411 ((string-match "^\\(BREAKPOINT\\|STEPPED\\) process [0-9]+ function [^ ]+ in \\(.+\\)\n\\([0-9]+\\):"
412 gud-marker-acc start)
413 (setq gud-sdb-lastfile
414 (substring gud-marker-acc (match-beginning 2) (match-end 2)))
415 (setq gud-last-frame
416 (cons
417 gud-sdb-lastfile
418 (string-to-int
419 (substring gud-marker-acc (match-beginning 3) (match-end 3))))))
420 ;; System V Release 4.0
421 ((string-match "^\\(BREAKPOINT\\|STEPPED\\) process [0-9]+ function [^ ]+ in \\(.+\\)\n"
422 gud-marker-acc start)
423 (setq gud-sdb-lastfile
424 (substring gud-marker-acc (match-beginning 2) (match-end 2))))
425 ((and gud-sdb-lastfile (string-match "^\\([0-9]+\\):"
426 gud-marker-acc start))
427 (setq gud-last-frame
428 (cons
429 gud-sdb-lastfile
430 (string-to-int
431 (substring gud-marker-acc (match-beginning 1) (match-end 1))))))
432 (t
433 (setq gud-sdb-lastfile nil)))
434 (setq start (match-end 0)))
435
436 ;; Search for the last incomplete line in this chunk
437 (while (string-match "\n" gud-marker-acc start)
438 (setq start (match-end 0)))
439
440 ;; If we have an incomplete line, store it in gud-marker-acc.
441 ;; Otherwise clear gud-marker-acc. to avoid an
442 ;; unnecessary concat when this function runs next.
443 (setq gud-marker-acc
444 (if (= start (length gud-marker-acc))
445 (substring gud-marker-acc start)
446 nil)))
13b80a60
ER
447 string)
448
ee0155df 449(defun gud-sdb-find-file (f)
9bb4544b
RS
450 (save-excursion
451 (let ((buf (if gud-sdb-needs-tags
452 (find-tag-noselect f)
453 (find-file-noselect f))))
454 (set-buffer buf)
23a3aa0a
RS
455 (use-local-map (gud-new-keymap (current-local-map)))
456 (define-key (current-local-map) [menu-bar debug]
457 (cons "Gud" (gud-new-keymap gud-menu-map)))
9bb4544b
RS
458 (local-set-key [menu-bar debug tbreak] '("Temporary breakpoint" . gud-tbreak))
459 buf)))
13b80a60 460
10a4c11f 461;;;###autoload
a223b10d 462(defun sdb (command-line)
13b80a60
ER
463 "Run sdb on program FILE in buffer *gud-FILE*.
464The directory containing FILE becomes the initial working directory
465and source-file directory for your debugger."
f6376199 466 (interactive
a223b10d 467 (list (read-from-minibuffer "Run sdb (like this): "
f6376199
JB
468 (if (consp gud-sdb-history)
469 (car gud-sdb-history)
a223b10d 470 "sdb ")
f6376199
JB
471 nil nil
472 '(gud-sdb-history . 1))))
ee0155df 473 (if (and gud-sdb-needs-tags
e290aebb
RS
474 (not (and (boundp 'tags-file-name)
475 (stringp tags-file-name)
476 (file-exists-p tags-file-name))))
13b80a60 477 (error "The sdb support requires a valid tags table to work."))
13b80a60 478
ee97eac3
RS
479 (gud-common-init command-line 'gud-sdb-massage-args
480 'gud-sdb-marker-filter 'gud-sdb-find-file)
5b08a462 481
dd8e46c7
RS
482 (gud-def gud-break "%l b" "\C-b" "Set breakpoint at current line.")
483 (gud-def gud-tbreak "%l c" "\C-t" "Set temporary breakpoint at current line.")
484 (gud-def gud-remove "%l d" "\C-d" "Remove breakpoint at current line")
485 (gud-def gud-step "s %p" "\C-s" "Step one source line with display.")
486 (gud-def gud-stepi "i %p" "\C-i" "Step one instruction with display.")
487 (gud-def gud-next "S %p" "\C-n" "Step one line (skip functions).")
488 (gud-def gud-cont "c" "\C-r" "Continue with display.")
489 (gud-def gud-print "%e/" "\C-p" "Evaluate C expression at point.")
13b80a60 490
6bde8427 491 (setq comint-prompt-regexp "\\(^\\|\n\\)\\*")
f54877b2 492 (setq paragraph-start comint-prompt-regexp)
2291bfaa
RS
493 (local-set-key [menu-bar debug tbreak]
494 '("Temporary breakpoint" . gud-tbreak))
13b80a60
ER
495 (run-hooks 'sdb-mode-hook)
496 )
575661b1 497\f
13b80a60
ER
498;; ======================================================================
499;; dbx functions
500
f6376199
JB
501;;; History of argument lists passed to dbx.
502(defvar gud-dbx-history nil)
503
dfbd82a6 504(defun gud-dbx-massage-args (file args) args)
13b80a60 505
ee0155df 506(defun gud-dbx-marker-filter (string)
7f629252
RS
507 (setq gud-marker-acc (if gud-marker-acc (concat gud-marker-acc string) string))
508
509 (let (start)
510 ;; Process all complete markers in this chunk.
511 (while (or (string-match
512 "stopped in .* at line \\([0-9]*\\) in file \"\\([^\"]*\\)\""
513 gud-marker-acc start)
514 (string-match
515 "signal .* in .* at line \\([0-9]*\\) in file \"\\([^\"]*\\)\""
516 gud-marker-acc start))
13b80a60
ER
517 (setq gud-last-frame
518 (cons
7f629252 519 (substring gud-marker-acc (match-beginning 2) (match-end 2))
13b80a60 520 (string-to-int
7f629252
RS
521 (substring gud-marker-acc (match-beginning 1) (match-end 1))))
522 start (match-end 0)))
523
524 ;; Search for the last incomplete line in this chunk
525 (while (string-match "\n" gud-marker-acc start)
526 (setq start (match-end 0)))
527
528 ;; If the incomplete line APPEARS to begin with another marker, keep it
529 ;; in the accumulator. Otherwise, clear the accumulator to avoid an
530 ;; unnecessary concat during the next call.
531 (setq gud-marker-acc
532 (if (string-match "\\(stopped\\|signal\\)" gud-marker-acc start)
533 (substring gud-marker-acc (match-beginning 0))
534 nil)))
13b80a60
ER
535 string)
536
f266485d
RS
537;; Functions for Mips-style dbx. Given the option `-emacs', documented in
538;; OSF1, not necessarily elsewhere, it produces markers similar to gdb's.
539(defvar gud-mips-p
540 (or (string-match "^mips-[^-]*-ultrix" system-configuration)
541 ;; We haven't tested gud on this system:
542 (string-match "^mips-[^-]*-riscos" system-configuration)
543 ;; It's documented on OSF/1.3
9f24ea14
RS
544 (string-match "^mips-[^-]*-osf1" system-configuration)
545 (string-match "^alpha-[^-]*-osf" system-configuration))
f266485d 546 "Non-nil to assume the MIPS/OSF dbx conventions (argument `-emacs').")
13eaa026
RS
547
548(defun gud-mipsdbx-massage-args (file args)
dfbd82a6 549 (cons "-emacs" args))
13eaa026 550
f266485d
RS
551;; This is just like the gdb one except for the regexps since we need to cope
552;; with an optional breakpoint number in [] before the ^Z^Z
13eaa026 553(defun gud-mipsdbx-marker-filter (string)
bed6a98d
RS
554 (setq gud-marker-acc (concat gud-marker-acc string))
555 (let ((output ""))
556
557 ;; Process all the complete markers in this chunk.
558 (while (string-match
559 ;; This is like th gdb marker but with an optional
560 ;; leading break point number like `[1] '
561 "[][ 0-9]*\032\032\\([^:\n]*\\):\\([0-9]*\\):.*\n"
562 gud-marker-acc)
563 (setq
564
565 ;; Extract the frame position from the marker.
566 gud-last-frame
567 (cons (substring gud-marker-acc (match-beginning 1) (match-end 1))
568 (string-to-int (substring gud-marker-acc
569 (match-beginning 2)
570 (match-end 2))))
571
572 ;; Append any text before the marker to the output we're going
573 ;; to return - we don't include the marker in this text.
574 output (concat output
575 (substring gud-marker-acc 0 (match-beginning 0)))
576
577 ;; Set the accumulator to the remaining text.
578 gud-marker-acc (substring gud-marker-acc (match-end 0))))
579
580 ;; Does the remaining text look like it might end with the
581 ;; beginning of another marker? If it does, then keep it in
582 ;; gud-marker-acc until we receive the rest of it. Since we
583 ;; know the full marker regexp above failed, it's pretty simple to
584 ;; test for marker starts.
585 (if (string-match "[][ 0-9]*\032.*\\'" gud-marker-acc)
586 (progn
587 ;; Everything before the potential marker start can be output.
588 (setq output (concat output (substring gud-marker-acc
589 0 (match-beginning 0))))
590
591 ;; Everything after, we save, to combine with later input.
592 (setq gud-marker-acc
593 (substring gud-marker-acc (match-beginning 0))))
594
595 (setq output (concat output gud-marker-acc)
596 gud-marker-acc ""))
597
598 output))
13eaa026 599
f266485d
RS
600;; The dbx in IRIX is a pain. It doesn't print the file name when
601;; stopping at a breakpoint (but you do get it from the `up' and
602;; `down' commands...). The only way to extract the information seems
603;; to be with a `file' command, although the current line number is
604;; available in $curline. Thus we have to look for output which
605;; appears to indicate a breakpoint. Then we prod the dbx sub-process
606;; to output the information we want with a combination of the
607;; `printf' and `file' commands as a pseudo marker which we can
608;; recognise next time through the marker-filter. This would be like
609;; the gdb marker but you can't get the file name without a newline...
610;; Note that gud-remove won't work since Irix dbx expects a breakpoint
611;; number rather than a line number etc. Maybe this could be made to
612;; work by listing all the breakpoints and picking the one(s) with the
613;; correct line number, but life's too short.
614;; d.love@dl.ac.uk (Dave Love) can be blamed for this
615
616(defvar gud-irix-p (string-match "^mips-[^-]*-irix" system-configuration)
617 "Non-nil to assume the interface appropriate for IRIX dbx.
2fb419e1
RS
618This works in IRIX 4, 5 and 6.")
619;; [Irix dbx seems to be a moving target. The dbx output changed
620;; subtly sometime between OS v4.0.5 and v5.2 so that, for instance,
621;; the output from `up' is no longer spotted by gud (and it's probably
622;; not distinctive enough to try to match it -- use C-<, C->
623;; exclusively) . For 5.3 and 6.0, the $curline variable changed to
624;; `long long'(why?!), so the printf stuff needed changing. The line
625;; number is cast to `long' as a compromise between the new `long
626;; long' and the original `int'. The process filter is also somewhat
627;; unreliable, sometimes not spotting the markers; I don't know
628;; whether there's anything that can be done about that. It would be
629;; much better if SGI could be persuaded to (re?)instate the MIPS
630;; -emacs flag for gdb-like output (which ought to be possible as most
631;; of the communication I've had over it has been from sgi.com).]
f266485d
RS
632
633;; this filter is influenced by the xdb one rather than the gdb one
634(defun gud-irixdbx-marker-filter (string)
bed6a98d
RS
635 (let (result (case-fold-search nil))
636 (if (or (string-match comint-prompt-regexp string)
637 (string-match ".*\012" string))
638 (setq result (concat gud-marker-acc string)
639 gud-marker-acc "")
640 (setq gud-marker-acc (concat gud-marker-acc string)))
641 (if result
642 (cond
643 ;; look for breakpoint or signal indication e.g.:
644 ;; [2] Process 1267 (pplot) stopped at [params:338 ,0x400ec0]
645 ;; Process 1281 (pplot) stopped at [params:339 ,0x400ec8]
646 ;; Process 1270 (pplot) Floating point exception [._read._read:16 ,0x452188]
647 ((string-match
648 "^\\(\\[[0-9]+] \\)?Process +[0-9]+ ([^)]*) [^[]+\\[[^]\n]*]\n"
649 result)
650 ;; prod dbx into printing out the line number and file
651 ;; name in a form we can grok as below
652 (process-send-string (get-buffer-process gud-comint-buffer)
e802811f 653 "printf \"\032\032%1d:\",(long)$curline;file\n"))
bed6a98d
RS
654 ;; look for result of, say, "up" e.g.:
655 ;; .pplot.pplot(0x800) ["src/pplot.f":261, 0x400c7c]
656 ;; (this will also catch one of the lines printed by "where")
657 ((string-match
658 "^[^ ][^[]*\\[\"\\([^\"]+\\)\":\\([0-9]+\\), [^]]+]\n"
659 result)
660 (let ((file (substring result (match-beginning 1)
661 (match-end 1))))
662 (if (file-exists-p file)
663 (setq gud-last-frame
664 (cons
665 (substring
666 result (match-beginning 1) (match-end 1))
667 (string-to-int
668 (substring
669 result (match-beginning 2) (match-end 2)))))))
670 result)
671 ((string-match ; kluged-up marker as above
672 "\032\032\\([0-9]*\\):\\(.*\\)\n" result)
673 (let ((file (substring result (match-beginning 2) (match-end 2))))
674 (if (file-exists-p file)
675 (setq gud-last-frame
676 (cons
677 file
678 (string-to-int
679 (substring
680 result (match-beginning 1) (match-end 1)))))))
681 (setq result (substring result 0 (match-beginning 0))))))
682 (or result "")))
f266485d 683
ee0155df 684(defun gud-dbx-find-file (f)
9bb4544b
RS
685 (save-excursion
686 (let ((buf (find-file-noselect f)))
687 (set-buffer buf)
23a3aa0a
RS
688 (use-local-map (gud-new-keymap (current-local-map)))
689 (define-key (current-local-map) [menu-bar debug]
690 (cons "Gud" (gud-new-keymap gud-menu-map)))
9bb4544b
RS
691 (local-set-key [menu-bar debug up] '("Up stack" . gud-up))
692 (local-set-key [menu-bar debug down] '("Down stack" . gud-down))
693 buf)))
13b80a60 694
10a4c11f 695;;;###autoload
a223b10d 696(defun dbx (command-line)
13b80a60
ER
697 "Run dbx on program FILE in buffer *gud-FILE*.
698The directory containing FILE becomes the initial working directory
699and source-file directory for your debugger."
f6376199 700 (interactive
a223b10d 701 (list (read-from-minibuffer "Run dbx (like this): "
f6376199
JB
702 (if (consp gud-dbx-history)
703 (car gud-dbx-history)
a223b10d 704 "dbx ")
f6376199
JB
705 nil nil
706 '(gud-dbx-history . 1))))
13eaa026 707
ee97eac3
RS
708 (cond
709 (gud-mips-p
710 (gud-common-init command-line 'gud-mipsdbx-massage-args
711 'gud-mipsdbx-marker-filter 'gud-dbx-find-file))
712 (gud-irix-p
713 (gud-common-init command-line 'gud-dbx-massage-args
714 'gud-irixdbx-marker-filter 'gud-dbx-find-file))
715 (t
716 (gud-common-init command-line 'gud-dbx-massage-args
717 'gud-dbx-marker-filter 'gud-dbx-find-file)))
5b08a462 718
13eaa026 719 (cond
f266485d 720 (gud-mips-p
2fb419e1
RS
721 (gud-def gud-up "up %p" "<" "Up (numeric arg) stack frames.")
722 (gud-def gud-down "down %p" ">" "Down (numeric arg) stack frames.")
13eaa026
RS
723 (gud-def gud-break "stop at \"%f\":%l"
724 "\C-b" "Set breakpoint at current line.")
725 (gud-def gud-finish "return" "\C-f" "Finish executing current function."))
f266485d
RS
726 (gud-irix-p
727 (gud-def gud-break "stop at \"%d%f\":%l"
728 "\C-b" "Set breakpoint at current line.")
729 (gud-def gud-finish "return" "\C-f" "Finish executing current function.")
2fb419e1
RS
730 (gud-def gud-up "up %p; printf \"\032\032%1ld:\",(long)$curline;file\n"
731 "<" "Up (numeric arg) stack frames.")
732 (gud-def gud-down "down %p; printf \"\032\032%1ld:\",(long)$curline;file\n"
733 ">" "Down (numeric arg) stack frames.")
f266485d
RS
734 ;; Make dbx give out the source location info that we need.
735 (process-send-string (get-buffer-process gud-comint-buffer)
e802811f 736 "printf \"\032\032%1d:\",(long)$curline;file\n"))
13eaa026 737 (t
2fb419e1
RS
738 (gud-def gud-up "up %p" "<" "Up (numeric arg) stack frames.")
739 (gud-def gud-down "down %p" ">" "Down (numeric arg) stack frames.")
13eaa026
RS
740 (gud-def gud-break "file \"%d%f\"\nstop at %l"
741 "\C-b" "Set breakpoint at current line.")))
742
dd8e46c7
RS
743 (gud-def gud-remove "clear %l" "\C-d" "Remove breakpoint at current line")
744 (gud-def gud-step "step %p" "\C-s" "Step one line with display.")
745 (gud-def gud-stepi "stepi %p" "\C-i" "Step one instruction with display.")
746 (gud-def gud-next "next %p" "\C-n" "Step one line (skip functions).")
747 (gud-def gud-cont "cont" "\C-r" "Continue with display.")
dd8e46c7 748 (gud-def gud-print "print %e" "\C-p" "Evaluate C expression at point.")
ee0155df 749
13eaa026 750 (setq comint-prompt-regexp "^[^)\n]*dbx) *")
f54877b2 751 (setq paragraph-start comint-prompt-regexp)
2291bfaa
RS
752 (local-set-key [menu-bar debug up] '("Up stack" . gud-up))
753 (local-set-key [menu-bar debug down] '("Down stack" . gud-down))
13b80a60
ER
754 (run-hooks 'dbx-mode-hook)
755 )
575661b1 756\f
6496f3d2
RS
757;; ======================================================================
758;; xdb (HP PARISC debugger) functions
759
f6376199
JB
760;;; History of argument lists passed to xdb.
761(defvar gud-xdb-history nil)
762
fce222c7
RS
763(defvar gud-xdb-directories nil
764 "*A list of directories that xdb should search for source code.
765If nil, only source files in the program directory
766will be known to xdb.
767
768The file names should be absolute, or relative to the directory
769containing the executable being debugged.")
770
a223b10d
RM
771(defun gud-xdb-massage-args (file args)
772 (nconc (let ((directories gud-xdb-directories)
773 (result nil))
774 (while directories
775 (setq result (cons (car directories) (cons "-d" result)))
776 (setq directories (cdr directories)))
dfbd82a6 777 (nreverse result))
a223b10d 778 args))
6496f3d2
RS
779
780(defun gud-xdb-file-name (f)
781 "Transform a relative pathname to a full pathname in xdb mode"
782 (let ((result nil))
783 (if (file-exists-p f)
784 (setq result (expand-file-name f))
fce222c7
RS
785 (let ((directories gud-xdb-directories))
786 (while directories
787 (let ((path (concat (car directories) "/" f)))
6496f3d2
RS
788 (if (file-exists-p path)
789 (setq result (expand-file-name path)
fce222c7
RS
790 directories nil)))
791 (setq directories (cdr directories)))))
6496f3d2
RS
792 result))
793
794;; xdb does not print the lines all at once, so we have to accumulate them
6496f3d2
RS
795(defun gud-xdb-marker-filter (string)
796 (let (result)
797 (if (or (string-match comint-prompt-regexp string)
798 (string-match ".*\012" string))
f266485d
RS
799 (setq result (concat gud-marker-acc string)
800 gud-marker-acc "")
801 (setq gud-marker-acc (concat gud-marker-acc string)))
6496f3d2
RS
802 (if result
803 (if (or (string-match "\\([^\n \t:]+\\): [^:]+: \\([0-9]+\\):" result)
804 (string-match "[^: \t]+:[ \t]+\\([^:]+\\): [^:]+: \\([0-9]+\\):"
805 result))
806 (let ((line (string-to-int
807 (substring result (match-beginning 2) (match-end 2))))
808 (file (gud-xdb-file-name
809 (substring result (match-beginning 1) (match-end 1)))))
810 (if file
811 (setq gud-last-frame (cons file line))))))
812 (or result "")))
813
6496f3d2 814(defun gud-xdb-find-file (f)
9bb4544b
RS
815 (save-excursion
816 (let ((realf (gud-xdb-file-name f)))
817 (if realf
818 (let ((buf (find-file-noselect realf)))
819 (set-buffer buf)
23a3aa0a
RS
820 (use-local-map (gud-new-keymap (current-local-map)))
821 (define-key (current-local-map) [menu-bar debug]
822 (cons "Gud" (gud-new-keymap gud-menu-map)))
9bb4544b
RS
823 (local-set-key [menu-bar debug tbreak]
824 '("Temporary breakpoint" . gud-tbreak))
825 (local-set-key [menu-bar debug finish]
826 '("Finish function" . gud-finish))
827 (local-set-key [menu-bar debug up] '("Up stack" . gud-up))
828 (local-set-key [menu-bar debug up] '("Up stack" . gud-up))
829 (local-set-key [menu-bar debug down] '("Down stack" . gud-down))
830 buf)
831 nil))))
6496f3d2
RS
832
833;;;###autoload
a223b10d 834(defun xdb (command-line)
6496f3d2
RS
835 "Run xdb on program FILE in buffer *gud-FILE*.
836The directory containing FILE becomes the initial working directory
837and source-file directory for your debugger.
838
fce222c7 839You can set the variable 'gud-xdb-directories' to a list of program source
6496f3d2 840directories if your program contains sources from more than one directory."
f6376199 841 (interactive
a223b10d 842 (list (read-from-minibuffer "Run xdb (like this): "
f6376199
JB
843 (if (consp gud-xdb-history)
844 (car gud-xdb-history)
a223b10d 845 "xdb ")
f6376199
JB
846 nil nil
847 '(gud-xdb-history . 1))))
6496f3d2 848
ee97eac3
RS
849 (gud-common-init command-line 'gud-xdb-massage-args
850 'gud-xdb-marker-filter 'gud-xdb-find-file)
6496f3d2
RS
851
852 (gud-def gud-break "b %f:%l" "\C-b" "Set breakpoint at current line.")
853 (gud-def gud-tbreak "b %f:%l\\t" "\C-t"
854 "Set temporary breakpoint at current line.")
855 (gud-def gud-remove "db" "\C-d" "Remove breakpoint at current line")
856 (gud-def gud-step "s %p" "\C-s" "Step one line with display.")
857 (gud-def gud-next "S %p" "\C-n" "Step one line (skip functions).")
858 (gud-def gud-cont "c" "\C-r" "Continue with display.")
859 (gud-def gud-up "up %p" "<" "Up (numeric arg) stack frames.")
860 (gud-def gud-down "down %p" ">" "Down (numeric arg) stack frames.")
861 (gud-def gud-finish "bu\\t" "\C-f" "Finish executing current function.")
862 (gud-def gud-print "p %e" "\C-p" "Evaluate C expression at point.")
863
864 (setq comint-prompt-regexp "^>")
f54877b2 865 (setq paragraph-start comint-prompt-regexp)
2291bfaa
RS
866 (local-set-key [menu-bar debug tbreak] '("Temporary breakpoint" . gud-tbreak))
867 (local-set-key [menu-bar debug finish] '("Finish function" . gud-finish))
868 (local-set-key [menu-bar debug up] '("Up stack" . gud-up))
869 (local-set-key [menu-bar debug down] '("Down stack" . gud-down))
6496f3d2 870 (run-hooks 'xdb-mode-hook))
575661b1
RS
871\f
872;; ======================================================================
873;; perldb functions
874
875;;; History of argument lists passed to perldb.
876(defvar gud-perldb-history nil)
877
878(defun gud-perldb-massage-args (file args)
dfbd82a6 879 (cons "-d" (cons "-emacs" args)))
575661b1
RS
880
881;; There's no guarantee that Emacs will hand the filter the entire
882;; marker at once; it could be broken up across several strings. We
883;; might even receive a big chunk with several markers in it. If we
884;; receive a chunk of text which looks like it might contain the
885;; beginning of a marker, we save it here between calls to the
886;; filter.
887(defvar gud-perldb-marker-acc "")
888
889(defun gud-perldb-marker-filter (string)
bed6a98d
RS
890 (setq gud-marker-acc (concat gud-marker-acc string))
891 (let ((output ""))
892
893 ;; Process all the complete markers in this chunk.
894 (while (string-match "\032\032\\([^:\n]*\\):\\([0-9]*\\):.*\n"
895 gud-marker-acc)
896 (setq
897
898 ;; Extract the frame position from the marker.
899 gud-last-frame
900 (cons (substring gud-marker-acc (match-beginning 1) (match-end 1))
901 (string-to-int (substring gud-marker-acc
902 (match-beginning 2)
903 (match-end 2))))
904
905 ;; Append any text before the marker to the output we're going
906 ;; to return - we don't include the marker in this text.
907 output (concat output
908 (substring gud-marker-acc 0 (match-beginning 0)))
909
910 ;; Set the accumulator to the remaining text.
911 gud-marker-acc (substring gud-marker-acc (match-end 0))))
912
913 ;; Does the remaining text look like it might end with the
914 ;; beginning of another marker? If it does, then keep it in
915 ;; gud-marker-acc until we receive the rest of it. Since we
916 ;; know the full marker regexp above failed, it's pretty simple to
917 ;; test for marker starts.
918 (if (string-match "\032.*\\'" gud-marker-acc)
919 (progn
920 ;; Everything before the potential marker start can be output.
921 (setq output (concat output (substring gud-marker-acc
922 0 (match-beginning 0))))
923
924 ;; Everything after, we save, to combine with later input.
925 (setq gud-marker-acc
926 (substring gud-marker-acc (match-beginning 0))))
927
928 (setq output (concat output gud-marker-acc)
929 gud-marker-acc ""))
930
931 output))
575661b1
RS
932
933(defun gud-perldb-find-file (f)
9bb4544b
RS
934 (save-excursion
935 (let ((buf (find-file-noselect f)))
936 (set-buffer buf)
937 (define-key (current-local-map) [menu-bar debug] (cons "Gud" (copy-keymap gud-menu-map)))
938 buf)))
575661b1
RS
939
940;;;###autoload
941(defun perldb (command-line)
942 "Run perldb on program FILE in buffer *gud-FILE*.
943The directory containing FILE becomes the initial working directory
944and source-file directory for your debugger."
945 (interactive
946 (list (read-from-minibuffer "Run perldb (like this): "
947 (if (consp gud-perldb-history)
948 (car gud-perldb-history)
2c32e5c6 949 "perl ")
575661b1
RS
950 nil nil
951 '(gud-perldb-history . 1))))
575661b1 952
ee97eac3
RS
953 (gud-common-init command-line 'gud-perldb-massage-args
954 'gud-perldb-marker-filter 'gud-perldb-find-file)
575661b1 955
2c32e5c6
RS
956 (gud-def gud-break "b %l" "\C-b" "Set breakpoint at current line.")
957 (gud-def gud-remove "d %l" "\C-d" "Remove breakpoint at current line")
958 (gud-def gud-step "s" "\C-s" "Step one source line with display.")
959 (gud-def gud-next "n" "\C-n" "Step one line (skip functions).")
960 (gud-def gud-cont "c" "\C-r" "Continue with display.")
961; (gud-def gud-finish "finish" "\C-f" "Finish executing current function.")
962; (gud-def gud-up "up %p" "<" "Up N stack frames (numeric arg).")
963; (gud-def gud-down "down %p" ">" "Down N stack frames (numeric arg).")
964 (gud-def gud-print "%e" "\C-p" "Evaluate perl expression at point.")
965
966 (setq comint-prompt-regexp "^ DB<[0-9]+> ")
f54877b2 967 (setq paragraph-start comint-prompt-regexp)
2c32e5c6 968 (run-hooks 'perldb-mode-hook)
575661b1 969 )
6496f3d2 970
13b80a60
ER
971;;
972;; End of debugger-specific information
10a4c11f 973;;
13b80a60 974
575661b1 975\f
53eb3a97
JB
976;;; When we send a command to the debugger via gud-call, it's annoying
977;;; to see the command and the new prompt inserted into the debugger's
978;;; buffer; we have other ways of knowing the command has completed.
979;;;
980;;; If the buffer looks like this:
981;;; --------------------
982;;; (gdb) set args foo bar
983;;; (gdb) -!-
984;;; --------------------
985;;; (the -!- marks the location of point), and we type `C-x SPC' in a
986;;; source file to set a breakpoint, we want the buffer to end up like
987;;; this:
988;;; --------------------
989;;; (gdb) set args foo bar
990;;; Breakpoint 1 at 0x92: file make-docfile.c, line 49.
991;;; (gdb) -!-
992;;; --------------------
993;;; Essentially, the old prompt is deleted, and the command's output
994;;; and the new prompt take its place.
995;;;
996;;; Not echoing the command is easy enough; you send it directly using
997;;; process-send-string, and it never enters the buffer. However,
998;;; getting rid of the old prompt is trickier; you don't want to do it
999;;; when you send the command, since that will result in an annoying
1000;;; flicker as the prompt is deleted, redisplay occurs while Emacs
1001;;; waits for a response from the debugger, and the new prompt is
1002;;; inserted. Instead, we'll wait until we actually get some output
1003;;; from the subprocess before we delete the prompt. If the command
1004;;; produced no output other than a new prompt, that prompt will most
1005;;; likely be in the first chunk of output received, so we will delete
1006;;; the prompt and then replace it with an identical one. If the
1007;;; command produces output, the prompt is moving anyway, so the
1008;;; flicker won't be annoying.
1009;;;
1010;;; So - when we want to delete the prompt upon receipt of the next
1011;;; chunk of debugger output, we position gud-delete-prompt-marker at
1012;;; the start of the prompt; the process filter will notice this, and
1013;;; delete all text between it and the process output marker. If
1014;;; gud-delete-prompt-marker points nowhere, we leave the current
1015;;; prompt alone.
1016(defvar gud-delete-prompt-marker nil)
1017
13b80a60
ER
1018\f
1019(defun gud-mode ()
1020 "Major mode for interacting with an inferior debugger process.
24d725c2 1021
6496f3d2
RS
1022 You start it up with one of the commands M-x gdb, M-x sdb, M-x dbx,
1023or M-x xdb. Each entry point finishes by executing a hook; `gdb-mode-hook',
1024`sdb-mode-hook', `dbx-mode-hook' or `xdb-mode-hook' respectively.
24d725c2 1025
ee0155df
ER
1026After startup, the following commands are available in both the GUD
1027interaction buffer and any source buffer GUD visits due to a breakpoint stop
1028or step operation:
13b80a60 1029
ee0155df
ER
1030\\[gud-break] sets a breakpoint at the current file and line. In the
1031GUD buffer, the current file and line are those of the last breakpoint or
1032step. In a source buffer, they are the buffer's file and current line.
1033
45025813
ER
1034\\[gud-remove] removes breakpoints on the current file and line.
1035
ee0155df 1036\\[gud-refresh] displays in the source window the last line referred to
24d725c2 1037in the gud buffer.
13b80a60 1038
ee0155df
ER
1039\\[gud-step], \\[gud-next], and \\[gud-stepi] do a step-one-line,
1040step-one-line (not entering function calls), and step-one-instruction
1041and then update the source window with the current file and position.
1042\\[gud-cont] continues execution.
13b80a60 1043
ee0155df
ER
1044\\[gud-print] tries to find the largest C lvalue or function-call expression
1045around point, and sends it to the debugger for value display.
24d725c2 1046
6496f3d2
RS
1047The above commands are common to all supported debuggers except xdb which
1048does not support stepping instructions.
24d725c2 1049
6496f3d2 1050Under gdb, sdb and xdb, \\[gud-tbreak] behaves exactly like \\[gud-break],
ee0155df
ER
1051except that the breakpoint is temporary; that is, it is removed when
1052execution stops on it.
24d725c2 1053
6496f3d2 1054Under gdb, dbx, and xdb, \\[gud-up] pops up through an enclosing stack
ee0155df 1055frame. \\[gud-down] drops back down through one.
24d725c2 1056
6496f3d2 1057If you are using gdb or xdb, \\[gud-finish] runs execution to the return from
ee0155df 1058the current function and stops.
24d725c2 1059
dcec1a3b
RS
1060All the keystrokes above are accessible in the GUD buffer
1061with the prefix C-c, and in all buffers through the prefix C-x C-a.
45025813 1062
ee0155df
ER
1063All pre-defined functions for which the concept make sense repeat
1064themselves the appropriate number of times if you give a prefix
1065argument.
13b80a60 1066
dcec1a3b 1067You may use the `gud-def' macro in the initialization hook to define other
ee0155df 1068commands.
13b80a60 1069
24d725c2
ER
1070Other commands for interacting with the debugger process are inherited from
1071comint mode, which see."
13b80a60
ER
1072 (interactive)
1073 (comint-mode)
13b80a60
ER
1074 (setq major-mode 'gud-mode)
1075 (setq mode-name "Debugger")
0b358e64 1076 (setq mode-line-process '(":%s"))
23a3aa0a 1077 (use-local-map (gud-new-keymap comint-mode-map))
2b64612d 1078 (define-key (current-local-map) "\C-c\C-l" 'gud-refresh)
2291bfaa 1079 (define-key (current-local-map) [menu-bar debug]
23a3aa0a 1080 (cons "Gud" (gud-new-keymap gud-menu-map)))
13b80a60
ER
1081 (make-local-variable 'gud-last-frame)
1082 (setq gud-last-frame nil)
1083 (make-local-variable 'comint-prompt-regexp)
f54877b2 1084 (make-local-variable 'paragraph-start)
53eb3a97
JB
1085 (make-local-variable 'gud-delete-prompt-marker)
1086 (setq gud-delete-prompt-marker (make-marker))
ee97eac3 1087 (run-hooks 'gud-mode-hook))
13b80a60 1088
a223b10d
RM
1089;; Chop STRING into words separated by SPC or TAB and return a list of them.
1090(defun gud-chop-words (string)
1091 (let ((i 0) (beg 0)
1092 (len (length string))
1093 (words nil))
1094 (while (< i len)
1095 (if (memq (aref string i) '(?\t ? ))
1096 (progn
1097 (setq words (cons (substring string beg i) words)
1098 beg (1+ i))
1099 (while (and (< beg len) (memq (aref string beg) '(?\t ? )))
1100 (setq beg (1+ beg)))
1101 (setq i (1+ beg)))
1102 (setq i (1+ i))))
1103 (if (< beg len)
1104 (setq words (cons (substring string beg) words)))
1105 (nreverse words)))
1106
1107;; Perform initializations common to all debuggers.
ee97eac3
RS
1108;; The first arg is the specified command line,
1109;; which starts with the program to debug.
1110;; The other three args specify the values to use
1111;; for local variables in the debugger buffer.
1112(defun gud-common-init (command-line massage-args marker-filter find-file)
a223b10d
RM
1113 (let* ((words (gud-chop-words command-line))
1114 (program (car words))
dfbd82a6
RS
1115 ;; Extract the file name from WORDS
1116 ;; and put t in its place.
1117 ;; Later on we will put the modified file name arg back there.
a223b10d
RM
1118 (file-word (let ((w (cdr words)))
1119 (while (and w (= ?- (aref (car w) 0)))
1120 (setq w (cdr w)))
dfbd82a6
RS
1121 (prog1 (car w)
1122 (setcar w t))))
0ec5b01d
RS
1123 (file-subst
1124 (and file-word (substitute-in-file-name file-word)))
dfbd82a6 1125 (args (cdr words))
0ec5b01d
RS
1126 ;; If a directory was specified, expand the file name.
1127 ;; Otherwise, don't expand it, so GDB can use the PATH.
1128 ;; A file name without directory is literally valid
1129 ;; only if the file exists in ., and in that case,
1130 ;; omitting the expansion here has no visible effect.
52b85866 1131 (file (and file-word
0ec5b01d
RS
1132 (if (file-name-directory file-subst)
1133 (expand-file-name file-subst)
1134 file-subst)))
52b85866 1135 (filepart (and file-word (file-name-nondirectory file))))
ee97eac3 1136 (switch-to-buffer (concat "*gud-" filepart "*"))
0ec5b01d
RS
1137 ;; Set default-directory to the file's directory.
1138 (and file-word
1139 ;; Don't set default-directory if no directory was specified.
1140 ;; In that case, either the file is found in the current directory,
1141 ;; in which case this setq is a no-op,
1142 ;; or it is found by searching PATH,
1143 ;; in which case we don't know what directory it was found in.
1144 (file-name-directory file)
1145 (setq default-directory (file-name-directory file)))
ee97eac3
RS
1146 (or (bolp) (newline))
1147 (insert "Current directory is " default-directory "\n")
dfbd82a6
RS
1148 ;; Put the substituted and expanded file name back in its place.
1149 (let ((w args))
1150 (while (and w (not (eq (car w) t)))
1151 (setq w (cdr w)))
1152 (setcar w file))
ee97eac3 1153 (apply 'make-comint (concat "gud-" filepart) program nil
dfbd82a6 1154 (if file-word (funcall massage-args file args) args)))
ee97eac3 1155 ;; Since comint clobbered the mode, we don't set it until now.
13b80a60 1156 (gud-mode)
ee97eac3
RS
1157 (make-local-variable 'gud-marker-filter)
1158 (setq gud-marker-filter marker-filter)
1159 (make-local-variable 'gud-find-file)
1160 (setq gud-find-file find-file)
1161
13b80a60
ER
1162 (set-process-filter (get-buffer-process (current-buffer)) 'gud-filter)
1163 (set-process-sentinel (get-buffer-process (current-buffer)) 'gud-sentinel)
13b80a60
ER
1164 (gud-set-buffer)
1165 )
1166
1167(defun gud-set-buffer ()
1168 (cond ((eq major-mode 'gud-mode)
ee0155df
ER
1169 (setq gud-comint-buffer (current-buffer)))))
1170
1171;; These functions are responsible for inserting output from your debugger
1172;; into the buffer. The hard work is done by the method that is
1173;; the value of gud-marker-filter.
13b80a60 1174
ee0155df 1175(defun gud-filter (proc string)
13b80a60 1176 ;; Here's where the actual buffer insertion is done
c561a0cb
RS
1177 (let (output)
1178 (if (buffer-name (process-buffer proc))
1179 (save-excursion
1180 (set-buffer (process-buffer proc))
1181 ;; If we have been so requested, delete the debugger prompt.
1182 (if (marker-buffer gud-delete-prompt-marker)
1183 (progn
1184 (delete-region (process-mark proc) gud-delete-prompt-marker)
1185 (set-marker gud-delete-prompt-marker nil)))
1186 ;; Save the process output, checking for source file markers.
1187 (setq output (gud-marker-filter string))
1188 ;; Check for a filename-and-line number.
1189 ;; Don't display the specified file
1190 ;; unless (1) point is at or after the position where output appears
1191 ;; and (2) this buffer is on the screen.
1192 (if (and gud-last-frame
1193 (>= (point) (process-mark proc))
1194 (get-buffer-window (current-buffer)))
1195 (gud-display-frame))
1196 ;; Let the comint filter do the actual insertion.
1197 ;; That lets us inherit various comint features.
1198 (comint-output-filter proc output)))))
13b80a60
ER
1199
1200(defun gud-sentinel (proc msg)
1201 (cond ((null (buffer-name (process-buffer proc)))
1202 ;; buffer killed
1203 ;; Stop displaying an arrow in a source file.
1204 (setq overlay-arrow-position nil)
1205 (set-process-buffer proc nil))
1206 ((memq (process-status proc) '(signal exit))
1207 ;; Stop displaying an arrow in a source file.
1208 (setq overlay-arrow-position nil)
1209 ;; Fix the mode line.
1210 (setq mode-line-process
0b358e64 1211 (concat ":"
13b80a60
ER
1212 (symbol-name (process-status proc))))
1213 (let* ((obuf (current-buffer)))
1214 ;; save-excursion isn't the right thing if
1215 ;; process-buffer is current-buffer
1216 (unwind-protect
1217 (progn
1218 ;; Write something in *compilation* and hack its mode line,
1219 (set-buffer (process-buffer proc))
1220 ;; Force mode line redisplay soon
1221 (set-buffer-modified-p (buffer-modified-p))
1222 (if (eobp)
1223 (insert ?\n mode-name " " msg)
1224 (save-excursion
1225 (goto-char (point-max))
1226 (insert ?\n mode-name " " msg)))
1227 ;; If buffer and mode line will show that the process
1228 ;; is dead, we can delete it now. Otherwise it
1229 ;; will stay around until M-x list-processes.
1230 (delete-process proc))
1231 ;; Restore old buffer, but don't restore old point
1232 ;; if obuf is the gud buffer.
1233 (set-buffer obuf))))))
1234
13b80a60
ER
1235(defun gud-display-frame ()
1236 "Find and obey the last filename-and-line marker from the debugger.
1237Obeying it means displaying in another window the specified file and line."
1238 (interactive)
1239 (if gud-last-frame
ee0155df 1240 (progn
13b80a60
ER
1241 (gud-set-buffer)
1242 (gud-display-line (car gud-last-frame) (cdr gud-last-frame))
32ab4c10
JB
1243 (setq gud-last-last-frame gud-last-frame
1244 gud-last-frame nil))))
13b80a60
ER
1245
1246;; Make sure the file named TRUE-FILE is in a buffer that appears on the screen
1247;; and that its line LINE is visible.
1248;; Put the overlay-arrow on the line LINE in that buffer.
ee0155df
ER
1249;; Most of the trickiness in here comes from wanting to preserve the current
1250;; region-restriction if that's possible. We use an explicit display-buffer
1251;; to get around the fact that this is called inside a save-excursion.
13b80a60
ER
1252
1253(defun gud-display-line (true-file line)
8f6c93e2
RS
1254 (let* ((last-nonmenu-event t) ; Prevent use of dialog box for questions.
1255 (buffer (gud-find-file true-file))
ee0155df 1256 (window (display-buffer buffer))
13b80a60 1257 (pos))
dd8e46c7
RS
1258;;; (if (equal buffer (current-buffer))
1259;;; nil
1260;;; (setq buffer-read-only nil))
13b80a60 1261 (save-excursion
dd8e46c7 1262;;; (setq buffer-read-only t)
13b80a60
ER
1263 (set-buffer buffer)
1264 (save-restriction
1265 (widen)
1266 (goto-line line)
1267 (setq pos (point))
1268 (setq overlay-arrow-string "=>")
1269 (or overlay-arrow-position
1270 (setq overlay-arrow-position (make-marker)))
1271 (set-marker overlay-arrow-position (point) (current-buffer)))
1272 (cond ((or (< pos (point-min)) (> pos (point-max)))
1273 (widen)
1274 (goto-char pos))))
1275 (set-window-point window overlay-arrow-position)))
53eb3a97 1276
ee0155df
ER
1277;;; The gud-call function must do the right thing whether its invoking
1278;;; keystroke is from the GUD buffer itself (via major-mode binding)
5b08a462
ER
1279;;; or a C buffer. In the former case, we want to supply data from
1280;;; gud-last-frame. Here's how we do it:
13b80a60 1281
ee0155df 1282(defun gud-format-command (str arg)
13eaa026
RS
1283 (let ((insource (not (eq (current-buffer) gud-comint-buffer)))
1284 (frame (or gud-last-frame gud-last-last-frame))
1285 result)
1286 (while (and str (string-match "\\([^%]*\\)%\\([adeflp]\\)" str))
1287 (let ((key (string-to-char (substring str (match-beginning 2))))
1288 subst)
1289 (cond
1290 ((eq key ?f)
1291 (setq subst (file-name-nondirectory (if insource
1292 (buffer-file-name)
1293 (car frame)))))
1294 ((eq key ?d)
1295 (setq subst (file-name-directory (if insource
7f359a21 1296 (buffer-file-name)
13eaa026
RS
1297 (car frame)))))
1298 ((eq key ?l)
1299 (setq subst (if insource
1300 (save-excursion
1301 (beginning-of-line)
1302 (save-restriction (widen)
1303 (1+ (count-lines 1 (point)))))
1304 (cdr frame))))
1305 ((eq key ?e)
1306 (setq subst (find-c-expr)))
1307 ((eq key ?a)
1308 (setq subst (gud-read-address)))
1309 ((eq key ?p)
1310 (setq subst (if arg (int-to-string arg) ""))))
1311 (setq result (concat result
1312 (substring str (match-beginning 1) (match-end 1))
1313 subst)))
1314 (setq str (substring str (match-end 2))))
1315 ;; There might be text left in STR when the loop ends.
1316 (concat result str)))
13b80a60 1317
6bde8427 1318(defun gud-read-address ()
13b80a60
ER
1319 "Return a string containing the core-address found in the buffer at point."
1320 (save-excursion
6bde8427 1321 (let ((pt (point)) found begin)
ee0155df 1322 (setq found (if (search-backward "0x" (- pt 7) t) (point)))
6bde8427
JB
1323 (cond
1324 (found (forward-char 2)
1325 (buffer-substring found
1326 (progn (re-search-forward "[^0-9a-f]")
1327 (forward-char -1)
1328 (point))))
1329 (t (setq begin (progn (re-search-backward "[^0-9]")
1330 (forward-char 1)
1331 (point)))
1332 (forward-char 1)
1333 (re-search-forward "[^0-9]")
1334 (forward-char -1)
1335 (buffer-substring begin (point)))))))
13b80a60 1336
ee0155df
ER
1337(defun gud-call (fmt &optional arg)
1338 (let ((msg (gud-format-command fmt arg)))
1339 (message "Command: %s" msg)
1340 (sit-for 0)
1341 (gud-basic-call msg)))
13b80a60 1342
ee0155df
ER
1343(defun gud-basic-call (command)
1344 "Invoke the debugger COMMAND displaying source in other window."
1345 (interactive)
1346 (gud-set-buffer)
1347 (let ((command (concat command "\n"))
1348 (proc (get-buffer-process gud-comint-buffer)))
4b8b296e 1349 (or proc (error "Current buffer has no process"))
ee0155df
ER
1350 ;; Arrange for the current prompt to get deleted.
1351 (save-excursion
1352 (set-buffer gud-comint-buffer)
1353 (goto-char (process-mark proc))
1354 (beginning-of-line)
1355 (if (looking-at comint-prompt-regexp)
1356 (set-marker gud-delete-prompt-marker (point))))
1357 (process-send-string proc command)))
1358
1359(defun gud-refresh (&optional arg)
1360 "Fix up a possibly garbled display, and redraw the arrow."
13b80a60 1361 (interactive "P")
ee0155df 1362 (recenter arg)
32ab4c10 1363 (or gud-last-frame (setq gud-last-frame gud-last-last-frame))
ee0155df 1364 (gud-display-frame))
dcec1a3b 1365\f
ee0155df
ER
1366;;; Code for parsing expressions out of C code. The single entry point is
1367;;; find-c-expr, which tries to return an lvalue expression from around point.
1368;;;
1369;;; The rest of this file is a hacked version of gdbsrc.el by
1370;;; Debby Ayers <ayers@asc.slb.com>,
1371;;; Rich Schaefer <schaefer@asc.slb.com> Schlumberger, Austin, Tx.
ee0155df
ER
1372
1373(defun find-c-expr ()
1374 "Returns the C expr that surrounds point."
1375 (interactive)
1376 (save-excursion
1377 (let ((p) (expr) (test-expr))
1378 (setq p (point))
1379 (setq expr (expr-cur))
1380 (setq test-expr (expr-prev))
1381 (while (expr-compound test-expr expr)
1382 (setq expr (cons (car test-expr) (cdr expr)))
1383 (goto-char (car expr))
dcec1a3b 1384 (setq test-expr (expr-prev)))
ee0155df
ER
1385 (goto-char p)
1386 (setq test-expr (expr-next))
1387 (while (expr-compound expr test-expr)
1388 (setq expr (cons (car expr) (cdr test-expr)))
1389 (setq test-expr (expr-next))
1390 )
dcec1a3b 1391 (buffer-substring (car expr) (cdr expr)))))
ee0155df
ER
1392
1393(defun expr-cur ()
1394 "Returns the expr that point is in; point is set to beginning of expr.
1395The expr is represented as a cons cell, where the car specifies the point in
1396the current buffer that marks the beginning of the expr and the cdr specifies
dcec1a3b 1397the character after the end of the expr."
ee0155df 1398 (let ((p (point)) (begin) (end))
dcec1a3b 1399 (expr-backward-sexp)
ee0155df 1400 (setq begin (point))
dcec1a3b 1401 (expr-forward-sexp)
ee0155df
ER
1402 (setq end (point))
1403 (if (>= p end)
1404 (progn
1405 (setq begin p)
1406 (goto-char p)
dcec1a3b 1407 (expr-forward-sexp)
ee0155df
ER
1408 (setq end (point))
1409 )
1410 )
1411 (goto-char begin)
dcec1a3b 1412 (cons begin end)))
ee0155df 1413
dcec1a3b
RS
1414(defun expr-backward-sexp ()
1415 "Version of `backward-sexp' that catches errors."
ee0155df
ER
1416 (condition-case nil
1417 (backward-sexp)
1418 (error t)))
1419
dcec1a3b
RS
1420(defun expr-forward-sexp ()
1421 "Version of `forward-sexp' that catches errors."
ee0155df
ER
1422 (condition-case nil
1423 (forward-sexp)
1424 (error t)))
1425
1426(defun expr-prev ()
1427 "Returns the previous expr, point is set to beginning of that expr.
1428The expr is represented as a cons cell, where the car specifies the point in
1429the current buffer that marks the beginning of the expr and the cdr specifies
1430the character after the end of the expr"
1431 (let ((begin) (end))
dcec1a3b 1432 (expr-backward-sexp)
ee0155df 1433 (setq begin (point))
dcec1a3b 1434 (expr-forward-sexp)
ee0155df
ER
1435 (setq end (point))
1436 (goto-char begin)
1437 (cons begin end)))
1438
1439(defun expr-next ()
1440 "Returns the following expr, point is set to beginning of that expr.
1441The expr is represented as a cons cell, where the car specifies the point in
1442the current buffer that marks the beginning of the expr and the cdr specifies
dcec1a3b 1443the character after the end of the expr."
ee0155df 1444 (let ((begin) (end))
dcec1a3b
RS
1445 (expr-forward-sexp)
1446 (expr-forward-sexp)
ee0155df 1447 (setq end (point))
dcec1a3b 1448 (expr-backward-sexp)
ee0155df 1449 (setq begin (point))
dcec1a3b 1450 (cons begin end)))
ee0155df
ER
1451
1452(defun expr-compound-sep (span-start span-end)
1453 "Returns '.' for '->' & '.', returns ' ' for white space,
eb8c3be9 1454returns '?' for other punctuation."
ee0155df
ER
1455 (let ((result ? )
1456 (syntax))
1457 (while (< span-start span-end)
1458 (setq syntax (char-syntax (char-after span-start)))
1459 (cond
1460 ((= syntax ? ) t)
1461 ((= syntax ?.) (setq syntax (char-after span-start))
1462 (cond
1463 ((= syntax ?.) (setq result ?.))
1464 ((and (= syntax ?-) (= (char-after (+ span-start 1)) ?>))
1465 (setq result ?.)
1466 (setq span-start (+ span-start 1)))
1467 (t (setq span-start span-end)
1468 (setq result ??)))))
1469 (setq span-start (+ span-start 1)))
dcec1a3b 1470 result))
ee0155df
ER
1471
1472(defun expr-compound (first second)
dcec1a3b
RS
1473 "Non-nil if concatenating FIRST and SECOND makes a single C token.
1474The two exprs are represented as a cons cells, where the car
ee0155df 1475specifies the point in the current buffer that marks the beginning of the
dcec1a3b 1476expr and the cdr specifies the character after the end of the expr.
ee0155df
ER
1477Link exprs of the form:
1478 Expr -> Expr
1479 Expr . Expr
1480 Expr (Expr)
1481 Expr [Expr]
1482 (Expr) Expr
1483 [Expr] Expr"
1484 (let ((span-start (cdr first))
1485 (span-end (car second))
1486 (syntax))
1487 (setq syntax (expr-compound-sep span-start span-end))
1488 (cond
1489 ((= (car first) (car second)) nil)
1490 ((= (cdr first) (cdr second)) nil)
1491 ((= syntax ?.) t)
1492 ((= syntax ? )
1493 (setq span-start (char-after (- span-start 1)))
1494 (setq span-end (char-after span-end))
1495 (cond
1496 ((= span-start ?) ) t )
1497 ((= span-start ?] ) t )
1498 ((= span-end ?( ) t )
1499 ((= span-end ?[ ) t )
1500 (t nil))
1501 )
dcec1a3b 1502 (t nil))))
5b08a462 1503
96f4e22e
RM
1504(provide 'gud)
1505
f961a17c 1506;;; gud.el ends here