]> code.delx.au - gnu-emacs/blobdiff - lisp/progmodes/gdb-ui.el
*** empty log message ***
[gnu-emacs] / lisp / progmodes / gdb-ui.el
index 697a85cced11a38e2f3c79b20ee980edd9f4006a..5eb44caa7a67bfe6354f03c946de5499b985a1a5 100644 (file)
@@ -4,15 +4,15 @@
 ;; Maintainer: FSF
 ;; Keywords: unix, tools
 
-;; Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008
+;; Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
 ;; Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
-;; GNU Emacs is free software; you can redistribute it and/or modify
+;; GNU Emacs is free software: you can redistribute it and/or modify
 ;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 3, or (at your option)
-;; any later version.
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
 
 ;; GNU Emacs is distributed in the hope that it will be useful,
 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -20,9 +20,7 @@
 ;; GNU General Public License for more details.
 
 ;; 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., 51 Franklin Street, Fifth Floor,
-;; Boston, MA 02110-1301, USA.
+;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
 
 ;;; Commentary:
 
 ;;   2) Use MinGW GDB instead.
 ;;   3) Use cygwin-mount.el
 
+;;; Mac OSX:
+
+;; GDB in Emacs on Mac OSX works best with FSF GDB as Apple have made
+;; some changes to the version that they include as part of Mac OSX.
+;; This requires GDB version 7.0 or later (estimated release date June 2009)
+;; as earlier versions don not compile on Mac OSX.
+
 ;;; Known Bugs:
 
 ;; 1) Cannot handle multiple debug sessions.
 ;;; TODO:
 
 ;; 1) Use MI command -data-read-memory for memory window.
-;; 2) Use tree-widget.el instead of the speedbar for watch-expressions?
+;; 2) Use tree-buffer.el (from ECB) instead of the speedbar for
+;;    watch-expressions?  Handling of watch-expressions needs to be
+;;    overhauled to work for large arrays/structures by creating variable
+;;    objects for visible watch-expressions only.
 ;; 3) Mark breakpoint locations on scroll-bar of source buffer?
 
 ;;; Code:
 (defvar gdb-pc-address nil "Initialization for Assembler buffer.
 Set to \"main\" at start if `gdb-show-main' is t.")
 (defvar gdb-frame-address nil "Identity of frame for watch expression.")
-(defvar gdb-previous-frame-address nil)
+(defvar gdb-previous-frame-pc-address nil)
 (defvar gdb-memory-address "main")
 (defvar gdb-previous-frame nil)
 (defvar gdb-selected-frame nil)
@@ -196,8 +204,7 @@ gdba (gdb-ui.el) uses all five values, gdbmi (gdb-mi.el) only two
 (defconst gdb-error-regexp "\\^error,msg=\"\\(.+\\)\"")
 
 (defvar gdb-locals-font-lock-keywords-1
-  '(
-    ;; var = (struct struct_tag) value
+  '(;; var = (struct struct_tag) value
     ( "\\(^\\(\\sw\\|[_.]\\)+\\) += +(\\(struct\\) \\(\\(\\sw\\|[_.]\\)+\\)"
       (1 font-lock-variable-name-face)
       (3 font-lock-keyword-face)
@@ -208,17 +215,14 @@ gdba (gdb-ui.el) uses all five values, gdbmi (gdb-mi.el) only two
       (3 font-lock-type-face))
     ;; var = val
     ( "\\(^\\(\\sw\\|[_.]\\)+\\) += +[^(]"
-      (1 font-lock-variable-name-face))
-    )
+      (1 font-lock-variable-name-face)))
   "Font lock keywords used in `gdb-local-mode'.")
 
 (defvar gdb-locals-font-lock-keywords-2
-  '(
-    ;; var = type value
+  '(;; var = type value
     ( "\\(^\\(\\sw\\|[_.]\\)+\\)\t+\\(\\(\\sw\\|[_.]\\)+\\)"
       (1 font-lock-variable-name-face)
-      (3 font-lock-type-face))
-    )
+      (3 font-lock-type-face)))
   "Font lock keywords used in `gdb-local-mode'.")
 
 ;; Variables for GDB 6.4+
@@ -253,34 +257,20 @@ The following commands help control operation :
 See Info node `(emacs)GDB Graphical Interface' for a more
 detailed description of this mode.
 
-
 +----------------------------------------------------------------------+
 |                               GDB Toolbar                            |
 +-----------------------------------+----------------------------------+
-| GUD buffer (I/O of GDB)           | Locals buffer                    |
-|                                   |                                  |
-|                                   |                                  |
-|                                   |                                  |
-+-----------------------------------+----------------------------------+
-| Source buffer                     | I/O buffer (of debugged program) |
-|                                   | (comint-mode)                    |
-|                                   |                                  |
-|                                   |                                  |
-|                                   |                                  |
+|  GUD buffer (I/O of GDB)          |  Locals buffer                   |
+|-----------------------------------+----------------------------------+
 |                                   |                                  |
+|  Source buffer                    |  I/O buffer for debugged program |
 |                                   |                                  |
-|                                   |                                  |
-+-----------------------------------+----------------------------------+
-| Stack buffer                      | Breakpoints buffer               |
-| RET      gdb-frames-select        | SPC    gdb-toggle-breakpoint     |
-|                                   | RET    gdb-goto-breakpoint       |
-|                                   | D      gdb-delete-breakpoint     |
+|-----------------------------------+----------------------------------+
+|  Stack buffer                     |  Breakpoints/threads buffer      |
 +-----------------------------------+----------------------------------+
 
-To run GDB in text command mode, replace the GDB \"--annotate=3\"
-option with \"--fullname\" either in the minibuffer for the
-current Emacs session, or the custom variable
-`gud-gdb-command-name' for all future sessions.  You need to use
+The option \"--annotate=3\" must be included in this value.  To
+run GDB in text command mode, use `gud-gdb'.  You need to use
 text command mode to debug multiple programs within one Emacs
 session."
   (interactive (list (gud-query-cmdline 'gdb)))
@@ -334,6 +324,7 @@ session."
   (setq gdb-flush-pending-output nil)
   (setq gdb-early-user-input nil)
   (setq gud-filter-pending-text nil)
+  (gdb-thread-identification)
   (run-hooks 'gdb-mode-hook))
 
 ;; Keep as an alias for compatibility with Emacs 22.1.
@@ -382,6 +373,18 @@ predefined macros."
   :group 'gdb
   :version "22.1")
 
+(defcustom gdb-create-source-file-list t
+  "Non-nil means create a list of files from which the executable was built.
+Set this to nil if the GUD buffer displays \"initializing...\" in the mode
+line for a long time when starting, possibly because your executable was
+built from a large number of files.  This allows quicker initialization
+but means that these files are not automatically enabled for debugging,
+e.g., you won't be able to click in the fringe to set a breakpoint until
+execution has already stopped there."
+  :type 'boolean
+  :group 'gdb
+  :version "23.1")
+
 (defcustom gdb-show-main nil
   "Non-nil means display source file containing the main routine at startup.
 Also display the main routine in the disassembly buffer if present."
@@ -415,6 +418,21 @@ for `gdba'."
          ;; Force mode line redisplay soon.
          (force-mode-line-update)))))
 
+(defun gdb-enable-debug (arg)
+  "Toggle logging of transaction between Emacs and Gdb.
+The log is stored in `gdb-debug-log' as an alist with elements
+whose cons is send, send-item or recv and whose cdr is the string
+being transferred.  This list may grow up to a size of
+`gdb-debug-log-max' after which the oldest element (at the end of
+the list) is deleted every time a new one is added (at the front)."
+  (interactive "P")
+  (setq gdb-enable-debug
+       (if (null arg)
+           (not gdb-enable-debug)
+         (> (prefix-numeric-value arg) 0)))
+  (message (format "Logging of transaction %sabled"
+                  (if gdb-enable-debug "en" "dis"))))
+
 (defun gdb-many-windows (arg)
   "Toggle the number of windows in the basic arrangement.
 With prefix argument ARG, display additional buffers if ARG is positive,
@@ -459,17 +477,23 @@ otherwise do not."
         (output
          (with-output-to-string
            (with-current-buffer standard-output
-             (and file (file-exists-p file)
-             (call-process shell-file-name file
-                           (list t nil) nil "-c"
-                           (concat gdb-cpp-define-alist-program " "
-                                   gdb-cpp-define-alist-flags))))))
+             (and file
+                  (file-exists-p file)
+                  ;; call-process doesn't work with remote file names.
+                  (not (file-remote-p default-directory))
+                  (call-process shell-file-name file
+                                (list t nil) nil "-c"
+                                (concat gdb-cpp-define-alist-program " "
+                                        gdb-cpp-define-alist-flags))))))
        (define-list (split-string output "\n" t)) (name))
     (setq gdb-define-alist nil)
     (dolist (define define-list)
       (setq name (nth 1 (split-string define "[( ]")))
       (push (cons name define) gdb-define-alist))))
 
+(declare-function tooltip-show "tooltip" (text &optional use-echo-area))
+(defvar tooltip-use-echo-area)
+
 (defun gdb-tooltip-print (expr)
   (tooltip-show
    (with-current-buffer (gdb-get-buffer 'gdb-partial-output-buffer)
@@ -480,7 +504,8 @@ otherwise do not."
              (buffer-string))))
        ;; remove newline for gud-tooltip-echo-area
        (substring string 0 (- (length string) 1))))
-   (or gud-tooltip-echo-area tooltip-use-echo-area)))
+   (or gud-tooltip-echo-area tooltip-use-echo-area
+   (not (display-graphic-p)))))
 
 ;; If expr is a macro for a function don't print because of possible dangerous
 ;; side-effects. Also printing a function within a tooltip generates an
@@ -496,6 +521,15 @@ otherwise do not."
 
 (defconst gdb-source-file-regexp "\\(.+?\\), \\|\\([^, \n].*$\\)")
 
+(defun gdb-init-buffer ()
+  (set (make-local-variable 'gud-minor-mode)
+       (buffer-local-value 'gud-minor-mode gud-comint-buffer))
+  (set (make-local-variable 'tool-bar-map) gud-tool-bar-map)
+  (when gud-tooltip-mode
+    (make-local-variable 'gdb-define-alist)
+    (gdb-create-define-alist)
+    (add-hook 'after-save-hook 'gdb-create-define-alist nil t)))
+
 (defun gdb-set-gud-minor-mode-existing-buffers ()
   "Create list of source files for current GDB session."
   (goto-char (point-min))
@@ -508,12 +542,7 @@ otherwise do not."
        (when (and buffer-file-name
                   (member (file-name-nondirectory buffer-file-name)
                           gdb-source-file-list))
-         (set (make-local-variable 'gud-minor-mode) 'gdba)
-         (set (make-local-variable 'tool-bar-map) gud-tool-bar-map)
-         (when gud-tooltip-mode
-           (make-local-variable 'gdb-define-alist)
-           (gdb-create-define-alist)
-           (add-hook 'after-save-hook 'gdb-create-define-alist nil t))))))
+         (gdb-init-buffer)))))
   (gdb-force-mode-line-update
    (propertize "ready" 'face font-lock-variable-name-face)))
 
@@ -600,7 +629,7 @@ otherwise do not."
 
   ;; (re-)initialize
   (setq gdb-pc-address (if gdb-show-main "main" nil))
-  (setq gdb-previous-frame-address nil
+  (setq gdb-previous-frame-pc-address nil
        gdb-memory-address "main"
        gdb-previous-frame nil
        gdb-selected-frame nil
@@ -646,7 +675,7 @@ otherwise do not."
   (gdb-enqueue-input (list "set width 0\n" 'ignore))
 
   (if (string-equal gdb-version "pre-6.4")
-      (progn
+      (if gdb-create-source-file-list
        (gdb-enqueue-input (list (concat gdb-server-prefix "info sources\n")
                                 'gdb-set-gud-minor-mode-existing-buffers))
        (setq gdb-locals-font-lock-keywords gdb-locals-font-lock-keywords-1))
@@ -654,17 +683,16 @@ otherwise do not."
      (list "server interpreter mi -data-list-register-names\n"
         'gdb-get-register-names))
     ; Needs GDB 6.2 onwards.
-    (gdb-enqueue-input
-     (list "server interpreter mi \"-file-list-exec-source-files\"\n"
-          'gdb-set-gud-minor-mode-existing-buffers-1))
+    (if gdb-create-source-file-list
+       (gdb-enqueue-input
+        (list "server interpreter mi \"-file-list-exec-source-files\"\n"
+              'gdb-set-gud-minor-mode-existing-buffers-1)))
     (setq gdb-locals-font-lock-keywords gdb-locals-font-lock-keywords-2))
 
   ;; Find source file and compilation directory here.
   ;; Works for C, C++, Fortran and Ada but not Java (GDB 6.4)
   (gdb-enqueue-input (list "server list\n" 'ignore))
-  (gdb-enqueue-input (list "server info source\n" 'gdb-source-info))
-
-  (run-hooks 'gdb-mode-hook))
+  (gdb-enqueue-input (list "server info source\n" 'gdb-source-info)))
 
 (defun gdb-get-version ()
   (goto-char (point-min))
@@ -750,6 +778,8 @@ positive, otherwise don't automatically raise it."
 (define-key gud-minor-mode-map "\C-c\C-w" 'gud-watch)
 (define-key global-map (concat gud-key-prefix "\C-w") 'gud-watch)
 
+(declare-function tooltip-identifier-from-point "tooltip" (point))
+
 (defun gud-watch (&optional arg event)
   "Watch expression at point.
 With arg, enter name of variable to be watched in the minibuffer."
@@ -766,16 +796,16 @@ With arg, enter name of variable to be watched in the minibuffer."
                                        'gud-gdb-complete-command)
                     (if (and transient-mark-mode mark-active)
                         (buffer-substring (region-beginning) (region-end))
-                      (tooltip-identifier-from-point (point))))))
-             (speedbar 1)
-               (set-text-properties 0 (length expr) nil expr)
-               (gdb-enqueue-input
-                (list
-                 (if (eq minor-mode 'gdba)
-                     (concat
-                      "server interpreter mi \"-var-create - * "  expr "\"\n")
-                   (concat"-var-create - * "  expr "\n"))
-                 `(lambda () (gdb-var-create-handler ,expr)))))))
+                      (concat (if (eq major-mode 'gdb-registers-mode) "$")
+                              (tooltip-identifier-from-point (point)))))))
+             (set-text-properties 0 (length expr) nil expr)
+             (gdb-enqueue-input
+              (list
+               (if (eq minor-mode 'gdba)
+                   (concat
+                    "server interpreter mi \"-var-create - * "  expr "\"\n")
+                 (concat"-var-create - * "  expr "\n"))
+               `(lambda () (gdb-var-create-handler ,expr)))))))
       (message "gud-watch is a no-op in this mode."))))
 
 (defconst gdb-var-create-regexp
@@ -795,6 +825,7 @@ With arg, enter name of variable to be watched in the minibuffer."
                  (if (match-string 3) (read (match-string 3)))
                  nil gdb-frame-address)))
        (push var gdb-var-list)
+       (speedbar 1)
        (unless (string-equal
                 speedbar-initial-expansion-list-name "GUD")
          (speedbar-change-initial-expansion-list "GUD"))
@@ -821,6 +852,8 @@ With arg, enter name of variable to be watched in the minibuffer."
     (push 'gdb-speedbar-timer gdb-pending-triggers)))
 
 (defun gdb-speedbar-timer-fn ()
+  (if gdb-speedbar-auto-raise
+      (raise-frame speedbar-frame))
   (setq gdb-pending-triggers
        (delq 'gdb-speedbar-timer gdb-pending-triggers))
   (speedbar-timer-fn))
@@ -842,8 +875,8 @@ With arg, enter name of variable to be watched in the minibuffer."
         `(lambda () (gdb-var-list-children-handler ,varnum)))))
 
 (defconst gdb-var-list-children-regexp
-  "child={.*?name=\"\\(.*?\\)\",.*?exp=\"\\(.*?\\)\",.*?\
-numchild=\"\\(.*?\\)\"\\(}\\|,.*?\\(type=\"\\(.*?\\)\"\\)?.*?}\\)")
+  "child={.*?name=\"\\(.*?\\)\".*?,exp=\"\\(.*?\\)\".*?,\
+numchild=\"\\(.*?\\)\"\\(}\\|.*?,\\(type=\"\\(.*?\\)\"\\)?.*?}\\)")
 
 (defun gdb-var-list-children-handler (varnum)
   (goto-char (point-min))
@@ -880,7 +913,7 @@ numchild=\"\\(.*?\\)\"\\(}\\|,.*?\\(type=\"\\(.*?\\)\"\\)?.*?}\\)")
     (push 'gdb-var-update gdb-pending-triggers)))
 
 (defconst gdb-var-update-regexp
-  "{.*?name=\"\\(.*?\\)\",.*?in_scope=\"\\(.*?\\)\",.*?\
+  "{.*?name=\"\\(.*?\\)\".*?,in_scope=\"\\(.*?\\)\".*?,\
 type_changed=\".*?\".*?}")
 
 (defun gdb-var-update-handler ()
@@ -1320,7 +1353,9 @@ want the GDB Graphical Interface."
     ("stopped" gdb-stopped)
     ("error-begin" gdb-error)
     ("error" gdb-error)
-    ("new-thread" (lambda (ignored) (gdb-get-buffer-create 'gdb-threads-buffer))))
+    ("new-thread" (lambda (ignored)
+                   (gdb-get-buffer-create 'gdb-threads-buffer)))
+    ("thread-changed" gdb-thread-changed))
   "An assoc mapping annotation tags to functions which process them.")
 
 (defun gdb-resync()
@@ -1479,7 +1514,7 @@ directives."
       (gdb-resync)
       (error "Unexpected frame-begin annotation (%S)" sink)))))
 
-(defcustom gdb-same-frame focus-follows-mouse
+(defcustom gdb-same-frame (not focus-follows-mouse)
   "Non-nil means pop up GUD buffer in same frame."
   :group 'gdb
   :type 'boolean
@@ -1546,6 +1581,9 @@ sink to `user' in `gdb-stopping', that is fine."
 (defun gdb-error (ignored)
   (setq gdb-error (not gdb-error)))
 
+(defun gdb-thread-changed (ignored)
+  (gdb-frames-force-update))
+
 (defun gdb-post-prompt (ignored)
   "An annotation handler for `post-prompt'.
 This begins the collection of output from the current command if that
@@ -1573,7 +1611,8 @@ happens to be appropriate."
       (gdb-invalidate-locals-1))
 
     (gdb-invalidate-threads)
-    (unless (eq system-type 'darwin) ;Breaks on Darwin's GDB-5.3.
+    (unless (or (null gdb-var-list)
+            (eq system-type 'darwin)) ;Breaks on Darwin's GDB-5.3.
       ;; FIXME: with GDB-6 on Darwin, this might very well work.
       ;; Only needed/used with speedbar/watch expressions.
       (when (and (boundp 'speedbar-frame) (frame-live-p speedbar-frame))
@@ -1647,15 +1686,12 @@ happens to be appropriate."
          (let* ((annotation-type (match-string 1 annotation))
                 (annotation-arguments (match-string 2 annotation))
                 (annotation-rule (assoc annotation-type
-                                        gdb-annotation-rules))
-                (fullname (string-match gdb-fullname-regexp annotation-type)))
+                                        gdb-annotation-rules)))
 
            ;; Stuff prior to the match is just ordinary output.
            ;; It is either concatenated to OUTPUT or directed
            ;; elsewhere.
-           (setq output
-                 (gdb-concat-output output
-                                    (concat before (if fullname "\n"))))
+           (setq output (gdb-concat-output output before))
 
            ;; Take that stuff off the gud-marker-acc.
            (setq gud-marker-acc after)
@@ -1663,19 +1699,7 @@ happens to be appropriate."
            ;; Call the handler for this annotation.
            (if annotation-rule
                (funcall (car (cdr annotation-rule))
-                        annotation-arguments)
-
-             ;; Switch to gud-gdb-marker-filter if appropriate.
-             (when fullname
-
-               ;; Extract the frame position from the marker.
-               (setq gud-last-frame (cons (match-string 1 annotation)
-                                          (string-to-number
-                                           (match-string 2 annotation))))
-
-               (set (make-local-variable 'gud-minor-mode) 'gdb)
-               (set (make-local-variable 'gud-marker-filter)
-                    'gud-gdb-marker-filter)))
+                        annotation-arguments))
 
            ;; Else the annotation is not recognized.  Ignore it silently,
            ;; so that GDB can add new annotations without causing
@@ -1891,6 +1915,9 @@ static char *magick[] = {
 (defvar breakpoint-disabled-icon nil
   "Icon for disabled breakpoint in display margin.")
 
+(declare-function define-fringe-bitmap "fringe.c"
+                 (bitmap bits &optional height width align))
+
 (and (display-images-p)
      ;; Bitmap for breakpoint in fringe
      (define-fringe-bitmap 'breakpoint
@@ -1934,43 +1961,40 @@ static char *magick[] = {
     (with-current-buffer (gdb-get-buffer 'gdb-breakpoints-buffer)
       (save-excursion
        (let ((buffer-read-only nil))
-       (goto-char (point-min))
-       (while (< (point) (- (point-max) 1))
-         (forward-line 1)
-         (if (looking-at gdb-breakpoint-regexp)
-             (progn
-               (setq bptno (or (match-string 1) (match-string 2)))
-               (setq flag (char-after (match-beginning 3)))
-               (if (match-string 1)
-                   (setq gdb-parent-bptno-enabled (eq flag ?y)))
-               (add-text-properties
-                (match-beginning 3) (match-end 3)
-                (if (eq flag ?y)
-                    '(face font-lock-warning-face)
-                  '(face font-lock-type-face)))
-               (let ((bl (point))
-                     (el (line-end-position)))
-                 (if (re-search-forward " in \\(.*\\) at\\s-+" el t)
-                     (progn
-                       (add-text-properties
-                        (match-beginning 1) (match-end 1)
-                        '(face font-lock-function-name-face))
-                       (looking-at "\\(\\S-+\\):\\([0-9]+\\)")
+         (goto-char (point-min))
+         (while (< (point) (- (point-max) 1))
+           (forward-line 1)
+           (if (looking-at gdb-breakpoint-regexp)
+               (progn
+                 (setq bptno (or (match-string 1) (match-string 2)))
+                 (setq flag (char-after (match-beginning 3)))
+                 (if (match-string 1)
+                     (setq gdb-parent-bptno-enabled (eq flag ?y)))
+                 (add-text-properties
+                  (match-beginning 3) (match-end 3)
+                  (if (eq flag ?y)
+                      '(face font-lock-warning-face)
+                    '(face font-lock-type-face)))
+                 (let ((bl (point))
+                       (el (line-end-position)))
+                   (when (re-search-forward " in \\(.*\\) at" el t)
+                     (add-text-properties
+                      (match-beginning 1) (match-end 1)
+                      '(face font-lock-function-name-face)))
+                   (if (re-search-forward
+                        ".*\\s-+\\(\\S-+\\):\\([0-9]+\\)$" el t)
                        (let ((line (match-string 2))
                              (file (match-string 1)))
                          (add-text-properties bl el
-                          '(mouse-face highlight
-                            help-echo "mouse-2, RET: visit breakpoint"))
+                              '(mouse-face highlight
+                                help-echo "mouse-2, RET: visit breakpoint"))
                          (unless (file-exists-p file)
                            (setq file (cdr (assoc bptno gdb-location-alist))))
                          (if (and file
                                   (not (string-equal file "File not found")))
                              (with-current-buffer
                                  (find-file-noselect file 'nowarn)
-                               (set (make-local-variable 'gud-minor-mode)
-                                    'gdba)
-                               (set (make-local-variable 'tool-bar-map)
-                                    gud-tool-bar-map)
+                               (gdb-init-buffer)
                                ;; Only want one breakpoint icon at each
                                ;; location.
                                (save-excursion
@@ -1984,20 +2008,20 @@ static char *magick[] = {
                            (gdb-enqueue-input
                             (list (concat gdb-server-prefix "info source\n")
                                   `(lambda () (gdb-get-location
-                                               ,bptno ,line ,flag)))))))
-                   (if (re-search-forward
-                        "<\\(\\(\\sw\\|[_.]\\)+\\)\\(\\+[0-9]+\\)?>"
-                        el t)
+                                               ,bptno ,line ,flag))))))
+                     (if (re-search-forward
+                          "<\\(\\(\\sw\\|[_.]\\)+\\)\\(\\+[0-9]+\\)?>"
+                          el t)
+                         (add-text-properties
+                          (match-beginning 1) (match-end 1)
+                          '(face font-lock-function-name-face))
+                       (end-of-line)
+                       (re-search-backward "\\s-\\(\\S-*\\)"
+                                           bl t)
                        (add-text-properties
                         (match-beginning 1) (match-end 1)
-                        '(face font-lock-function-name-face))
-                     (end-of-line)
-                     (re-search-backward "\\s-\\(\\S-*\\)"
-                                         bl t)
-                     (add-text-properties
-                      (match-beginning 1) (match-end 1)
-                      '(face font-lock-variable-name-face)))))))
-         (end-of-line))))))
+                        '(face font-lock-variable-name-face)))))))
+           (end-of-line))))))
   (if (gdb-get-buffer 'gdb-assembler-buffer) (gdb-assembler-custom))
 
   ;; Breakpoints buffer is always present.  Hack to just update
@@ -2008,6 +2032,7 @@ static char *magick[] = {
 
 (declare-function gud-remove "gdb-ui" t t) ; gud-def
 (declare-function gud-break  "gdb-ui" t t) ; gud-def
+(declare-function fringe-bitmaps-at-pos "fringe.c" (&optional pos window))
 
 (defun gdb-mouse-set-clear-breakpoint (event)
   "Set/clear breakpoint in left fringe/margin at mouse click.
@@ -2015,9 +2040,9 @@ If not in a source or disassembly buffer just set point."
   (interactive "e")
   (mouse-minibuffer-check event)
   (let ((posn (event-end event)))
-    (if (or (buffer-file-name) (eq major-mode 'gdb-assembler-mode))
-       (if (numberp (posn-point posn))
-           (with-selected-window (posn-window posn)
+    (with-selected-window (posn-window posn)
+      (if (or (buffer-file-name) (eq major-mode 'gdb-assembler-mode))
+         (if (numberp (posn-point posn))
              (save-excursion
                (goto-char (posn-point posn))
                (if (or (posn-object posn)
@@ -2118,6 +2143,47 @@ If not in a source or disassembly buffer just set point."
   (if (one-window-p) (delete-frame)
     (delete-window)))
 
+;;from make-mode-line-mouse-map
+(defun gdb-make-header-line-mouse-map (mouse function) "\
+Return a keymap with single entry for mouse key MOUSE on the header line.
+MOUSE is defined to run function FUNCTION with no args in the buffer
+corresponding to the mode line clicked."
+  (let ((map (make-sparse-keymap)))
+    (define-key map (vector 'header-line mouse) function)
+    (define-key map (vector 'header-line 'down-mouse-1) 'ignore)
+    map))
+
+(defvar gdb-breakpoints-header
+ `(,(propertize "Breakpoints"
+               'help-echo "mouse-1: select"
+               'mouse-face 'mode-line-highlight
+               'face 'mode-line
+               'local-map
+               (gdb-make-header-line-mouse-map
+                'mouse-1
+                (lambda (event) (interactive "e")
+                  (save-selected-window
+                    (select-window (posn-window (event-start event)))
+                    (set-window-dedicated-p (selected-window) nil)
+                    (switch-to-buffer
+                     (gdb-get-buffer-create 'gdb-breakpoints-buffer))
+                    (set-window-dedicated-p (selected-window) t)))))
+   " "
+   ,(propertize "Threads"
+               'help-echo "mouse-1: select"
+               'mouse-face 'mode-line-highlight
+               'face 'mode-line
+               'local-map
+               (gdb-make-header-line-mouse-map
+                'mouse-1
+                (lambda (event) (interactive "e")
+                  (save-selected-window
+                    (select-window (posn-window (event-start event)))
+                    (set-window-dedicated-p (selected-window) nil)
+                    (switch-to-buffer
+                     (gdb-get-buffer-create 'gdb-threads-buffer))
+                    (set-window-dedicated-p (selected-window) t)))))))
+
 (defun gdb-breakpoints-mode ()
   "Major mode for gdb breakpoints.
 
@@ -2127,6 +2193,8 @@ If not in a source or disassembly buffer just set point."
   (setq mode-name "Breakpoints")
   (use-local-map gdb-breakpoints-mode-map)
   (setq buffer-read-only t)
+  (buffer-disable-undo)
+  (setq header-line-format gdb-breakpoints-header)
   (run-mode-hooks 'gdb-breakpoints-mode-hook)
   (if (eq (buffer-local-value 'gud-minor-mode gud-comint-buffer) 'gdba)
       'gdb-invalidate-breakpoints
@@ -2167,7 +2235,7 @@ If not in a source or disassembly buffer just set point."
   (if event (posn-set-point (event-end event)))
   (save-excursion
     (beginning-of-line 1)
-    (if (looking-at "\\([0-9]+\\.?[0-9]*\\) .+ in .+ at\\s-+\\(\\S-+\\):\\([0-9]+\\)")
+    (if (looking-at "\\([0-9]+\\.?[0-9]*\\) .*\\s-+\\(\\S-+\\):\\([0-9]+\\)$")
        (let ((bptno (match-string 1))
              (file  (match-string 2))
              (line  (match-string 3)))
@@ -2184,7 +2252,7 @@ If not in a source or disassembly buffer just set point."
       (error "No location specified."))))
 \f
 
-;; Frames buffer.  This displays a perpetually correct bactracktrace
+;; Frames buffer.  This displays a perpetually correct backtrace
 ;; (from the command `where').
 ;;
 ;; Alas, if your stack is deep, it is costly.
@@ -2225,20 +2293,20 @@ If not in a source or disassembly buffer just set point."
                    el (line-end-position))
              (when (looking-at "#")
                (add-text-properties bl el
-                                    '(mouse-face highlight
-                                                 help-echo "mouse-2, RET: Select frame")))
+                   '(mouse-face highlight
+                                help-echo "mouse-2, RET: Select frame")))
              (goto-char bl)
              (when (looking-at "^#\\([0-9]+\\)")
                (when (string-equal (match-string 1) gdb-frame-number)
-                 (if (> (car (window-fringes)) 0)
+                 (if (gud-tool-bar-item-visible-no-fringe)
                      (progn
-                       (or gdb-stack-position
-                           (setq gdb-stack-position (make-marker)))
-                       (set-marker gdb-stack-position (point))
-                       (setq move-to gdb-stack-position))
-                   (put-text-property bl (+ bl 4)
-                                      'face '(:inverse-video t))
-                   (setq move-to bl)))
+                       (put-text-property bl (+ bl 4)
+                                          'face '(:inverse-video t))
+                       (setq move-to bl))
+                   (or gdb-stack-position
+                       (setq gdb-stack-position (make-marker)))
+                   (set-marker gdb-stack-position (point))
+                   (setq move-to gdb-stack-position)))
                (when (re-search-forward "\\([^ ]+\\) (" el t)
                  (put-text-property (match-beginning 1) (match-end 1)
                                     'face font-lock-function-name-face)
@@ -2253,11 +2321,13 @@ If not in a source or disassembly buffer just set point."
              (forward-line 1))
            (forward-line -1)
            (when (looking-at "(More stack frames follow...)")
-             (add-text-properties (match-beginning 0) (match-end 0)
-                                  '(mouse-face highlight
-                                               gdb-max-frames t
-                                               help-echo
-                                               "mouse-2, RET: customize gdb-max-frames to see more frames")))))
+             (add-text-properties
+              (match-beginning 0) (match-end 0)
+              '(mouse-face highlight
+                gdb-max-frames t
+                help-echo
+                  "mouse-2, RET: customize gdb-max-frames to see more frames"
+                )))))
        (when gdb-look-up-stack
          (goto-char (point-min))
          (when (re-search-forward "\\(\\S-+?\\):\\([0-9]+\\)" nil t)
@@ -2314,6 +2384,8 @@ If not in a source or disassembly buffer just set point."
     (define-key map [follow-link] 'mouse-face)
     map))
 
+(declare-function gdbmi-invalidate-frames "ext:gdb-mi" nil t)
+
 (defun gdb-frames-force-update ()
   "Force update of call stack.
 Use when the displayed call stack gets out of sync with the
@@ -2336,6 +2408,7 @@ $pc directly from the GUD buffer.  This command isn't normally needed."
   (add-to-list 'overlay-arrow-variable-list 'gdb-stack-position)
   (setq truncate-lines t)  ;; Make it easier to see overlay arrow.
   (setq buffer-read-only t)
+  (buffer-disable-undo)
   (gdb-thread-identification)
   (use-local-map gdb-frames-mode-map)
   (run-mode-hooks 'gdb-frames-mode-hook)
@@ -2436,6 +2509,8 @@ another GDB command e.g pwd, to see new frames")
   (setq major-mode 'gdb-threads-mode)
   (setq mode-name "Threads")
   (setq buffer-read-only t)
+  (buffer-disable-undo)
+  (setq header-line-format gdb-breakpoints-header)
   (use-local-map gdb-threads-mode-map)
   (set (make-local-variable 'font-lock-defaults)
        '(gdb-threads-font-lock-keywords))
@@ -2519,6 +2594,37 @@ another GDB command e.g pwd, to see new frames")
     (define-key map "q" 'kill-this-buffer)
      map))
 
+(defvar gdb-locals-header
+ `(,(propertize "Locals"
+               'help-echo "mouse-1: select"
+               'mouse-face 'mode-line-highlight
+               'face 'mode-line
+               'local-map
+               (gdb-make-header-line-mouse-map
+                'mouse-1
+                (lambda (event) (interactive "e")
+                  (save-selected-window
+                    (select-window (posn-window (event-start event)))
+                    (set-window-dedicated-p (selected-window) nil)
+                    (switch-to-buffer
+                     (gdb-get-buffer-create 'gdb-locals-buffer))
+                    (set-window-dedicated-p (selected-window) t)))))
+   " "
+   ,(propertize "Registers"
+               'help-echo "mouse-1: select"
+               'mouse-face 'mode-line-highlight
+               'face 'mode-line
+               'local-map
+               (gdb-make-header-line-mouse-map
+                'mouse-1
+                (lambda (event) (interactive "e")
+                  (save-selected-window
+                    (select-window (posn-window (event-start event)))
+                    (set-window-dedicated-p (selected-window) nil)
+                    (switch-to-buffer
+                     (gdb-get-buffer-create 'gdb-registers-buffer))
+                    (set-window-dedicated-p (selected-window) t)))))))
+
 (defun gdb-registers-mode ()
   "Major mode for gdb registers.
 
@@ -2526,7 +2632,9 @@ another GDB command e.g pwd, to see new frames")
   (kill-all-local-variables)
   (setq major-mode 'gdb-registers-mode)
   (setq mode-name "Registers")
+  (setq header-line-format gdb-locals-header)
   (setq buffer-read-only t)
+  (buffer-disable-undo)
   (gdb-thread-identification)
   (use-local-map gdb-registers-mode-map)
   (run-mode-hooks 'gdb-registers-mode-hook)
@@ -2617,29 +2725,27 @@ another GDB command e.g pwd, to see new frames")
 (defvar gdb-memory-mode-map
   (let ((map (make-sparse-keymap)))
     (suppress-keymap map)
+    (define-key map "S" 'gdb-memory-set-address)
+    (define-key map "N" 'gdb-memory-set-repeat-count)
     (define-key map "q" 'kill-this-buffer)
      map))
 
-(defun gdb-memory-set-address (event)
+(defun gdb-memory-set-address (&optional event)
   "Set the start memory address."
-  (interactive "e")
-  (save-selected-window
-    (select-window (posn-window (event-start event)))
-    (let ((arg (read-from-minibuffer "Memory address: ")))
-      (setq gdb-memory-address arg))
-    (gdb-invalidate-memory)))
+  (interactive)
+  (let ((arg (read-from-minibuffer "Start address: ")))
+    (setq gdb-memory-address arg))
+    (gdb-invalidate-memory))
 
-(defun gdb-memory-set-repeat-count (event)
+(defun gdb-memory-set-repeat-count (&optional event)
   "Set the number of data items in memory window."
-  (interactive "e")
-  (save-selected-window
-    (select-window (posn-window (event-start event)))
-    (let* ((arg (read-from-minibuffer "Repeat count: "))
-         (count (string-to-number arg)))
-      (if (<= count 0)
-         (error "Positive numbers only")
-       (customize-set-variable 'gdb-memory-repeat-count count)
-       (gdb-invalidate-memory)))))
+  (interactive)
+  (let* ((arg (read-from-minibuffer "Repeat count: "))
+        (count (string-to-number arg)))
+    (if (<= count 0)
+       (error "Positive numbers only")
+      (customize-set-variable 'gdb-memory-repeat-count count)
+      (gdb-invalidate-memory))))
 
 (defun gdb-memory-format-binary ()
   "Set the display format to binary."
@@ -2768,16 +2874,6 @@ another GDB command e.g pwd, to see new frames")
                                               (vector (car selection))))))
       (if binding (call-interactively binding)))))
 
-;;from make-mode-line-mouse-map
-(defun gdb-make-header-line-mouse-map (mouse function) "\
-Return a keymap with single entry for mouse key MOUSE on the header line.
-MOUSE is defined to run function FUNCTION with no args in the buffer
-corresponding to the mode line clicked."
-  (let ((map (make-sparse-keymap)))
-    (define-key map (vector 'header-line mouse) function)
-    (define-key map (vector 'header-line 'down-mouse-1) 'ignore)
-    map))
-
 (defvar gdb-memory-font-lock-keywords
   '(;; <__function.name+n>
     ("<\\(\\(\\sw\\|[_.]\\)+\\)\\(\\+[0-9]+\\)?>" (1 font-lock-function-name-face))
@@ -2792,11 +2888,12 @@ corresponding to the mode line clicked."
   (setq major-mode 'gdb-memory-mode)
   (setq mode-name "Memory")
   (setq buffer-read-only t)
+  (buffer-disable-undo)
   (use-local-map gdb-memory-mode-map)
   (setq header-line-format
        '(:eval
          (concat
-          "Read address["
+          "Start address["
           (propertize
            "-"
            'face font-lock-warning-face
@@ -2830,7 +2927,7 @@ corresponding to the mode line clicked."
           "]: "
           (propertize gdb-memory-address
                       'face font-lock-warning-face
-                      'help-echo "mouse-1: set memory address"
+                      'help-echo "mouse-1: set start address"
                       'mouse-face 'mode-line-highlight
                       'local-map (gdb-make-header-line-mouse-map
                                   'mouse-1
@@ -2925,13 +3022,14 @@ corresponding to the mode line clicked."
   (let ((buf (gdb-get-buffer 'gdb-partial-output-buffer)))
     (with-current-buffer buf
       (goto-char (point-min))
+      ;; Need this in case "set print pretty" is on.
       (while (re-search-forward "^[ }].*\n" nil t)
        (replace-match "" nil nil))
       (goto-char (point-min))
       (while (re-search-forward "{\\(.*=.*\n\\|\n\\)" nil t)
        (replace-match gdb-struct-string nil nil))
       (goto-char (point-min))
-      (while (re-search-forward "\\s-*{.*\n" nil t)
+      (while (re-search-forward "\\s-*{[^.].*\n" nil t)
        (replace-match gdb-array-string nil nil))))
   (let ((buf (gdb-get-buffer 'gdb-locals-buffer)))
     (and buf
@@ -2944,8 +3042,7 @@ corresponding to the mode line clicked."
                 (insert-buffer-substring (gdb-get-buffer-create
                                           'gdb-partial-output-buffer))
                (set-window-start window start)
-               (set-window-point window p))
-)))
+               (set-window-point window p)))))
   (run-hooks 'gdb-info-locals-hook))
 
 (defvar gdb-locals-mode-map
@@ -2961,9 +3058,11 @@ corresponding to the mode line clicked."
   (kill-all-local-variables)
   (setq major-mode 'gdb-locals-mode)
   (setq mode-name (concat "Locals:" gdb-selected-frame))
+  (use-local-map gdb-locals-mode-map)
   (setq buffer-read-only t)
+  (buffer-disable-undo)
+  (setq header-line-format gdb-locals-header)
   (gdb-thread-identification)
-  (use-local-map gdb-locals-mode-map)
   (set (make-local-variable 'font-lock-defaults)
        '(gdb-locals-font-lock-keywords))
   (run-mode-hooks 'gdb-locals-mode-hook)
@@ -2991,29 +3090,21 @@ corresponding to the mode line clicked."
 \f
 
 ;;;; Window management
-(defun gdb-display-buffer (buf dedicated &optional size)
-  (let ((answer (get-buffer-window buf 0))
-       (must-split nil))
+(defun gdb-display-buffer (buf dedicated &optional frame)
+  (let ((answer (get-buffer-window buf (or frame 0))))
     (if answer
-       (display-buffer buf nil 0)      ;Deiconify the frame if necessary.
-      ;; The buffer is not yet displayed.
-      (pop-to-buffer gud-comint-buffer)        ;Select the right frame.
+       (display-buffer buf nil (or frame 0)) ;Deiconify the frame if necessary.
       (let ((window (get-lru-window)))
-       (if (and window
-                (not (memq window `(,(get-buffer-window gud-comint-buffer)
-                                    ,gdb-source-window))))
-           (progn
-             (set-window-buffer window buf)
-             (setq answer window))
-         (setq must-split t)))
-      (if must-split
-         (let* ((largest (get-largest-window))
-                (cur-size (window-height largest))
-                (new-size (and size (< size cur-size) (- cur-size size))))
-           (setq answer (split-window largest new-size))
-           (set-window-buffer answer buf)
-           (set-window-dedicated-p answer dedicated)))
-      answer)))
+       (if (memq (buffer-local-value 'gud-minor-mode (window-buffer window))
+                 '(gdba gdbmi))
+           (let* ((largest (get-largest-window))
+                  (cur-size (window-height largest)))
+             (setq answer (split-window largest))
+             (set-window-buffer answer buf)
+             (set-window-dedicated-p answer dedicated)
+             answer)
+         (set-window-buffer window buf)
+         window)))))
 
 \f
 ;;; Shared keymap initialization:
@@ -3094,7 +3185,7 @@ corresponding to the mode line clicked."
   "Display GUD buffer."
   (interactive)
   (let ((same-window-regexps nil))
-    (pop-to-buffer gud-comint-buffer)))
+    (select-window (display-buffer gud-comint-buffer nil 0))))
 
 (defun gdb-set-window-buffer (name)
   (set-window-buffer (selected-window) (get-buffer name))
@@ -3181,7 +3272,7 @@ Kills the gdb buffers, and resets variables and the source buffers."
   (remove-hook 'after-save-hook 'gdb-create-define-alist t))
 
 (defun gdb-source-info ()
-  "Find the source file where the program starts and displays it with related
+  "Find the source file where the program starts and display it with related
 buffers."
   (goto-char (point-min))
   (if (and (search-forward "Located in " nil t)
@@ -3193,7 +3284,7 @@ buffers."
   (if gdb-many-windows
       (gdb-setup-windows)
    (gdb-get-buffer-create 'gdb-breakpoints-buffer)
-   (if gdb-show-main
+   (if (and gdb-show-main gdb-main-file)
        (let ((pop-up-windows t))
         (display-buffer (gud-find-file gdb-main-file)))))
  (setq gdb-ready t))
@@ -3215,9 +3306,7 @@ Add directory to search path for source files using the GDB command, dir."))
       (throw 'file-not-found nil))
     (with-current-buffer
        (find-file-noselect (match-string 0))
-      (save-current-buffer
-       (set (make-local-variable 'gud-minor-mode) 'gdba)
-       (set (make-local-variable 'tool-bar-map) gud-tool-bar-map))
+      (gdb-init-buffer)
       ;; only want one breakpoint icon at each location
       (save-excursion
        (goto-line (string-to-number line))
@@ -3239,9 +3328,7 @@ of the current session."
                    buffer-file-name)
                  gdb-source-file-list)
          (with-current-buffer (find-buffer-visiting buffer-file-name)
-           (set (make-local-variable 'gud-minor-mode)
-                (buffer-local-value 'gud-minor-mode gud-comint-buffer))
-           (set (make-local-variable 'tool-bar-map) gud-tool-bar-map)))))
+           (gdb-init-buffer)))))
 
 ;;from put-image
 (defun gdb-put-string (putstring pos &optional dprop &rest sprops)
@@ -3413,7 +3500,7 @@ BUFFER nil or omitted means use the current buffer."
          (with-current-buffer buffer
            (save-excursion
              (goto-char (point-min))
-             (if (search-forward address nil t)
+             (if (re-search-forward (concat "^0x0*" address) nil t)
                  (gdb-put-breakpoint-icon (eq flag ?y) bptno)))))))
     (if (not (equal gdb-pc-address "main"))
        (with-current-buffer buffer
@@ -3451,6 +3538,7 @@ BUFFER nil or omitted means use the current buffer."
   (add-to-list 'overlay-arrow-variable-list 'gdb-overlay-arrow-position)
   (setq fringes-outside-margins t)
   (setq buffer-read-only t)
+  (buffer-disable-undo)
   (gdb-thread-identification)
   (use-local-map gdb-assembler-mode-map)
   (gdb-invalidate-assembler)
@@ -3487,8 +3575,9 @@ BUFFER nil or omitted means use the current buffer."
                     (string-equal gdb-selected-frame gdb-previous-frame))
          (if (or (not (member 'gdb-invalidate-assembler
                               gdb-pending-triggers))
-                 (not (string-equal gdb-pc-address
-                                    gdb-previous-frame-address)))
+                 (not (equal (string-to-number gdb-pc-address)
+                             (string-to-number
+                              gdb-previous-frame-pc-address))))
          (progn
            ;; take previous disassemble command, if any, off the queue
            (with-current-buffer gud-comint-buffer
@@ -3499,21 +3588,23 @@ BUFFER nil or omitted means use the current buffer."
                            (delete item gdb-input-queue))))))
            (gdb-enqueue-input
             (list
-             (concat gdb-server-prefix "disassemble "
-                     (if (member gdb-pc-address '(nil "main")) nil "0x")
-                          gdb-pc-address "\n")
+             (concat gdb-server-prefix "disassemble " gdb-pc-address "\n")
                   'gdb-assembler-handler))
            (push 'gdb-invalidate-assembler gdb-pending-triggers)
-           (setq gdb-previous-frame-address gdb-pc-address)
+           (setq gdb-previous-frame-pc-address gdb-pc-address)
            (setq gdb-previous-frame gdb-selected-frame)))))))
 
 (defun gdb-get-selected-frame ()
   (if (not (member 'gdb-get-selected-frame gdb-pending-triggers))
       (progn
-       (gdb-enqueue-input
-        (list (concat gdb-server-prefix "info frame\n") 'gdb-frame-handler))
-       (push 'gdb-get-selected-frame
-              gdb-pending-triggers))))
+       (if (string-equal gdb-version "pre-6.4")
+           (gdb-enqueue-input
+            (list (concat gdb-server-prefix "info frame\n")
+                  'gdb-frame-handler))
+         (gdb-enqueue-input
+           (list "server interpreter mi -stack-info-frame\n"
+                 'gdb-frame-handler-1)))
+       (push 'gdb-get-selected-frame gdb-pending-triggers))))
 
 (defun gdb-frame-handler ()
   (setq gdb-pending-triggers
@@ -3524,7 +3615,7 @@ BUFFER nil or omitted means use the current buffer."
     (setq gdb-frame-number (match-string 1))
     (setq gdb-frame-address (match-string 2)))
   (goto-char (point-min))
-  (when (re-search-forward ".*=\\s-+0x0*\\(\\S-*\\)\\s-+in\\s-+\\(.*?\\)\
+  (when (re-search-forward ".*=\\s-+\\(\\S-*\\)\\s-+in\\s-+\\(.*?\\)\
 \\(?: (\\(\\S-+?\\):[0-9]+?)\\)*; "
      nil t)
     (setq gdb-selected-frame (match-string 2))
@@ -3567,16 +3658,45 @@ is set in them."
   (dolist (buffer (buffer-list))
     (with-current-buffer buffer
       (when (member buffer-file-name gdb-source-file-list)
-       (set (make-local-variable 'gud-minor-mode)
-            (buffer-local-value 'gud-minor-mode gud-comint-buffer))
-       (set (make-local-variable 'tool-bar-map) gud-tool-bar-map)
-       (when gud-tooltip-mode
-         (make-local-variable 'gdb-define-alist)
-         (gdb-create-define-alist)
-         (add-hook 'after-save-hook 'gdb-create-define-alist nil t)))))
+       (gdb-init-buffer))))
   (gdb-force-mode-line-update
    (propertize "ready" 'face font-lock-variable-name-face)))
 
+;; Used for -stack-info-frame but could be used for -stack-list-frames too.
+(defconst gdb-stack-list-frames-regexp
+".*?level=\"\\(.*?\\)\".*?,addr=\"\\(.*?\\)\".*?,func=\"\\(.*?\\)\",\
+\\(?:.*?file=\".*?\".*?,fullname=\"\\(.*?\\)\".*?,line=\"\\(.*?\\)\".*?}\\|\
+from=\"\\(.*?\\)\"\\)")
+
+(defun gdb-frame-handler-1 ()
+  (setq gdb-pending-triggers
+       (delq 'gdb-get-selected-frame gdb-pending-triggers))
+  (goto-char (point-min))
+    (when (re-search-forward gdb-stack-list-frames-regexp nil t)
+      (setq gdb-frame-number (match-string 1))
+      (setq gdb-pc-address (match-string 2))
+      (setq gdb-selected-frame (match-string 3))
+      (if (gdb-get-buffer 'gdb-locals-buffer)
+         (with-current-buffer (gdb-get-buffer 'gdb-locals-buffer)
+           (setq mode-name (concat "Locals:" gdb-selected-frame))))
+      (if (gdb-get-buffer 'gdb-assembler-buffer)
+         (with-current-buffer (gdb-get-buffer 'gdb-assembler-buffer)
+           (setq mode-name (concat "Machine:" gdb-selected-frame)))))
+    (if (and (match-string 4) (match-string 5) gud-overlay-arrow-position)
+       (let ((buffer (marker-buffer gud-overlay-arrow-position))
+             (position (marker-position gud-overlay-arrow-position)))
+         (when (and buffer
+                    (string-equal (file-name-nondirectory
+                                   (buffer-file-name buffer))
+                                  (file-name-nondirectory (match-string 4))))
+           (with-current-buffer buffer
+             (setq fringe-indicator-alist
+                   (if (string-equal gdb-frame-number "0")
+                       nil
+                     '((overlay-arrow . hollow-right-triangle))))
+             (set-marker gud-overlay-arrow-position position)))))
+  (gdb-invalidate-assembler))
+
 ; Uses "-var-list-children --all-values".  Needs GDB 6.4 onwards.
 (defun gdb-var-list-children-1 (varnum)
   (gdb-enqueue-input
@@ -3588,9 +3708,9 @@ is set in them."
     `(lambda () (gdb-var-list-children-handler-1 ,varnum)))))
 
 (defconst gdb-var-list-children-regexp-1
-  "child={.*?name=\"\\(.+?\\)\",.*?exp=\"\\(.+?\\)\",.*?\
-numchild=\"\\(.+?\\)\",.*?value=\\(\".*?\"\\)\
-\\(}\\|,.*?\\(type=\"\\(.+?\\)\"\\)?.*?}\\)")
+  "child={.*?name=\"\\(.+?\\)\".*?,exp=\"\\(.+?\\)\".*?,\
+numchild=\"\\(.+?\\)\".*?,value=\\(\".*?\"\\)\
+\\(}\\|.*?,\\(type=\"\\(.+?\\)\"\\)?.*?}\\)")
 
 (defun gdb-var-list-children-handler-1 (varnum)
   (goto-char (point-min))
@@ -3627,7 +3747,7 @@ numchild=\"\\(.+?\\)\",.*?value=\\(\".*?\"\\)\
        (push 'gdb-var-update gdb-pending-triggers))))
 
 (defconst gdb-var-update-regexp-1
-  "{.*?name=\"\\(.*?\\)\",.*?\\(?:value=\\(\".*?\"\\),\\)?.*?\
+  "{.*?name=\"\\(.*?\\)\".*?,\\(?:value=\\(\".*?\"\\),\\)?.*?\
 in_scope=\"\\(.*?\\)\".*?}")
 
 (defun gdb-var-update-handler-1 ()
@@ -3667,7 +3787,7 @@ in_scope=\"\\(.*?\\)\".*?}")
     gdb-data-list-register-values-handler)
 
 (defconst gdb-data-list-register-values-regexp
-  "{.*?number=\"\\(.*?\\)\",.*?value=\"\\(.*?\\)\".*?}")
+  "{.*?number=\"\\(.*?\\)\".*?,value=\"\\(.*?\\)\".*?}")
 
 (defun gdb-data-list-register-values-handler ()
   (setq gdb-pending-triggers (delq 'gdb-invalidate-registers-1
@@ -3762,7 +3882,7 @@ in_scope=\"\\(.*?\\)\".*?}")
   gdb-stack-list-locals-handler)
 
 (defconst gdb-stack-list-locals-regexp
-  "{.*?name=\"\\(.*?\\)\",.*?type=\"\\(.*?\\)\"")
+  "{.*?name=\"\\(.*?\\)\".*?,type=\"\\(.*?\\)\"")
 
 (defvar gdb-locals-watch-map-1
   (let ((map (make-sparse-keymap)))
@@ -3789,7 +3909,7 @@ in_scope=\"\\(.*?\\)\".*?}")
     (let* ((var (current-word))
           (value (read-string (format "New value (%s): " var))))
       (gdb-enqueue-input
-       (list (concat  gdb-server-prefix"set variable " var " = " value "\n")
+       (list (concat  gdb-server-prefix "set variable " var " = " value "\n")
             'ignore)))))
 
 ;; Dont display values of arrays or structures.