diff options
| author | Jean-Philippe Gravel | 2013-05-14 14:13:31 -0400 |
|---|---|---|
| committer | Jean-Philippe Gravel | 2013-05-14 14:13:31 -0400 |
| commit | 53267ccaa501b9ea2ff55555660d12082c461d65 (patch) | |
| tree | 17e039f0677e7208a9712243274b012738531bb2 | |
| parent | d04ce803e5434854b6c4601e413bd8e79da00569 (diff) | |
| download | emacs-53267ccaa501b9ea2ff55555660d12082c461d65.tar.gz emacs-53267ccaa501b9ea2ff55555660d12082c461d65.zip | |
* progmodes/gdb-mi.el: Fix non-responsive gud commands (bug#13845)
(gdb-handler-alist, gdb-handler-number): Remove variables.
(gdb-handler-list): New variable.
(gdb-add-handler, gdb-delete-handler, gdb-get-handler-function)
(gdb-pending-handler-p, gdb-handle-reply)
(gdb-remove-all-pending-triggers): New functions.
(gdb-discard-unordered-replies): New defcustom.
(gdb-handler): New defstruct.
(gdb-wait-for-pending): Fix invalid backquote. Use gdb-handler-list.
instead of gdb-pending-triggers. Update docstring.
(gdb-init-1): Remove dead variables. Initialize gdb-handler-list.
(gdb-speedbar-update, gdb-speedbar-timer-fn, gdb-var-update)
(gdb-var-update-handler, def-gdb-auto-update-trigger)
(def-gdb-auto-update-handler, gdb-get-changed-registers)
(gdb-changed-registers-handler, gdb-get-main-selected-frame)
(gdb-frame-handler): Pending triggers are now automatically managed.
(def-gdb-trigger-and-handler, def-gdb-auto-update-handler):
Remove argument.
(gdb-input): Automatically handles pending triggers. Update docstring.
(gdb-resync): Replace gdb-pending-triggers by gdb-handler-list.
(gdb-thread-exited, gdb-thread-selected, gdb-register-names-handler):
Update comments.
(gdb-done-or-error): Now use gdb-handle-reply.
| -rw-r--r-- | lisp/ChangeLog | 26 | ||||
| -rw-r--r-- | lisp/progmodes/gdb-mi.el | 245 |
2 files changed, 183 insertions, 88 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 1007517d29a..d1c27acff24 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -1,5 +1,31 @@ | |||
| 1 | 2013-05-14 Jean-Philippe Gravel <jpgravel@gmail.com> | 1 | 2013-05-14 Jean-Philippe Gravel <jpgravel@gmail.com> |
| 2 | 2 | ||
| 3 | * progmodes/gdb-mi.el: Fix non-responsive gud commands (bug#13845) | ||
| 4 | (gdb-handler-alist, gdb-handler-number): Remove variables. | ||
| 5 | (gdb-handler-list): New variable. | ||
| 6 | (gdb-add-handler, gdb-delete-handler, gdb-get-handler-function) | ||
| 7 | (gdb-pending-handler-p, gdb-handle-reply) | ||
| 8 | (gdb-remove-all-pending-triggers): New functions. | ||
| 9 | (gdb-discard-unordered-replies): New defcustom. | ||
| 10 | (gdb-handler): New defstruct. | ||
| 11 | (gdb-wait-for-pending): Fix invalid backquote. Use gdb-handler-list. | ||
| 12 | instead of gdb-pending-triggers. Update docstring. | ||
| 13 | (gdb-init-1): Remove dead variables. Initialize gdb-handler-list. | ||
| 14 | (gdb-speedbar-update, gdb-speedbar-timer-fn, gdb-var-update) | ||
| 15 | (gdb-var-update-handler, def-gdb-auto-update-trigger) | ||
| 16 | (def-gdb-auto-update-handler, gdb-get-changed-registers) | ||
| 17 | (gdb-changed-registers-handler, gdb-get-main-selected-frame) | ||
| 18 | (gdb-frame-handler): Pending triggers are now automatically managed. | ||
| 19 | (def-gdb-trigger-and-handler, def-gdb-auto-update-handler): | ||
| 20 | Remove argument. | ||
| 21 | (gdb-input): Automatically handles pending triggers. Update docstring. | ||
| 22 | (gdb-resync): Replace gdb-pending-triggers by gdb-handler-list. | ||
| 23 | (gdb-thread-exited, gdb-thread-selected, gdb-register-names-handler): | ||
| 24 | Update comments. | ||
| 25 | (gdb-done-or-error): Now use gdb-handle-reply. | ||
| 26 | |||
| 27 | 2013-05-14 Jean-Philippe Gravel <jpgravel@gmail.com> | ||
| 28 | |||
| 3 | * progmodes/gdb-mi.el (gdb-input): Include token numbers in | 29 | * progmodes/gdb-mi.el (gdb-input): Include token numbers in |
| 4 | gdb-debug-log. | 30 | gdb-debug-log. |
| 5 | 31 | ||
diff --git a/lisp/progmodes/gdb-mi.el b/lisp/progmodes/gdb-mi.el index 43eab07fb8d..2799eecb553 100644 --- a/lisp/progmodes/gdb-mi.el +++ b/lisp/progmodes/gdb-mi.el | |||
| @@ -91,7 +91,7 @@ | |||
| 91 | (require 'gud) | 91 | (require 'gud) |
| 92 | (require 'json) | 92 | (require 'json) |
| 93 | (require 'bindat) | 93 | (require 'bindat) |
| 94 | (eval-when-compile (require 'cl-lib)) | 94 | (require 'cl-lib) |
| 95 | 95 | ||
| 96 | (declare-function speedbar-change-initial-expansion-list | 96 | (declare-function speedbar-change-initial-expansion-list |
| 97 | "speedbar" (new-default)) | 97 | "speedbar" (new-default)) |
| @@ -206,8 +206,8 @@ Only used for files that Emacs can't find.") | |||
| 206 | (defvar gdb-last-command nil) | 206 | (defvar gdb-last-command nil) |
| 207 | (defvar gdb-prompt-name nil) | 207 | (defvar gdb-prompt-name nil) |
| 208 | (defvar gdb-token-number 0) | 208 | (defvar gdb-token-number 0) |
| 209 | (defvar gdb-handler-alist '()) | 209 | (defvar gdb-handler-list '() |
| 210 | (defvar gdb-handler-number nil) | 210 | "List of gdb-handler keeping track of all pending GDB commands.") |
| 211 | (defvar gdb-source-file-list nil | 211 | (defvar gdb-source-file-list nil |
| 212 | "List of source files for the current executable.") | 212 | "List of source files for the current executable.") |
| 213 | (defvar gdb-first-done-or-error t) | 213 | (defvar gdb-first-done-or-error t) |
| @@ -242,33 +242,114 @@ Possible values are these symbols: | |||
| 242 | disposition of output generated by commands that | 242 | disposition of output generated by commands that |
| 243 | gdb mode sends to gdb on its own behalf.") | 243 | gdb mode sends to gdb on its own behalf.") |
| 244 | 244 | ||
| 245 | ;; Pending triggers prevent congestion: Emacs won't send two similar | 245 | (defcustom gdb-discard-unordered-replies t |
| 246 | ;; consecutive requests. | 246 | "Non-nil means discard any out-of-order GDB replies. |
| 247 | 247 | This protects against lost GDB replies, assuming that GDB always | |
| 248 | (defvar gdb-pending-triggers '() | 248 | replies in the same order as Emacs sends commands. When receiving a |
| 249 | "A list of trigger functions which have not yet been handled. | 249 | reply with a given token-number, assume any pending messages with a |
| 250 | 250 | lower token-number are out-of-order." | |
| 251 | Elements are either function names or pairs (buffer . function)") | 251 | :type 'boolean |
| 252 | 252 | :group 'gud | |
| 253 | (defmacro gdb-add-pending (item) | 253 | :version "24.4") |
| 254 | `(push ,item gdb-pending-triggers)) | 254 | |
| 255 | (defmacro gdb-pending-p (item) | 255 | (cl-defstruct gdb-handler |
| 256 | `(member ,item gdb-pending-triggers)) | 256 | "Data required to handle the reply of a command sent to GDB." |
| 257 | (defmacro gdb-delete-pending (item) | 257 | ;; Prefix of the command sent to GDB. The GDB reply for this command |
| 258 | `(setq gdb-pending-triggers | 258 | ;; will be prefixed with this same TOKEN-NUMBER |
| 259 | (delete ,item gdb-pending-triggers))) | 259 | (token-number nil :read-only t) |
| 260 | ;; Callback to invoke when the reply is received from GDB | ||
| 261 | (function nil :read-only t) | ||
| 262 | ;; PENDING-TRIGGER is used to prevent congestion: Emacs won't send | ||
| 263 | ;; two requests with the same PENDING-TRIGGER until a reply is received | ||
| 264 | ;; for the first one." | ||
| 265 | (pending-trigger nil)) | ||
| 266 | |||
| 267 | (defun gdb-add-handler (token-number handler-function &optional pending-trigger) | ||
| 268 | "Insert a new GDB command handler in `gdb-handler-list'. | ||
| 269 | Handlers are used to keep track of the commands sent to GDB | ||
| 270 | and to handle the replies received. | ||
| 271 | Upon reception of a reply prefixed with TOKEN-NUMBER, | ||
| 272 | invoke the callback HANDLER-FUNCTION. | ||
| 273 | If PENDING-TRIGGER is specified, no new GDB commands will be | ||
| 274 | sent with this same PENDING-TRIGGER until a reply is received | ||
| 275 | for this handler." | ||
| 276 | |||
| 277 | (push (make-gdb-handler :token-number token-number | ||
| 278 | :function handler-function | ||
| 279 | :pending-trigger pending-trigger) | ||
| 280 | gdb-handler-list)) | ||
| 281 | |||
| 282 | (defun gdb-delete-handler (token-number) | ||
| 283 | "Remove the handler TOKEN-NUMBER from `gdb-handler-list'. | ||
| 284 | Additionally, if `gdb-discard-unordered-replies' is non-nil, | ||
| 285 | discard all handlers having a token number less than TOKEN-NUMBER." | ||
| 286 | (if gdb-discard-unordered-replies | ||
| 287 | |||
| 288 | (setq gdb-handler-list | ||
| 289 | (cl-delete-if | ||
| 290 | (lambda (handler) | ||
| 291 | "Discard any HANDLER with a token number `<=' than TOKEN-NUMBER." | ||
| 292 | (when (< (gdb-handler-token-number handler) token-number) | ||
| 293 | (message (format | ||
| 294 | "WARNING! Discarding GDB handler with token #%d\n" | ||
| 295 | (gdb-handler-token-number handler)))) | ||
| 296 | (<= (gdb-handler-token-number handler) token-number)) | ||
| 297 | gdb-handler-list)) | ||
| 298 | |||
| 299 | (setq gdb-handler-list | ||
| 300 | (cl-delete-if | ||
| 301 | (lambda (handler) | ||
| 302 | "Discard any HANDLER with a token number `eq' to TOKEN-NUMBER." | ||
| 303 | (eq (gdb-handler-token-number handler) token-number)) | ||
| 304 | gdb-handler-list)))) | ||
| 305 | |||
| 306 | (defun gdb-get-handler-function (token-number) | ||
| 307 | "Return the function callback registered with the handler TOKEN-NUMBER." | ||
| 308 | (gdb-handler-function | ||
| 309 | (cl-find-if (lambda (handler) (eq (gdb-handler-token-number handler) | ||
| 310 | token-number)) | ||
| 311 | gdb-handler-list))) | ||
| 312 | |||
| 313 | |||
| 314 | (defun gdb-pending-handler-p (pending-trigger) | ||
| 315 | "Return non-nil if a command handler is pending with trigger PENDING-TRIGGER." | ||
| 316 | (cl-find-if (lambda (handler) (eq (gdb-handler-pending-trigger handler) | ||
| 317 | pending-trigger)) | ||
| 318 | gdb-handler-list)) | ||
| 319 | |||
| 320 | |||
| 321 | (defun gdb-handle-reply (token-number) | ||
| 322 | "Handle the GDB reply TOKEN-NUMBER. | ||
| 323 | This invokes the handler registered with this token number | ||
| 324 | in `gdb-handler-list' and clears all pending handlers invalidated | ||
| 325 | by the reception of this reply." | ||
| 326 | (let ((handler-function (gdb-get-handler-function token-number))) | ||
| 327 | (when handler-function | ||
| 328 | (funcall handler-function) | ||
| 329 | (gdb-delete-handler token-number)))) | ||
| 330 | |||
| 331 | (defun gdb-remove-all-pending-triggers () | ||
| 332 | "Remove all pending triggers from gdb-handler-list. | ||
| 333 | The handlers are left in gdb-handler-list so that replies received | ||
| 334 | from GDB could still be handled. However, removing the pending triggers | ||
| 335 | allows Emacs to send new commands even if replies of previous commands | ||
| 336 | were not yet received." | ||
| 337 | (dolist (handler gdb-handler-list) | ||
| 338 | (setf (gdb-handler-pending-trigger handler) nil))) | ||
| 260 | 339 | ||
| 261 | (defmacro gdb-wait-for-pending (&rest body) | 340 | (defmacro gdb-wait-for-pending (&rest body) |
| 262 | "Wait until `gdb-pending-triggers' is empty and evaluate FORM. | 341 | "Wait for all pending GDB commands to finish and evaluate BODY. |
| 263 | 342 | ||
| 264 | This function checks `gdb-pending-triggers' value every | 343 | This function checks every 0.5 seconds if there are any pending |
| 265 | `gdb-wait-for-pending' seconds." | 344 | triggers in `gdb-handler-list'." |
| 266 | (run-with-timer | 345 | `(run-with-timer |
| 267 | 0.5 nil | 346 | 0.5 nil |
| 268 | `(lambda () | 347 | '(lambda () |
| 269 | (if (not gdb-pending-triggers) | 348 | (if (not (gdb-find-if (lambda (handler) |
| 270 | (progn ,@body) | 349 | (gdb-handler-pending-trigger handler)) |
| 271 | (gdb-wait-for-pending ,@body))))) | 350 | gdb-handler-list)) |
| 351 | (progn ,@body) | ||
| 352 | (gdb-wait-for-pending ,@body))))) | ||
| 272 | 353 | ||
| 273 | ;; Publish-subscribe | 354 | ;; Publish-subscribe |
| 274 | 355 | ||
| @@ -820,14 +901,12 @@ detailed description of this mode. | |||
| 820 | gdb-frame-number nil | 901 | gdb-frame-number nil |
| 821 | gdb-thread-number nil | 902 | gdb-thread-number nil |
| 822 | gdb-var-list nil | 903 | gdb-var-list nil |
| 823 | gdb-pending-triggers nil | ||
| 824 | gdb-output-sink 'user | 904 | gdb-output-sink 'user |
| 825 | gdb-location-alist nil | 905 | gdb-location-alist nil |
| 826 | gdb-source-file-list nil | 906 | gdb-source-file-list nil |
| 827 | gdb-last-command nil | 907 | gdb-last-command nil |
| 828 | gdb-token-number 0 | 908 | gdb-token-number 0 |
| 829 | gdb-handler-alist '() | 909 | gdb-handler-list '() |
| 830 | gdb-handler-number nil | ||
| 831 | gdb-prompt-name nil | 910 | gdb-prompt-name nil |
| 832 | gdb-first-done-or-error t | 911 | gdb-first-done-or-error t |
| 833 | gdb-buffer-fringe-width (car (window-fringes)) | 912 | gdb-buffer-fringe-width (car (window-fringes)) |
| @@ -1107,17 +1186,15 @@ With arg, enter name of variable to be watched in the minibuffer." | |||
| 1107 | (message-box "No symbol \"%s\" in current context." expr)))) | 1186 | (message-box "No symbol \"%s\" in current context." expr)))) |
| 1108 | 1187 | ||
| 1109 | (defun gdb-speedbar-update () | 1188 | (defun gdb-speedbar-update () |
| 1110 | (when (and (boundp 'speedbar-frame) (frame-live-p speedbar-frame) | 1189 | (when (and (boundp 'speedbar-frame) (frame-live-p speedbar-frame)) |
| 1111 | (not (gdb-pending-p 'gdb-speedbar-timer))) | ||
| 1112 | ;; Dummy command to update speedbar even when idle. | 1190 | ;; Dummy command to update speedbar even when idle. |
| 1113 | (gdb-input "-environment-pwd" 'gdb-speedbar-timer-fn) | 1191 | (gdb-input "-environment-pwd" |
| 1114 | ;; Keep gdb-pending-triggers non-nil till end. | 1192 | 'gdb-speedbar-timer-fn |
| 1115 | (gdb-add-pending 'gdb-speedbar-timer))) | 1193 | 'gdb-speedbar-update))) |
| 1116 | 1194 | ||
| 1117 | (defun gdb-speedbar-timer-fn () | 1195 | (defun gdb-speedbar-timer-fn () |
| 1118 | (if gdb-speedbar-auto-raise | 1196 | (if gdb-speedbar-auto-raise |
| 1119 | (raise-frame speedbar-frame)) | 1197 | (raise-frame speedbar-frame)) |
| 1120 | (gdb-delete-pending 'gdb-speedbar-timer) | ||
| 1121 | (speedbar-timer-fn)) | 1198 | (speedbar-timer-fn)) |
| 1122 | 1199 | ||
| 1123 | (defun gdb-var-evaluate-expression-handler (varnum changed) | 1200 | (defun gdb-var-evaluate-expression-handler (varnum changed) |
| @@ -1207,9 +1284,9 @@ With arg, enter name of variable to be watched in the minibuffer." | |||
| 1207 | 1284 | ||
| 1208 | ; Uses "-var-update --all-values". Needs GDB 6.4 onwards. | 1285 | ; Uses "-var-update --all-values". Needs GDB 6.4 onwards. |
| 1209 | (defun gdb-var-update () | 1286 | (defun gdb-var-update () |
| 1210 | (if (not (gdb-pending-p 'gdb-var-update)) | 1287 | (gdb-input "-var-update --all-values *" |
| 1211 | (gdb-input "-var-update --all-values *" 'gdb-var-update-handler)) | 1288 | 'gdb-var-update-handler |
| 1212 | (gdb-add-pending 'gdb-var-update)) | 1289 | 'gdb-var-update)) |
| 1213 | 1290 | ||
| 1214 | (defun gdb-var-update-handler () | 1291 | (defun gdb-var-update-handler () |
| 1215 | (let ((changelist (bindat-get-field (gdb-json-partial-output) 'changelist))) | 1292 | (let ((changelist (bindat-get-field (gdb-json-partial-output) 'changelist))) |
| @@ -1272,8 +1349,6 @@ With arg, enter name of variable to be watched in the minibuffer." | |||
| 1272 | (push var1 var-list)) | 1349 | (push var1 var-list)) |
| 1273 | (setq var1 (pop temp-var-list))) | 1350 | (setq var1 (pop temp-var-list))) |
| 1274 | (setq gdb-var-list (nreverse var-list)))))))) | 1351 | (setq gdb-var-list (nreverse var-list)))))))) |
| 1275 | (setq gdb-pending-triggers | ||
| 1276 | (delq 'gdb-var-update gdb-pending-triggers)) | ||
| 1277 | (gdb-speedbar-update)) | 1352 | (gdb-speedbar-update)) |
| 1278 | 1353 | ||
| 1279 | (defun gdb-speedbar-expand-node (text token indent) | 1354 | (defun gdb-speedbar-expand-node (text token indent) |
| @@ -1727,19 +1802,25 @@ All embedded quotes, newlines, and backslashes are preceded with a backslash." | |||
| 1727 | (setq string (replace-regexp-in-string "\n" "\\n" string t t)) | 1802 | (setq string (replace-regexp-in-string "\n" "\\n" string t t)) |
| 1728 | (concat "\"" string "\"")) | 1803 | (concat "\"" string "\"")) |
| 1729 | 1804 | ||
| 1730 | (defun gdb-input (command handler-function) | 1805 | (defun gdb-input (command handler-function &optional trigger-name) |
| 1731 | "Send COMMAND to GDB via the MI interface. | 1806 | "Send COMMAND to GDB via the MI interface. |
| 1732 | Run the function HANDLER-FUNCTION, with no arguments, once the command is | 1807 | Run the function HANDLER-FUNCTION, with no arguments, once the command is |
| 1733 | complete." | 1808 | complete. Do not send COMMAND to GDB if TRIGGER-NAME is non-nil and |
| 1734 | (setq gdb-token-number (1+ gdb-token-number)) | 1809 | Emacs is still waiting for a reply from another command previously |
| 1735 | (setq command (concat (number-to-string gdb-token-number) command)) | 1810 | sent with the same TRIGGER-NAME." |
| 1811 | (when (or (not trigger-name) | ||
| 1812 | (not (gdb-pending-handler-p trigger-name))) | ||
| 1813 | (setq gdb-token-number (1+ gdb-token-number)) | ||
| 1814 | (setq command (concat (number-to-string gdb-token-number) command)) | ||
| 1815 | |||
| 1816 | (if gdb-enable-debug (push (list 'send-item command handler-function) | ||
| 1817 | gdb-debug-log)) | ||
| 1736 | 1818 | ||
| 1737 | (if gdb-enable-debug (push (list 'send-item command handler-function) | 1819 | (gdb-add-handler gdb-token-number handler-function trigger-name) |
| 1738 | gdb-debug-log)) | 1820 | |
| 1739 | (push (cons gdb-token-number handler-function) gdb-handler-alist) | 1821 | (if gdbmi-debug-mode (message "gdb-input: %s" command)) |
| 1740 | (if gdbmi-debug-mode (message "gdb-input: %s" command)) | 1822 | (process-send-string (get-buffer-process gud-comint-buffer) |
| 1741 | (process-send-string (get-buffer-process gud-comint-buffer) | 1823 | (concat command "\n")))) |
| 1742 | (concat command "\n"))) | ||
| 1743 | 1824 | ||
| 1744 | ;; NOFRAME is used for gud execution control commands | 1825 | ;; NOFRAME is used for gud execution control commands |
| 1745 | (defun gdb-current-context-command (command) | 1826 | (defun gdb-current-context-command (command) |
| @@ -1775,7 +1856,7 @@ If `gdb-thread-number' is nil, just wrap NAME in asterisks." | |||
| 1775 | (defun gdb-resync() | 1856 | (defun gdb-resync() |
| 1776 | (setq gud-running nil) | 1857 | (setq gud-running nil) |
| 1777 | (setq gdb-output-sink 'user) | 1858 | (setq gdb-output-sink 'user) |
| 1778 | (setq gdb-pending-triggers nil)) | 1859 | (gdb-remove-all-pending-triggers)) |
| 1779 | 1860 | ||
| 1780 | (defun gdb-update (&optional no-proc) | 1861 | (defun gdb-update (&optional no-proc) |
| 1781 | "Update buffers showing status of debug session. | 1862 | "Update buffers showing status of debug session. |
| @@ -2256,9 +2337,9 @@ Unset `gdb-thread-number' if current thread exited and update threads list." | |||
| 2256 | (if (string= gdb-thread-number thread-id) | 2337 | (if (string= gdb-thread-number thread-id) |
| 2257 | (gdb-setq-thread-number nil)) | 2338 | (gdb-setq-thread-number nil)) |
| 2258 | ;; When we continue current thread and it quickly exits, | 2339 | ;; When we continue current thread and it quickly exits, |
| 2259 | ;; gdb-pending-triggers left after gdb-running disallow us to | 2340 | ;; the pending triggers in gdb-handler-list left after gdb-running |
| 2260 | ;; properly call -thread-info without --thread option. Thus we | 2341 | ;; disallow us to properly call -thread-info without --thread option. |
| 2261 | ;; need to use gdb-wait-for-pending. | 2342 | ;; Thus we need to use gdb-wait-for-pending. |
| 2262 | (gdb-wait-for-pending | 2343 | (gdb-wait-for-pending |
| 2263 | (gdb-emit-signal gdb-buf-publisher 'update-threads)))) | 2344 | (gdb-emit-signal gdb-buf-publisher 'update-threads)))) |
| 2264 | 2345 | ||
| @@ -2273,9 +2354,10 @@ Sets `gdb-thread-number' to new id." | |||
| 2273 | ;; by `=thread-selected` notification. `^done` causes `gdb-update` | 2354 | ;; by `=thread-selected` notification. `^done` causes `gdb-update` |
| 2274 | ;; as usually. Things happen to fast and second call (from | 2355 | ;; as usually. Things happen to fast and second call (from |
| 2275 | ;; gdb-thread-selected handler) gets cut off by our beloved | 2356 | ;; gdb-thread-selected handler) gets cut off by our beloved |
| 2276 | ;; gdb-pending-triggers. | 2357 | ;; pending triggers. |
| 2277 | ;; Solution is `gdb-wait-for-pending` macro: it guarantees that its | 2358 | ;; Solution is `gdb-wait-for-pending' macro: it guarantees that its |
| 2278 | ;; body will get executed when `gdb-pending-triggers` is empty. | 2359 | ;; body will get executed when `gdb-handler-list' if free of |
| 2360 | ;; pending triggers. | ||
| 2279 | (gdb-wait-for-pending | 2361 | (gdb-wait-for-pending |
| 2280 | (gdb-update)))) | 2362 | (gdb-update)))) |
| 2281 | 2363 | ||
| @@ -2439,10 +2521,7 @@ current thread and update GDB buffers." | |||
| 2439 | (when (and token-number is-complete) | 2521 | (when (and token-number is-complete) |
| 2440 | (with-current-buffer | 2522 | (with-current-buffer |
| 2441 | (gdb-get-buffer-create 'gdb-partial-output-buffer) | 2523 | (gdb-get-buffer-create 'gdb-partial-output-buffer) |
| 2442 | (funcall | 2524 | (gdb-handle-reply (string-to-number token-number)))) |
| 2443 | (cdr (assoc (string-to-number token-number) gdb-handler-alist)))) | ||
| 2444 | (setq gdb-handler-alist | ||
| 2445 | (assq-delete-all token-number gdb-handler-alist))) | ||
| 2446 | 2525 | ||
| 2447 | (when is-complete | 2526 | (when is-complete |
| 2448 | (gdb-clear-partial-output)))) | 2527 | (gdb-clear-partial-output)))) |
| @@ -2660,27 +2739,23 @@ trigger argument when describing buffer types with | |||
| 2660 | (when | 2739 | (when |
| 2661 | (or (not ,signal-list) | 2740 | (or (not ,signal-list) |
| 2662 | (memq signal ,signal-list)) | 2741 | (memq signal ,signal-list)) |
| 2663 | (when (not (gdb-pending-p | 2742 | (gdb-input ,gdb-command |
| 2664 | (cons (current-buffer) ',trigger-name))) | 2743 | (gdb-bind-function-to-buffer ',handler-name (current-buffer)) |
| 2665 | (gdb-input ,gdb-command | 2744 | (cons (current-buffer) ',trigger-name))))) |
| 2666 | (gdb-bind-function-to-buffer ',handler-name (current-buffer))) | ||
| 2667 | (gdb-add-pending (cons (current-buffer) ',trigger-name)))))) | ||
| 2668 | 2745 | ||
| 2669 | ;; Used by disassembly buffer only, the rest use | 2746 | ;; Used by disassembly buffer only, the rest use |
| 2670 | ;; def-gdb-trigger-and-handler | 2747 | ;; def-gdb-trigger-and-handler |
| 2671 | (defmacro def-gdb-auto-update-handler (handler-name trigger-name custom-defun | 2748 | (defmacro def-gdb-auto-update-handler (handler-name custom-defun |
| 2672 | &optional nopreserve) | 2749 | &optional nopreserve) |
| 2673 | "Define a handler HANDLER-NAME for TRIGGER-NAME with CUSTOM-DEFUN. | 2750 | "Define a handler HANDLER-NAME calling CUSTOM-DEFUN. |
| 2674 | 2751 | ||
| 2675 | Handlers are normally called from the buffers they put output in. | 2752 | Handlers are normally called from the buffers they put output in. |
| 2676 | 2753 | ||
| 2677 | Delete ((current-buffer) . TRIGGER-NAME) from | 2754 | Erase current buffer and evaluate CUSTOM-DEFUN. |
| 2678 | `gdb-pending-triggers', erase current buffer and evaluate | 2755 | Then call `gdb-update-buffer-name'. |
| 2679 | CUSTOM-DEFUN. Then `gdb-update-buffer-name' is called. | ||
| 2680 | 2756 | ||
| 2681 | If NOPRESERVE is non-nil, window point is not restored after CUSTOM-DEFUN." | 2757 | If NOPRESERVE is non-nil, window point is not restored after CUSTOM-DEFUN." |
| 2682 | `(defun ,handler-name () | 2758 | `(defun ,handler-name () |
| 2683 | (gdb-delete-pending (cons (current-buffer) ',trigger-name)) | ||
| 2684 | (let* ((inhibit-read-only t) | 2759 | (let* ((inhibit-read-only t) |
| 2685 | ,@(unless nopreserve | 2760 | ,@(unless nopreserve |
| 2686 | '((window (get-buffer-window (current-buffer) 0)) | 2761 | '((window (get-buffer-window (current-buffer) 0)) |
| @@ -2708,7 +2783,7 @@ See `def-gdb-auto-update-handler'." | |||
| 2708 | ,gdb-command | 2783 | ,gdb-command |
| 2709 | ,handler-name ,signal-list) | 2784 | ,handler-name ,signal-list) |
| 2710 | (def-gdb-auto-update-handler ,handler-name | 2785 | (def-gdb-auto-update-handler ,handler-name |
| 2711 | ,trigger-name ,custom-defun))) | 2786 | ,custom-defun))) |
| 2712 | 2787 | ||
| 2713 | 2788 | ||
| 2714 | 2789 | ||
| @@ -3625,7 +3700,6 @@ DOC is an optional documentation string." | |||
| 3625 | 3700 | ||
| 3626 | (def-gdb-auto-update-handler | 3701 | (def-gdb-auto-update-handler |
| 3627 | gdb-disassembly-handler | 3702 | gdb-disassembly-handler |
| 3628 | gdb-invalidate-disassembly | ||
| 3629 | gdb-disassembly-handler-custom | 3703 | gdb-disassembly-handler-custom |
| 3630 | t) | 3704 | t) |
| 3631 | 3705 | ||
| @@ -4117,21 +4191,19 @@ member." | |||
| 4117 | 4191 | ||
| 4118 | ;; Needs GDB 6.4 onwards (used to fail with no stack). | 4192 | ;; Needs GDB 6.4 onwards (used to fail with no stack). |
| 4119 | (defun gdb-get-changed-registers () | 4193 | (defun gdb-get-changed-registers () |
| 4120 | (when (and (gdb-get-buffer 'gdb-registers-buffer) | 4194 | (when (gdb-get-buffer 'gdb-registers-buffer) |
| 4121 | (not (gdb-pending-p 'gdb-get-changed-registers))) | ||
| 4122 | (gdb-input "-data-list-changed-registers" | 4195 | (gdb-input "-data-list-changed-registers" |
| 4123 | 'gdb-changed-registers-handler) | 4196 | 'gdb-changed-registers-handler |
| 4124 | (gdb-add-pending 'gdb-get-changed-registers))) | 4197 | 'gdb-get-changed-registers))) |
| 4125 | 4198 | ||
| 4126 | (defun gdb-changed-registers-handler () | 4199 | (defun gdb-changed-registers-handler () |
| 4127 | (gdb-delete-pending 'gdb-get-changed-registers) | ||
| 4128 | (setq gdb-changed-registers nil) | 4200 | (setq gdb-changed-registers nil) |
| 4129 | (dolist (register-number | 4201 | (dolist (register-number |
| 4130 | (bindat-get-field (gdb-json-partial-output) 'changed-registers)) | 4202 | (bindat-get-field (gdb-json-partial-output) 'changed-registers)) |
| 4131 | (push register-number gdb-changed-registers))) | 4203 | (push register-number gdb-changed-registers))) |
| 4132 | 4204 | ||
| 4133 | (defun gdb-register-names-handler () | 4205 | (defun gdb-register-names-handler () |
| 4134 | ;; Don't use gdb-pending-triggers because this handler is called | 4206 | ;; Don't use pending triggers because this handler is called |
| 4135 | ;; only once (in gdb-init-1) | 4207 | ;; only once (in gdb-init-1) |
| 4136 | (setq gdb-register-names nil) | 4208 | (setq gdb-register-names nil) |
| 4137 | (dolist (register-name | 4209 | (dolist (register-name |
| @@ -4155,16 +4227,13 @@ is set in them." | |||
| 4155 | (defun gdb-get-main-selected-frame () | 4227 | (defun gdb-get-main-selected-frame () |
| 4156 | "Trigger for `gdb-frame-handler' which uses main current thread. | 4228 | "Trigger for `gdb-frame-handler' which uses main current thread. |
| 4157 | Called from `gdb-update'." | 4229 | Called from `gdb-update'." |
| 4158 | (if (not (gdb-pending-p 'gdb-get-main-selected-frame)) | 4230 | (gdb-input (gdb-current-context-command "-stack-info-frame") |
| 4159 | (progn | 4231 | 'gdb-frame-handler |
| 4160 | (gdb-input (gdb-current-context-command "-stack-info-frame") | 4232 | 'gdb-get-main-selected-frame)) |
| 4161 | 'gdb-frame-handler) | ||
| 4162 | (gdb-add-pending 'gdb-get-main-selected-frame)))) | ||
| 4163 | 4233 | ||
| 4164 | (defun gdb-frame-handler () | 4234 | (defun gdb-frame-handler () |
| 4165 | "Set `gdb-selected-frame' and `gdb-selected-file' to show | 4235 | "Set `gdb-selected-frame' and `gdb-selected-file' to show |
| 4166 | overlay arrow in source buffer." | 4236 | overlay arrow in source buffer." |
| 4167 | (gdb-delete-pending 'gdb-get-main-selected-frame) | ||
| 4168 | (let ((frame (bindat-get-field (gdb-json-partial-output) 'frame))) | 4237 | (let ((frame (bindat-get-field (gdb-json-partial-output) 'frame))) |
| 4169 | (when frame | 4238 | (when frame |
| 4170 | (setq gdb-selected-frame (bindat-get-field frame 'func)) | 4239 | (setq gdb-selected-frame (bindat-get-field frame 'func)) |