]> code.delx.au - gnu-emacs/blobdiff - lisp/progmodes/gdb-mi.el
2012-01-05 Michael R. Mauger <mmaug@yahoo.com>
[gnu-emacs] / lisp / progmodes / gdb-mi.el
index 87209a78ffbdef94494cf86e9598a569534801e2..1c38c59bba633fa67fa554379f42c93e2cc85a1a 100644 (file)
@@ -25,7 +25,7 @@
 
 ;;; Credits:
 
-;; This file was written by by Nick Roberts following the general design
+;; This file was written by Nick Roberts following the general design
 ;; used in gdb-ui.el for Emacs 22.1 - 23.1.  It is currently being developed
 ;; by Dmitry Dzhus <dima@sphinx.net.ru> as part of the Google Summer
 ;; of Code 2009 Project "Emacs GDB/MI migration".
 
 ;; M-x gdb will start the debugger.
 
-;; This file uses GDB/MI as the primary interface to GDB.  It is still under
-;; development and is part of a process to migrate Emacs from annotations (as
-;; used in gdb-ui.el) to GDB/MI.  It runs gdb with GDB/MI (-interp=mi) and
-;; access CLI using "-interpreter-exec console cli-command".  This code works
-;; without gdb-ui.el and uses MI tokens instead of queues. Eventually MI
-;; should be asynchronous.
-
-;; This mode will PARTLY WORK WITH RECENT GDB RELEASES (status in modeline
-;; doesn't update properly when execution commands are issued from GUD buffer)
-;; and WORKS BEST when GDB runs asynchronously: maint set linux-async on.
-;;
-;; You need development version of GDB 7.0 for the thread buffer to work.
-
-;; This file replaces gdb-ui.el and is for development with GDB.  Use the
-;; release branch of Emacs 22 for the latest version of gdb-ui.el.
+;; This file uses GDB/MI as the primary interface to GDB.  It runs gdb with
+;; GDB/MI (-interp=mi) and access CLI using "-interpreter-exec console
+;; cli-command".  This code works without gdb-ui.el and uses MI tokens instead
+;; of queues.  Eventually MI should be asynchronous.
 
 ;; Windows Platforms:
 
@@ -85,7 +74,7 @@
 ;; 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 Aug 2009)
-;; as earlier versions don not compile on Mac OSX.
+;; as earlier versions do not compile on Mac OSX.
 
 ;;; Known Bugs:
 
@@ -225,7 +214,7 @@ Emacs can't find.")
 (defvar gdb-source-window nil)
 (defvar gdb-inferior-status nil)
 (defvar gdb-continuation nil)
-(defvar gdb-version nil)
+(defvar gdb-supports-non-stop nil)
 (defvar gdb-filter-output nil
   "Message to be shown in GUD console.
 
@@ -361,7 +350,7 @@ automatically.
 
 This setting is used in non-stop mode only. In all-stop mode,
 Emacs always switches to the thread which caused the stop."
-  ;; exited, exited-normally and exited-signalled are not
+  ;; exited, exited-normally and exited-signaled are not
   ;; thread-specific stop reasons and therefore are not included in
   ;; this list
   :type '(choice
@@ -585,7 +574,7 @@ When `gdb-non-stop' is nil, return COMMAND unchanged."
   (if gdb-non-stop
       (if (and gdb-gud-control-all-threads
                (not noall)
-              (string-equal gdb-version "7.0+"))
+              gdb-supports-non-stop)
           (concat command " --all ")
         (gdb-current-context-command command))
     command))
@@ -599,12 +588,34 @@ NOARG must be t when this macro is used outside `gud-def'"
     (concat (gdb-gud-context-command ,cmd1 ,noall) " " ,cmd2)
     ,(when (not noarg) 'arg)))
 
+(defun gdb--check-interpreter (proc string)
+  (unless (zerop (length string))
+    (let ((filter (process-get proc 'gud-normal-filter)))
+      (set-process-filter proc filter)
+      (unless (memq (aref string 0) '(?^ ?~ ?@ ?& ?* ?=))
+        ;; Apparently we're not running with -i=mi.
+        (let ((msg "Error: you did not specify -i=mi on GDB's command line!"))
+          (message msg)
+          (setq string (concat (propertize msg 'font-lock-face 'error)
+                               "\n" string)))
+        ;; Use the old gud-gbd filter, not because it works, but because it
+        ;; will properly display GDB's answers rather than hanging waiting for
+        ;; answers that aren't coming.
+        (set (make-local-variable 'gud-marker-filter) #'gud-gdb-marker-filter))
+      (funcall filter proc string))))
+
 ;;;###autoload
 (defun gdb (command-line)
   "Run gdb on program FILE in buffer *gud-FILE*.
 The directory containing FILE becomes the initial working directory
 and source-file directory for your debugger.
 
+COMMAND-LINE is the shell command for starting the gdb session.
+It should be a string consisting of the name of the gdb
+executable followed by command-line options.  The command-line
+options should include \"-i=mi\" to use gdb's MI text interface.
+Note that the old \"--annotate\" option is no longer supported.
+
 If `gdb-many-windows' is nil (the default value) then gdb just
 pops up the GUD buffer unless `gdb-show-main' is t.  In this case
 it starts with two windows: one displaying the GUD buffer and the
@@ -659,6 +670,13 @@ detailed description of this mode.
      "Multiple debugging requires restarting in text command mode"))
   ;;
   (gud-common-init command-line nil 'gud-gdbmi-marker-filter)
+
+  ;; Setup a temporary process filter to warn when GDB was not started
+  ;; with -i=mi.
+  (let ((proc (get-buffer-process gud-comint-buffer)))
+    (process-put proc 'gud-normal-filter (process-filter proc))
+    (set-process-filter proc #'gdb--check-interpreter))
+
   (set (make-local-variable 'gud-minor-mode) 'gdbmi)
   (setq comint-input-sender 'gdb-send)
   (when (ring-empty-p comint-input-ring) ; cf shell-mode
@@ -793,6 +811,9 @@ detailed description of this mode.
   (define-key gud-minor-mode-map [left-margin C-mouse-3]
     'gdb-mouse-jump)
 
+  (set (make-local-variable 'gud-gdb-completion-function)
+       'gud-gdbmi-completions)
+
   (add-hook 'completion-at-point-functions #'gud-gdb-completion-at-point
             nil 'local)
   (local-set-key "\C-i" 'completion-at-point)
@@ -805,7 +826,7 @@ detailed description of this mode.
   (run-hooks 'gdb-mode-hook))
 
 (defun gdb-init-1 ()
-  ;; (re-)initialise
+  ;; (re-)initialize
   (setq gdb-selected-frame nil
        gdb-frame-number nil
         gdb-thread-number nil
@@ -841,29 +862,28 @@ detailed description of this mode.
   (set-process-filter (get-process "gdb-inferior") 'gdb-inferior-filter)
   (gdb-input
    ;; Needs GDB 6.4 onwards
-   (list (concat "-inferior-tty-set "
-                (or
-                 ;; The process can run on a remote host.
-                 (process-get (get-process "gdb-inferior") 'remote-tty)
-                 (process-tty-name (get-process "gdb-inferior"))))
-        'ignore))
+   (concat "-inferior-tty-set "
+          (or
+           ;; The process can run on a remote host.
+           (process-get (get-process "gdb-inferior") 'remote-tty)
+           (process-tty-name (get-process "gdb-inferior"))))
+   'ignore)
   (if (eq window-system 'w32)
-      (gdb-input (list "-gdb-set new-console off" 'ignore)))
-  (gdb-input (list "-gdb-set height 0" 'ignore))
+      (gdb-input "-gdb-set new-console off" 'ignore))
+  (gdb-input "-gdb-set height 0" 'ignore)
 
   (when gdb-non-stop
-    (gdb-input (list "-gdb-set non-stop 1" 'gdb-non-stop-handler)))
+    (gdb-input "-gdb-set non-stop 1" 'gdb-non-stop-handler))
+
+  (gdb-input "-enable-pretty-printing" 'ignore)
 
   ;; find source file and compilation directory here
-  (gdb-input
-                                        ; Needs GDB 6.2 onwards.
-   (list "-file-list-exec-source-files" 'gdb-get-source-file-list))
   (if gdb-create-source-file-list
-      (gdb-input
-                                        ; Needs GDB 6.0 onwards.
-       (list "-file-list-exec-source-file" 'gdb-get-source-file)))
-  (gdb-input
-   (list "-gdb-show prompt" 'gdb-get-prompt)))
+      ;; Needs GDB 6.2 onwards.
+      (gdb-input "-file-list-exec-source-files" 'gdb-get-source-file-list))
+  ;; Needs GDB 6.0 onwards.
+  (gdb-input "-file-list-exec-source-file" 'gdb-get-source-file)
+  (gdb-input "-gdb-show prompt" 'gdb-get-prompt))
 
 (defun gdb-non-stop-handler ()
   (goto-char (point-min))
@@ -872,10 +892,18 @@ detailed description of this mode.
        (message
          "This version of GDB doesn't support non-stop mode.  Turning it off.")
        (setq gdb-non-stop nil)
-       (setq gdb-version "pre-7.0"))
-    (setq gdb-version "7.0+")
-    (gdb-input (list "-gdb-set target-async 1" 'ignore))
-    (gdb-input (list "-enable-pretty-printing" 'ignore))))
+       (setq gdb-supports-non-stop nil))
+    (setq gdb-supports-non-stop t)
+    (gdb-input "-gdb-set target-async 1" 'ignore)
+    (gdb-input "-list-target-features" 'gdb-check-target-async)))
+
+(defun gdb-check-target-async ()
+  (goto-char (point-min))
+  (unless (re-search-forward "async" nil t)
+    (message
+     "Target doesn't support non-stop mode.  Turning it off.")
+    (setq gdb-non-stop nil)
+    (gdb-input "-gdb-set non-stop 0" 'ignore)))
 
 (defvar gdb-define-alist nil "Alist of #define directives for GUD tooltips.")
 
@@ -920,9 +948,8 @@ detailed description of this mode.
     (goto-char (point-min))
     (if (search-forward "expands to: " nil t)
        (unless (looking-at "\\S-+.*(.*).*")
-         (gdb-input
-          (list  (concat "-data-evaluate-expression " expr)
-                 `(lambda () (gdb-tooltip-print ,expr))))))))
+         (gdb-input (concat "-data-evaluate-expression " expr)
+                    `(lambda () (gdb-tooltip-print ,expr)))))))
 
 (defun gdb-init-buffer ()
   (set (make-local-variable 'gud-minor-mode) 'gdbmi)
@@ -1052,9 +1079,8 @@ With arg, enter name of variable to be watched in the minibuffer."
                       (concat (if (derived-mode-p 'gdb-registers-mode) "$")
                               (tooltip-identifier-from-point (point)))))))
              (set-text-properties 0 (length expr) nil expr)
-             (gdb-input
-              (list (concat"-var-create - * "  expr "")
-                    `(lambda () (gdb-var-create-handler ,expr)))))))
+             (gdb-input (concat "-var-create - * "  expr "")
+                        `(lambda () (gdb-var-create-handler ,expr))))))
       (message "gud-watch is a no-op in this mode."))))
 
 (defun gdb-var-create-handler (expr)
@@ -1083,7 +1109,7 @@ With arg, enter name of variable to be watched in the minibuffer."
   (when (and (boundp 'speedbar-frame) (frame-live-p speedbar-frame)
             (not (gdb-pending-p 'gdb-speedbar-timer)))
     ;; Dummy command to update speedbar even when idle.
-    (gdb-input (list "-environment-pwd" 'gdb-speedbar-timer-fn))
+    (gdb-input "-environment-pwd" 'gdb-speedbar-timer-fn)
     ;; Keep gdb-pending-triggers non-nil till end.
     (gdb-add-pending 'gdb-speedbar-timer)))
 
@@ -1104,12 +1130,9 @@ With arg, enter name of variable to be watched in the minibuffer."
 
                                         ; Uses "-var-list-children --all-values".  Needs GDB 6.1 onwards.
 (defun gdb-var-list-children (varnum)
-  (gdb-input
-   (list (concat "-var-update " varnum) 'ignore))
-  (gdb-input
-   (list (concat "-var-list-children --all-values "
-                 varnum)
-         `(lambda () (gdb-var-list-children-handler ,varnum)))))
+  (gdb-input (concat "-var-update " varnum) 'ignore)
+  (gdb-input (concat "-var-list-children --all-values " varnum)
+            `(lambda () (gdb-var-list-children-handler ,varnum))))
 
 (defun gdb-var-list-children-handler (varnum)
   (let* ((var-list nil)
@@ -1141,13 +1164,11 @@ With arg, enter name of variable to be watched in the minibuffer."
   "Set the output format for a variable displayed in the speedbar."
   (let* ((var (nth (- (count-lines (point-min) (point)) 2) gdb-var-list))
         (varnum (car var)))
-    (gdb-input
-     (list (concat "-var-set-format " varnum " " format) 'ignore))
+    (gdb-input (concat "-var-set-format " varnum " " format) 'ignore)
     (gdb-var-update)))
 
 (defun gdb-var-delete-1 (var varnum)
-  (gdb-input
-   (list (concat "-var-delete " varnum) 'ignore))
+  (gdb-input (concat "-var-delete " varnum) 'ignore)
   (setq gdb-var-list (delq var gdb-var-list))
   (dolist (varchild gdb-var-list)
     (if (string-match (concat (car var) "\\.") (car varchild))
@@ -1166,17 +1187,15 @@ With arg, enter name of variable to be watched in the minibuffer."
 
 (defun gdb-var-delete-children (varnum)
   "Delete children of variable object at point from the speedbar."
-  (gdb-input
-   (list (concat "-var-delete -c " varnum) 'ignore)))
+  (gdb-input (concat "-var-delete -c " varnum) 'ignore))
 
 (defun gdb-edit-value (_text _token _indent)
   "Assign a value to a variable displayed in the speedbar."
   (let* ((var (nth (- (count-lines (point-min) (point)) 2) gdb-var-list))
         (varnum (car var)) (value))
     (setq value (read-string "New value: "))
-    (gdb-input
-     (list (concat "-var-assign " varnum " " value)
-          `(lambda () (gdb-edit-value-handler ,value))))))
+    (gdb-input (concat "-var-assign " varnum " " value)
+              `(lambda () (gdb-edit-value-handler ,value)))))
 
 (defconst gdb-error-regexp "\\^error,msg=\\(\".+\"\\)")
 
@@ -1188,8 +1207,7 @@ With arg, enter name of variable to be watched in the minibuffer."
                                         ; Uses "-var-update --all-values".  Needs GDB 6.4 onwards.
 (defun gdb-var-update ()
   (if (not (gdb-pending-p 'gdb-var-update))
-      (gdb-input
-       (list "-var-update --all-values *" 'gdb-var-update-handler)))
+      (gdb-input "-var-update --all-values *" 'gdb-var-update-handler))
   (gdb-add-pending 'gdb-var-update))
 
 (defun gdb-var-update-handler ()
@@ -1669,19 +1687,23 @@ static char *magick[] = {
                                        gdb-continuation string "\"\n"))
       (setq gdb-continuation nil))))
 
-(defun gdb-input (item)
-  (if gdb-enable-debug (push (cons 'send-item item) gdb-debug-log))
+(defun gdb-input (command handler-function)
+  "Send COMMAND to GDB via the MI interface.
+Run the function HANDLER-FUNCTION, with no arguments, once the command is
+complete."
+  (if gdb-enable-debug (push (list 'send-item command handler-function)
+                            gdb-debug-log))
   (setq gdb-token-number (1+ gdb-token-number))
-  (setcar item (concat (number-to-string gdb-token-number) (car item)))
-  (push (cons gdb-token-number (car (cdr item))) gdb-handler-alist)
+  (setq command (concat (number-to-string gdb-token-number) command))
+  (push (cons gdb-token-number handler-function) gdb-handler-alist)
   (process-send-string (get-buffer-process gud-comint-buffer)
-                      (concat (car item) "\n")))
+                      (concat command "\n")))
 
 ;; NOFRAME is used for gud execution control commands
 (defun gdb-current-context-command (command)
   "Add --thread to gdb COMMAND when needed."
   (if (and gdb-thread-number
-          (string-equal gdb-version "7.0+"))
+          gdb-supports-non-stop)
       (concat command " --thread " gdb-thread-number)
     command))
 
@@ -1862,15 +1884,16 @@ is running."
       (let ((record-type (cadr output-record))
            (arg1 (nth 2 output-record))
            (arg2 (nth 3 output-record)))
-       (if (eq record-type 'gdb-error)
-           (gdb-done-or-error arg2 arg1 'error)
-         (if (eq record-type 'gdb-done)
-             (gdb-done-or-error arg2 arg1 'done)
-           ;; Suppress "No registers." since GDB 6.8 and earlier duplicates MI
-           ;; error message on internal stream.  Don't print to GUD buffer.
-           (unless (and (eq record-type 'gdb-internals)
-                         (string-equal (read arg1) "No registers.\n"))
-             (funcall record-type arg1))))))
+       (cond ((eq record-type 'gdb-error)
+              (gdb-done-or-error arg2 arg1 'error))
+             ((eq record-type 'gdb-done)
+              (gdb-done-or-error arg2 arg1 'done))
+             ;; Suppress "No registers."  GDB 6.8 and earlier
+             ;; duplicates MI error message on internal stream.
+             ;; Don't print to GUD buffer.
+             ((not (and (eq record-type 'gdb-internals)
+                        (string-equal (read arg1) "No registers.\n")))
+              (funcall record-type arg1)))))
 
     (setq gdb-output-sink 'user)
     ;; Remove padding.
@@ -1947,7 +1970,7 @@ Sets `gdb-thread-number' to new id."
   (setq gud-running t)
   ;; GDB doesn't seem to respond to -thread-info before first stop or
   ;; thread exit (even in non-stop mode), so this is useless.
-  ;; Behaviour may change in the future.
+  ;; Behavior may change in the future.
   (gdb-emit-signal gdb-buf-publisher 'update-threads))
 
 ;; -break-insert -t didn't give a reason before gdb 6.9
@@ -1963,11 +1986,10 @@ current thread and update GDB buffers."
     ;; -data-list-register-names needs to be issued for any stopped
     ;; thread
     (when (not gdb-register-names)
-      (gdb-input
-       (list (concat "-data-list-register-names"
-                    (if (string-equal gdb-version "7.0+")
-                        (concat" --thread " thread-id)))
-             'gdb-register-names-handler)))
+      (gdb-input (concat "-data-list-register-names"
+                        (if gdb-supports-non-stop
+                            (concat " --thread " thread-id)))
+                'gdb-register-names-handler))
 
 ;;; Don't set gud-last-frame here as it's currently done in gdb-frame-handler
 ;;; because synchronous GDB doesn't give these fields with CLI.
@@ -2034,9 +2056,7 @@ current thread and update GDB buffers."
 ;; (frontend MI commands should not print to this stream)
 (defun gdb-console (output-field)
   (setq gdb-filter-output
-       (gdb-concat-output
-        gdb-filter-output
-        (read output-field))))
+       (gdb-concat-output gdb-filter-output (read output-field))))
 
 (defun gdb-done-or-error (output-field token-number type)
   (if (string-equal token-number "")
@@ -2074,12 +2094,11 @@ current thread and update GDB buffers."
              (assq-delete-all token-number gdb-handler-alist)))))
 
 (defun gdb-concat-output (so-far new)
-  (let ((sink gdb-output-sink))
-    (cond
-     ((eq sink 'user) (concat so-far new))
-     ((eq sink 'emacs)
-      (gdb-append-to-partial-output new)
-      so-far))))
+  (cond
+   ((eq gdb-output-sink 'user) (concat so-far new))
+   ((eq gdb-output-sink 'emacs)
+    (gdb-append-to-partial-output new)
+    so-far)))
 
 (defun gdb-append-to-partial-output (string)
   (with-current-buffer (gdb-get-buffer-create 'gdb-partial-output-buffer)
@@ -2199,7 +2218,7 @@ Return position where LINE begins."
 (defun gdb-mapcar* (function &rest seqs)
   "Apply FUNCTION to each element of SEQS, and make a list of the results.
 If there are several SEQS, FUNCTION is called with that many
-arugments, and mapping stops as sson as the shortest list runs
+arguments, and mapping stops as soon as the shortest list runs
 out."
   (let ((shortest (apply #'min (mapcar #'length seqs))))
     (mapcar (lambda (i)
@@ -2289,9 +2308,8 @@ trigger argument when describing buffer types with
              (memq signal ,signal-list))
        (when (not (gdb-pending-p
                    (cons (current-buffer) ',trigger-name)))
-         (gdb-input
-          (list ,gdb-command
-                (gdb-bind-function-to-buffer ',handler-name (current-buffer))))
+         (gdb-input ,gdb-command
+                   (gdb-bind-function-to-buffer ',handler-name (current-buffer)))
          (gdb-add-pending (cons (current-buffer) ',trigger-name))))))
 
 ;; Used by disassembly buffer only, the rest use
@@ -2418,13 +2436,10 @@ HANDLER-NAME handler uses customization of CUSTOM-DEFUN. See
                 ;; Only want one breakpoint icon at each location.
                 (gdb-put-breakpoint-icon (string-equal flag "y") bptno
                                          (string-to-number line)))
-            (gdb-input
-             (list (concat "list " file ":1")
-                   'ignore))
-            (gdb-input
-             (list "-file-list-exec-source-file"
-                   `(lambda () (gdb-get-location
-                           ,bptno ,line ,flag))))))))))
+            (gdb-input (concat "list " file ":1") 'ignore)
+            (gdb-input "-file-list-exec-source-file"
+                      `(lambda () (gdb-get-location
+                                   ,bptno ,line ,flag)))))))))
 
 (defvar gdb-source-file-regexp "fullname=\"\\(.*?\\)\"")
 
@@ -2754,7 +2769,7 @@ on the current line."
 (def-gdb-thread-buffer-command gdb-select-thread
   (let ((new-id (bindat-get-field thread 'id)))
     (gdb-setq-thread-number new-id)
-    (gdb-input (list (concat "-thread-select " new-id) 'ignore))
+    (gdb-input (concat "-thread-select " new-id) 'ignore)
     (gdb-update))
   "Select the thread at current line of threads buffer.")
 
@@ -3410,7 +3425,7 @@ breakpoints buffer."
         (error "Not recognized as break/watchpoint line")))))
 
 \f
-;; Frames buffer.  This displays a perpetually correct bactrack trace.
+;; Frames buffer.  This displays a perpetually correct backtrack trace.
 ;;
 (def-gdb-trigger-and-handler
   gdb-invalidate-frames (gdb-current-context-command "-stack-list-frames")
@@ -3510,8 +3525,8 @@ member."
         (if (gdb-buffer-shows-main-thread-p)
             (let ((new-level (bindat-get-field frame 'level)))
               (setq gdb-frame-number new-level)
-              (gdb-input (list (concat "-stack-select-frame " new-level)
-                               'ignore))
+              (gdb-input (concat "-stack-select-frame " new-level)
+                        'ignore)
               (gdb-update))
           (error "Could not select frame for non-current thread"))
       (error "Not recognized as frame line"))))
@@ -3560,7 +3575,7 @@ member."
       (gud-basic-call
        (concat  "-gdb-set variable " var " = " value)))))
 
-;; Dont display values of arrays or structures.
+;; Don't display values of arrays or structures.
 ;; These can be expanded using gud-watch.
 (defun gdb-locals-handler-custom ()
   (let ((locals-list (bindat-get-field (gdb-json-partial-output) 'locals))
@@ -3739,14 +3754,11 @@ member."
 
 ;; Needs GDB 6.4 onwards (used to fail with no stack).
 (defun gdb-get-changed-registers ()
-  (if (and (gdb-get-buffer 'gdb-registers-buffer)
-          (not (gdb-pending-p 'gdb-get-changed-registers)))
-      (progn
-       (gdb-input
-        (list
-         "-data-list-changed-registers"
-         'gdb-changed-registers-handler))
-       (gdb-add-pending 'gdb-get-changed-registers))))
+  (when (and (gdb-get-buffer 'gdb-registers-buffer)
+            (not (gdb-pending-p 'gdb-get-changed-registers)))
+    (gdb-input "-data-list-changed-registers"
+              'gdb-changed-registers-handler)
+    (gdb-add-pending 'gdb-get-changed-registers)))
 
 (defun gdb-changed-registers-handler ()
   (gdb-delete-pending 'gdb-get-changed-registers)
@@ -3775,18 +3787,15 @@ is set in them."
   (dolist (buffer (buffer-list))
     (with-current-buffer buffer
       (when (member buffer-file-name gdb-source-file-list)
-       (gdb-init-buffer))))
-  (gdb-force-mode-line-update
-   (propertize "ready" 'face font-lock-variable-name-face)))
+       (gdb-init-buffer)))))
 
 (defun gdb-get-main-selected-frame ()
   "Trigger for `gdb-frame-handler' which uses main current
 thread. Called from `gdb-update'."
   (if (not (gdb-pending-p 'gdb-get-main-selected-frame))
       (progn
-       (gdb-input
-        (list (gdb-current-context-command "-stack-info-frame")
-               'gdb-frame-handler))
+       (gdb-input (gdb-current-context-command "-stack-info-frame")
+                  'gdb-frame-handler)
        (gdb-add-pending 'gdb-get-main-selected-frame))))
 
 (defun gdb-frame-handler ()
@@ -3834,7 +3843,7 @@ overlay arrow in source buffer."
 If BUF is already displayed in some window, show it, deiconifying
 the frame if necessary. Otherwise, find least recently used
 window and show BUF there, if the window is not used for GDB
-already, in which case that window is splitted first."
+already, in which case that window is split first."
   (let ((answer (get-buffer-window buf (or frame 0))))
     (if answer
        (display-buffer buf nil (or frame 0)) ;Deiconify frame if necessary.
@@ -3980,18 +3989,12 @@ SPLIT-HORIZONTAL and show BUF in the new window."
 (defun gdb-frame-gdb-buffer ()
   "Display GUD buffer in a new frame."
   (interactive)
-  (let ((special-display-regexps (append special-display-regexps '(".*")))
-       (special-display-frame-alist
-        (remove '(menu-bar-lines) (remove '(tool-bar-lines)
-                                          gdb-frame-parameters)))
-       (same-window-regexps nil))
-    (display-buffer gud-comint-buffer)))
+  (display-buffer-other-frame gud-comint-buffer))
 
 (defun gdb-display-gdb-buffer ()
   "Display GUD buffer."
   (interactive)
-  (let ((same-window-regexps nil))
-    (select-window (display-buffer gud-comint-buffer nil 0))))
+  (pop-to-buffer gud-comint-buffer nil 0))
 
 (defun gdb-set-window-buffer (name &optional ignore-dedicated window)
   "Set buffer of selected window to NAME and dedicate window.
@@ -4012,11 +4015,11 @@ window is dedicated."
   (gdb-display-breakpoints-buffer)
   (delete-other-windows)
   ;; Don't dedicate.
-  (pop-to-buffer gud-comint-buffer)
+  (switch-to-buffer gud-comint-buffer)
   (let ((win0 (selected-window))
         (win1 (split-window nil ( / ( * (window-height) 3) 4)))
         (win2 (split-window nil ( / (window-height) 3)))
-        (win3 (split-window-horizontally)))
+        (win3 (split-window-right)))
     (gdb-set-window-buffer (gdb-locals-buffer-name) nil win3)
     (select-window win2)
     (set-window-buffer
@@ -4029,12 +4032,12 @@ window is dedicated."
          ;; can't find a source file.
          (list-buffers-noselect))))
     (setq gdb-source-window (selected-window))
-    (let ((win4 (split-window-horizontally)))
+    (let ((win4 (split-window-right)))
       (gdb-set-window-buffer
        (gdb-get-buffer-create 'gdb-inferior-io) nil win4))
     (select-window win1)
     (gdb-set-window-buffer (gdb-stack-buffer-name))
-    (let ((win5 (split-window-horizontally)))
+    (let ((win5 (split-window-right)))
       (gdb-set-window-buffer (if gdb-show-threads-by-default
                                  (gdb-threads-buffer-name)
                                (gdb-breakpoints-buffer-name))
@@ -4071,7 +4074,7 @@ With arg, display additional buffers iff arg is positive."
   "Restore the basic arrangement of windows used by gdb.
 This arrangement depends on the value of `gdb-many-windows'."
   (interactive)
-  (pop-to-buffer gud-comint-buffer) ;Select the right window and frame.
+  (switch-to-buffer gud-comint-buffer) ;Select the right window and frame.
   (delete-other-windows)
   (if gdb-many-windows
       (gdb-setup-windows)
@@ -4121,9 +4124,11 @@ buffers, if required."
   (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))))))
+          (display-buffer (gud-find-file gdb-main-file)))))
+  (gdb-force-mode-line-update
+   (propertize "ready" 'face font-lock-variable-name-face)))
 
 ;;from put-image
 (defun gdb-put-string (putstring pos &optional dprop &rest sprops)
@@ -4234,6 +4239,42 @@ BUFFER nil or omitted means use the current buffer."
           (set-window-margins
            window left-margin-width right-margin-width)))))
 
+\f
+;;; Functions for inline completion.
+
+(defvar gud-gdb-fetch-lines-in-progress)
+(defvar gud-gdb-fetch-lines-string)
+(defvar gud-gdb-fetch-lines-break)
+(defvar gud-gdb-fetched-lines)
+
+(defun gud-gdbmi-completions (context command)
+  "Completion table for GDB/MI commands.
+COMMAND is the prefix for which we seek completion.
+CONTEXT is the text before COMMAND on the line."
+  (let ((gud-gdb-fetch-lines-in-progress t)
+       (gud-gdb-fetch-lines-string nil)
+       (gud-gdb-fetch-lines-break (length context))
+       (gud-gdb-fetched-lines nil)
+       ;; This filter dumps output lines to `gud-gdb-fetched-lines'.
+       (gud-marker-filter #'gud-gdbmi-fetch-lines-filter)
+       complete-list)
+    (with-current-buffer (gdb-get-buffer 'gdb-partial-output-buffer)
+      (gdb-input (concat "complete " context command)
+                (lambda () (setq gud-gdb-fetch-lines-in-progress nil)))
+      (while gud-gdb-fetch-lines-in-progress
+       (accept-process-output (get-buffer-process gud-comint-buffer))))
+    (gud-gdb-completions-1 gud-gdb-fetched-lines)))
+
+(defun gud-gdbmi-fetch-lines-filter (string)
+  "Custom filter function for `gud-gdbmi-completions'."
+  (setq string (concat gud-gdb-fetch-lines-string
+                      (gud-gdbmi-marker-filter string)))
+  (while (string-match "\n" string)
+    (push (substring string gud-gdb-fetch-lines-break (match-beginning 0))
+         gud-gdb-fetched-lines)
+    (setq string (substring string (match-end 0))))
+  "")
+
 (provide 'gdb-mi)
 
 ;;; gdb-mi.el ends here