diff options
| author | Gustaf Waldemarson | 2022-03-06 22:56:04 +0100 |
|---|---|---|
| committer | Lars Ingebrigtsen | 2022-03-06 22:56:04 +0100 |
| commit | f70bf8a21dc1283a58367cbca31decef633c6dab (patch) | |
| tree | 2411f3fd0f2d3413a1cad5cd120b8592a7a595cf | |
| parent | 5b7ce98ea0fd368aa5a73d5f6e01cf8b0fd253c1 (diff) | |
| download | emacs-f70bf8a21dc1283a58367cbca31decef633c6dab.tar.gz emacs-f70bf8a21dc1283a58367cbca31decef633c6dab.zip | |
Display complex data types in gdb-mi
* lisp/progmodes/gdb-mi.el (bindat): Require.
(gdb-invalidate-locals): Use `-stack-list-variables` instead of
the deprecated `-stack-list-locals`. Additionally, this allow
function arguments to be displayed in the locals buffer.
(gdb-locals-values-buffer, gdb-locals-values-buffer-name)
(gdb-locals-simple-values-only, gdb-locals-values-table): New
variables.
(gdb-locals-values-handler-custom): Create a new gdb buffer for
extracting local variable values. To
extract the values for 'complex' data-types, the command
`-stack-list-locals` is used with the `--all-values` flag.
The extracted values are then stored in a hash-table for later use in
the `gdb-locals-handler-custom` that performs the actual update of the
Local variable buffer.
All variable values are filtered to fit it into a single line, being
truncated as necessary by the user customizable option
`gdb-locals-value-limit`.
The old behavior of hiding complex values can be restored using the
customizable `gdb-locals-simple-values-only` option.
Patch amended by William Xu <william.xwl@gmail.com>.
| -rw-r--r-- | lisp/progmodes/gdb-mi.el | 69 |
1 files changed, 64 insertions, 5 deletions
diff --git a/lisp/progmodes/gdb-mi.el b/lisp/progmodes/gdb-mi.el index ddccbe80e7f..a35a7deb4b1 100644 --- a/lisp/progmodes/gdb-mi.el +++ b/lisp/progmodes/gdb-mi.el | |||
| @@ -90,6 +90,7 @@ | |||
| 90 | (require 'gud) | 90 | (require 'gud) |
| 91 | (require 'cl-lib) | 91 | (require 'cl-lib) |
| 92 | (require 'cl-seq) | 92 | (require 'cl-seq) |
| 93 | (require 'bindat) | ||
| 93 | (eval-when-compile (require 'pcase)) | 94 | (eval-when-compile (require 'pcase)) |
| 94 | 95 | ||
| 95 | (declare-function speedbar-change-initial-expansion-list | 96 | (declare-function speedbar-change-initial-expansion-list |
| @@ -4288,7 +4289,7 @@ member." | |||
| 4288 | ;; uses "-stack-list-locals --simple-values". Needs GDB 6.1 onwards. | 4289 | ;; uses "-stack-list-locals --simple-values". Needs GDB 6.1 onwards. |
| 4289 | (def-gdb-trigger-and-handler | 4290 | (def-gdb-trigger-and-handler |
| 4290 | gdb-invalidate-locals | 4291 | gdb-invalidate-locals |
| 4291 | (concat (gdb-current-context-command "-stack-list-locals") | 4292 | (concat (gdb-current-context-command "-stack-list-variables") |
| 4292 | " --simple-values") | 4293 | " --simple-values") |
| 4293 | gdb-locals-handler gdb-locals-handler-custom | 4294 | gdb-locals-handler gdb-locals-handler-custom |
| 4294 | '(start update)) | 4295 | '(start update)) |
| @@ -4299,6 +4300,48 @@ member." | |||
| 4299 | 'gdb-locals-mode | 4300 | 'gdb-locals-mode |
| 4300 | 'gdb-invalidate-locals) | 4301 | 'gdb-invalidate-locals) |
| 4301 | 4302 | ||
| 4303 | |||
| 4304 | ;; Retrieve the values of all variables before invalidating locals. | ||
| 4305 | (def-gdb-trigger-and-handler | ||
| 4306 | gdb-locals-values | ||
| 4307 | (concat (gdb-current-context-command "-stack-list-variables") | ||
| 4308 | " --all-values") | ||
| 4309 | gdb-locals-values-handler gdb-locals-values-handler-custom | ||
| 4310 | '(start update)) | ||
| 4311 | |||
| 4312 | (gdb-set-buffer-rules | ||
| 4313 | 'gdb-locals-values-buffer | ||
| 4314 | 'gdb-locals-values-buffer-name | ||
| 4315 | 'gdb-locals-mode | ||
| 4316 | 'gdb-locals-values) | ||
| 4317 | |||
| 4318 | (defun gdb-locals-values-buffer-name () | ||
| 4319 | (gdb-current-context-buffer-name | ||
| 4320 | (concat "local values of " (gdb-get-target-string)))) | ||
| 4321 | |||
| 4322 | (defcustom gdb-locals-simple-values-only nil | ||
| 4323 | "Only display simple values in the Locals buffer." | ||
| 4324 | :type 'boolean | ||
| 4325 | :group 'gud | ||
| 4326 | :version "29.1") | ||
| 4327 | |||
| 4328 | (defcustom gdb-locals-value-limit 100 | ||
| 4329 | "Maximum length the value of a local variable is allowed to be." | ||
| 4330 | :type 'integer | ||
| 4331 | :group 'gud | ||
| 4332 | :version "29.1") | ||
| 4333 | |||
| 4334 | (defvar gdb-locals-values-table (make-hash-table :test #'equal) | ||
| 4335 | "Mapping of local variable names to a string with their value.") | ||
| 4336 | |||
| 4337 | (defun gdb-locals-values-handler-custom () | ||
| 4338 | "Store the values of local variables in `gdb-locals-value-map'." | ||
| 4339 | (let ((locals-list (bindat-get-field (gdb-mi--partial-output) 'variables))) | ||
| 4340 | (dolist (local locals-list) | ||
| 4341 | (let ((name (bindat-get-field local 'name)) | ||
| 4342 | (value (bindat-get-field local 'value))) | ||
| 4343 | (puthash name value gdb-locals-values-table))))) | ||
| 4344 | |||
| 4302 | (defvar gdb-locals-watch-map | 4345 | (defvar gdb-locals-watch-map |
| 4303 | (let ((map (make-sparse-keymap))) | 4346 | (let ((map (make-sparse-keymap))) |
| 4304 | (suppress-keymap map) | 4347 | (suppress-keymap map) |
| @@ -4315,6 +4358,15 @@ member." | |||
| 4315 | map) | 4358 | map) |
| 4316 | "Keymap to edit value of a simple data type local variable.") | 4359 | "Keymap to edit value of a simple data type local variable.") |
| 4317 | 4360 | ||
| 4361 | (defun gdb-locals-value-filter (value) | ||
| 4362 | "Filter function for the local variable VALUE." | ||
| 4363 | (let* ((no-nl (replace-regexp-in-string "\n" " " value)) | ||
| 4364 | (str (replace-regexp-in-string "[[:space:]]+" " " no-nl)) | ||
| 4365 | (limit gdb-locals-value-limit)) | ||
| 4366 | (if (>= (length str) limit) | ||
| 4367 | (concat (substring str 0 limit) "...") | ||
| 4368 | str))) | ||
| 4369 | |||
| 4318 | (defun gdb-edit-locals-value (&optional event) | 4370 | (defun gdb-edit-locals-value (&optional event) |
| 4319 | "Assign a value to a variable displayed in the locals buffer." | 4371 | "Assign a value to a variable displayed in the locals buffer." |
| 4320 | (interactive (list last-input-event)) | 4372 | (interactive (list last-input-event)) |
| @@ -4327,17 +4379,22 @@ member." | |||
| 4327 | (gud-basic-call | 4379 | (gud-basic-call |
| 4328 | (concat "-gdb-set variable " var " = " value))))) | 4380 | (concat "-gdb-set variable " var " = " value))))) |
| 4329 | 4381 | ||
| 4330 | ;; Don't display values of arrays or structures. | 4382 | ;; Complex data types are looked up in `gdb-locals-values-table'. |
| 4331 | ;; These can be expanded using gud-watch. | ||
| 4332 | (defun gdb-locals-handler-custom () | 4383 | (defun gdb-locals-handler-custom () |
| 4333 | (let ((locals-list (gdb-mi--field (gdb-mi--partial-output) 'locals)) | 4384 | "Handler to rebuild the local variables table buffer." |
| 4385 | (let ((locals-list (bindat-get-field (gdb-mi--partial-output) 'variables)) | ||
| 4334 | (table (make-gdb-table))) | 4386 | (table (make-gdb-table))) |
| 4335 | (dolist (local locals-list) | 4387 | (dolist (local locals-list) |
| 4336 | (let ((name (gdb-mi--field local 'name)) | 4388 | (let ((name (gdb-mi--field local 'name)) |
| 4337 | (value (gdb-mi--field local 'value)) | 4389 | (value (gdb-mi--field local 'value)) |
| 4338 | (type (gdb-mi--field local 'type))) | 4390 | (type (gdb-mi--field local 'type))) |
| 4339 | (when (not value) | 4391 | (when (not value) |
| 4340 | (setq value "<complex data type>")) | 4392 | (setq value |
| 4393 | (if gdb-locals-simple-values-only | ||
| 4394 | "<complex data type>" | ||
| 4395 | (gethash name gdb-locals-values-table "<unavailable>")))) | ||
| 4396 | (setq value (gdb-locals-value-filter value)) | ||
| 4397 | |||
| 4341 | (if (or (not value) | 4398 | (if (or (not value) |
| 4342 | (string-match "0x" value)) | 4399 | (string-match "0x" value)) |
| 4343 | (add-text-properties 0 (length name) | 4400 | (add-text-properties 0 (length name) |
| @@ -4860,6 +4917,8 @@ file\" where the GDB session starts (see `gdb-main-file')." | |||
| 4860 | (expand-file-name gdb-default-window-configuration-file | 4917 | (expand-file-name gdb-default-window-configuration-file |
| 4861 | gdb-window-configuration-directory))) | 4918 | gdb-window-configuration-directory))) |
| 4862 | ;; Create default layout as before. | 4919 | ;; Create default layout as before. |
| 4920 | ;; Make sure that local values are updated before locals. | ||
| 4921 | (gdb-get-buffer-create 'gdb-locals-values-buffer) | ||
| 4863 | (gdb-get-buffer-create 'gdb-locals-buffer) | 4922 | (gdb-get-buffer-create 'gdb-locals-buffer) |
| 4864 | (gdb-get-buffer-create 'gdb-stack-buffer) | 4923 | (gdb-get-buffer-create 'gdb-stack-buffer) |
| 4865 | (gdb-get-buffer-create 'gdb-breakpoints-buffer) | 4924 | (gdb-get-buffer-create 'gdb-breakpoints-buffer) |