(pr-get-symbol): Define during compile.
[bpt/emacs.git] / lisp / gud.el
CommitLineData
c3fd0eea 1;;; gud.el --- Grand Unified Debugger mode for running GDB and other debuggers
f961a17c 2
ee0155df 3;; Author: Eric S. Raymond <esr@snark.thyrsus.com>
8ba194fc 4;; Maintainer: FSF
f961a17c
ER
5;; Keywords: unix, tools
6
e78e1cd1 7;; Copyright (C) 1992,93,94,95,96,1998,2000,2002 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
c6094cae 18;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13b80a60
ER
19;; GNU General Public License for more details.
20
21;; You should have received a copy of the GNU General Public License
c6094cae 22;; along with GNU Emacs; see the file COPYING. If not, write to the
b578f267
EN
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>
f4b643a1 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
f4b643a1 36;; a menu. Brian D. Carlstrom <bdc@ai.mit.edu> combined the IRIX kluge with
c6094cae 37;; the gud-xdb-directories hack producing gud-dbx-directories. Derek L. Davies
c3fd0eea 38;; <ddavies@world.std.com> added support for jdb (Java debugger.)
13b80a60 39
f961a17c
ER
40;;; Code:
41
13b80a60 42(require 'comint)
e8a57935 43(require 'etags)
13b80a60 44
ee0155df 45;; ======================================================================
5b08a462 46;; GUD commands must be visible in C buffers visited by GUD
ee0155df 47
69c1dd37 48(defgroup gud nil
f4b643a1 49 "Grand Unified Debugger mode for gdb and other debuggers under Emacs.
d4c2acb9 50Supported debuggers include gdb, sdb, dbx, xdb, perldb, pdb (Python), jdb, and bash."
69c1dd37
RS
51 :group 'unix
52 :group 'tools)
53
54
55(defcustom gud-key-prefix "\C-x\C-a"
56 "Prefix of all GUD commands valid in C buffers."
57 :type 'string
58 :group 'gud)
ee0155df 59
5b08a462 60(global-set-key (concat gud-key-prefix "\C-l") 'gud-refresh)
16776e8d 61(define-key ctl-x-map " " 'gud-break) ;; backward compatibility hack
ee0155df 62
ee97eac3
RS
63(defvar gud-marker-filter nil)
64(put 'gud-marker-filter 'permanent-local t)
65(defvar gud-find-file nil)
66(put 'gud-find-file 'permanent-local t)
67
ee97eac3
RS
68(defun gud-marker-filter (&rest args)
69 (apply gud-marker-filter args))
70
c157af51
SM
71(defvar gud-minor-mode nil)
72(put 'gud-minor-mode 'permanent-local t)
73
7461cbeb
NR
74(defvar gud-keep-buffer nil)
75
c157af51
SM
76(defun gud-symbol (sym &optional soft minor-mode)
77 "Return the symbol used for SYM in MINOR-MODE.
78MINOR-MODE defaults to `gud-minor-mode.
79The symbol returned is `gud-<MINOR-MODE>-<SYM>'.
80If SOFT is non-nil, returns nil if the symbol doesn't already exist."
81 (unless (or minor-mode gud-minor-mode) (error "Gud internal error"))
82 (funcall (if soft 'intern-soft 'intern)
83 (format "gud-%s-%s" (or minor-mode gud-minor-mode) sym)))
84
85(defun gud-val (sym &optional minor-mode)
86 "Return the value of `gud-symbol' SYM. Default to nil."
87 (let ((sym (gud-symbol sym t minor-mode)))
88 (if (boundp sym) (symbol-value sym))))
89
b94a3001
SM
90(defvar gud-running nil
91 "Non-nil if debuggee is running.
92Used to grey out relevant toolbar icons.")
c157af51
SM
93
94(easy-mmode-defmap gud-menu-map
95 '(([refresh] "Refresh" . gud-refresh)
f36ca832 96 ([run] menu-item "Run" gud-run
b94a3001 97 :enable (and (not gud-running)
b0592138 98 (memq gud-minor-mode '(gdba gdb jdb))))
fcf58c9b 99 ([goto] menu-item "Continue to selection" gud-until
b94a3001 100 :enable (and (not gud-running)
1a21c370
NR
101 (memq gud-minor-mode '(gdba gdb))))
102 ([remove] menu-item "Remove Breakpoint" gud-remove
b94a3001 103 :enable (not gud-running))
c157af51 104 ([tbreak] menu-item "Temporary Breakpoint" gud-tbreak
d4c2acb9 105 :enable (memq gud-minor-mode '(gdba gdb sdb xdb bashdb)))
1a21c370 106 ([break] menu-item "Set Breakpoint" gud-break
b94a3001 107 :enable (not gud-running))
c157af51 108 ([up] menu-item "Up Stack" gud-up
9f6991fd 109 :enable (and (not gud-running)
d4c2acb9 110 (memq gud-minor-mode
9f6991fd 111 '(gdba gdb dbx xdb jdb pdb bashdb))))
c157af51 112 ([down] menu-item "Down Stack" gud-down
9f6991fd 113 :enable (and (not gud-running)
d4c2acb9 114 (memq gud-minor-mode
9f6991fd 115 '(gdba gdb dbx xdb jdb pdb bashdb))))
1a21c370 116 ([print] menu-item "Print Expression" gud-print
b94a3001 117 :enable (not gud-running))
f36ca832 118 ([display] menu-item "Display Expression" gud-display
b94a3001 119 :enable (and (not gud-running)
1a21c370 120 (eq gud-minor-mode 'gdba)))
c157af51 121 ([finish] menu-item "Finish Function" gud-finish
9f6991fd 122 :enable (and (not gud-running)
d4c2acb9 123 (memq gud-minor-mode
9f6991fd 124 '(gdba gdb xdb jdb pdb bashdb))))
c157af51 125 ([stepi] "Step Instruction" . gud-stepi)
1a21c370 126 ([step] menu-item "Step Line" gud-step
b94a3001 127 :enable (not gud-running))
1a21c370 128 ([next] menu-item "Next Line" gud-next
b94a3001 129 :enable (not gud-running))
1a21c370 130 ([cont] menu-item "Continue" gud-cont
b94a3001 131 :enable (not gud-running)))
c157af51
SM
132 "Menu for `gud-mode'."
133 :name "Gud")
134
135(easy-mmode-defmap gud-minor-mode-map
136 `(([menu-bar debug] . ("Gud" . ,gud-menu-map)))
137 "Map used in visited files.")
138
139(let ((m (assq 'gud-minor-mode minor-mode-map-alist)))
140 (if m (setcdr m gud-minor-mode-map)
141 (push (cons 'gud-minor-mode gud-minor-mode-map) minor-mode-map-alist)))
142
143(defvar gud-mode-map
144 ;; Will inherit from comint-mode via define-derived-mode.
145 (make-sparse-keymap)
146 "`gud-mode' keymap.")
1a21c370
NR
147
148(defvar gud-tool-bar-map
149 (if (display-graphic-p)
b94a3001
SM
150 (let ((map (make-sparse-keymap)))
151 (dolist (x '((gud-break . "gud-break")
152 (gud-remove . "gud-remove")
153 (gud-print . "gud-print")
154 (gud-display . "gud-display")
155 (gud-run . "gud-run")
fcf58c9b 156 (gud-until . "gud-until")
b94a3001
SM
157 (gud-cont . "gud-cont")
158 (gud-step . "gud-step")
159 (gud-next . "gud-next")
160 (gud-finish . "gud-finish")
161 (gud-up . "gud-up")
162 (gud-down . "gud-down"))
163 map)
164 (tool-bar-local-item-from-menu
165 (car x) (cdr x) map gud-minor-mode-map)))))
166
167(defun gud-file-name (f)
168 "Transform a relative file name to an absolute file name.
169Uses `gud-<MINOR-MODE>-directories' to find the source files."
170 (if (file-exists-p f) (expand-file-name f)
171 (let ((directories (gud-val 'directories))
172 (result nil))
173 (while directories
174 (let ((path (expand-file-name f (car directories))))
175 (if (file-exists-p path)
176 (setq result path
177 directories nil)))
178 (setq directories (cdr directories)))
179 result)))
1a21c370
NR
180
181(defun gud-find-file (file)
182 ;; Don't get confused by double slashes in the name that comes from GDB.
183 (while (string-match "//+" file)
184 (setq file (replace-match "/" t t file)))
185 (let ((minor-mode gud-minor-mode)
b94a3001
SM
186 (buf (funcall (or gud-find-file 'gud-file-name) file)))
187 (when (stringp buf)
188 (setq buf (and (file-readable-p buf) (find-file-noselect buf 'nowarn))))
1a21c370
NR
189 (when buf
190 ;; Copy `gud-minor-mode' to the found buffer to turn on the menu.
191 (with-current-buffer buf
192 (set (make-local-variable 'gud-minor-mode) minor-mode)
7461cbeb
NR
193 (set (make-local-variable 'tool-bar-map) gud-tool-bar-map)
194 (make-local-variable 'gud-keep-buffer))
1a21c370 195 buf)))
575661b1 196\f
ee0155df
ER
197;; ======================================================================
198;; command definition
13b80a60
ER
199
200;; This macro is used below to define some basic debugger interface commands.
f961a17c 201;; Of course you may use `gud-def' with any other debugger command, including
6bde8427
JB
202;; user defined ones.
203
204;; A macro call like (gud-def FUNC NAME KEY DOC) expands to a form
205;; which defines FUNC to send the command NAME to the debugger, gives
ee0155df 206;; it the docstring DOC, and binds that function to KEY in the GUD
c6094cae 207;; major mode. The function is also bound in the global keymap with the
5b08a462 208;; GUD prefix.
ee0155df
ER
209
210(defmacro gud-def (func cmd key &optional doc)
211 "Define FUNC to be a command sending STR and bound to KEY, with
212optional doc string DOC. Certain %-escapes in the string arguments
213are interpreted specially if present. These are:
214
c6094cae
EZ
215 %f name (without directory) of current source file.
216 %F name (without directory or extension) of current source file.
217 %d directory of current source file.
218 %l number of current source line
219 %e text of the C lvalue or function-call expression surrounding point.
220 %a text of the hexadecimal address surrounding point
221 %p prefix argument to the command (if any) as a number
ee0155df 222
5b08a462
ER
223 The `current' source file is the file of the current buffer (if
224we're in a C file) or the source file current at the last break or
225step (if we're in the GUD buffer).
226 The `current' line is that of the current buffer (if we're in a
227source file) or the source line number at the last break or step (if
228we're in the GUD buffer)."
9f6991fd
SM
229 `(progn
230 (defun ,func (arg)
231 ,@(if doc (list doc))
232 (interactive "p")
233 ,(if (stringp cmd)
234 `(gud-call ,cmd arg)
235 cmd))
236 ,(if key `(local-set-key ,(concat "\C-c" key) ',func))
237 ,(if key `(global-set-key (vconcat gud-key-prefix ,key) ',func))))
13b80a60 238
f4b643a1
RS
239;; Where gud-display-frame should put the debugging arrow; a cons of
240;; (filename . line-number). This is set by the marker-filter, which scans
241;; the debugger's output for indications of the current program counter.
d840a865
JB
242(defvar gud-last-frame nil)
243
32ab4c10
JB
244;; Used by gud-refresh, which should cause gud-display-frame to redisplay
245;; the last frame, even if it's been called before and gud-last-frame has
246;; been set to nil.
7447c37a 247(defvar gud-last-last-frame nil)
32ab4c10 248
ee0155df
ER
249;; All debugger-specific information is collected here.
250;; Here's how it works, in case you ever need to add a debugger to the mode.
13b80a60
ER
251;;
252;; Each entry must define the following at startup:
253;;
254;;<name>
255;; comint-prompt-regexp
a223b10d 256;; gud-<name>-massage-args
13b80a60 257;; gud-<name>-marker-filter
ee0155df 258;; gud-<name>-find-file
13b80a60 259;;
a223b10d
RM
260;; The job of the massage-args method is to modify the given list of
261;; debugger arguments before running the debugger.
10a4c11f
JB
262;;
263;; The job of the marker-filter method is to detect file/line markers in
264;; strings and set the global gud-last-frame to indicate what display
265;; action (if any) should be triggered by the marker. Note that only
eb8c3be9 266;; whatever the method *returns* is displayed in the buffer; thus, you
10a4c11f
JB
267;; can filter the debugger's output, interpreting some and passing on
268;; the rest.
269;;
ee0155df 270;; The job of the find-file method is to visit and return the buffer indicated
c6094cae 271;; by the car of gud-tag-frame. This may be a file name, a tag name, or
c157af51 272;; something else.
575661b1 273\f
e9a918f9
EL
274;; ======================================================================
275;; speedbar support functions and variables.
8b5cd4d0 276(eval-when-compile (require 'speedbar)) ;For speedbar-with-attached-buffer.
acb50e3c 277
e9a918f9
EL
278(defvar gud-last-speedbar-buffer nil
279 "The last GUD buffer used.")
280
281(defvar gud-last-speedbar-stackframe nil
282 "Description of the currently displayed GUD stack.
283t means that there is no stack, and we are in display-file mode.")
284
acb50e3c
KH
285(defvar gud-speedbar-key-map nil
286 "Keymap used when in the buffers display mode.")
287
288(defun gud-install-speedbar-variables ()
289 "Install those variables used by speedbar to enhance gud/gdb."
290 (if gud-speedbar-key-map
291 nil
292 (setq gud-speedbar-key-map (speedbar-make-specialized-keymap))
293
294 (define-key gud-speedbar-key-map "j" 'speedbar-edit-line)
295 (define-key gud-speedbar-key-map "e" 'speedbar-edit-line)
296 (define-key gud-speedbar-key-map "\C-m" 'speedbar-edit-line)))
297
e9a918f9
EL
298(defvar gud-speedbar-menu-items
299 ;; Note to self. Add expand, and turn off items when not available.
300 '(["Jump to stack frame" speedbar-edit-line t])
110c171f 301 "Additional menu items to add to the speedbar frame.")
e9a918f9 302
acb50e3c
KH
303;; Make sure our special speedbar mode is loaded
304(if (featurep 'speedbar)
305 (gud-install-speedbar-variables)
306 (add-hook 'speedbar-load-hook 'gud-install-speedbar-variables))
307
e9a918f9
EL
308(defun gud-speedbar-buttons (buffer)
309 "Create a speedbar display based on the current state of GUD.
310If the GUD BUFFER is not running a supported debugger, then turn
311off the specialized speedbar mode."
312 (if (and (save-excursion (goto-char (point-min))
313 (looking-at "Current Stack"))
314 (equal gud-last-last-frame gud-last-speedbar-stackframe))
315 nil
316 (setq gud-last-speedbar-buffer buffer)
b94a3001 317 (let* ((minor-mode (with-current-buffer buffer gud-minor-mode))
e9a918f9 318 (frames
b94a3001
SM
319 (cond ((memq minor-mode '(gdba gdb))
320 (gud-gdb-get-stackframe buffer))
e9a918f9
EL
321 ;; Add more debuggers here!
322 (t
323 (speedbar-remove-localized-speedbar-support buffer)
324 nil))))
325 (erase-buffer)
326 (if (not frames)
327 (insert "No Stack frames\n")
328 (insert "Current Stack:\n"))
329 (while frames
330 (insert (nth 1 (car frames)) ":\n")
331 (if (= (length (car frames)) 2)
332 (progn
333; (speedbar-insert-button "[?]"
334; 'speedbar-button-face
335; nil nil nil t)
336 (speedbar-insert-button (car (car frames))
337 'speedbar-directory-face
338 nil nil nil t))
339; (speedbar-insert-button "[+]"
340; 'speedbar-button-face
341; 'speedbar-highlight-face
342; 'gud-gdb-get-scope-data
343; (car frames) t)
344 (speedbar-insert-button (car (car frames))
345 'speedbar-file-face
346 'speedbar-highlight-face
b94a3001 347 (cond ((memq minor-mode '(gdba gdb))
e9a918f9 348 'gud-gdb-goto-stackframe)
55535639 349 (t (error "Should never be here")))
e9a918f9
EL
350 (car frames) t))
351 (setq frames (cdr frames)))
352; (let ((selected-frame
353; (cond ((eq ff 'gud-gdb-find-file)
354; (gud-gdb-selected-frame-info buffer))
55535639 355; (t (error "Should never be here"))))))
e9a918f9
EL
356 )
357 (setq gud-last-speedbar-stackframe gud-last-last-frame)))
358
359\f
13b80a60
ER
360;; ======================================================================
361;; gdb functions
362
8b5cd4d0 363;; History of argument lists passed to gdb.
f6376199
JB
364(defvar gud-gdb-history nil)
365
8b5cd4d0
SM
366(defcustom gud-gdb-command-name "gdb --fullname"
367 "Default command to execute an executable under the GDB debugger."
368 :type 'string
369 :group 'gud)
13b80a60 370
dfb7d195 371(defvar gud-gdb-marker-regexp
1ac95fab
RS
372 ;; This used to use path-separator instead of ":";
373 ;; however, we found that on both Windows 32 and MSDOS
374 ;; a colon is correct here.
15cf3ecc 375 (concat "\032\032\\(.:?[^" ":" "\n]*\\)" ":"
1ac95fab 376 "\\([0-9]*\\)" ":" ".*\n"))
dfb7d195 377
768c29d0
JB
378;; There's no guarantee that Emacs will hand the filter the entire
379;; marker at once; it could be broken up across several strings. We
380;; might even receive a big chunk with several markers in it. If we
381;; receive a chunk of text which looks like it might contain the
382;; beginning of a marker, we save it here between calls to the
383;; filter.
f266485d 384(defvar gud-marker-acc "")
0d29cfe9 385(make-variable-buffer-local 'gud-marker-acc)
768c29d0 386
ee0155df 387(defun gud-gdb-marker-filter (string)
bed6a98d
RS
388 (setq gud-marker-acc (concat gud-marker-acc string))
389 (let ((output ""))
390
391 ;; Process all the complete markers in this chunk.
dfb7d195 392 (while (string-match gud-gdb-marker-regexp gud-marker-acc)
bed6a98d
RS
393 (setq
394
395 ;; Extract the frame position from the marker.
9f6991fd
SM
396 gud-last-frame (cons (match-string 1 gud-marker-acc)
397 (string-to-int (match-string 2 gud-marker-acc)))
bed6a98d
RS
398
399 ;; Append any text before the marker to the output we're going
400 ;; to return - we don't include the marker in this text.
401 output (concat output
402 (substring gud-marker-acc 0 (match-beginning 0)))
403
404 ;; Set the accumulator to the remaining text.
405 gud-marker-acc (substring gud-marker-acc (match-end 0))))
406
407 ;; Does the remaining text look like it might end with the
408 ;; beginning of another marker? If it does, then keep it in
f5851398 409 ;; gud-marker-acc until we receive the rest of it. Since we
bed6a98d
RS
410 ;; know the full marker regexp above failed, it's pretty simple to
411 ;; test for marker starts.
412 (if (string-match "\032.*\\'" gud-marker-acc)
413 (progn
414 ;; Everything before the potential marker start can be output.
415 (setq output (concat output (substring gud-marker-acc
416 0 (match-beginning 0))))
417
418 ;; Everything after, we save, to combine with later input.
419 (setq gud-marker-acc
420 (substring gud-marker-acc (match-beginning 0))))
421
422 (setq output (concat output gud-marker-acc)
423 gud-marker-acc ""))
424
425 output))
13b80a60 426
c157af51
SM
427(easy-mmode-defmap gud-minibuffer-local-map
428 '(("\C-i" . comint-dynamic-complete-filename))
429 "Keymap for minibuffer prompting of gud startup command."
430 :inherit minibuffer-local-map)
431
432(defun gud-query-cmdline (minor-mode &optional init)
433 (let* ((hist-sym (gud-symbol 'history nil minor-mode))
434 (cmd-name (gud-val 'command-name minor-mode)))
435 (unless (boundp hist-sym) (set hist-sym nil))
436 (read-from-minibuffer
437 (format "Run %s (like this): " minor-mode)
438 (or (car-safe (symbol-value hist-sym))
8b5cd4d0 439 (concat (or cmd-name (symbol-name minor-mode))
b94a3001 440 " "
8b5cd4d0
SM
441 (or init
442 (let ((file nil))
443 (dolist (f (directory-files default-directory) file)
444 (if (and (file-executable-p f)
445 (not (file-directory-p f))
446 (or (not file)
447 (file-newer-than-file-p f file)))
448 (setq file f)))))))
c157af51
SM
449 gud-minibuffer-local-map nil
450 hist-sym)))
e886137a 451
10a4c11f 452;;;###autoload
a223b10d 453(defun gdb (command-line)
13b80a60
ER
454 "Run gdb on program FILE in buffer *gud-FILE*.
455The directory containing FILE becomes the initial working directory
456and source-file directory for your debugger."
c157af51 457 (interactive (list (gud-query-cmdline 'gdb)))
ee0155df 458
b94a3001 459 (gud-common-init command-line nil 'gud-gdb-marker-filter)
c157af51 460 (set (make-local-variable 'gud-minor-mode) 'gdb)
5b08a462 461
dd8e46c7 462 (gud-def gud-break "break %f:%l" "\C-b" "Set breakpoint at current line.")
2fb419e1 463 (gud-def gud-tbreak "tbreak %f:%l" "\C-t" "Set temporary breakpoint at current line.")
23a3aa0a 464 (gud-def gud-remove "clear %f:%l" "\C-d" "Remove breakpoint at current line")
c6094cae 465 (gud-def gud-step "step %p" "\C-s" "Step one source line with display.")
dd8e46c7 466 (gud-def gud-stepi "stepi %p" "\C-i" "Step one instruction with display.")
c6094cae
EZ
467 (gud-def gud-next "next %p" "\C-n" "Step one line (skip functions).")
468 (gud-def gud-cont "cont" "\C-r" "Continue with display.")
469 (gud-def gud-finish "finish" "\C-f" "Finish executing current function.")
38eba485
RS
470 (gud-def gud-jump "tbreak %f:%l\njump %f:%l" "\C-j" "Relocate execution address to line at point in source buffer.")
471
c6094cae
EZ
472 (gud-def gud-up "up %p" "<" "Up N stack frames (numeric arg).")
473 (gud-def gud-down "down %p" ">" "Down N stack frames (numeric arg).")
dd8e46c7 474 (gud-def gud-print "print %e" "\C-p" "Evaluate C expression at point.")
fcf58c9b 475 (gud-def gud-until "until %l" "\C-u" "Continue up to current line.")
f36ca832 476 (gud-def gud-run "run" nil "Run the program.")
ee0155df 477
0e0de659 478 (local-set-key "\C-i" 'gud-gdb-complete-command)
13b80a60 479 (setq comint-prompt-regexp "^(.*gdb[+]?) *")
f54877b2 480 (setq paragraph-start comint-prompt-regexp)
13b80a60
ER
481 (run-hooks 'gdb-mode-hook)
482 )
483
0e0de659
RS
484;; One of the nice features of GDB is its impressive support for
485;; context-sensitive command completion. We preserve that feature
486;; in the GUD buffer by using a GDB command designed just for Emacs.
487
488;; The completion process filter indicates when it is finished.
9f6991fd 489(defvar gud-gdb-fetch-lines-in-progress)
0e0de659
RS
490
491;; Since output may arrive in fragments we accumulate partials strings here.
9f6991fd 492(defvar gud-gdb-fetch-lines-string)
0e0de659
RS
493
494;; We need to know how much of the completion to chop off.
9f6991fd 495(defvar gud-gdb-fetch-lines-break)
0e0de659
RS
496
497;; The completion list is constructed by the process filter.
9f6991fd 498(defvar gud-gdb-fetched-lines)
0e0de659 499
30df2a53
RS
500(defvar gud-comint-buffer nil)
501
0e0de659
RS
502(defun gud-gdb-complete-command ()
503 "Perform completion on the GDB command preceding point.
504This is implemented using the GDB `complete' command which isn't
505available with older versions of GDB."
506 (interactive)
507 (let* ((end (point))
01d8967d 508 (command (buffer-substring (comint-line-beginning-position) end))
9f6991fd
SM
509 (command-word
510 ;; Find the word break. This match will always succeed.
511 (and (string-match "\\(\\`\\| \\)\\([^ ]*\\)\\'" command)
512 (substring command (match-beginning 2))))
513 (complete-list
514 (gud-gdb-run-command-fetch-lines (concat "complete " command)
515 (current-buffer)
516 ;; From string-match above.
517 (match-beginning 2))))
0e0de659 518 ;; Protect against old versions of GDB.
9f6991fd
SM
519 (and complete-list
520 (string-match "^Undefined command: \"complete\"" (car complete-list))
55535639 521 (error "This version of GDB doesn't support the `complete' command"))
0e0de659 522 ;; Sort the list like readline.
9f6991fd 523 (setq complete-list (sort complete-list (function string-lessp)))
0e0de659 524 ;; Remove duplicates.
9f6991fd
SM
525 (let ((first complete-list)
526 (second (cdr complete-list)))
0e0de659
RS
527 (while second
528 (if (string-equal (car first) (car second))
529 (setcdr first (setq second (cdr second)))
530 (setq first second
531 second (cdr second)))))
fd63b4f4
KH
532 ;; Add a trailing single quote if there is a unique completion
533 ;; and it contains an odd number of unquoted single quotes.
9f6991fd
SM
534 (and (= (length complete-list) 1)
535 (let ((str (car complete-list))
fd63b4f4
KH
536 (pos 0)
537 (count 0))
538 (while (string-match "\\([^'\\]\\|\\\\'\\)*'" str pos)
539 (setq count (1+ count)
540 pos (match-end 0)))
541 (and (= (mod count 2) 1)
9f6991fd 542 (setq complete-list (list (concat str "'"))))))
0e0de659 543 ;; Let comint handle the rest.
9f6991fd 544 (comint-dynamic-simple-complete command-word complete-list)))
f4b643a1 545
0e0de659
RS
546;; The completion process filter is installed temporarily to slurp the
547;; output of GDB up to the next prompt and build the completion list.
9f6991fd
SM
548(defun gud-gdb-fetch-lines-filter (string filter)
549 "Filter used to read the list of lines output by a command.
550STRING is the output to filter.
551It is passed through FILTER before we look at it."
552 (setq string (funcall filter string))
553 (setq string (concat gud-gdb-fetch-lines-string string))
0e0de659 554 (while (string-match "\n" string)
9f6991fd
SM
555 (push (substring string gud-gdb-fetch-lines-break (match-beginning 0))
556 gud-gdb-fetched-lines)
0e0de659 557 (setq string (substring string (match-end 0))))
e9a918f9
EL
558 (if (string-match comint-prompt-regexp string)
559 (progn
9f6991fd 560 (setq gud-gdb-fetch-lines-in-progress nil)
e9a918f9
EL
561 string)
562 (progn
9f6991fd 563 (setq gud-gdb-fetch-lines-string string)
e9a918f9
EL
564 "")))
565
566;; gdb speedbar functions
567
568(defun gud-gdb-goto-stackframe (text token indent)
569 "Goto the stackframe described by TEXT, TOKEN, and INDENT."
570 (speedbar-with-attached-buffer
571 (gud-basic-call (concat "frame " (nth 1 token)))
572 (sit-for 1)))
573
574(defvar gud-gdb-fetched-stack-frame nil
575 "Stack frames we are fetching from GDB.")
576
e9a918f9
EL
577;(defun gud-gdb-get-scope-data (text token indent)
578; ;; checkdoc-params: (indent)
579; "Fetch data associated with a stack frame, and expand/contract it.
580;Data to do this is retrieved from TEXT and TOKEN."
581; (let ((args nil) (scope nil))
582; (gud-gdb-run-command-fetch-lines "info args")
583;
584; (gud-gdb-run-command-fetch-lines "info local")
585;
586; ))
587
588(defun gud-gdb-get-stackframe (buffer)
589 "Extract the current stack frame out of the GUD GDB BUFFER."
590 (let ((newlst nil)
9f6991fd
SM
591 (fetched-stack-frame-list
592 (gud-gdb-run-command-fetch-lines "backtrace" buffer)))
593 (if (and (car fetched-stack-frame-list)
594 (string-match "No stack" (car fetched-stack-frame-list)))
e9a918f9
EL
595 ;; Go into some other mode???
596 nil
9f6991fd
SM
597 (dolist (e fetched-stack-frame-list)
598 (let ((name nil) (num nil))
e9a918f9 599 (if (not (or
acb50e3c
KH
600 (string-match "^#\\([0-9]+\\) +[0-9a-fx]+ in \\([:0-9a-zA-Z_]+\\) (" e)
601 (string-match "^#\\([0-9]+\\) +\\([:0-9a-zA-Z_]+\\) (" e)))
e9a918f9
EL
602 (if (not (string-match
603 "at \\([-0-9a-zA-Z_.]+\\):\\([0-9]+\\)$" e))
604 nil
605 (setcar newlst
606 (list (nth 0 (car newlst))
607 (nth 1 (car newlst))
608 (match-string 1 e)
609 (match-string 2 e))))
610 (setq num (match-string 1 e)
611 name (match-string 2 e))
612 (setq newlst
613 (cons
614 (if (string-match
615 "at \\([-0-9a-zA-Z_.]+\\):\\([0-9]+\\)$" e)
616 (list name num (match-string 1 e)
617 (match-string 2 e))
618 (list name num))
9f6991fd 619 newlst)))))
e9a918f9
EL
620 (nreverse newlst))))
621
622;(defun gud-gdb-selected-frame-info (buffer)
623; "Learn GDB information for the currently selected stack frame in BUFFER."
624; )
625
9f6991fd
SM
626(defun gud-gdb-run-command-fetch-lines (command buffer &optional skip)
627 "Run COMMAND, and return the list of lines it outputs.
628BUFFER is the GUD buffer in which to run the command.
629SKIP is the number of chars to skip on each lines, it defaults to 0."
e9a918f9
EL
630 (save-excursion
631 (set-buffer buffer)
632 (if (save-excursion
633 (goto-char (point-max))
d2d1851b 634 (forward-line 0)
e9a918f9
EL
635 (not (looking-at comint-prompt-regexp)))
636 nil
637 ;; Much of this copied from GDB complete, but I'm grabbing the stack
638 ;; frame instead.
9f6991fd
SM
639 (let ((gud-gdb-fetch-lines-in-progress t)
640 (gud-gdb-fetched-lines nil)
641 (gud-gdb-fetch-lines-string nil)
642 (gud-gdb-fetch-lines-break (or skip 0))
643 (gud-marker-filter
644 `(lambda (string) (gud-gdb-fetch-lines-filter string ',gud-marker-filter))))
e9a918f9
EL
645 ;; Issue the command to GDB.
646 (gud-basic-call command)
e9a918f9 647 ;; Slurp the output.
9f6991fd
SM
648 (while gud-gdb-fetch-lines-in-progress
649 (accept-process-output (get-buffer-process buffer)))
650 (nreverse gud-gdb-fetched-lines)))))
0e0de659 651
575661b1 652\f
13b80a60
ER
653;; ======================================================================
654;; sdb functions
655
8b5cd4d0 656;; History of argument lists passed to sdb.
f6376199
JB
657(defvar gud-sdb-history nil)
658
ee0155df
ER
659(defvar gud-sdb-needs-tags (not (file-exists-p "/var"))
660 "If nil, we're on a System V Release 4 and don't need the tags hack.")
661
662(defvar gud-sdb-lastfile nil)
663
ee0155df 664(defun gud-sdb-marker-filter (string)
7f629252
RS
665 (setq gud-marker-acc
666 (if gud-marker-acc (concat gud-marker-acc string) string))
667 (let (start)
668 ;; Process all complete markers in this chunk
f4b643a1
RS
669 (while
670 (cond
7f629252 671 ;; System V Release 3.2 uses this format
bcdef904 672 ((string-match "\\(^\\|\n\\)\\*?\\(0x\\w* in \\)?\\([^:\n]*\\):\\([0-9]*\\):.*\n"
7f629252
RS
673 gud-marker-acc start)
674 (setq gud-last-frame
9f6991fd
SM
675 (cons (match-string 3 gud-marker-acc)
676 (string-to-int (match-string 4 gud-marker-acc)))))
7f629252 677 ;; System V Release 4.0 quite often clumps two lines together
f4b643a1 678 ((string-match "^\\(BREAKPOINT\\|STEPPED\\) process [0-9]+ function [^ ]+ in \\(.+\\)\n\\([0-9]+\\):"
7f629252 679 gud-marker-acc start)
9f6991fd 680 (setq gud-sdb-lastfile (match-string 2 gud-marker-acc))
7f629252 681 (setq gud-last-frame
9f6991fd
SM
682 (cons gud-sdb-lastfile
683 (string-to-int (match-string 3 gud-marker-acc)))))
f4b643a1 684 ;; System V Release 4.0
7f629252
RS
685 ((string-match "^\\(BREAKPOINT\\|STEPPED\\) process [0-9]+ function [^ ]+ in \\(.+\\)\n"
686 gud-marker-acc start)
9f6991fd 687 (setq gud-sdb-lastfile (match-string 2 gud-marker-acc)))
7f629252
RS
688 ((and gud-sdb-lastfile (string-match "^\\([0-9]+\\):"
689 gud-marker-acc start))
690 (setq gud-last-frame
9f6991fd
SM
691 (cons gud-sdb-lastfile
692 (string-to-int (match-string 1 gud-marker-acc)))))
f4b643a1 693 (t
7f629252
RS
694 (setq gud-sdb-lastfile nil)))
695 (setq start (match-end 0)))
696
697 ;; Search for the last incomplete line in this chunk
698 (while (string-match "\n" gud-marker-acc start)
699 (setq start (match-end 0)))
700
701 ;; If we have an incomplete line, store it in gud-marker-acc.
bcdef904 702 (setq gud-marker-acc (substring gud-marker-acc (or start 0))))
13b80a60
ER
703 string)
704
ee0155df 705(defun gud-sdb-find-file (f)
c157af51 706 (if gud-sdb-needs-tags (find-tag-noselect f) (find-file-noselect f)))
13b80a60 707
10a4c11f 708;;;###autoload
a223b10d 709(defun sdb (command-line)
13b80a60
ER
710 "Run sdb on program FILE in buffer *gud-FILE*.
711The directory containing FILE becomes the initial working directory
712and source-file directory for your debugger."
c157af51
SM
713 (interactive (list (gud-query-cmdline 'sdb)))
714
ee0155df 715 (if (and gud-sdb-needs-tags
e290aebb
RS
716 (not (and (boundp 'tags-file-name)
717 (stringp tags-file-name)
718 (file-exists-p tags-file-name))))
55535639 719 (error "The sdb support requires a valid tags table to work"))
13b80a60 720
b94a3001 721 (gud-common-init command-line nil 'gud-sdb-marker-filter 'gud-sdb-find-file)
c157af51 722 (set (make-local-variable 'gud-minor-mode) 'sdb)
5b08a462 723
dd8e46c7
RS
724 (gud-def gud-break "%l b" "\C-b" "Set breakpoint at current line.")
725 (gud-def gud-tbreak "%l c" "\C-t" "Set temporary breakpoint at current line.")
726 (gud-def gud-remove "%l d" "\C-d" "Remove breakpoint at current line")
727 (gud-def gud-step "s %p" "\C-s" "Step one source line with display.")
728 (gud-def gud-stepi "i %p" "\C-i" "Step one instruction with display.")
729 (gud-def gud-next "S %p" "\C-n" "Step one line (skip functions).")
730 (gud-def gud-cont "c" "\C-r" "Continue with display.")
731 (gud-def gud-print "%e/" "\C-p" "Evaluate C expression at point.")
13b80a60 732
6bde8427 733 (setq comint-prompt-regexp "\\(^\\|\n\\)\\*")
f54877b2 734 (setq paragraph-start comint-prompt-regexp)
13b80a60
ER
735 (run-hooks 'sdb-mode-hook)
736 )
575661b1 737\f
13b80a60
ER
738;; ======================================================================
739;; dbx functions
740
8b5cd4d0 741;; History of argument lists passed to dbx.
f6376199
JB
742(defvar gud-dbx-history nil)
743
69c1dd37 744(defcustom gud-dbx-directories nil
3b3703fa
RS
745 "*A list of directories that dbx should search for source code.
746If nil, only source files in the program directory
747will be known to dbx.
748
749The file names should be absolute, or relative to the directory
69c1dd37
RS
750containing the executable being debugged."
751 :type '(choice (const :tag "Current Directory" nil)
752 (repeat :value ("")
753 directory))
754 :group 'gud)
3b3703fa
RS
755
756(defun gud-dbx-massage-args (file args)
757 (nconc (let ((directories gud-dbx-directories)
758 (result nil))
759 (while directories
760 (setq result (cons (car directories) (cons "-I" result)))
761 (setq directories (cdr directories)))
762 (nreverse result))
763 args))
764
ee0155df 765(defun gud-dbx-marker-filter (string)
7f629252
RS
766 (setq gud-marker-acc (if gud-marker-acc (concat gud-marker-acc string) string))
767
768 (let (start)
769 ;; Process all complete markers in this chunk.
770 (while (or (string-match
771 "stopped in .* at line \\([0-9]*\\) in file \"\\([^\"]*\\)\""
772 gud-marker-acc start)
773 (string-match
774 "signal .* in .* at line \\([0-9]*\\) in file \"\\([^\"]*\\)\""
775 gud-marker-acc start))
13b80a60 776 (setq gud-last-frame
9f6991fd
SM
777 (cons (match-string 2 gud-marker-acc)
778 (string-to-int (match-string 1 gud-marker-acc)))
7f629252
RS
779 start (match-end 0)))
780
781 ;; Search for the last incomplete line in this chunk
782 (while (string-match "\n" gud-marker-acc start)
783 (setq start (match-end 0)))
784
785 ;; If the incomplete line APPEARS to begin with another marker, keep it
786 ;; in the accumulator. Otherwise, clear the accumulator to avoid an
787 ;; unnecessary concat during the next call.
f4b643a1 788 (setq gud-marker-acc
7f629252
RS
789 (if (string-match "\\(stopped\\|signal\\)" gud-marker-acc start)
790 (substring gud-marker-acc (match-beginning 0))
791 nil)))
13b80a60
ER
792 string)
793
f266485d
RS
794;; Functions for Mips-style dbx. Given the option `-emacs', documented in
795;; OSF1, not necessarily elsewhere, it produces markers similar to gdb's.
796(defvar gud-mips-p
797 (or (string-match "^mips-[^-]*-ultrix" system-configuration)
798 ;; We haven't tested gud on this system:
799 (string-match "^mips-[^-]*-riscos" system-configuration)
800 ;; It's documented on OSF/1.3
9f24ea14 801 (string-match "^mips-[^-]*-osf1" system-configuration)
7c82656b 802 (string-match "^alpha[^-]*-[^-]*-osf" system-configuration))
f266485d 803 "Non-nil to assume the MIPS/OSF dbx conventions (argument `-emacs').")
13eaa026 804
b94a3001
SM
805(defvar gud-dbx-command-name
806 (concat "dbx" (if gud-mips-p " -emacs")))
13eaa026 807
f266485d
RS
808;; This is just like the gdb one except for the regexps since we need to cope
809;; with an optional breakpoint number in [] before the ^Z^Z
13eaa026 810(defun gud-mipsdbx-marker-filter (string)
bed6a98d
RS
811 (setq gud-marker-acc (concat gud-marker-acc string))
812 (let ((output ""))
813
814 ;; Process all the complete markers in this chunk.
815 (while (string-match
816 ;; This is like th gdb marker but with an optional
817 ;; leading break point number like `[1] '
818 "[][ 0-9]*\032\032\\([^:\n]*\\):\\([0-9]*\\):.*\n"
819 gud-marker-acc)
820 (setq
821
822 ;; Extract the frame position from the marker.
823 gud-last-frame
9f6991fd
SM
824 (cons (match-string 1 gud-marker-acc)
825 (string-to-int (match-string 2 gud-marker-acc)))
bed6a98d
RS
826
827 ;; Append any text before the marker to the output we're going
828 ;; to return - we don't include the marker in this text.
829 output (concat output
830 (substring gud-marker-acc 0 (match-beginning 0)))
831
832 ;; Set the accumulator to the remaining text.
833 gud-marker-acc (substring gud-marker-acc (match-end 0))))
834
835 ;; Does the remaining text look like it might end with the
836 ;; beginning of another marker? If it does, then keep it in
c6094cae 837 ;; gud-marker-acc until we receive the rest of it. Since we
bed6a98d
RS
838 ;; know the full marker regexp above failed, it's pretty simple to
839 ;; test for marker starts.
840 (if (string-match "[][ 0-9]*\032.*\\'" gud-marker-acc)
841 (progn
842 ;; Everything before the potential marker start can be output.
843 (setq output (concat output (substring gud-marker-acc
844 0 (match-beginning 0))))
845
846 ;; Everything after, we save, to combine with later input.
847 (setq gud-marker-acc
848 (substring gud-marker-acc (match-beginning 0))))
849
850 (setq output (concat output gud-marker-acc)
851 gud-marker-acc ""))
852
853 output))
13eaa026 854
f266485d
RS
855;; The dbx in IRIX is a pain. It doesn't print the file name when
856;; stopping at a breakpoint (but you do get it from the `up' and
c6094cae 857;; `down' commands...). The only way to extract the information seems
f266485d
RS
858;; to be with a `file' command, although the current line number is
859;; available in $curline. Thus we have to look for output which
860;; appears to indicate a breakpoint. Then we prod the dbx sub-process
861;; to output the information we want with a combination of the
862;; `printf' and `file' commands as a pseudo marker which we can
863;; recognise next time through the marker-filter. This would be like
864;; the gdb marker but you can't get the file name without a newline...
865;; Note that gud-remove won't work since Irix dbx expects a breakpoint
866;; number rather than a line number etc. Maybe this could be made to
867;; work by listing all the breakpoints and picking the one(s) with the
868;; correct line number, but life's too short.
869;; d.love@dl.ac.uk (Dave Love) can be blamed for this
870
ac8da950
KH
871(defvar gud-irix-p
872 (and (string-match "^mips-[^-]*-irix" system-configuration)
873 (not (string-match "irix[6-9]\\.[1-9]" system-configuration)))
f266485d 874 "Non-nil to assume the interface appropriate for IRIX dbx.
ac8da950
KH
875This works in IRIX 4, 5 and 6, but `gud-dbx-use-stopformat-p' provides
876a better solution in 6.1 upwards.")
877(defvar gud-dbx-use-stopformat-p
878 (string-match "irix[6-9]\\.[1-9]" system-configuration)
879 "Non-nil to use the dbx feature present at least from Irix 6.1
880 whereby $stopformat=1 produces an output format compatiable with
881 `gud-dbx-marker-filter'.")
2fb419e1
RS
882;; [Irix dbx seems to be a moving target. The dbx output changed
883;; subtly sometime between OS v4.0.5 and v5.2 so that, for instance,
884;; the output from `up' is no longer spotted by gud (and it's probably
885;; not distinctive enough to try to match it -- use C-<, C->
886;; exclusively) . For 5.3 and 6.0, the $curline variable changed to
887;; `long long'(why?!), so the printf stuff needed changing. The line
ac8da950
KH
888;; number was cast to `long' as a compromise between the new `long
889;; long' and the original `int'. This is reported not to work in 6.2,
890;; so it's changed back to int -- don't make your sources too long.
891;; From Irix6.1 (but not 6.0?) dbx supports an undocumented feature
892;; whereby `set $stopformat=1' reportedly produces output compatible
893;; with `gud-dbx-marker-filter', which we prefer.
894
895;; The process filter is also somewhat
2fb419e1
RS
896;; unreliable, sometimes not spotting the markers; I don't know
897;; whether there's anything that can be done about that. It would be
898;; much better if SGI could be persuaded to (re?)instate the MIPS
899;; -emacs flag for gdb-like output (which ought to be possible as most
900;; of the communication I've had over it has been from sgi.com).]
f266485d
RS
901
902;; this filter is influenced by the xdb one rather than the gdb one
903(defun gud-irixdbx-marker-filter (string)
bed6a98d
RS
904 (let (result (case-fold-search nil))
905 (if (or (string-match comint-prompt-regexp string)
906 (string-match ".*\012" string))
907 (setq result (concat gud-marker-acc string)
908 gud-marker-acc "")
909 (setq gud-marker-acc (concat gud-marker-acc string)))
910 (if result
911 (cond
912 ;; look for breakpoint or signal indication e.g.:
c6094cae 913 ;; [2] Process 1267 (pplot) stopped at [params:338 ,0x400ec0]
bed6a98d
RS
914 ;; Process 1281 (pplot) stopped at [params:339 ,0x400ec8]
915 ;; Process 1270 (pplot) Floating point exception [._read._read:16 ,0x452188]
916 ((string-match
f4b643a1 917 "^\\(\\[[0-9]+] \\)?Process +[0-9]+ ([^)]*) [^[]+\\[[^]\n]*]\n"
bed6a98d
RS
918 result)
919 ;; prod dbx into printing out the line number and file
920 ;; name in a form we can grok as below
921 (process-send-string (get-buffer-process gud-comint-buffer)
ac8da950 922 "printf \"\032\032%1d:\",(int)$curline;file\n"))
bed6a98d
RS
923 ;; look for result of, say, "up" e.g.:
924 ;; .pplot.pplot(0x800) ["src/pplot.f":261, 0x400c7c]
925 ;; (this will also catch one of the lines printed by "where")
926 ((string-match
927 "^[^ ][^[]*\\[\"\\([^\"]+\\)\":\\([0-9]+\\), [^]]+]\n"
928 result)
9f6991fd 929 (let ((file (match-string 1 result)))
bed6a98d
RS
930 (if (file-exists-p file)
931 (setq gud-last-frame
9f6991fd
SM
932 (cons (match-string 1 result)
933 (string-to-int (match-string 2 result))))))
bed6a98d
RS
934 result)
935 ((string-match ; kluged-up marker as above
936 "\032\032\\([0-9]*\\):\\(.*\\)\n" result)
b94a3001 937 (let ((file (gud-file-name (match-string 2 result))))
3b3703fa 938 (if (and file (file-exists-p file))
bed6a98d 939 (setq gud-last-frame
9f6991fd
SM
940 (cons file
941 (string-to-int (match-string 1 result))))))
bed6a98d
RS
942 (setq result (substring result 0 (match-beginning 0))))))
943 (or result "")))
f266485d 944
34c8b673
RS
945(defvar gud-dgux-p (string-match "-dgux" system-configuration)
946 "Non-nil means to assume the interface approriate for DG/UX dbx.
947This was tested using R4.11.")
948
949;; There are a couple of differences between DG's dbx output and normal
950;; dbx output which make it nontrivial to integrate this into the
951;; standard dbx-marker-filter (mainly, there are a different number of
952;; backreferences). The markers look like:
953;;
954;; (0) Stopped at line 10, routine main(argc=1, argv=0xeffff0e0), file t.c
955;;
956;; from breakpoints (the `(0)' there isn't constant, it's the breakpoint
957;; number), and
958;;
959;; Stopped at line 13, routine main(argc=1, argv=0xeffff0e0), file t.c
960;;
961;; from signals and
962;;
963;; Frame 21, line 974, routine command_loop(), file keyboard.c
964;;
965;; from up/down/where.
966
967(defun gud-dguxdbx-marker-filter (string)
968 (setq gud-marker-acc (if gud-marker-acc
969 (concat gud-marker-acc string)
970 string))
971 (let ((re (concat "^\\(\\(([0-9]+) \\)?Stopped at\\|Frame [0-9]+,\\)"
972 " line \\([0-9]+\\), routine .*, file \\([^ \t\n]+\\)"))
973 start)
974 ;; Process all complete markers in this chunk.
975 (while (string-match re gud-marker-acc start)
976 (setq gud-last-frame
9f6991fd
SM
977 (cons (match-string 4 gud-marker-acc)
978 (string-to-int (match-string 3 gud-marker-acc)))
34c8b673
RS
979 start (match-end 0)))
980
981 ;; Search for the last incomplete line in this chunk
982 (while (string-match "\n" gud-marker-acc start)
983 (setq start (match-end 0)))
984
985 ;; If the incomplete line APPEARS to begin with another marker, keep it
986 ;; in the accumulator. Otherwise, clear the accumulator to avoid an
987 ;; unnecessary concat during the next call.
f4b643a1 988 (setq gud-marker-acc
34c8b673
RS
989 (if (string-match "Stopped\\|Frame" gud-marker-acc start)
990 (substring gud-marker-acc (match-beginning 0))
991 nil)))
992 string)
993
10a4c11f 994;;;###autoload
a223b10d 995(defun dbx (command-line)
13b80a60
ER
996 "Run dbx on program FILE in buffer *gud-FILE*.
997The directory containing FILE becomes the initial working directory
998and source-file directory for your debugger."
c157af51 999 (interactive (list (gud-query-cmdline 'dbx)))
13eaa026 1000
ee97eac3
RS
1001 (cond
1002 (gud-mips-p
b94a3001 1003 (gud-common-init command-line nil 'gud-mipsdbx-marker-filter))
ee97eac3
RS
1004 (gud-irix-p
1005 (gud-common-init command-line 'gud-dbx-massage-args
b94a3001 1006 'gud-irixdbx-marker-filter))
34c8b673
RS
1007 (gud-dgux-p
1008 (gud-common-init command-line 'gud-dbx-massage-args
b94a3001 1009 'gud-dguxdbx-marker-filter))
ee97eac3
RS
1010 (t
1011 (gud-common-init command-line 'gud-dbx-massage-args
b94a3001 1012 'gud-dbx-marker-filter)))
5b08a462 1013
c157af51
SM
1014 (set (make-local-variable 'gud-minor-mode) 'dbx)
1015
13eaa026 1016 (cond
f266485d 1017 (gud-mips-p
c6094cae 1018 (gud-def gud-up "up %p" "<" "Up (numeric arg) stack frames.")
f5851398 1019 (gud-def gud-down "down %p" ">" "Down (numeric arg) stack frames.")
c6094cae 1020 (gud-def gud-break "stop at \"%f\":%l"
13eaa026
RS
1021 "\C-b" "Set breakpoint at current line.")
1022 (gud-def gud-finish "return" "\C-f" "Finish executing current function."))
f266485d 1023 (gud-irix-p
c6094cae 1024 (gud-def gud-break "stop at \"%d%f\":%l"
f266485d
RS
1025 "\C-b" "Set breakpoint at current line.")
1026 (gud-def gud-finish "return" "\C-f" "Finish executing current function.")
f5851398 1027 (gud-def gud-up "up %p; printf \"\032\032%1d:\",(int)$curline;file\n"
2fb419e1 1028 "<" "Up (numeric arg) stack frames.")
ac8da950 1029 (gud-def gud-down "down %p; printf \"\032\032%1d:\",(int)$curline;file\n"
2fb419e1 1030 ">" "Down (numeric arg) stack frames.")
f266485d
RS
1031 ;; Make dbx give out the source location info that we need.
1032 (process-send-string (get-buffer-process gud-comint-buffer)
ac8da950 1033 "printf \"\032\032%1d:\",(int)$curline;file\n"))
13eaa026 1034 (t
c6094cae 1035 (gud-def gud-up "up %p" "<" "Up (numeric arg) stack frames.")
f5851398 1036 (gud-def gud-down "down %p" ">" "Down (numeric arg) stack frames.")
13eaa026 1037 (gud-def gud-break "file \"%d%f\"\nstop at %l"
cfcda0ba
EZ
1038 "\C-b" "Set breakpoint at current line.")
1039 (if gud-dbx-use-stopformat-p
1040 (process-send-string (get-buffer-process gud-comint-buffer)
1041 "set $stopformat=1\n"))))
13eaa026 1042
dd8e46c7 1043 (gud-def gud-remove "clear %l" "\C-d" "Remove breakpoint at current line")
c6094cae 1044 (gud-def gud-step "step %p" "\C-s" "Step one line with display.")
dd8e46c7 1045 (gud-def gud-stepi "stepi %p" "\C-i" "Step one instruction with display.")
c6094cae
EZ
1046 (gud-def gud-next "next %p" "\C-n" "Step one line (skip functions).")
1047 (gud-def gud-cont "cont" "\C-r" "Continue with display.")
dd8e46c7 1048 (gud-def gud-print "print %e" "\C-p" "Evaluate C expression at point.")
ee0155df 1049
13eaa026 1050 (setq comint-prompt-regexp "^[^)\n]*dbx) *")
f54877b2 1051 (setq paragraph-start comint-prompt-regexp)
13b80a60
ER
1052 (run-hooks 'dbx-mode-hook)
1053 )
575661b1 1054\f
6496f3d2
RS
1055;; ======================================================================
1056;; xdb (HP PARISC debugger) functions
1057
8b5cd4d0 1058;; History of argument lists passed to xdb.
f6376199
JB
1059(defvar gud-xdb-history nil)
1060
69c1dd37 1061(defcustom gud-xdb-directories nil
fce222c7
RS
1062 "*A list of directories that xdb should search for source code.
1063If nil, only source files in the program directory
1064will be known to xdb.
1065
1066The file names should be absolute, or relative to the directory
69c1dd37
RS
1067containing the executable being debugged."
1068 :type '(choice (const :tag "Current Directory" nil)
1069 (repeat :value ("")
1070 directory))
1071 :group 'gud)
fce222c7 1072
a223b10d
RM
1073(defun gud-xdb-massage-args (file args)
1074 (nconc (let ((directories gud-xdb-directories)
1075 (result nil))
1076 (while directories
1077 (setq result (cons (car directories) (cons "-d" result)))
1078 (setq directories (cdr directories)))
dfbd82a6 1079 (nreverse result))
a223b10d 1080 args))
6496f3d2 1081
6496f3d2 1082;; xdb does not print the lines all at once, so we have to accumulate them
6496f3d2
RS
1083(defun gud-xdb-marker-filter (string)
1084 (let (result)
1085 (if (or (string-match comint-prompt-regexp string)
f5851398
EZ
1086 (string-match ".*\012" string))
1087 (setq result (concat gud-marker-acc string)
1088 gud-marker-acc "")
f266485d 1089 (setq gud-marker-acc (concat gud-marker-acc string)))
6496f3d2 1090 (if result
f5851398 1091 (if (or (string-match "\\([^\n \t:]+\\): [^:]+: \\([0-9]+\\)[: ]"
1dc9668c 1092 result)
b94a3001
SM
1093 (string-match "[^: \t]+:[ \t]+\\([^:]+\\): [^:]+: \\([0-9]+\\):"
1094 result))
1095 (let ((line (string-to-int (match-string 2 result)))
1096 (file (gud-file-name (match-string 1 result))))
1097 (if file
1098 (setq gud-last-frame (cons file line))))))
f4b643a1
RS
1099 (or result "")))
1100
6496f3d2 1101;;;###autoload
a223b10d 1102(defun xdb (command-line)
6496f3d2
RS
1103 "Run xdb on program FILE in buffer *gud-FILE*.
1104The directory containing FILE becomes the initial working directory
1105and source-file directory for your debugger.
1106
fce222c7 1107You can set the variable 'gud-xdb-directories' to a list of program source
6496f3d2 1108directories if your program contains sources from more than one directory."
c157af51 1109 (interactive (list (gud-query-cmdline 'xdb)))
6496f3d2 1110
ee97eac3 1111 (gud-common-init command-line 'gud-xdb-massage-args
b94a3001 1112 'gud-xdb-marker-filter)
c157af51 1113 (set (make-local-variable 'gud-minor-mode) 'xdb)
6496f3d2 1114
c6094cae 1115 (gud-def gud-break "b %f:%l" "\C-b" "Set breakpoint at current line.")
6496f3d2 1116 (gud-def gud-tbreak "b %f:%l\\t" "\C-t"
f5851398 1117 "Set temporary breakpoint at current line.")
c6094cae
EZ
1118 (gud-def gud-remove "db" "\C-d" "Remove breakpoint at current line")
1119 (gud-def gud-step "s %p" "\C-s" "Step one line with display.")
1120 (gud-def gud-next "S %p" "\C-n" "Step one line (skip functions).")
1121 (gud-def gud-cont "c" "\C-r" "Continue with display.")
1122 (gud-def gud-up "up %p" "<" "Up (numeric arg) stack frames.")
1123 (gud-def gud-down "down %p" ">" "Down (numeric arg) stack frames.")
1124 (gud-def gud-finish "bu\\t" "\C-f" "Finish executing current function.")
1125 (gud-def gud-print "p %e" "\C-p" "Evaluate C expression at point.")
6496f3d2
RS
1126
1127 (setq comint-prompt-regexp "^>")
f54877b2 1128 (setq paragraph-start comint-prompt-regexp)
6496f3d2 1129 (run-hooks 'xdb-mode-hook))
575661b1
RS
1130\f
1131;; ======================================================================
1132;; perldb functions
1133
8b5cd4d0 1134;; History of argument lists passed to perldb.
575661b1
RS
1135(defvar gud-perldb-history nil)
1136
1137(defun gud-perldb-massage-args (file args)
8b5cd4d0
SM
1138 "Convert a command line as would be typed normally to run perldb
1139into one that invokes an Emacs-enabled debugging session.
1140\"-emacs\" is inserted where it will be $ARGV[0] (see perl5db.pl)."
1141 ;; FIXME: what if the command is `make perldb' and doesn't accept those extra
1142 ;; arguments ?
1143 (let* ((new-args nil)
a09754e6 1144 (seen-e nil)
8b5cd4d0 1145 (shift (lambda () (push (pop args) new-args))))
f2eb772d 1146
a09754e6 1147 ;; Pass all switches and -e scripts through.
f2eb772d 1148 (while (and args
a09754e6
GM
1149 (string-match "^-" (car args))
1150 (not (equal "-" (car args)))
1151 (not (equal "--" (car args))))
1152 (when (equal "-e" (car args))
1153 ;; -e goes with the next arg, so shift one extra.
1154 (or (funcall shift)
1155 ;; -e as the last arg is an error in Perl.
55535639 1156 (error "No code specified for -e"))
a09754e6
GM
1157 (setq seen-e t))
1158 (funcall shift))
1159
d2d1851b 1160 (unless seen-e
a09754e6
GM
1161 (if (or (not args)
1162 (string-match "^-" (car args)))
55535639 1163 (error "Can't use stdin as the script to debug"))
a09754e6
GM
1164 ;; This is the program name.
1165 (funcall shift))
1166
1167 ;; If -e specified, make sure there is a -- so -emacs is not taken
1168 ;; as -e macs.
1169 (if (and args (equal "--" (car args)))
1170 (funcall shift)
d2d1851b 1171 (and seen-e (push "--" new-args)))
f2eb772d 1172
d2d1851b 1173 (push "-emacs" new-args)
f2eb772d 1174 (while args
a09754e6 1175 (funcall shift))
f2eb772d 1176
a09754e6 1177 (nreverse new-args)))
575661b1
RS
1178
1179;; There's no guarantee that Emacs will hand the filter the entire
1180;; marker at once; it could be broken up across several strings. We
1181;; might even receive a big chunk with several markers in it. If we
1182;; receive a chunk of text which looks like it might contain the
1183;; beginning of a marker, we save it here between calls to the
1184;; filter.
575661b1 1185(defun gud-perldb-marker-filter (string)
bed6a98d
RS
1186 (setq gud-marker-acc (concat gud-marker-acc string))
1187 (let ((output ""))
1188
1189 ;; Process all the complete markers in this chunk.
aa9063cb 1190 (while (string-match "\032\032\\(\\([a-zA-Z]:\\)?[^:\n]*\\):\\([0-9]*\\):.*\n"
bed6a98d
RS
1191 gud-marker-acc)
1192 (setq
1193
1194 ;; Extract the frame position from the marker.
1195 gud-last-frame
9f6991fd
SM
1196 (cons (match-string 1 gud-marker-acc)
1197 (string-to-int (match-string 3 gud-marker-acc)))
bed6a98d
RS
1198
1199 ;; Append any text before the marker to the output we're going
1200 ;; to return - we don't include the marker in this text.
1201 output (concat output
1202 (substring gud-marker-acc 0 (match-beginning 0)))
1203
1204 ;; Set the accumulator to the remaining text.
1205 gud-marker-acc (substring gud-marker-acc (match-end 0))))
1206
1207 ;; Does the remaining text look like it might end with the
1208 ;; beginning of another marker? If it does, then keep it in
f5851398 1209 ;; gud-marker-acc until we receive the rest of it. Since we
bed6a98d
RS
1210 ;; know the full marker regexp above failed, it's pretty simple to
1211 ;; test for marker starts.
1212 (if (string-match "\032.*\\'" gud-marker-acc)
1213 (progn
1214 ;; Everything before the potential marker start can be output.
1215 (setq output (concat output (substring gud-marker-acc
1216 0 (match-beginning 0))))
1217
1218 ;; Everything after, we save, to combine with later input.
1219 (setq gud-marker-acc
1220 (substring gud-marker-acc (match-beginning 0))))
1221
1222 (setq output (concat output gud-marker-acc)
1223 gud-marker-acc ""))
1224
1225 output))
575661b1 1226
8b5cd4d0
SM
1227(defcustom gud-perldb-command-name "perl -d"
1228 "Default command to execute a Perl script under debugger."
69c1dd37
RS
1229 :type 'string
1230 :group 'gud)
9ab5d005 1231
575661b1
RS
1232;;;###autoload
1233(defun perldb (command-line)
1234 "Run perldb on program FILE in buffer *gud-FILE*.
1235The directory containing FILE becomes the initial working directory
1236and source-file directory for your debugger."
1237 (interactive
c157af51
SM
1238 (list (gud-query-cmdline 'perldb
1239 (concat (or (buffer-file-name) "-e 0") " "))))
575661b1 1240
ee97eac3 1241 (gud-common-init command-line 'gud-perldb-massage-args
b94a3001 1242 'gud-perldb-marker-filter)
c157af51 1243 (set (make-local-variable 'gud-minor-mode) 'perldb)
575661b1 1244
c6094cae
EZ
1245 (gud-def gud-break "b %l" "\C-b" "Set breakpoint at current line.")
1246 (gud-def gud-remove "d %l" "\C-d" "Remove breakpoint at current line")
1247 (gud-def gud-step "s" "\C-s" "Step one source line with display.")
1248 (gud-def gud-next "n" "\C-n" "Step one line (skip functions).")
1249 (gud-def gud-cont "c" "\C-r" "Continue with display.")
1250; (gud-def gud-finish "finish" "\C-f" "Finish executing current function.")
1251; (gud-def gud-up "up %p" "<" "Up N stack frames (numeric arg).")
2c32e5c6 1252; (gud-def gud-down "down %p" ">" "Down N stack frames (numeric arg).")
c6094cae 1253 (gud-def gud-print "%e" "\C-p" "Evaluate perl expression at point.")
2c32e5c6 1254
9cd1fbc3 1255 (setq comint-prompt-regexp "^ DB<+[0-9]+>+ ")
f54877b2 1256 (setq paragraph-start comint-prompt-regexp)
c157af51 1257 (run-hooks 'perldb-mode-hook))
c3fd0eea 1258\f
d2d23393
RS
1259;; ======================================================================
1260;; pdb (Python debugger) functions
1261
8b5cd4d0 1262;; History of argument lists passed to pdb.
d2d23393
RS
1263(defvar gud-pdb-history nil)
1264
d2d23393
RS
1265;; Last group is for return value, e.g. "> test.py(2)foo()->None"
1266;; Either file or function name may be omitted: "> <string>(0)?()"
1267(defvar gud-pdb-marker-regexp
a385f6bf 1268 "^> \\([-a-zA-Z0-9_/.:\\]*\\|<string>\\)(\\([0-9]+\\))\\([a-zA-Z0-9_]*\\|\\?\\)()\\(->[^\n]*\\)?\n")
d2d23393
RS
1269(defvar gud-pdb-marker-regexp-file-group 1)
1270(defvar gud-pdb-marker-regexp-line-group 2)
1271(defvar gud-pdb-marker-regexp-fnname-group 3)
1272
1273(defvar gud-pdb-marker-regexp-start "^> ")
1274
1275;; There's no guarantee that Emacs will hand the filter the entire
1276;; marker at once; it could be broken up across several strings. We
1277;; might even receive a big chunk with several markers in it. If we
1278;; receive a chunk of text which looks like it might contain the
1279;; beginning of a marker, we save it here between calls to the
1280;; filter.
1281(defun gud-pdb-marker-filter (string)
1282 (setq gud-marker-acc (concat gud-marker-acc string))
1283 (let ((output ""))
1284
1285 ;; Process all the complete markers in this chunk.
1286 (while (string-match gud-pdb-marker-regexp gud-marker-acc)
1287 (setq
1288
1289 ;; Extract the frame position from the marker.
1290 gud-last-frame
1291 (let ((file (match-string gud-pdb-marker-regexp-file-group
1292 gud-marker-acc))
1293 (line (string-to-int
1294 (match-string gud-pdb-marker-regexp-line-group
1295 gud-marker-acc))))
1296 (if (string-equal file "<string>")
1297 gud-last-frame
1298 (cons file line)))
1299
1300 ;; Output everything instead of the below
1301 output (concat output (substring gud-marker-acc 0 (match-end 0)))
f5851398
EZ
1302;; ;; Append any text before the marker to the output we're going
1303;; ;; to return - we don't include the marker in this text.
1304;; output (concat output
1305;; (substring gud-marker-acc 0 (match-beginning 0)))
d2d23393
RS
1306
1307 ;; Set the accumulator to the remaining text.
1308 gud-marker-acc (substring gud-marker-acc (match-end 0))))
1309
1310 ;; Does the remaining text look like it might end with the
1311 ;; beginning of another marker? If it does, then keep it in
f5851398 1312 ;; gud-marker-acc until we receive the rest of it. Since we
d2d23393
RS
1313 ;; know the full marker regexp above failed, it's pretty simple to
1314 ;; test for marker starts.
1315 (if (string-match gud-pdb-marker-regexp-start gud-marker-acc)
1316 (progn
1317 ;; Everything before the potential marker start can be output.
1318 (setq output (concat output (substring gud-marker-acc
1319 0 (match-beginning 0))))
1320
1321 ;; Everything after, we save, to combine with later input.
1322 (setq gud-marker-acc
1323 (substring gud-marker-acc (match-beginning 0))))
1324
1325 (setq output (concat output gud-marker-acc)
1326 gud-marker-acc ""))
1327
1328 output))
1329
d2d23393
RS
1330(defcustom gud-pdb-command-name "pdb"
1331 "File name for executing the Python debugger.
1332This should be an executable on your path, or an absolute file name."
1333 :type 'string
1334 :group 'gud)
1335
1336;;;###autoload
1337(defun pdb (command-line)
1338 "Run pdb on program FILE in buffer `*gud-FILE*'.
1339The directory containing FILE becomes the initial working directory
1340and source-file directory for your debugger."
1341 (interactive
c157af51 1342 (list (gud-query-cmdline 'pdb)))
d2d23393 1343
b94a3001 1344 (gud-common-init command-line nil 'gud-pdb-marker-filter)
c157af51 1345 (set (make-local-variable 'gud-minor-mode) 'pdb)
d2d23393
RS
1346
1347 (gud-def gud-break "break %l" "\C-b" "Set breakpoint at current line.")
a385f6bf 1348 (gud-def gud-remove "clear %f:%l" "\C-d" "Remove breakpoint at current line")
c6094cae
EZ
1349 (gud-def gud-step "step" "\C-s" "Step one source line with display.")
1350 (gud-def gud-next "next" "\C-n" "Step one line (skip functions).")
d2d23393 1351 (gud-def gud-cont "continue" "\C-r" "Continue with display.")
c6094cae
EZ
1352 (gud-def gud-finish "return" "\C-f" "Finish executing current function.")
1353 (gud-def gud-up "up" "<" "Up one stack frame.")
1354 (gud-def gud-down "down" ">" "Down one stack frame.")
1355 (gud-def gud-print "p %e" "\C-p" "Evaluate Python expression at point.")
d2d23393 1356 ;; Is this right?
c6094cae 1357 (gud-def gud-statement "! %e" "\C-e" "Execute Python statement at point.")
d2d23393 1358
d2d23393
RS
1359 ;; (setq comint-prompt-regexp "^(.*pdb[+]?) *")
1360 (setq comint-prompt-regexp "^(Pdb) *")
1361 (setq paragraph-start comint-prompt-regexp)
1362 (run-hooks 'pdb-mode-hook))
1363\f
c3fd0eea
RS
1364;; ======================================================================
1365;;
1366;; JDB support.
1367;;
1368;; AUTHOR: Derek Davies <ddavies@world.std.com>
f5851398 1369;; Zoltan Kemenczy <zoltan@ieee.org;zkemenczy@rim.net>
c3fd0eea
RS
1370;;
1371;; CREATED: Sun Feb 22 10:46:38 1998 Derek Davies.
f5851398 1372;; UPDATED: Nov 11, 2001 Zoltan Kemenczy
b0592138 1373;; Dec 10, 2002 Zoltan Kemenczy - added nested class support
c3fd0eea
RS
1374;;
1375;; INVOCATION NOTES:
1376;;
1377;; You invoke jdb-mode with:
1378;;
1379;; M-x jdb <enter>
1380;;
1381;; It responds with:
1382;;
f4b643a1 1383;; Run jdb (like this): jdb
c3fd0eea
RS
1384;;
1385;; type any jdb switches followed by the name of the class you'd like to debug.
1386;; Supply a fully qualfied classname (these do not have the ".class" extension)
1387;; for the name of the class to debug (e.g. "COM.the-kind.ddavies.CoolClass").
1388;; See the known problems section below for restrictions when specifying jdb
1389;; command line switches (search forward for '-classpath').
1390;;
1391;; You should see something like the following:
1392;;
1393;; Current directory is ~/src/java/hello/
1394;; Initializing jdb...
1395;; 0xed2f6628:class(hello)
1396;; >
1397;;
1398;; To set an initial breakpoint try:
1399;;
1400;; > stop in hello.main
1401;; Breakpoint set in hello.main
1402;; >
1403;;
1404;; To execute the program type:
1405;;
1406;; > run
f4b643a1 1407;; run hello
c3fd0eea
RS
1408;;
1409;; Breakpoint hit: running ...
1410;; hello.main (hello:12)
1411;;
1412;; Type M-n to step over the current line and M-s to step into it. That,
1413;; along with the JDB 'help' command should get you started. The 'quit'
35dd3c55
KH
1414;; JDB command will get out out of the debugger. There is some truly
1415;; pathetic JDB documentation available at:
1416;;
1417;; http://java.sun.com/products/jdk/1.1/debugging/
c3fd0eea
RS
1418;;
1419;; KNOWN PROBLEMS AND FIXME's:
1420;;
35dd3c55 1421;; Not sure what happens with inner classes ... haven't tried them.
c3fd0eea 1422;;
c6094cae 1423;; Does not grok UNICODE id's. Only ASCII id's are supported.
c3fd0eea 1424;;
c3fd0eea
RS
1425;; You must not put whitespace between "-classpath" and the path to
1426;; search for java classes even though it is required when invoking jdb
1427;; from the command line. See gud-jdb-massage-args for details.
e78e1cd1 1428;; The same applies for "-sourcepath".
c3fd0eea 1429;;
2ef4e909
RS
1430;; Note: The following applies only if `gud-jdb-use-classpath' is nil;
1431;; refer to the documentation of `gud-jdb-use-classpath' and
e78e1cd1
EZ
1432;; `gud-jdb-classpath',`gud-jdb-sourcepath' variables for information
1433;; on using the classpath for locating java source files.
2ef4e909 1434;;
35dd3c55
KH
1435;; If any of the source files in the directories listed in
1436;; gud-jdb-directories won't parse you'll have problems. Make sure
1437;; every file ending in ".java" in these directories parses without error.
1438;;
1439;; All the .java files in the directories in gud-jdb-directories are
c6094cae 1440;; syntactically analyzed each time gud jdb is invoked. It would be
35dd3c55
KH
1441;; nice to keep as much information as possible between runs. It would
1442;; be really nice to analyze the files only as neccessary (when the
1443;; source needs to be displayed.) I'm not sure to what extent the former
1444;; can be accomplished and I'm not sure the latter can be done at all
1445;; since I don't know of any general way to tell which .class files are
1446;; defined by which .java file without analyzing all the .java files.
1447;; If anyone knows why JavaSoft didn't put the source file names in
1448;; debuggable .class files please clue me in so I find something else
1449;; to be spiteful and bitter about.
1450;;
c3fd0eea
RS
1451;; ======================================================================
1452;; gud jdb variables and functions
1453
2ef4e909
RS
1454(defcustom gud-jdb-command-name "jdb"
1455 "Command that executes the Java debugger."
1456 :type 'string
1457 :group 'gud)
1458
1459(defcustom gud-jdb-use-classpath t
1460 "If non-nil, search for Java source files in classpath directories.
1461The list of directories to search is the value of `gud-jdb-classpath'.
1462The file pathname is obtained by converting the fully qualified
1463class information output by jdb to a relative pathname and appending
1464it to `gud-jdb-classpath' element by element until a match is found.
1465
1466This method has a significant jdb startup time reduction advantage
1467since it does not require the scanning of all `gud-jdb-directories'
1468and parsing all Java files for class information.
1469
1470Set to nil to use `gud-jdb-directories' to scan java sources for
1471class information on jdb startup (original method)."
1472 :type 'boolean
1473 :group 'gud)
1474
1475(defvar gud-jdb-classpath nil
1476 "Java/jdb classpath directories list.
1477If `gud-jdb-use-classpath' is non-nil, gud-jdb derives the `gud-jdb-classpath'
1478list automatically using the following methods in sequence
8b5cd4d0 1479\(with subsequent successful steps overriding the results of previous
2ef4e909
RS
1480steps):
1481
14821) Read the CLASSPATH environment variable,
14832) Read any \"-classpath\" argument used to run jdb,
1484 or detected in jdb output (e.g. if jdb is run by a script
1485 that echoes the actual jdb command before starting jdb)
14863) Send a \"classpath\" command to jdb and scan jdb output for
1487 classpath information if jdb is invoked with an \"-attach\" (to
1488 an already running VM) argument (This case typically does not
1489 have a \"-classpath\" command line argument - that is provided
1490 to the VM when it is started).
1491
1492Note that method 3 cannot be used with oldjdb (or Java 1 jdb) since
1493those debuggers do not support the classpath command. Use 1) or 2).")
1494
e78e1cd1
EZ
1495(defvar gud-jdb-sourcepath nil
1496 "Directory list provided by an (optional) \"-sourcepath\" option to jdb.
1497This list is prepended to `gud-jdb-classpath' to form the complete
1498list of directories searched for source files.")
1499
2ef4e909
RS
1500(defvar gud-marker-acc-max-length 4000
1501 "Maximum number of debugger output characters to keep.
1502This variable limits the size of `gud-marker-acc' which holds
1503the most recent debugger output history while searching for
1504source file information.")
1505
1506(defvar gud-jdb-history nil
1507"History of argument lists passed to jdb.")
1508
c3fd0eea
RS
1509
1510;; List of Java source file directories.
1511(defvar gud-jdb-directories (list ".")
f4b643a1 1512 "*A list of directories that gud jdb should search for source code.
8050f8c8
GM
1513The file names should be absolute, or relative to the current
1514directory.
1515
1516The set of .java files residing in the directories listed are
1517syntactically analyzed to determine the classes they define and the
c6094cae 1518packages in which these classes belong. In this way gud jdb maps the
8050f8c8
GM
1519package-qualified class names output by the jdb debugger to the source
1520file from which the class originated. This allows gud mode to keep
1521the source code display in sync with the debugging session.")
c3fd0eea 1522
2ef4e909
RS
1523(defvar gud-jdb-source-files nil
1524"List of the java source files for this debugging session.")
c3fd0eea 1525
2ef4e909
RS
1526;; Association list of fully qualified class names (package + class name)
1527;; and their source files.
1528(defvar gud-jdb-class-source-alist nil
1529"Association list of fully qualified class names and source files.")
500f12df
RS
1530
1531;; This is used to hold a source file during analysis.
1532(defvar gud-jdb-analysis-buffer nil)
1533
2ef4e909
RS
1534(defvar gud-jdb-classpath-string nil
1535"Holds temporary classpath values.")
1536
c3fd0eea 1537(defun gud-jdb-build-source-files-list (path extn)
e78e1cd1 1538"Return a list of java source files (absolute paths).
2ef4e909 1539PATH gives the directories in which to search for files with
c6094cae 1540extension EXTN. Normally EXTN is given as the regular expression
2ef4e909 1541 \"\\.java$\" ."
90757bb3 1542 (apply 'nconc (mapcar (lambda (d)
471cd1d3 1543 (when (file-directory-p d)
e5ef2f5c
SM
1544 (directory-files d t extn nil)))
1545 path)))
c3fd0eea 1546
35dd3c55
KH
1547;; Move point past whitespace.
1548(defun gud-jdb-skip-whitespace ()
1549 (skip-chars-forward " \n\r\t\014"))
1550
1551;; Move point past a "// <eol>" type of comment.
1552(defun gud-jdb-skip-single-line-comment ()
1553 (end-of-line))
1554
1555;; Move point past a "/* */" or "/** */" type of comment.
1556(defun gud-jdb-skip-traditional-or-documentation-comment ()
1557 (forward-char 2)
1558 (catch 'break
f4b643a1
RS
1559 (while (not (eobp))
1560 (if (eq (following-char) ?*)
1561 (progn
1562 (forward-char)
1563 (if (not (eobp))
1564 (if (eq (following-char) ?/)
1565 (progn
1566 (forward-char)
1567 (throw 'break nil)))))
1568 (forward-char)))))
1569
35dd3c55
KH
1570;; Move point past any number of consecutive whitespace chars and/or comments.
1571(defun gud-jdb-skip-whitespace-and-comments ()
1572 (gud-jdb-skip-whitespace)
1573 (catch 'done
f4b643a1
RS
1574 (while t
1575 (cond
1576 ((looking-at "//")
1577 (gud-jdb-skip-single-line-comment)
1578 (gud-jdb-skip-whitespace))
1579 ((looking-at "/\\*")
1580 (gud-jdb-skip-traditional-or-documentation-comment)
1581 (gud-jdb-skip-whitespace))
1582 (t (throw 'done nil))))))
35dd3c55
KH
1583
1584;; Move point past things that are id-like. The intent is to skip regular
1585;; id's, such as class or interface names as well as package and interface
1586;; names.
1587(defun gud-jdb-skip-id-ish-thing ()
1588 (skip-chars-forward "^ /\n\r\t\014,;{"))
1589
1590;; Move point past a string literal.
1591(defun gud-jdb-skip-string-literal ()
1592 (forward-char)
73739399
RS
1593 (while (not (cond
1594 ((eq (following-char) ?\\)
1595 (forward-char))
1596 ((eq (following-char) ?\042))))
f4b643a1 1597 (forward-char))
35dd3c55
KH
1598 (forward-char))
1599
1600;; Move point past a character literal.
1601(defun gud-jdb-skip-character-literal ()
1602 (forward-char)
1603 (while
f4b643a1
RS
1604 (progn
1605 (if (eq (following-char) ?\\)
1606 (forward-char 2))
1607 (not (eq (following-char) ?\')))
1608 (forward-char))
35dd3c55 1609 (forward-char))
f4b643a1 1610
f5851398 1611;; Move point past the following block. There may be (legal) cruft before
35dd3c55
KH
1612;; the block's opening brace. There must be a block or it's the end of life
1613;; in petticoat junction.
1614(defun gud-jdb-skip-block ()
f4b643a1 1615
35dd3c55
KH
1616 ;; Find the begining of the block.
1617 (while
f4b643a1
RS
1618 (not (eq (following-char) ?{))
1619
1620 ;; Skip any constructs that can harbor literal block delimiter
1621 ;; characters and/or the delimiters for the constructs themselves.
1622 (cond
1623 ((looking-at "//")
1624 (gud-jdb-skip-single-line-comment))
1625 ((looking-at "/\\*")
1626 (gud-jdb-skip-traditional-or-documentation-comment))
1627 ((eq (following-char) ?\042)
1628 (gud-jdb-skip-string-literal))
1629 ((eq (following-char) ?\')
1630 (gud-jdb-skip-character-literal))
1631 (t (forward-char))))
35dd3c55 1632
35dd3c55
KH
1633 ;; Now at the begining of the block.
1634 (forward-char)
1635
1636 ;; Skip over the body of the block as well as the final brace.
1637 (let ((open-level 1))
f4b643a1
RS
1638 (while (not (eq open-level 0))
1639 (cond
1640 ((looking-at "//")
1641 (gud-jdb-skip-single-line-comment))
1642 ((looking-at "/\\*")
1643 (gud-jdb-skip-traditional-or-documentation-comment))
1644 ((eq (following-char) ?\042)
1645 (gud-jdb-skip-string-literal))
1646 ((eq (following-char) ?\')
1647 (gud-jdb-skip-character-literal))
1648 ((eq (following-char) ?{)
1649 (setq open-level (+ open-level 1))
1650 (forward-char))
1651 ((eq (following-char) ?})
1652 (setq open-level (- open-level 1))
1653 (forward-char))
1654 (t (forward-char))))))
35dd3c55
KH
1655
1656;; Find the package and class definitions in Java source file FILE. Assumes
1657;; that FILE contains a legal Java program. BUF is a scratch buffer used
1658;; to hold the source during analysis.
1659(defun gud-jdb-analyze-source (buf file)
1660 (let ((l nil))
f4b643a1
RS
1661 (set-buffer buf)
1662 (insert-file-contents file nil nil nil t)
1663 (goto-char 0)
1664 (catch 'abort
1665 (let ((p ""))
1666 (while (progn
1667 (gud-jdb-skip-whitespace)
1668 (not (eobp)))
1669 (cond
1670
c6094cae 1671 ;; Any number of semi's following a block is legal. Move point
f4b643a1
RS
1672 ;; past them. Note that comments and whitespace may be
1673 ;; interspersed as well.
1674 ((eq (following-char) ?\073)
1675 (forward-char))
1676
1677 ;; Move point past a single line comment.
1678 ((looking-at "//")
1679 (gud-jdb-skip-single-line-comment))
1680
1681 ;; Move point past a traditional or documentation comment.
1682 ((looking-at "/\\*")
1683 (gud-jdb-skip-traditional-or-documentation-comment))
1684
1685 ;; Move point past a package statement, but save the PackageName.
1686 ((looking-at "package")
1687 (forward-char 7)
1688 (gud-jdb-skip-whitespace-and-comments)
1689 (let ((s (point)))
1690 (gud-jdb-skip-id-ish-thing)
1691 (setq p (concat (buffer-substring s (point)) "."))
1692 (gud-jdb-skip-whitespace-and-comments)
1693 (if (eq (following-char) ?\073)
1694 (forward-char))))
1695
1696 ;; Move point past an import statement.
1697 ((looking-at "import")
1698 (forward-char 6)
1699 (gud-jdb-skip-whitespace-and-comments)
1700 (gud-jdb-skip-id-ish-thing)
1701 (gud-jdb-skip-whitespace-and-comments)
1702 (if (eq (following-char) ?\073)
1703 (forward-char)))
1704
1705 ;; Move point past the various kinds of ClassModifiers.
1706 ((looking-at "public")
1707 (forward-char 6))
1708 ((looking-at "abstract")
1709 (forward-char 8))
1710 ((looking-at "final")
1711 (forward-char 5))
1712
1713 ;; Move point past a ClassDeclaraction, but save the class
1714 ;; Identifier.
1715 ((looking-at "class")
1716 (forward-char 5)
1717 (gud-jdb-skip-whitespace-and-comments)
1718 (let ((s (point)))
1719 (gud-jdb-skip-id-ish-thing)
1720 (setq
1721 l (nconc l (list (concat p (buffer-substring s (point)))))))
1722 (gud-jdb-skip-block))
1723
1724 ;; Move point past an interface statement.
1725 ((looking-at "interface")
1726 (forward-char 9)
1727 (gud-jdb-skip-block))
1728
1729 ;; Anything else means the input is invalid.
1730 (t
1731 (message (format "Error parsing file %s." file))
1732 (throw 'abort nil))))))
1733 l))
35dd3c55
KH
1734
1735(defun gud-jdb-build-class-source-alist-for-file (file)
1736 (mapcar
1737 (lambda (c)
f4b643a1 1738 (cons c file))
35dd3c55 1739 (gud-jdb-analyze-source gud-jdb-analysis-buffer file)))
c3fd0eea 1740
c3fd0eea
RS
1741;; Return an alist of fully qualified classes and the source files
1742;; holding their definitions. SOURCES holds a list of all the source
1743;; files to examine.
1744(defun gud-jdb-build-class-source-alist (sources)
b2e60475 1745 (setq gud-jdb-analysis-buffer (get-buffer-create " *gud-jdb-scratch*"))
35dd3c55 1746 (prog1
f4b643a1
RS
1747 (apply
1748 'nconc
1749 (mapcar
1750 'gud-jdb-build-class-source-alist-for-file
1751 sources))
1752 (kill-buffer gud-jdb-analysis-buffer)
1753 (setq gud-jdb-analysis-buffer nil)))
c3fd0eea
RS
1754
1755;; Change what was given in the minibuffer to something that can be used to
1756;; invoke the debugger.
1757(defun gud-jdb-massage-args (file args)
1758 ;; The jdb executable must have whitespace between "-classpath" and
f4b643a1 1759 ;; its value while gud-common-init expects all switch values to
c6094cae 1760 ;; follow the switch keyword without intervening whitespace. We
c3fd0eea
RS
1761 ;; require that when the user enters the "-classpath" switch in the
1762 ;; EMACS minibuffer that they do so without the intervening
1763 ;; whitespace. This function adds it back (it's called after
c6094cae 1764 ;; gud-common-init). There are more switches like this (for
c3fd0eea
RS
1765 ;; instance "-host" and "-password") but I don't care about them
1766 ;; yet.
1767 (if args
f4b643a1
RS
1768 (let (massaged-args user-error)
1769
e78e1cd1
EZ
1770 (while (and args (not user-error))
1771 (cond
1772 ((setq user-error (string-match "-classpath$" (car args))))
1773 ((setq user-error (string-match "-sourcepath$" (car args))))
1774 ((string-match "-classpath\\(.+\\)" (car args))
1775 (setq massaged-args
1776 (append massaged-args
9f6991fd
SM
1777 (list "-classpath"
1778 (setq gud-jdb-classpath-string
1779 (match-string 1 (car args)))))))
e78e1cd1
EZ
1780 ((string-match "-sourcepath\\(.+\\)" (car args))
1781 (setq massaged-args
1782 (append massaged-args
9f6991fd
SM
1783 (list "-sourcepath"
1784 (setq gud-jdb-sourcepath
1785 (match-string 1 (car args)))))))
e78e1cd1 1786 (t (setq massaged-args (append massaged-args (list (car args))))))
f4b643a1
RS
1787 (setq args (cdr args)))
1788
1789 ;; By this point the current directory is all screwed up. Maybe we
1790 ;; could fix things and re-invoke gud-common-init, but for now I think
1791 ;; issueing the error is good enough.
1792 (if user-error
1793 (progn
1794 (kill-buffer (current-buffer))
e78e1cd1
EZ
1795 (error "Error: Omit whitespace between '-classpath or -sourcepath' and its value")))
1796 massaged-args)))
c3fd0eea
RS
1797
1798;; Search for an association with P, a fully qualified class name, in
f5851398 1799;; gud-jdb-class-source-alist. The asssociation gives the fully
c3fd0eea
RS
1800;; qualified file name of the source file which produced the class.
1801(defun gud-jdb-find-source-file (p)
1802 (cdr (assoc p gud-jdb-class-source-alist)))
1803
2ef4e909
RS
1804;; Note: Reset to this value every time a prompt is seen
1805(defvar gud-jdb-lowest-stack-level 999)
1806
1807(defun gud-jdb-find-source-using-classpath (p)
1808"Find source file corresponding to fully qualified class p.
1809Convert p from jdb's output, converted to a pathname
1810relative to a classpath directory."
1811 (save-match-data
1812 (let
1813 (;; Replace dots with slashes and append ".java" to generate file
1814 ;; name relative to classpath
1815 (filename
f5851398 1816 (concat
b0592138 1817 (mapconcat 'identity
f5851398
EZ
1818 (split-string
1819 ;; Eliminate any subclass references in the class
1820 ;; name string. These start with a "$"
1821 ((lambda (x)
1822 (if (string-match "$.*" x)
1823 (replace-match "" t t x) p))
1824 p)
1825 "\\.") "/")
1826 ".java"))
e78e1cd1 1827 (cplist (append gud-jdb-sourcepath gud-jdb-classpath))
2ef4e909
RS
1828 found-file)
1829 (while (and cplist
f5851398
EZ
1830 (not (setq found-file
1831 (file-readable-p
1832 (concat (car cplist) "/" filename)))))
2ef4e909
RS
1833 (setq cplist (cdr cplist)))
1834 (if found-file (concat (car cplist) "/" filename)))))
1835
1836(defun gud-jdb-find-source (string)
1837"Alias for function used to locate source files.
1838Set to `gud-jdb-find-source-using-classpath' or `gud-jdb-find-source-file'
1839during jdb initialization depending on the value of
1840`gud-jdb-use-classpath'."
1841nil)
1842
1843(defun gud-jdb-parse-classpath-string (string)
1844"Parse the classpath list and convert each item to an absolute pathname."
e78e1cd1 1845 (mapcar (lambda (s) (if (string-match "[/\\]$" s)
f5851398
EZ
1846 (replace-match "" nil nil s) s))
1847 (mapcar 'file-truename
1848 (split-string
1849 string
1850 (concat "[ \t\n\r,\"" path-separator "]+")))))
2ef4e909 1851
c3fd0eea
RS
1852;; See comentary for other debugger's marker filters - there you will find
1853;; important notes about STRING.
1854(defun gud-jdb-marker-filter (string)
1855
1856 ;; Build up the accumulator.
1857 (setq gud-marker-acc
f4b643a1
RS
1858 (if gud-marker-acc
1859 (concat gud-marker-acc string)
1860 string))
c3fd0eea 1861
2ef4e909 1862 ;; Look for classpath information until gud-jdb-classpath-string is found
e78e1cd1
EZ
1863 ;; (interactive, multiple settings of classpath from jdb
1864 ;; not supported/followed)
2ef4e909 1865 (if (and gud-jdb-use-classpath
f5851398
EZ
1866 (not gud-jdb-classpath-string)
1867 (or (string-match "classpath:[ \t[]+\\([^]]+\\)" gud-marker-acc)
1868 (string-match "-classpath[ \t\"]+\\([^ \"]+\\)" gud-marker-acc)))
2ef4e909 1869 (setq gud-jdb-classpath
f5851398
EZ
1870 (gud-jdb-parse-classpath-string
1871 (setq gud-jdb-classpath-string
9f6991fd 1872 (match-string 1 gud-marker-acc)))))
2ef4e909
RS
1873
1874 ;; We process STRING from left to right. Each time through the
1875 ;; following loop we process at most one marker. After we've found a
1876 ;; marker, delete gud-marker-acc up to and including the match
1877 (let (file-found)
1878 ;; Process each complete marker in the input.
f4b643a1
RS
1879 (while
1880
1881 ;; Do we see a marker?
1882 (string-match
1883 ;; jdb puts out a string of the following form when it
1884 ;; hits a breakpoint:
1885 ;;
f5851398 1886 ;; <fully-qualified-class><method> (<class>:<line-number>)
f4b643a1
RS
1887 ;;
1888 ;; <fully-qualified-class>'s are composed of Java ID's
1889 ;; separated by periods. <method> and <class> are
1890 ;; also Java ID's. <method> begins with a period and
1891 ;; may contain less-than and greater-than (constructors,
1892 ;; for instance, are called <init> in the symbol table.)
1893 ;; Java ID's begin with a letter followed by letters
1894 ;; and/or digits. The set of letters includes underscore
1895 ;; and dollar sign.
1896 ;;
1897 ;; The first group matches <fully-qualified-class>,
1898 ;; the second group matches <class> and the third group
1899 ;; matches <line-number>. We don't care about using
1900 ;; <method> so we don't "group" it.
1901 ;;
1902 ;; FIXME: Java ID's are UNICODE strings, this matches ASCII
1903 ;; ID's only.
b0592138
PJ
1904 ;;
1905 ;; The "," in the last square-bracket is necessary because of
1906 ;; Sun's total disrespect for backwards compatibility in
1907 ;; reported line numbers from jdb - starting in 1.4.0 they
1908 ;; introduced a comma at the thousands position (how
1909 ;; ingenious!)
1910
1911 "\\(\[[0-9]+\] \\)*\\([a-zA-Z0-9.$_]+\\)\\.[a-zA-Z0-9$_<>(),]+ \
1912\\(([a-zA-Z0-9.$_]+:\\|line=\\)\\([0-9,]+\\)"
2ef4e909
RS
1913 gud-marker-acc)
1914
1915 ;; A good marker is one that:
1916 ;; 1) does not have a "[n] " prefix (not part of a stack backtrace)
1917 ;; 2) does have an "[n] " prefix and n is the lowest prefix seen
1918 ;; since the last prompt
f4b643a1
RS
1919 ;; Figure out the line on which to position the debugging arrow.
1920 ;; Return the info as a cons of the form:
1921 ;;
1922 ;; (<file-name> . <line-number>) .
2ef4e909
RS
1923 (if (if (match-beginning 1)
1924 (let (n)
b0592138
PJ
1925 (setq n (string-to-int (substring
1926 gud-marker-acc
1927 (1+ (match-beginning 1))
1928 (- (match-end 1) 2))))
2ef4e909
RS
1929 (if (< n gud-jdb-lowest-stack-level)
1930 (progn (setq gud-jdb-lowest-stack-level n) t)))
f5851398 1931 t)
2ef4e909 1932 (if (setq file-found
9f6991fd 1933 (gud-jdb-find-source (match-string 2 gud-marker-acc)))
2ef4e909
RS
1934 (setq gud-last-frame
1935 (cons file-found
b0592138 1936 (string-to-int
71296446 1937 (let
b0592138
PJ
1938 ((numstr (match-string 4 gud-marker-acc)))
1939 (if (string-match "," numstr)
1940 (replace-match "" nil nil numstr)
1941 numstr)))))
2ef4e909
RS
1942 (message "Could not find source file.")))
1943
1944 ;; Set the accumulator to the remaining text.
1945 (setq gud-marker-acc (substring gud-marker-acc (match-end 0))))
1946
1947 (if (string-match comint-prompt-regexp gud-marker-acc)
1948 (setq gud-jdb-lowest-stack-level 999)))
1949
1950 ;; Do not allow gud-marker-acc to grow without bound. If the source
1951 ;; file information is not within the last 3/4
1952 ;; gud-marker-acc-max-length characters, well,...
1953 (if (> (length gud-marker-acc) gud-marker-acc-max-length)
1954 (setq gud-marker-acc
f5851398
EZ
1955 (substring gud-marker-acc
1956 (- (/ (* gud-marker-acc-max-length 3) 4)))))
c3fd0eea
RS
1957
1958 ;; We don't filter any debugger output so just return what we were given.
1959 string)
1960
b94a3001 1961(defvar gud-jdb-command-name "jdb" "Command that executes the Java debugger.")
c3fd0eea 1962
c3fd0eea
RS
1963;;;###autoload
1964(defun jdb (command-line)
aa3b6a3f
PJ
1965 "Run jdb with command line COMMAND-LINE in a buffer.
1966The buffer is named \"*gud*\" if no initial class is given or
f5851398 1967\"*gud-<initial-class-basename>*\" if there is. If the \"-classpath\"
2ef4e909
RS
1968switch is given, omit all whitespace between it and its value.
1969
1970See `gud-jdb-use-classpath' and `gud-jdb-classpath' documentation for
1971information on how jdb accesses source files. Alternatively (if
1972`gud-jdb-use-classpath' is nil), see `gud-jdb-directories' for the
1973original source file access method.
1974
1975For general information about commands available to control jdb from
1976gud, see `gud-mode'."
c3fd0eea 1977 (interactive
c157af51 1978 (list (gud-query-cmdline 'jdb)))
e78e1cd1
EZ
1979 (setq gud-jdb-classpath nil)
1980 (setq gud-jdb-sourcepath nil)
c3fd0eea 1981
2ef4e909
RS
1982 ;; Set gud-jdb-classpath from the CLASSPATH environment variable,
1983 ;; if CLASSPATH is set.
1984 (setq gud-jdb-classpath-string (getenv "CLASSPATH"))
1985 (if gud-jdb-classpath-string
1986 (setq gud-jdb-classpath
f5851398
EZ
1987 (gud-jdb-parse-classpath-string gud-jdb-classpath-string)))
1988 (setq gud-jdb-classpath-string nil) ; prepare for next
2ef4e909 1989
c3fd0eea 1990 (gud-common-init command-line 'gud-jdb-massage-args
b94a3001 1991 'gud-jdb-marker-filter)
c157af51 1992 (set (make-local-variable 'gud-minor-mode) 'jdb)
c3fd0eea 1993
2ef4e909
RS
1994 ;; If a -classpath option was provided, set gud-jdb-classpath
1995 (if gud-jdb-classpath-string
1996 (setq gud-jdb-classpath
1997 (gud-jdb-parse-classpath-string gud-jdb-classpath-string)))
f5851398 1998 (setq gud-jdb-classpath-string nil) ; prepare for next
e78e1cd1
EZ
1999 ;; If a -sourcepath option was provided, parse it
2000 (if gud-jdb-sourcepath
2001 (setq gud-jdb-sourcepath
f5851398 2002 (gud-jdb-parse-classpath-string gud-jdb-sourcepath)))
2ef4e909
RS
2003
2004 (gud-def gud-break "stop at %c:%l" "\C-b" "Set breakpoint at current line.")
2005 (gud-def gud-remove "clear %c:%l" "\C-d" "Remove breakpoint at current line")
c6094cae
EZ
2006 (gud-def gud-step "step" "\C-s" "Step one source line with display.")
2007 (gud-def gud-next "next" "\C-n" "Step one line (skip functions).")
2008 (gud-def gud-cont "cont" "\C-r" "Continue with display.")
2009 (gud-def gud-finish "step up" "\C-f" "Continue until current method returns.")
2ef4e909
RS
2010 (gud-def gud-up "up\C-Mwhere" "<" "Up one stack frame.")
2011 (gud-def gud-down "down\C-Mwhere" ">" "Up one stack frame.")
b0592138 2012 (gud-def gud-run "run" nil "Run the program.") ;if VM start using jdb
c3fd0eea 2013
2ef4e909 2014 (setq comint-prompt-regexp "^> \\|^[^ ]+\\[[0-9]+\\] ")
c3fd0eea
RS
2015 (setq paragraph-start comint-prompt-regexp)
2016 (run-hooks 'jdb-mode-hook)
2017
2ef4e909 2018 (if gud-jdb-use-classpath
e78e1cd1 2019 ;; Get the classpath information from the debugger
2ef4e909 2020 (progn
f5851398
EZ
2021 (if (string-match "-attach" command-line)
2022 (gud-call "classpath"))
2023 (fset 'gud-jdb-find-source
2024 'gud-jdb-find-source-using-classpath))
2ef4e909
RS
2025
2026 ;; Else create and bind the class/source association list as well
2027 ;; as the source file list.
2028 (setq gud-jdb-class-source-alist
f5851398
EZ
2029 (gud-jdb-build-class-source-alist
2030 (setq gud-jdb-source-files
2031 (gud-jdb-build-source-files-list gud-jdb-directories
2032 "\\.java$"))))
2ef4e909 2033 (fset 'gud-jdb-find-source 'gud-jdb-find-source-file)))
c3fd0eea 2034\f
6496f3d2 2035
d4c2acb9
RS
2036;; ======================================================================
2037;;
2038;; BASHDB support. See http://bashdb.sourceforge.net
2039;;
2040;; AUTHOR: Rocky Bernstein <rocky@panix.com>
2041;;
2042;; CREATED: Sun Nov 10 10:46:38 2002 Rocky Bernstein.
2043;;
2044;; INVOCATION NOTES:
2045;;
2046;; You invoke bashdb-mode with:
2047;;
2048;; M-x bashdb <enter>
2049;;
2050;; It responds with:
2051;;
2052;; Run bashdb (like this): bash
2053;;
2054
9f6991fd 2055;; History of argument lists passed to bashdb.
d4c2acb9
RS
2056(defvar gud-bashdb-history nil)
2057
2058;; Convert a command line as would be typed normally to run a script
2059;; into one that invokes an Emacs-enabled debugging session.
2060;; "--debugger" in inserted as the first switch.
2061
d4c2acb9
RS
2062;; There's no guarantee that Emacs will hand the filter the entire
2063;; marker at once; it could be broken up across several strings. We
2064;; might even receive a big chunk with several markers in it. If we
2065;; receive a chunk of text which looks like it might contain the
2066;; beginning of a marker, we save it here between calls to the
2067;; filter.
2068(defun gud-bashdb-marker-filter (string)
2069 (setq gud-marker-acc (concat gud-marker-acc string))
2070 (let ((output ""))
2071
2072 ;; Process all the complete markers in this chunk.
2073 ;; Format of line looks like this:
2074 ;; (/etc/init.d/ntp.init:16):
2075 ;; but we also allow DOS drive letters
2076 ;; (d:/etc/init.d/ntp.init:16):
2077 (while (string-match "\\(^\\|\n\\)(\\(\\([a-zA-Z]:\\)?[^:\n]*\\):\\([0-9]*\\)):.*\n"
2078 gud-marker-acc)
2079 (setq
2080
2081 ;; Extract the frame position from the marker.
2082 gud-last-frame
9f6991fd
SM
2083 (cons (match-string 2 gud-marker-acc)
2084 (string-to-int (match-string 4 gud-marker-acc)))
d4c2acb9
RS
2085
2086 ;; Append any text before the marker to the output we're going
2087 ;; to return - we don't include the marker in this text.
2088 output (concat output
2089 (substring gud-marker-acc 0 (match-beginning 0)))
2090
2091 ;; Set the accumulator to the remaining text.
2092 gud-marker-acc (substring gud-marker-acc (match-end 0))))
2093
2094 ;; Does the remaining text look like it might end with the
2095 ;; beginning of another marker? If it does, then keep it in
2096 ;; gud-marker-acc until we receive the rest of it. Since we
2097 ;; know the full marker regexp above failed, it's pretty simple to
2098 ;; test for marker starts.
2099 (if (string-match "\032.*\\'" gud-marker-acc)
2100 (progn
2101 ;; Everything before the potential marker start can be output.
2102 (setq output (concat output (substring gud-marker-acc
2103 0 (match-beginning 0))))
2104
2105 ;; Everything after, we save, to combine with later input.
2106 (setq gud-marker-acc
2107 (substring gud-marker-acc (match-beginning 0))))
2108
2109 (setq output (concat output gud-marker-acc)
2110 gud-marker-acc ""))
2111
2112 output))
2113
9f6991fd 2114(defcustom gud-bashdb-command-name "bash --debugger"
d4c2acb9
RS
2115 "File name for executing bash debugger."
2116 :type 'string
2117 :group 'gud)
2118
2119;;;###autoload
2120(defun bashdb (command-line)
2121 "Run bashdb on program FILE in buffer *gud-FILE*.
2122The directory containing FILE becomes the initial working directory
2123and source-file directory for your debugger."
2124 (interactive
2125 (list (read-from-minibuffer "Run bashdb (like this): "
2126 (if (consp gud-bashdb-history)
2127 (car gud-bashdb-history)
2128 (concat gud-bashdb-command-name
2129 " "))
2130 gud-minibuffer-local-map nil
2131 '(gud-bashdb-history . 1))))
2132
9f6991fd 2133 (gud-common-init command-line nil 'gud-bashdb-marker-filter)
d4c2acb9
RS
2134
2135 (set (make-local-variable 'gud-minor-mode) 'bashdb)
2136
2137 (gud-def gud-break "break %l" "\C-b" "Set breakpoint at current line.")
2138 (gud-def gud-tbreak "tbreak %l" "\C-t" "Set temporary breakpoint at current line.")
2139 (gud-def gud-remove "clear %l" "\C-d" "Remove breakpoint at current line")
2140 (gud-def gud-step "step" "\C-s" "Step one source line with display.")
2141 (gud-def gud-next "next" "\C-n" "Step one line (skip functions).")
2142 (gud-def gud-cont "continue" "\C-r" "Continue with display.")
2143 (gud-def gud-finish "finish" "\C-f" "Finish executing current function.")
2144 (gud-def gud-up "up %p" "<" "Up N stack frames (numeric arg).")
2145 (gud-def gud-down "down %p" ">" "Down N stack frames (numeric arg).")
9cd1fbc3 2146 (gud-def gud-print "x %e" "\C-p" "Evaluate BASH expression at point.")
d4c2acb9
RS
2147
2148 ;; Is this right?
9cd1fbc3 2149 (gud-def gud-statement "eval %e" "\C-e" "Execute BASH statement at point.")
d4c2acb9 2150
9cd1fbc3 2151 (setq comint-prompt-regexp "^bashdb<+(*[0-9]+)*>+ ")
d4c2acb9
RS
2152 (setq paragraph-start comint-prompt-regexp)
2153 (run-hooks 'bashdb-mode-hook)
2154 )
2155
13b80a60
ER
2156;;
2157;; End of debugger-specific information
10a4c11f 2158;;
13b80a60 2159
575661b1 2160\f
8b5cd4d0
SM
2161;; When we send a command to the debugger via gud-call, it's annoying
2162;; to see the command and the new prompt inserted into the debugger's
2163;; buffer; we have other ways of knowing the command has completed.
2164;;
2165;; If the buffer looks like this:
2166;; --------------------
2167;; (gdb) set args foo bar
2168;; (gdb) -!-
2169;; --------------------
2170;; (the -!- marks the location of point), and we type `C-x SPC' in a
2171;; source file to set a breakpoint, we want the buffer to end up like
2172;; this:
2173;; --------------------
2174;; (gdb) set args foo bar
2175;; Breakpoint 1 at 0x92: file make-docfile.c, line 49.
2176;; (gdb) -!-
2177;; --------------------
2178;; Essentially, the old prompt is deleted, and the command's output
2179;; and the new prompt take its place.
2180;;
2181;; Not echoing the command is easy enough; you send it directly using
2182;; process-send-string, and it never enters the buffer. However,
2183;; getting rid of the old prompt is trickier; you don't want to do it
2184;; when you send the command, since that will result in an annoying
2185;; flicker as the prompt is deleted, redisplay occurs while Emacs
2186;; waits for a response from the debugger, and the new prompt is
2187;; inserted. Instead, we'll wait until we actually get some output
2188;; from the subprocess before we delete the prompt. If the command
2189;; produced no output other than a new prompt, that prompt will most
2190;; likely be in the first chunk of output received, so we will delete
2191;; the prompt and then replace it with an identical one. If the
2192;; command produces output, the prompt is moving anyway, so the
2193;; flicker won't be annoying.
2194;;
2195;; So - when we want to delete the prompt upon receipt of the next
2196;; chunk of debugger output, we position gud-delete-prompt-marker at
2197;; the start of the prompt; the process filter will notice this, and
2198;; delete all text between it and the process output marker. If
2199;; gud-delete-prompt-marker points nowhere, we leave the current
2200;; prompt alone.
53eb3a97
JB
2201(defvar gud-delete-prompt-marker nil)
2202
13b80a60 2203\f
c47264b3
RS
2204(put 'gud-mode 'mode-class 'special)
2205
c157af51 2206(define-derived-mode gud-mode comint-mode "Debugger"
13b80a60 2207 "Major mode for interacting with an inferior debugger process.
24d725c2 2208
6496f3d2 2209 You start it up with one of the commands M-x gdb, M-x sdb, M-x dbx,
2ef4e909 2210M-x perldb, M-x xdb, or M-x jdb. Each entry point finishes by executing a
b0764b2d 2211hook; `gdb-mode-hook', `sdb-mode-hook', `dbx-mode-hook',
2ef4e909 2212`perldb-mode-hook', `xdb-mode-hook', or `jdb-mode-hook' respectively.
24d725c2 2213
ee0155df
ER
2214After startup, the following commands are available in both the GUD
2215interaction buffer and any source buffer GUD visits due to a breakpoint stop
2216or step operation:
13b80a60 2217
ee0155df
ER
2218\\[gud-break] sets a breakpoint at the current file and line. In the
2219GUD buffer, the current file and line are those of the last breakpoint or
2220step. In a source buffer, they are the buffer's file and current line.
2221
45025813
ER
2222\\[gud-remove] removes breakpoints on the current file and line.
2223
ee0155df 2224\\[gud-refresh] displays in the source window the last line referred to
24d725c2 2225in the gud buffer.
13b80a60 2226
ee0155df
ER
2227\\[gud-step], \\[gud-next], and \\[gud-stepi] do a step-one-line,
2228step-one-line (not entering function calls), and step-one-instruction
2229and then update the source window with the current file and position.
2230\\[gud-cont] continues execution.
13b80a60 2231
ee0155df
ER
2232\\[gud-print] tries to find the largest C lvalue or function-call expression
2233around point, and sends it to the debugger for value display.
24d725c2 2234
6496f3d2
RS
2235The above commands are common to all supported debuggers except xdb which
2236does not support stepping instructions.
24d725c2 2237
6496f3d2 2238Under gdb, sdb and xdb, \\[gud-tbreak] behaves exactly like \\[gud-break],
ee0155df
ER
2239except that the breakpoint is temporary; that is, it is removed when
2240execution stops on it.
24d725c2 2241
6496f3d2 2242Under gdb, dbx, and xdb, \\[gud-up] pops up through an enclosing stack
c6094cae 2243frame. \\[gud-down] drops back down through one.
24d725c2 2244
6496f3d2 2245If you are using gdb or xdb, \\[gud-finish] runs execution to the return from
ee0155df 2246the current function and stops.
24d725c2 2247
dcec1a3b
RS
2248All the keystrokes above are accessible in the GUD buffer
2249with the prefix C-c, and in all buffers through the prefix C-x C-a.
45025813 2250
ee0155df
ER
2251All pre-defined functions for which the concept make sense repeat
2252themselves the appropriate number of times if you give a prefix
2253argument.
13b80a60 2254
dcec1a3b 2255You may use the `gud-def' macro in the initialization hook to define other
ee0155df 2256commands.
13b80a60 2257
24d725c2
ER
2258Other commands for interacting with the debugger process are inherited from
2259comint mode, which see."
0b358e64 2260 (setq mode-line-process '(":%s"))
2b64612d 2261 (define-key (current-local-map) "\C-c\C-l" 'gud-refresh)
c157af51 2262 (set (make-local-variable 'gud-last-frame) nil)
f36ca832 2263 (set (make-local-variable 'tool-bar-map) gud-tool-bar-map)
13b80a60 2264 (make-local-variable 'comint-prompt-regexp)
aa9063cb 2265 ;; Don't put repeated commands in command history many times.
c157af51 2266 (set (make-local-variable 'comint-input-ignoredups) t)
f54877b2 2267 (make-local-variable 'paragraph-start)
c157af51 2268 (set (make-local-variable 'gud-delete-prompt-marker) (make-marker)))
a223b10d 2269
18aa807e
RS
2270;; Cause our buffers to be displayed, by default,
2271;; in the selected window.
2272;;;###autoload (add-hook 'same-window-regexps "\\*gud-.*\\*\\(\\|<[0-9]+>\\)")
2273
d2d1851b
SM
2274(defcustom gud-chdir-before-run t
2275 "Non-nil if GUD should `cd' to the debugged executable."
2276 :group 'gud
2277 :type 'boolean)
2278
9f6991fd
SM
2279(defvar gud-target-name "--unknown--"
2280 "The apparent name of the program being debugged in a gud buffer.")
2281
a223b10d 2282;; Perform initializations common to all debuggers.
ee97eac3
RS
2283;; The first arg is the specified command line,
2284;; which starts with the program to debug.
2285;; The other three args specify the values to use
2286;; for local variables in the debugger buffer.
b94a3001
SM
2287(defun gud-common-init (command-line massage-args marker-filter
2288 &optional find-file)
c157af51 2289 (let* ((words (split-string command-line))
a223b10d 2290 (program (car words))
b94a3001 2291 (dir default-directory)
dfbd82a6
RS
2292 ;; Extract the file name from WORDS
2293 ;; and put t in its place.
2294 ;; Later on we will put the modified file name arg back there.
a223b10d
RM
2295 (file-word (let ((w (cdr words)))
2296 (while (and w (= ?- (aref (car w) 0)))
2297 (setq w (cdr w)))
c27c1042
KH
2298 (and w
2299 (prog1 (car w)
2300 (setcar w t)))))
0ec5b01d
RS
2301 (file-subst
2302 (and file-word (substitute-in-file-name file-word)))
dfbd82a6 2303 (args (cdr words))
0ec5b01d
RS
2304 ;; If a directory was specified, expand the file name.
2305 ;; Otherwise, don't expand it, so GDB can use the PATH.
2306 ;; A file name without directory is literally valid
2307 ;; only if the file exists in ., and in that case,
2308 ;; omitting the expansion here has no visible effect.
52b85866 2309 (file (and file-word
0ec5b01d
RS
2310 (if (file-name-directory file-subst)
2311 (expand-file-name file-subst)
2312 file-subst)))
c27c1042 2313 (filepart (and file-word (concat "-" (file-name-nondirectory file)))))
18aa807e 2314 (pop-to-buffer (concat "*gud" filepart "*"))
b94a3001
SM
2315 ;; Set the dir, in case the buffer already existed with a different dir.
2316 (setq default-directory dir)
0ec5b01d
RS
2317 ;; Set default-directory to the file's directory.
2318 (and file-word
d2d1851b 2319 gud-chdir-before-run
0ec5b01d
RS
2320 ;; Don't set default-directory if no directory was specified.
2321 ;; In that case, either the file is found in the current directory,
2322 ;; in which case this setq is a no-op,
2323 ;; or it is found by searching PATH,
2324 ;; in which case we don't know what directory it was found in.
2325 (file-name-directory file)
2326 (setq default-directory (file-name-directory file)))
ee97eac3
RS
2327 (or (bolp) (newline))
2328 (insert "Current directory is " default-directory "\n")
dfbd82a6
RS
2329 ;; Put the substituted and expanded file name back in its place.
2330 (let ((w args))
2331 (while (and w (not (eq (car w) t)))
2332 (setq w (cdr w)))
c27c1042
KH
2333 (if w
2334 (setcar w file)))
2335 (apply 'make-comint (concat "gud" filepart) program nil
9f6991fd
SM
2336 (if massage-args (funcall massage-args file args) args))
2337 ;; Since comint clobbered the mode, we don't set it until now.
2338 (gud-mode)
2339 (set (make-local-variable 'gud-target-name)
2340 (and file-word (file-name-nondirectory file))))
2341 (set (make-local-variable 'gud-marker-filter) marker-filter)
d2d1851b 2342 (if find-file (set (make-local-variable 'gud-find-file) find-file))
9f6991fd
SM
2343 (setq gud-running nil)
2344 (setq gud-last-last-frame nil)
ee97eac3 2345
13b80a60
ER
2346 (set-process-filter (get-buffer-process (current-buffer)) 'gud-filter)
2347 (set-process-sentinel (get-buffer-process (current-buffer)) 'gud-sentinel)
c157af51 2348 (gud-set-buffer))
13b80a60
ER
2349
2350(defun gud-set-buffer ()
c157af51
SM
2351 (when (eq major-mode 'gud-mode)
2352 (setq gud-comint-buffer (current-buffer))))
ee0155df 2353
11736488
RS
2354(defvar gud-filter-defer-flag nil
2355 "Non-nil means don't process anything from the debugger right now.
2356It is saved for when this flag is not set.")
2357
2358(defvar gud-filter-pending-text nil
2359 "Non-nil means this is text that has been saved for later in `gud-filter'.")
2360
ee0155df
ER
2361;; These functions are responsible for inserting output from your debugger
2362;; into the buffer. The hard work is done by the method that is
2363;; the value of gud-marker-filter.
13b80a60 2364
ee0155df 2365(defun gud-filter (proc string)
13b80a60 2366 ;; Here's where the actual buffer insertion is done
7f4bda7c 2367 (let (output process-window)
c561a0cb 2368 (if (buffer-name (process-buffer proc))
11736488
RS
2369 (if gud-filter-defer-flag
2370 ;; If we can't process any text now,
2371 ;; save it for later.
2372 (setq gud-filter-pending-text
2373 (concat (or gud-filter-pending-text "") string))
c7856dbe
RS
2374
2375 ;; If we have to ask a question during the processing,
2376 ;; defer any additional text that comes from the debugger
2377 ;; during that time.
2378 (let ((gud-filter-defer-flag t))
2379 ;; Process now any text we previously saved up.
2380 (if gud-filter-pending-text
2381 (setq string (concat gud-filter-pending-text string)
2382 gud-filter-pending-text nil))
f09b5567
MB
2383
2384 (with-current-buffer (process-buffer proc)
11736488 2385 ;; If we have been so requested, delete the debugger prompt.
136b4eda
MB
2386 (save-restriction
2387 (widen)
2388 (if (marker-buffer gud-delete-prompt-marker)
2389 (progn
2390 (delete-region (process-mark proc)
2391 gud-delete-prompt-marker)
2392 (set-marker gud-delete-prompt-marker nil)))
2393 ;; Save the process output, checking for source file markers.
2394 (setq output (gud-marker-filter string))
2395 ;; Check for a filename-and-line number.
2396 ;; Don't display the specified file
2397 ;; unless (1) point is at or after the position where output appears
2398 ;; and (2) this buffer is on the screen.
2399 (setq process-window
2400 (and gud-last-frame
2401 (>= (point) (process-mark proc))
2402 (get-buffer-window (current-buffer)))))
c7856dbe
RS
2403
2404 ;; Let the comint filter do the actual insertion.
2405 ;; That lets us inherit various comint features.
88be0819
RS
2406 (comint-output-filter proc output))
2407
2408 ;; Put the arrow on the source line.
2409 ;; This must be outside of the save-excursion
2410 ;; in case the source file is our current buffer.
2411 (if process-window
2412 (save-selected-window
2413 (select-window process-window)
2414 (gud-display-frame))
2415 ;; We have to be in the proper buffer, (process-buffer proc),
2416 ;; but not in a save-excursion, because that would restore point.
2417 (let ((old-buf (current-buffer)))
2418 (set-buffer (process-buffer proc))
2419 (unwind-protect
2420 (gud-display-frame)
2421 (set-buffer old-buf)))))
c7856dbe
RS
2422
2423 ;; If we deferred text that arrived during this processing,
2424 ;; handle it now.
2425 (if gud-filter-pending-text
2426 (gud-filter proc ""))))))
13b80a60
ER
2427
2428(defun gud-sentinel (proc msg)
2429 (cond ((null (buffer-name (process-buffer proc)))
2430 ;; buffer killed
2431 ;; Stop displaying an arrow in a source file.
2432 (setq overlay-arrow-position nil)
703ce2c3
NR
2433 (set-process-buffer proc nil)
2434 (if (eq gud-minor-mode-type 'gdba)
2435 (gdb-reset)
2436 (gud-reset)))
13b80a60
ER
2437 ((memq (process-status proc) '(signal exit))
2438 ;; Stop displaying an arrow in a source file.
2439 (setq overlay-arrow-position nil)
703ce2c3
NR
2440 (with-current-buffer gud-comint-buffer
2441 (if (eq gud-minor-mode 'gdba)
2442 (gdb-reset)
2443 (gud-reset)))
13b80a60
ER
2444 (let* ((obuf (current-buffer)))
2445 ;; save-excursion isn't the right thing if
2446 ;; process-buffer is current-buffer
2447 (unwind-protect
2448 (progn
2449 ;; Write something in *compilation* and hack its mode line,
2450 (set-buffer (process-buffer proc))
1a3ce5c4
AS
2451 ;; Fix the mode line.
2452 (setq mode-line-process
2453 (concat ":"
2454 (symbol-name (process-status proc))))
e726eb56 2455 (force-mode-line-update)
13b80a60
ER
2456 (if (eobp)
2457 (insert ?\n mode-name " " msg)
2458 (save-excursion
2459 (goto-char (point-max))
2460 (insert ?\n mode-name " " msg)))
2461 ;; If buffer and mode line will show that the process
2462 ;; is dead, we can delete it now. Otherwise it
2463 ;; will stay around until M-x list-processes.
2464 (delete-process proc))
2465 ;; Restore old buffer, but don't restore old point
2466 ;; if obuf is the gud buffer.
2467 (set-buffer obuf))))))
2468
703ce2c3
NR
2469(defvar gud-minor-mode-type nil)
2470
2471(defun gud-kill-buffer-hook ()
2472 (if gud-minor-mode
2473 (setq gud-minor-mode-type gud-minor-mode)))
2474
2475(add-hook 'kill-buffer-hook 'gud-kill-buffer-hook)
2476
2477(defun gud-reset ()
2478 (dolist (buffer (buffer-list))
2479 (if (not (eq buffer gud-comint-buffer))
2480 (save-excursion
2481 (set-buffer buffer)
2482 (when gud-minor-mode
2483 (setq gud-minor-mode nil)
2484 (kill-local-variable 'tool-bar-map))))))
2485
13b80a60
ER
2486(defun gud-display-frame ()
2487 "Find and obey the last filename-and-line marker from the debugger.
2488Obeying it means displaying in another window the specified file and line."
2489 (interactive)
9f6991fd
SM
2490 (when gud-last-frame
2491 (gud-set-buffer)
2492 (gud-display-line (car gud-last-frame) (cdr gud-last-frame))
2493 (setq gud-last-last-frame gud-last-frame
2494 gud-last-frame nil)))
13b80a60
ER
2495
2496;; Make sure the file named TRUE-FILE is in a buffer that appears on the screen
2497;; and that its line LINE is visible.
2498;; Put the overlay-arrow on the line LINE in that buffer.
ee0155df
ER
2499;; Most of the trickiness in here comes from wanting to preserve the current
2500;; region-restriction if that's possible. We use an explicit display-buffer
2501;; to get around the fact that this is called inside a save-excursion.
13b80a60
ER
2502
2503(defun gud-display-line (true-file line)
8f6c93e2 2504 (let* ((last-nonmenu-event t) ; Prevent use of dialog box for questions.
36d6372a
RS
2505 (buffer
2506 (save-excursion
2507 (or (eq (current-buffer) gud-comint-buffer)
2508 (set-buffer gud-comint-buffer))
2509 (gud-find-file true-file)))
f55d65a1 2510 (window (and buffer (or (get-buffer-window buffer)
f36ca832
NR
2511 (if (eq gud-minor-mode 'gdba)
2512 (gdb-display-source-buffer buffer)
2513 (display-buffer buffer)))))
13b80a60 2514 (pos))
87a3fd19
RS
2515 (if buffer
2516 (progn
2517 (save-excursion
2518 (set-buffer buffer)
7461cbeb
NR
2519 (if (not (or (verify-visited-file-modtime buffer) gud-keep-buffer))
2520 (progn
2521 (if
71296446 2522 (yes-or-no-p
7461cbeb
NR
2523 (format "File %s changed on disk. Reread from disk? "
2524 (buffer-name)))
2525 (revert-buffer t t)
2526 (setq gud-keep-buffer t))))
87a3fd19
RS
2527 (save-restriction
2528 (widen)
2529 (goto-line line)
2530 (setq pos (point))
2531 (setq overlay-arrow-string "=>")
2532 (or overlay-arrow-position
7461cbeb 2533 (setq overlay-arrow-position (make-marker)))
87a3fd19
RS
2534 (set-marker overlay-arrow-position (point) (current-buffer)))
2535 (cond ((or (< pos (point-min)) (> pos (point-max)))
7461cbeb
NR
2536 (widen)
2537 (goto-char pos))))
87a3fd19 2538 (set-window-point window overlay-arrow-position)))))
53eb3a97 2539
8b5cd4d0
SM
2540;; The gud-call function must do the right thing whether its invoking
2541;; keystroke is from the GUD buffer itself (via major-mode binding)
2542;; or a C buffer. In the former case, we want to supply data from
2543;; gud-last-frame. Here's how we do it:
13b80a60 2544
ee0155df 2545(defun gud-format-command (str arg)
13eaa026
RS
2546 (let ((insource (not (eq (current-buffer) gud-comint-buffer)))
2547 (frame (or gud-last-frame gud-last-last-frame))
2548 result)
2ef4e909 2549 (while (and str (string-match "\\([^%]*\\)%\\([adeflpc]\\)" str))
9f6991fd 2550 (let ((key (string-to-char (match-string 2 str)))
13eaa026
RS
2551 subst)
2552 (cond
2553 ((eq key ?f)
2554 (setq subst (file-name-nondirectory (if insource
2555 (buffer-file-name)
2556 (car frame)))))
73739399
RS
2557 ((eq key ?F)
2558 (setq subst (file-name-sans-extension
2559 (file-name-nondirectory (if insource
2560 (buffer-file-name)
2561 (car frame))))))
13eaa026
RS
2562 ((eq key ?d)
2563 (setq subst (file-name-directory (if insource
7f359a21 2564 (buffer-file-name)
13eaa026
RS
2565 (car frame)))))
2566 ((eq key ?l)
38eba485
RS
2567 (setq subst (int-to-string
2568 (if insource
2569 (save-restriction
2570 (widen)
8b5cd4d0 2571 (+ (count-lines (point-min) (point))
38eba485
RS
2572 (if (bolp) 1 0)))
2573 (cdr frame)))))
13eaa026 2574 ((eq key ?e)
ab4b0d2f 2575 (setq subst (gud-find-c-expr)))
13eaa026
RS
2576 ((eq key ?a)
2577 (setq subst (gud-read-address)))
2ef4e909 2578 ((eq key ?c)
71296446
JB
2579 (setq subst
2580 (gud-find-class
b0592138
PJ
2581 (if insource
2582 (buffer-file-name)
2583 (car frame))
2584 (if insource
2585 (save-restriction
2586 (widen)
2587 (+ (count-lines (point-min) (point))
2588 (if (bolp) 1 0)))
2589 (cdr frame)))))
13eaa026 2590 ((eq key ?p)
b2e60475
DL
2591 (setq subst (if arg (int-to-string arg)))))
2592 (setq result (concat result (match-string 1 str) subst)))
13eaa026
RS
2593 (setq str (substring str (match-end 2))))
2594 ;; There might be text left in STR when the loop ends.
2595 (concat result str)))
13b80a60 2596
6bde8427 2597(defun gud-read-address ()
13b80a60 2598 "Return a string containing the core-address found in the buffer at point."
f36ca832
NR
2599 (save-match-data
2600 (save-excursion
2601 (let ((pt (point)) found begin)
2602 (setq found (if (search-backward "0x" (- pt 7) t) (point)))
2603 (cond
2604 (found (forward-char 2)
2605 (buffer-substring found
2606 (progn (re-search-forward "[^0-9a-f]")
2607 (forward-char -1)
2608 (point))))
2609 (t (setq begin (progn (re-search-backward "[^0-9]")
2610 (forward-char 1)
2611 (point)))
2612 (forward-char 1)
2613 (re-search-forward "[^0-9]")
2614 (forward-char -1)
2615 (buffer-substring begin (point))))))))
13b80a60 2616
ee0155df
ER
2617(defun gud-call (fmt &optional arg)
2618 (let ((msg (gud-format-command fmt arg)))
2619 (message "Command: %s" msg)
2620 (sit-for 0)
2621 (gud-basic-call msg)))
13b80a60 2622
ee0155df
ER
2623(defun gud-basic-call (command)
2624 "Invoke the debugger COMMAND displaying source in other window."
2625 (interactive)
2626 (gud-set-buffer)
f36ca832 2627 (let ((proc (get-buffer-process gud-comint-buffer)))
4b8b296e 2628 (or proc (error "Current buffer has no process"))
ee0155df
ER
2629 ;; Arrange for the current prompt to get deleted.
2630 (save-excursion
2631 (set-buffer gud-comint-buffer)
136b4eda
MB
2632 (save-restriction
2633 (widen)
2634 (goto-char (process-mark proc))
2635 (forward-line 0)
2636 (if (looking-at comint-prompt-regexp)
f36ca832
NR
2637 (set-marker gud-delete-prompt-marker (point)))
2638 (if (eq gud-minor-mode 'gdba)
2639 (apply comint-input-sender (list proc command))
2640 (process-send-string proc (concat command "\n")))))))
ee0155df
ER
2641
2642(defun gud-refresh (&optional arg)
2643 "Fix up a possibly garbled display, and redraw the arrow."
13b80a60 2644 (interactive "P")
32ab4c10 2645 (or gud-last-frame (setq gud-last-frame gud-last-last-frame))
7ff24607
EZ
2646 (gud-display-frame)
2647 (recenter arg))
dcec1a3b 2648\f
8b5cd4d0
SM
2649;; Code for parsing expressions out of C code. The single entry point is
2650;; find-c-expr, which tries to return an lvalue expression from around point.
2651;;
2652;; The rest of this file is a hacked version of gdbsrc.el by
2653;; Debby Ayers <ayers@asc.slb.com>,
2654;; Rich Schaefer <schaefer@asc.slb.com> Schlumberger, Austin, Tx.
ee0155df 2655
ab4b0d2f 2656(defun gud-find-c-expr ()
ee0155df
ER
2657 "Returns the C expr that surrounds point."
2658 (interactive)
2659 (save-excursion
ab4b0d2f 2660 (let (p expr test-expr)
ee0155df 2661 (setq p (point))
ab4b0d2f
RS
2662 (setq expr (gud-innermost-expr))
2663 (setq test-expr (gud-prev-expr))
2664 (while (and test-expr (gud-expr-compound test-expr expr))
2665 (let ((prev-expr expr))
2666 (setq expr (cons (car test-expr) (cdr expr)))
2667 (goto-char (car expr))
2668 (setq test-expr (gud-prev-expr))
2669 ;; If we just pasted on the condition of an if or while,
2670 ;; throw it away again.
2671 (if (member (buffer-substring (car test-expr) (cdr test-expr))
2672 '("if" "while" "for"))
2673 (setq test-expr nil
2674 expr prev-expr))))
ee0155df 2675 (goto-char p)
ab4b0d2f
RS
2676 (setq test-expr (gud-next-expr))
2677 (while (gud-expr-compound expr test-expr)
ee0155df 2678 (setq expr (cons (car expr) (cdr test-expr)))
c157af51 2679 (setq test-expr (gud-next-expr)))
dcec1a3b 2680 (buffer-substring (car expr) (cdr expr)))))
ee0155df 2681
ab4b0d2f
RS
2682(defun gud-innermost-expr ()
2683 "Returns the smallest expr that point is in; move point to beginning of it.
ee0155df 2684The expr is represented as a cons cell, where the car specifies the point in
f4b643a1 2685the current buffer that marks the beginning of the expr and the cdr specifies
dcec1a3b 2686the character after the end of the expr."
ab4b0d2f
RS
2687 (let ((p (point)) begin end)
2688 (gud-backward-sexp)
ee0155df 2689 (setq begin (point))
ab4b0d2f 2690 (gud-forward-sexp)
ee0155df 2691 (setq end (point))
f4b643a1 2692 (if (>= p end)
ee0155df
ER
2693 (progn
2694 (setq begin p)
2695 (goto-char p)
ab4b0d2f
RS
2696 (gud-forward-sexp)
2697 (setq end (point)))
ee0155df
ER
2698 )
2699 (goto-char begin)
dcec1a3b 2700 (cons begin end)))
ee0155df 2701
ab4b0d2f 2702(defun gud-backward-sexp ()
dcec1a3b 2703 "Version of `backward-sexp' that catches errors."
ee0155df
ER
2704 (condition-case nil
2705 (backward-sexp)
2706 (error t)))
2707
ab4b0d2f 2708(defun gud-forward-sexp ()
dcec1a3b 2709 "Version of `forward-sexp' that catches errors."
ee0155df
ER
2710 (condition-case nil
2711 (forward-sexp)
2712 (error t)))
2713
ab4b0d2f 2714(defun gud-prev-expr ()
ee0155df
ER
2715 "Returns the previous expr, point is set to beginning of that expr.
2716The expr is represented as a cons cell, where the car specifies the point in
f4b643a1 2717the current buffer that marks the beginning of the expr and the cdr specifies
ee0155df
ER
2718the character after the end of the expr"
2719 (let ((begin) (end))
ab4b0d2f 2720 (gud-backward-sexp)
ee0155df 2721 (setq begin (point))
ab4b0d2f 2722 (gud-forward-sexp)
ee0155df
ER
2723 (setq end (point))
2724 (goto-char begin)
2725 (cons begin end)))
2726
ab4b0d2f 2727(defun gud-next-expr ()
ee0155df
ER
2728 "Returns the following expr, point is set to beginning of that expr.
2729The expr is represented as a cons cell, where the car specifies the point in
f4b643a1 2730the current buffer that marks the beginning of the expr and the cdr specifies
dcec1a3b 2731the character after the end of the expr."
ee0155df 2732 (let ((begin) (end))
ab4b0d2f
RS
2733 (gud-forward-sexp)
2734 (gud-forward-sexp)
ee0155df 2735 (setq end (point))
ab4b0d2f 2736 (gud-backward-sexp)
ee0155df 2737 (setq begin (point))
dcec1a3b 2738 (cons begin end)))
ee0155df 2739
ab4b0d2f
RS
2740(defun gud-expr-compound-sep (span-start span-end)
2741 "Scan from SPAN-START to SPAN-END for punctuation characters.
c6094cae 2742If `->' is found, return `?.'. If `.' is found, return `?.'.
ab4b0d2f
RS
2743If any other punctuation is found, return `??'.
2744If no punctuation is found, return `? '."
2745 (let ((result ?\ )
ee0155df
ER
2746 (syntax))
2747 (while (< span-start span-end)
2748 (setq syntax (char-syntax (char-after span-start)))
2749 (cond
ab4b0d2f 2750 ((= syntax ?\ ) t)
ee0155df 2751 ((= syntax ?.) (setq syntax (char-after span-start))
f4b643a1 2752 (cond
ee0155df
ER
2753 ((= syntax ?.) (setq result ?.))
2754 ((and (= syntax ?-) (= (char-after (+ span-start 1)) ?>))
2755 (setq result ?.)
2756 (setq span-start (+ span-start 1)))
2757 (t (setq span-start span-end)
2758 (setq result ??)))))
2759 (setq span-start (+ span-start 1)))
dcec1a3b 2760 result))
ee0155df 2761
ab4b0d2f
RS
2762(defun gud-expr-compound (first second)
2763 "Non-nil if concatenating FIRST and SECOND makes a single C expression.
f4b643a1
RS
2764The two exprs are represented as a cons cells, where the car
2765specifies the point in the current buffer that marks the beginning of the
dcec1a3b 2766expr and the cdr specifies the character after the end of the expr.
ee0155df
ER
2767Link exprs of the form:
2768 Expr -> Expr
2769 Expr . Expr
2770 Expr (Expr)
2771 Expr [Expr]
2772 (Expr) Expr
2773 [Expr] Expr"
2774 (let ((span-start (cdr first))
2775 (span-end (car second))
2776 (syntax))
ab4b0d2f 2777 (setq syntax (gud-expr-compound-sep span-start span-end))
ee0155df
ER
2778 (cond
2779 ((= (car first) (car second)) nil)
2780 ((= (cdr first) (cdr second)) nil)
2781 ((= syntax ?.) t)
ab4b0d2f 2782 ((= syntax ?\ )
ee0155df
ER
2783 (setq span-start (char-after (- span-start 1)))
2784 (setq span-end (char-after span-end))
2785 (cond
ab4b0d2f
RS
2786 ((= span-start ?)) t)
2787 ((= span-start ?]) t)
f5851398 2788 ((= span-end ?() t)
ab4b0d2f
RS
2789 ((= span-end ?[) t)
2790 (t nil)))
dcec1a3b 2791 (t nil))))
5b08a462 2792
b0592138
PJ
2793(defun gud-find-class (f line)
2794 "Find fully qualified class in file F at line LINE.
e78e1cd1
EZ
2795This function uses the `gud-jdb-classpath' (and optional
2796`gud-jdb-sourcepath') list(s) to derive a file
2ef4e909
RS
2797pathname relative to its classpath directory. The values in
2798`gud-jdb-classpath' are assumed to have been converted to absolute
b0592138
PJ
2799pathname standards using file-truename.
2800If F is visited by a buffer and its mode is CC-mode(Java),
2801syntactic information of LINE is used to find the enclosing (nested)
2802class string which is appended to the top level
2803class of the file (using s to separate nested class ids)."
2ef4e909 2804 ;; Convert f to a standard representation and remove suffix
e78e1cd1 2805 (if (and gud-jdb-use-classpath (or gud-jdb-classpath gud-jdb-sourcepath))
2ef4e909 2806 (save-match-data
b0592138
PJ
2807 (let ((cplist (append gud-jdb-sourcepath gud-jdb-classpath))
2808 (fbuffer (get-file-buffer f))
2809 class-found)
2810 (setq f (file-name-sans-extension (file-truename f)))
2811 ;; Search through classpath list for an entry that is
2812 ;; contained in f
2813 (while (and cplist (not class-found))
2814 (if (string-match (car cplist) f)
2815 (setq class-found
9f6991fd 2816 (mapconcat 'identity
b0592138
PJ
2817 (split-string
2818 (substring f (+ (match-end 0) 1))
2819 "/") ".")))
2820 (setq cplist (cdr cplist)))
2821 ;; if f is visited by a java(cc-mode) buffer, walk up the
2822 ;; syntactic information chain and collect any 'inclass
2823 ;; symbols until 'topmost-intro is reached to find out if
2824 ;; point is within a nested class
2825 (if (and fbuffer (equal (symbol-file 'java-mode) "cc-mode"))
2826 (save-excursion
2827 (set-buffer fbuffer)
2828 (let ((nclass) (syntax)
2829 (pos (point)))
2830 ;; While the c-syntactic information does not start
2831 ;; with the 'topmost-intro symbol, there may be
2832 ;; nested classes...
71296446 2833 (while (not (eq 'topmost-intro
b0592138
PJ
2834 (car (car (c-guess-basic-syntax)))))
2835 ;; Check if the current position c-syntactic
2836 ;; analysis has 'inclass
2837 (setq syntax (c-guess-basic-syntax))
71296446 2838 (while
b0592138
PJ
2839 (and (not (eq 'inclass (car (car syntax))))
2840 (cdr syntax))
2841 (setq syntax (cdr syntax)))
2842 (if (eq 'inclass (car (car syntax)))
2843 (progn
2844 (goto-char (cdr (car syntax)))
2845 ;; Now we're at the beginning of a class
2846 ;; definition. Find class name
2847 (looking-at
2848 "[A-Za-z0-9 \t\n]*?class[ \t\n]+\\([^ \t\n]+\\)")
2849 (setq nclass
2850 (append (list (match-string-no-properties 1))
2851 nclass)))
2852 (setq syntax (c-guess-basic-syntax))
2853 (while (and (not (cdr (car syntax))) (cdr syntax))
2854 (setq syntax (cdr syntax)))
2855 (goto-char (cdr (car syntax)))
2856 ))
2857 (string-match (concat (car nclass) "$") class-found)
71296446 2858 (setq class-found
b0592138
PJ
2859 (replace-match (mapconcat 'identity nclass "$")
2860 t t class-found)))))
2861 (if (not class-found)
2862 (message "gud-find-class: class for file %s not found!" f))
2863 class-found))
e78e1cd1
EZ
2864 ;; Not using classpath - try class/source association list
2865 (let ((class-found (rassoc f gud-jdb-class-source-alist)))
2866 (if class-found
f5851398
EZ
2867 (car class-found)
2868 (message "gud-find-class: class for file %s not found in gud-jdb-class-source-alist!" f)
2869 nil))))
2ef4e909 2870
2c46c4c8 2871(provide 'gud)
96f4e22e 2872
f961a17c 2873;;; gud.el ends here