]> code.delx.au - gnu-emacs/blobdiff - lisp/progmodes/gud.el
Update copyright year to 2014 by running admin/update-copyright.
[gnu-emacs] / lisp / progmodes / gud.el
index 47cbdf19ed2c448c7cbc4e695ce400e876d5e11e..f1a8be240131d2ef682b9c18131e29d7f2049328 100644 (file)
@@ -1,6 +1,7 @@
 ;;; gud.el --- Grand Unified Debugger mode for running GDB and other debuggers
 
-;; Copyright (C) 1992-1996, 1998, 2000-2011 Free Software Foundation, Inc.
+;; Copyright (C) 1992-1996, 1998, 2000-2014 Free Software Foundation,
+;; Inc.
 
 ;; Author: Eric S. Raymond <esr@snark.thyrsus.com>
 ;; Maintainer: FSF
@@ -37,8 +38,6 @@
 
 ;;; Code:
 
-(eval-when-compile (require 'cl)) ; for case macro
-
 (require 'comint)
 
 (defvar gdb-active-process)
 (defvar gdb-show-changed-values)
 (defvar gdb-source-window)
 (defvar gdb-var-list)
-(defvar gdb-speedbar-auto-raise)
-(defvar gud-tooltip-mode)
 (defvar hl-line-mode)
 (defvar hl-line-sticky-flag)
-(defvar tool-bar-map)
 
 
 ;; ======================================================================
 ;; GUD commands must be visible in C buffers visited by GUD
 
 (defgroup gud nil
-  "Grand Unified Debugger mode for gdb and other debuggers under Emacs.
-Supported debuggers include gdb, sdb, dbx, xdb, perldb, pdb (Python) and jdb."
+  "The \"Grand Unified Debugger\" interface.
+Supported debuggers include gdb, sdb, dbx, xdb, perldb,
+pdb (Python), and jdb."
   :group 'processes
   :group 'tools)
 
 
 (defcustom gud-key-prefix "\C-x\C-a"
   "Prefix of all GUD commands valid in C buffers."
-  :type 'string
+  :type 'key-sequence
   :group 'gud)
 
-(global-set-key (concat gud-key-prefix "\C-l") 'gud-refresh)
-(define-key ctl-x-map " " 'gud-break)  ;; backward compatibility hack
+(global-set-key (vconcat gud-key-prefix "\C-l") 'gud-refresh)
+;; (define-key ctl-x-map " " 'gud-break); backward compatibility hack
 
 (defvar gud-marker-filter nil)
 (put 'gud-marker-filter 'permanent-local t)
@@ -103,7 +100,7 @@ If SOFT is non-nil, returns nil if the symbol doesn't already exist."
 
 (defvar gud-running nil
   "Non-nil if debugged program is running.
-Used to grey out relevant toolbar icons.")
+Used to gray out relevant toolbar icons.")
 
 (defvar gud-target-name "--unknown--"
   "The apparent name of the program being debugged in a gud buffer.")
@@ -112,20 +109,9 @@ Used to grey out relevant toolbar icons.")
 (defun gud-goto-info ()
   "Go to relevant Emacs info node."
   (interactive)
-  (let ((same-window-regexps same-window-regexps)
-       (display-buffer-reuse-frames t))
-    (catch 'info-found
-      (walk-windows
-       '(lambda (window)
-         (if (eq (window-buffer window) (get-buffer "*info*"))
-             (progn
-               (setq same-window-regexps nil)
-               (throw 'info-found nil))))
-       nil 0)
-      (select-frame (make-frame)))
-    (if (eq gud-minor-mode 'gdbmi)
-       (info "(emacs)GDB Graphical Interface")
-      (info "(emacs)Debuggers"))))
+  (if (eq gud-minor-mode 'gdbmi)
+      (info-other-window "(emacs)GDB Graphical Interface")
+    (info-other-window "(emacs)Debuggers")))
 
 (defun gud-tool-bar-item-visible-no-fringe ()
   (not (or (eq (buffer-local-value 'major-mode (window-buffer)) 'speedbar-mode)
@@ -160,7 +146,8 @@ Used to grey out relevant toolbar icons.")
     ([run]     menu-item "Run" gud-run
                   :enable (not gud-running)
                  :visible (memq gud-minor-mode '(gdbmi gdb dbx jdb)))
-    ([go]      menu-item (if gdb-active-process "Continue" "Run") gud-go
+    ([go]      menu-item (if (bound-and-true-p gdb-active-process)
+                             "Continue" "Run") gud-go
                  :visible (and (eq gud-minor-mode 'gdbmi)
                                 (gdb-show-run-p)))
     ([stop]    menu-item "Stop" gud-stop-subjob
@@ -190,7 +177,7 @@ Used to grey out relevant toolbar icons.")
                                 '(gdbmi gdb dbx xdb jdb pdb)))
     ([pp]      menu-item "Print S-expression" gud-pp
                   :enable (and (not gud-running)
-                                 gdb-active-process)
+                                 (bound-and-true-p gdb-active-process))
                  :visible (and (string-equal
                                 (buffer-local-value
                                  'gud-target-name gud-comint-buffer) "emacs")
@@ -334,8 +321,9 @@ Uses `gud-<MINOR-MODE>-directories' to find the source files."
     (when buf
       ;; Copy `gud-minor-mode' to the found buffer to turn on the menu.
       (with-current-buffer buf
-       (set (make-local-variable 'gud-minor-mode) minor-mode)
-       (set (make-local-variable 'tool-bar-map) gud-tool-bar-map)
+       (setq-local gud-minor-mode minor-mode)
+       (if (boundp 'tool-bar-map)      ; not --without-x
+           (setq-local tool-bar-map gud-tool-bar-map))
        (when (and gud-tooltip-mode
                   (eq gud-minor-mode 'gdbmi))
          (make-local-variable 'gdb-define-alist)
@@ -379,13 +367,13 @@ step (if we're in the GUD buffer).
 source file) or the source line number at the last break or step (if
 we're in the GUD buffer)."
   `(progn
-     (defun ,func (arg)
+     (defalias ',func (lambda (arg)
        ,@(if doc (list doc))
        (interactive "p")
        (if (not gud-running)
         ,(if (stringp cmd)
              `(gud-call ,cmd arg)
-           cmd)))
+           cmd))))
      ,(if key `(local-set-key ,(concat "\C-c" key) ',func))
      ,(if key `(global-set-key (vconcat gud-key-prefix ,key) ',func))))
 
@@ -426,7 +414,7 @@ we're in the GUD buffer)."
 \f
 ;; ======================================================================
 ;; speedbar support functions and variables.
-(eval-when-compile (require 'speedbar))        ;For speedbar-with-attached-buffer.
+(eval-when-compile (require 'dframe)) ; for dframe-with-attached-buffer
 
 (defvar gud-last-speedbar-stackframe nil
   "Description of the currently displayed GUD stack.
@@ -435,19 +423,24 @@ The value 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.")
 
+;; At runtime, will be pulled in as a require of speedbar.
+(declare-function dframe-message "dframe" (fmt &rest args))
+
 (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 7 var)
-       (speedbar-message "%s: %s" (nth 7 var) (nth 3 var))
-      (speedbar-message "%s" (nth 3 var)))))
+       (dframe-message "%s: %s" (nth 7 var) (nth 3 var))
+      (dframe-message "%s" (nth 3 var)))))
+
+(declare-function speedbar-make-specialized-keymap "speedbar" ())
+(declare-function speedbar-add-expansion-list "speedbar" (new-list))
+(defvar speedbar-mode-functions-list)
 
 (defun gud-install-speedbar-variables ()
   "Install those variables used by speedbar to enhance gud/gdb."
-  (if gud-speedbar-key-map
-      nil
+  (unless gud-speedbar-key-map
     (setq gud-speedbar-key-map (speedbar-make-specialized-keymap))
-
     (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)
@@ -491,11 +484,18 @@ The value t means that there is no stack, and we are in display-file mode.")
     (gud-install-speedbar-variables)
   (add-hook 'speedbar-load-hook 'gud-install-speedbar-variables))
 
-(defun gud-expansion-speedbar-buttons (directory zero)
+(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))
 
+(declare-function speedbar-make-tag-line "speedbar"
+                  (type char func data tag tfunc tdata tface depth))
+(declare-function speedbar-remove-localized-speedbar-support "speedbar"
+                  (buffer))
+(declare-function speedbar-insert-button "speedbar"
+                 (text face mouse function &optional token prevline))
+
 (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
@@ -538,10 +538,10 @@ required by the caller."
                       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)))
+                      (or parent (pcase status
+                                   (`changed 'font-lock-warning-face)
+                                   (`out-of-scope 'shadow)
+                                   (_ t)))
                     t)
                   depth)
                (if (eq status 'out-of-scope) (setq parent 'shadow))
@@ -559,10 +559,10 @@ required by the caller."
                         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)))
+                        (or parent (pcase status
+                                     (`changed 'font-lock-warning-face)
+                                     (`out-of-scope 'shadow)
+                                     (_ t)))
                       t)
                     depth)
                  (speedbar-make-tag-line
@@ -657,17 +657,15 @@ The option \"--fullname\" must be included in this value."
        gud-marker-acc (substring gud-marker-acc (match-end 0))))
 
     (while (string-match "\n\032\032\\(.*\\)\n" gud-marker-acc)
-      (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)))
+      (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.
+       ;; Set the accumulator to the remaining text.
 
-        gud-marker-acc (substring gud-marker-acc (match-end 0)))))
+       gud-marker-acc (substring gud-marker-acc (match-end 0))))
 
     ;; Does the remaining text look like it might end with the
     ;; beginning of another marker?  If it does, then keep it in
@@ -719,6 +717,16 @@ The option \"--fullname\" must be included in this value."
 (defvar gud-filter-pending-text nil
   "Non-nil means this is text that has been saved for later in `gud-filter'.")
 
+;; One of the nice features of GDB is its impressive support for
+;; context-sensitive command completion.  We preserve that feature
+;; in the GUD buffer by using a GDB command designed just for Emacs.
+
+(defvar gud-gdb-completion-function nil
+  "Completion function for GDB commands.
+It receives two arguments: COMMAND, the prefix for which we seek
+completion; and CONTEXT, the text before COMMAND on the line.
+It should return a list of completion strings.")
+
 ;; If in gdb mode, gdb-mi is loaded.
 (declare-function gdb-restore-windows "gdb-mi" ())
 
@@ -762,12 +770,16 @@ directory and source-file directory for your debugger."
           "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-pv "pv %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)
+  (add-hook 'completion-at-point-functions #'gud-gdb-completion-at-point
+            nil 'local)
+  (set (make-local-variable 'gud-gdb-completion-function) 'gud-gdb-completions)
+
+  (local-set-key "\C-i" 'completion-at-point)
   (setq comint-prompt-regexp "^(.*gdb[+]?) *")
   (setq paragraph-start comint-prompt-regexp)
   (setq gdb-first-prompt t)
@@ -775,10 +787,6 @@ directory and source-file directory for your debugger."
   (setq gud-filter-pending-text nil)
   (run-hooks 'gud-gdb-mode-hook))
 
-;; One of the nice features of GDB is its impressive support for
-;; context-sensitive command completion.  We preserve that feature
-;; in the GUD buffer by using a GDB command designed just for Emacs.
-
 ;; The completion process filter indicates when it is finished.
 (defvar gud-gdb-fetch-lines-in-progress)
 
@@ -791,61 +799,86 @@ directory and source-file directory for your debugger."
 ;; The completion list is constructed by the process filter.
 (defvar gud-gdb-fetched-lines)
 
-(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)
-  (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))))
-        (complete-list
-         (gud-gdb-run-command-fetch-lines (concat "complete " command)
+(defun gud-gdb-completions (context command)
+  "Completion table for GDB commands.
+COMMAND is the prefix for which we seek completion.
+CONTEXT is the text before COMMAND on the line."
+  (let* ((start (- (point) (field-beginning)))
+         (complete-list
+         (gud-gdb-run-command-fetch-lines (concat "complete " context command)
                                           (current-buffer)
                                           ;; From string-match above.
-                                          (match-beginning 2))))
+                                          (length context))))
+    ;; `gud-gdb-run-command-fetch-lines' has some nasty side-effects on the
+    ;; buffer (via `gud-delete-prompt-marker'): it removes the prompt and then
+    ;; re-adds it later, thus messing up markers and overlays along the way.
+    ;; This is a problem for completion-in-region which uses an overlay to
+    ;; create a field.
+    ;; So we restore completion-in-region's field if needed.
+    ;; FIXME: change gud-gdb-run-command-fetch-lines so it doesn't modify the
+    ;; buffer at all.
+    (when (/= start (- (point) (field-beginning)))
+      (dolist (ol (overlays-at (1- (point))))
+        (when (eq (overlay-get ol 'field) 'completion)
+          (move-overlay ol (- (point) start) (overlay-end ol)))))
     ;; Protect against old versions of GDB.
     (and complete-list
         (string-match "^Undefined command: \"complete\"" (car complete-list))
         (error "This version of GDB doesn't support the `complete' command"))
-    ;; Sort the list like readline.
-    (setq complete-list (sort complete-list (function string-lessp)))
-    ;; Remove duplicates.
-    (let ((first complete-list)
-         (second (cdr complete-list)))
-      (while second
-       (if (string-equal (car first) (car second))
-           (setcdr first (setq second (cdr second)))
-         (setq first second
-               second (cdr second)))))
-    ;; Add a trailing single quote if there is a unique completion
-    ;; and it contains an odd number of unquoted single quotes.
-    (and (= (length complete-list) 1)
-        (let ((str (car complete-list))
-              (pos 0)
-              (count 0))
-          (while (string-match "\\([^'\\]\\|\\\\'\\)*'" str pos)
-            (setq count (1+ count)
-                  pos (match-end 0)))
-          (and (= (mod count 2) 1)
-               (setq complete-list (list (concat str "'"))))))
-    ;; Let comint handle the rest.
-    (comint-dynamic-simple-complete command-word complete-list)))
+    (gud-gdb-completions-1 complete-list)))
+
+;; This function is also used by `gud-gdbmi-completions'.
+(defun gud-gdb-completions-1 (complete-list)
+  ;; Sort the list like readline.
+  (setq complete-list (sort complete-list (function string-lessp)))
+  ;; Remove duplicates.
+  (let ((first complete-list)
+       (second (cdr complete-list)))
+    (while second
+      (if (string-equal (car first) (car second))
+         (setcdr first (setq second (cdr second)))
+       (setq first second
+             second (cdr second)))))
+  ;; Add a trailing single quote if there is a unique completion
+  ;; and it contains an odd number of unquoted single quotes.
+  (and (= (length complete-list) 1)
+       (let ((str (car complete-list))
+            (pos 0)
+            (count 0))
+        (while (string-match "\\([^'\\]\\|\\\\'\\)*'" str pos)
+          (setq count (1+ count)
+                pos (match-end 0)))
+        (and (= (mod count 2) 1)
+             (setq complete-list (list (concat str "'"))))))
+  complete-list)
+
+(defun gud-gdb-completion-at-point ()
+  "Return the data to complete the GDB command before point."
+  (let ((end (point))
+        (start
+         (save-excursion
+           (skip-chars-backward "^ " (comint-line-beginning-position))
+           (point))))
+    (list start end
+          (completion-table-dynamic
+           (apply-partially gud-gdb-completion-function
+                            (buffer-substring (comint-line-beginning-position)
+                                              start))))))
+
+;; (defun gud-gdb-complete-command ()
+;;   "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)
+;;   (apply #'completion-in-region (gud-gdb-completion-at-point)))
 
 ;; The completion process filter is installed temporarily to slurp the
 ;; output of GDB up to the next prompt and build the completion list.
-(defun gud-gdb-fetch-lines-filter (string filter)
+(defun gud-gdb-fetch-lines-filter (string)
   "Filter used to read the list of lines output by a command.
 STRING is the output to filter.
-It is passed through FILTER before we look at it."
-  (setq string (funcall filter string))
+It is passed through `gud-gdb-marker-filter' before we look at it."
+  (setq string (gud-gdb-marker-filter string))
   (setq string (concat gud-gdb-fetch-lines-string string))
   (while (string-match "\n" string)
     (push (substring string gud-gdb-fetch-lines-break (match-beginning 0))
@@ -861,26 +894,20 @@ It is passed through FILTER before we look at it."
 
 ;; gdb speedbar functions
 
-(defun gud-gdb-goto-stackframe (text token indent)
+;; Part of the macro expansion of dframe-with-attached-buffer.
+;; At runtime, will be pulled in as a require of speedbar.
+(declare-function dframe-select-attached-frame "dframe" (&optional frame))
+(declare-function dframe-maybee-jump-to-attached-frame "dframe" ())
+
+(defun gud-gdb-goto-stackframe (_text token _indent)
   "Goto the stackframe described by TEXT, TOKEN, and INDENT."
-  (speedbar-with-attached-buffer
+  (dframe-with-attached-buffer
    (gud-basic-call (concat "server frame " (nth 1 token)))
    (sit-for 1)))
 
 (defvar gud-gdb-fetched-stack-frame nil
   "Stack frames we are fetching from GDB.")
 
-;(defun gud-gdb-get-scope-data (text token indent)
-;  ;; checkdoc-params: (indent)
-;  "Fetch data associated with a stack frame, and expand/contract it.
-;Data to do this is retrieved from TEXT and TOKEN."
-;  (let ((args nil) (scope nil))
-;    (gud-gdb-run-command-fetch-lines "info args")
-;
-;    (gud-gdb-run-command-fetch-lines "info local")
-;
-;    ))
-
 (defun gud-gdb-get-stackframe (buffer)
   "Extract the current stack frame out of the GUD GDB BUFFER."
   (let ((newlst nil)
@@ -924,21 +951,16 @@ It is passed through FILTER before we look at it."
 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 line, it defaults to 0."
   (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.
+    (unless (and (eq gud-comint-buffer buffer)
+                (save-excursion
+                  (goto-char (point-max))
+                  (forward-line 0)
+                  (not (looking-at comint-prompt-regexp))))
       (let ((gud-gdb-fetch-lines-in-progress t)
            (gud-gdb-fetched-lines nil)
            (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))))
+           (gud-marker-filter #'gud-gdb-fetch-lines-filter))
        ;; Issue the command to GDB.
        (gud-basic-call command)
        ;; Slurp the output.
@@ -1040,7 +1062,7 @@ and source-file directory for your debugger."
 (defvar gud-dbx-history nil)
 
 (defcustom gud-dbx-directories nil
-  "*A list of directories that dbx should search for source code.
+  "A list of directories that dbx should search for source code.
 If nil, only source files in the program directory
 will be known to dbx.
 
@@ -1051,7 +1073,7 @@ containing the executable being debugged."
                         directory))
   :group 'gud)
 
-(defun gud-dbx-massage-args (file args)
+(defun gud-dbx-massage-args (_file args)
   (nconc (let ((directories gud-dbx-directories)
               (result nil))
           (while directories
@@ -1158,7 +1180,7 @@ containing the executable being debugged."
 ;; appears to indicate a breakpoint.  Then we prod the dbx sub-process
 ;; to output the information we want with a combination of the
 ;; `printf' and `file' commands as a pseudo marker which we can
-;; recognise next time through the marker-filter.  This would be like
+;; recognize next time through the marker-filter.  This would be like
 ;; the gdb marker but you can't get the file name without a newline...
 ;; Note that gud-remove won't work since Irix dbx expects a breakpoint
 ;; number rather than a line number etc.  Maybe this could be made to
@@ -1352,7 +1374,7 @@ and source-file directory for your debugger."
 (defvar gud-xdb-history nil)
 
 (defcustom gud-xdb-directories nil
-  "*A list of directories that xdb should search for source code.
+  "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.
 
@@ -1363,7 +1385,7 @@ containing the executable being debugged."
                         directory))
   :group 'gud)
 
-(defun gud-xdb-massage-args (file args)
+(defun gud-xdb-massage-args (_file args)
   (nconc (let ((directories gud-xdb-directories)
               (result nil))
           (while directories
@@ -1427,7 +1449,7 @@ directories if your program contains sources from more than one directory."
 ;; History of argument lists passed to perldb.
 (defvar gud-perldb-history nil)
 
-(defun gud-perldb-massage-args (file args)
+(defun gud-perldb-massage-args (_file args)
   "Convert a command line as would be typed normally to run perldb
 into one that invokes an Emacs-enabled debugging session.
 \"-emacs\" is inserted where it will be $ARGV[0] (see perl5db.pl)."
@@ -1480,14 +1502,38 @@ into one that invokes an Emacs-enabled debugging session.
   (let ((output ""))
 
     ;; Process all the complete markers in this chunk.
-    (while (string-match "\032\032\\(\\([a-zA-Z]:\\)?[^:\n]*\\):\\([0-9]*\\):.*\n"
-                        gud-marker-acc)
+    ;;
+    ;; Here I match the string coming out of perldb.
+    ;; The strings can look like any of
+    ;;
+    ;;  "\032\032/tmp/tst.pl:6:0\n"
+    ;;  "\032\032(eval 5)[/tmp/tst.pl:6]:3:0\n"
+    ;;  "\032\032(eval 17)[Basic/Core/Core.pm.PL (i.e. PDL::Core.pm):2931]:1:0\n"
+    ;;
+    ;; From those I want the filename and the line number.  First I look for
+    ;; the eval case.  If that doesn't match, I look for the "normal" case.
+    (while
+        (string-match
+         (eval-when-compile
+           (let ((file-re "\\(?:[a-zA-Z]:\\)?[^:\n]*"))
+             (concat "\032\032\\(?:"
+                     (concat
+                      "(eval [0-9]+)\\["
+                      "\\(" file-re "\\)" ; Filename.
+                      "\\(?: (i\\.e\\. [^)]*)\\)?"
+                      ":\\([0-9]*\\)\\]") ; Line number.
+                     "\\|"
+                     (concat
+                      "\\(?1:" file-re "\\)" ; Filename.
+                      ":\\(?2:[0-9]*\\)")    ; Line number.
+                     "\\):.*\n")))
+         gud-marker-acc)
       (setq
 
        ;; Extract the frame position from the marker.
        gud-last-frame
        (cons (match-string 1 gud-marker-acc)
-            (string-to-number (match-string 3 gud-marker-acc)))
+            (string-to-number (match-string 2 gud-marker-acc)))
 
        ;; Append any text before the marker to the output we're going
        ;; to return - we don't include the marker in this text.
@@ -1560,7 +1606,8 @@ and source-file directory for your debugger."
 ;; Last group is for return value, e.g. "> test.py(2)foo()->None"
 ;; Either file or function name may be omitted: "> <string>(0)?()"
 (defvar gud-pdb-marker-regexp
-  "^> \\([-a-zA-Z0-9_/.:\\]*\\|<string>\\)(\\([0-9]+\\))\\([a-zA-Z0-9_]*\\|\\?\\|<module>\\)()\\(->[^\n]*\\)?\n")
+  "^> \\([-a-zA-Z0-9_/.:\\]*\\|<string>\\)(\\([0-9]+\\))\\([a-zA-Z0-9_]*\\|\\?\\|<module>\\)()\\(->[^\n\r]*\\)?[\n\r]")
+
 (defvar gud-pdb-marker-regexp-file-group 1)
 (defvar gud-pdb-marker-regexp-line-group 2)
 (defvar gud-pdb-marker-regexp-fnname-group 3)
@@ -1639,8 +1686,8 @@ and source-file directory for your debugger."
   (gud-common-init command-line nil 'gud-pdb-marker-filter)
   (set (make-local-variable 'gud-minor-mode) 'pdb)
 
-  (gud-def gud-break  "break %f:%l"  "\C-b" "Set breakpoint at current line.")
-  (gud-def gud-remove "clear %f:%l"  "\C-d" "Remove breakpoint at current line")
+  (gud-def gud-break  "break %d%f:%l"  "\C-b" "Set breakpoint at current line.")
+  (gud-def gud-remove "clear %d%f:%l"  "\C-d" "Remove breakpoint at current line")
   (gud-def gud-step   "step"         "\C-s" "Step one source line with display.")
   (gud-def gud-next   "next"         "\C-n" "Step one line (skip functions).")
   (gud-def gud-cont   "continue"     "\C-r" "Continue with display.")
@@ -1678,7 +1725,7 @@ and source-file directory for your debugger."
 ;;    Run jdb (like this): jdb
 ;;
 ;; type any jdb switches followed by the name of the class you'd like to debug.
-;; Supply a fully qualfied classname (these do not have the ".class" extension)
+;; Supply a fully qualified classname (these don't have the ".class" extension)
 ;; for the name of the class to debug (e.g. "COM.the-kind.ddavies.CoolClass").
 ;; See the known problems section below for restrictions when specifying jdb
 ;; command line switches (search forward for '-classpath').
@@ -1734,7 +1781,7 @@ and source-file directory for your debugger."
 ;; All the .java files in the directories in gud-jdb-directories are
 ;; syntactically analyzed each time gud jdb is invoked.  It would be
 ;; nice to keep as much information as possible between runs.  It would
-;; be really nice to analyze the files only as neccessary (when the
+;; be really nice to analyze the files only as necessary (when the
 ;; source needs to be displayed.)  I'm not sure to what extent the former
 ;; can be accomplished and I'm not sure the latter can be done at all
 ;; since I don't know of any general way to tell which .class files are
@@ -1804,7 +1851,7 @@ source file information.")
 
 ;; List of Java source file directories.
 (defvar gud-jdb-directories (list ".")
-  "*A list of directories that gud jdb should search for source code.
+  "A list of directories that gud jdb should search for source code.
 The file names should be absolute, or relative to the current
 directory.
 
@@ -1908,7 +1955,7 @@ extension EXTN.  Normally EXTN is given as the regular expression
 ;; in petticoat junction.
 (defun gud-jdb-skip-block ()
 
-  ;; Find the begining of the block.
+  ;; Find the beginning of the block.
   (while
       (not (eq (following-char) ?{))
 
@@ -1925,7 +1972,7 @@ extension EXTN.  Normally EXTN is given as the regular expression
       (gud-jdb-skip-character-literal))
      (t (forward-char))))
 
-  ;; Now at the begining of the block.
+  ;; Now at the beginning of the block.
   (forward-char)
 
   ;; Skip over the body of the block as well as the final brace.
@@ -2005,7 +2052,7 @@ extension EXTN.  Normally EXTN is given as the regular expression
           ((looking-at "final")
            (forward-char 5))
 
-          ;; Move point past a ClassDeclaraction, but save the class
+          ;; Move point past a ClassDeclaration, but save the class
           ;; Identifier.
           ((looking-at "class")
            (forward-char 5)
@@ -2049,7 +2096,7 @@ extension EXTN.  Normally EXTN is given as the regular expression
 
 ;; Change what was given in the minibuffer to something that can be used to
 ;; invoke the debugger.
-(defun gud-jdb-massage-args (file args)
+(defun gud-jdb-massage-args (_file args)
   ;; The jdb executable must have whitespace between "-classpath" and
   ;; its value while gud-common-init expects all switch values to
   ;; follow the switch keyword without intervening whitespace.  We
@@ -2083,7 +2130,7 @@ extension EXTN.  Normally EXTN is given as the regular expression
 
        ;; By this point the current directory is all screwed up.  Maybe we
        ;; could fix things and re-invoke gud-common-init, but for now I think
-       ;; issueing the error is good enough.
+       ;; issuing the error is good enough.
        (if user-error
            (progn
              (kill-buffer (current-buffer))
@@ -2091,7 +2138,7 @@ extension EXTN.  Normally EXTN is given as the regular expression
        massaged-args)))
 
 ;; Search for an association with P, a fully qualified class name, in
-;; gud-jdb-class-source-alist.  The asssociation gives the fully
+;; gud-jdb-class-source-alist.  The association gives the fully
 ;; qualified file name of the source file which produced the class.
 (defun gud-jdb-find-source-file (p)
   (cdr (assoc p gud-jdb-class-source-alist)))
@@ -2113,10 +2160,8 @@ relative to a classpath directory."
                    (split-string
                     ;; Eliminate any subclass references in the class
                     ;; name string. These start with a "$"
-                    ((lambda (x)
-                       (if (string-match "$.*" x)
-                           (replace-match "" t t x) p))
-                     p)
+                     (if (string-match "$.*" p)
+                         (replace-match "" t t p) p)
                     "\\.") "/")
         ".java"))
        (cplist (append gud-jdb-sourcepath gud-jdb-classpath))
@@ -2128,7 +2173,7 @@ relative to a classpath directory."
       (setq cplist (cdr cplist)))
     (if found-file (concat (car cplist) "/" filename)))))
 
-(defun gud-jdb-find-source (string)
+(defun gud-jdb-find-source (_string)
   "Alias for function used to locate source files.
 Set to `gud-jdb-find-source-using-classpath' or `gud-jdb-find-source-file'
 during jdb initialization depending on the value of
@@ -2144,7 +2189,7 @@ during jdb initialization depending on the value of
                   string
                   (concat "[ \t\n\r,\"" path-separator "]+")))))
 
-;; See comentary for other debugger's marker filters - there you will find
+;; See commentary for other debugger's marker filters - there you will find
 ;; important notes about STRING.
 (defun gud-jdb-marker-filter (string)
 
@@ -2436,7 +2481,8 @@ comint mode, which see."
   (setq mode-line-process '(":%s"))
   (define-key (current-local-map) "\C-c\C-l" 'gud-refresh)
   (set (make-local-variable 'gud-last-frame) nil)
-  (set (make-local-variable 'tool-bar-map) gud-tool-bar-map)
+  (if (boundp 'tool-bar-map)            ; not --without-x
+      (setq-local tool-bar-map gud-tool-bar-map))
   (make-local-variable 'comint-prompt-regexp)
   ;; Don't put repeated commands in command history many times.
   (set (make-local-variable 'comint-input-ignoredups) t)
@@ -2444,10 +2490,6 @@ comint mode, which see."
   (set (make-local-variable 'gud-delete-prompt-marker) (make-marker))
   (add-hook 'kill-buffer-hook 'gud-kill-buffer-hook nil t))
 
-;; Cause our buffers to be displayed, by default,
-;; in the selected window.
-;;;###autoload (add-hook 'same-window-regexps (purecopy "\\*gud-.*\\*\\(\\|<[0-9]+>\\)"))
-
 (defcustom gud-chdir-before-run t
   "Non-nil if GUD should `cd' to the debugged executable."
   :group 'gud
@@ -2489,7 +2531,7 @@ comint mode, which see."
                      file-subst)))
         (filepart (and file-word (concat "-" (file-name-nondirectory file))))
         (existing-buffer (get-buffer (concat "*gud" filepart "*"))))
-    (pop-to-buffer (concat "*gud" filepart "*"))
+    (switch-to-buffer (concat "*gud" filepart "*"))
     (when (and existing-buffer (get-buffer-process existing-buffer))
       (error "This program is already being debugged"))
     ;; Set the dir, in case the buffer already existed with a different dir.
@@ -2608,6 +2650,8 @@ It is saved for when this flag is not set.")
 (add-to-list 'overlay-arrow-variable-list 'gud-overlay-arrow-position)
 
 (declare-function gdb-reset "gdb-mi" ())
+(declare-function speedbar-change-initial-expansion-list "speedbar" (new))
+(defvar speedbar-previously-used-expansion-list-name)
 
 (defun gud-sentinel (proc msg)
   (cond ((null (buffer-name (process-buffer proc)))
@@ -2615,7 +2659,7 @@ It is saved for when this flag is not set.")
         ;; Stop displaying an arrow in a source file.
         (setq gud-overlay-arrow-position nil)
         (set-process-buffer proc nil)
-        (if (and (boundp 'speedbar-frame)
+        (if (and (boundp 'speedbar-initial-expansion-list-name)
                  (string-equal speedbar-initial-expansion-list-name "GUD"))
             (speedbar-change-initial-expansion-list
              speedbar-previously-used-expansion-list-name))
@@ -2683,7 +2727,6 @@ Obeying it means displaying in another window the specified file and line."
 (declare-function global-hl-line-highlight  "hl-line" ())
 (declare-function hl-line-highlight         "hl-line" ())
 (declare-function gdb-display-source-buffer "gdb-mi"  (buffer))
-(declare-function gdb-display-buffer "gdb-mi" (buf dedicated &optional size))
 
 ;; Make sure the file named TRUE-FILE is in a buffer that appears on the screen
 ;; and that its line LINE is visible.
@@ -2699,45 +2742,39 @@ Obeying it means displaying in another window the specified file and line."
            (gud-find-file true-file)))
         (window (and buffer
                      (or (get-buffer-window buffer)
-                         (if (eq gud-minor-mode 'gdbmi)
-                             (or (if (get-buffer-window buffer 'visible)
-                                     (display-buffer buffer nil 'visible))
-                                 (unless (gdb-display-source-buffer buffer)
-                                   (gdb-display-buffer buffer nil 'visible))))
                          (display-buffer buffer))))
         (pos))
-    (if buffer
-       (progn
-         (with-current-buffer buffer
-           (unless (or (verify-visited-file-modtime buffer) gud-keep-buffer)
-                 (if (yes-or-no-p
-                      (format "File %s changed on disk.  Reread from disk? "
-                              (buffer-name)))
-                     (revert-buffer t t)
-                   (setq gud-keep-buffer t)))
-           (save-restriction
-             (widen)
-             (goto-char (point-min))
-             (forward-line (1- line))
-             (setq pos (point))
-             (or gud-overlay-arrow-position
-                 (setq gud-overlay-arrow-position (make-marker)))
-             (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))))
-         (when window
-           (set-window-point window gud-overlay-arrow-position)
-           (if (eq gud-minor-mode 'gdbmi)
-               (setq gdb-source-window window)))))))
+    (when buffer
+      (with-current-buffer buffer
+       (unless (or (verify-visited-file-modtime buffer) gud-keep-buffer)
+         (if (yes-or-no-p
+              (format "File %s changed on disk.  Reread from disk? "
+                      (buffer-name)))
+             (revert-buffer t t)
+           (setq gud-keep-buffer t)))
+       (save-restriction
+         (widen)
+         (goto-char (point-min))
+         (forward-line (1- line))
+         (setq pos (point))
+         (or gud-overlay-arrow-position
+             (setq gud-overlay-arrow-position (make-marker)))
+         (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))))
+      (when window
+       (set-window-point window gud-overlay-arrow-position)
+       (if (eq gud-minor-mode 'gdbmi)
+           (setq gdb-source-window window))))))
 
 ;; The gud-call function must do the right thing whether its invoking
 ;; keystroke is from the GUD buffer itself (via major-mode binding)
@@ -2759,10 +2796,9 @@ Obeying it means displaying in another window the specified file and line."
                                                  (buffer-file-name)
                                                (car frame)))))
         ((eq key ?F)
-         (setq subst (file-name-sans-extension
-                      (file-name-nondirectory (if insource
-                                                  (buffer-file-name)
-                                                (car frame))))))
+         (setq subst (file-name-base (if insource
+                                          (buffer-file-name)
+                                        (car frame)))))
         ((eq key ?d)
          (setq subst (file-name-directory (if insource
                                               (buffer-file-name)
@@ -3021,10 +3057,8 @@ Link exprs of the form:
 
 (declare-function c-langelem-sym "cc-defs" (langelem))
 (declare-function c-langelem-pos "cc-defs" (langelem))
-(declare-function syntax-symbol  "gud"     (x))
-(declare-function syntax-point   "gud"     (x))
 
-(defun gud-find-class (f line)
+(defun gud-find-class (f _line)
   "Find fully qualified class in file F at line LINE.
 This function uses the `gud-jdb-classpath' (and optional
 `gud-jdb-sourcepath') list(s) to derive a file
@@ -3040,13 +3074,13 @@ class of the file (using s to separate nested class ids)."
       (save-match-data
         (let ((cplist (append gud-jdb-sourcepath gud-jdb-classpath))
               (fbuffer (get-file-buffer f))
-              syntax-symbol syntax-point class-found)
+              class-found
+              ;; Syntax-symbol returns the symbol of the *first* element
+              ;; in the syntactical analysis result list, syntax-point
+              ;; returns the buffer position of same
+              (syntax-symbol (lambda (x) (c-langelem-sym (car x))))
+              (syntax-point (lambda (x) (c-langelem-pos (car x)))))
           (setq f (file-name-sans-extension (file-truename f)))
-          ;; Syntax-symbol returns the symbol of the *first* element
-          ;; in the syntactical analysis result list, syntax-point
-          ;; returns the buffer position of same
-          (fset 'syntax-symbol (lambda (x) (c-langelem-sym (car x))))
-          (fset 'syntax-point (lambda (x) (c-langelem-pos (car x))))
           ;; Search through classpath list for an entry that is
           ;; contained in f
           (while (and cplist (not class-found))
@@ -3061,6 +3095,7 @@ class of the file (using s to separate nested class ids)."
           ;; syntactic information chain and collect any 'inclass
           ;; symbols until 'topmost-intro is reached to find out if
           ;; point is within a nested class
+         ;; FIXME: Yuck!!!  cc-mode should provide a function instead.
           (if (and fbuffer (equal (symbol-file 'java-mode) "cc-mode"))
               (with-current-buffer fbuffer
                 (let ((nclass) (syntax))
@@ -3068,17 +3103,17 @@ class of the file (using s to separate nested class ids)."
                   ;; with the 'topmost-intro symbol, there may be
                   ;; nested classes...
                   (while (not (eq 'topmost-intro
-                                  (syntax-symbol (c-guess-basic-syntax))))
+                                  (funcall syntax-symbol (c-guess-basic-syntax))))
                     ;; Check if the current position c-syntactic
                     ;; analysis has 'inclass
                     (setq syntax (c-guess-basic-syntax))
                     (while
-                        (and (not (eq 'inclass (syntax-symbol syntax)))
+                        (and (not (eq 'inclass (funcall syntax-symbol syntax)))
                              (cdr syntax))
                       (setq syntax (cdr syntax)))
-                    (if (eq 'inclass (syntax-symbol syntax))
+                    (if (eq 'inclass (funcall syntax-symbol syntax))
                         (progn
-                          (goto-char (syntax-point syntax))
+                          (goto-char (funcall syntax-point syntax))
                           ;; Now we're at the beginning of a class
                           ;; definition.  Find class name
                           (looking-at
@@ -3087,9 +3122,9 @@ class of the file (using s to separate nested class ids)."
                                 (append (list (match-string-no-properties 1))
                                         nclass)))
                       (setq syntax (c-guess-basic-syntax))
-                      (while (and (not (syntax-point syntax)) (cdr syntax))
+                      (while (and (not (funcall syntax-point syntax)) (cdr syntax))
                         (setq syntax (cdr syntax)))
-                      (goto-char (syntax-point syntax))
+                      (goto-char (funcall syntax-point syntax))
                       ))
                   (string-match (concat (car nclass) "$") class-found)
                   (setq class-found
@@ -3247,9 +3282,14 @@ Treats actions as defuns."
 
 ;;; Customizable settings
 
+(defvar tooltip-mode)
+
 ;;;###autoload
 (define-minor-mode gud-tooltip-mode
-  "Toggle the display of GUD tooltips."
+  "Toggle the display of GUD tooltips.
+With a prefix argument ARG, enable the feature if ARG is
+positive, and disable it otherwise.  If called from Lisp, enable
+it if ARG is omitted or nil."
   :global t
   :group 'gud
   :group 'tooltip
@@ -3314,6 +3354,9 @@ only tooltips in the buffer containing the overlay arrow."
   :group 'gud
   :group 'tooltip)
 
+(make-obsolete-variable 'gud-tooltip-echo-area
+                       "disable Tooltip mode instead" "24.4" 'set)
+
 ;;; Reacting on mouse movements
 
 (defun gud-tooltip-change-major-mode ()
@@ -3365,9 +3408,6 @@ ACTIVATEP non-nil means activate mouse motion events."
 
 ;;; Tips for `gud'
 
-(defvar gud-tooltip-original-filter nil
-  "Process filter to restore after GUD output has been received.")
-
 (defvar gud-tooltip-dereference nil
   "Non-nil means print expressions with a `*' in front of them.
 For C this would dereference a pointer expression.")
@@ -3378,7 +3418,7 @@ This event can be examined by forms in `gud-tooltip-display'.")
 
 (defun gud-tooltip-dereference (&optional arg)
   "Toggle whether tooltips should show `* expr' or `expr'.
-With arg, dereference expr if ARG is positive, otherwise do not derereference."
+With arg, dereference expr if ARG is positive, otherwise do not dereference."
  (interactive "P")
   (setq gud-tooltip-dereference
        (if (null arg)
@@ -3398,22 +3438,23 @@ With arg, dereference expr if ARG is positive, otherwise do not derereference."
 ; 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 GDB/MI as in
-; gdb-mi.el gets round this problem.
+; gdb-mi.el gets around this problem.
 (defun gud-tooltip-process-output (process output)
   "Process debugger output and show it in a tooltip window."
-  (set-process-filter process gud-tooltip-original-filter)
+  (remove-function (process-filter process) #'gud-tooltip-process-output)
   (tooltip-show (tooltip-strip-prompt process output)
-               (or gud-tooltip-echo-area tooltip-use-echo-area)))
+               (or gud-tooltip-echo-area tooltip-use-echo-area
+                    (not tooltip-mode))))
 
 (defun gud-tooltip-print-command (expr)
   "Return a suitable command to print the expression EXPR."
-  (case gud-minor-mode
-       (gdbmi (concat "-data-evaluate-expression " expr))
-       (dbx (concat "print " expr))
-       ((xdb pdb) (concat "p " expr))
-       (sdb (concat expr "/"))))
+  (pcase gud-minor-mode
+    (`gdbmi (concat "-data-evaluate-expression \"" expr "\""))
+    (`dbx (concat "print " expr))
+    ((or `xdb `pdb) (concat "p " expr))
+    (`sdb (concat expr "/"))))
 
-(declare-function gdb-input "gdb-mi" (item))
+(declare-function gdb-input "gdb-mi" (command handler &optional trigger))
 (declare-function tooltip-expr-to-print "tooltip" (event))
 (declare-function tooltip-event-buffer "tooltip" (event))
 
@@ -3446,27 +3487,31 @@ This function must return nil if it doesn't handle EVENT."
                    (unless (null define-elt)
                      (tooltip-show
                       (cdr define-elt)
-                      (or gud-tooltip-echo-area tooltip-use-echo-area))
+                      (or gud-tooltip-echo-area tooltip-use-echo-area
+                           (not tooltip-mode)))
                      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)
-               (message-box "Using GUD tooltips in this mode is unsafe\n\
+               ;; The blank before the newline is for MS-Windows,
+               ;; whose emulation of message box removes newlines and
+               ;; displays a single long line.
+               (message-box "Using GUD tooltips in this mode is unsafe \n\
 so they have been disabled."))
              (unless (null cmd) ; CMD can be nil if unknown debugger
                (if (eq gud-minor-mode 'gdbmi)
-                     (if gdb-macro-info
-                         (gdb-input
-                          (list (concat
-                                 "server macro expand " expr "\n")
-                                `(lambda () (gdb-tooltip-print-1 ,expr))))
-                       (gdb-input
-                        (list  (concat cmd "\n")
-                                `(lambda () (gdb-tooltip-print ,expr)))))
-                 (setq gud-tooltip-original-filter (process-filter process))
-                 (set-process-filter process 'gud-tooltip-process-output)
+                    (if gdb-macro-info
+                        (gdb-input
+                         (concat
+                         "server macro expand " expr "\n")
+                        `(lambda () (gdb-tooltip-print-1 ,expr)))
+                      (gdb-input
+                      (concat cmd "\n")
+                      `(lambda () (gdb-tooltip-print ,expr))))
+                  (add-function :override (process-filter process)
+                                #'gud-tooltip-process-output)
                  (gud-basic-call cmd))
                expr))))))))