(gdb-var-list, gdb-var-changed, gdb-update-flag)
(gdb-update-flag): New variables. (gdb-var-update, gdb-var-update-handler,gdb-var-delete) (gdb-speedbar-expand-node, gdb-var-evaluate-expression-handler) (gud-watch, gdb-var-create-handler) : New functions. (gdb-var-list-children, gdb-var-list-children-handler) (gdb-var-create-regexp, gdb-var-update-regexp) (gdb-var-list-children-regexp): New constants. (gud-gdba-command-name): Don't specify -noasync so that GDB/MI works. (gdb-annotation-rules): Reduced annotation set (level 3). (gdb-pre-prompt, gdb-prompt): Call handler in gdb-prompt. (gdb-post-prompt): Don't update GDB buffers every time speedbar updates. (gdb-window-height, gdb-window-width, gdb-display-in-progress) (gdb-expression-buffer-name, gdb-display-number, gdb-point) (gdb-dive-display-number, gdb-nesting-level, gdb-expression) (gdb-annotation-arg, gdb-dive-map, gdb-values, gdb-array-start) (gdb-array-stop, gdb-array-slice-map, gdb-display-string) (gdb-array-size, gdb-display-mode-map, gdb-expressions-mode-map): (gdb-expressions-mode-menu, gdb-dive): Remove variables. (gud-display, gud-display1) (gdb-display-begin,gdb-display-number-end, gdb-delete-line) (gdb-display-end, gdb-display-go-back, gdb-array-section-end) (gdb-field-begin, gdb-field-end, gdb-elt,gdb-field-format-begin) (gdb-field-format-end, gdb-dive, gdb-dive-new-frame) (gdb-insert-field, gdb-array-format, gdb-mouse-array-slice) (gdb-array-slice, gdb-array-format1, gdb-info-display-custom) (gdb-delete-frames, gdb-display-mode, gdb-display-buffer-name) (gdb-display-display-buffer, gdb-toggle-display) (gdb-delete-display, gdb-expressions-popup-menu) (gdb-expressions-mode, gdb-array-visualise): Remove functions. (gdb-setup-windows, gdb-reset, gdb-source-info): Remove references to display buffer.
This commit is contained in:
parent
8591f729cc
commit
a641269a1b
1 changed files with 153 additions and 629 deletions
782
lisp/gdb-ui.el
782
lisp/gdb-ui.el
|
@ -50,29 +50,19 @@
|
|||
|
||||
(require 'gud)
|
||||
|
||||
(defcustom gdb-window-height 20
|
||||
"Number of lines in a frame for a displayed expression in GDB-UI."
|
||||
:type 'integer
|
||||
:group 'gud)
|
||||
|
||||
(defcustom gdb-window-width 30
|
||||
"Width of a frame for a displayed expression in GDB-UI."
|
||||
:type 'integer
|
||||
:group 'gud)
|
||||
|
||||
(defvar gdb-current-address "main" "Initialisation for Assembler buffer.")
|
||||
(defvar gdb-previous-address nil)
|
||||
(defvar gdb-previous-frame nil)
|
||||
(defvar gdb-current-frame "main")
|
||||
(defvar gdb-display-in-progress nil)
|
||||
(defvar gdb-dive nil)
|
||||
(defvar gdb-view-source t "Non-nil means that source code can be viewed")
|
||||
(defvar gdb-selected-view 'source "Code type that user wishes to view")
|
||||
(defvar gdb-var-list nil "List of variables in watch window")
|
||||
(defvar gdb-var-changed nil "Non-nil means that gdb-var-list has changed")
|
||||
(defvar gdb-update-flag t "Non-il means update buffers")
|
||||
(defvar gdb-buffer-type nil)
|
||||
(defvar gdb-variables '()
|
||||
"A list of variables that are local to the GUD buffer.")
|
||||
|
||||
|
||||
;;;###autoload
|
||||
(defun gdba (command-line)
|
||||
"Run gdb on program FILE in buffer *gud-FILE*.
|
||||
|
@ -162,10 +152,11 @@ The following interactive lisp functions help control operation :
|
|||
(setq gdb-previous-address nil)
|
||||
(setq gdb-previous-frame nil)
|
||||
(setq gdb-current-frame "main")
|
||||
(setq gdb-display-in-progress nil)
|
||||
(setq gdb-dive nil)
|
||||
(setq gdb-view-source t)
|
||||
(setq gdb-selected-view 'source)
|
||||
(setq gdb-var-list nil)
|
||||
(setq gdb-var-changed nil)
|
||||
(setq gdb-update-flag t)
|
||||
;;
|
||||
(mapc 'make-local-variable gdb-variables)
|
||||
(setq gdb-buffer-type 'gdba)
|
||||
|
@ -182,30 +173,148 @@ The following interactive lisp functions help control operation :
|
|||
;;
|
||||
(run-hooks 'gdba-mode-hook))
|
||||
|
||||
(defun gud-display ()
|
||||
"Auto-display (possibly dereferenced) C expression at point."
|
||||
(defun gud-watch ()
|
||||
"Watch expression."
|
||||
(interactive)
|
||||
(save-excursion
|
||||
(let ((expr (gud-find-c-expr)))
|
||||
(let ((expr (tooltip-identifier-from-point (point))))
|
||||
(setq expr (concat gdb-current-frame "::" expr))
|
||||
(catch 'already-watched
|
||||
(dolist (var gdb-var-list)
|
||||
(if (string-equal expr (car var)) (throw 'already-watched nil)))
|
||||
(gdb-enqueue-input
|
||||
(list (concat "server ptype " expr "\n")
|
||||
`(lambda () (gud-display1 ,expr)))))))
|
||||
(list (concat "interpreter mi \"-var-create - * " expr "\"\n")
|
||||
`(lambda () (gdb-var-create-handler ,expr))))))
|
||||
(select-window (get-buffer-window gud-comint-buffer)))
|
||||
|
||||
(defun gud-display1 (expr)
|
||||
(goto-char (point-min))
|
||||
(if (looking-at "No symbol")
|
||||
(defconst gdb-var-create-regexp
|
||||
"name=\"\\(.*?\\)\",numchild=\"\\(.*?\\)\",type=\"\\(.*?\\)\"")
|
||||
|
||||
(defun gdb-var-create-handler (expr)
|
||||
(with-current-buffer (gdb-get-create-buffer 'gdb-partial-output-buffer)
|
||||
(goto-char (point-min))
|
||||
(if (re-search-forward gdb-var-create-regexp nil t)
|
||||
(let ((var (list expr
|
||||
(match-string-no-properties 1)
|
||||
(match-string-no-properties 2)
|
||||
(match-string-no-properties 3)
|
||||
nil)))
|
||||
(push var gdb-var-list)
|
||||
(speedbar 1)
|
||||
(if (equal (nth 2 var) "0")
|
||||
(gdb-enqueue-input
|
||||
(list (concat "interpreter mi \"-var-evaluate-expression "
|
||||
(nth 1 var) "\"\n")
|
||||
`(lambda () (gdb-var-evaluate-expression-handler
|
||||
,(nth 1 var)))))
|
||||
(setq gdb-var-changed t)))
|
||||
(if (re-search-forward "Undefined command" nil t)
|
||||
(message "Watching expressions requires gdb 6.0 onwards")
|
||||
(message "No symbol %s in current context." expr)))))
|
||||
|
||||
(defun gdb-var-evaluate-expression-handler (varnum)
|
||||
(with-current-buffer (gdb-get-create-buffer 'gdb-partial-output-buffer)
|
||||
(goto-char (point-min))
|
||||
(re-search-forward ".*value=\"\\(.*?\\)\"" nil t)
|
||||
(let ((var-list nil))
|
||||
(dolist (var gdb-var-list)
|
||||
(if (string-equal varnum (cadr var))
|
||||
(progn
|
||||
(push (nreverse (cons (match-string-no-properties 1)
|
||||
(cdr (nreverse var)))) var-list))
|
||||
(push var var-list)))
|
||||
(setq gdb-var-list (nreverse var-list))))
|
||||
(setq gdb-var-changed t))
|
||||
|
||||
(defun gdb-var-list-children (varnum)
|
||||
(gdb-enqueue-input
|
||||
(list (concat "interpreter mi \"-var-list-children " varnum "\"\n")
|
||||
`(lambda () (gdb-var-list-children-handler ,varnum)))))
|
||||
|
||||
(defconst gdb-var-list-children-regexp
|
||||
"name=\"\\(.*?\\)\",exp=\"\\(.*?\\)\",numchild=\"\\(.*?\\)\",type=\"\\(.*?\\)\"")
|
||||
|
||||
(defun gdb-var-list-children-handler (varnum)
|
||||
(with-current-buffer (gdb-get-create-buffer 'gdb-partial-output-buffer)
|
||||
(goto-char (point-min))
|
||||
(let ((var-list nil))
|
||||
(catch 'child-already-watched
|
||||
(dolist (var gdb-var-list)
|
||||
(if (string-equal varnum (cadr var))
|
||||
(progn
|
||||
(push var var-list)
|
||||
(while (re-search-forward gdb-var-list-children-regexp nil t)
|
||||
(let ((varchild (list (match-string-no-properties 2)
|
||||
(match-string-no-properties 1)
|
||||
(match-string-no-properties 3)
|
||||
(match-string-no-properties 4)
|
||||
nil)))
|
||||
(dolist (var1 gdb-var-list)
|
||||
(if (string-equal (cadr var1) (cadr varchild))
|
||||
(throw 'child-already-watched nil)))
|
||||
(push varchild var-list)
|
||||
(if (equal (nth 2 varchild) "0")
|
||||
(gdb-enqueue-input
|
||||
(list
|
||||
(concat "interpreter mi \"-var-evaluate-expression "
|
||||
(nth 1 varchild) "\"\n")
|
||||
`(lambda () (gdb-var-evaluate-expression-handler
|
||||
,(nth 1 varchild)))))))))
|
||||
(push var var-list)))
|
||||
(setq gdb-var-list (nreverse var-list))))))
|
||||
|
||||
(defun gdb-var-update ()
|
||||
(setq gdb-update-flag nil)
|
||||
(if (not (member 'gdb-var-update (gdb-get-pending-triggers)))
|
||||
(progn
|
||||
(gdb-set-output-sink 'user)
|
||||
(gud-call (concat "server ptype " expr)))
|
||||
(goto-char (- (point-max) 1))
|
||||
(if (equal (char-before) (string-to-char "\*"))
|
||||
(gud-call (concat "display* " expr))
|
||||
(gud-call (concat "display " expr)))))
|
||||
(gdb-enqueue-input (list "server interpreter mi \"-var-update *\"\n"
|
||||
'gdb-var-update-handler))
|
||||
(gdb-set-pending-triggers (cons 'gdb-var-update
|
||||
(gdb-get-pending-triggers))))))
|
||||
|
||||
; this would messy because these bindings don't work with M-x gdb
|
||||
; (define-key global-map "\C-x\C-a\C-a" 'gud-display)
|
||||
; (define-key gud-minor-mode-map "\C-c\C-a" 'gud-display)
|
||||
(defconst gdb-var-update-regexp "name=\"\\(.*?\\)\"")
|
||||
|
||||
(defun gdb-var-update-handler ()
|
||||
(with-current-buffer (gdb-get-create-buffer 'gdb-partial-output-buffer)
|
||||
(goto-char (point-min))
|
||||
(while (re-search-forward gdb-var-update-regexp nil t)
|
||||
(let ((varnum (match-string-no-properties 1)))
|
||||
(gdb-enqueue-input
|
||||
(list (concat "interpreter mi \"-var-evaluate-expression "
|
||||
varnum "\"\n")
|
||||
`(lambda () (gdb-var-evaluate-expression-handler
|
||||
,varnum)))))))
|
||||
(gdb-set-pending-triggers
|
||||
(delq 'gdb-var-update (gdb-get-pending-triggers))))
|
||||
|
||||
(defun gdb-var-delete (text token indent)
|
||||
"Delete watched expression."
|
||||
(interactive)
|
||||
(when (eq indent 0)
|
||||
(string-match "\\(\\S-+\\)" text)
|
||||
(let* ((expr (match-string 1 text))
|
||||
(var (assoc expr gdb-var-list))
|
||||
(varnum (cadr var)))
|
||||
(gdb-enqueue-input
|
||||
(list (concat "interpreter mi \"-var-delete " varnum "\"\n")
|
||||
'ignore))
|
||||
(setq gdb-var-list (delq var gdb-var-list))
|
||||
(dolist (varchild gdb-var-list)
|
||||
(if (string-match (concat (nth 1 var) "\\.") (nth 1 varchild))
|
||||
(setq gdb-var-list (delq varchild gdb-var-list)))))
|
||||
(setq gdb-var-changed t)))
|
||||
|
||||
(defun gdb-speedbar-expand-node (text token indent)
|
||||
"Expand the node the user clicked on.
|
||||
TEXT is the text of the button we clicked on, a + or - item.
|
||||
TOKEN is data related to this node.
|
||||
INDENT is the current indentation depth."
|
||||
(cond ((string-match "+" text) ;expand this node
|
||||
(gdb-var-list-children token))
|
||||
((string-match "-" text) ;contract this node
|
||||
(dolist (var gdb-var-list)
|
||||
(if (string-match (concat token "\\.") (nth 1 var))
|
||||
(setq gdb-var-list (delq var gdb-var-list))))
|
||||
(setq gdb-var-changed t))))
|
||||
|
||||
|
||||
;; ======================================================================
|
||||
|
@ -445,7 +554,7 @@ This filter may simply queue output for a later time."
|
|||
(gdb-enqueue-input (concat string "\n")))
|
||||
|
||||
;; Note: Stuff enqueued here will be sent to the next prompt, even if it
|
||||
;; is a query, or other non-top-level prompt.
|
||||
;; is a query, or other non-top-level prompt.
|
||||
|
||||
(defun gdb-enqueue-input (item)
|
||||
(if (gdb-get-prompting)
|
||||
|
@ -489,7 +598,7 @@ This filter may simply queue output for a later time."
|
|||
;; any newlines.
|
||||
;;
|
||||
|
||||
(defcustom gud-gdba-command-name "gdb -annotate=2 -noasync"
|
||||
(defcustom gud-gdba-command-name "~/gdb/gdb/gdb -annotate=3"
|
||||
"Default command to execute an executable under the GDB-UI debugger."
|
||||
:type 'string
|
||||
:group 'gud)
|
||||
|
@ -511,18 +620,6 @@ This filter may simply queue output for a later time."
|
|||
("watchpoint" gdb-stopping)
|
||||
("frame-begin" gdb-frame-begin)
|
||||
("stopped" gdb-stopped)
|
||||
("display-begin" gdb-display-begin)
|
||||
("display-end" gdb-display-end)
|
||||
; GDB commands info stack, info locals and frame generate an error-begin
|
||||
; annotation at start when there is no stack but this is a quirk/bug in
|
||||
; annotations.
|
||||
; ("error-begin" gdb-error-begin)
|
||||
("display-number-end" gdb-display-number-end)
|
||||
("array-section-begin" gdb-array-section-begin)
|
||||
("array-section-end" gdb-array-section-end)
|
||||
;; ("elt" gdb-elt)
|
||||
("field-begin" gdb-field-begin)
|
||||
("field-end" gdb-field-end)
|
||||
) "An assoc mapping annotation tags to functions which process them.")
|
||||
|
||||
(defconst gdb-source-spec-regexp
|
||||
|
@ -558,11 +655,7 @@ output from a previous command if that happens to be in effect."
|
|||
(cond
|
||||
((eq sink 'user) t)
|
||||
((eq sink 'emacs)
|
||||
(gdb-set-output-sink 'post-emacs)
|
||||
(let ((handler
|
||||
(car (cdr (gdb-get-current-item)))))
|
||||
(with-current-buffer (gdb-get-create-buffer 'gdb-partial-output-buffer)
|
||||
(funcall handler))))
|
||||
(gdb-set-output-sink 'post-emacs))
|
||||
(t
|
||||
(gdb-set-output-sink 'user)
|
||||
(error "Phase error in gdb-pre-prompt (got %s)" sink)))))
|
||||
|
@ -574,7 +667,11 @@ This sends the next command (if any) to gdb."
|
|||
(cond
|
||||
((eq sink 'user) t)
|
||||
((eq sink 'post-emacs)
|
||||
(gdb-set-output-sink 'user))
|
||||
(gdb-set-output-sink 'user)
|
||||
(let ((handler
|
||||
(car (cdr (gdb-get-current-item)))))
|
||||
(with-current-buffer (gdb-get-create-buffer 'gdb-partial-output-buffer)
|
||||
(funcall handler))))
|
||||
(t
|
||||
(gdb-set-output-sink 'user)
|
||||
(error "Phase error in gdb-prompt (got %s)" sink))))
|
||||
|
@ -632,7 +729,7 @@ that if we already set the output sink to 'user in gdb-stopping, that is fine."
|
|||
(defun gdb-post-prompt (ignored)
|
||||
"An annotation handler for `post-prompt'. This begins the collection of
|
||||
output from the current command if that happens to be appropriate."
|
||||
(if (not (gdb-get-pending-triggers))
|
||||
(if (and (not (gdb-get-pending-triggers)) gdb-update-flag)
|
||||
(progn
|
||||
(gdb-get-current-frame)
|
||||
(gdb-invalidate-frames)
|
||||
|
@ -640,8 +737,8 @@ output from the current command if that happens to be appropriate."
|
|||
(gdb-invalidate-assembler)
|
||||
(gdb-invalidate-registers)
|
||||
(gdb-invalidate-locals)
|
||||
(gdb-invalidate-display)
|
||||
(gdb-invalidate-threads)))
|
||||
(setq gdb-update-flag t)
|
||||
(let ((sink (gdb-get-output-sink)))
|
||||
(cond
|
||||
((eq sink 'user) t)
|
||||
|
@ -651,392 +748,6 @@ output from the current command if that happens to be appropriate."
|
|||
(gdb-set-output-sink 'user)
|
||||
(error "Phase error in gdb-post-prompt (got %s)" sink)))))
|
||||
|
||||
;; If we get an error whilst evaluating one of the expressions
|
||||
;; we won't get the display-end annotation. Set the sink back to
|
||||
;; user to make sure that the error message is seen.
|
||||
;; NOT USED: see annotation-rules for reason.
|
||||
;(defun gdb-error-begin (ignored)
|
||||
; (gdb-set-output-sink 'user))
|
||||
|
||||
(defun gdb-display-begin (ignored)
|
||||
(gdb-set-output-sink 'emacs)
|
||||
(gdb-clear-partial-output)
|
||||
(setq gdb-display-in-progress t))
|
||||
|
||||
(defvar gdb-expression-buffer-name nil)
|
||||
(defvar gdb-display-number nil)
|
||||
(defvar gdb-dive-display-number nil)
|
||||
|
||||
(defun gdb-display-number-end (ignored)
|
||||
(set-buffer (gdb-get-buffer 'gdb-partial-output-buffer))
|
||||
(setq gdb-display-number (buffer-string))
|
||||
(setq gdb-expression-buffer-name
|
||||
(concat "*display " gdb-display-number "*"))
|
||||
(save-excursion
|
||||
(if (progn
|
||||
(set-buffer (window-buffer))
|
||||
gdb-dive)
|
||||
(progn
|
||||
(let ((number gdb-display-number))
|
||||
(switch-to-buffer
|
||||
(set-buffer (get-buffer-create gdb-expression-buffer-name)))
|
||||
(gdb-expressions-mode)
|
||||
(setq gdb-dive-display-number number)))
|
||||
(set-buffer (get-buffer-create gdb-expression-buffer-name))
|
||||
(if (display-graphic-p)
|
||||
(catch 'frame-exists
|
||||
(dolist (frame (frame-list))
|
||||
(if (string-equal (frame-parameter frame 'name)
|
||||
gdb-expression-buffer-name)
|
||||
(throw 'frame-exists nil)))
|
||||
(gdb-expressions-mode)
|
||||
(make-frame `((height . ,gdb-window-height)
|
||||
(width . ,gdb-window-width)
|
||||
(tool-bar-lines . nil)
|
||||
(menu-bar-lines . nil)
|
||||
(minibuffer . nil))))
|
||||
(gdb-expressions-mode)
|
||||
(gdb-display-buffer (get-buffer gdb-expression-buffer-name)))))
|
||||
(set-buffer (gdb-get-buffer 'gdb-partial-output-buffer))
|
||||
(setq gdb-dive nil))
|
||||
|
||||
(defvar gdb-nesting-level nil)
|
||||
(defvar gdb-expression nil)
|
||||
(defvar gdb-point nil)
|
||||
(defvar gdb-annotation-arg nil)
|
||||
|
||||
(defun gdb-delete-line ()
|
||||
"Delete the current line."
|
||||
(delete-region (line-beginning-position) (line-beginning-position 2)))
|
||||
|
||||
(defun gdb-display-end (ignored)
|
||||
(set-buffer (gdb-get-buffer 'gdb-partial-output-buffer))
|
||||
(goto-char (point-min))
|
||||
(search-forward ": ")
|
||||
(looking-at "\\(.*?\\) =")
|
||||
(let ((char "")
|
||||
(gdb-temp-value (match-string 1)))
|
||||
;;move * to front of expression if necessary
|
||||
(if (looking-at ".*\\*")
|
||||
(progn
|
||||
(setq char "*")
|
||||
(setq gdb-temp-value (substring gdb-temp-value 1 nil))))
|
||||
(with-current-buffer gdb-expression-buffer-name
|
||||
(setq gdb-expression gdb-temp-value)
|
||||
(if (not (string-match "::" gdb-expression))
|
||||
(setq gdb-expression (concat char gdb-current-frame
|
||||
"::" gdb-expression))
|
||||
;;else put * back on if necessary
|
||||
(setq gdb-expression (concat char gdb-expression)))
|
||||
(if (not header-line-format)
|
||||
(setq header-line-format (concat "-- " gdb-expression " %-")))))
|
||||
;;
|
||||
;;-if scalar/string
|
||||
(if (not (re-search-forward "##" nil t))
|
||||
(progn
|
||||
(with-current-buffer gdb-expression-buffer-name
|
||||
(let ((buffer-read-only nil))
|
||||
(delete-region (point-min) (point-max))
|
||||
(insert-buffer-substring
|
||||
(gdb-get-buffer 'gdb-partial-output-buffer)))))
|
||||
;; display expression name...
|
||||
(goto-char (point-min))
|
||||
(let ((start (progn (point)))
|
||||
(end (progn (end-of-line) (point))))
|
||||
(with-current-buffer gdb-expression-buffer-name
|
||||
(let ((buffer-read-only nil))
|
||||
(delete-region (point-min) (point-max))
|
||||
(insert-buffer-substring (gdb-get-buffer
|
||||
'gdb-partial-output-buffer)
|
||||
start end)
|
||||
(insert "\n"))))
|
||||
(goto-char (point-min))
|
||||
(re-search-forward "##" nil t)
|
||||
(setq gdb-nesting-level 0)
|
||||
(if (looking-at "array-section-begin")
|
||||
(progn
|
||||
(gdb-delete-line)
|
||||
(setq gdb-point (point))
|
||||
(gdb-array-format)))
|
||||
(if (looking-at "field-begin \\(.\\)")
|
||||
(progn
|
||||
(setq gdb-annotation-arg (match-string 1))
|
||||
(gdb-field-format-begin))))
|
||||
(with-current-buffer gdb-expression-buffer-name
|
||||
(if gdb-dive-display-number
|
||||
(progn
|
||||
(let ((buffer-read-only nil))
|
||||
(goto-char (point-max))
|
||||
(insert "\n")
|
||||
(insert-text-button "[back]" 'type 'gdb-display-back)))))
|
||||
(gdb-clear-partial-output)
|
||||
(gdb-set-output-sink 'user)
|
||||
(setq gdb-display-in-progress nil))
|
||||
|
||||
(define-button-type 'gdb-display-back
|
||||
'help-echo "mouse-2, RET: go back to previous display buffer"
|
||||
'action (lambda (button) (gdb-display-go-back)))
|
||||
|
||||
(defun gdb-display-go-back ()
|
||||
;; delete display so they don't accumulate and delete buffer
|
||||
(let ((number gdb-display-number))
|
||||
(gdb-enqueue-input
|
||||
(list (concat "server delete display " number "\n") 'ignore))
|
||||
(switch-to-buffer (concat "*display " gdb-dive-display-number "*"))
|
||||
(kill-buffer (get-buffer (concat "*display " number "*")))))
|
||||
|
||||
;; prefix annotations with ## and process whole output in one chunk
|
||||
;; in gdb-partial-output-buffer (to allow recursion).
|
||||
|
||||
;; array-section flags are just removed again but after counting. They
|
||||
;; might also be useful for arrays of structures and structures with arrays.
|
||||
(defun gdb-array-section-begin (args)
|
||||
(if gdb-display-in-progress
|
||||
(progn
|
||||
(with-current-buffer (gdb-get-buffer 'gdb-partial-output-buffer)
|
||||
(goto-char (point-max))
|
||||
(insert (concat "\n##array-section-begin " args "\n"))))))
|
||||
|
||||
(defun gdb-array-section-end (ignored)
|
||||
(if gdb-display-in-progress
|
||||
(progn
|
||||
(with-current-buffer (gdb-get-buffer 'gdb-partial-output-buffer)
|
||||
(goto-char (point-max))
|
||||
(insert "\n##array-section-end\n")))))
|
||||
|
||||
(defun gdb-field-begin (args)
|
||||
(if gdb-display-in-progress
|
||||
(progn
|
||||
(with-current-buffer (gdb-get-buffer 'gdb-partial-output-buffer)
|
||||
(goto-char (point-max))
|
||||
(insert (concat "\n##field-begin " args "\n"))))))
|
||||
|
||||
(defun gdb-field-end (ignored)
|
||||
(if gdb-display-in-progress
|
||||
(progn
|
||||
(with-current-buffer (gdb-get-buffer 'gdb-partial-output-buffer)
|
||||
(goto-char (point-max))
|
||||
(insert "\n##field-end\n")))))
|
||||
|
||||
(defun gdb-elt (ignored)
|
||||
(if gdb-display-in-progress
|
||||
(progn
|
||||
(goto-char (point-max))
|
||||
(insert "\n##elt\n"))))
|
||||
|
||||
(defun gdb-field-format-begin ()
|
||||
;; get rid of ##field-begin
|
||||
(gdb-delete-line)
|
||||
(gdb-insert-field)
|
||||
(setq gdb-nesting-level (+ gdb-nesting-level 1))
|
||||
(while (re-search-forward "##" nil t)
|
||||
;; keep making recursive calls...
|
||||
(if (looking-at "field-begin \\(.\\)")
|
||||
(progn
|
||||
(setq gdb-annotation-arg (match-string 1))
|
||||
(gdb-field-format-begin)))
|
||||
;; until field-end.
|
||||
(if (looking-at "field-end") (gdb-field-format-end))))
|
||||
|
||||
(defun gdb-field-format-end ()
|
||||
;; get rid of ##field-end and `,' or `}'
|
||||
(gdb-delete-line)
|
||||
(gdb-delete-line)
|
||||
(setq gdb-nesting-level (- gdb-nesting-level 1)))
|
||||
|
||||
(defvar gdb-dive-map
|
||||
(let ((map (make-sparse-keymap)))
|
||||
(define-key map [mouse-2] 'gdb-dive)
|
||||
(define-key map [S-mouse-2] 'gdb-dive-new-frame)
|
||||
map))
|
||||
|
||||
(defun gdb-dive (event)
|
||||
"Dive into structure."
|
||||
(interactive "e")
|
||||
(setq gdb-dive t)
|
||||
(gdb-dive-new-frame event))
|
||||
|
||||
(defun gdb-dive-new-frame (event)
|
||||
"Dive into structure and display in a new frame."
|
||||
(interactive "e")
|
||||
(save-excursion
|
||||
(mouse-set-point event)
|
||||
(let ((point (point)) (gdb-full-expression gdb-expression)
|
||||
(end (progn (end-of-line) (point)))
|
||||
(gdb-part-expression "") (gdb-last-field nil) (gdb-display-char nil))
|
||||
(beginning-of-line)
|
||||
(if (looking-at "\*") (setq gdb-display-char "*"))
|
||||
(re-search-forward "\\(\\S-+\\) = " end t)
|
||||
(setq gdb-last-field (match-string-no-properties 1))
|
||||
(goto-char (match-beginning 1))
|
||||
(let ((last-column (current-column)))
|
||||
(while (re-search-backward "\\s-\\(\\S-+\\) = {" nil t)
|
||||
(goto-char (match-beginning 1))
|
||||
(if (and (< (current-column) last-column)
|
||||
(> (count-lines 1 (point)) 1))
|
||||
(progn
|
||||
(setq gdb-part-expression
|
||||
(concat "." (match-string-no-properties 1)
|
||||
gdb-part-expression))
|
||||
(setq last-column (current-column))))))
|
||||
;; * not needed for components of a pointer to a structure in gdb
|
||||
(if (string-equal "*" (substring gdb-full-expression 0 1))
|
||||
(setq gdb-full-expression (substring gdb-full-expression 1 nil)))
|
||||
(setq gdb-full-expression
|
||||
(concat gdb-full-expression gdb-part-expression "." gdb-last-field))
|
||||
(gdb-enqueue-input
|
||||
(list (concat "server display" gdb-display-char
|
||||
" " gdb-full-expression "\n")
|
||||
'ignore)))))
|
||||
|
||||
(defun gdb-insert-field ()
|
||||
(let ((start (progn (point)))
|
||||
(end (progn (next-line) (point)))
|
||||
(num 0))
|
||||
(with-current-buffer gdb-expression-buffer-name
|
||||
(let ((buffer-read-only nil))
|
||||
(if (string-equal gdb-annotation-arg "\*") (insert "\*"))
|
||||
(while (<= num gdb-nesting-level)
|
||||
(insert "\t")
|
||||
(setq num (+ num 1)))
|
||||
(insert-buffer-substring (gdb-get-buffer
|
||||
'gdb-partial-output-buffer)
|
||||
start end)
|
||||
(add-text-properties
|
||||
(- (point) (- end start)) (- (point) 1)
|
||||
`(mouse-face highlight
|
||||
local-map ,gdb-dive-map
|
||||
help-echo "mouse-2: dive, S-mouse-2: dive in a new frame"))))
|
||||
(delete-region start end)))
|
||||
|
||||
(defvar gdb-values nil)
|
||||
|
||||
(defun gdb-array-format ()
|
||||
(while (re-search-forward "##" nil t)
|
||||
;; keep making recursive calls...
|
||||
(if (looking-at "array-section-begin")
|
||||
(progn
|
||||
;;get rid of ##array-section-begin
|
||||
(gdb-delete-line)
|
||||
(setq gdb-nesting-level (+ gdb-nesting-level 1))
|
||||
(gdb-array-format)))
|
||||
;;until *matching* array-section-end is found
|
||||
(if (looking-at "array-section-end")
|
||||
(if (eq gdb-nesting-level 0)
|
||||
(progn
|
||||
(let ((values (buffer-substring gdb-point (- (point) 2))))
|
||||
(with-current-buffer gdb-expression-buffer-name
|
||||
(setq gdb-values
|
||||
(concat "{" (replace-regexp-in-string "\n" "" values)
|
||||
"}"))
|
||||
(gdb-array-format1))))
|
||||
;;else get rid of ##array-section-end etc
|
||||
(gdb-delete-line)
|
||||
(setq gdb-nesting-level (- gdb-nesting-level 1))
|
||||
(gdb-array-format)))))
|
||||
|
||||
(defvar gdb-array-start nil)
|
||||
(defvar gdb-array-stop nil)
|
||||
|
||||
(defvar gdb-array-slice-map
|
||||
(let ((map (make-sparse-keymap)))
|
||||
(define-key map "\r" 'gdb-array-slice)
|
||||
(define-key map [mouse-2] 'gdb-mouse-array-slice)
|
||||
map))
|
||||
|
||||
(defun gdb-mouse-array-slice (event)
|
||||
"Select an array slice to display."
|
||||
(interactive "e")
|
||||
(mouse-set-point event)
|
||||
(gdb-array-slice))
|
||||
|
||||
(defun gdb-array-slice ()
|
||||
(interactive)
|
||||
(save-excursion
|
||||
(let ((n -1) (stop 0) (start 0) (point (point)))
|
||||
(beginning-of-line)
|
||||
(while (search-forward "[" point t)
|
||||
(setq n (+ n 1)))
|
||||
(setq start (string-to-int (read-string "Start index: ")))
|
||||
(aset gdb-array-start n start)
|
||||
(setq stop (string-to-int (read-string "Stop index: ")))
|
||||
(aset gdb-array-stop n stop)))
|
||||
(gdb-array-format1))
|
||||
|
||||
(defvar gdb-display-string nil)
|
||||
(defvar gdb-array-size nil)
|
||||
|
||||
(defun gdb-array-format1 ()
|
||||
(setq gdb-display-string "")
|
||||
(let ((buffer-read-only nil))
|
||||
(delete-region (point-min) (point-max))
|
||||
(let ((gdb-value-list (split-string gdb-values ", ")))
|
||||
(string-match "\\({+\\)" (car gdb-value-list))
|
||||
(let* ((depth (- (match-end 1) (match-beginning 1)))
|
||||
(indices (make-vector depth '0))
|
||||
(index 0) (num 0) (array-start "")
|
||||
(array-stop "") (array-slice "") (array-range nil)
|
||||
(flag t) (indices-string ""))
|
||||
(dolist (gdb-value gdb-value-list)
|
||||
(string-match "{*\\([^}]*\\)\\(}*\\)" gdb-value)
|
||||
(setq num 0)
|
||||
(while (< num depth)
|
||||
(setq indices-string
|
||||
(concat indices-string
|
||||
"[" (int-to-string (aref indices num)) "]"))
|
||||
(if (not (= (aref gdb-array-start num) -1))
|
||||
(if (or (< (aref indices num) (aref gdb-array-start num))
|
||||
(> (aref indices num) (aref gdb-array-stop num)))
|
||||
(setq flag nil))
|
||||
(aset gdb-array-size num (aref indices num)))
|
||||
(setq num (+ num 1)))
|
||||
(if flag
|
||||
(let ((gdb-display-value (match-string 1 gdb-value)))
|
||||
(setq gdb-display-string (concat gdb-display-string " "
|
||||
gdb-display-value))
|
||||
(insert
|
||||
(concat indices-string "\t" gdb-display-value "\n"))))
|
||||
(setq indices-string "")
|
||||
(setq flag t)
|
||||
;; 0<= index < depth, start at right : (- depth 1)
|
||||
(setq index (- (- depth 1)
|
||||
(- (match-end 2) (match-beginning 2))))
|
||||
;;don't set for very last brackets
|
||||
(when (>= index 0)
|
||||
(aset indices index (+ 1 (aref indices index)))
|
||||
(setq num (+ 1 index))
|
||||
(while (< num depth)
|
||||
(aset indices num 0)
|
||||
(setq num (+ num 1)))))
|
||||
(setq num 0)
|
||||
(while (< num depth)
|
||||
(if (= (aref gdb-array-start num) -1)
|
||||
(progn
|
||||
(aset gdb-array-start num 0)
|
||||
(aset gdb-array-stop num (aref indices num))))
|
||||
(setq array-start (int-to-string (aref gdb-array-start num)))
|
||||
(setq array-stop (int-to-string (aref gdb-array-stop num)))
|
||||
(setq array-range (concat "[" array-start
|
||||
":" array-stop "]"))
|
||||
(add-text-properties
|
||||
1 (+ (length array-start) (length array-stop) 2)
|
||||
`(mouse-face highlight
|
||||
local-map ,gdb-array-slice-map
|
||||
help-echo "mouse-2, RET: select slice for this index") array-range)
|
||||
(goto-char (point-min))
|
||||
(setq array-slice (concat array-slice array-range))
|
||||
(setq num (+ num 1)))
|
||||
(goto-char (point-min))
|
||||
(insert "Array Size : ")
|
||||
(setq num 0)
|
||||
(while (< num depth)
|
||||
(insert
|
||||
(concat "["
|
||||
(int-to-string (+ (aref gdb-array-size num) 1)) "]"))
|
||||
(setq num (+ num 1)))
|
||||
(insert
|
||||
(concat "\n Slice : " array-slice "\n\nIndex\tValues\n\n"))))))
|
||||
|
||||
(defun gud-gdba-marker-filter (string)
|
||||
"A gud marker filter for gdb. Handle a burst of output from GDB."
|
||||
(let (
|
||||
|
@ -1728,155 +1439,6 @@ the source buffer."
|
|||
(switch-to-buffer-other-frame
|
||||
(gdb-get-create-buffer 'gdb-locals-buffer)))
|
||||
|
||||
;;
|
||||
;; Display expression buffer.
|
||||
;;
|
||||
(gdb-set-buffer-rules 'gdb-display-buffer
|
||||
'gdb-display-buffer-name
|
||||
'gdb-display-mode)
|
||||
|
||||
(def-gdb-auto-updated-buffer gdb-display-buffer
|
||||
;; `gdb-display-buffer'.
|
||||
gdb-invalidate-display
|
||||
"server info display\n"
|
||||
gdb-info-display-handler
|
||||
gdb-info-display-custom)
|
||||
|
||||
(defun gdb-info-display-custom ()
|
||||
(let ((display-list nil))
|
||||
(with-current-buffer (gdb-get-buffer 'gdb-display-buffer)
|
||||
(goto-char (point-min))
|
||||
(while (< (point) (- (point-max) 1))
|
||||
(forward-line 1)
|
||||
(if (looking-at "\\([0-9]+\\): \\([ny]\\)")
|
||||
(setq display-list
|
||||
(cons (string-to-int (match-string 1)) display-list)))
|
||||
(end-of-line)))
|
||||
(if (not (display-graphic-p))
|
||||
(progn
|
||||
(dolist (buffer (buffer-list))
|
||||
(if (string-match "\\*display \\([0-9]+\\)\\*" (buffer-name buffer))
|
||||
(progn
|
||||
(let ((number
|
||||
(match-string 1 (buffer-name buffer))))
|
||||
(if (not (memq (string-to-int number) display-list))
|
||||
(kill-buffer
|
||||
(get-buffer (concat "*display " number "*")))))))))
|
||||
(gdb-delete-frames display-list))))
|
||||
|
||||
(defun gdb-delete-frames (display-list)
|
||||
(dolist (frame (frame-list))
|
||||
(let ((frame-name (frame-parameter frame 'name)))
|
||||
(if (string-match "\\*display \\([0-9]+\\)\\*" frame-name)
|
||||
(progn
|
||||
(let ((number (match-string 1 frame-name)))
|
||||
(if (not (memq (string-to-int number) display-list))
|
||||
(progn (kill-buffer
|
||||
(get-buffer (concat "*display " number "*")))
|
||||
(delete-frame frame)))))))))
|
||||
|
||||
(defvar gdb-display-mode-map
|
||||
(let ((map (make-sparse-keymap))
|
||||
(menu (make-sparse-keymap "Display")))
|
||||
(define-key menu [toggle] '("Toggle" . gdb-toggle-display))
|
||||
(define-key menu [delete] '("Delete" . gdb-delete-display))
|
||||
|
||||
(suppress-keymap map)
|
||||
(define-key map [menu-bar display] (cons "Display" menu))
|
||||
(define-key map " " 'gdb-toggle-display)
|
||||
(define-key map "d" 'gdb-delete-display)
|
||||
map))
|
||||
|
||||
(defun gdb-display-mode ()
|
||||
"Major mode for gdb display.
|
||||
|
||||
\\{gdb-display-mode-map}"
|
||||
(setq major-mode 'gdb-display-mode)
|
||||
(setq mode-name "Display")
|
||||
(setq buffer-read-only t)
|
||||
(use-local-map gdb-display-mode-map)
|
||||
(gdb-invalidate-display))
|
||||
|
||||
(defun gdb-display-buffer-name ()
|
||||
(with-current-buffer gud-comint-buffer
|
||||
(concat "*Displayed expressions of " (gdb-get-target-string) "*")))
|
||||
|
||||
(defun gdb-display-display-buffer ()
|
||||
(interactive)
|
||||
(gdb-display-buffer
|
||||
(gdb-get-create-buffer 'gdb-display-buffer)))
|
||||
|
||||
(defun gdb-frame-display-buffer ()
|
||||
(interactive)
|
||||
(switch-to-buffer-other-frame
|
||||
(gdb-get-create-buffer 'gdb-display-buffer)))
|
||||
|
||||
(defun gdb-toggle-display ()
|
||||
"Enable/disable the displayed expression at current line."
|
||||
(interactive)
|
||||
(save-excursion
|
||||
(beginning-of-line 1)
|
||||
(if (not (looking-at "\\([0-9]+\\): \\([ny]\\)"))
|
||||
(error "No expression on this line")
|
||||
(gdb-enqueue-input
|
||||
(list
|
||||
(concat
|
||||
(if (eq ?y (char-after (match-beginning 2)))
|
||||
"server disable display "
|
||||
"server enable display ")
|
||||
(match-string 1) "\n")
|
||||
'ignore)))))
|
||||
|
||||
(defun gdb-delete-display ()
|
||||
"Delete the displayed expression at current line."
|
||||
(interactive)
|
||||
(with-current-buffer (gdb-get-buffer 'gdb-display-buffer)
|
||||
(beginning-of-line 1)
|
||||
(if (not (looking-at "\\([0-9]+\\): \\([ny]\\)"))
|
||||
(error "No expression on this line")
|
||||
(let ((number (match-string 1)))
|
||||
(gdb-enqueue-input
|
||||
(list (concat "server delete display " number "\n") 'ignore))))))
|
||||
|
||||
(defvar gdb-expressions-mode-map
|
||||
(let ((map (make-sparse-keymap)))
|
||||
(suppress-keymap map)
|
||||
(define-key map "v" 'gdb-array-visualise)
|
||||
(define-key map "q" 'gdb-delete-expression)
|
||||
(define-key map [mouse-3] 'gdb-expressions-popup-menu)
|
||||
map))
|
||||
|
||||
(defvar gdb-expressions-mode-menu
|
||||
'("GDB Expressions Commands"
|
||||
"----"
|
||||
["Visualise" gdb-array-visualise t]
|
||||
["Delete" gdb-delete-expression t])
|
||||
"Menu for `gdb-expressions-mode'.")
|
||||
|
||||
(defun gdb-expressions-popup-menu (event)
|
||||
"Explicit Popup menu as this buffer doesn't have a menubar."
|
||||
(interactive "@e")
|
||||
(mouse-set-point event)
|
||||
(popup-menu gdb-expressions-mode-menu))
|
||||
|
||||
(defun gdb-expressions-mode ()
|
||||
"Major mode for display expressions.
|
||||
|
||||
\\{gdb-expressions-mode-map}"
|
||||
(setq major-mode 'gdb-expressions-mode)
|
||||
(setq mode-name "Expressions")
|
||||
(use-local-map gdb-expressions-mode-map)
|
||||
(make-local-variable 'gdb-display-number)
|
||||
(make-local-variable 'gdb-values)
|
||||
(make-local-variable 'gdb-expression)
|
||||
(set (make-local-variable 'gdb-display-string) nil)
|
||||
(set (make-local-variable 'gdb-dive-display-number) nil)
|
||||
(set (make-local-variable 'gud-minor-mode) 'gdba)
|
||||
(set (make-local-variable 'gdb-array-start) (make-vector 16 '-1))
|
||||
(set (make-local-variable 'gdb-array-stop) (make-vector 16 '-1))
|
||||
(set (make-local-variable 'gdb-array-size) (make-vector 16 '-1))
|
||||
(setq buffer-read-only t))
|
||||
|
||||
|
||||
;;;; Window management
|
||||
|
||||
|
@ -1943,7 +1505,6 @@ the source buffer."
|
|||
(define-key menu [registers] '("Registers" . gdb-frame-registers-buffer))
|
||||
(define-key menu [frames] '("Stack" . gdb-frame-stack-buffer))
|
||||
(define-key menu [breakpoints] '("Breakpoints" . gdb-frame-breakpoints-buffer))
|
||||
(define-key menu [display] '("Display" . gdb-frame-display-buffer))
|
||||
(define-key menu [threads] '("Threads" . gdb-frame-threads-buffer))
|
||||
; (define-key menu [assembler] '("Assembler" . gdb-frame-assembler-buffer))
|
||||
)
|
||||
|
@ -1956,7 +1517,6 @@ the source buffer."
|
|||
(define-key menu [registers] '("Registers" . gdb-display-registers-buffer))
|
||||
(define-key menu [frames] '("Stack" . gdb-display-stack-buffer))
|
||||
(define-key menu [breakpoints] '("Breakpoints" . gdb-display-breakpoints-buffer))
|
||||
(define-key menu [display] '("Display" . gdb-display-display-buffer))
|
||||
(define-key menu [threads] '("Threads" . gdb-display-threads-buffer))
|
||||
; (define-key menu [assembler] '("Assembler" . gdb-display-assembler-buffer))
|
||||
)
|
||||
|
@ -2021,7 +1581,6 @@ the source buffer."
|
|||
(gdb-display-stack-buffer)
|
||||
(delete-other-windows)
|
||||
(gdb-display-breakpoints-buffer)
|
||||
(gdb-display-display-buffer)
|
||||
(delete-other-windows)
|
||||
(switch-to-buffer gud-comint-buffer)
|
||||
(split-window nil ( / ( * (window-height) 3) 4))
|
||||
|
@ -2089,11 +1648,10 @@ This arrangement depends on the value of `gdb-many-windows'."
|
|||
(defun gdb-reset ()
|
||||
"Exit a debugging session cleanly by killing the gdb buffers and resetting
|
||||
the source buffers."
|
||||
(gdb-delete-frames '())
|
||||
(dolist (buffer (buffer-list))
|
||||
(if (not (eq buffer gud-comint-buffer))
|
||||
(with-current-buffer buffer
|
||||
(if (eq gud-minor-mode 'gdba)
|
||||
(if (memq gud-minor-mode '(gdba pdb))
|
||||
(if (string-match "^\*.+*$" (buffer-name))
|
||||
(kill-buffer nil)
|
||||
(if (display-images-p)
|
||||
|
@ -2128,7 +1686,6 @@ buffers."
|
|||
(if gdb-many-windows
|
||||
(gdb-setup-windows)
|
||||
(gdb-display-breakpoints-buffer)
|
||||
(gdb-display-display-buffer)
|
||||
(delete-other-windows)
|
||||
(split-window)
|
||||
(other-window 1)
|
||||
|
@ -2195,39 +1752,6 @@ BUFFER nil or omitted means use the current buffer."
|
|||
(when (overlay-get overlay 'put-arrow)
|
||||
(delete-overlay overlay)))
|
||||
(setq overlays (cdr overlays)))))
|
||||
|
||||
(defun gdb-array-visualise ()
|
||||
"Visualise arrays and slices using graph program from plotutils."
|
||||
(interactive)
|
||||
(when (and (display-graphic-p) gdb-display-string)
|
||||
(let ((n 0) m)
|
||||
(catch 'multi-dimensional
|
||||
(while (eq (aref gdb-array-start n) (aref gdb-array-stop n))
|
||||
(setq n (+ n 1)))
|
||||
(setq m (+ n 1))
|
||||
(while (< m (length gdb-array-start))
|
||||
(if (not (eq (aref gdb-array-start m) (aref gdb-array-stop m)))
|
||||
(progn
|
||||
(x-popup-dialog
|
||||
t `(,(concat "Only one dimensional data can be visualised.\n"
|
||||
"Use an array slice to reduce the number of\n"
|
||||
"dimensions") ("OK" t)))
|
||||
(throw 'multi-dimensional nil))
|
||||
(setq m (+ m 1))))
|
||||
(shell-command (concat "echo" gdb-display-string " | graph -a 1 "
|
||||
(int-to-string (aref gdb-array-start n))
|
||||
" -x "
|
||||
(int-to-string (aref gdb-array-start n))
|
||||
" "
|
||||
(int-to-string (aref gdb-array-stop n))
|
||||
" 1 -T X"))))))
|
||||
|
||||
(defun gdb-delete-expression ()
|
||||
"Delete displayed expression and its frame."
|
||||
(interactive)
|
||||
(gdb-enqueue-input
|
||||
(list (concat "server delete display " gdb-display-number "\n")
|
||||
'ignore)))
|
||||
|
||||
;;
|
||||
;; Assembler buffer.
|
||||
|
|
Loading…
Add table
Reference in a new issue