From ebed165be8af3d7e145e1defa97892fdf9ddf560 Mon Sep 17 00:00:00 2001 From: Gustaf Waldemarson Date: Thu, 21 Feb 2019 13:37:14 +0100 Subject: [PATCH 1/2] gdb-mi.el: Display complex data-types. 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. --- lisp/progmodes/gdb-mi.el | 69 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 66 insertions(+), 3 deletions(-) diff --git a/lisp/progmodes/gdb-mi.el b/lisp/progmodes/gdb-mi.el index b63f82b..6fb09d1 100644 --- a/lisp/progmodes/gdb-mi.el +++ b/lisp/progmodes/gdb-mi.el @@ -4119,6 +4119,51 @@ gdb-select-frame 'gdb-locals-mode 'gdb-invalidate-locals) + +;; Retrieve the values of all variables before invalidating locals. +(def-gdb-trigger-and-handler + gdb-locals-values + (concat (gdb-current-context-command "-stack-list-locals") + " --all-values") + gdb-locals-values-handler gdb-locals-values-handler-custom + '(start update)) + +(gdb-set-buffer-rules + 'gdb-locals-values-buffer + 'gdb-locals-values-buffer-name + 'gdb-locals-mode + 'gdb-locals-values) + +(defun gdb-locals-values-buffer-name () + (gdb-current-context-buffer-name + (concat "local values of " (gdb-get-target-string)))) + + +(defcustom gdb-locals-simple-values-only nil + "Only display simple values in the Locals buffer." + :type 'boolean + :group 'gud) + + +(defcustom gdb-locals-value-limit 100 + "Maximum length the value of a local variable is allowed to be." + :type 'integer + :group 'gud) + + +(defvar gdb-locals-values-table (make-hash-table :test #'equal) + "Mapping of local variable names to a string with their value.") + + +(defun gdb-locals-values-handler-custom () + "Store the values of local variables in `gdb-locals-value-map'." + (let ((locals-list (bindat-get-field (gdb-json-partial-output) 'locals))) + (dolist (local locals-list) + (let ((name (bindat-get-field local 'name)) + (value (bindat-get-field local 'value))) + (puthash name value gdb-locals-values-table))))) + + (defvar gdb-locals-watch-map (let ((map (make-sparse-keymap))) (suppress-keymap map) @@ -4135,6 +4180,17 @@ gdb-edit-locals-map-1 map) "Keymap to edit value of a simple data type local variable.") + +(defun gdb-locals-value-filter (value) + "Filter function for the local variable VALUE." + (let* ((no-nl (replace-regexp-in-string "\n" " " value)) + (str (replace-regexp-in-string "[[:space:]]+" " " no-nl)) + (limit gdb-locals-value-limit)) + (if (>= (length str) limit) + (concat (substring str 0 limit) "...") + str))) + + (defun gdb-edit-locals-value (&optional event) "Assign a value to a variable displayed in the locals buffer." (interactive (list last-input-event)) @@ -4147,9 +4203,10 @@ gdb-edit-locals-value (gud-basic-call (concat "-gdb-set variable " var " = " value))))) -;; Don't display values of arrays or structures. -;; These can be expanded using gud-watch. + +;; Complex data types are looked up in `gdb-locals-values-table'. (defun gdb-locals-handler-custom () + "Handler to rebuild the local variables table buffer." (let ((locals-list (bindat-get-field (gdb-json-partial-output) 'locals)) (table (make-gdb-table))) (dolist (local locals-list) @@ -4157,7 +4214,11 @@ gdb-locals-handler-custom (value (bindat-get-field local 'value)) (type (bindat-get-field local 'type))) (when (not value) - (setq value "")) + (setq value + (if gdb-locals-simple-values-only + "" + (gethash name gdb-locals-values-table "")))) + (setq value (gdb-locals-value-filter value)) (if (or (not value) (string-match "\\0x" value)) (add-text-properties 0 (length name) @@ -4581,6 +4642,8 @@ gdb-set-window-buffer (defun gdb-setup-windows () "Layout the window pattern for option `gdb-many-windows'." + ;; Make sure that local values are updated before locals. + (gdb-get-buffer-create 'gdb-locals-values-buffer) (gdb-get-buffer-create 'gdb-locals-buffer) (gdb-get-buffer-create 'gdb-stack-buffer) (gdb-get-buffer-create 'gdb-breakpoints-buffer) -- 2.7.4