aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJean-Philippe Gravel2013-03-11 13:13:39 -0400
committerStefan Monnier2013-03-11 13:13:39 -0400
commit6ff2c8f1febc01a8c59accc340b91b51c41677cf (patch)
tree8808067592c1ebb722cae8d2fa1eca9b5dc64184
parentb388e7ad07438a3e3434b63798e3a691982e3bc4 (diff)
downloademacs-6ff2c8f1febc01a8c59accc340b91b51c41677cf.tar.gz
emacs-6ff2c8f1febc01a8c59accc340b91b51c41677cf.zip
* lisp/progmodes/gdb-mi.el: Speed up initialization. Use lexical-binding.
Fix up docstring according to conventions. (gdbmi-debug-mode): New var. (gdbmi-start-with, gdbmi-same-start, gdbmi-is-number, gdbmi-bnf-init) (gdbmi-bnf-output, gdbmi-bnf-skip-unrecognized, gdbmi-bnf-gdb-prompt) (gdbmi-bnf-result-record, gdbmi-bnf-out-of-band-record) (gdbmi-bnf-async-record, gdbmi-bnf-stream-record) (gdbmi-bnf-console-stream-output, gdbmi-bnf-target-stream-output) (gdbmi-bnf-log-stream-output, gdbmi-bnf-result-and-async-record-impl) (gdbmi-bnf-incomplete-record-result): New functions. (gdb-car<): Remove function. (gdbmi-record-list): Remove variable. (gdbmi-bnf-state, gdbmi-bnf-offset): New vars. (gdbmi-bnf-result-state-configs): New const. (gud-gdbmi-marker-filter): Rewrite. (gdb-ignored-notification, gdb-thread-created, gdb-thread-exited) (gdb-thread-selected, gdb-running, gdb-starting, gdb-stopped): Add `token' argument. (gdb-done, gdb-error): New functions. (gdb-done-or-error): Add `is-complete' argument. Change arg order. Fixes: debbugs:10580
-rw-r--r--lisp/ChangeLog23
-rw-r--r--lisp/progmodes/gdb-mi.el632
2 files changed, 488 insertions, 167 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index 1f136ca398a..483957033bd 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,26 @@
12013-03-11 Jean-Philippe Gravel <jpgravel@gmail.com>
2
3 * progmodes/gdb-mi.el: Speed up initialization (bug#10580).
4 Use lexical-binding. Fix up docstring according to conventions.
5 (gdbmi-debug-mode): New var.
6 (gdbmi-start-with, gdbmi-same-start, gdbmi-is-number, gdbmi-bnf-init)
7 (gdbmi-bnf-output, gdbmi-bnf-skip-unrecognized, gdbmi-bnf-gdb-prompt)
8 (gdbmi-bnf-result-record, gdbmi-bnf-out-of-band-record)
9 (gdbmi-bnf-async-record, gdbmi-bnf-stream-record)
10 (gdbmi-bnf-console-stream-output, gdbmi-bnf-target-stream-output)
11 (gdbmi-bnf-log-stream-output, gdbmi-bnf-result-and-async-record-impl)
12 (gdbmi-bnf-incomplete-record-result): New functions.
13 (gdb-car<): Remove function.
14 (gdbmi-record-list): Remove variable.
15 (gdbmi-bnf-state, gdbmi-bnf-offset): New vars.
16 (gdbmi-bnf-result-state-configs): New const.
17 (gud-gdbmi-marker-filter): Rewrite.
18 (gdb-ignored-notification, gdb-thread-created, gdb-thread-exited)
19 (gdb-thread-selected, gdb-running, gdb-starting, gdb-stopped):
20 Add `token' argument.
21 (gdb-done, gdb-error): New functions.
22 (gdb-done-or-error): Add `is-complete' argument. Change arg order.
23
12013-03-11 Stefan Monnier <monnier@iro.umontreal.ca> 242013-03-11 Stefan Monnier <monnier@iro.umontreal.ca>
2 25
3 * term/xterm.el (xterm--report-background-handler): Don't burp 26 * term/xterm.el (xterm--report-background-handler): Don't burp
diff --git a/lisp/progmodes/gdb-mi.el b/lisp/progmodes/gdb-mi.el
index 90c7cfc5008..8ba2822c3a3 100644
--- a/lisp/progmodes/gdb-mi.el
+++ b/lisp/progmodes/gdb-mi.el
@@ -1,4 +1,4 @@
1;;; gdb-mi.el --- User Interface for running GDB 1;;; gdb-mi.el --- User Interface for running GDB -*- lexical-binding: t -*-
2 2
3;; Copyright (C) 2007-2013 Free Software Foundation, Inc. 3;; Copyright (C) 2007-2013 Free Software Foundation, Inc.
4 4
@@ -192,8 +192,8 @@ address for root variables.")
192(defvar gdb-disassembly-position nil) 192(defvar gdb-disassembly-position nil)
193 193
194(defvar gdb-location-alist nil 194(defvar gdb-location-alist nil
195 "Alist of breakpoint numbers and full filenames. Only used for files that 195 "Alist of breakpoint numbers and full filenames.
196Emacs can't find.") 196Only used for files that Emacs can't find.")
197(defvar gdb-active-process nil 197(defvar gdb-active-process nil
198 "GUD tooltips display variable values when t, and macro definitions otherwise.") 198 "GUD tooltips display variable values when t, and macro definitions otherwise.")
199(defvar gdb-error "Non-nil when GDB is reporting an error.") 199(defvar gdb-error "Non-nil when GDB is reporting an error.")
@@ -227,9 +227,8 @@ This variable is updated in `gdb-done-or-error' and returned by
227It is initialized to `gdb-non-stop-setting' at the beginning of 227It is initialized to `gdb-non-stop-setting' at the beginning of
228every GDB session.") 228every GDB session.")
229 229
230(defvar gdb-buffer-type nil 230(defvar-local gdb-buffer-type nil
231 "One of the symbols bound in `gdb-buffer-rules'.") 231 "One of the symbols bound in `gdb-buffer-rules'.")
232(make-variable-buffer-local 'gdb-buffer-type)
233 232
234(defvar gdb-output-sink 'nil 233(defvar gdb-output-sink 'nil
235 "The disposition of the output of the current gdb command. 234 "The disposition of the output of the current gdb command.
@@ -294,9 +293,7 @@ argument (see `gdb-emit-signal')."
294 (funcall (cdr subscriber) signal))) 293 (funcall (cdr subscriber) signal)))
295 294
296(defvar gdb-buf-publisher '() 295(defvar gdb-buf-publisher '()
297 "Used to invalidate GDB buffers by emitting a signal in 296 "Used to invalidate GDB buffers by emitting a signal in `gdb-update'.
298`gdb-update'.
299
300Must be a list of pairs with cars being buffers and cdr's being 297Must be a list of pairs with cars being buffers and cdr's being
301valid signal handlers.") 298valid signal handlers.")
302 299
@@ -327,8 +324,7 @@ valid signal handlers.")
327 "When in non-stop mode, stopped threads can be examined while 324 "When in non-stop mode, stopped threads can be examined while
328other threads continue to execute. 325other threads continue to execute.
329 326
330GDB session needs to be restarted for this setting to take 327GDB session needs to be restarted for this setting to take effect."
331effect."
332 :type 'boolean 328 :type 'boolean
333 :group 'gdb-non-stop 329 :group 'gdb-non-stop
334 :version "23.2") 330 :version "23.2")
@@ -336,19 +332,18 @@ effect."
336;; TODO Some commands can't be called with --all (give a notice about 332;; TODO Some commands can't be called with --all (give a notice about
337;; it in setting doc) 333;; it in setting doc)
338(defcustom gdb-gud-control-all-threads t 334(defcustom gdb-gud-control-all-threads t
339 "When enabled, GUD execution commands affect all threads when 335 "When non-nil, GUD execution commands affect all threads when
340in non-stop mode. Otherwise, only current thread is affected." 336in non-stop mode. Otherwise, only current thread is affected."
341 :type 'boolean 337 :type 'boolean
342 :group 'gdb-non-stop 338 :group 'gdb-non-stop
343 :version "23.2") 339 :version "23.2")
344 340
345(defcustom gdb-switch-reasons t 341(defcustom gdb-switch-reasons t
346 "List of stop reasons which cause Emacs to switch to the thread 342 "List of stop reasons for which Emacs should switch thread.
347which caused the stop. When t, switch to stopped thread no matter 343When t, switch to stopped thread no matter what the reason was.
348what the reason was. When nil, never switch to stopped thread 344When nil, never switch to stopped thread automatically.
349automatically.
350 345
351This setting is used in non-stop mode only. In all-stop mode, 346This setting is used in non-stop mode only. In all-stop mode,
352Emacs always switches to the thread which caused the stop." 347Emacs always switches to the thread which caused the stop."
353 ;; exited, exited-normally and exited-signaled are not 348 ;; exited, exited-normally and exited-signaled are not
354 ;; thread-specific stop reasons and therefore are not included in 349 ;; thread-specific stop reasons and therefore are not included in
@@ -404,7 +399,7 @@ and GDB buffers were updated in `gdb-stopped'."
404 :link '(info-link "(gdb)GDB/MI Async Records")) 399 :link '(info-link "(gdb)GDB/MI Async Records"))
405 400
406(defcustom gdb-switch-when-another-stopped t 401(defcustom gdb-switch-when-another-stopped t
407 "When nil, Emacs won't switch to stopped thread if some other 402 "When nil, don't switch to stopped thread if some other
408stopped thread is already selected." 403stopped thread is already selected."
409 :type 'boolean 404 :type 'boolean
410 :group 'gdb-non-stop 405 :group 'gdb-non-stop
@@ -447,8 +442,7 @@ stopped thread is already selected."
447 :version "23.2") 442 :version "23.2")
448 443
449(defcustom gdb-show-threads-by-default nil 444(defcustom gdb-show-threads-by-default nil
450 "Show threads list buffer instead of breakpoints list by 445 "Show threads list buffer instead of breakpoints list by default."
451default."
452 :type 'boolean 446 :type 'boolean
453 :group 'gdb-buffers 447 :group 'gdb-buffers
454 :version "23.2") 448 :version "23.2")
@@ -490,12 +484,12 @@ predefined macros."
490 484
491(defcustom gdb-create-source-file-list t 485(defcustom gdb-create-source-file-list t
492 "Non-nil means create a list of files from which the executable was built. 486 "Non-nil means create a list of files from which the executable was built.
493 Set this to nil if the GUD buffer displays \"initializing...\" in the mode 487Set this to nil if the GUD buffer displays \"initializing...\" in the mode
494 line for a long time when starting, possibly because your executable was 488line for a long time when starting, possibly because your executable was
495 built from a large number of files. This allows quicker initialization 489built from a large number of files. This allows quicker initialization
496 but means that these files are not automatically enabled for debugging, 490but means that these files are not automatically enabled for debugging,
497 e.g., you won't be able to click in the fringe to set a breakpoint until 491e.g., you won't be able to click in the fringe to set a breakpoint until
498 execution has already stopped there." 492execution has already stopped there."
499 :type 'boolean 493 :type 'boolean
500 :group 'gdb 494 :group 'gdb
501 :version "23.1") 495 :version "23.1")
@@ -507,6 +501,9 @@ Also display the main routine in the disassembly buffer if present."
507 :group 'gdb 501 :group 'gdb
508 :version "22.1") 502 :version "22.1")
509 503
504(defvar gdbmi-debug-mode nil
505 "When non-nil, print the messages sent/received from GDB/MI in *Messages*.")
506
510(defun gdb-force-mode-line-update (status) 507(defun gdb-force-mode-line-update (status)
511 (let ((buffer gud-comint-buffer)) 508 (let ((buffer gud-comint-buffer))
512 (if (and buffer (buffer-name buffer)) 509 (if (and buffer (buffer-name buffer))
@@ -570,7 +567,7 @@ When `gdb-non-stop' is nil, return COMMAND unchanged."
570 567
571(defmacro gdb-gud-context-call (cmd1 &optional cmd2 noall noarg) 568(defmacro gdb-gud-context-call (cmd1 &optional cmd2 noall noarg)
572 "`gud-call' wrapper which adds --thread/--all options between 569 "`gud-call' wrapper which adds --thread/--all options between
573CMD1 and CMD2. NOALL is the same as in `gdb-gud-context-command'. 570CMD1 and CMD2. NOALL is the same as in `gdb-gud-context-command'.
574 571
575NOARG must be t when this macro is used outside `gud-def'" 572NOARG must be t when this macro is used outside `gud-def'"
576 `(gud-call 573 `(gud-call
@@ -603,7 +600,7 @@ and source-file directory for your debugger.
603 600
604COMMAND-LINE is the shell command for starting the gdb session. 601COMMAND-LINE is the shell command for starting the gdb session.
605It should be a string consisting of the name of the gdb 602It should be a string consisting of the name of the gdb
606executable followed by command-line options. The command-line 603executable followed by command line options. The command line
607options should include \"-i=mi\" to use gdb's MI text interface. 604options should include \"-i=mi\" to use gdb's MI text interface.
608Note that the old \"--annotate\" option is no longer supported. 605Note that the old \"--annotate\" option is no longer supported.
609 606
@@ -846,6 +843,8 @@ detailed description of this mode.
846 gdb-register-names '() 843 gdb-register-names '()
847 gdb-non-stop gdb-non-stop-setting) 844 gdb-non-stop gdb-non-stop-setting)
848 ;; 845 ;;
846 (gdbmi-bnf-init)
847 ;;
849 (setq gdb-buffer-type 'gdbmi) 848 (setq gdb-buffer-type 'gdbmi)
850 ;; 849 ;;
851 (gdb-force-mode-line-update 850 (gdb-force-mode-line-update
@@ -1254,7 +1253,7 @@ With arg, enter name of variable to be watched in the minibuffer."
1254 (cond 1253 (cond
1255 ((> new previous) 1254 ((> new previous)
1256 ;; Add new children to list. 1255 ;; Add new children to list.
1257 (dotimes (dummy previous) 1256 (dotimes (_ previous)
1258 (push (pop temp-var-list) var-list)) 1257 (push (pop temp-var-list) var-list))
1259 (dolist (child children) 1258 (dolist (child children)
1260 (let ((varchild 1259 (let ((varchild
@@ -1268,9 +1267,9 @@ With arg, enter name of variable to be watched in the minibuffer."
1268 (push varchild var-list)))) 1267 (push varchild var-list))))
1269 ;; Remove deleted children from list. 1268 ;; Remove deleted children from list.
1270 ((< new previous) 1269 ((< new previous)
1271 (dotimes (dummy new) 1270 (dotimes (_ new)
1272 (push (pop temp-var-list) var-list)) 1271 (push (pop temp-var-list) var-list))
1273 (dotimes (dummy (- previous new)) 1272 (dotimes (_ (- previous new))
1274 (pop temp-var-list))))) 1273 (pop temp-var-list)))))
1275 (push var1 var-list)) 1274 (push var1 var-list))
1276 (setq var1 (pop temp-var-list))) 1275 (setq var1 (pop temp-var-list)))
@@ -1502,7 +1501,7 @@ this trigger is subscribed to `gdb-buf-publisher' and called with
1502 (gdb-input 1501 (gdb-input
1503 (concat "-inferior-tty-set " tty) 'ignore)))) 1502 (concat "-inferior-tty-set " tty) 'ignore))))
1504 1503
1505(defun gdb-inferior-io-sentinel (proc str) 1504(defun gdb-inferior-io-sentinel (proc _str)
1506 (when (eq (process-status proc) 'failed) 1505 (when (eq (process-status proc) 'failed)
1507 ;; When the debugged process exits, Emacs gets an EIO error on 1506 ;; When the debugged process exits, Emacs gets an EIO error on
1508 ;; read from the pty, and stops listening to it. If the gdb 1507 ;; read from the pty, and stops listening to it. If the gdb
@@ -1739,6 +1738,7 @@ complete."
1739 (setq gdb-token-number (1+ gdb-token-number)) 1738 (setq gdb-token-number (1+ gdb-token-number))
1740 (setq command (concat (number-to-string gdb-token-number) command)) 1739 (setq command (concat (number-to-string gdb-token-number) command))
1741 (push (cons gdb-token-number handler-function) gdb-handler-alist) 1740 (push (cons gdb-token-number handler-function) gdb-handler-alist)
1741 (if gdbmi-debug-mode (message "gdb-input: %s" command))
1742 (process-send-string (get-buffer-process gud-comint-buffer) 1742 (process-send-string (get-buffer-process gud-comint-buffer)
1743 (concat command "\n"))) 1743 (concat command "\n")))
1744 1744
@@ -1761,8 +1761,7 @@ If `gdb-thread-number' is nil, just wrap NAME in asterisks."
1761 "*")) 1761 "*"))
1762 1762
1763(defun gdb-current-context-mode-name (mode) 1763(defun gdb-current-context-mode-name (mode)
1764 "Add thread information to MODE which is to be used as 1764 "Add thread information to MODE which is to be used as `mode-name'."
1765`mode-name'."
1766 (concat mode 1765 (concat mode
1767 (if gdb-thread-number 1766 (if gdb-thread-number
1768 (format " [thread %s]" gdb-thread-number) 1767 (format " [thread %s]" gdb-thread-number)
@@ -1809,7 +1808,8 @@ If NO-PROC is non-nil, do not try to contact the GDB process."
1809;; because we may need to update current gud-running value without 1808;; because we may need to update current gud-running value without
1810;; changing current thread (see gdb-running) 1809;; changing current thread (see gdb-running)
1811(defun gdb-setq-thread-number (number) 1810(defun gdb-setq-thread-number (number)
1812 "Only this function must be used to change `gdb-thread-number' 1811 "Set `gdb-thread-number' to NUMBER.
1812Only this function must be used to change `gdb-thread-number'
1813value to NUMBER, because `gud-running' and `gdb-frame-number' 1813value to NUMBER, because `gud-running' and `gdb-frame-number'
1814need to be updated appropriately when current thread changes." 1814need to be updated appropriately when current thread changes."
1815 ;; GDB 6.8 and earlier always output thread-id="0" when stopping. 1815 ;; GDB 6.8 and earlier always output thread-id="0" when stopping.
@@ -1824,7 +1824,7 @@ need to be updated appropriately when current thread changes."
1824 1824
1825Note that when `gdb-gud-control-all-threads' is t, `gud-running' 1825Note that when `gdb-gud-control-all-threads' is t, `gud-running'
1826cannot be reliably used to determine whether or not execution 1826cannot be reliably used to determine whether or not execution
1827control buttons should be shown in menu or toolbar. Use 1827control buttons should be shown in menu or toolbar. Use
1828`gdb-running-threads-count' and `gdb-stopped-threads-count' 1828`gdb-running-threads-count' and `gdb-stopped-threads-count'
1829instead. 1829instead.
1830 1830
@@ -1874,23 +1874,337 @@ is running."
1874 (set-window-buffer source-window buffer)) 1874 (set-window-buffer source-window buffer))
1875 source-window)) 1875 source-window))
1876 1876
1877(defun gdb-car< (a b) 1877
1878 (< (car a) (car b))) 1878(defun gdbmi-start-with (str offset match)
1879 1879 "Return non-nil if string STR starts with MATCH, else returns nil.
1880(defvar gdbmi-record-list 1880OFFSET is the position in STR at which the comparison takes place."
1881 '((gdb-gdb . "(gdb) \n") 1881 (let ((match-length (length match))
1882 (gdb-done . "\\([0-9]*\\)\\^done,?\\(.*?\\)\n") 1882 (str-length (- (length str) offset)))
1883 (gdb-starting . "\\([0-9]*\\)\\^running\n") 1883 (when (>= str-length match-length)
1884 (gdb-error . "\\([0-9]*\\)\\^error,\\(.*?\\)\n") 1884 (string-equal match (substring str offset (+ offset match-length))))))
1885 (gdb-console . "~\\(\".*?\"\\)\n") 1885
1886 (gdb-internals . "&\\(\".*?\"\\)\n") 1886(defun gdbmi-same-start (str offset match)
1887 (gdb-stopped . "\\*stopped,?\\(.*?\\)\n") 1887 "Return non-nil iff STR and MATCH are equal up to the end of either strings.
1888 (gdb-running . "\\*running,\\(.*?\n\\)") 1888OFFSET is the position in STR at which the comparison takes place."
1889 (gdb-thread-created . "=thread-created,\\(.*?\n\\)") 1889 (let* ((str-length (- (length str) offset))
1890 (gdb-thread-selected . "=thread-selected,\\(.*?\\)\n") 1890 (match-length (length match))
1891 (gdb-thread-exited . "=thread-exited,\\(.*?\n\\)") 1891 (compare-length (min str-length match-length)))
1892 (gdb-ignored-notification . "=[-[:alpha:]]+,?\\(.*?\\)\n") 1892 (when (> compare-length 0)
1893 (gdb-shell . "\\(\\(?:^.+\n\\)+\\)"))) 1893 (string-equal (substring str offset (+ offset compare-length))
1894 (substring match 0 compare-length)))))
1895
1896(defun gdbmi-is-number (character)
1897 "Return non-nil iff CHARACTER is a numerical character between 0 and 9."
1898 (and (>= character ?0)
1899 (<= character ?9)))
1900
1901
1902(defvar-local gdbmi-bnf-state 'gdbmi-bnf-output
1903 "Current GDB/MI output parser state.
1904The parser is placed in a different state when an incomplete data steam is
1905received from GDB.
1906This variable will preserve the state required to resume the parsing
1907when more data arrives.")
1908
1909(defvar-local gdbmi-bnf-offset 0
1910 "Offset in `gud-marker-acc' at which the parser is reading.
1911This offset is used to be able to parse the GDB/MI message
1912in-place, without the need of copying the string in a temporary buffer
1913or discarding parsed tokens by substringing the message.")
1914
1915(defun gdbmi-bnf-init ()
1916 "Initialize the GDB/MI message parser."
1917 (setq gdbmi-bnf-state 'gdbmi-bnf-output)
1918 (setq gdbmi-bnf-offset 0)
1919 (setq gud-marker-acc ""))
1920
1921
1922(defun gdbmi-bnf-output ()
1923 "Implementation of the following GDB/MI output grammar rule:
1924
1925 output ==>
1926 ( out-of-band-record )* [ result-record ] gdb-prompt"
1927
1928 (gdbmi-bnf-skip-unrecognized)
1929 (while (gdbmi-bnf-out-of-band-record))
1930 (gdbmi-bnf-result-record)
1931 (gdbmi-bnf-gdb-prompt))
1932
1933
1934(defun gdbmi-bnf-skip-unrecognized ()
1935 "Skip characters until is encounters the beginning of a valid record.
1936Used as a protection mechanism in case something goes wrong when parsing
1937a GDB/MI reply message."
1938 (let ((acc-length (length gud-marker-acc))
1939 (prefix-offset gdbmi-bnf-offset)
1940 (prompt "(gdb) \n"))
1941
1942 (while (and (< prefix-offset acc-length)
1943 (gdbmi-is-number (aref gud-marker-acc prefix-offset)))
1944 (setq prefix-offset (1+ prefix-offset)))
1945
1946 (if (and (< prefix-offset acc-length)
1947 (not (memq (aref gud-marker-acc prefix-offset)
1948 '(?^ ?* ?+ ?= ?~ ?@ ?&)))
1949 (not (gdbmi-same-start gud-marker-acc gdbmi-bnf-offset prompt))
1950 (string-match "\\([^^*+=~@&]+\\)" gud-marker-acc
1951 gdbmi-bnf-offset))
1952 (let ((unrecognized-str (match-string 0 gud-marker-acc)))
1953 (setq gdbmi-bnf-offset (match-end 0))
1954 (if gdbmi-debug-mode
1955 (message "gdbmi-bnf-skip-unrecognized: %s" unrecognized-str))
1956 (gdb-shell unrecognized-str)
1957 t))))
1958
1959
1960(defun gdbmi-bnf-gdb-prompt ()
1961 "Implementation of the following GDB/MI output grammar rule:
1962 gdb-prompt ==>
1963 '(gdb)' nl
1964
1965 nl ==>
1966 CR | CR-LF"
1967
1968 (let ((prompt "(gdb) \n"))
1969 (when (gdbmi-start-with gud-marker-acc gdbmi-bnf-offset prompt)
1970 (if gdbmi-debug-mode (message "gdbmi-bnf-gdb-prompt: %s" prompt))
1971 (gdb-gdb prompt)
1972 (setq gdbmi-bnf-offset (+ gdbmi-bnf-offset (length prompt)))
1973
1974 ;; Returns non-nil to tell gud-gdbmi-marker-filter we've reached
1975 ;; the end of a GDB reply message.
1976 t)))
1977
1978
1979(defun gdbmi-bnf-result-record ()
1980 "Implementation of the following GDB/MI output grammar rule:
1981
1982 result-record ==>
1983 [ token ] '^' result-class ( ',' result )* nl
1984
1985 token ==>
1986 any sequence of digits."
1987
1988 (gdbmi-bnf-result-and-async-record-impl))
1989
1990
1991(defun gdbmi-bnf-out-of-band-record ()
1992 "Implementation of the following GDB/MI output grammar rule:
1993
1994 out-of-band-record ==>
1995 async-record | stream-record"
1996
1997 (or (gdbmi-bnf-async-record)
1998 (gdbmi-bnf-stream-record)))
1999
2000
2001(defun gdbmi-bnf-async-record ()
2002 "Implementation of the following GDB/MI output grammar rules:
2003
2004 async-record ==>
2005 exec-async-output | status-async-output | notify-async-output
2006
2007 exec-async-output ==>
2008 [ token ] '*' async-output
2009
2010 status-async-output ==>
2011 [ token ] '+' async-output
2012
2013 notify-async-output ==>
2014 [ token ] '=' async-output
2015
2016 async-output ==>
2017 async-class ( ',' result )* nl"
2018
2019 (gdbmi-bnf-result-and-async-record-impl))
2020
2021
2022(defun gdbmi-bnf-stream-record ()
2023 "Implement the following GDB/MI output grammar rule:
2024 stream-record ==>
2025 console-stream-output | target-stream-output | log-stream-output
2026
2027 console-stream-output ==>
2028 '~' c-string
2029
2030 target-stream-output ==>
2031 '@' c-string
2032
2033 log-stream-output ==>
2034 '&' c-string"
2035 (when (< gdbmi-bnf-offset (length gud-marker-acc))
2036 (if (and (member (aref gud-marker-acc gdbmi-bnf-offset) '(?~ ?@ ?&))
2037 (string-match "\\([~@&]\\)\\(\".*?\"\\)\n" gud-marker-acc
2038 gdbmi-bnf-offset))
2039 (let ((prefix (match-string 1 gud-marker-acc))
2040 (c-string (match-string 2 gud-marker-acc)))
2041
2042 (setq gdbmi-bnf-offset (match-end 0))
2043 (if gdbmi-debug-mode (message "gdbmi-bnf-stream-record: %s"
2044 (match-string 0 gud-marker-acc)))
2045
2046 (cond ((string-equal prefix "~")
2047 (gdbmi-bnf-console-stream-output c-string))
2048 ((string-equal prefix "@")
2049 (gdbmi-bnf-target-stream-output c-string))
2050 ((string-equal prefix "&")
2051 (gdbmi-bnf-log-stream-output c-string)))
2052 t))))
2053
2054(defun gdbmi-bnf-console-stream-output (c-string)
2055 "Handler for the console-stream-output GDB/MI output grammar rule."
2056 (gdb-console c-string))
2057
2058(defun gdbmi-bnf-target-stream-output (_c-string)
2059 "Handler for the target-stream-output GDB/MI output grammar rule."
2060 ;; Not currently used.
2061 )
2062
2063(defun gdbmi-bnf-log-stream-output (c-string)
2064 "Handler for the log-stream-output GDB/MI output grammar rule."
2065 ;; Suppress "No registers." GDB 6.8 and earlier
2066 ;; duplicates MI error message on internal stream.
2067 ;; Don't print to GUD buffer.
2068 (if (not (string-equal (read c-string) "No registers.\n"))
2069 (gdb-internals c-string)))
2070
2071
2072(defconst gdbmi-bnf-result-state-configs
2073 '(("^" . (("done" . (gdb-done . progressive))
2074 ("error" . (gdb-error . progressive))
2075 ("running" . (gdb-starting . atomic))))
2076 ("*" . (("stopped" . (gdb-stopped . atomic))
2077 ("running" . (gdb-running . atomic))))
2078 ("+" . ())
2079 ("=" . (("thread-created" . (gdb-thread-created . atomic))
2080 ("thread-selected" . (gdb-thread-selected . atomic))
2081 ("thread-existed" . (gdb-ignored-notification . atomic))
2082 ('default . (gdb-ignored-notification . atomic)))))
2083 "Alist of alists, mapping the type and class of message to a handler function.
2084Handler functions are all flagged as either `progressive' or `atomic'.
2085`progressive' handlers are capable of parsing incomplete messages.
2086They can be called several time with new data chunk as they arrive from GDB.
2087`progressive' handlers must have an extra argument that is set to a non-nil
2088value when the message is complete.
2089
2090Implement the following GDB/MI output grammar rule:
2091 result-class ==>
2092 'done' | 'running' | 'connected' | 'error' | 'exit'
2093
2094 async-class ==>
2095 'stopped' | others (where others will be added depending on the needs
2096 --this is still in development).")
2097
2098(defun gdbmi-bnf-result-and-async-record-impl ()
2099 "Common implementation of the result-record and async-record rule.
2100Both rules share the same syntax. Those records may be very large in size.
2101For that reason, the \"result\" part of the record is parsed by
2102`gdbmi-bnf-incomplete-record-result', which will keep
2103receiving characters as they arrive from GDB until the record is complete."
2104 (let ((acc-length (length gud-marker-acc))
2105 (prefix-offset gdbmi-bnf-offset))
2106
2107 (while (and (< prefix-offset acc-length)
2108 (gdbmi-is-number (aref gud-marker-acc prefix-offset)))
2109 (setq prefix-offset (1+ prefix-offset)))
2110
2111 (if (and (< prefix-offset acc-length)
2112 (member (aref gud-marker-acc prefix-offset) '(?* ?+ ?= ?^))
2113 (string-match "\\([0-9]*\\)\\([*+=^]\\)\\(.+?\\)\\([,\n]\\)"
2114 gud-marker-acc gdbmi-bnf-offset))
2115
2116 (let ((token (match-string 1 gud-marker-acc))
2117 (prefix (match-string 2 gud-marker-acc))
2118 (class (match-string 3 gud-marker-acc))
2119 (complete (string-equal (match-string 4 gud-marker-acc) "\n"))
2120 class-alist
2121 class-command)
2122
2123 (setq gdbmi-bnf-offset (match-end 0))
2124 (if gdbmi-debug-mode (message "gdbmi-bnf-result-record: %s"
2125 (match-string 0 gud-marker-acc)))
2126
2127 (setq class-alist
2128 (cdr (assoc prefix gdbmi-bnf-result-state-configs)))
2129 (setq class-command (cdr (assoc class class-alist)))
2130 (if (null class-command)
2131 (setq class-command (cdr (assoc 'default class-alist))))
2132
2133 (if complete
2134 (if class-command
2135 (if (equal (cdr class-command) 'progressive)
2136 (funcall (car class-command) token "" complete)
2137 (funcall (car class-command) token "")))
2138 (setq gdbmi-bnf-state
2139 (lambda ()
2140 (gdbmi-bnf-incomplete-record-result token class-command)))
2141 (funcall gdbmi-bnf-state))
2142 t))))
2143
2144(defun gdbmi-bnf-incomplete-record-result (token class-command)
2145 "State of the parser used to progressively parse a result-record or async-record
2146rule from an incomplete data stream. The parser will stay in this state until
2147the end of the current result or async record is reached."
2148 (when (< gdbmi-bnf-offset (length gud-marker-acc))
2149 ;; Search the data stream for the end of the current record:
2150 (let* ((newline-pos (string-match "\n" gud-marker-acc gdbmi-bnf-offset))
2151 (is-progressive (equal (cdr class-command) 'progressive))
2152 (is-complete (not (null newline-pos)))
2153 result-str)
2154
2155 ;; Update the gdbmi-bnf-offset only if the current chunk of data can
2156 ;; be processed by the class-command handler:
2157 (when (or is-complete is-progressive)
2158 (setq result-str
2159 (substring gud-marker-acc gdbmi-bnf-offset newline-pos))
2160 (setq gdbmi-bnf-offset (+ 1 newline-pos)))
2161
2162 (if gdbmi-debug-mode
2163 (message "gdbmi-bnf-incomplete-record-result: %s"
2164 (substring gud-marker-acc gdbmi-bnf-offset newline-pos)))
2165
2166 ;; Update the parsing state before invoking the handler in class-command
2167 ;; to make sure it's not left in an invalid state if the handler was
2168 ;; to generate an error.
2169 (if is-complete
2170 (setq gdbmi-bnf-state 'gdbmi-bnf-output))
2171
2172 (if class-command
2173 (if is-progressive
2174 (funcall (car class-command) token result-str is-complete)
2175 (if is-complete
2176 (funcall (car class-command) token result-str))))
2177
2178 (unless is-complete
2179 ;; Incomplete gdb response: abort parsing until we receive more data.
2180 (if gdbmi-debug-mode (message "gdbmi-bnf-incomplete-record-result, aborting: incomplete stream"))
2181 (throw 'gdbmi-incomplete-stream nil))
2182
2183 is-complete)))
2184
2185
2186; The following grammar rules are not yet implemented by this GDBMI-BNF parser.
2187; The handling of those rules is currently done by the handlers registered
2188; in gdbmi-bnf-result-state-configs
2189;
2190; result ==>
2191; variable "=" value
2192;
2193; variable ==>
2194; string
2195;
2196; value ==>
2197; const | tuple | list
2198;
2199; const ==>
2200; c-string
2201;
2202; tuple ==>
2203; "{}" | "{" result ( "," result )* "}"
2204;
2205; list ==>
2206; "[]" | "[" value ( "," value )* "]" | "[" result ( "," result )* "]"
2207
1894 2208
1895(defun gud-gdbmi-marker-filter (string) 2209(defun gud-gdbmi-marker-filter (string)
1896 "Filter GDB/MI output." 2210 "Filter GDB/MI output."
@@ -1907,46 +2221,20 @@ is running."
1907 2221
1908 ;; Start accumulating output for the GUD buffer. 2222 ;; Start accumulating output for the GUD buffer.
1909 (setq gdb-filter-output "") 2223 (setq gdb-filter-output "")
1910 (let (output-record-list)
1911
1912 ;; Process all the complete markers in this chunk.
1913 (dolist (gdbmi-record gdbmi-record-list)
1914 (while (string-match (cdr gdbmi-record) gud-marker-acc)
1915 (push (list (match-beginning 0)
1916 (car gdbmi-record)
1917 (match-string 1 gud-marker-acc)
1918 (match-string 2 gud-marker-acc)
1919 (match-end 0))
1920 output-record-list)
1921 (setq gud-marker-acc
1922 (concat (substring gud-marker-acc 0 (match-beginning 0))
1923 ;; Pad with spaces to preserve position.
1924 (make-string (length (match-string 0 gud-marker-acc)) 32)
1925 (substring gud-marker-acc (match-end 0))))))
1926
1927 (setq output-record-list (sort output-record-list 'gdb-car<))
1928
1929 (dolist (output-record output-record-list)
1930 (let ((record-type (cadr output-record))
1931 (arg1 (nth 2 output-record))
1932 (arg2 (nth 3 output-record)))
1933 (cond ((eq record-type 'gdb-error)
1934 (gdb-done-or-error arg2 arg1 'error))
1935 ((eq record-type 'gdb-done)
1936 (gdb-done-or-error arg2 arg1 'done))
1937 ;; Suppress "No registers." GDB 6.8 and earlier
1938 ;; duplicates MI error message on internal stream.
1939 ;; Don't print to GUD buffer.
1940 ((not (and (eq record-type 'gdb-internals)
1941 (string-equal (read arg1) "No registers.\n")))
1942 (funcall record-type arg1)))))
1943 2224
1944 (setq gdb-output-sink 'user) 2225 (let ((acc-length (length gud-marker-acc)))
1945 ;; Remove padding. 2226 (catch 'gdbmi-incomplete-stream
1946 (string-match "^ *" gud-marker-acc) 2227 (while (and (< gdbmi-bnf-offset acc-length)
1947 (setq gud-marker-acc (substring gud-marker-acc (match-end 0))) 2228 (funcall gdbmi-bnf-state)))))
2229
2230 (when (/= gdbmi-bnf-offset 0)
2231 (setq gud-marker-acc (substring gud-marker-acc gdbmi-bnf-offset))
2232 (setq gdbmi-bnf-offset 0))
2233
2234 (when (and gdbmi-debug-mode (> (length gud-marker-acc) 0))
2235 (message "gud-gdbmi-marker-filter, unparsed string: %s" gud-marker-acc))
1948 2236
1949 gdb-filter-output)) 2237 gdb-filter-output)
1950 2238
1951(defun gdb-gdb (_output-field)) 2239(defun gdb-gdb (_output-field))
1952 2240
@@ -1954,13 +2242,13 @@ is running."
1954 (setq gdb-filter-output 2242 (setq gdb-filter-output
1955 (concat output-field gdb-filter-output))) 2243 (concat output-field gdb-filter-output)))
1956 2244
1957(defun gdb-ignored-notification (_output-field)) 2245(defun gdb-ignored-notification (_token _output-field))
1958 2246
1959;; gdb-invalidate-threads is defined to accept 'update-threads signal 2247;; gdb-invalidate-threads is defined to accept 'update-threads signal
1960(defun gdb-thread-created (_output-field)) 2248(defun gdb-thread-created (_token _output-field))
1961(defun gdb-thread-exited (output-field) 2249(defun gdb-thread-exited (_token output-field)
1962 "Handle =thread-exited async record: unset `gdb-thread-number' 2250 "Handle =thread-exited async record.
1963 if current thread exited and update threads list." 2251Unset `gdb-thread-number' if current thread exited and update threads list."
1964 (let* ((thread-id (bindat-get-field (gdb-json-string output-field) 'id))) 2252 (let* ((thread-id (bindat-get-field (gdb-json-string output-field) 'id)))
1965 (if (string= gdb-thread-number thread-id) 2253 (if (string= gdb-thread-number thread-id)
1966 (gdb-setq-thread-number nil)) 2254 (gdb-setq-thread-number nil))
@@ -1971,7 +2259,7 @@ is running."
1971 (gdb-wait-for-pending 2259 (gdb-wait-for-pending
1972 (gdb-emit-signal gdb-buf-publisher 'update-threads)))) 2260 (gdb-emit-signal gdb-buf-publisher 'update-threads))))
1973 2261
1974(defun gdb-thread-selected (output-field) 2262(defun gdb-thread-selected (_token output-field)
1975 "Handler for =thread-selected MI output record. 2263 "Handler for =thread-selected MI output record.
1976 2264
1977Sets `gdb-thread-number' to new id." 2265Sets `gdb-thread-number' to new id."
@@ -1988,7 +2276,7 @@ Sets `gdb-thread-number' to new id."
1988 (gdb-wait-for-pending 2276 (gdb-wait-for-pending
1989 (gdb-update)))) 2277 (gdb-update))))
1990 2278
1991(defun gdb-running (output-field) 2279(defun gdb-running (_token output-field)
1992 (let* ((thread-id 2280 (let* ((thread-id
1993 (bindat-get-field (gdb-json-string output-field) 'thread-id))) 2281 (bindat-get-field (gdb-json-string output-field) 'thread-id)))
1994 ;; We reset gdb-frame-number to nil if current thread has gone 2282 ;; We reset gdb-frame-number to nil if current thread has gone
@@ -2006,7 +2294,7 @@ Sets `gdb-thread-number' to new id."
2006 (setq gdb-active-process t) 2294 (setq gdb-active-process t)
2007 (gdb-emit-signal gdb-buf-publisher 'update-threads)) 2295 (gdb-emit-signal gdb-buf-publisher 'update-threads))
2008 2296
2009(defun gdb-starting (_output-field) 2297(defun gdb-starting (_output-field _result)
2010 ;; CLI commands don't emit ^running at the moment so use gdb-running too. 2298 ;; CLI commands don't emit ^running at the moment so use gdb-running too.
2011 (setq gdb-inferior-status "running") 2299 (setq gdb-inferior-status "running")
2012 (gdb-force-mode-line-update 2300 (gdb-force-mode-line-update
@@ -2020,7 +2308,7 @@ Sets `gdb-thread-number' to new id."
2020 2308
2021;; -break-insert -t didn't give a reason before gdb 6.9 2309;; -break-insert -t didn't give a reason before gdb 6.9
2022 2310
2023(defun gdb-stopped (output-field) 2311(defun gdb-stopped (_token output-field)
2024 "Given the contents of *stopped MI async record, select new 2312 "Given the contents of *stopped MI async record, select new
2025current thread and update GDB buffers." 2313current thread and update GDB buffers."
2026 ;; Reason is available with target-async only 2314 ;; Reason is available with target-async only
@@ -2106,7 +2394,13 @@ current thread and update GDB buffers."
2106 (setq gdb-filter-output 2394 (setq gdb-filter-output
2107 (gdb-concat-output gdb-filter-output (read output-field)))) 2395 (gdb-concat-output gdb-filter-output (read output-field))))
2108 2396
2109(defun gdb-done-or-error (output-field token-number type) 2397(defun gdb-done (token-number output-field is-complete)
2398 (gdb-done-or-error token-number 'done output-field is-complete))
2399
2400(defun gdb-error (token-number output-field is-complete)
2401 (gdb-done-or-error token-number 'error output-field is-complete))
2402
2403(defun gdb-done-or-error (token-number type output-field is-complete)
2110 (if (string-equal token-number "") 2404 (if (string-equal token-number "")
2111 ;; Output from command entered by user 2405 ;; Output from command entered by user
2112 (progn 2406 (progn
@@ -2122,14 +2416,12 @@ current thread and update GDB buffers."
2122 ;; Output from command from frontend. 2416 ;; Output from command from frontend.
2123 (setq gdb-output-sink 'emacs)) 2417 (setq gdb-output-sink 'emacs))
2124 2418
2125 (gdb-clear-partial-output)
2126
2127 ;; The process may already be dead (e.g. C-d at the gdb prompt). 2419 ;; The process may already be dead (e.g. C-d at the gdb prompt).
2128 (let* ((proc (get-buffer-process gud-comint-buffer)) 2420 (let* ((proc (get-buffer-process gud-comint-buffer))
2129 (no-proc (or (null proc) 2421 (no-proc (or (null proc)
2130 (memq (process-status proc) '(exit signal))))) 2422 (memq (process-status proc) '(exit signal)))))
2131 2423
2132 (when gdb-first-done-or-error 2424 (when (and is-complete gdb-first-done-or-error)
2133 (unless (or token-number gud-running no-proc) 2425 (unless (or token-number gud-running no-proc)
2134 (setq gdb-filter-output (concat gdb-filter-output gdb-prompt-name))) 2426 (setq gdb-filter-output (concat gdb-filter-output gdb-prompt-name)))
2135 (gdb-update no-proc) 2427 (gdb-update no-proc)
@@ -2138,13 +2430,19 @@ current thread and update GDB buffers."
2138 (setq gdb-filter-output 2430 (setq gdb-filter-output
2139 (gdb-concat-output gdb-filter-output output-field)) 2431 (gdb-concat-output gdb-filter-output output-field))
2140 2432
2141 (when token-number 2433 ;; We are done concatenating to the output sink. Restore it to user sink:
2434 (setq gdb-output-sink 'user)
2435
2436 (when (and token-number is-complete)
2142 (with-current-buffer 2437 (with-current-buffer
2143 (gdb-get-buffer-create 'gdb-partial-output-buffer) 2438 (gdb-get-buffer-create 'gdb-partial-output-buffer)
2144 (funcall 2439 (funcall
2145 (cdr (assoc (string-to-number token-number) gdb-handler-alist)))) 2440 (cdr (assoc (string-to-number token-number) gdb-handler-alist))))
2146 (setq gdb-handler-alist 2441 (setq gdb-handler-alist
2147 (assq-delete-all token-number gdb-handler-alist))))) 2442 (assq-delete-all token-number gdb-handler-alist)))
2443
2444 (when is-complete
2445 (gdb-clear-partial-output))))
2148 2446
2149(defun gdb-concat-output (so-far new) 2447(defun gdb-concat-output (so-far new)
2150 (cond 2448 (cond
@@ -2169,8 +2467,8 @@ Field names are wrapped in double quotes and equal signs are
2169replaced with semicolons. 2467replaced with semicolons.
2170 2468
2171If FIX-KEY is non-nil, strip all \"FIX-KEY=\" occurrences from 2469If FIX-KEY is non-nil, strip all \"FIX-KEY=\" occurrences from
2172partial output. This is used to get rid of useless keys in lists 2470partial output. This is used to get rid of useless keys in lists
2173in MI messages, e.g.: [key=.., key=..]. -stack-list-frames and 2471in MI messages, e.g.: [key=.., key=..]. -stack-list-frames and
2174-break-info are examples of MI commands which issue such 2472-break-info are examples of MI commands which issue such
2175responses. 2473responses.
2176 2474
@@ -2337,16 +2635,16 @@ calling `gdb-table-string'."
2337 handler-name 2635 handler-name
2338 &optional signal-list) 2636 &optional signal-list)
2339 "Define a trigger TRIGGER-NAME which sends GDB-COMMAND and sets 2637 "Define a trigger TRIGGER-NAME which sends GDB-COMMAND and sets
2340HANDLER-NAME as its handler. HANDLER-NAME is bound to current 2638HANDLER-NAME as its handler. HANDLER-NAME is bound to current
2341buffer with `gdb-bind-function-to-buffer'. 2639buffer with `gdb-bind-function-to-buffer'.
2342 2640
2343If SIGNAL-LIST is non-nil, GDB-COMMAND is sent only when the 2641If SIGNAL-LIST is non-nil, GDB-COMMAND is sent only when the
2344defined trigger is called with an argument from SIGNAL-LIST. It's 2642defined trigger is called with an argument from SIGNAL-LIST. It's
2345not recommended to define triggers with empty SIGNAL-LIST. 2643not recommended to define triggers with empty SIGNAL-LIST.
2346Normally triggers should respond at least to 'update signal. 2644Normally triggers should respond at least to 'update signal.
2347 2645
2348Normally the trigger defined by this command must be called from 2646Normally the trigger defined by this command must be called from
2349the buffer where HANDLER-NAME must work. This should be done so 2647the buffer where HANDLER-NAME must work. This should be done so
2350that buffer-local thread number may be used in GDB-COMMAND (by 2648that buffer-local thread number may be used in GDB-COMMAND (by
2351calling `gdb-current-context-command'). 2649calling `gdb-current-context-command').
2352`gdb-bind-function-to-buffer' is used to achieve this, see 2650`gdb-bind-function-to-buffer' is used to achieve this, see
@@ -2375,32 +2673,33 @@ Handlers are normally called from the buffers they put output in.
2375 2673
2376Delete ((current-buffer) . TRIGGER-NAME) from 2674Delete ((current-buffer) . TRIGGER-NAME) from
2377`gdb-pending-triggers', erase current buffer and evaluate 2675`gdb-pending-triggers', erase current buffer and evaluate
2378CUSTOM-DEFUN. Then `gdb-update-buffer-name' is called. 2676CUSTOM-DEFUN. Then `gdb-update-buffer-name' is called.
2379 2677
2380If NOPRESERVE is non-nil, window point is not restored after CUSTOM-DEFUN." 2678If NOPRESERVE is non-nil, window point is not restored after CUSTOM-DEFUN."
2381 `(defun ,handler-name () 2679 `(defun ,handler-name ()
2382 (gdb-delete-pending (cons (current-buffer) ',trigger-name)) 2680 (gdb-delete-pending (cons (current-buffer) ',trigger-name))
2383 (let* ((buffer-read-only nil) 2681 (let* ((inhibit-read-only t)
2384 (window (get-buffer-window (current-buffer) 0)) 2682 ,@(unless nopreserve
2385 (start (window-start window)) 2683 '((window (get-buffer-window (current-buffer) 0))
2386 (p (window-point window))) 2684 (start (window-start window))
2685 (p (window-point window)))))
2387 (erase-buffer) 2686 (erase-buffer)
2388 (,custom-defun) 2687 (,custom-defun)
2389 (gdb-update-buffer-name) 2688 (gdb-update-buffer-name)
2390 ,(when (not nopreserve) 2689 ,@(when (not nopreserve)
2391 '(set-window-start window start) 2690 '((set-window-start window start)
2392 '(set-window-point window p))))) 2691 (set-window-point window p))))))
2393 2692
2394(defmacro def-gdb-trigger-and-handler (trigger-name gdb-command 2693(defmacro def-gdb-trigger-and-handler (trigger-name gdb-command
2395 handler-name custom-defun 2694 handler-name custom-defun
2396 &optional signal-list) 2695 &optional signal-list)
2397 "Define trigger and handler. 2696 "Define trigger and handler.
2398 2697
2399TRIGGER-NAME trigger is defined to send GDB-COMMAND. See 2698TRIGGER-NAME trigger is defined to send GDB-COMMAND.
2400`def-gdb-auto-update-trigger'. 2699See `def-gdb-auto-update-trigger'.
2401 2700
2402HANDLER-NAME handler uses customization of CUSTOM-DEFUN. See 2701HANDLER-NAME handler uses customization of CUSTOM-DEFUN.
2403`def-gdb-auto-update-handler'." 2702See `def-gdb-auto-update-handler'."
2404 `(progn 2703 `(progn
2405 (def-gdb-auto-update-trigger ,trigger-name 2704 (def-gdb-auto-update-trigger ,trigger-name
2406 ,gdb-command 2705 ,gdb-command
@@ -2757,37 +3056,38 @@ corresponding to the mode line clicked."
2757 gdb-running-threads-count 3056 gdb-running-threads-count
2758 gdb-stopped-threads-count)) 3057 gdb-stopped-threads-count))
2759 3058
2760 (gdb-table-add-row table 3059 (gdb-table-add-row
2761 (list 3060 table
2762 (bindat-get-field thread 'id) 3061 (list
2763 (concat 3062 (bindat-get-field thread 'id)
2764 (if gdb-thread-buffer-verbose-names 3063 (concat
2765 (concat (bindat-get-field thread 'target-id) " ") "") 3064 (if gdb-thread-buffer-verbose-names
2766 (bindat-get-field thread 'state) 3065 (concat (bindat-get-field thread 'target-id) " ") "")
2767 ;; Include frame information for stopped threads 3066 (bindat-get-field thread 'state)
2768 (if (not running) 3067 ;; Include frame information for stopped threads
2769 (concat 3068 (if (not running)
2770 " in " (bindat-get-field thread 'frame 'func) 3069 (concat
2771 (if gdb-thread-buffer-arguments 3070 " in " (bindat-get-field thread 'frame 'func)
2772 (concat 3071 (if gdb-thread-buffer-arguments
2773 " (" 3072 (concat
2774 (let ((args (bindat-get-field thread 'frame 'args))) 3073 " ("
2775 (mapconcat 3074 (let ((args (bindat-get-field thread 'frame 'args)))
2776 (lambda (arg) 3075 (mapconcat
2777 (apply #'format "%s=%s" 3076 (lambda (arg)
2778 (gdb-get-many-fields arg 'name 'value))) 3077 (apply #'format "%s=%s"
2779 args ",")) 3078 (gdb-get-many-fields arg 'name 'value)))
2780 ")") 3079 args ","))
2781 "") 3080 ")")
2782 (if gdb-thread-buffer-locations 3081 "")
2783 (gdb-frame-location (bindat-get-field thread 'frame)) "") 3082 (if gdb-thread-buffer-locations
2784 (if gdb-thread-buffer-addresses 3083 (gdb-frame-location (bindat-get-field thread 'frame)) "")
2785 (concat " at " (bindat-get-field thread 'frame 'addr)) "")) 3084 (if gdb-thread-buffer-addresses
2786 ""))) 3085 (concat " at " (bindat-get-field thread 'frame 'addr)) ""))
2787 (list 3086 "")))
2788 'gdb-thread thread 3087 (list
2789 'mouse-face 'highlight 3088 'gdb-thread thread
2790 'help-echo "mouse-2, RET: select thread"))) 3089 'mouse-face 'highlight
3090 'help-echo "mouse-2, RET: select thread")))
2791 (when (string-equal gdb-thread-number 3091 (when (string-equal gdb-thread-number
2792 (bindat-get-field thread 'id)) 3092 (bindat-get-field thread 'id))
2793 (setq marked-line (length gdb-threads-list)))) 3093 (setq marked-line (length gdb-threads-list))))
@@ -2803,8 +3103,8 @@ corresponding to the mode line clicked."
2803 "Define a NAME command which will act upon thread on the current line. 3103 "Define a NAME command which will act upon thread on the current line.
2804 3104
2805CUSTOM-DEFUN may use locally bound `thread' variable, which will 3105CUSTOM-DEFUN may use locally bound `thread' variable, which will
2806be the value of 'gdb-thread property of the current line. If 3106be the value of 'gdb-thread property of the current line.
2807'gdb-thread is nil, error is signaled." 3107If `gdb-thread' is nil, error is signaled."
2808 `(defun ,name (&optional event) 3108 `(defun ,name (&optional event)
2809 ,(when doc doc) 3109 ,(when doc doc)
2810 (interactive (list last-input-event)) 3110 (interactive (list last-input-event))
@@ -2953,7 +3253,7 @@ line."
2953(defun gdb-memory-column-width (size format) 3253(defun gdb-memory-column-width (size format)
2954 "Return length of string with memory unit of SIZE in FORMAT. 3254 "Return length of string with memory unit of SIZE in FORMAT.
2955 3255
2956SIZE is in bytes, as in `gdb-memory-unit'. FORMAT is a string as 3256SIZE is in bytes, as in `gdb-memory-unit'. FORMAT is a string as
2957in `gdb-memory-format'." 3257in `gdb-memory-format'."
2958 (let ((format-base (cdr (assoc format 3258 (let ((format-base (cdr (assoc format
2959 '(("x" . 16) 3259 '(("x" . 16)
@@ -3455,8 +3755,7 @@ DOC is an optional documentation string."
3455 (error "Not recognized as break/watchpoint line"))))) 3755 (error "Not recognized as break/watchpoint line")))))
3456 3756
3457(defun gdb-goto-breakpoint (&optional event) 3757(defun gdb-goto-breakpoint (&optional event)
3458 "Go to the location of breakpoint at current line of 3758 "Go to the location of breakpoint at current line of breakpoints buffer."
3459breakpoints buffer."
3460 (interactive (list last-input-event)) 3759 (interactive (list last-input-event))
3461 (if event (posn-set-point (event-end event))) 3760 (if event (posn-set-point (event-end event)))
3462 ;; Hack to stop gdb-goto-breakpoint displaying in GUD buffer. 3761 ;; Hack to stop gdb-goto-breakpoint displaying in GUD buffer.
@@ -3840,7 +4139,7 @@ member."
3840 4139
3841(defun gdb-get-source-file-list () 4140(defun gdb-get-source-file-list ()
3842 "Create list of source files for current GDB session. 4141 "Create list of source files for current GDB session.
3843If buffers already exist for any of these files, gud-minor-mode 4142If buffers already exist for any of these files, `gud-minor-mode'
3844is set in them." 4143is set in them."
3845 (goto-char (point-min)) 4144 (goto-char (point-min))
3846 (while (re-search-forward gdb-source-file-regexp nil t) 4145 (while (re-search-forward gdb-source-file-regexp nil t)
@@ -3851,8 +4150,8 @@ is set in them."
3851 (gdb-init-buffer))))) 4150 (gdb-init-buffer)))))
3852 4151
3853(defun gdb-get-main-selected-frame () 4152(defun gdb-get-main-selected-frame ()
3854 "Trigger for `gdb-frame-handler' which uses main current 4153 "Trigger for `gdb-frame-handler' which uses main current thread.
3855thread. Called from `gdb-update'." 4154Called from `gdb-update'."
3856 (if (not (gdb-pending-p 'gdb-get-main-selected-frame)) 4155 (if (not (gdb-pending-p 'gdb-get-main-selected-frame))
3857 (progn 4156 (progn
3858 (gdb-input (gdb-current-context-command "-stack-info-frame") 4157 (gdb-input (gdb-current-context-command "-stack-info-frame")
@@ -3860,7 +4159,7 @@ thread. Called from `gdb-update'."
3860 (gdb-add-pending 'gdb-get-main-selected-frame)))) 4159 (gdb-add-pending 'gdb-get-main-selected-frame))))
3861 4160
3862(defun gdb-frame-handler () 4161(defun gdb-frame-handler ()
3863 "Sets `gdb-selected-frame' and `gdb-selected-file' to show 4162 "Set `gdb-selected-frame' and `gdb-selected-file' to show
3864overlay arrow in source buffer." 4163overlay arrow in source buffer."
3865 (gdb-delete-pending 'gdb-get-main-selected-frame) 4164 (gdb-delete-pending 'gdb-get-main-selected-frame)
3866 (let ((frame (bindat-get-field (gdb-json-partial-output) 'frame))) 4165 (let ((frame (bindat-get-field (gdb-json-partial-output) 'frame)))
@@ -3921,8 +4220,8 @@ overlay arrow in source buffer."
3921 4220
3922(defun gdb-preempt-existing-or-display-buffer (buf &optional split-horizontal) 4221(defun gdb-preempt-existing-or-display-buffer (buf &optional split-horizontal)
3923 "Find window displaying a buffer with the same 4222 "Find window displaying a buffer with the same
3924`gdb-buffer-type' as BUF and show BUF there. If no such window 4223`gdb-buffer-type' as BUF and show BUF there. If no such window
3925exists, just call `gdb-display-buffer' for BUF. If the window 4224exists, just call `gdb-display-buffer' for BUF. If the window
3926found is already dedicated, split window according to 4225found is already dedicated, split window according to
3927SPLIT-HORIZONTAL and show BUF in the new window." 4226SPLIT-HORIZONTAL and show BUF in the new window."
3928 (if buf 4227 (if buf
@@ -4310,8 +4609,7 @@ CONTEXT is the text before COMMAND on the line."
4310 (gud-gdb-fetch-lines-break (length context)) 4609 (gud-gdb-fetch-lines-break (length context))
4311 (gud-gdb-fetched-lines nil) 4610 (gud-gdb-fetched-lines nil)
4312 ;; This filter dumps output lines to `gud-gdb-fetched-lines'. 4611 ;; This filter dumps output lines to `gud-gdb-fetched-lines'.
4313 (gud-marker-filter #'gud-gdbmi-fetch-lines-filter) 4612 (gud-marker-filter #'gud-gdbmi-fetch-lines-filter))
4314 complete-list)
4315 (with-current-buffer (gdb-get-buffer 'gdb-partial-output-buffer) 4613 (with-current-buffer (gdb-get-buffer 'gdb-partial-output-buffer)
4316 (gdb-input (concat "complete " context command) 4614 (gdb-input (concat "complete " context command)
4317 (lambda () (setq gud-gdb-fetch-lines-in-progress nil))) 4615 (lambda () (setq gud-gdb-fetch-lines-in-progress nil)))