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