;;; 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:
;; 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:
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
(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
"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
(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
(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
(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)
(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")
(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))
(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.
(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
;; 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))
"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)