diff options
| author | Dmitry Dzhus | 2009-08-04 15:07:23 +0000 |
|---|---|---|
| committer | Dmitry Dzhus | 2009-08-04 15:07:23 +0000 |
| commit | 4a31122c337fbc0c6242e624d9e26eb13b9cd5e0 (patch) | |
| tree | 77fbb6982dab49ea54137c8d82719d2308e1a0f1 | |
| parent | 4a6bcbc60243f18091b676b25cdff253515e0baa (diff) | |
| download | emacs-4a31122c337fbc0c6242e624d9e26eb13b9cd5e0.tar.gz emacs-4a31122c337fbc0c6242e624d9e26eb13b9cd5e0.zip | |
* progmodes/gud.el (gud-stop-subjob, gud-menu-map): Respect GDB
non-stop settings.
* progmodes/gdb-mi.el (gdb-thread-number): Initialize with nil.
(gdb-current-context-command): Do not append --thread if
`gdb-thread-number' is nil.
(gdb-running-threads-count, gdb-stopped-threads-count): New
variables.
(gdb-non-stop, gdb-gud-control-all-threads, gdb-switch-reasons)
(gdb-stopped-hooks, gdb-switch-when-another-stopped): New
customization options.
(gdb-gud-context-command, gdb-gud-context-call): New wrappers for
GUD commands.
(gdb): `gud-def' definitions changed to use `gdb-gud-context-call'
(gdb-init-1): Activate non-stop mode if `gdb-non-stop' is enabled.
(gdb-setq-thread-number, gdb-update-gud-running): New functions to
set `gdb-thread-number' and update `gud-running' properly.
(gdb-running): Update threads list when new threads appear.
(gdb-stopped): Support non-stop operation and new thread switching
logic.
(gdb-jsonify-buffer, gdb-json-read-buffer, gdb-json-string)
(gdb-json-partial-output): New set of JSON routines.
(def-gdb-auto-update-trigger): New `signal-list' optional
argument.
(gdb-thread-list-handler-custom): Update `gud-running',
`gdb-stopped-threads-count' and `gdb-running-threads-count'.
(def-gdb-thread-buffer-gdb-command, gdb-interrupt-thread)
(gdb-continue-thread, gdb-step-thread): New commands for fine
thread execution control.
(gud-menu-map): New menu items to switch non-stop options.
(gdb-reset): Cleanup `gdb-thread-position' overlay arrow marker.
| -rw-r--r-- | lisp/ChangeLog | 95 | ||||
| -rw-r--r-- | lisp/progmodes/gdb-mi.el | 543 | ||||
| -rw-r--r-- | lisp/progmodes/gud.el | 48 |
3 files changed, 520 insertions, 166 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index f7ee7f9b652..cebabd01b14 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -1,24 +1,52 @@ | |||
| 1 | 2009-08-04 Dmitry Dzhus <dima@sphinx.net.ru> | 1 | 2009-08-04 Dmitry Dzhus <dima@sphinx.net.ru> |
| 2 | 2 | ||
| 3 | * progmodes/gdb-mi.el Basic thread selection support. | 3 | * progmodes/gud.el (gud-stop-subjob, gud-menu-map): Respect GDB |
| 4 | (gdb-thread-number): New variable. | 4 | non-stop settings. |
| 5 | (gdb-current-context-command): New macro which adds --thread | 5 | |
| 6 | option to command. | 6 | * progmodes/gdb-mi.el (gdb-thread-number): Initialize with nil. |
| 7 | (gdb-threads-mode-map): Select thread with SPC | 7 | (gdb-current-context-command): Do not append --thread if |
| 8 | (gdb-thread-list-handler-custom): Mark current thread with overlay | 8 | `gdb-thread-number' is nil. |
| 9 | arrow. Synchronize GDB thread and Emacs thread. | 9 | (gdb-running-threads-count, gdb-stopped-threads-count): New |
| 10 | (gdb-select-thread): New command which selects current thread. | 10 | variables. |
| 11 | (gdb-invalidate-frames, gdb-invalidate-locals) | 11 | (gdb-non-stop, gdb-gud-control-all-threads, gdb-switch-reasons) |
| 12 | (gdb-invalidate-registers): Use --thread option. | 12 | (gdb-stopped-hooks, gdb-switch-when-another-stopped): New |
| 13 | (gdb-breakpoints-buffer-name,gdb-locals-buffer-name) | 13 | customization options. |
| 14 | (gdb-registers-buffer-name) | 14 | (gdb-gud-context-command, gdb-gud-context-call): New wrappers for |
| 15 | (gdb-memory-buffer-name, gdb-stack-buffer-name): Do not switch | 15 | GUD commands. |
| 16 | to (gud-comint-buffer) in *-buffer-name functions | 16 | (gdb): `gud-def' definitions changed to use `gdb-gud-context-call' |
| 17 | because (gdb-get-target-string) already does that. | 17 | (gdb-init-1): Activate non-stop mode if `gdb-non-stop' is enabled. |
| 18 | (gdb-locals-handler-custom, gdb-registers-handler-custom) | 18 | (gdb-setq-thread-number, gdb-update-gud-running): New functions to |
| 19 | (gdb-changed-registers-handler): Rewritten without regexps. | 19 | set `gdb-thread-number' and update `gud-running' properly. |
| 20 | (gdb-get-buffer, gdb-get-buffer-create, gdb-init-1) | 20 | (gdb-running): Update threads list when new threads appear. |
| 21 | (gdb-bind-function-to-buffer, gdb-add-subscriber) | 21 | (gdb-stopped): Support non-stop operation and new thread switching |
| 22 | logic. | ||
| 23 | (gdb-jsonify-buffer, gdb-json-read-buffer, gdb-json-string) | ||
| 24 | (gdb-json-partial-output): New set of JSON routines. | ||
| 25 | (def-gdb-auto-update-trigger): New `signal-list' optional | ||
| 26 | argument. | ||
| 27 | (gdb-thread-list-handler-custom): Update `gud-running', | ||
| 28 | `gdb-stopped-threads-count' and `gdb-running-threads-count'. | ||
| 29 | (def-gdb-thread-buffer-gdb-command, gdb-interrupt-thread) | ||
| 30 | (gdb-continue-thread, gdb-step-thread): New commands for fine | ||
| 31 | thread execution control. | ||
| 32 | (gud-menu-map): New menu items to switch non-stop options. | ||
| 33 | (gdb-reset): Cleanup `gdb-thread-position' overlay arrow marker. | ||
| 34 | |||
| 35 | * progmodes/gdb-mi.el (gdb-rules-name-maker) | ||
| 36 | (gdb-rules-buffer-mode, gdb-rules-update-trigger): Accessors for | ||
| 37 | gdb-buffer-rules. | ||
| 38 | (def-gdb-auto-update-handler): New nopreserve optional argument. | ||
| 39 | (gdb-stack-list-frames-custom): Print stack from top to bottom. | ||
| 40 | |||
| 41 | * progmodes/gdb-mi.el (gdb-pc-address): Removed unused variable. | ||
| 42 | (gdb-threads-list, gdb-breakpoints-list): New assoc lists. | ||
| 43 | (gdb-parent-mode): New mode to derive other GDB modes from. | ||
| 44 | (gdb-display-disassembly-for-thread) | ||
| 45 | (gdb-frame-disassembly-for-thread): New commands for threads | ||
| 46 | buffer. | ||
| 47 | |||
| 48 | * progmodes/gdb-mi.el (gdb-get-buffer, gdb-get-buffer-create) | ||
| 49 | (gdb-init-1, gdb-bind-function-to-buffer, gdb-add-subscriber) | ||
| 22 | (gdb-get-subscribers, gdb-emit-signal, gdb-buf-publisher) | 50 | (gdb-get-subscribers, gdb-emit-signal, gdb-buf-publisher) |
| 23 | (gdb-update): We now store all GDB buffers in a list so that they | 51 | (gdb-update): We now store all GDB buffers in a list so that they |
| 24 | can be updated by traversing a list instead of calling invalidate | 52 | can be updated by traversing a list instead of calling invalidate |
| @@ -35,16 +63,25 @@ | |||
| 35 | (gdb-frame-locals-for-thread, gdb-frame-registers-for-thread): New | 63 | (gdb-frame-locals-for-thread, gdb-frame-registers-for-thread): New |
| 36 | commands which show buffers bound to thread. | 64 | commands which show buffers bound to thread. |
| 37 | (gdb-stack-list-locals-regexp): Removed unused regexp. | 65 | (gdb-stack-list-locals-regexp): Removed unused regexp. |
| 38 | (gdb-pc-address): Removed unused variable. | 66 | |
| 39 | (gdb-threads-list, gdb-breakpoints-list): New assoc lists. | 67 | * progmodes/gdb-mi.el (gdb-breakpoints-buffer-name,gdb-locals-buffer-name) |
| 40 | (gdb-parent-mode): New mode to derive other GDB modes from. | 68 | (gdb-registers-buffer-name) |
| 41 | (gdb-display-disassembly-for-thread) | 69 | (gdb-memory-buffer-name, gdb-stack-buffer-name): Do not switch |
| 42 | (gdb-frame-disassembly-for-thread): New commands for threads | 70 | to (gud-comint-buffer) in *-buffer-name functions |
| 43 | buffer. | 71 | because (gdb-get-target-string) already does that. |
| 44 | (gdb-rules-name-maker, gdb-rules-buffer-mode) | 72 | (gdb-locals-handler-custom, gdb-registers-handler-custom) |
| 45 | (gdb-rules-update-trigger): Accessors for gdb-buffer-rules. | 73 | (gdb-changed-registers-handler): Rewritten without regexps. |
| 46 | (def-gdb-auto-update-handler): New nopreserve optional argument. | 74 | |
| 47 | (gdb-stack-list-frames-custom): Print stack from top to bottom. | 75 | * progmodes/gdb-mi.el Basic thread selection support. |
| 76 | (gdb-thread-number): New variable. | ||
| 77 | (gdb-current-context-command): New macro which adds --thread | ||
| 78 | option to command. | ||
| 79 | (gdb-threads-mode-map): Select thread with SPC | ||
| 80 | (gdb-thread-list-handler-custom): Mark current thread with overlay | ||
| 81 | arrow. Synchronize GDB thread and Emacs thread. | ||
| 82 | (gdb-select-thread): New command which selects current thread. | ||
| 83 | (gdb-invalidate-frames, gdb-invalidate-locals) | ||
| 84 | (gdb-invalidate-registers): Use --thread option. | ||
| 48 | 85 | ||
| 49 | 2009-08-04 Michael Albinus <michael.albinus@gmx.de> | 86 | 2009-08-04 Michael Albinus <michael.albinus@gmx.de> |
| 50 | 87 | ||
diff --git a/lisp/progmodes/gdb-mi.el b/lisp/progmodes/gdb-mi.el index 1f722264a34..4c3a8531a42 100644 --- a/lisp/progmodes/gdb-mi.el +++ b/lisp/progmodes/gdb-mi.el | |||
| @@ -116,16 +116,18 @@ | |||
| 116 | "Address of previous memory page for program memory buffer.") | 116 | "Address of previous memory page for program memory buffer.") |
| 117 | 117 | ||
| 118 | (defvar gdb-frame-number "0") | 118 | (defvar gdb-frame-number "0") |
| 119 | (defvar gdb-thread-number "1" | 119 | (defvar gdb-thread-number nil |
| 120 | "Main current thread. | 120 | "Main current thread. |
| 121 | 121 | ||
| 122 | Invalidation triggers use this variable to query GDB for | 122 | Invalidation triggers use this variable to query GDB for |
| 123 | information on the specified thread by wrapping GDB/MI commands | 123 | information on the specified thread by wrapping GDB/MI commands |
| 124 | in `gdb-current-context-command'. | 124 | in `gdb-current-context-command'. |
| 125 | 125 | ||
| 126 | This variable may be updated implicitly by GDB via | 126 | This variable may be updated implicitly by GDB via `gdb-stopped' |
| 127 | `gdb-thread-list-handler-custom' or explicitly by | 127 | or explicitly by `gdb-select-thread'. |
| 128 | `gdb-select-thread'.") | 128 | |
| 129 | Only `gdb-setq-thread-number' should be used to change this | ||
| 130 | value.") | ||
| 129 | 131 | ||
| 130 | ;; Used to show overlay arrow in source buffer. All set in | 132 | ;; Used to show overlay arrow in source buffer. All set in |
| 131 | ;; gdb-get-main-selected-frame. Disassembly buffer should not use | 133 | ;; gdb-get-main-selected-frame. Disassembly buffer should not use |
| @@ -141,14 +143,26 @@ This variable may be updated implicitly by GDB via | |||
| 141 | "Associative list of threads provided by \"-thread-info\" MI command. | 143 | "Associative list of threads provided by \"-thread-info\" MI command. |
| 142 | 144 | ||
| 143 | Keys are thread numbers (in strings) and values are structures as | 145 | Keys are thread numbers (in strings) and values are structures as |
| 144 | returned from -thread-info by `json-partial-output'. Updated in | 146 | returned from -thread-info by `gdb-json-partial-output'. Updated in |
| 145 | `gdb-thread-list-handler-custom'.") | 147 | `gdb-thread-list-handler-custom'.") |
| 146 | 148 | ||
| 149 | (defvar gdb-running-threads-count nil | ||
| 150 | "Number of currently running threads. | ||
| 151 | |||
| 152 | Nil means that no information is available. | ||
| 153 | |||
| 154 | Updated in `gdb-thread-list-handler-custom'.") | ||
| 155 | |||
| 156 | (defvar gdb-stopped-threads-count nil | ||
| 157 | "Number of currently stopped threads. | ||
| 158 | |||
| 159 | See also `gdb-running-threads-count'.") | ||
| 160 | |||
| 147 | (defvar gdb-breakpoints-list nil | 161 | (defvar gdb-breakpoints-list nil |
| 148 | "Associative list of breakpoints provided by \"-break-list\" MI command. | 162 | "Associative list of breakpoints provided by \"-break-list\" MI command. |
| 149 | 163 | ||
| 150 | Keys are breakpoint numbers (in string) and values are structures | 164 | Keys are breakpoint numbers (in string) and values are structures |
| 151 | as returned from \"-break-list\" by `json-partial-output' | 165 | as returned from \"-break-list\" by `gdb-json-partial-output' |
| 152 | \(\"body\" field is used). Updated in | 166 | \(\"body\" field is used). Updated in |
| 153 | `gdb-breakpoints-list-handler-custom'.") | 167 | `gdb-breakpoints-list-handler-custom'.") |
| 154 | 168 | ||
| @@ -226,6 +240,85 @@ Elements are either function names or pairs (buffer . function)") | |||
| 226 | (const :tag "Unlimited" nil)) | 240 | (const :tag "Unlimited" nil)) |
| 227 | :version "22.1") | 241 | :version "22.1") |
| 228 | 242 | ||
| 243 | (defcustom gdb-non-stop t | ||
| 244 | "When in non-stop mode, stopped threads can be examined while | ||
| 245 | other threads continue to execute." | ||
| 246 | :type 'boolean | ||
| 247 | :group 'gdb | ||
| 248 | :version "23.2") | ||
| 249 | |||
| 250 | ;; TODO Some commands can't be called with --all (give a notice about | ||
| 251 | ;; it in setting doc) | ||
| 252 | (defcustom gdb-gud-control-all-threads t | ||
| 253 | "When enabled, GUD execution commands affect all threads when | ||
| 254 | in non-stop mode. Otherwise, only currently selected thread is | ||
| 255 | affected." | ||
| 256 | :type 'boolean | ||
| 257 | :group 'gdb | ||
| 258 | :version "23.2") | ||
| 259 | |||
| 260 | (defcustom gdb-switch-reasons t | ||
| 261 | "List of stop reasons which cause Emacs to switch to the thread | ||
| 262 | which caused the stop. When t, switch to stopped thread no matter | ||
| 263 | what the reason was. When nil, never switch to stopped thread | ||
| 264 | automatically. | ||
| 265 | |||
| 266 | This setting is used in non-stop mode only. In all-stop mode, | ||
| 267 | Emacs always switches to the thread which caused the stop." | ||
| 268 | ;; exited, exited-normally and exited-signalled are not | ||
| 269 | ;; thread-specific stop reasons and therefore are not included in | ||
| 270 | ;; this list | ||
| 271 | :type '(choice | ||
| 272 | (const :tag "All reasons" t) | ||
| 273 | (set :tag "Selection of reasons..." | ||
| 274 | (const :tag "A breakpoint was reached." "breakpoint-hit") | ||
| 275 | (const :tag "A watchpoint was triggered." "watchpoint-trigger") | ||
| 276 | (const :tag "A read watchpoint was triggered." "read-watchpoint-trigger") | ||
| 277 | (const :tag "An access watchpoint was triggered." "access-watchpoint-trigger") | ||
| 278 | (const :tag "Function finished execution." "function-finished") | ||
| 279 | (const :tag "Location reached." "location-reached") | ||
| 280 | (const :tag "Watchpoint has gone out of scope" "watchpoint-scope") | ||
| 281 | (const :tag "End of stepping range reached." "end-stepping-range") | ||
| 282 | (const :tag "Signal received (like interruption)." "signal-received")) | ||
| 283 | (const :tag "None" nil)) | ||
| 284 | :group 'gdb | ||
| 285 | :version "23.2" | ||
| 286 | :link '(info-link "(gdb)GDB/MI Async Records")) | ||
| 287 | |||
| 288 | (defcustom gdb-stopped-hooks nil | ||
| 289 | "This variable holds a list of functions to be called whenever | ||
| 290 | GDB stops. | ||
| 291 | |||
| 292 | Each function takes one argument, a parsed MI response, which | ||
| 293 | contains fields of corresponding MI *stopped async record: | ||
| 294 | |||
| 295 | ((stopped-threads . \"all\") | ||
| 296 | (thread-id . \"1\") | ||
| 297 | (frame (line . \"38\") | ||
| 298 | (fullname . \"/home/sphinx/projects/gsoc/server.c\") | ||
| 299 | (file . \"server.c\") | ||
| 300 | (args ((value . \"0x804b038\") | ||
| 301 | (name . \"arg\"))) | ||
| 302 | (func . \"hello\") | ||
| 303 | (addr . \"0x0804869e\")) | ||
| 304 | (reason . \"end-stepping-range\")) | ||
| 305 | |||
| 306 | `gdb-get-field' may be used to access the fields of response. | ||
| 307 | |||
| 308 | Each function is called after the new current thread was selected | ||
| 309 | and GDB buffers were updated in `gdb-stopped'." | ||
| 310 | :type '(repeat function) | ||
| 311 | :group 'gdb | ||
| 312 | :version "23.2" | ||
| 313 | :link '(info-link "(gdb)GDB/MI Async Records")) | ||
| 314 | |||
| 315 | (defcustom gdb-switch-when-another-stopped t | ||
| 316 | "When nil, Emacs won't switch to stopped thread if some other | ||
| 317 | stopped thread is already selected." | ||
| 318 | :type 'boolean | ||
| 319 | :group 'gdb | ||
| 320 | :version "23.2") | ||
| 321 | |||
| 229 | (defvar gdb-debug-log nil | 322 | (defvar gdb-debug-log nil |
| 230 | "List of commands sent to and replies received from GDB. | 323 | "List of commands sent to and replies received from GDB. |
| 231 | Most recent commands are listed first. This list stores only the last | 324 | Most recent commands are listed first. This list stores only the last |
| @@ -329,6 +422,29 @@ the list) is deleted every time a new one is added (at the front)." | |||
| 329 | ) | 422 | ) |
| 330 | "Font lock keywords used in `gdb-local-mode'.") | 423 | "Font lock keywords used in `gdb-local-mode'.") |
| 331 | 424 | ||
| 425 | ;; noall is used for commands which don't take --all, but only | ||
| 426 | ;; --thread. | ||
| 427 | (defun gdb-gud-context-command (command &optional noall) | ||
| 428 | "When `gdb-non-stop' is t, add --thread option to COMMAND if | ||
| 429 | `gdb-gud-control-all-threads' is nil and --all option otherwise. | ||
| 430 | If NOALL is t, always add --thread option no matter what | ||
| 431 | `gdb-gud-control-all-threads' value is. | ||
| 432 | |||
| 433 | When `gdb-non-stop' is nil, return COMMAND unchanged." | ||
| 434 | (if gdb-non-stop | ||
| 435 | (if (and gdb-gud-control-all-threads | ||
| 436 | (not noall)) | ||
| 437 | (concat command " --all ") | ||
| 438 | (gdb-current-context-command command)) | ||
| 439 | command)) | ||
| 440 | |||
| 441 | ;; TODO Document this. We use noarg when not in gud-def | ||
| 442 | (defmacro gdb-gud-context-call (cmd1 &optional cmd2 noall noarg) | ||
| 443 | `(gud-call | ||
| 444 | (concat | ||
| 445 | (gdb-gud-context-command ,cmd1 ,noall) | ||
| 446 | ,cmd2) ,(when (not noarg) 'arg))) | ||
| 447 | |||
| 332 | ;;;###autoload | 448 | ;;;###autoload |
| 333 | (defun gdb (command-line) | 449 | (defun gdb (command-line) |
| 334 | "Run gdb on program FILE in buffer *gud-FILE*. | 450 | "Run gdb on program FILE in buffer *gud-FILE*. |
| @@ -404,27 +520,28 @@ detailed description of this mode. | |||
| 404 | (gud-def gud-pstar "print* %e" nil | 520 | (gud-def gud-pstar "print* %e" nil |
| 405 | "Evaluate C dereferenced pointer expression at point.") | 521 | "Evaluate C dereferenced pointer expression at point.") |
| 406 | 522 | ||
| 407 | (gud-def gud-step "-exec-step %p" "\C-s" | 523 | (gud-def gud-step (gdb-gud-context-call "-exec-step" "%p" t) |
| 524 | "\C-s" | ||
| 408 | "Step one source line with display.") | 525 | "Step one source line with display.") |
| 409 | (gud-def gud-stepi "-exec-step-instruction %p" "\C-i" | 526 | (gud-def gud-stepi (gdb-gud-context-call "-exec-step-instruction" "%p" t) |
| 527 | "\C-i" | ||
| 410 | "Step one instruction with display.") | 528 | "Step one instruction with display.") |
| 411 | (gud-def gud-next "-exec-next %p" "\C-n" | 529 | (gud-def gud-next (gdb-gud-context-call "-exec-next" "%p" t) |
| 530 | "\C-n" | ||
| 412 | "Step one line (skip functions).") | 531 | "Step one line (skip functions).") |
| 413 | (gud-def gud-nexti "nexti %p" nil | 532 | (gud-def gud-nexti (gdb-gud-context-call "-exec-next-instruction" "%p" t) |
| 533 | nil | ||
| 414 | "Step one instruction (skip functions).") | 534 | "Step one instruction (skip functions).") |
| 415 | (gud-def gud-cont "-exec-continue" "\C-r" | 535 | (gud-def gud-cont (gdb-gud-context-call "-exec-continue") |
| 536 | "\C-r" | ||
| 416 | "Continue with display.") | 537 | "Continue with display.") |
| 417 | (gud-def gud-finish "-exec-finish" "\C-f" | 538 | (gud-def gud-finish (gdb-gud-context-call "-exec-finish" nil t) |
| 539 | "\C-f" | ||
| 418 | "Finish executing current function.") | 540 | "Finish executing current function.") |
| 419 | (gud-def gud-run "-exec-run" nil "Runn the program.") | 541 | (gud-def gud-run "-exec-run" |
| 420 | 542 | nil | |
| 421 | (local-set-key "\C-i" 'gud-gdb-complete-command) | 543 | "Run the program.") |
| 422 | (setq gdb-first-prompt t) | ||
| 423 | (setq gud-running nil) | ||
| 424 | (gdb-update) | ||
| 425 | (run-hooks 'gdb-mode-hook)) | ||
| 426 | 544 | ||
| 427 | (defun gdb-init-1 () | ||
| 428 | (gud-def gud-break (if (not (string-match "Disassembly" mode-name)) | 545 | (gud-def gud-break (if (not (string-match "Disassembly" mode-name)) |
| 429 | (gud-call "break %f:%l" arg) | 546 | (gud-call "break %f:%l" arg) |
| 430 | (save-excursion | 547 | (save-excursion |
| @@ -432,7 +549,7 @@ detailed description of this mode. | |||
| 432 | (forward-char 2) | 549 | (forward-char 2) |
| 433 | (gud-call "break *%a" arg))) | 550 | (gud-call "break *%a" arg))) |
| 434 | "\C-b" "Set breakpoint at current line or address.") | 551 | "\C-b" "Set breakpoint at current line or address.") |
| 435 | ;; | 552 | |
| 436 | (gud-def gud-remove (if (not (string-match "Disassembly" mode-name)) | 553 | (gud-def gud-remove (if (not (string-match "Disassembly" mode-name)) |
| 437 | (gud-call "clear %f:%l" arg) | 554 | (gud-call "clear %f:%l" arg) |
| 438 | (save-excursion | 555 | (save-excursion |
| @@ -440,7 +557,8 @@ detailed description of this mode. | |||
| 440 | (forward-char 2) | 557 | (forward-char 2) |
| 441 | (gud-call "clear *%a" arg))) | 558 | (gud-call "clear *%a" arg))) |
| 442 | "\C-d" "Remove breakpoint at current line or address.") | 559 | "\C-d" "Remove breakpoint at current line or address.") |
| 443 | ;; | 560 | |
| 561 | ;; -exec-until doesn't support --all yet | ||
| 444 | (gud-def gud-until (if (not (string-match "Disassembly" mode-name)) | 562 | (gud-def gud-until (if (not (string-match "Disassembly" mode-name)) |
| 445 | (gud-call "-exec-until %f:%l" arg) | 563 | (gud-call "-exec-until %f:%l" arg) |
| 446 | (save-excursion | 564 | (save-excursion |
| @@ -448,9 +566,11 @@ detailed description of this mode. | |||
| 448 | (forward-char 2) | 566 | (forward-char 2) |
| 449 | (gud-call "-exec-until *%a" arg))) | 567 | (gud-call "-exec-until *%a" arg))) |
| 450 | "\C-u" "Continue to current line or address.") | 568 | "\C-u" "Continue to current line or address.") |
| 451 | ;; | 569 | ;; TODO Why arg here? |
| 452 | (gud-def | 570 | (gud-def |
| 453 | gud-go (gud-call (if gdb-active-process "-exec-continue" "-exec-run") arg) | 571 | gud-go (gud-call (if gdb-active-process |
| 572 | (gdb-gud-context-command "-exec-continue") | ||
| 573 | "-exec-run") arg) | ||
| 454 | nil "Start or continue execution.") | 574 | nil "Start or continue execution.") |
| 455 | 575 | ||
| 456 | ;; For debugging Emacs only. | 576 | ;; For debugging Emacs only. |
| @@ -488,7 +608,14 @@ detailed description of this mode. | |||
| 488 | 'gdb-mouse-jump) | 608 | 'gdb-mouse-jump) |
| 489 | (define-key gud-minor-mode-map [left-margin C-mouse-3] | 609 | (define-key gud-minor-mode-map [left-margin C-mouse-3] |
| 490 | 'gdb-mouse-jump) | 610 | 'gdb-mouse-jump) |
| 491 | ;; | 611 | |
| 612 | (local-set-key "\C-i" 'gud-gdb-complete-command) | ||
| 613 | (setq gdb-first-prompt t) | ||
| 614 | (setq gud-running nil) | ||
| 615 | (gdb-update) | ||
| 616 | (run-hooks 'gdb-mode-hook)) | ||
| 617 | |||
| 618 | (defun gdb-init-1 () | ||
| 492 | ;; (re-)initialise | 619 | ;; (re-)initialise |
| 493 | (setq gdb-selected-frame nil | 620 | (setq gdb-selected-frame nil |
| 494 | gdb-frame-number nil | 621 | gdb-frame-number nil |
| @@ -507,13 +634,15 @@ detailed description of this mode. | |||
| 507 | gdb-debug-log nil | 634 | gdb-debug-log nil |
| 508 | gdb-source-window nil | 635 | gdb-source-window nil |
| 509 | gdb-inferior-status nil | 636 | gdb-inferior-status nil |
| 510 | gdb-continuation nil) | 637 | gdb-continuation nil |
| 638 | gdb-buf-publisher '() | ||
| 639 | gdb-threads-list '() | ||
| 640 | gdb-breakpoints-list '()) | ||
| 511 | ;; | 641 | ;; |
| 512 | (setq gdb-buffer-type 'gdbmi) | 642 | (setq gdb-buffer-type 'gdbmi) |
| 513 | ;; | 643 | ;; |
| 514 | (gdb-force-mode-line-update | 644 | (gdb-force-mode-line-update |
| 515 | (propertize "initializing..." 'face font-lock-variable-name-face)) | 645 | (propertize "initializing..." 'face font-lock-variable-name-face)) |
| 516 | (setq gdb-buf-publisher '()) | ||
| 517 | (when gdb-use-separate-io-buffer | 646 | (when gdb-use-separate-io-buffer |
| 518 | (gdb-get-buffer-create 'gdb-inferior-io) | 647 | (gdb-get-buffer-create 'gdb-inferior-io) |
| 519 | (gdb-clear-inferior-io) | 648 | (gdb-clear-inferior-io) |
| @@ -526,6 +655,11 @@ detailed description of this mode. | |||
| 526 | (if (eq window-system 'w32) | 655 | (if (eq window-system 'w32) |
| 527 | (gdb-input (list "-gdb-set new-console off" 'ignore))) | 656 | (gdb-input (list "-gdb-set new-console off" 'ignore))) |
| 528 | (gdb-input (list "-gdb-set height 0" 'ignore)) | 657 | (gdb-input (list "-gdb-set height 0" 'ignore)) |
| 658 | |||
| 659 | (when gdb-non-stop | ||
| 660 | (gdb-input (list "-gdb-set non-stop 1" 'ignore)) | ||
| 661 | (gdb-input (list "-gdb-set target-async 1" 'ignore))) | ||
| 662 | |||
| 529 | ;; find source file and compilation directory here | 663 | ;; find source file and compilation directory here |
| 530 | (gdb-input | 664 | (gdb-input |
| 531 | ; Needs GDB 6.2 onwards. | 665 | ; Needs GDB 6.2 onwards. |
| @@ -944,11 +1078,14 @@ INDENT is the current indentation depth." | |||
| 944 | (assoc gdb-buffer-type gdb-buffer-rules)) | 1078 | (assoc gdb-buffer-type gdb-buffer-rules)) |
| 945 | 1079 | ||
| 946 | (defun gdb-current-buffer-thread () | 1080 | (defun gdb-current-buffer-thread () |
| 947 | "Get thread of current buffer from `gdb-threads-list'." | 1081 | "Get thread object of current buffer from `gdb-threads-list'. |
| 1082 | |||
| 1083 | When current buffer is not bound to any thread, return main | ||
| 1084 | thread." | ||
| 948 | (cdr (assoc gdb-thread-number gdb-threads-list))) | 1085 | (cdr (assoc gdb-thread-number gdb-threads-list))) |
| 949 | 1086 | ||
| 950 | (defun gdb-current-buffer-frame () | 1087 | (defun gdb-current-buffer-frame () |
| 951 | "Get current stack frame for thread of current buffer." | 1088 | "Get current stack frame object for thread of current buffer." |
| 952 | (gdb-get-field (gdb-current-buffer-thread) 'frame)) | 1089 | (gdb-get-field (gdb-current-buffer-thread) 'frame)) |
| 953 | 1090 | ||
| 954 | (defun gdb-get-buffer (key &optional thread) | 1091 | (defun gdb-get-buffer (key &optional thread) |
| @@ -1043,6 +1180,7 @@ DOC is an optional documentation string." | |||
| 1043 | 1180 | ||
| 1044 | (defun gdb-parent-mode () | 1181 | (defun gdb-parent-mode () |
| 1045 | "Generic mode to derive all other GDB buffer modes from." | 1182 | "Generic mode to derive all other GDB buffer modes from." |
| 1183 | (kill-all-local-variables) | ||
| 1046 | (setq buffer-read-only t) | 1184 | (setq buffer-read-only t) |
| 1047 | (buffer-disable-undo) | 1185 | (buffer-disable-undo) |
| 1048 | ;; Delete buffer from gdb-buf-publisher when it's killed | 1186 | ;; Delete buffer from gdb-buf-publisher when it's killed |
| @@ -1256,7 +1394,7 @@ static char *magick[] = { | |||
| 1256 | (let ((inhibit-read-only t)) | 1394 | (let ((inhibit-read-only t)) |
| 1257 | (remove-text-properties (point-min) (point-max) '(face)))) | 1395 | (remove-text-properties (point-min) (point-max) '(face)))) |
| 1258 | ;; mimic <RET> key to repeat previous command in GDB | 1396 | ;; mimic <RET> key to repeat previous command in GDB |
| 1259 | (if (not (string-match "^\\s+$" string)) | 1397 | (if (not (string= "" string)) |
| 1260 | (setq gdb-last-command string) | 1398 | (setq gdb-last-command string) |
| 1261 | (if gdb-last-command (setq string gdb-last-command))) | 1399 | (if gdb-last-command (setq string gdb-last-command))) |
| 1262 | (if gdb-enable-debug | 1400 | (if gdb-enable-debug |
| @@ -1285,8 +1423,11 @@ static char *magick[] = { | |||
| 1285 | (defun gdb-current-context-command (command) | 1423 | (defun gdb-current-context-command (command) |
| 1286 | "Add --thread option to gdb COMMAND. | 1424 | "Add --thread option to gdb COMMAND. |
| 1287 | 1425 | ||
| 1288 | Option value is taken from `gdb-thread-number'." | 1426 | Option value is taken from `gdb-thread-number'. If |
| 1289 | (concat command " --thread " gdb-thread-number)) | 1427 | `gdb-thread-number' is nil, COMMAND is returned unchanged." |
| 1428 | (if gdb-thread-number | ||
| 1429 | (concat command " --thread " gdb-thread-number " ") | ||
| 1430 | command)) | ||
| 1290 | 1431 | ||
| 1291 | (defun gdb-current-context-buffer-name (name) | 1432 | (defun gdb-current-context-buffer-name (name) |
| 1292 | "Add thread information and asterisks to string NAME." | 1433 | "Add thread information and asterisks to string NAME." |
| @@ -1343,15 +1484,15 @@ valid signal handlers.") | |||
| 1343 | (propertize "initializing..." 'face font-lock-variable-name-face)) | 1484 | (propertize "initializing..." 'face font-lock-variable-name-face)) |
| 1344 | (gdb-init-1) | 1485 | (gdb-init-1) |
| 1345 | (setq gdb-first-prompt nil)) | 1486 | (setq gdb-first-prompt nil)) |
| 1346 | ;; We may need to update gdb-thread-number and gdb-threads-list | 1487 | ;; We may need to update gdb-threads-list so we can use |
| 1347 | (gdb-get-buffer-create 'gdb-threads-buffer) | 1488 | (gdb-get-buffer-create 'gdb-threads-buffer) |
| 1348 | ;; gdb-break-list is maintained in breakpoints handler | 1489 | ;; gdb-break-list is maintained in breakpoints handler |
| 1349 | (gdb-get-buffer-create 'gdb-breakpoints-buffer) | 1490 | (gdb-get-buffer-create 'gdb-breakpoints-buffer) |
| 1350 | 1491 | ||
| 1351 | (gdb-get-main-selected-frame) | ||
| 1352 | |||
| 1353 | (gdb-emit-signal gdb-buf-publisher 'update) | 1492 | (gdb-emit-signal gdb-buf-publisher 'update) |
| 1354 | 1493 | ||
| 1494 | (gdb-get-main-selected-frame) | ||
| 1495 | |||
| 1355 | (gdb-get-changed-registers) | 1496 | (gdb-get-changed-registers) |
| 1356 | 1497 | ||
| 1357 | (when (and (boundp 'speedbar-frame) (frame-live-p speedbar-frame)) | 1498 | (when (and (boundp 'speedbar-frame) (frame-live-p speedbar-frame)) |
| @@ -1359,6 +1500,28 @@ valid signal handlers.") | |||
| 1359 | (setcar (nthcdr 5 var) nil)) | 1500 | (setcar (nthcdr 5 var) nil)) |
| 1360 | (gdb-var-update))) | 1501 | (gdb-var-update))) |
| 1361 | 1502 | ||
| 1503 | ;; gdb-setq-thread-number and gdb-update-gud-running are decoupled | ||
| 1504 | ;; because we may need to update current gud-running value without | ||
| 1505 | ;; changing current thread (see gdb-running) | ||
| 1506 | (defun gdb-setq-thread-number (number) | ||
| 1507 | "Set `gdb-thread-number' to NUMBER and update `gud-running'." | ||
| 1508 | (setq gdb-thread-number number) | ||
| 1509 | (gdb-update-gud-running)) | ||
| 1510 | |||
| 1511 | (defun gdb-update-gud-running () | ||
| 1512 | "Set `gud-running' according to the state of current thread. | ||
| 1513 | |||
| 1514 | Note that when `gdb-gud-control-all-threads' is t, `gud-running' | ||
| 1515 | cannot be reliably used to determine whether or not execution | ||
| 1516 | control buttons should be shown in menu or toolbar. Use | ||
| 1517 | `gdb-running-threads-count' and `gdb-stopped-threads-count' | ||
| 1518 | instead. | ||
| 1519 | |||
| 1520 | For all-stop mode, thread information is unavailable while target is running" | ||
| 1521 | (setq gud-running | ||
| 1522 | (string= (gdb-get-field (gdb-current-buffer-thread) 'state) | ||
| 1523 | "running"))) | ||
| 1524 | |||
| 1362 | ;; GUD displays the selected GDB frame. This might might not be the current | 1525 | ;; GUD displays the selected GDB frame. This might might not be the current |
| 1363 | ;; GDB frame (after up, down etc). If no GDB frame is visible but the last | 1526 | ;; GDB frame (after up, down etc). If no GDB frame is visible but the last |
| 1364 | ;; visited breakpoint is, use that window. | 1527 | ;; visited breakpoint is, use that window. |
| @@ -1385,7 +1548,7 @@ valid signal handlers.") | |||
| 1385 | (gdb-error . "\\([0-9]*\\)\\^error,\\(.*?\\)\n") | 1548 | (gdb-error . "\\([0-9]*\\)\\^error,\\(.*?\\)\n") |
| 1386 | (gdb-console . "~\\(\".*?\"\\)\n") | 1549 | (gdb-console . "~\\(\".*?\"\\)\n") |
| 1387 | (gdb-internals . "&\\(\".*?\"\\)\n") | 1550 | (gdb-internals . "&\\(\".*?\"\\)\n") |
| 1388 | (gdb-stopped . "\\*stopped,?\\(.*?\n\\)") | 1551 | (gdb-stopped . "\\*stopped,?\\(.*?\\)\n") |
| 1389 | (gdb-running . "\\*running,\\(.*?\n\\)") | 1552 | (gdb-running . "\\*running,\\(.*?\n\\)") |
| 1390 | (gdb-thread-created . "=thread-created,\\(.*?\n\\)") | 1553 | (gdb-thread-created . "=thread-created,\\(.*?\n\\)") |
| 1391 | (gdb-thread-exited . "=thread-exited,\\(.*?\n\\)"))) | 1554 | (gdb-thread-exited . "=thread-exited,\\(.*?\n\\)"))) |
| @@ -1446,15 +1609,20 @@ valid signal handlers.") | |||
| 1446 | gdb-filter-output)) | 1609 | gdb-filter-output)) |
| 1447 | 1610 | ||
| 1448 | (defun gdb-gdb (output-field)) | 1611 | (defun gdb-gdb (output-field)) |
| 1612 | |||
| 1613 | ;; gdb-invalidate-threads is defined to accept 'update-threads signal | ||
| 1449 | (defun gdb-thread-created (output-field)) | 1614 | (defun gdb-thread-created (output-field)) |
| 1450 | (defun gdb-thread-exited (output-field)) | 1615 | (defun gdb-thread-exited (output-field) |
| 1616 | (gdb-emit-signal gdb-buf-publisher 'update-threads)) | ||
| 1451 | 1617 | ||
| 1452 | (defun gdb-running (output-field) | 1618 | (defun gdb-running (output-field) |
| 1453 | (setq gdb-inferior-status "running") | 1619 | (setq gdb-inferior-status "running") |
| 1454 | (gdb-force-mode-line-update | 1620 | (gdb-force-mode-line-update |
| 1455 | (propertize gdb-inferior-status 'face font-lock-type-face)) | 1621 | (propertize gdb-inferior-status 'face font-lock-type-face)) |
| 1622 | (when (not gdb-non-stop) | ||
| 1623 | (setq gud-running t)) | ||
| 1456 | (setq gdb-active-process t) | 1624 | (setq gdb-active-process t) |
| 1457 | (setq gud-running t)) | 1625 | (gdb-emit-signal gdb-buf-publisher 'update-threads)) |
| 1458 | 1626 | ||
| 1459 | (defun gdb-starting (output-field) | 1627 | (defun gdb-starting (output-field) |
| 1460 | ;; CLI commands don't emit ^running at the moment so use gdb-running too. | 1628 | ;; CLI commands don't emit ^running at the moment so use gdb-running too. |
| @@ -1464,17 +1632,18 @@ valid signal handlers.") | |||
| 1464 | (gdb-force-mode-line-update | 1632 | (gdb-force-mode-line-update |
| 1465 | (propertize gdb-inferior-status 'face font-lock-type-face)) | 1633 | (propertize gdb-inferior-status 'face font-lock-type-face)) |
| 1466 | (setq gdb-active-process t) | 1634 | (setq gdb-active-process t) |
| 1467 | (setq gud-running t)) | 1635 | (when (not gdb-non-stop) |
| 1636 | (setq gud-running t))) | ||
| 1468 | 1637 | ||
| 1469 | ;; -break-insert -t didn't give a reason before gdb 6.9 | 1638 | ;; -break-insert -t didn't give a reason before gdb 6.9 |
| 1470 | (defconst gdb-stopped-regexp | ||
| 1471 | "\\(reason=\"\\(.*?\\)\"\\)?\\(\\(,exit-code=.*?\\)*\n\\|.*?,file=\".*?\".*?,fullname=\"\\(.*?\\)\".*?,line=\"\\(.*?\\)\".*?\n\\)") | ||
| 1472 | 1639 | ||
| 1473 | (defun gdb-stopped (output-field) | 1640 | (defun gdb-stopped (output-field) |
| 1474 | (setq gud-running nil) | 1641 | "Given the contents of *stopped MI async record, select new |
| 1475 | (string-match gdb-stopped-regexp output-field) | 1642 | current thread and update GDB buffers." |
| 1476 | (let ((reason (match-string 2 output-field)) | 1643 | ;; Reason is available with target-async only |
| 1477 | (file (match-string 5 output-field))) | 1644 | (let* ((result (gdb-json-string output-field)) |
| 1645 | (reason (gdb-get-field result 'reason)) | ||
| 1646 | (thread-id (gdb-get-field result 'thread-id))) | ||
| 1478 | 1647 | ||
| 1479 | ;;; Don't set gud-last-frame here as it's currently done in gdb-frame-handler | 1648 | ;;; Don't set gud-last-frame here as it's currently done in gdb-frame-handler |
| 1480 | ;;; because synchronous GDB doesn't give these fields with CLI. | 1649 | ;;; because synchronous GDB doesn't give these fields with CLI. |
| @@ -1485,16 +1654,42 @@ valid signal handlers.") | |||
| 1485 | ;;; (string-to-number | 1654 | ;;; (string-to-number |
| 1486 | ;;; (match-string 6 gud-marker-acc))))) | 1655 | ;;; (match-string 6 gud-marker-acc))))) |
| 1487 | 1656 | ||
| 1488 | (setq gdb-inferior-status (if reason reason "unknown")) | 1657 | (setq gdb-inferior-status (or reason "unknown")) |
| 1489 | (gdb-force-mode-line-update | 1658 | (gdb-force-mode-line-update |
| 1490 | (propertize gdb-inferior-status 'face font-lock-warning-face)) | 1659 | (propertize gdb-inferior-status 'face font-lock-warning-face)) |
| 1491 | (if (string-equal reason "exited-normally") | 1660 | (if (string-equal reason "exited-normally") |
| 1492 | (setq gdb-active-process nil))) | 1661 | (setq gdb-active-process nil)) |
| 1493 | 1662 | ||
| 1663 | ;; Select new current thread. | ||
| 1664 | |||
| 1665 | ;; Don't switch if we have no reasons selected | ||
| 1666 | (when gdb-switch-reasons | ||
| 1667 | ;; Switch from another stopped thread only if we have | ||
| 1668 | ;; gdb-switch-when-another-stopped: | ||
| 1669 | (when (or gdb-switch-when-another-stopped | ||
| 1670 | (not (string= "stopped" | ||
| 1671 | (gdb-get-field (gdb-current-buffer-thread) 'state)))) | ||
| 1672 | ;; Switch if current reason has been selected or we have no | ||
| 1673 | ;; reasons | ||
| 1674 | (if (or (eq gdb-switch-reasons t) | ||
| 1675 | (member reason gdb-switch-reasons)) | ||
| 1676 | (progn | ||
| 1677 | (gdb-setq-thread-number thread-id) | ||
| 1678 | (message (concat "Switched to thread " thread-id))) | ||
| 1679 | (message (format "Thread %s stopped" thread-id))))) | ||
| 1680 | |||
| 1681 | ;; Print "(gdb)" to GUD console | ||
| 1494 | (when gdb-first-done-or-error | 1682 | (when gdb-first-done-or-error |
| 1495 | (setq gdb-filter-output (concat gdb-filter-output gdb-prompt-name)) | 1683 | (setq gdb-filter-output (concat gdb-filter-output gdb-prompt-name))) |
| 1684 | |||
| 1685 | ;; In non-stop, we update information as soon as another thread gets | ||
| 1686 | ;; stopped | ||
| 1687 | (when (or gdb-first-done-or-error | ||
| 1688 | gdb-non-stop) | ||
| 1689 | ;; In all-stop this updates gud-running properly as well. | ||
| 1496 | (gdb-update) | 1690 | (gdb-update) |
| 1497 | (setq gdb-first-done-or-error nil))) | 1691 | (setq gdb-first-done-or-error nil)) |
| 1692 | (run-hook-with-args 'gdb-stopped-hook result))) | ||
| 1498 | 1693 | ||
| 1499 | ;; Remove the trimmings from log stream containing debugging messages | 1694 | ;; Remove the trimmings from log stream containing debugging messages |
| 1500 | ;; being produced by GDB's internals, use warning face and send to GUD | 1695 | ;; being produced by GDB's internals, use warning face and send to GUD |
| @@ -1571,8 +1766,11 @@ valid signal handlers.") | |||
| 1571 | (with-current-buffer (gdb-get-buffer-create 'gdb-partial-output-buffer) | 1766 | (with-current-buffer (gdb-get-buffer-create 'gdb-partial-output-buffer) |
| 1572 | (erase-buffer))) | 1767 | (erase-buffer))) |
| 1573 | 1768 | ||
| 1574 | (defun json-partial-output (&optional fix-key fix-list) | 1769 | (defun gdb-jsonify-buffer (&optional fix-key fix-list) |
| 1575 | "Parse gdb-partial-output-buffer with `json-read'. | 1770 | "Prepare GDB/MI output in current buffer for parsing with `json-read'. |
| 1771 | |||
| 1772 | Field names are wrapped in double quotes and equal signs are | ||
| 1773 | replaced with semicolons. | ||
| 1576 | 1774 | ||
| 1577 | If FIX-KEY is non-nil, strip all \"FIX-KEY=\" occurences from | 1775 | If FIX-KEY is non-nil, strip all \"FIX-KEY=\" occurences from |
| 1578 | partial output. This is used to get rid of useless keys in lists | 1776 | partial output. This is used to get rid of useless keys in lists |
| @@ -1583,20 +1781,17 @@ responses. | |||
| 1583 | If FIX-LIST is non-nil, \"FIX-LIST={..}\" is replaced with | 1781 | If FIX-LIST is non-nil, \"FIX-LIST={..}\" is replaced with |
| 1584 | \"FIX-LIST=[..]\" prior to parsing. This is used to fix broken | 1782 | \"FIX-LIST=[..]\" prior to parsing. This is used to fix broken |
| 1585 | -break-info output when it contains breakpoint script field | 1783 | -break-info output when it contains breakpoint script field |
| 1586 | incompatible with GDB/MI output syntax. | 1784 | incompatible with GDB/MI output syntax." |
| 1587 | 1785 | (save-excursion | |
| 1588 | Note that GDB/MI output syntax is different from JSON both | ||
| 1589 | cosmetically and (in some cases) structurally, so correct results | ||
| 1590 | are not guaranteed." | ||
| 1591 | (with-current-buffer (gdb-get-buffer-create 'gdb-partial-output-buffer) | ||
| 1592 | (goto-char (point-min)) | 1786 | (goto-char (point-min)) |
| 1593 | (when fix-key | 1787 | (when fix-key |
| 1594 | (save-excursion | 1788 | (save-excursion |
| 1595 | (while (re-search-forward (concat "[\\[,]\\(" fix-key "=\\)") nil t) | 1789 | (while (re-search-forward (concat "[\\[,]\\(" fix-key "=\\)") nil t) |
| 1596 | (replace-match "" nil nil nil 1)))) | 1790 | (replace-match "" nil nil nil 1)))) |
| 1791 | ;; Emacs bug #3794 | ||
| 1597 | (when fix-list | 1792 | (when fix-list |
| 1598 | (save-excursion | 1793 | (save-excursion |
| 1599 | ;; Find positions of brackets which enclose broken list | 1794 | ;; Find positions of braces which enclose broken list |
| 1600 | (while (re-search-forward (concat fix-list "={\"") nil t) | 1795 | (while (re-search-forward (concat fix-list "={\"") nil t) |
| 1601 | (let ((p1 (goto-char (- (point) 2))) | 1796 | (let ((p1 (goto-char (- (point) 2))) |
| 1602 | (p2 (progn (forward-sexp) | 1797 | (p2 (progn (forward-sexp) |
| @@ -1611,17 +1806,37 @@ are not guaranteed." | |||
| 1611 | (insert "]")))))) | 1806 | (insert "]")))))) |
| 1612 | (goto-char (point-min)) | 1807 | (goto-char (point-min)) |
| 1613 | (insert "{") | 1808 | (insert "{") |
| 1614 | ;; Wrap field names in double quotes and replace equal sign with | ||
| 1615 | ;; semicolon. | ||
| 1616 | ;; TODO: This breaks badly with foo= inside constants | 1809 | ;; TODO: This breaks badly with foo= inside constants |
| 1617 | (while (re-search-forward "\\([[:alpha:]-_]+\\)=" nil t) | 1810 | (while (re-search-forward "\\([[:alpha:]-_]+\\)=" nil t) |
| 1618 | (replace-match "\"\\1\":" nil nil)) | 1811 | (replace-match "\"\\1\":" nil nil)) |
| 1619 | (goto-char (point-max)) | 1812 | (goto-char (point-max)) |
| 1620 | (insert "}") | 1813 | (insert "}"))) |
| 1814 | |||
| 1815 | (defun gdb-json-read-buffer (&optional fix-key fix-list) | ||
| 1816 | "Prepare and parse GDB/MI output in current buffer with `json-read'. | ||
| 1817 | |||
| 1818 | FIX-KEY and FIX-LIST work as in `gdb-jsonify-buffer'." | ||
| 1819 | (gdb-jsonify-buffer fix-key fix-list) | ||
| 1820 | (save-excursion | ||
| 1621 | (goto-char (point-min)) | 1821 | (goto-char (point-min)) |
| 1622 | (let ((json-array-type 'list)) | 1822 | (let ((json-array-type 'list)) |
| 1623 | (json-read)))) | 1823 | (json-read)))) |
| 1624 | 1824 | ||
| 1825 | (defun gdb-json-string (string &optional fix-key fix-list) | ||
| 1826 | "Prepare and parse STRING containing GDB/MI output with `json-read'. | ||
| 1827 | |||
| 1828 | FIX-KEY and FIX-LIST work as in `gdb-jsonify-buffer'." | ||
| 1829 | (with-temp-buffer | ||
| 1830 | (insert string) | ||
| 1831 | (gdb-json-read-buffer fix-key fix-list))) | ||
| 1832 | |||
| 1833 | (defun gdb-json-partial-output (&optional fix-key fix-list) | ||
| 1834 | "Prepare and parse gdb-partial-output-buffer with `json-read'. | ||
| 1835 | |||
| 1836 | FIX-KEY and FIX-KEY work as in `gdb-jsonify-buffer'." | ||
| 1837 | (with-current-buffer (gdb-get-buffer-create 'gdb-partial-output-buffer) | ||
| 1838 | (gdb-json-read-buffer fix-key fix-list))) | ||
| 1839 | |||
| 1625 | (defun gdb-pad-string (string padding) | 1840 | (defun gdb-pad-string (string padding) |
| 1626 | (format (concat "%" (number-to-string padding) "s") string)) | 1841 | (format (concat "%" (number-to-string padding) "s") string)) |
| 1627 | 1842 | ||
| @@ -1634,29 +1849,35 @@ are not guaranteed." | |||
| 1634 | (setq values (append values (list (gdb-get-field struct field))))))) | 1849 | (setq values (append values (list (gdb-get-field struct field))))))) |
| 1635 | 1850 | ||
| 1636 | (defmacro def-gdb-auto-update-trigger (trigger-name gdb-command | 1851 | (defmacro def-gdb-auto-update-trigger (trigger-name gdb-command |
| 1637 | handler-name) | 1852 | handler-name |
| 1853 | &optional signal-list) | ||
| 1638 | "Define a trigger TRIGGER-NAME which sends GDB-COMMAND and sets | 1854 | "Define a trigger TRIGGER-NAME which sends GDB-COMMAND and sets |
| 1639 | HANDLER-NAME as its handler. HANDLER-NAME is bound to current | 1855 | HANDLER-NAME as its handler. HANDLER-NAME is bound to current |
| 1640 | buffer with `gdb-bind-function-to-buffer'. | 1856 | buffer with `gdb-bind-function-to-buffer'. |
| 1641 | 1857 | ||
| 1858 | If SIGNAL-LIST is non-nil, GDB-COMMAND is sent only when the | ||
| 1859 | defined trigger is called with an argument from SIGNAL-LIST. | ||
| 1860 | |||
| 1642 | Normally the trigger defined by this command must be called from | 1861 | Normally the trigger defined by this command must be called from |
| 1643 | the buffer where HANDLER-NAME must work. This should be done so | 1862 | the buffer where HANDLER-NAME must work. This should be done so |
| 1644 | that buffer-local thread number may be used in GDB-COMMAND (by | 1863 | that buffer-local thread number may be used in GDB-COMMAND (by |
| 1645 | calling `gdb-current-context-command'). | 1864 | calling `gdb-current-context-command'). |
| 1646 | `gdb-bind-function-to-buffer' is used to achieve this, see how | 1865 | `gdb-bind-function-to-buffer' is used to achieve this, see |
| 1647 | it's done in `gdb-get-buffer-create'. | 1866 | `gdb-get-buffer-create'. |
| 1648 | 1867 | ||
| 1649 | Triggers defined by this command are meant to be used as a | 1868 | Triggers defined by this command are meant to be used as a |
| 1650 | trigger argument when describing buffer types with | 1869 | trigger argument when describing buffer types with |
| 1651 | `gdb-set-buffer-rules'." | 1870 | `gdb-set-buffer-rules'." |
| 1652 | `(defun ,trigger-name (&optional signal) | 1871 | `(defun ,trigger-name (&optional signal) |
| 1653 | (if (not (gdb-pending-p | 1872 | (when |
| 1654 | (cons (current-buffer) ',trigger-name))) | 1873 | (or (not ,signal-list) |
| 1655 | (progn | 1874 | (memq signal ,signal-list)) |
| 1656 | (gdb-input | 1875 | (when (not (gdb-pending-p |
| 1657 | (list ,gdb-command | 1876 | (cons (current-buffer) ',trigger-name))) |
| 1658 | (gdb-bind-function-to-buffer ',handler-name (current-buffer)))) | 1877 | (gdb-input |
| 1659 | (gdb-add-pending (cons (current-buffer) ',trigger-name)))))) | 1878 | (list ,gdb-command |
| 1879 | (gdb-bind-function-to-buffer ',handler-name (current-buffer)))) | ||
| 1880 | (gdb-add-pending (cons (current-buffer) ',trigger-name)))))) | ||
| 1660 | 1881 | ||
| 1661 | ;; Used by disassembly buffer only, the rest use | 1882 | ;; Used by disassembly buffer only, the rest use |
| 1662 | ;; def-gdb-trigger-and-handler | 1883 | ;; def-gdb-trigger-and-handler |
| @@ -1665,9 +1886,9 @@ trigger argument when describing buffer types with | |||
| 1665 | 1886 | ||
| 1666 | Handlers are normally called from the buffers they put output in. | 1887 | Handlers are normally called from the buffers they put output in. |
| 1667 | 1888 | ||
| 1668 | Delete ((current-buffer) . TRIGGER) from `gdb-pending-triggers', | 1889 | Delete ((current-buffer) . TRIGGER-NAME) from |
| 1669 | erase current buffer and evaluate CUSTOM-DEFUN. Then | 1890 | `gdb-pending-triggers', erase current buffer and evaluate |
| 1670 | `gdb-update-buffer-name' is called. | 1891 | CUSTOM-DEFUN. Then `gdb-update-buffer-name' is called. |
| 1671 | 1892 | ||
| 1672 | If NOPRESERVE is non-nil, window point is not restored after CUSTOM-DEFUN." | 1893 | If NOPRESERVE is non-nil, window point is not restored after CUSTOM-DEFUN." |
| 1673 | `(defun ,handler-name () | 1894 | `(defun ,handler-name () |
| @@ -1684,18 +1905,19 @@ If NOPRESERVE is non-nil, window point is not restored after CUSTOM-DEFUN." | |||
| 1684 | '(set-window-point window p))))) | 1905 | '(set-window-point window p))))) |
| 1685 | 1906 | ||
| 1686 | (defmacro def-gdb-trigger-and-handler (trigger-name gdb-command | 1907 | (defmacro def-gdb-trigger-and-handler (trigger-name gdb-command |
| 1687 | handler-name custom-defun) | 1908 | handler-name custom-defun |
| 1909 | &optional signal-list) | ||
| 1688 | "Define trigger and handler. | 1910 | "Define trigger and handler. |
| 1689 | 1911 | ||
| 1690 | TRIGGER-NAME trigger is defined to send GDB-COMMAND. See | 1912 | TRIGGER-NAME trigger is defined to send GDB-COMMAND. See |
| 1691 | `def-gdb-auto-update-trigger'. | 1913 | `def-gdb-auto-update-trigger'. SIGNAL-LIST determines when |
| 1692 | 1914 | ||
| 1693 | HANDLER-NAME handler uses customization of CUSTOM-DEFUN. See | 1915 | HANDLER-NAME handler uses customization of CUSTOM-DEFUN. See |
| 1694 | `def-gdb-auto-update-handler'." | 1916 | `def-gdb-auto-update-handler'." |
| 1695 | `(progn | 1917 | `(progn |
| 1696 | (def-gdb-auto-update-trigger ,trigger-name | 1918 | (def-gdb-auto-update-trigger ,trigger-name |
| 1697 | ,gdb-command | 1919 | ,gdb-command |
| 1698 | ,handler-name) | 1920 | ,handler-name ,signal-list) |
| 1699 | (def-gdb-auto-update-handler ,handler-name | 1921 | (def-gdb-auto-update-handler ,handler-name |
| 1700 | ,trigger-name ,custom-defun))) | 1922 | ,trigger-name ,custom-defun))) |
| 1701 | 1923 | ||
| @@ -1714,7 +1936,7 @@ HANDLER-NAME handler uses customization of CUSTOM-DEFUN. See | |||
| 1714 | 1936 | ||
| 1715 | (defun gdb-breakpoints-list-handler-custom () | 1937 | (defun gdb-breakpoints-list-handler-custom () |
| 1716 | (let ((breakpoints-list (gdb-get-field | 1938 | (let ((breakpoints-list (gdb-get-field |
| 1717 | (json-partial-output "bkpt" "script") | 1939 | (gdb-json-partial-output "bkpt" "script") |
| 1718 | 'BreakpointTable 'body))) | 1940 | 'BreakpointTable 'body))) |
| 1719 | (setq gdb-breakpoints-list nil) | 1941 | (setq gdb-breakpoints-list nil) |
| 1720 | (insert "Num\tType\t\tDisp\tEnb\tHits\tAddr What\n") | 1942 | (insert "Num\tType\t\tDisp\tEnb\tHits\tAddr What\n") |
| @@ -1730,7 +1952,7 @@ HANDLER-NAME handler uses customization of CUSTOM-DEFUN. See | |||
| 1730 | (let ((flag (gdb-get-field breakpoint 'enabled))) | 1952 | (let ((flag (gdb-get-field breakpoint 'enabled))) |
| 1731 | (if (string-equal flag "y") | 1953 | (if (string-equal flag "y") |
| 1732 | (propertize "y" 'face font-lock-warning-face) | 1954 | (propertize "y" 'face font-lock-warning-face) |
| 1733 | (propertize "n" 'face font-lock-type-face))) "\t" | 1955 | (propertize "n" 'face font-lock-comment-face))) "\t" |
| 1734 | (gdb-get-field breakpoint 'times) "\t" | 1956 | (gdb-get-field breakpoint 'times) "\t" |
| 1735 | (gdb-get-field breakpoint 'addr))) | 1957 | (gdb-get-field breakpoint 'addr))) |
| 1736 | (let ((at (gdb-get-field breakpoint 'at))) | 1958 | (let ((at (gdb-get-field breakpoint 'at))) |
| @@ -2026,7 +2248,8 @@ FILE is a full path." | |||
| 2026 | 2248 | ||
| 2027 | (def-gdb-trigger-and-handler | 2249 | (def-gdb-trigger-and-handler |
| 2028 | gdb-invalidate-threads "-thread-info" | 2250 | gdb-invalidate-threads "-thread-info" |
| 2029 | gdb-thread-list-handler gdb-thread-list-handler-custom) | 2251 | gdb-thread-list-handler gdb-thread-list-handler-custom |
| 2252 | '(update update-threads)) | ||
| 2030 | 2253 | ||
| 2031 | (gdb-set-buffer-rules | 2254 | (gdb-set-buffer-rules |
| 2032 | 'gdb-threads-buffer | 2255 | 'gdb-threads-buffer |
| @@ -2037,20 +2260,24 @@ FILE is a full path." | |||
| 2037 | (defvar gdb-threads-font-lock-keywords | 2260 | (defvar gdb-threads-font-lock-keywords |
| 2038 | '(("in \\([^ ]+\\) (" (1 font-lock-function-name-face)) | 2261 | '(("in \\([^ ]+\\) (" (1 font-lock-function-name-face)) |
| 2039 | (" \\(stopped\\) in " (1 font-lock-warning-face)) | 2262 | (" \\(stopped\\) in " (1 font-lock-warning-face)) |
| 2263 | (" \\(running\\)" (1 font-lock-string-face)) | ||
| 2040 | ("\\(\\(\\sw\\|[_.]\\)+\\)=" (1 font-lock-variable-name-face))) | 2264 | ("\\(\\(\\sw\\|[_.]\\)+\\)=" (1 font-lock-variable-name-face))) |
| 2041 | "Font lock keywords used in `gdb-threads-mode'.") | 2265 | "Font lock keywords used in `gdb-threads-mode'.") |
| 2042 | 2266 | ||
| 2043 | (defvar gdb-threads-mode-map | 2267 | (defvar gdb-threads-mode-map |
| 2044 | (let ((map (make-sparse-keymap))) | 2268 | (let ((map (make-sparse-keymap))) |
| 2045 | (define-key map "\r" 'gdb-select-thread) | 2269 | (define-key map "\r" 'gdb-select-thread) |
| 2046 | (define-key map "s" 'gdb-display-stack-for-thread) | 2270 | (define-key map "f" 'gdb-display-stack-for-thread) |
| 2047 | (define-key map "S" 'gdb-frame-stack-for-thread) | 2271 | (define-key map "F" 'gdb-frame-stack-for-thread) |
| 2048 | (define-key map "l" 'gdb-display-locals-for-thread) | 2272 | (define-key map "l" 'gdb-display-locals-for-thread) |
| 2049 | (define-key map "L" 'gdb-frame-locals-for-thread) | 2273 | (define-key map "L" 'gdb-frame-locals-for-thread) |
| 2050 | (define-key map "r" 'gdb-display-registers-for-thread) | 2274 | (define-key map "r" 'gdb-display-registers-for-thread) |
| 2051 | (define-key map "R" 'gdb-frame-registers-for-thread) | 2275 | (define-key map "R" 'gdb-frame-registers-for-thread) |
| 2052 | (define-key map "d" 'gdb-display-disassembly-for-thread) | 2276 | (define-key map "d" 'gdb-display-disassembly-for-thread) |
| 2053 | (define-key map "D" 'gdb-frame-disassembly-for-thread) | 2277 | (define-key map "D" 'gdb-frame-disassembly-for-thread) |
| 2278 | (define-key map "i" 'gdb-interrupt-thread) | ||
| 2279 | (define-key map "c" 'gdb-continue-thread) | ||
| 2280 | (define-key map "s" 'gdb-step-thread) | ||
| 2054 | map)) | 2281 | map)) |
| 2055 | 2282 | ||
| 2056 | (defvar gdb-breakpoints-header | 2283 | (defvar gdb-breakpoints-header |
| @@ -2073,45 +2300,52 @@ FILE is a full path." | |||
| 2073 | 'gdb-invalidate-threads) | 2300 | 'gdb-invalidate-threads) |
| 2074 | 2301 | ||
| 2075 | (defun gdb-thread-list-handler-custom () | 2302 | (defun gdb-thread-list-handler-custom () |
| 2076 | (let* ((res (json-partial-output)) | 2303 | (let* ((res (gdb-json-partial-output)) |
| 2077 | (threads-list (gdb-get-field res 'threads)) | 2304 | (threads-list (gdb-get-field res 'threads))) |
| 2078 | (current-thread (gdb-get-field res 'current-thread-id))) | ||
| 2079 | (setq gdb-threads-list nil) | 2305 | (setq gdb-threads-list nil) |
| 2080 | (when (and current-thread | 2306 | (setq gdb-running-threads-count 0) |
| 2081 | (not (string-equal current-thread gdb-thread-number))) | 2307 | (setq gdb-stopped-threads-count 0) |
| 2082 | ;; Implicitly switch thread (in case previous one dies) | ||
| 2083 | (message (concat "GDB switched to another thread: " current-thread)) | ||
| 2084 | (setq gdb-thread-number current-thread)) | ||
| 2085 | (set-marker gdb-thread-position nil) | 2308 | (set-marker gdb-thread-position nil) |
| 2086 | (dolist (thread threads-list) | 2309 | |
| 2310 | (dolist (thread (reverse threads-list)) | ||
| 2311 | (let ((running (string-equal (gdb-get-field thread 'state) "running"))) | ||
| 2087 | (add-to-list 'gdb-threads-list | 2312 | (add-to-list 'gdb-threads-list |
| 2088 | (cons (gdb-get-field thread 'id) | 2313 | (cons (gdb-get-field thread 'id) |
| 2089 | thread)) | 2314 | thread)) |
| 2090 | (insert (apply 'format `("%s (%s) %s in %s " | 2315 | (if running |
| 2091 | ,@(gdb-get-many-fields thread 'id 'target-id 'state) | 2316 | (incf gdb-running-threads-count) |
| 2092 | ,(gdb-get-field thread 'frame 'func)))) | 2317 | (incf gdb-stopped-threads-count)) |
| 2093 | ;; Arguments | 2318 | |
| 2094 | (insert "(") | 2319 | (insert (apply 'format `("%s (%s) %s" |
| 2095 | (let ((args (gdb-get-field thread 'frame 'args))) | 2320 | ,@(gdb-get-many-fields thread 'id 'target-id 'state)))) |
| 2096 | (dolist (arg args) | 2321 | ;; Include frame information for stopped threads |
| 2097 | (insert (apply 'format `("%s=%s" ,@(gdb-get-many-fields arg 'name 'value))))) | 2322 | (when (not running) |
| 2098 | (when args (kill-backward-chars 1))) | 2323 | (insert (concat " in " (gdb-get-field thread 'frame 'func))) |
| 2099 | (insert ")") | 2324 | (insert " (") |
| 2100 | (gdb-insert-frame-location (gdb-get-field thread 'frame)) | 2325 | (let ((args (gdb-get-field thread 'frame 'args))) |
| 2101 | (insert (format " at %s" (gdb-get-field thread 'frame 'addr))) | 2326 | (dolist (arg args) |
| 2327 | (insert (apply 'format `("%s=%s," ,@(gdb-get-many-fields arg 'name 'value))))) | ||
| 2328 | (when args (kill-backward-chars 1))) | ||
| 2329 | (insert ")") | ||
| 2330 | (gdb-insert-frame-location (gdb-get-field thread 'frame)) | ||
| 2331 | (insert (format " at %s" (gdb-get-field thread 'frame 'addr)))) | ||
| 2102 | (add-text-properties (line-beginning-position) | 2332 | (add-text-properties (line-beginning-position) |
| 2103 | (line-end-position) | 2333 | (line-end-position) |
| 2104 | `(gdb-thread ,thread)) | 2334 | `(gdb-thread ,thread)) |
| 2335 | ;; We assume that gdb-thread-number is non-nil by this time | ||
| 2105 | (when (string-equal gdb-thread-number | 2336 | (when (string-equal gdb-thread-number |
| 2106 | (gdb-get-field thread 'id)) | 2337 | (gdb-get-field thread 'id)) |
| 2107 | (set-marker gdb-thread-position (line-beginning-position))) | 2338 | (set-marker gdb-thread-position (line-beginning-position)))) |
| 2108 | (newline)))) | 2339 | (newline)) |
| 2340 | ;; We update gud-running here because we need to make sure that | ||
| 2341 | ;; gdb-threads-list is up-to-date | ||
| 2342 | (gdb-update-gud-running))) | ||
| 2109 | 2343 | ||
| 2110 | (defmacro def-gdb-thread-buffer-command (name custom-defun &optional doc) | 2344 | (defmacro def-gdb-thread-buffer-command (name custom-defun &optional doc) |
| 2111 | "Define a NAME command which will act upon thread on the current line. | 2345 | "Define a NAME command which will act upon thread on the current line. |
| 2112 | 2346 | ||
| 2113 | CUSTOM-DEFUN may use locally bound `thread' variable, which will | 2347 | CUSTOM-DEFUN may use locally bound `thread' variable, which will |
| 2114 | be the value of 'gdb-thread propery of the current line. If | 2348 | be the value of 'gdb-thread property of the current line. If |
| 2115 | 'gdb-thread is nil, error is signaled." | 2349 | 'gdb-thread is nil, error is signaled." |
| 2116 | `(defun ,name () | 2350 | `(defun ,name () |
| 2117 | ,(when doc doc) | 2351 | ,(when doc doc) |
| @@ -2131,12 +2365,10 @@ on the current line." | |||
| 2131 | ,doc)) | 2365 | ,doc)) |
| 2132 | 2366 | ||
| 2133 | (def-gdb-thread-buffer-command gdb-select-thread | 2367 | (def-gdb-thread-buffer-command gdb-select-thread |
| 2134 | (if (string-equal (gdb-get-field thread 'state) "running") | 2368 | (let ((new-id (gdb-get-field thread 'id))) |
| 2135 | (error "Cannot select running thread") | 2369 | (gdb-setq-thread-number new-id) |
| 2136 | (let ((new-id (gdb-get-field thread 'id))) | 2370 | (gdb-input (list (concat "-thread-select " new-id) 'ignore)) |
| 2137 | (setq gdb-thread-number new-id) | 2371 | (gdb-update)) |
| 2138 | (gdb-input (list (concat "-thread-select " new-id) 'ignore)) | ||
| 2139 | (gdb-update))) | ||
| 2140 | "Select the thread at current line of threads buffer.") | 2372 | "Select the thread at current line of threads buffer.") |
| 2141 | 2373 | ||
| 2142 | (def-gdb-thread-simple-buffer-command | 2374 | (def-gdb-thread-simple-buffer-command |
| @@ -2183,6 +2415,34 @@ current line.") | |||
| 2183 | "Display a new frame with disassembly buffer for the thread at | 2415 | "Display a new frame with disassembly buffer for the thread at |
| 2184 | current line.") | 2416 | current line.") |
| 2185 | 2417 | ||
| 2418 | (defmacro def-gdb-thread-buffer-gdb-command (name gdb-command &optional doc) | ||
| 2419 | "Define a NAME which will execute send GDB-COMMAND with | ||
| 2420 | `gdb-thread-number' locally bound to id of thread on the current | ||
| 2421 | line." | ||
| 2422 | `(def-gdb-thread-buffer-command ,name | ||
| 2423 | (if gdb-non-stop | ||
| 2424 | (let ((gdb-thread-number (gdb-get-field thread 'id))) | ||
| 2425 | (gdb-input (list (gdb-current-context-command ,gdb-command) | ||
| 2426 | 'ignore))) | ||
| 2427 | (error "Available in non-stop mode only, customize gdb-non-stop.")) | ||
| 2428 | ,doc)) | ||
| 2429 | |||
| 2430 | ;; Does this make sense in all-stop mode? | ||
| 2431 | (def-gdb-thread-buffer-gdb-command | ||
| 2432 | gdb-interrupt-thread | ||
| 2433 | "-exec-interrupt" | ||
| 2434 | "Interrupt thread at current line.") | ||
| 2435 | |||
| 2436 | (def-gdb-thread-buffer-gdb-command | ||
| 2437 | gdb-continue-thread | ||
| 2438 | "-exec-continue" | ||
| 2439 | "Continue thread at current line.") | ||
| 2440 | |||
| 2441 | (def-gdb-thread-buffer-gdb-command | ||
| 2442 | gdb-step-thread | ||
| 2443 | "-exec-step" | ||
| 2444 | "Step thread at current line.") | ||
| 2445 | |||
| 2186 | 2446 | ||
| 2187 | ;;; Memory view | 2447 | ;;; Memory view |
| 2188 | 2448 | ||
| @@ -2255,7 +2515,7 @@ in `gdb-memory-format'." | |||
| 2255 | (error "Unknown format")))) | 2515 | (error "Unknown format")))) |
| 2256 | 2516 | ||
| 2257 | (defun gdb-read-memory-custom () | 2517 | (defun gdb-read-memory-custom () |
| 2258 | (let* ((res (json-partial-output)) | 2518 | (let* ((res (gdb-json-partial-output)) |
| 2259 | (err-msg (gdb-get-field res 'msg))) | 2519 | (err-msg (gdb-get-field res 'msg))) |
| 2260 | (if (not err-msg) | 2520 | (if (not err-msg) |
| 2261 | (let ((memory (gdb-get-field res 'memory))) | 2521 | (let ((memory (gdb-get-field res 'memory))) |
| @@ -2635,6 +2895,7 @@ DOC is an optional documentation string." | |||
| 2635 | "Major mode for GDB disassembly information. | 2895 | "Major mode for GDB disassembly information. |
| 2636 | 2896 | ||
| 2637 | \\{gdb-disassembly-mode-map}" | 2897 | \\{gdb-disassembly-mode-map}" |
| 2898 | ;; TODO Rename overlay variable for disassembly mode | ||
| 2638 | (add-to-list 'overlay-arrow-variable-list 'gdb-overlay-arrow-position) | 2899 | (add-to-list 'overlay-arrow-variable-list 'gdb-overlay-arrow-position) |
| 2639 | (setq fringes-outside-margins t) | 2900 | (setq fringes-outside-margins t) |
| 2640 | (setq gdb-overlay-arrow-position (make-marker)) | 2901 | (setq gdb-overlay-arrow-position (make-marker)) |
| @@ -2646,7 +2907,7 @@ DOC is an optional documentation string." | |||
| 2646 | (defun gdb-disassembly-handler-custom () | 2907 | (defun gdb-disassembly-handler-custom () |
| 2647 | (let* ((pos 1) | 2908 | (let* ((pos 1) |
| 2648 | (address (gdb-get-field (gdb-current-buffer-frame) 'addr)) | 2909 | (address (gdb-get-field (gdb-current-buffer-frame) 'addr)) |
| 2649 | (res (json-partial-output)) | 2910 | (res (gdb-json-partial-output)) |
| 2650 | (instructions (gdb-get-field res 'asm_insns)) | 2911 | (instructions (gdb-get-field res 'asm_insns)) |
| 2651 | (last-instr (car (last instructions))) | 2912 | (last-instr (car (last instructions))) |
| 2652 | (column-padding (+ 2 (string-width | 2913 | (column-padding (+ 2 (string-width |
| @@ -2783,7 +3044,7 @@ member." | |||
| 2783 | (from (insert (format " of %s" from)))))) | 3044 | (from (insert (format " of %s" from)))))) |
| 2784 | 3045 | ||
| 2785 | (defun gdb-stack-list-frames-custom () | 3046 | (defun gdb-stack-list-frames-custom () |
| 2786 | (let* ((res (json-partial-output "frame")) | 3047 | (let* ((res (gdb-json-partial-output "frame")) |
| 2787 | (stack (gdb-get-field res 'stack))) | 3048 | (stack (gdb-get-field res 'stack))) |
| 2788 | (dolist (frame stack) | 3049 | (dolist (frame stack) |
| 2789 | (insert (apply 'format `("%s in %s" ,@(gdb-get-many-fields frame 'level 'func)))) | 3050 | (insert (apply 'format `("%s in %s" ,@(gdb-get-many-fields frame 'level 'func)))) |
| @@ -2904,7 +3165,7 @@ member." | |||
| 2904 | ;; Dont display values of arrays or structures. | 3165 | ;; Dont display values of arrays or structures. |
| 2905 | ;; These can be expanded using gud-watch. | 3166 | ;; These can be expanded using gud-watch. |
| 2906 | (defun gdb-locals-handler-custom () | 3167 | (defun gdb-locals-handler-custom () |
| 2907 | (let ((locals-list (gdb-get-field (json-partial-output) 'locals))) | 3168 | (let ((locals-list (gdb-get-field (gdb-json-partial-output) 'locals))) |
| 2908 | (dolist (local locals-list) | 3169 | (dolist (local locals-list) |
| 2909 | (let ((name (gdb-get-field local 'name)) | 3170 | (let ((name (gdb-get-field local 'name)) |
| 2910 | (value (gdb-get-field local 'value)) | 3171 | (value (gdb-get-field local 'value)) |
| @@ -2981,7 +3242,7 @@ member." | |||
| 2981 | 'gdb-invalidate-registers) | 3242 | 'gdb-invalidate-registers) |
| 2982 | 3243 | ||
| 2983 | (defun gdb-registers-handler-custom () | 3244 | (defun gdb-registers-handler-custom () |
| 2984 | (let ((register-values (gdb-get-field (json-partial-output) 'register-values)) | 3245 | (let ((register-values (gdb-get-field (gdb-json-partial-output) 'register-values)) |
| 2985 | (register-names-list (reverse gdb-register-names))) | 3246 | (register-names-list (reverse gdb-register-names))) |
| 2986 | (dolist (register register-values) | 3247 | (dolist (register register-values) |
| 2987 | (let* ((register-number (gdb-get-field register 'number)) | 3248 | (let* ((register-number (gdb-get-field register 'number)) |
| @@ -3039,14 +3300,14 @@ member." | |||
| 3039 | (defun gdb-changed-registers-handler () | 3300 | (defun gdb-changed-registers-handler () |
| 3040 | (gdb-delete-pending 'gdb-get-changed-registers) | 3301 | (gdb-delete-pending 'gdb-get-changed-registers) |
| 3041 | (setq gdb-changed-registers nil) | 3302 | (setq gdb-changed-registers nil) |
| 3042 | (dolist (register-number (gdb-get-field (json-partial-output) 'changed-registers)) | 3303 | (dolist (register-number (gdb-get-field (gdb-json-partial-output) 'changed-registers)) |
| 3043 | (push register-number gdb-changed-registers))) | 3304 | (push register-number gdb-changed-registers))) |
| 3044 | 3305 | ||
| 3045 | (defun gdb-register-names-handler () | 3306 | (defun gdb-register-names-handler () |
| 3046 | ;; Don't use gdb-pending-triggers because this handler is called | 3307 | ;; Don't use gdb-pending-triggers because this handler is called |
| 3047 | ;; only once (in gdb-init-1) | 3308 | ;; only once (in gdb-init-1) |
| 3048 | (setq gdb-register-names nil) | 3309 | (setq gdb-register-names nil) |
| 3049 | (dolist (register-name (gdb-get-field (json-partial-output) 'register-names)) | 3310 | (dolist (register-name (gdb-get-field (gdb-json-partial-output) 'register-names)) |
| 3050 | (push register-name gdb-register-names)) | 3311 | (push register-name gdb-register-names)) |
| 3051 | (setq gdb-register-names (reverse gdb-register-names))) | 3312 | (setq gdb-register-names (reverse gdb-register-names))) |
| 3052 | 3313 | ||
| @@ -3078,7 +3339,7 @@ thread. Called from `gdb-update'." | |||
| 3078 | "Sets `gdb-pc-address', `gdb-selected-frame' and | 3339 | "Sets `gdb-pc-address', `gdb-selected-frame' and |
| 3079 | `gdb-selected-file' to show overlay arrow in source buffer." | 3340 | `gdb-selected-file' to show overlay arrow in source buffer." |
| 3080 | (gdb-delete-pending 'gdb-get-main-selected-frame) | 3341 | (gdb-delete-pending 'gdb-get-main-selected-frame) |
| 3081 | (let ((frame (gdb-get-field (json-partial-output) 'frame))) | 3342 | (let ((frame (gdb-get-field (gdb-json-partial-output) 'frame))) |
| 3082 | (when frame | 3343 | (when frame |
| 3083 | (setq gdb-frame-number (gdb-get-field frame 'level)) | 3344 | (setq gdb-frame-number (gdb-get-field frame 'level)) |
| 3084 | (setq gdb-selected-frame (gdb-get-field frame 'func)) | 3345 | (setq gdb-selected-frame (gdb-get-field frame 'func)) |
| @@ -3165,9 +3426,8 @@ thread. Called from `gdb-update'." | |||
| 3165 | (define-key menu [breakpoints] | 3426 | (define-key menu [breakpoints] |
| 3166 | '("Breakpoints" . gdb-frame-breakpoints-buffer))) | 3427 | '("Breakpoints" . gdb-frame-breakpoints-buffer))) |
| 3167 | 3428 | ||
| 3168 | (let ((menu (make-sparse-keymap "GDB-MI"))) | 3429 | (let ((menu (make-sparse-keymap "GDB-MI")) |
| 3169 | (define-key gud-menu-map [mi] | 3430 | (submenu (make-sparse-keymap "GUD thread control mode"))) |
| 3170 | `(menu-item "GDB-MI" ,menu :visible (eq gud-minor-mode 'gdbmi))) | ||
| 3171 | (define-key menu [gdb-customize] | 3431 | (define-key menu [gdb-customize] |
| 3172 | '(menu-item "Customize" (lambda () (interactive) (customize-group 'gdb)) | 3432 | '(menu-item "Customize" (lambda () (interactive) (customize-group 'gdb)) |
| 3173 | :help "Customize Gdb Graphical Mode options.")) | 3433 | :help "Customize Gdb Graphical Mode options.")) |
| @@ -3177,7 +3437,37 @@ thread. Called from `gdb-update'." | |||
| 3177 | :button (:toggle . gdb-many-windows))) | 3437 | :button (:toggle . gdb-many-windows))) |
| 3178 | (define-key menu [gdb-restore-windows] | 3438 | (define-key menu [gdb-restore-windows] |
| 3179 | '(menu-item "Restore Window Layout" gdb-restore-windows | 3439 | '(menu-item "Restore Window Layout" gdb-restore-windows |
| 3180 | :help "Restore standard layout for debug session."))) | 3440 | :help "Restore standard layout for debug session.")) |
| 3441 | (define-key menu [sep1] | ||
| 3442 | '(menu-item "--")) | ||
| 3443 | (define-key submenu [all-threads] | ||
| 3444 | '(menu-item "All threads" | ||
| 3445 | (lambda () | ||
| 3446 | (interactive) | ||
| 3447 | (setq gdb-gud-control-all-threads t)) | ||
| 3448 | :help "GUD start/stop commands apply to all threads" | ||
| 3449 | :button (:radio . gdb-gud-control-all-threads))) | ||
| 3450 | (define-key submenu [current-thread] | ||
| 3451 | '(menu-item "Current thread" | ||
| 3452 | (lambda () | ||
| 3453 | (interactive) | ||
| 3454 | (setq gdb-gud-control-all-threads nil)) | ||
| 3455 | :help "GUD start/stop commands apply to current thread only" | ||
| 3456 | :button (:radio . (not gdb-gud-control-all-threads)))) | ||
| 3457 | (define-key menu [thread-control] | ||
| 3458 | `("GUD thread control mode" . ,submenu)) | ||
| 3459 | (define-key gud-menu-map [mi] | ||
| 3460 | `(menu-item "GDB-MI" ,menu :visible (eq gud-minor-mode 'gdbmi))) | ||
| 3461 | (define-key menu [gdb-switch-when-another-stopped] | ||
| 3462 | (menu-bar-make-toggle gdb-toggle-switch-when-another-stopped gdb-switch-when-another-stopped | ||
| 3463 | "Automatically switch to stopped thread" | ||
| 3464 | "GDB thread switching %s" | ||
| 3465 | "Switch to stopped thread")) | ||
| 3466 | (define-key menu [gdb-non-stop] | ||
| 3467 | (menu-bar-make-toggle gdb-toggle-non-stop gdb-non-stop | ||
| 3468 | "Non-stop mode" | ||
| 3469 | "GDB non-stop mode %s" | ||
| 3470 | "Allow examining stopped threads while others continue to execute"))) | ||
| 3181 | 3471 | ||
| 3182 | (defun gdb-frame-gdb-buffer () | 3472 | (defun gdb-frame-gdb-buffer () |
| 3183 | "Display GUD buffer in a new frame." | 3473 | "Display GUD buffer in a new frame." |
| @@ -3299,6 +3589,9 @@ Kills the gdb buffers, and resets variables and the source buffers." | |||
| 3299 | (setq gdb-stack-position nil) | 3589 | (setq gdb-stack-position nil) |
| 3300 | (setq overlay-arrow-variable-list | 3590 | (setq overlay-arrow-variable-list |
| 3301 | (delq 'gdb-stack-position overlay-arrow-variable-list)) | 3591 | (delq 'gdb-stack-position overlay-arrow-variable-list)) |
| 3592 | (setq gdb-thread-position nil) | ||
| 3593 | (setq overlay-arrow-variable-list | ||
| 3594 | (delq 'gdb-thread-position overlay-arrow-variable-list)) | ||
| 3302 | (if (boundp 'speedbar-frame) (speedbar-timer-fn)) | 3595 | (if (boundp 'speedbar-frame) (speedbar-timer-fn)) |
| 3303 | (setq gud-running nil) | 3596 | (setq gud-running nil) |
| 3304 | (setq gdb-active-process nil) | 3597 | (setq gdb-active-process nil) |
diff --git a/lisp/progmodes/gud.el b/lisp/progmodes/gud.el index c20f5adeefc..e31ec2b0883 100644 --- a/lisp/progmodes/gud.el +++ b/lisp/progmodes/gud.el | |||
| @@ -136,11 +136,14 @@ Used to grey out relevant toolbar icons.") | |||
| 136 | (defun gud-stop-subjob () | 136 | (defun gud-stop-subjob () |
| 137 | (interactive) | 137 | (interactive) |
| 138 | (with-current-buffer gud-comint-buffer | 138 | (with-current-buffer gud-comint-buffer |
| 139 | (if (string-equal gud-target-name "emacs") | 139 | (cond ((string-equal gud-target-name "emacs") |
| 140 | (comint-stop-subjob) | 140 | (comint-stop-subjob)) |
| 141 | (if (eq gud-minor-mode 'jdb) | 141 | ((eq gud-minor-mode 'jdb) |
| 142 | (gud-call "suspend") | 142 | (gud-call "suspend")) |
| 143 | (comint-interrupt-subjob))))) | 143 | ((eq gud-minor-mode 'gdbmi) |
| 144 | (gdb-gud-context-call "-exec-interrupt" nil nil t)) | ||
| 145 | (t | ||
| 146 | (comint-interrupt-subjob))))) | ||
| 144 | 147 | ||
| 145 | (easy-mmode-defmap gud-menu-map | 148 | (easy-mmode-defmap gud-menu-map |
| 146 | '(([help] "Info (debugger)" . gud-goto-info) | 149 | '(([help] "Info (debugger)" . gud-goto-info) |
| @@ -156,12 +159,22 @@ Used to grey out relevant toolbar icons.") | |||
| 156 | :enable (not gud-running) | 159 | :enable (not gud-running) |
| 157 | :visible (memq gud-minor-mode '(gdbmi gdb dbx jdb))) | 160 | :visible (memq gud-minor-mode '(gdbmi gdb dbx jdb))) |
| 158 | ([go] menu-item (if gdb-active-process "Continue" "Run") gud-go | 161 | ([go] menu-item (if gdb-active-process "Continue" "Run") gud-go |
| 159 | :visible (and (not gud-running) | 162 | :visible (and (eq gud-minor-mode 'gdbmi) |
| 160 | (eq gud-minor-mode 'gdbmi))) | 163 | (or (and (or |
| 164 | (not gdb-gud-control-all-threads) | ||
| 165 | (not gdb-non-stop)) | ||
| 166 | (not gud-running)) | ||
| 167 | (and gdb-gud-control-all-threads | ||
| 168 | (> gdb-stopped-threads-count 0))))) | ||
| 161 | ([stop] menu-item "Stop" gud-stop-subjob | 169 | ([stop] menu-item "Stop" gud-stop-subjob |
| 162 | :visible (or (not (memq gud-minor-mode '(gdbmi pdb))) | 170 | :visible (or (not (memq gud-minor-mode '(gdbmi pdb))) |
| 163 | (and gud-running | 171 | (and (eq gud-minor-mode 'gdbmi) |
| 164 | (eq gud-minor-mode 'gdbmi)))) | 172 | (or (and (or |
| 173 | (not gdb-gud-control-all-threads) | ||
| 174 | (not gdb-non-stop)) | ||
| 175 | gud-running) | ||
| 176 | (and gdb-gud-control-all-threads | ||
| 177 | (> gdb-running-threads-count 0)))))) | ||
| 165 | ([until] menu-item "Continue to selection" gud-until | 178 | ([until] menu-item "Continue to selection" gud-until |
| 166 | :enable (not gud-running) | 179 | :enable (not gud-running) |
| 167 | :visible (and (memq gud-minor-mode '(gdbmi gdb perldb)) | 180 | :visible (and (memq gud-minor-mode '(gdbmi gdb perldb)) |
| @@ -248,11 +261,22 @@ Used to grey out relevant toolbar icons.") | |||
| 248 | :visible (memq gud-minor-mode '(gdbmi gdb dbx jdb))) | 261 | :visible (memq gud-minor-mode '(gdbmi gdb dbx jdb))) |
| 249 | ([menu-bar go] menu-item | 262 | ([menu-bar go] menu-item |
| 250 | ,(propertize " go " 'face 'font-lock-doc-face) gud-go | 263 | ,(propertize " go " 'face 'font-lock-doc-face) gud-go |
| 251 | :visible (and (not gud-running) | 264 | :visible (and (eq gud-minor-mode 'gdbmi) |
| 252 | (eq gud-minor-mode 'gdbmi))) | 265 | (or (and (or |
| 266 | (not gdb-gud-control-all-threads) | ||
| 267 | (not gdb-non-stop)) | ||
| 268 | (not gud-running)) | ||
| 269 | (and gdb-gud-control-all-threads | ||
| 270 | (> gdb-stopped-threads-count 0))))) | ||
| 253 | ([menu-bar stop] menu-item | 271 | ([menu-bar stop] menu-item |
| 254 | ,(propertize "stop" 'face 'font-lock-doc-face) gud-stop-subjob | 272 | ,(propertize "stop" 'face 'font-lock-doc-face) gud-stop-subjob |
| 255 | :visible (or gud-running | 273 | :visible (or (and (eq gud-minor-mode 'gdbmi) |
| 274 | (or (and (or | ||
| 275 | (not gdb-gud-control-all-threads) | ||
| 276 | (not gdb-non-stop)) | ||
| 277 | gud-running) | ||
| 278 | (and gdb-gud-control-all-threads | ||
| 279 | (> gdb-running-threads-count 0)))) | ||
| 256 | (not (eq gud-minor-mode 'gdbmi)))) | 280 | (not (eq gud-minor-mode 'gdbmi)))) |
| 257 | ([menu-bar print] | 281 | ([menu-bar print] |
| 258 | . (,(propertize "print" 'face 'font-lock-doc-face) . gud-print)) | 282 | . (,(propertize "print" 'face 'font-lock-doc-face) . gud-print)) |