-;;; gud.el --- Grand Unified Debugger mode for gdb, sdb, or dbx under Emacs
+;;; gud.el --- Grand Unified Debugger mode for gdb, sdb, dbx, or xdb
+;;; under Emacs
;; Author: Eric S. Raymond <esr@snark.thyrsus.com>
-;; Version: 1.1
+;; Version: 1.3
;; Keywords: unix, tools
-;; Copyright (C) 1992 Free Software Foundation, Inc.
+;; Copyright (C) 1992, 1993 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
;; It was later rewritten by rms. Some ideas were due to Masanobu.
;; Grand Unification (sdb/dbx support) by Eric S. Raymond <esr@thyrsus.com>
;; The overloading code was then rewritten by Barry Warsaw <bwarsaw@cen.com>,
-;; who also hacked the mode to use comint.el.
-
-;; This code will not work under Emacs 18. It relies on Emacs 19's
-;; minor-mode-keymap support and the find-tag-noselect entry point of etags.
-
-;;; Change Log:
-
-;; Version 1.1: ESR 6 Apr 1993
-;; * Facility to accept and parse command-line switches other than the
-;; filename added.
-;; * System V Release 4 support added.
-;; * Can now set temporary breakpoints in sdb.
-;; * A GUD minor mode using the 19 minor-mode-keymap facilities is now
-;; enabled in visited C buffers.
-;; * Command bindings are now automatically the same in gud-minor-mode
-;; as they are in the GUD buffer itself, and use ^XX as a common
-;; prefix (for compatibility with electric-debug).
-;; * There is a new command for printing the C expression around point.
-
-;; Version 1.0: ESR
-;; * Created.
+;; who also hacked the mode to use comint.el. Shane Hartman <shane@spr.com>
+;; added support for xdb (HPUX debugger).
;;; Code:
(require 'etags)
;; ======================================================================
-;; minor-mode machinery for C buffers visited by GUD
-
-(defvar gud-key-prefix "\C-xX"
- "Prefix of all GUD minor-mode commands valid in C buffers.")
-
-(defvar gud-minor-mode nil)
-(or (assq 'gud-minor-mode minor-mode-alist)
- (setq minor-mode-alist
- (cons '(gud-minor-mode " GUD") minor-mode-alist)))
-
-(defvar gud-mode-map nil)
-(if gud-mode-map
- nil
- (setq gud-mode-map (make-sparse-keymap))
- (define-key gud-mode-map gud-key-prefix (make-sparse-keymap))
- (define-key gud-mode-map (concat gud-key-prefix "\C-l") 'gud-refresh)
- )
+;; GUD commands must be visible in C buffers visited by GUD
-(or (assq 'gud-minor-mode minor-mode-map-alist)
- (setq minor-mode-map-alist
- (cons
- (cons 'gud-minor-mode gud-mode-map)
- minor-mode-map-alist)))
-
-(defun gud-minor-mode (&optional enable)
- "GUD minor mode is enabled in C buffers visited due to a GUD stop at
-breakpoint. All GUD-specific commands defined in GUD major mode will work,
-but they get their current file and current line number from the context of
-this buffer."
- (interactive "P")
- (setq gud-minor-mode
- (if (null enable) (not gud-minor-mode)
- (> (prefix-numeric-value enable) 0)))
-)
+(defvar gud-key-prefix "\C-x\C-a"
+ "Prefix of all GUD commands valid in C buffers.")
+
+(global-set-key (concat gud-key-prefix "\C-l") 'gud-refresh)
+(global-set-key "\C-x " 'gud-break) ;; backward compatibility hack
;; ======================================================================
;; the overloading mechanism
(function (lambda (p) (fset (car p) (symbol-function (cdr p)))))
gud-overload-alist))
-(defun gud-debugger-startup (file args)
+(defun gud-massage-args (file args)
(error "GUD not properly entered."))
(defun gud-marker-filter (str)
;; A macro call like (gud-def FUNC NAME KEY DOC) expands to a form
;; which defines FUNC to send the command NAME to the debugger, gives
;; it the docstring DOC, and binds that function to KEY in the GUD
-;; major mode. The function is also bound in the GUD minor-mode
-;; keymap. If a numeric prefix argument is given to FUNC, it gets
-;; sent after NAME.
+;; major mode. The function is also bound in the global keymap with the
+;; GUD prefix.
(defmacro gud-def (func cmd key &optional doc)
"Define FUNC to be a command sending STR and bound to KEY, with
%a text of the hexadecimal address surrounding point
%p prefix argument to the command (if any) as a number
- The `current' source file is the file of the current buffer (if we're in a
-C file with gud-minor-mode active) or the source file current at the last
-break or step (if we're in the GUD buffer).
- The `current' line is that of the current buffer (if we're in a source
-file with gud-minor-mode active) or the source line number at the last
-break or step (if we're in the GUD buffer)."
+ The `current' source file is the file of the current buffer (if
+we're in a C file) or the source file current at the last break or
+step (if we're in the GUD buffer).
+ The `current' line is that of the current buffer (if we're in a
+source file) or the source line number at the last break or step (if
+we're in the GUD buffer)."
(list 'progn
(list 'defun func '(arg)
(or doc "")
(list 'gud-call cmd 'arg))
(if key
(list 'define-key
- 'gud-mode-map
- (concat gud-key-prefix key)
+ '(current-local-map)
+ (concat "\C-c" key)
+ (list 'quote func)))
+ (if key
+ (list 'global-set-key
+ (list 'concat 'gud-key-prefix key)
(list 'quote func)))))
;; Where gud-display-frame should put the debugging arrow. This is
;; indications of the current program counter.
(defvar gud-last-frame nil)
+;; Used by gud-refresh, which should cause gud-display-frame to redisplay
+;; the last frame, even if it's been called before and gud-last-frame has
+;; been set to nil.
+(defvar gud-last-last-frame)
+
;; All debugger-specific information is collected here.
;; Here's how it works, in case you ever need to add a debugger to the mode.
;;
;;
;;<name>
;; comint-prompt-regexp
-;; gud-<name>-debugger-startup
+;; gud-<name>-massage-args
;; gud-<name>-marker-filter
;; gud-<name>-find-file
;;
-;; The job of the startup-command method is to fire up a copy of the debugger,
-;; given a list of debugger arguments.
+;; The job of the massage-args method is to modify the given list of
+;; debugger arguments before running the debugger.
;;
;; The job of the marker-filter method is to detect file/line markers in
;; strings and set the global gud-last-frame to indicate what display
;; action (if any) should be triggered by the marker. Note that only
-;; whetever the method *returns* is displayed in the buffer; thus, you
+;; whatever the method *returns* is displayed in the buffer; thus, you
;; can filter the debugger's output, interpreting some and passing on
;; the rest.
;;
;; ======================================================================
;; gdb functions
-(defun gud-gdb-debugger-startup (file args)
- (apply 'make-comint (concat "gud-" file) "gdb" nil "-fullname" args))
+;;; History of argument lists passed to gdb.
+(defvar gud-gdb-history nil)
+
+(defun gud-gdb-massage-args (file args)
+ (cons "-fullname" (cons file args)))
(defun gud-gdb-marker-filter (string)
(if (string-match "\032\032\\([^:\n]*\\):\\([0-9]*\\):.*\n" string)
(find-file-noselect f))
;;;###autoload
-(defun gdb (args)
+(defun gdb (command-line)
"Run gdb on program FILE in buffer *gud-FILE*.
The directory containing FILE becomes the initial working directory
and source-file directory for your debugger."
- (interactive "sRun gdb (like this): gdb ")
- (gud-overload-functions '((gud-debugger-startup . gud-gdb-debugger-startup)
- (gud-marker-filter . gud-gdb-marker-filter)
- (gud-find-file . gud-gdb-find-file)
+ (interactive
+ (list (read-from-minibuffer "Run gdb (like this): "
+ (if (consp gud-gdb-history)
+ (car gud-gdb-history)
+ "gdb ")
+ nil nil
+ '(gud-gdb-history . 1))))
+ (gud-overload-functions '((gud-massage-args . gud-gdb-massage-args)
+ (gud-marker-filter . gud-gdb-marker-filter)
+ (gud-find-file . gud-gdb-find-file)
))
- (gud-def gud-break "break %f:%l" "b" "Set breakpoint at current line.")
- (gud-def gud-tbreak "tbreak %f:%l" "t" "Set breakpoint at current line.")
- (gud-def gud-remove "clear %l" "d" "Remove breakpoint at current line")
- (gud-def gud-step "step %p" "s" "Step one source line with display.")
- (gud-def gud-stepi "stepi %p" "i" "Step one instruction with display.")
- (gud-def gud-next "next %p" "n" "Step one line (skip functions).")
- (gud-def gud-cont "cont" "r" "Continue with display.")
- (gud-def gud-finish "finish" "f" "Finish executing current function.")
+ (gud-common-init command-line)
+
+ (gud-def gud-break "break %f:%l" "\C-b" "Set breakpoint at current line.")
+ (gud-def gud-tbreak "tbreak %f:%l" "\C-t" "Set breakpoint at current line.")
+ (gud-def gud-remove "clear %l" "\C-d" "Remove breakpoint at current line")
+ (gud-def gud-step "step %p" "\C-s" "Step one source line with display.")
+ (gud-def gud-stepi "stepi %p" "\C-i" "Step one instruction with display.")
+ (gud-def gud-next "next %p" "\C-n" "Step one line (skip functions).")
+ (gud-def gud-cont "cont" "\C-r" "Continue with display.")
+ (gud-def gud-finish "finish" "\C-f" "Finish executing current function.")
(gud-def gud-up "up %p" "<" "Up N stack frames (numeric arg).")
(gud-def gud-down "down %p" ">" "Down N stack frames (numeric arg).")
- (gud-def gud-print "print %e" "p" "Evaluate C expression at point.")
-
- (gud-common-init args)
+ (gud-def gud-print "print %e" "\C-p" "Evaluate C expression at point.")
(setq comint-prompt-regexp "^(.*gdb[+]?) *")
(run-hooks 'gdb-mode-hook)
;; ======================================================================
;; sdb functions
+;;; History of argument lists passed to sdb.
+(defvar gud-sdb-history nil)
+
(defvar gud-sdb-needs-tags (not (file-exists-p "/var"))
"If nil, we're on a System V Release 4 and don't need the tags hack.")
(defvar gud-sdb-lastfile nil)
-(defun gud-sdb-debugger-startup (file args)
- (apply 'make-comint (concat "gud-" file) "sdb" nil args))
+(defun gud-sdb-massage-args (file args)
+ (cons file args))
(defun gud-sdb-marker-filter (string)
(cond
(find-file-noselect f)))
;;;###autoload
-(defun sdb (args)
+(defun sdb (command-line)
"Run sdb on program FILE in buffer *gud-FILE*.
The directory containing FILE becomes the initial working directory
and source-file directory for your debugger."
-
- (interactive "sRun sdb (like this): sdb ")
-
+ (interactive
+ (list (read-from-minibuffer "Run sdb (like this): "
+ (if (consp gud-sdb-history)
+ (car gud-sdb-history)
+ "sdb ")
+ nil nil
+ '(gud-sdb-history . 1))))
(if (and gud-sdb-needs-tags
(not (and (boundp 'tags-file-name) (file-exists-p tags-file-name))))
(error "The sdb support requires a valid tags table to work."))
- (gud-overload-functions '((gud-debugger-startup . gud-sdb-debugger-startup)
- (gud-marker-filter . gud-sdb-marker-filter)
- (gud-find-file . gud-sdb-find-file)
+ (gud-overload-functions '((gud-massage-args . gud-sdb-massage-args)
+ (gud-marker-filter . gud-sdb-marker-filter)
+ (gud-find-file . gud-sdb-find-file)
))
- (gud-def gud-break "%l b" "b" "Set breakpoint at current line.")
- (gud-def gud-tbreak "%l c" "t" "Set temporary breakpoint at current line.")
- (gud-def gud-remove "%l d" "d" "Remove breakpoint at current line")
- (gud-def gud-step "s %p" "s" "Step one source line with display.")
- (gud-def gud-stepi "i %p" "i" "Step one instruction with display.")
- (gud-def gud-next "S %p" "n" "Step one line (skip functions).")
- (gud-def gud-cont "c" "r" "Continue with display.")
- (gud-def gud-print "%e/" "p" "Evaluate C expression at point.")
+ (gud-common-init command-line)
- (gud-common-init args)
+ (gud-def gud-break "%l b" "\C-b" "Set breakpoint at current line.")
+ (gud-def gud-tbreak "%l c" "\C-t" "Set temporary breakpoint at current line.")
+ (gud-def gud-remove "%l d" "\C-d" "Remove breakpoint at current line")
+ (gud-def gud-step "s %p" "\C-s" "Step one source line with display.")
+ (gud-def gud-stepi "i %p" "\C-i" "Step one instruction with display.")
+ (gud-def gud-next "S %p" "\C-n" "Step one line (skip functions).")
+ (gud-def gud-cont "c" "\C-r" "Continue with display.")
+ (gud-def gud-print "%e/" "\C-p" "Evaluate C expression at point.")
(setq comint-prompt-regexp "\\(^\\|\n\\)\\*")
(run-hooks 'sdb-mode-hook)
;; ======================================================================
;; dbx functions
-(defun gud-dbx-debugger-startup (file args)
- (apply 'make-comint (concat "gud-" file) "dbx" nil args))
+;;; History of argument lists passed to dbx.
+(defvar gud-dbx-history nil)
+
+(defun gud-dbx-massage-args (file args)
+ (cons file args))
(defun gud-dbx-marker-filter (string)
(if (string-match
(find-file-noselect f))
;;;###autoload
-(defun dbx (args)
+(defun dbx (command-line)
"Run dbx on program FILE in buffer *gud-FILE*.
The directory containing FILE becomes the initial working directory
and source-file directory for your debugger."
- (interactive "sRun dbx (like this): dbx")
- (gud-overload-functions '((gud-debugger-startup . gud-dbx-debugger-startup)
- (gud-marker-filter . gud-dbx-marker-filter)
- (gud-find-file . gud-dbx-find-file)
+ (interactive
+ (list (read-from-minibuffer "Run dbx (like this): "
+ (if (consp gud-dbx-history)
+ (car gud-dbx-history)
+ "dbx ")
+ nil nil
+ '(gud-dbx-history . 1))))
+ (gud-overload-functions '((gud-massage-args . gud-dbx-massage-args)
+ (gud-marker-filter . gud-dbx-marker-filter)
+ (gud-find-file . gud-dbx-find-file)
))
+ (gud-common-init command-line)
+
(gud-def gud-break "stop at \"%f\":%l"
- "b" "Set breakpoint at current line.")
- (gud-def gud-remove "clear %l" "d" "Remove breakpoint at current line")
- (gud-def gud-step "step %p" "s" "Step one line with display.")
- (gud-def gud-stepi "stepi %p" "i" "Step one instruction with display.")
- (gud-def gud-next "next %p" "n" "Step one line (skip functions).")
- (gud-def gud-cont "cont" "r" "Continue with display.")
+ "\C-b" "Set breakpoint at current line.")
+ (gud-def gud-remove "clear %l" "\C-d" "Remove breakpoint at current line")
+ (gud-def gud-step "step %p" "\C-s" "Step one line with display.")
+ (gud-def gud-stepi "stepi %p" "\C-i" "Step one instruction with display.")
+ (gud-def gud-next "next %p" "\C-n" "Step one line (skip functions).")
+ (gud-def gud-cont "cont" "\C-r" "Continue with display.")
(gud-def gud-up "up %p" "<" "Up (numeric arg) stack frames.")
(gud-def gud-down "down %p" ">" "Down (numeric arg) stack frames.")
- (gud-def gud-print "print %e" "p" "Evaluate C expression at point.")
+ (gud-def gud-print "print %e" "\C-p" "Evaluate C expression at point.")
- (gud-common-init args)
(setq comint-prompt-regexp "^[^)]*dbx) *")
-
(run-hooks 'dbx-mode-hook)
)
+;; ======================================================================
+;; xdb (HP PARISC debugger) functions
+
+;;; History of argument lists passed to xdb.
+(defvar gud-xdb-history nil)
+
+(defvar gud-xdb-directories nil
+ "*A list of directories that xdb should search for source code.
+If nil, only source files in the program directory
+will be known to xdb.
+
+The file names should be absolute, or relative to the directory
+containing the executable being debugged.")
+
+(defun gud-xdb-massage-args (file args)
+ (nconc (let ((directories gud-xdb-directories)
+ (result nil))
+ (while directories
+ (setq result (cons (car directories) (cons "-d" result)))
+ (setq directories (cdr directories)))
+ (nreverse (cons file result)))
+ args))
+
+(defun gud-xdb-file-name (f)
+ "Transform a relative pathname to a full pathname in xdb mode"
+ (let ((result nil))
+ (if (file-exists-p f)
+ (setq result (expand-file-name f))
+ (let ((directories gud-xdb-directories))
+ (while directories
+ (let ((path (concat (car directories) "/" f)))
+ (if (file-exists-p path)
+ (setq result (expand-file-name path)
+ directories nil)))
+ (setq directories (cdr directories)))))
+ result))
+
+;; xdb does not print the lines all at once, so we have to accumulate them
+(defvar gud-xdb-accumulation "")
+
+(defun gud-xdb-marker-filter (string)
+ (let (result)
+ (if (or (string-match comint-prompt-regexp string)
+ (string-match ".*\012" string))
+ (setq result (concat gud-xdb-accumulation string)
+ gud-xdb-accumulation "")
+ (setq gud-xdb-accumulation (concat gud-xdb-accumulation string)))
+ (if result
+ (if (or (string-match "\\([^\n \t:]+\\): [^:]+: \\([0-9]+\\):" result)
+ (string-match "[^: \t]+:[ \t]+\\([^:]+\\): [^:]+: \\([0-9]+\\):"
+ result))
+ (let ((line (string-to-int
+ (substring result (match-beginning 2) (match-end 2))))
+ (file (gud-xdb-file-name
+ (substring result (match-beginning 1) (match-end 1)))))
+ (if file
+ (setq gud-last-frame (cons file line))))))
+ (or result "")))
+
+(defun gud-xdb-find-file (f)
+ (let ((realf (gud-xdb-file-name f)))
+ (if realf (find-file-noselect realf))))
+
+;;;###autoload
+(defun xdb (command-line)
+ "Run xdb on program FILE in buffer *gud-FILE*.
+The directory containing FILE becomes the initial working directory
+and source-file directory for your debugger.
+
+You can set the variable 'gud-xdb-directories' to a list of program source
+directories if your program contains sources from more than one directory."
+ (interactive
+ (list (read-from-minibuffer "Run xdb (like this): "
+ (if (consp gud-xdb-history)
+ (car gud-xdb-history)
+ "xdb ")
+ nil nil
+ '(gud-xdb-history . 1))))
+ (gud-overload-functions '((gud-massage-args . gud-xdb-massage-args)
+ (gud-marker-filter . gud-xdb-marker-filter)
+ (gud-find-file . gud-xdb-find-file)))
+
+ (gud-common-init command-line)
+
+ (gud-def gud-break "b %f:%l" "\C-b" "Set breakpoint at current line.")
+ (gud-def gud-tbreak "b %f:%l\\t" "\C-t"
+ "Set temporary breakpoint at current line.")
+ (gud-def gud-remove "db" "\C-d" "Remove breakpoint at current line")
+ (gud-def gud-step "s %p" "\C-s" "Step one line with display.")
+ (gud-def gud-next "S %p" "\C-n" "Step one line (skip functions).")
+ (gud-def gud-cont "c" "\C-r" "Continue with display.")
+ (gud-def gud-up "up %p" "<" "Up (numeric arg) stack frames.")
+ (gud-def gud-down "down %p" ">" "Down (numeric arg) stack frames.")
+ (gud-def gud-finish "bu\\t" "\C-f" "Finish executing current function.")
+ (gud-def gud-print "p %e" "\C-p" "Evaluate C expression at point.")
+
+ (setq comint-prompt-regexp "^>")
+ (make-local-variable 'gud-xdb-accumulation)
+ (setq gud-xdb-accumulation "")
+ (run-hooks 'xdb-mode-hook))
+
;;
;; End of debugger-specific information
;;
(defun gud-mode ()
"Major mode for interacting with an inferior debugger process.
- You start it up with one of the commands M-x gdb, M-x sdb, or
-M-x dbx. Each entry point finishes by executing a hook; gdb-mode-hook,
-sdb-mode-hook or dbx-mode-hook respectively.
+ You start it up with one of the commands M-x gdb, M-x sdb, M-x dbx,
+or M-x xdb. Each entry point finishes by executing a hook; `gdb-mode-hook',
+`sdb-mode-hook', `dbx-mode-hook' or `xdb-mode-hook' respectively.
After startup, the following commands are available in both the GUD
interaction buffer and any source buffer GUD visits due to a breakpoint stop
or step operation:
-\\{gud-mode-map}
-
\\[gud-break] sets a breakpoint at the current file and line. In the
GUD buffer, the current file and line are those of the last breakpoint or
step. In a source buffer, they are the buffer's file and current line.
+\\[gud-remove] removes breakpoints on the current file and line.
+
\\[gud-refresh] displays in the source window the last line referred to
in the gud buffer.
\\[gud-print] tries to find the largest C lvalue or function-call expression
around point, and sends it to the debugger for value display.
-The above commands are common to all supported debuggers.
+The above commands are common to all supported debuggers except xdb which
+does not support stepping instructions.
-Under gdb and sdb, \\[gud-tbreak] behaves exactly like \\[gud-break],
+Under gdb, sdb and xdb, \\[gud-tbreak] behaves exactly like \\[gud-break],
except that the breakpoint is temporary; that is, it is removed when
execution stops on it.
-Under gdb and dbx, \\[gud-up] pops up through an enclosing stack
+Under gdb, dbx, and xdb, \\[gud-up] pops up through an enclosing stack
frame. \\[gud-down] drops back down through one.
-If you are using gdb, \\[gdb-finish] runs execution to the return from
+If you are using gdb or xdb, \\[gud-finish] runs execution to the return from
the current function and stops.
+All the keystrokes above are accessible in the GUD buffer
+with the prefix C-c, and in all buffers through the prefix C-x C-a.
+
All pre-defined functions for which the concept make sense repeat
themselves the appropriate number of times if you give a prefix
argument.
-You may use the gud-def macro in the initialization hook to define other
+You may use the `gud-def' macro in the initialization hook to define other
commands.
Other commands for interacting with the debugger process are inherited from
(setq mode-name "Debugger")
(setq mode-line-process '(": %s"))
(use-local-map (copy-keymap comint-mode-map))
- (define-key (current-local-map)
- gud-key-prefix (lookup-key gud-mode-map gud-key-prefix))
(make-local-variable 'gud-last-frame)
(setq gud-last-frame nil)
(make-local-variable 'comint-prompt-regexp)
(defvar gud-comint-buffer nil)
-(defun gud-common-init (args)
- ;; Perform initializations common to all debuggers
- ;; There *must* be a cleaner way to lex the arglist...
- (let (file i)
- (if (string= args "")
- (setq args nil)
- (set-buffer (get-buffer-create "*gud-scratch*"))
- (erase-buffer)
- (insert args)
- (goto-char (point-max))
- (insert "\")")
- (goto-char (point-min))
- (insert "(\"")
- (while (re-search-forward " +" nil t)
- (replace-match "\" \"" nil nil))
- (goto-char (point-min))
- (while (re-search-forward "\"\"" nil t)
- (replace-match "" nil nil))
- (setq args (read (buffer-string)))
- (kill-buffer (current-buffer)))
- (setq i (1- (length args)))
- (while (and (>= i 0) (not (= (aref (nth i args) 0) ?-)))
- (setq file (nth i args)) (setq i (1- i)))
- (let* ((path (expand-file-name file))
- (filepart (file-name-nondirectory path)))
+;; Chop STRING into words separated by SPC or TAB and return a list of them.
+(defun gud-chop-words (string)
+ (let ((i 0) (beg 0)
+ (len (length string))
+ (words nil))
+ (while (< i len)
+ (if (memq (aref string i) '(?\t ? ))
+ (progn
+ (setq words (cons (substring string beg i) words)
+ beg (1+ i))
+ (while (and (< beg len) (memq (aref string beg) '(?\t ? )))
+ (setq beg (1+ beg)))
+ (setq i (1+ beg)))
+ (setq i (1+ i))))
+ (if (< beg len)
+ (setq words (cons (substring string beg) words)))
+ (nreverse words)))
+
+;; Perform initializations common to all debuggers.
+(defun gud-common-init (command-line)
+ (let* ((words (gud-chop-words command-line))
+ (program (car words))
+ (file-word (let ((w (cdr words)))
+ (while (and w (= ?- (aref (car w) 0)))
+ (setq w (cdr w)))
+ (car w)))
+ (args (delq file-word (cdr words)))
+ (file (expand-file-name file-word))
+ (filepart (file-name-nondirectory file)))
(switch-to-buffer (concat "*gud-" filepart "*"))
- (setq default-directory (file-name-directory path))
+ (setq default-directory (file-name-directory file))
(or (bolp) (newline))
(insert "Current directory is " default-directory "\n")
- (gud-debugger-startup filepart args)))
+ (apply 'make-comint (concat "gud-" filepart) program nil
+ (gud-massage-args file args)))
(gud-mode)
(set-process-filter (get-buffer-process (current-buffer)) 'gud-filter)
(set-process-sentinel (get-buffer-process (current-buffer)) 'gud-sentinel)
(let ((inhibit-quit t))
(save-excursion
(set-buffer (process-buffer proc))
- (let ((moving (= (point) (process-mark proc)))
- (output-after-point (< (point) (process-mark proc))))
+ (let (moving output-after-point)
(save-excursion
(goto-char (process-mark proc))
;; If we have been so requested, delete the debugger prompt.
(delete-region (point) gud-delete-prompt-marker)
(set-marker gud-delete-prompt-marker nil)))
(insert-before-markers (gud-marker-filter string))
+ (setq moving (= (point) (process-mark proc)))
+ (setq output-after-point (< (point) (process-mark proc)))
;; Check for a filename-and-line number.
;; Don't display the specified file
;; unless (1) point is at or after the position where output appears
;; buffer killed
;; Stop displaying an arrow in a source file.
(setq overlay-arrow-position nil)
- (setq gud-minor-mode nil)
(set-process-buffer proc nil))
((memq (process-status proc) '(signal exit))
;; Stop displaying an arrow in a source file.
- (setq gud-minor-mode nil)
(setq overlay-arrow-position nil)
;; Fix the mode line.
(setq mode-line-process
(progn
(gud-set-buffer)
(gud-display-line (car gud-last-frame) (cdr gud-last-frame))
- (setq gud-last-frame nil))))
+ (setq gud-last-last-frame gud-last-frame
+ gud-last-frame nil))))
;; Make sure the file named TRUE-FILE is in a buffer that appears on the screen
;; and that its line LINE is visible.
(let* ((buffer (gud-find-file true-file))
(window (display-buffer buffer))
(pos))
+;;; (if (equal buffer (current-buffer))
+;;; nil
+;;; (setq buffer-read-only nil))
(save-excursion
+;;; (setq buffer-read-only t)
(set-buffer buffer)
- (make-local-variable 'gud-minor-mode)
- (setq gud-minor-mode t)
(save-restriction
(widen)
(goto-line line)
;;; The gud-call function must do the right thing whether its invoking
;;; keystroke is from the GUD buffer itself (via major-mode binding)
-;;; or a C buffer in GUD minor mode. In the former case, we want to
-;;; supply data from gud-last-frame. Here's how we do it:
+;;; or a C buffer. In the former case, we want to supply data from
+;;; gud-last-frame. Here's how we do it:
(defun gud-format-command (str arg)
- (let ((minor (not (eq (current-buffer) gud-comint-buffer))))
+ (let ((insource (not (eq (current-buffer) gud-comint-buffer))))
(if (string-match "\\(.*\\)%f\\(.*\\)" str)
(progn
(setq str (concat
(substring str (match-beginning 1) (match-end 1))
- (if minor
- (buffer-file-name)
- (car gud-last-frame))
+ (file-name-nondirectory (if insource
+ (buffer-file-name)
+ (car gud-last-frame)))
(substring str (match-beginning 2) (match-end 2))))))
(if (string-match "\\(.*\\)%l\\(.*\\)" str)
(progn
(setq str (concat
(substring str (match-beginning 1) (match-end 1))
- (if minor
+ (if insource
(save-excursion
(beginning-of-line)
(save-restriction (widen)
"Fix up a possibly garbled display, and redraw the arrow."
(interactive "P")
(recenter arg)
+ (or gud-last-frame (setq gud-last-frame gud-last-last-frame))
(gud-display-frame))
-
+\f
;;; Code for parsing expressions out of C code. The single entry point is
;;; find-c-expr, which tries to return an lvalue expression from around point.
;;;
;;; The rest of this file is a hacked version of gdbsrc.el by
;;; Debby Ayers <ayers@asc.slb.com>,
;;; Rich Schaefer <schaefer@asc.slb.com> Schlumberger, Austin, Tx.
-;;; ??? We're waiting on papers from these people
(defun find-c-expr ()
"Returns the C expr that surrounds point."
(while (expr-compound test-expr expr)
(setq expr (cons (car test-expr) (cdr expr)))
(goto-char (car expr))
- (setq test-expr (expr-prev))
- )
+ (setq test-expr (expr-prev)))
(goto-char p)
(setq test-expr (expr-next))
(while (expr-compound expr test-expr)
(setq expr (cons (car expr) (cdr test-expr)))
(setq test-expr (expr-next))
)
- (buffer-substring (car expr) (cdr expr))
- )
- )
- )
+ (buffer-substring (car expr) (cdr expr)))))
(defun expr-cur ()
"Returns the expr that point is in; point is set to beginning of expr.
The expr is represented as a cons cell, where the car specifies the point in
the current buffer that marks the beginning of the expr and the cdr specifies
-the character after the end of the expr"
+the character after the end of the expr."
(let ((p (point)) (begin) (end))
- (back-expr)
+ (expr-backward-sexp)
(setq begin (point))
- (forw-expr)
+ (expr-forward-sexp)
(setq end (point))
(if (>= p end)
(progn
(setq begin p)
(goto-char p)
- (forw-expr)
+ (expr-forward-sexp)
(setq end (point))
)
)
(goto-char begin)
- (cons begin end)
- )
- )
+ (cons begin end)))
-(defun back-expr ()
- "Version of backward-sexp that catches errors"
+(defun expr-backward-sexp ()
+ "Version of `backward-sexp' that catches errors."
(condition-case nil
(backward-sexp)
(error t)))
-(defun forw-expr ()
- "Version of forward-sexp that catches errors"
+(defun expr-forward-sexp ()
+ "Version of `forward-sexp' that catches errors."
(condition-case nil
(forward-sexp)
(error t)))
the current buffer that marks the beginning of the expr and the cdr specifies
the character after the end of the expr"
(let ((begin) (end))
- (back-expr)
+ (expr-backward-sexp)
(setq begin (point))
- (forw-expr)
+ (expr-forward-sexp)
(setq end (point))
(goto-char begin)
(cons begin end)))
"Returns the following expr, point is set to beginning of that expr.
The expr is represented as a cons cell, where the car specifies the point in
the current buffer that marks the beginning of the expr and the cdr specifies
-the character after the end of the expr"
+the character after the end of the expr."
(let ((begin) (end))
- (forw-expr)
- (forw-expr)
+ (expr-forward-sexp)
+ (expr-forward-sexp)
(setq end (point))
- (back-expr)
+ (expr-backward-sexp)
(setq begin (point))
- (cons begin end)
- )
- )
+ (cons begin end)))
(defun expr-compound-sep (span-start span-end)
"Returns '.' for '->' & '.', returns ' ' for white space,
-returns '?' for other puctuation."
+returns '?' for other punctuation."
(let ((result ? )
(syntax))
(while (< span-start span-end)
(t (setq span-start span-end)
(setq result ??)))))
(setq span-start (+ span-start 1)))
- result
- )
- )
+ result))
(defun expr-compound (first second)
- "Returns non-nil if the concatenation of two exprs results in a single C
-token. The two exprs are represented as a cons cells, where the car
+ "Non-nil if concatenating FIRST and SECOND makes a single C token.
+The two exprs are represented as a cons cells, where the car
specifies the point in the current buffer that marks the beginning of the
-expr and the cdr specifies the character after the end of the expr
+expr and the cdr specifies the character after the end of the expr.
Link exprs of the form:
Expr -> Expr
Expr . Expr
((= span-end ?[ ) t )
(t nil))
)
- (t nil))
- )
- )
+ (t nil))))
+
+(provide 'gud)
;;; gud.el ends here