;; Maintainer: FSF
;; Keywords: unix, tools
-;; Copyright (C) 1992,93,94,95,96,1998,2000,02,03,04 Free Software Foundation, Inc.
+;; Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 2000, 2001, 2002, 2003,
+;; 2004, 2005, 2006 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
;;; Commentary:
-;; The ancestral gdb.el was by W. Schelter <wfs@rascal.ics.utexas.edu>
-;; 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. Shane Hartman <shane@spr.com>
-;; added support for xdb (HPUX debugger). Rick Sladkey <jrs@world.std.com>
-;; wrote the GDB command completion code. Dave Love <d.love@dl.ac.uk>
-;; added the IRIX kluge, re-implemented the Mips-ish variant and added
-;; a menu. Brian D. Carlstrom <bdc@ai.mit.edu> combined the IRIX kluge with
-;; the gud-xdb-directories hack producing gud-dbx-directories. Derek L. Davies
-;; <ddavies@world.std.com> added support for jdb (Java debugger.)
+;; The ancestral gdb.el was by W. Schelter <wfs@rascal.ics.utexas.edu> It was
+;; later rewritten by rms. Some ideas were due to Masanobu. Grand
+;; Unification (sdb/dbx support) by Eric S. Raymond <esr@thyrsus.com> Barry
+;; Warsaw <bwarsaw@cen.com> hacked the mode to use comint.el. Shane Hartman
+;; <shane@spr.com> added support for xdb (HPUX debugger). Rick Sladkey
+;; <jrs@world.std.com> wrote the GDB command completion code. Dave Love
+;; <d.love@dl.ac.uk> added the IRIX kluge, re-implemented the Mips-ish variant
+;; and added a menu. Brian D. Carlstrom <bdc@ai.mit.edu> combined the IRIX
+;; kluge with the gud-xdb-directories hack producing gud-dbx-directories.
+;; Derek L. Davies <ddavies@world.std.com> added support for jdb (Java
+;; debugger.)
;;; Code:
(eval-when-compile (require 'cl)) ; for case macro
(require 'comint)
-(require 'etags)
+
+(defvar gdb-active-process)
+(defvar gdb-define-alist)
+(defvar gdb-macro-info)
+(defvar gdb-server-prefix)
+(defvar gdb-show-changed-values)
+(defvar gdb-force-update)
+(defvar gdb-var-list)
+(defvar gdb-speedbar-auto-raise)
+(defvar tool-bar-map)
;; ======================================================================
;; GUD commands must be visible in C buffers visited by GUD
(defvar gud-minor-mode nil)
(put 'gud-minor-mode 'permanent-local t)
+(defvar gud-comint-buffer nil)
+
(defvar gud-keep-buffer nil)
(defun gud-symbol (sym &optional soft minor-mode)
(setq same-window-regexps nil)
(throw 'info-found nil))))
nil 0)
- (require 'info)
(select-frame (make-frame)))
(if (memq gud-minor-mode '(gdbmi gdba))
- (Info-goto-node "(emacs)GDB Graphical Interface")
- (Info-goto-node "(emacs)Debuggers"))))
+ (info "(emacs)GDB Graphical Interface")
+ (info "(emacs)Debuggers"))))
+
+(defun gud-tool-bar-item-visible-no-fringe ()
+ (not (or (eq (buffer-local-value 'major-mode (window-buffer)) 'speedbar-mode)
+ (and (memq gud-minor-mode '(gdbmi gdba))
+ (> (car (window-fringes)) 0)))))
+
+(defun gud-stop-subjob ()
+ (interactive)
+ (if (string-equal
+ (buffer-local-value 'gud-target-name gud-comint-buffer) "emacs")
+ (comint-stop-subjob)
+ (comint-interrupt-subjob)))
(easy-mmode-defmap gud-menu-map
'(([help] "Info" . gud-goto-info)
([tooltips] menu-item "Toggle GUD tooltips" gud-tooltip-mode
- :enable (and (not emacs-basic-display)
- (display-graphic-p)
- (fboundp 'x-show-tip))
+ :enable (and (not emacs-basic-display)
+ (display-graphic-p)
+ (fboundp 'x-show-tip))
:button (:toggle . gud-tooltip-mode))
([refresh] "Refresh" . gud-refresh)
([run] menu-item "Run" gud-run
:enable (and (not gud-running)
- (memq gud-minor-mode '(gdbmi gdba gdb dbx jdb))))
+ (memq gud-minor-mode '(gdbmi gdb dbx jdb)))
+ :visible (not (eq gud-minor-mode 'gdba)))
+ ([go] menu-item "Run/Continue" gud-go
+ :visible (and (not gud-running)
+ (eq gud-minor-mode 'gdba)))
+ ([stop] menu-item "Stop" gud-stop-subjob
+ :visible (or (not (eq gud-minor-mode 'gdba))
+ (and gud-running
+ (eq gud-minor-mode 'gdba))))
([until] menu-item "Continue to selection" gud-until
:enable (and (not gud-running)
- (memq gud-minor-mode '(gdbmi gdba gdb perldb))))
+ (memq gud-minor-mode '(gdbmi gdba gdb perldb)))
+ :visible (gud-tool-bar-item-visible-no-fringe))
([remove] menu-item "Remove Breakpoint" gud-remove
- :enable (not gud-running))
+ :enable (not gud-running)
+ :visible (gud-tool-bar-item-visible-no-fringe))
([tbreak] menu-item "Temporary Breakpoint" gud-tbreak
- :enable (memq gud-minor-mode '(gdbmi gdba gdb sdb xdb bashdb)))
+ :enable (memq gud-minor-mode
+ '(gdbmi gdba gdb sdb xdb bashdb)))
([break] menu-item "Set Breakpoint" gud-break
- :enable (not gud-running))
+ :enable (not gud-running)
+ :visible (gud-tool-bar-item-visible-no-fringe))
([up] menu-item "Up Stack" gud-up
:enable (and (not gud-running)
(memq gud-minor-mode
:enable (and (not gud-running)
(memq gud-minor-mode
'(gdbmi gdba gdb dbx xdb jdb pdb bashdb))))
+ ([pp] menu-item "Print S-expression" gud-pp
+ :enable (and (not gud-running)
+ gdb-active-process)
+ :visible (and (string-equal
+ (buffer-local-value
+ 'gud-target-name gud-comint-buffer) "emacs")
+ (eq gud-minor-mode 'gdba)))
+ ([print*] menu-item "Print Dereference" gud-pstar
+ :enable (and (not gud-running)
+ (memq gud-minor-mode '(gdbmi gdba gdb))))
([print] menu-item "Print Expression" gud-print
- :enable (not gud-running))
+ :enable (not gud-running))
([watch] menu-item "Watch Expression" gud-watch
- :enable (and (not gud-running)
- (memq gud-minor-mode '(gdbmi gdba))))
+ :enable (and (not gud-running)
+ (memq gud-minor-mode '(gdbmi gdba))))
([finish] menu-item "Finish Function" gud-finish
- :enable (and (not gud-running)
- (memq gud-minor-mode
- '(gdbmi gdba gdb xdb jdb pdb bashdb))))
+ :enable (and (not gud-running)
+ (memq gud-minor-mode
+ '(gdbmi gdba gdb xdb jdb pdb bashdb))))
([stepi] menu-item "Step Instruction" gud-stepi
- :enable (and (not gud-running)
- (memq gud-minor-mode '(gdbmi gdba gdb dbx))))
+ :enable (and (not gud-running)
+ (memq gud-minor-mode '(gdbmi gdba gdb dbx))))
([nexti] menu-item "Next Instruction" gud-nexti
- :enable (and (not gud-running)
- (memq gud-minor-mode '(gdbmi gdba gdb dbx))))
+ :enable (and (not gud-running)
+ (memq gud-minor-mode '(gdbmi gdba gdb dbx))))
([step] menu-item "Step Line" gud-step
- :enable (not gud-running))
+ :enable (not gud-running))
([next] menu-item "Next Line" gud-next
- :enable (not gud-running))
+ :enable (not gud-running))
([cont] menu-item "Continue" gud-cont
- :enable (not gud-running)))
+ :enable (not gud-running)
+ :visible (not (eq gud-minor-mode 'gdba))))
"Menu for `gud-mode'."
:name "Gud")
(defvar gud-tool-bar-map
(if (display-graphic-p)
(let ((map (make-sparse-keymap)))
- (dolist (x '((gud-break . "gud-break")
- (gud-remove . "gud-remove")
- (gud-print . "gud-print")
- (gud-watch . "gud-watch")
- (gud-run . "gud-run")
- (gud-until . "gud-until")
- (gud-cont . "gud-cont")
- ;; gud-s, gud-si etc. instead of gud-step,
- ;; gud-stepi, to avoid file-name clashes on DOS
- ;; 8+3 filesystems.
- (gud-step . "gud-s")
- (gud-next . "gud-n")
- (gud-finish . "gud-finish")
- (gud-stepi . "gud-si")
- (gud-nexti . "gud-ni")
- (gud-up . "gud-up")
- (gud-down . "gud-down")
+ (dolist (x '((gud-break . "gud/break")
+ (gud-remove . "gud/remove")
+ (gud-print . "gud/print")
+ (gud-pstar . "gud/pstar")
+ (gud-pp . "gud/pp")
+ (gud-watch . "gud/watch")
+ (gud-run . "gud/run")
+ (gud-go . "gud/go")
+ (gud-stop-subjob . "gud/stop")
+ (gud-cont . "gud/cont")
+ (gud-until . "gud/until")
+ (gud-next . "gud/next")
+ (gud-step . "gud/step")
+ (gud-finish . "gud/finish")
+ (gud-nexti . "gud/nexti")
+ (gud-stepi . "gud/stepi")
+ (gud-up . "gud/up")
+ (gud-down . "gud/down")
(gud-goto-info . "info"))
map)
(tool-bar-local-item-from-menu
optional doc string DOC. Certain %-escapes in the string arguments
are interpreted specially if present. These are:
- %f name (without directory) of current source file.
- %F name (without directory or extension) of current source file.
- %d directory of current source file.
- %l number of current source line
- %e text of the C lvalue or function-call expression surrounding point.
- %a text of the hexadecimal address surrounding point
- %p prefix argument to the command (if any) as a number
+ %f -- Name (without directory) of current source file.
+ %F -- Name (without directory or extension) of current source file.
+ %d -- Directory of current source file.
+ %l -- Number of current source line.
+ %e -- Text of the C lvalue or function-call expression surrounding point.
+ %a -- Text of the hexadecimal address surrounding point.
+ %p -- Prefix argument to the command (if any) as a number.
+ %c -- Fully qualified class name derived from the expression
+ surrounding point (jdb only).
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
;; speedbar support functions and variables.
(eval-when-compile (require 'speedbar)) ;For speedbar-with-attached-buffer.
-(defvar gud-last-speedbar-buffer nil
- "The last GUD buffer used.")
-
(defvar gud-last-speedbar-stackframe nil
"Description of the currently displayed GUD stack.
t means that there is no stack, and we are in display-file mode.")
(defvar gud-speedbar-key-map nil
"Keymap used when in the buffers display mode.")
+(defun gud-speedbar-item-info ()
+ "Display the data type of the watch expression element."
+ (let ((var (nth (- (line-number-at-pos (point)) 2) gdb-var-list)))
+ (if (nth 6 var)
+ (speedbar-message "%s: %s" (nth 6 var) (nth 3 var))
+ (speedbar-message "%s" (nth 3 var)))))
+
(defun gud-install-speedbar-variables ()
"Install those variables used by speedbar to enhance gud/gdb."
(if gud-speedbar-key-map
(define-key gud-speedbar-key-map "j" 'speedbar-edit-line)
(define-key gud-speedbar-key-map "e" 'speedbar-edit-line)
(define-key gud-speedbar-key-map "\C-m" 'speedbar-edit-line)
- (define-key gud-speedbar-key-map "D" 'gdb-var-delete)))
+ (define-key gud-speedbar-key-map " " 'speedbar-toggle-line-expansion)
+ (define-key gud-speedbar-key-map "[" 'speedbar-expand-line-descendants)
+ (define-key gud-speedbar-key-map "]" 'speedbar-contract-line-descendants)
+ (define-key gud-speedbar-key-map "D" 'gdb-var-delete)
+ (define-key gud-speedbar-key-map "p" 'gud-pp))
+
+ (speedbar-add-expansion-list '("GUD" gud-speedbar-menu-items
+ gud-speedbar-key-map
+ gud-expansion-speedbar-buttons))
+ (add-to-list
+ 'speedbar-mode-functions-list
+ '("GUD" (speedbar-item-info . gud-speedbar-item-info)
+ (speedbar-line-directory . ignore))))
(defvar gud-speedbar-menu-items
- ;; Note to self. Add expand, and turn off items when not available.
- '(["Jump to stack frame" speedbar-edit-line
- (with-current-buffer gud-comint-buffer
- (not (memq gud-minor-mode '(gdbmi gdba))))]
- ["Edit value" speedbar-edit-line
- (with-current-buffer gud-comint-buffer
- (not (memq gud-minor-mode '(gdbmi gdba))))]
- ["Delete expression" gdb-var-delete
- (with-current-buffer gud-comint-buffer
- (not (memq gud-minor-mode '(gdbmi gdba))))])
+ '(["Jump to stack frame" speedbar-edit-line
+ :visible (not (memq (buffer-local-value 'gud-minor-mode gud-comint-buffer)
+ '(gdbmi gdba)))]
+ ["Edit value" speedbar-edit-line
+ :visible (memq (buffer-local-value 'gud-minor-mode gud-comint-buffer)
+ '(gdbmi gdba))]
+ ["Delete expression" gdb-var-delete
+ :visible (memq (buffer-local-value 'gud-minor-mode gud-comint-buffer)
+ '(gdbmi gdba))]
+ ["Auto raise frame" gdb-speedbar-auto-raise
+ :style toggle :selected gdb-speedbar-auto-raise
+ :visible (memq (buffer-local-value 'gud-minor-mode gud-comint-buffer)
+ '(gdbmi gdba))])
"Additional menu items to add to the speedbar frame.")
;; Make sure our special speedbar mode is loaded
(gud-install-speedbar-variables)
(add-hook 'speedbar-load-hook 'gud-install-speedbar-variables))
+(defun gud-expansion-speedbar-buttons (directory zero)
+ "Wrapper for call to speedbar-add-expansion-list. DIRECTORY and
+ZERO are not used, but are required by the caller."
+ (gud-speedbar-buttons gud-comint-buffer))
+
(defun gud-speedbar-buttons (buffer)
"Create a speedbar display based on the current state of GUD.
If the GUD BUFFER is not running a supported debugger, then turn
-off the specialized speedbar mode."
- (let ((minor-mode (with-current-buffer buffer gud-minor-mode)))
- (cond
- ((memq minor-mode '(gdbmi gdba))
- (when (or gdb-var-changed
- (not (save-excursion
- (goto-char (point-min))
- (let ((case-fold-search t))
- (looking-at "Watch Expressions:")))))
- (erase-buffer)
- (insert "Watch Expressions:\n")
- (let ((var-list gdb-var-list))
- (while var-list
- (let* ((depth 0) (start 0) (char ?+)
- (var (car var-list)) (varnum (nth 1 var)))
- (while (string-match "\\." varnum start)
- (setq depth (1+ depth)
- start (1+ (match-beginning 0))))
- (if (equal (nth 2 var) "0")
- (speedbar-make-tag-line 'bracket ?? nil nil
- (concat (car var) "\t" (nth 4 var))
- 'gdb-edit-value
- nil
- (if (and (nth 5 var)
- gdb-show-changed-values)
- 'font-lock-warning-face
- nil) depth)
- (if (and (cadr var-list)
- (string-match varnum (cadr (cadr var-list))))
- (setq char ?-))
- (speedbar-make-tag-line 'bracket char
- 'gdb-speedbar-expand-node varnum
- (concat (car var) "\t" (nth 3 var))
- nil nil nil depth)))
- (setq var-list (cdr var-list))))
- (setq gdb-var-changed nil)))
- (t (if (and (save-excursion
- (goto-char (point-min))
- (looking-at "Current Stack"))
- (equal gud-last-last-frame gud-last-speedbar-stackframe))
- nil
- (setq gud-last-speedbar-buffer buffer)
- (let ((gud-frame-list
- (cond ((eq minor-mode 'gdb)
- (gud-gdb-get-stackframe buffer))
- ;; Add more debuggers here!
- (t (speedbar-remove-localized-speedbar-support buffer)
- nil))))
- (erase-buffer)
- (if (not gud-frame-list)
- (insert "No Stack frames\n")
- (insert "Current Stack:\n"))
- (dolist (frame gud-frame-list)
- (insert (nth 1 frame) ":\n")
- (if (= (length frame) 2)
- (progn
-; (speedbar-insert-button "[?]"
-; 'speedbar-button-face
-; nil nil nil t)
- (speedbar-insert-button (car frame)
- 'speedbar-directory-face
- nil nil nil t))
-; (speedbar-insert-button "[+]"
-; 'speedbar-button-face
-; 'speedbar-highlight-face
-; 'gud-gdb-get-scope-data
-; frame t)
- (speedbar-insert-button (car frame)
- 'speedbar-file-face
- 'speedbar-highlight-face
- (cond ((memq minor-mode '(gdbmi gdba gdb))
- 'gud-gdb-goto-stackframe)
- (t (error "Should never be here")))
- frame t)))
-; (let ((selected-frame
-; (cond ((eq ff 'gud-gdb-find-file)
-; (gud-gdb-selected-frame-info buffer))
-; (t (error "Should never be here"))))))
- )
- (setq gud-last-speedbar-stackframe gud-last-last-frame))))))
+off the specialized speedbar mode. BUFFER is not used, but are
+required by the caller."
+ (when (and gud-comint-buffer
+ ;; gud-comint-buffer might be killed
+ (buffer-name gud-comint-buffer))
+ (let* ((minor-mode (with-current-buffer buffer gud-minor-mode))
+ (window (get-buffer-window (current-buffer) 0))
+ (p (window-point window)))
+ (cond
+ ((memq minor-mode '(gdbmi gdba))
+ (when (or gdb-force-update
+ (not (save-excursion
+ (goto-char (point-min))
+ (looking-at "Watch Expressions:"))))
+ (erase-buffer)
+ (insert "Watch Expressions:\n")
+ (if gdb-speedbar-auto-raise
+ (raise-frame speedbar-frame))
+ (let ((var-list gdb-var-list) parent)
+ (while var-list
+ (let* (char (depth 0) (start 0) (var (car var-list))
+ (varnum (car var)) (expr (nth 1 var))
+ (type (nth 3 var)) (value (nth 4 var))
+ (status (nth 5 var)))
+ (put-text-property
+ 0 (length expr) 'face font-lock-variable-name-face expr)
+ (put-text-property
+ 0 (length type) 'face font-lock-type-face type)
+ (while (string-match "\\." varnum start)
+ (setq depth (1+ depth)
+ start (1+ (match-beginning 0))))
+ (if (eq depth 0) (setq parent nil))
+ (if (or (equal (nth 2 var) "0")
+ (and (equal (nth 2 var) "1")
+ (string-match "char \\*$" type)))
+ (speedbar-make-tag-line
+ 'bracket ?? nil nil
+ (concat expr "\t" value)
+ (if (or parent (eq status 'out-of-scope))
+ nil 'gdb-edit-value)
+ nil
+ (if gdb-show-changed-values
+ (or parent (case status
+ (changed 'font-lock-warning-face)
+ (out-of-scope 'shadow)
+ (t t)))
+ t)
+ depth)
+ (if (eq status 'out-of-scope) (setq parent 'shadow))
+ (if (and (nth 1 var-list)
+ (string-match (concat varnum "\\.")
+ (car (nth 1 var-list))))
+ (setq char ?-)
+ (setq char ?+))
+ (if (string-match "\\*$" type)
+ (speedbar-make-tag-line
+ 'bracket char
+ 'gdb-speedbar-expand-node varnum
+ (concat expr "\t" type "\t" value)
+ (if (or parent (eq status 'out-of-scope))
+ nil 'gdb-edit-value)
+ nil
+ (if gdb-show-changed-values
+ (or parent (case status
+ (changed 'font-lock-warning-face)
+ (out-of-scope 'shadow)
+ (t t)))
+ t)
+ depth)
+ (speedbar-make-tag-line
+ 'bracket char
+ 'gdb-speedbar-expand-node varnum
+ (concat expr "\t" type)
+ nil nil
+ (if (and (or parent status) gdb-show-changed-values)
+ 'shadow t)
+ depth))))
+ (setq var-list (cdr var-list))))
+ (setq gdb-force-update nil)))
+ (t (unless (and (save-excursion
+ (goto-char (point-min))
+ (looking-at "Current Stack:"))
+ (equal gud-last-last-frame gud-last-speedbar-stackframe))
+ (let ((gud-frame-list
+ (cond ((eq minor-mode 'gdb)
+ (gud-gdb-get-stackframe buffer))
+ ;; Add more debuggers here!
+ (t (speedbar-remove-localized-speedbar-support buffer)
+ nil))))
+ (erase-buffer)
+ (if (not gud-frame-list)
+ (insert "No Stack frames\n")
+ (insert "Current Stack:\n"))
+ (dolist (frame gud-frame-list)
+ (insert (nth 1 frame) ":\n")
+ (if (= (length frame) 2)
+ (progn
+ (speedbar-insert-button (car frame)
+ 'speedbar-directory-face
+ nil nil nil t))
+ (speedbar-insert-button
+ (car frame)
+ 'speedbar-file-face
+ 'speedbar-highlight-face
+ (cond ((memq minor-mode '(gdbmi gdba gdb))
+ 'gud-gdb-goto-stackframe)
+ (t (error "Should never be here")))
+ frame t))))
+ (setq gud-last-speedbar-stackframe gud-last-last-frame))))
+ (set-window-point window p))))
\f
;; ======================================================================
;; Check for annotations and change gud-minor-mode to 'gdba if
;; they are found.
(while (string-match "\n\032\032\\(.*\\)\n" gud-marker-acc)
- (when (string-equal (match-string 1 gud-marker-acc) "prompt")
- (require 'gdb-ui)
- (gdb-prompt nil))
+ (let ((match (match-string 1 gud-marker-acc)))
- (setq
- ;; Append any text before the marker to the output we're going
- ;; to return - we don't include the marker in this text.
- output (concat output
- (substring gud-marker-acc 0 (match-beginning 0)))
+ ;; Pick up stopped annotation if attaching to process.
+ (if (string-equal match "stopped") (setq gdb-active-process t))
- ;; Set the accumulator to the remaining text.
- gud-marker-acc (substring gud-marker-acc (match-end 0))))
+ ;; Using annotations, switch to gud-gdba-marker-filter.
+ (when (string-equal match "prompt")
+ (require 'gdb-ui)
+ (gdb-prompt nil))
+
+ (setq
+ ;; Append any text before the marker to the output we're going
+ ;; to return - we don't include the marker in this text.
+ output (concat output
+ (substring gud-marker-acc 0 (match-beginning 0)))
+
+ ;; Set the accumulator to the remaining text.
+
+ gud-marker-acc (substring gud-marker-acc (match-end 0)))
+
+ ;; Pick up any errors that occur before first prompt annotation.
+ (if (string-equal match "error-begin")
+ (put-text-property 0 (length gud-marker-acc)
+ 'face font-lock-warning-face
+ gud-marker-acc))))
;; Does the remaining text look like it might end with the
;; beginning of another marker? If it does, then keep it in
;;;###autoload
(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."
+The directory containing FILE becomes the initial working
+directory and source-file directory for your debugger. By
+default this command starts GDB using a graphical interface. See
+`gdba' for more information.
+
+To run GDB in text command mode, set `gud-gdb-command-name' to
+\"gdb --fullname\" and include the pathname, if necessary."
(interactive (list (gud-query-cmdline 'gdb)))
+ (if (and gud-comint-buffer
+ (buffer-name gud-comint-buffer)
+ (get-buffer-process gud-comint-buffer)
+ (with-current-buffer gud-comint-buffer (eq gud-minor-mode 'gdba)))
+ (error "Multiple debugging is only supported with \"gdb --fullname\""))
+
(gud-common-init command-line nil 'gud-gdb-marker-filter)
(set (make-local-variable 'gud-minor-mode) 'gdb)
(gud-def gud-break "break %f:%l" "\C-b" "Set breakpoint at current line.")
- (gud-def gud-tbreak "tbreak %f:%l" "\C-t" "Set temporary breakpoint at current line.")
- (gud-def gud-remove "clear %f:%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-nexti "nexti %p" nil "Step one instruction (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-jump "tbreak %f:%l\njump %f:%l" "\C-j" "Relocate execution address to line at point in source buffer.")
-
- (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" "\C-p" "Evaluate C expression at point.")
- (gud-def gud-until "until %l" "\C-u" "Continue to current line.")
- (gud-def gud-run "run" nil "Run the program.")
+ (gud-def gud-tbreak "tbreak %f:%l" "\C-t"
+ "Set temporary breakpoint at current line.")
+ (gud-def gud-remove "clear %f:%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-nexti "nexti %p" nil "Step one instruction (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-jump
+ (progn (gud-call "tbreak %f:%l") (gud-call "jump %f:%l"))
+ "\C-j" "Set execution address to current line.")
+
+ (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" "\C-p" "Evaluate C expression at point.")
+ (gud-def gud-pstar "print* %e" nil
+ "Evaluate C dereferenced pointer expression at point.")
+
+ ;; For debugging Emacs only.
+ (gud-def gud-pv "pv1 %e" "\C-v" "Print the value of the lisp variable.")
+
+ (gud-def gud-until "until %l" "\C-u" "Continue to current line.")
+ (gud-def gud-run "run" nil "Run the program.")
(local-set-key "\C-i" 'gud-gdb-complete-command)
(setq comint-prompt-regexp "^(.*gdb[+]?) *")
;; The completion list is constructed by the process filter.
(defvar gud-gdb-fetched-lines)
-(defvar gud-comint-buffer nil)
-
-(defun gud-gdb-complete-command ()
+(defun gud-gdb-complete-command (&optional command a b)
"Perform completion on the GDB command preceding point.
This is implemented using the GDB `complete' command which isn't
available with older versions of GDB."
(interactive)
- (let* ((end (point))
- (command (buffer-substring (comint-line-beginning-position) end))
- (command-word
+ (if command
+ ;; Used by gud-watch in mini-buffer.
+ (setq command (concat "p " command))
+ ;; Used in GUD buffer.
+ (let ((end (point)))
+ (setq command (buffer-substring (comint-line-beginning-position) end))))
+ (let* ((command-word
;; Find the word break. This match will always succeed.
(and (string-match "\\(\\`\\| \\)\\([^ ]*\\)\\'" command)
(substring command (match-beginning 2))))
(defun gud-gdb-run-command-fetch-lines (command buffer &optional skip)
"Run COMMAND, and return the list of lines it outputs.
-BUFFER is the GUD buffer in which to run the command.
+BUFFER is the current buffer which may be the GUD buffer in which to run.
SKIP is the number of chars to skip on each lines, it defaults to 0."
- (with-current-buffer buffer
- (if (save-excursion
- (goto-char (point-max))
- (forward-line 0)
- (not (looking-at comint-prompt-regexp)))
+ (with-current-buffer gud-comint-buffer
+ (if (and (eq gud-comint-buffer buffer)
+ (save-excursion
+ (goto-char (point-max))
+ (forward-line 0)
+ (not (looking-at comint-prompt-regexp))))
nil
;; Much of this copied from GDB complete, but I'm grabbing the stack
;; frame instead.
(gud-gdb-fetch-lines-string nil)
(gud-gdb-fetch-lines-break (or skip 0))
(gud-marker-filter
- `(lambda (string) (gud-gdb-fetch-lines-filter string ',gud-marker-filter))))
+ `(lambda (string)
+ (gud-gdb-fetch-lines-filter string ',gud-marker-filter))))
;; Issue the command to GDB.
(gud-basic-call command)
;; Slurp the output.
(while gud-gdb-fetch-lines-in-progress
- (accept-process-output (get-buffer-process buffer)))
+ (accept-process-output (get-buffer-process gud-comint-buffer)))
(nreverse gud-gdb-fetched-lines)))))
\f
and source-file directory for your debugger."
(interactive (list (gud-query-cmdline 'sdb)))
+ (if gud-sdb-needs-tags (require 'etags))
(if (and gud-sdb-needs-tags
(not (and (boundp 'tags-file-name)
(stringp tags-file-name)
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
+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 (gud-query-cmdline 'xdb)))
;; Anything else means the input is invalid.
(t
- (message (format "Error parsing file %s." file))
+ (message "Error parsing file %s." file)
(throw 'abort nil))))))
l))
;; print line numbers using LOCALE, inserting a comma or a
;; period at the thousands positions (how ingenious!).
- "\\(\[[0-9]+\] \\)*\\([a-zA-Z0-9.$_]+\\)\\.[a-zA-Z0-9$_<>(),]+ \
+ "\\(\\[[0-9]+] \\)*\\([a-zA-Z0-9.$_]+\\)\\.[a-zA-Z0-9$_<>(),]+ \
\\(([a-zA-Z0-9.$_]+:\\|line=\\)\\([0-9.,]+\\)"
gud-marker-acc)
(save-restriction
(widen)
(if (marker-buffer gud-delete-prompt-marker)
- (progn
+ (let ((inhibit-read-only t))
(delete-region (process-mark proc)
gud-delete-prompt-marker)
+ (comint-update-fence)
(set-marker gud-delete-prompt-marker nil)))
;; Save the process output, checking for source file markers.
(setq output (gud-marker-filter string))
;; This must be outside of the save-excursion
;; in case the source file is our current buffer.
(if process-window
- (save-selected-window
- (select-window process-window)
+ (with-selected-window process-window
(gud-display-frame))
;; We have to be in the proper buffer, (process-buffer proc),
;; but not in a save-excursion, because that would restore point.
- (let ((old-buf (current-buffer)))
- (set-buffer (process-buffer proc))
- (unwind-protect
- (gud-display-frame)
- (set-buffer old-buf)))))
+ (with-current-buffer (process-buffer proc)
+ (gud-display-frame))))
;; If we deferred text that arrived during this processing,
;; handle it now.
;; Stop displaying an arrow in a source file.
(setq gud-overlay-arrow-position nil)
(set-process-buffer proc nil)
+ (if (and (boundp 'speedbar-frame)
+ (string-equal speedbar-initial-expansion-list-name "GUD"))
+ (speedbar-change-initial-expansion-list
+ speedbar-previously-used-expansion-list-name))
(if (memq gud-minor-mode-type '(gdbmi gdba))
(gdb-reset)
(gud-reset)))
(defun gud-kill-buffer-hook ()
(setq gud-minor-mode-type gud-minor-mode)
(condition-case nil
- (kill-process (get-buffer-process gud-comint-buffer))
+ (kill-process (get-buffer-process (current-buffer)))
(error nil)))
(defun gud-reset ()
(with-current-buffer gud-comint-buffer
(gud-find-file true-file)))
(window (and buffer (or (get-buffer-window buffer)
- (display-buffer buffer))))
+ (if (memq gud-minor-mode '(gdbmi gdba))
+ (gdb-display-source-buffer buffer))
+ (display-buffer buffer))))
(pos))
(if buffer
(progn
(setq pos (point))
(or gud-overlay-arrow-position
(setq gud-overlay-arrow-position (make-marker)))
- (set-marker gud-overlay-arrow-position (point) (current-buffer)))
+ (set-marker gud-overlay-arrow-position (point) (current-buffer))
+ ;; If they turned on hl-line, move the hl-line highlight to
+ ;; the arrow's line.
+ (when (featurep 'hl-line)
+ (cond
+ (global-hl-line-mode
+ (global-hl-line-highlight))
+ ((and hl-line-mode hl-line-sticky-flag)
+ (hl-line-highlight)))))
(cond ((or (< pos (point-min)) (> pos (point-max)))
(widen)
(goto-char pos))))
(let ((insource (not (eq (current-buffer) gud-comint-buffer)))
(frame (or gud-last-frame gud-last-last-frame))
result)
- (while (and str (string-match "\\([^%]*\\)%\\([adeflpc]\\)" str))
+ (while (and str
+ (let ((case-fold-search nil))
+ (string-match "\\([^%]*\\)%\\([adefFlpc]\\)" str)))
(let ((key (string-to-char (match-string 2 str)))
subst)
(cond
(set-buffer gud-comint-buffer)
(save-restriction
(widen)
- (goto-char (process-mark proc))
- (forward-line 0)
+ (if (marker-position gud-delete-prompt-marker)
+ ;; We get here when printing an expression.
+ (goto-char gud-delete-prompt-marker)
+ (goto-char (process-mark proc))
+ (forward-line 0))
(if (looking-at comint-prompt-regexp)
(set-marker gud-delete-prompt-marker (point)))
(if (memq gud-minor-mode '(gdbmi gdba))
(defvar gud-find-expr-function 'gud-find-c-expr)
(defun gud-find-expr (&rest args)
- (apply gud-find-expr-function args))
+ (let ((expr (if (and transient-mark-mode mark-active)
+ (buffer-substring (region-beginning) (region-end))
+ (apply gud-find-expr-function args))))
+ (save-match-data
+ (if (string-match "\n" expr)
+ (error "Expression must not include a newline"))
+ (with-current-buffer gud-comint-buffer
+ (save-excursion
+ (goto-char (process-mark (get-buffer-process gud-comint-buffer)))
+ (forward-line 0)
+ (when (looking-at comint-prompt-regexp)
+ (set-marker gud-delete-prompt-marker (point))
+ (set-marker-insertion-type gud-delete-prompt-marker t))
+ (insert (concat expr " = ")))))
+ expr))
;; The next eight functions are hacked from gdbsrc.el by
;; Debby Ayers <ayers@asc.slb.com>,
If `->' is found, return `?.'. If `.' is found, return `?.'.
If any other punctuation is found, return `??'.
If no punctuation is found, return `? '."
- (let ((result ?\ )
+ (let ((result ?\s)
(syntax))
(while (< span-start span-end)
(setq syntax (char-syntax (char-after span-start)))
(cond
- ((= syntax ?\ ) t)
+ ((= syntax ?\s) t)
((= syntax ?.) (setq syntax (char-after span-start))
(cond
((= syntax ?.) (setq result ?.))
((= (car first) (car second)) nil)
((= (cdr first) (cdr second)) nil)
((= syntax ?.) t)
- ((= syntax ?\ )
+ ((= syntax ?\s)
(setq span-start (char-after (- span-start 1)))
(setq span-end (char-after span-end))
(cond
(defvar gdb-script-font-lock-keywords
'(("^define\\s-+\\(\\(\\w\\|\\s_\\)+\\)" (1 font-lock-function-name-face))
("\\$\\(\\w+\\)" (1 font-lock-variable-name-face))
- ("^\\s-*\\([a-z]+\\)" (1 font-lock-keyword-face))))
+ ("^\\s-*\\(\\(\\w\\|\\s_\\)+\\)" (1 font-lock-keyword-face))))
+;; FIXME: The keyword "end" associated with "document"
+;; should have font-lock-keyword-face (currently font-lock-doc-face).
(defvar gdb-script-font-lock-syntactic-keywords
'(("^document\\s-.*\\(\n\\)" (1 "< b"))
;; It would be best to change the \n in front, but it's more difficult.
(defun gdb-script-skip-to-head ()
"We're just in front of an `end' and we need to go to its head."
- (while (and (re-search-backward "^\\s-*\\(\\(end\\)\\|define\\|document\\|if\\|while\\)\\>" nil 'move)
+ (while (and (re-search-backward "^\\s-*\\(\\(end\\)\\|define\\|document\\|if\\|while\\|commands\\)\\>" nil 'move)
(match-end 2))
(gdb-script-skip-to-head)))
(forward-line 0)
(skip-chars-forward " \t")
(+ (current-indentation)
- (if (looking-at "\\(if\\|while\\|define\\|else\\)\\>")
+ (if (looking-at "\\(if\\|while\\|define\\|else\\|commands\\)\\>")
gdb-script-basic-indent 0)))))
(defun gdb-script-indent-line ()
;;; tooltips for GUD
;;; Customizable settings
+
+(define-minor-mode gud-tooltip-mode
+ "Toggle the display of GUD tooltips."
+ :global t
+ :group 'gud
+ :group 'tooltip
+ (require 'tooltip)
+ (if gud-tooltip-mode
+ (progn
+ (add-hook 'change-major-mode-hook 'gud-tooltip-change-major-mode)
+ (add-hook 'pre-command-hook 'tooltip-hide)
+ (add-hook 'tooltip-hook 'gud-tooltip-tips)
+ (define-key global-map [mouse-movement] 'gud-tooltip-mouse-motion))
+ (unless tooltip-mode (remove-hook 'pre-command-hook 'tooltip-hide)
+ (remove-hook 'change-major-mode-hook 'gud-tooltip-change-major-mode)
+ (remove-hook 'tooltip-hook 'gud-tooltip-tips)
+ (define-key global-map [mouse-movement] 'ignore)))
+ (gud-tooltip-activate-mouse-motions-if-enabled)
+ (if (and gud-comint-buffer
+ (buffer-name gud-comint-buffer); gud-comint-buffer might be killed
+ (memq (buffer-local-value 'gud-minor-mode gud-comint-buffer)
+ '(gdbmi gdba)))
+ (if gud-tooltip-mode
+ (progn
+ (dolist (buffer (buffer-list))
+ (unless (eq buffer gud-comint-buffer)
+ (with-current-buffer buffer
+ (when (and (memq gud-minor-mode '(gdbmi gdba))
+ (not (string-match "\\`\\*.+\\*\\'"
+ (buffer-name))))
+ (make-local-variable 'gdb-define-alist)
+ (gdb-create-define-alist)
+ (add-hook 'after-save-hook
+ 'gdb-create-define-alist nil t))))))
+ (kill-local-variable 'gdb-define-alist)
+ (remove-hook 'after-save-hook 'gdb-create-define-alist t))))
+
(defcustom gud-tooltip-modes '(gud-mode c-mode c++-mode fortran-mode)
- "List of modes for which to enable GUD tips."
+ "List of modes for which to enable GUD tooltips."
:type 'sexp
- :tag "GUD modes"
+ :group 'gud
:group 'tooltip)
(defcustom gud-tooltip-display
Forms in the list are combined with AND. The default is to display
only tooltips in the buffer containing the overlay arrow."
:type 'sexp
- :tag "GUD buffers predicate"
+ :group 'gud
:group 'tooltip)
(defcustom gud-tooltip-echo-area nil
"Use the echo area instead of frames for GUD tooltips."
:type 'boolean
- :tag "Use echo area"
+ :group 'gud
:group 'tooltip)
(define-obsolete-variable-alias 'tooltip-gud-modes
'gud-tooltip-modes "22.1")
(define-obsolete-variable-alias 'tooltip-gud-display
'gud-tooltip-display "22.1")
-(define-obsolete-variable-alias 'tooltip-use-echo-area
- 'gud-tooltip-echo-area "22.1")
;;; Reacting on mouse movements
"The mouse movement event that led to a tooltip display.
This event can be examined by forms in GUD-TOOLTIP-DISPLAY.")
-(defun gud-tooltip-toggle-dereference ()
- "Toggle whether tooltips should show `* expr' or `expr'."
- (interactive)
- (setq gud-tooltip-dereference (not gud-tooltip-dereference))
- (when (interactive-p)
- (message "Dereferencing is now %s."
- (if gud-tooltip-dereference "on" "off"))))
+(defun gud-tooltip-dereference (&optional arg)
+ "Toggle whether tooltips should show `* expr' or `expr'.
+With arg, dereference expr iff arg is positive."
+ (interactive "P")
+ (setq gud-tooltip-dereference
+ (if (null arg)
+ (not gud-tooltip-dereference)
+ (> (prefix-numeric-value arg) 0)))
+ (message "Dereferencing is now %s."
+ (if gud-tooltip-dereference "on" "off")))
(define-obsolete-function-alias 'tooltip-gud-toggle-dereference
- 'gud-tooltip-toggle-dereference "22.1")
-
-(define-minor-mode gud-tooltip-mode
- "Toggle the display of GUD tooltips."
- :global t
- :group 'gud
- (require 'tooltip)
- (if gud-tooltip-mode
- (progn
- (add-hook 'change-major-mode-hook 'gud-tooltip-change-major-mode)
- (add-hook 'pre-command-hook 'tooltip-hide)
- (add-hook 'tooltip-hook 'gud-tooltip-tips)
- (define-key global-map [mouse-movement] 'gud-tooltip-mouse-motion))
- (unless tooltip-mode (remove-hook 'pre-command-hook 'tooltip-hide)
- (remove-hook 'change-major-mode-hook 'gud-tooltip-change-major-mode)
- (remove-hook 'tooltip-hook 'gud-tooltip-tips)
- (define-key global-map [mouse-movement] 'ignore)))
- (gud-tooltip-activate-mouse-motions-if-enabled)
- (if (with-current-buffer gud-comint-buffer (eq gud-minor-mode 'gdba))
- (if gud-tooltip-mode
- (progn
- (dolist (buffer (buffer-list))
- (unless (eq buffer gud-comint-buffer)
- (with-current-buffer buffer
- (when (and (memq gud-minor-mode '(gdbmi gdba))
- (not (string-match "\\`\\*.+\\*\\'"
- (buffer-name))))
- (make-local-variable 'gdb-define-alist)
- (gdb-create-define-alist)
- (add-hook 'after-save-hook
- 'gdb-create-define-alist nil t))))))
- (kill-local-variable 'gdb-define-alist)
- (remove-hook 'after-save-hook 'gdb-create-define-alist t))))
+ 'gud-tooltip-dereference "22.1")
; This will only display data that comes in one chunk.
; Larger arrays (say 400 elements) are displayed in
-; the tootip incompletely and spill over into the gud buffer.
+; the tooltip incompletely and spill over into the gud buffer.
; Switching the process-filter creates timing problems and
; it may be difficult to do better. Using annotations as in
; gdb-ui.el gets round this problem.
"Process debugger output and show it in a tooltip window."
(set-process-filter process gud-tooltip-original-filter)
(tooltip-show (tooltip-strip-prompt process output)
- gud-tooltip-echo-area))
+ (or gud-tooltip-echo-area tooltip-use-echo-area)))
(defun gud-tooltip-print-command (expr)
- "Return a suitable command to print the expression EXPR.
-If GUD-TOOLTIP-DEREFERENCE is t, also prepend a `*' to EXPR."
- (when gud-tooltip-dereference
- (setq expr (concat "*" expr)))
+ "Return a suitable command to print the expression EXPR."
(case gud-minor-mode
- (gdba (concat "server print " expr))
- ((dbx gdbmi) (concat "print " expr))
- (xdb (concat "p " expr))
- (sdb (concat expr "/"))
- (perldb expr)))
+ (gdba (concat "server print " expr))
+ ((dbx gdbmi) (concat "print " expr))
+ (xdb (concat "p " expr))
+ (sdb (concat expr "/"))
+ (perldb expr)))
(defun gud-tooltip-tips (event)
"Show tip for identifier or selection under the mouse.
(let (process)
(when (and (eventp event)
gud-tooltip-mode
- (boundp 'gud-comint-buffer)
gud-comint-buffer
- (buffer-name gud-comint-buffer); gud-comint-buffer might be killed
+ (buffer-name gud-comint-buffer); might be killed
(setq process (get-buffer-process gud-comint-buffer))
(posn-point (event-end event))
(or (and (eq gud-minor-mode 'gdba) (not gdb-active-process))
(cddr mouse))))
(let ((define-elt (assoc expr gdb-define-alist)))
(unless (null define-elt)
- (tooltip-show (cdr define-elt))
+ (tooltip-show
+ (cdr define-elt)
+ (or gud-tooltip-echo-area tooltip-use-echo-area))
expr))))
+ (when gud-tooltip-dereference
+ (setq expr (concat "*" expr)))
(let ((cmd (gud-tooltip-print-command expr)))
(when (and gud-tooltip-mode (eq gud-minor-mode 'gdb))
(gud-tooltip-mode -1)