comparison lisp/progmodes/gdb-ui.el @ 83407:37d0562504bf

Merged in changes from CVS trunk. Patches applied: * miles@gnu.org--gnu-2005/emacs--cvs-trunk--0--patch-664 Update from CVS * miles@gnu.org--gnu-2005/emacs--cvs-trunk--0--patch-665 Update from CVS * miles@gnu.org--gnu-2005/emacs--cvs-trunk--0--patch-666 Update from CVS git-archimport-id: lorentey@elte.hu--2004/emacs--multi-tty--0--patch-447
author Karoly Lorentey <lorentey@elte.hu>
date Sat, 10 Dec 2005 21:18:28 +0000
parents 1955a4462bf9 7736e7015779
children 14a4eb789b45
comparison
equal deleted inserted replaced
83406:8e25aa911e3e 83407:37d0562504bf
76 ;;; TODO: 76 ;;; TODO:
77 77
78 ;; 1) Use MI command -data-read-memory for memory window. 78 ;; 1) Use MI command -data-read-memory for memory window.
79 ;; 2) Highlight changed register values (use MI commands 79 ;; 2) Highlight changed register values (use MI commands
80 ;; -data-list-register-values and -data-list-changed-registers instead 80 ;; -data-list-register-values and -data-list-changed-registers instead
81 ;; of 'info registers'. 81 ;; of 'info registers' after release of 22.1.
82 ;; 3) Use tree-widget.el instead of the speedbar for watch-expressions? 82 ;; 3) Use tree-widget.el instead of the speedbar for watch-expressions?
83 ;; 4) Mark breakpoint locations on scroll-bar of source buffer? 83 ;; 4) Mark breakpoint locations on scroll-bar of source buffer?
84 ;; 5) After release of 22.1, use "-var-list-children --all-values" 84 ;; 5) After release of 22.1, use "-var-list-children --all-values"
85 ;; and "-stack-list-locals --simple-values" which need GDB 6.1 onwards. 85 ;; and "-stack-list-locals --simple-values" which need GDB 6.1 onwards.
86 ;; 6) After release of 22.1, use "-var-update --all-values" which needs 86 ;; 6) After release of 22.1, use "-var-update --all-values" which needs
91 ;;; Code: 91 ;;; Code:
92 92
93 (require 'gud) 93 (require 'gud)
94 94
95 (defvar tool-bar-map) 95 (defvar tool-bar-map)
96 (defvar speedbar-initial-expansion-list-name)
96 97
97 (defvar gdb-frame-address "main" "Initialization for Assembler buffer.") 98 (defvar gdb-frame-address "main" "Initialization for Assembler buffer.")
98 (defvar gdb-previous-frame-address nil) 99 (defvar gdb-previous-frame-address nil)
99 (defvar gdb-memory-address "main") 100 (defvar gdb-memory-address "main")
100 (defvar gdb-previous-frame nil) 101 (defvar gdb-previous-frame nil)
107 (defvar gdb-overlay-arrow-position nil) 108 (defvar gdb-overlay-arrow-position nil)
108 (defvar gdb-server-prefix nil) 109 (defvar gdb-server-prefix nil)
109 (defvar gdb-flush-pending-output nil) 110 (defvar gdb-flush-pending-output nil)
110 (defvar gdb-location-alist nil 111 (defvar gdb-location-alist nil
111 "Alist of breakpoint numbers and full filenames.") 112 "Alist of breakpoint numbers and full filenames.")
112 (defvar gdb-find-file-unhook nil)
113 (defvar gdb-active-process nil "GUD tooltips display variable values when t, \ 113 (defvar gdb-active-process nil "GUD tooltips display variable values when t, \
114 and #define directives otherwise.") 114 and #define directives otherwise.")
115 (defvar gdb-error "Non-nil when GDB is reporting an error.") 115 (defvar gdb-error "Non-nil when GDB is reporting an error.")
116 (defvar gdb-macro-info nil 116 (defvar gdb-macro-info nil
117 "Non-nil if GDB knows that the inferior includes preprocessor macro info.") 117 "Non-nil if GDB knows that the inferior includes preprocessor macro info.")
154 154
155 (defvar gdb-pending-triggers '() 155 (defvar gdb-pending-triggers '()
156 "A list of trigger functions that have run later than their output 156 "A list of trigger functions that have run later than their output
157 handlers.") 157 handlers.")
158 158
159 ;; end of gdb variables 159 (defvar gdb-first-post-prompt nil)
160 (defvar gdb-version nil)
161 (defvar gdb-locals-font-lock-keywords nil)
162 (defvar gdb-source-file-list nil
163 "List of source files for the current executable")
164 (defconst gdb-error-regexp "\\^error,msg=\"\\(.+\\)\"")
165
166 (defvar gdb-locals-font-lock-keywords-1
167 '(
168 ;; var = (struct struct_tag) value
169 ( "\\(^\\(\\sw\\|[_.]\\)+\\) += +(\\(struct\\) \\(\\(\\sw\\|[_.]\\)+\\)"
170 (1 font-lock-variable-name-face)
171 (3 font-lock-keyword-face)
172 (4 font-lock-type-face))
173 ;; var = (type) value
174 ( "\\(^\\(\\sw\\|[_.]\\)+\\) += +(\\(\\(\\sw\\|[_.]\\)+\\)"
175 (1 font-lock-variable-name-face)
176 (3 font-lock-type-face))
177 ;; var = val
178 ( "\\(^\\(\\sw\\|[_.]\\)+\\) += +[^(]"
179 (1 font-lock-variable-name-face))
180 )
181 "Font lock keywords used in `gdb-local-mode'.")
182
183 (defvar gdb-locals-font-lock-keywords-2
184 '(
185 ;; var = type value
186 ( "\\(^\\(\\sw\\|[_.]\\)+\\)\t+\\(\\(\\sw\\|[_.]\\)+\\)"
187 (1 font-lock-variable-name-face)
188 (3 font-lock-type-face))
189 )
190 "Font lock keywords used in `gdb-local-mode'.")
191
192 ;; Variables for GDB 6.4+
193
194 (defvar gdb-register-names nil "List of register names.")
195 (defvar gdb-changed-registers nil
196 "List of changed register numbers (strings).")
160 197
161 ;;;###autoload 198 ;;;###autoload
162 (defun gdba (command-line) 199 (defun gdba (command-line)
163 "Run gdb on program FILE in buffer *gud-FILE*. 200 "Run gdb on program FILE in buffer *gud-FILE*.
164 The directory containing FILE becomes the initial working directory 201 The directory containing FILE becomes the initial working directory
211 ;; 248 ;;
212 (interactive (list (gud-query-cmdline 'gdba))) 249 (interactive (list (gud-query-cmdline 'gdba)))
213 ;; 250 ;;
214 ;; Let's start with a basic gud-gdb buffer and then modify it a bit. 251 ;; Let's start with a basic gud-gdb buffer and then modify it a bit.
215 (gdb command-line) 252 (gdb command-line)
216 (gdb-ann3)) 253 (gdb-init-1))
217 254
218 (defvar gdb-debug-log nil) 255 (defvar gdb-debug-log nil)
219 256
220 ;;;###autoload 257 ;;;###autoload
221 (defcustom gdb-enable-debug-log nil 258 (defcustom gdb-enable-debug-log nil
261 (interactive "P") 298 (interactive "P")
262 (setq gdb-use-inferior-io-buffer 299 (setq gdb-use-inferior-io-buffer
263 (if (null arg) 300 (if (null arg)
264 (not gdb-use-inferior-io-buffer) 301 (not gdb-use-inferior-io-buffer)
265 (> (prefix-numeric-value arg) 0))) 302 (> (prefix-numeric-value arg) 0)))
303 (message (format "Separate inferior IO %sabled"
304 (if gdb-use-inferior-io-buffer "en" "dis")))
266 (if (and gud-comint-buffer 305 (if (and gud-comint-buffer
267 (buffer-name gud-comint-buffer)) 306 (buffer-name gud-comint-buffer))
268 (condition-case nil 307 (condition-case nil
269 (if gdb-use-inferior-io-buffer 308 (if gdb-use-inferior-io-buffer
270 (gdb-restore-windows) 309 (gdb-restore-windows)
309 (unless (looking-at "\\S-+.*(.*).*") 348 (unless (looking-at "\\S-+.*(.*).*")
310 (gdb-enqueue-input 349 (gdb-enqueue-input
311 (list (concat gdb-server-prefix "print " expr "\n") 350 (list (concat gdb-server-prefix "print " expr "\n")
312 'gdb-tooltip-print)))))) 351 'gdb-tooltip-print))))))
313 352
314 (defun gdb-set-gud-minor-mode (buffer) 353 (defconst gdb-source-file-regexp "\\(.+?\\), \\|\\([^, \n].*$\\)")
315 "Set `gud-minor-mode' from find-file if appropriate." 354
355 (defun gdb-set-gud-minor-mode-existing-buffers ()
356 "Create list of source files for current GDB session."
316 (goto-char (point-min)) 357 (goto-char (point-min))
317 (unless (search-forward "No source file named " nil t) 358 (when (search-forward "read in on demand:" nil t)
318 (condition-case nil 359 (while (re-search-forward gdb-source-file-regexp nil t)
319 (gdb-enqueue-input 360 (push (or (match-string 1) (match-string 2)) gdb-source-file-list))
320 (list (concat gdb-server-prefix "info source\n") 361 (dolist (buffer (buffer-list))
321 `(lambda () (gdb-set-gud-minor-mode-1 ,buffer)))) 362 (with-current-buffer buffer
322 (error (setq gdb-find-file-unhook t))))) 363 (when (and buffer-file-name
323 364 (member (file-name-nondirectory buffer-file-name)
324 (defun gdb-set-gud-minor-mode-1 (buffer) 365 gdb-source-file-list))
325 (goto-char (point-min)) 366 (set (make-local-variable 'gud-minor-mode) 'gdba)
326 (when (and (search-forward "Located in " nil t) 367 (set (make-local-variable 'tool-bar-map) gud-tool-bar-map)
327 (looking-at "\\S-+") 368 (when gud-tooltip-mode
328 (string-equal (buffer-file-name buffer) 369 (make-local-variable 'gdb-define-alist)
329 (match-string 0))) 370 (gdb-create-define-alist)
330 (with-current-buffer buffer 371 (add-hook 'after-save-hook 'gdb-create-define-alist nil t)))))))
331 (set (make-local-variable 'gud-minor-mode) 'gdba)
332 (set (make-local-variable 'tool-bar-map) gud-tool-bar-map)
333 (when gud-tooltip-mode
334 (make-local-variable 'gdb-define-alist)
335 (gdb-create-define-alist)
336 (add-hook 'after-save-hook 'gdb-create-define-alist nil t)))))
337
338 (defun gdb-set-gud-minor-mode-existing-buffers ()
339 (dolist (buffer (buffer-list))
340 (let ((file (buffer-file-name buffer)))
341 (if file
342 (progn
343 (gdb-enqueue-input
344 (list (concat gdb-server-prefix "list "
345 (file-name-nondirectory file) ":1\n")
346 `(lambda () (gdb-set-gud-minor-mode ,buffer)))))))))
347 372
348 (defun gdb-find-watch-expression () 373 (defun gdb-find-watch-expression ()
349 (let* ((var (nth (- (line-number-at-pos (point)) 2) gdb-var-list)) 374 (let* ((var (nth (- (line-number-at-pos (point)) 2) gdb-var-list))
350 (varno (nth 1 var)) (expr)) 375 (varno (nth 1 var)) (expr))
351 (string-match "\\(var[0-9]+\\)\\.\\(.*\\)" varno) 376 (string-match "\\(var[0-9]+\\)\\.\\(.*\\)" varno)
352 (dolist (var1 gdb-var-list) 377 (dolist (var1 gdb-var-list)
353 (if (string-equal (nth 1 var1) (match-string 1 varno)) 378 (if (string-equal (nth 1 var1) (match-string 1 varno))
354 (setq expr (concat (car var1) "." (match-string 2 varno))))) 379 (setq expr (concat (car var1) "." (match-string 2 varno)))))
355 expr)) 380 expr))
356 381
357 (defun gdb-ann3 () 382 (defun gdb-init-1 ()
358 (setq gdb-debug-log nil) 383 (setq gdb-debug-log nil)
359 (set (make-local-variable 'gud-minor-mode) 'gdba) 384 (set (make-local-variable 'gud-minor-mode) 'gdba)
360 (set (make-local-variable 'gud-marker-filter) 'gud-gdba-marker-filter) 385 (set (make-local-variable 'gud-marker-filter) 'gud-gdba-marker-filter)
361 ;; 386 ;;
362 (gud-def gud-break (if (not (string-match "Machine" mode-name)) 387 (gud-def gud-break (if (not (string-match "Machine" mode-name))
374 (forward-char 2) 399 (forward-char 2)
375 (gud-call "clear *%a" arg))) 400 (gud-call "clear *%a" arg)))
376 "\C-d" "Remove breakpoint at current line or address.") 401 "\C-d" "Remove breakpoint at current line or address.")
377 ;; 402 ;;
378 (gud-def gud-until (if (not (string-match "Machine" mode-name)) 403 (gud-def gud-until (if (not (string-match "Machine" mode-name))
379 (gud-call "until %f:%l" arg) 404 (gud-call "until %f:%l" arg)
380 (save-excursion 405 (save-excursion
381 (beginning-of-line) 406 (beginning-of-line)
382 (forward-char 2) 407 (forward-char 2)
383 (gud-call "until *%a" arg))) 408 (gud-call "until *%a" arg)))
384 "\C-u" "Continue to current line or address.") 409 "\C-u" "Continue to current line or address.")
385 ;; 410 ;;
386 (gud-def gud-go (gud-call (if gdb-active-process "continue" "run") arg) 411 (gud-def gud-go (gud-call (if gdb-active-process "continue" "run") arg)
387 nil "Start or continue execution.") 412 nil "Start or continue execution.")
388 413
409 'gdb-mouse-toggle-breakpoint-margin) 434 'gdb-mouse-toggle-breakpoint-margin)
410 (define-key gud-minor-mode-map [left-fringe mouse-3] 435 (define-key gud-minor-mode-map [left-fringe mouse-3]
411 'gdb-mouse-toggle-breakpoint-fringe) 436 'gdb-mouse-toggle-breakpoint-fringe)
412 437
413 (setq comint-input-sender 'gdb-send) 438 (setq comint-input-sender 'gdb-send)
414 ;; 439
415 ;; (re-)initialize 440 ;; (re-)initialize
416 (setq gdb-frame-address (if gdb-show-main "main" nil)) 441 (setq gdb-frame-address (if gdb-show-main "main" nil))
417 (setq gdb-previous-frame-address nil 442 (setq gdb-previous-frame-address nil
418 gdb-memory-address "main" 443 gdb-memory-address "main"
419 gdb-previous-frame nil 444 gdb-previous-frame nil
420 gdb-selected-frame nil 445 gdb-selected-frame nil
421 gdb-current-language nil 446 gdb-current-language nil
422 gdb-frame-number nil 447 gdb-frame-number nil
423 gdb-var-list nil 448 gdb-var-list nil
424 gdb-var-changed nil 449 gdb-var-changed nil
425 gdb-first-prompt nil 450 gdb-first-post-prompt t
426 gdb-prompting nil 451 gdb-prompting nil
427 gdb-input-queue nil 452 gdb-input-queue nil
428 gdb-current-item nil 453 gdb-current-item nil
429 gdb-pending-triggers nil 454 gdb-pending-triggers nil
430 gdb-output-sink 'user 455 gdb-output-sink 'user
431 gdb-server-prefix "server " 456 gdb-server-prefix "server "
432 gdb-flush-pending-output nil 457 gdb-flush-pending-output nil
433 gdb-location-alist nil 458 gdb-location-alist nil
434 gdb-find-file-unhook nil 459 gdb-source-file-list nil
435 gdb-error nil 460 gdb-error nil
436 gdb-macro-info nil 461 gdb-macro-info nil
437 gdb-buffer-fringe-width (car (window-fringes))) 462 gdb-buffer-fringe-width (car (window-fringes)))
438 ;; 463
439 (setq gdb-buffer-type 'gdba) 464 (setq gdb-buffer-type 'gdba)
440 ;; 465
441 (if gdb-use-inferior-io-buffer (gdb-clear-inferior-io)) 466 (if gdb-use-inferior-io-buffer (gdb-clear-inferior-io))
442 ;; 467
468 ;; Hack to see test for GDB 6.4+ (-stack-info-frame was implemented in 6.4)
469 (setq gdb-version nil)
470 (gdb-enqueue-input (list "server interpreter mi -stack-info-frame\n"
471 'gdb-get-version)))
472
473 (defun gdb-init-2 ()
443 (if (eq window-system 'w32) 474 (if (eq window-system 'w32)
444 (gdb-enqueue-input (list "set new-console off\n" 'ignore))) 475 (gdb-enqueue-input (list "set new-console off\n" 'ignore)))
445 (gdb-enqueue-input (list "set height 0\n" 'ignore)) 476 (gdb-enqueue-input (list "set height 0\n" 'ignore))
446 (gdb-enqueue-input (list "set width 0\n" 'ignore)) 477 (gdb-enqueue-input (list "set width 0\n" 'ignore))
478
479 (if (string-equal gdb-version "pre-6.4")
480 (progn
481 (gdb-enqueue-input (list (concat gdb-server-prefix "info sources\n")
482 'gdb-set-gud-minor-mode-existing-buffers))
483 (setq gdb-locals-font-lock-keywords gdb-locals-font-lock-keywords-1))
484 (gdb-enqueue-input
485 (list "server interpreter mi -data-list-register-names\n"
486 'gdb-get-register-names))
487 ; Needs GDB 6.2 onwards.
488 (gdb-enqueue-input
489 (list "server interpreter mi \"-file-list-exec-source-files\"\n"
490 'gdb-set-gud-minor-mode-existing-buffers-1))
491 (setq gdb-locals-font-lock-keywords gdb-locals-font-lock-keywords-2))
492
447 ;; find source file and compilation directory here 493 ;; find source file and compilation directory here
448 (gdb-enqueue-input (list "server list main\n" 'ignore)) ; C program 494 (gdb-enqueue-input (list "server list main\n" 'ignore)) ; C program
449 (gdb-enqueue-input (list "server list MAIN__\n" 'ignore)) ; Fortran program 495 (gdb-enqueue-input (list "server list MAIN__\n" 'ignore)) ; Fortran program
450 (gdb-enqueue-input (list "server info source\n" 'gdb-source-info)) 496 (gdb-enqueue-input (list "server info source\n" 'gdb-source-info))
451 ;; 497
452 (gdb-set-gud-minor-mode-existing-buffers)
453 (run-hooks 'gdba-mode-hook)) 498 (run-hooks 'gdba-mode-hook))
499
500 (defun gdb-get-version ()
501 (goto-char (point-min))
502 (if (and (re-search-forward gdb-error-regexp nil t)
503 (string-match ".*(missing implementation)" (match-string 1)))
504 (setq gdb-version "pre-6.4")
505 (setq gdb-version "6.4+"))
506 (gdb-init-2))
454 507
455 (defun gdb-mouse-until (event) 508 (defun gdb-mouse-until (event)
456 "Execute source lines by dragging the overlay arrow (fringe) with the mouse." 509 "Execute source lines by dragging the overlay arrow (fringe) with the mouse."
457 (interactive "e") 510 (interactive "e")
458 (if gud-overlay-arrow-position 511 (if gud-overlay-arrow-position
490 "Toggle automatic raising of the speedbar for watch expressions." 543 "Toggle automatic raising of the speedbar for watch expressions."
491 (interactive "P") 544 (interactive "P")
492 (setq gdb-speedbar-auto-raise 545 (setq gdb-speedbar-auto-raise
493 (if (null arg) 546 (if (null arg)
494 (not gdb-speedbar-auto-raise) 547 (not gdb-speedbar-auto-raise)
495 (> (prefix-numeric-value arg) 0)))) 548 (> (prefix-numeric-value arg) 0)))
549 (message (format "Auto raising %sabled"
550 (if gdb-speedbar-auto-raise "en" "dis"))))
496 551
497 (defcustom gdb-use-colon-colon-notation nil 552 (defcustom gdb-use-colon-colon-notation nil
498 "If non-nil use FUN::VAR format to display variables in the speedbar." 553 "If non-nil use FUN::VAR format to display variables in the speedbar."
499 :type 'boolean 554 :type 'boolean
500 :group 'gud 555 :group 'gud
501 :version "22.1") 556 :version "22.1")
502 557
503 (defun gud-watch () 558 (defun gud-watch (&optional event)
504 "Watch expression at point." 559 "Watch expression at point."
505 (interactive) 560 (interactive (list last-input-event))
561 (if event (posn-set-point (event-end event)))
506 (require 'tooltip) 562 (require 'tooltip)
507 (save-selected-window 563 (save-selected-window
508 (let ((expr (tooltip-identifier-from-point (point)))) 564 (let ((expr (tooltip-identifier-from-point (point))))
509 (if (and (string-equal gdb-current-language "c") 565 (if (and (string-equal gdb-current-language "c")
510 gdb-use-colon-colon-notation gdb-selected-frame) 566 gdb-use-colon-colon-notation gdb-selected-frame)
522 578
523 (defconst gdb-var-create-regexp 579 (defconst gdb-var-create-regexp
524 "name=\"\\(.*?\\)\",numchild=\"\\(.*?\\)\",type=\"\\(.*?\\)\"") 580 "name=\"\\(.*?\\)\",numchild=\"\\(.*?\\)\",type=\"\\(.*?\\)\"")
525 581
526 (defun gdb-var-create-handler (expr) 582 (defun gdb-var-create-handler (expr)
527 (with-current-buffer (gdb-get-create-buffer 'gdb-partial-output-buffer) 583 (goto-char (point-min))
528 (goto-char (point-min)) 584 (if (re-search-forward gdb-var-create-regexp nil t)
529 (if (re-search-forward gdb-var-create-regexp nil t) 585 (let ((var (list expr
530 (let ((var (list expr 586 (match-string 1)
531 (match-string 1) 587 (match-string 2)
532 (match-string 2) 588 (match-string 3)
533 (match-string 3) 589 nil nil)))
534 nil nil))) 590 (push var gdb-var-list)
535 (push var gdb-var-list) 591 (speedbar 1)
536 (speedbar 1) 592 (unless (string-equal
537 (unless (string-equal 593 speedbar-initial-expansion-list-name "GUD")
538 speedbar-initial-expansion-list-name "GUD") 594 (speedbar-change-initial-expansion-list "GUD"))
539 (speedbar-change-initial-expansion-list "GUD")) 595 (gdb-enqueue-input
540 (gdb-enqueue-input 596 (list
541 (list 597 (if (eq (buffer-local-value 'gud-minor-mode gud-comint-buffer)
542 (if (eq (buffer-local-value 'gud-minor-mode gud-comint-buffer) 598 'gdba)
543 'gdba) 599 (concat "server interpreter mi \"-var-evaluate-expression "
544 (concat "server interpreter mi \"-var-evaluate-expression " 600 (nth 1 var) "\"\n")
545 (nth 1 var) "\"\n") 601 (concat "-var-evaluate-expression " (nth 1 var) "\n"))
546 (concat "-var-evaluate-expression " (nth 1 var) "\n")) 602 `(lambda () (gdb-var-evaluate-expression-handler
547 `(lambda () (gdb-var-evaluate-expression-handler 603 ,(nth 1 var) nil))))
548 ,(nth 1 var) nil)))) 604 (setq gdb-var-changed t))
549 (setq gdb-var-changed t)) 605 (if (search-forward "Undefined command" nil t)
550 (if (re-search-forward "Undefined command" nil t) 606 (message-box "Watching expressions requires gdb 6.0 onwards")
551 (message-box "Watching expressions requires gdb 6.0 onwards") 607 (message "No symbol \"%s\" in current context." expr))))
552 (message "No symbol \"%s\" in current context." expr)))))
553 608
554 (defun gdb-var-evaluate-expression-handler (varnum changed) 609 (defun gdb-var-evaluate-expression-handler (varnum changed)
555 (with-current-buffer (gdb-get-create-buffer 'gdb-partial-output-buffer) 610 (goto-char (point-min))
556 (goto-char (point-min)) 611 (re-search-forward ".*value=\\(\".*\"\\)" nil t)
557 (re-search-forward ".*value=\\(\".*\"\\)" nil t) 612 (catch 'var-found
558 (catch 'var-found 613 (let ((num 0))
559 (let ((num 0)) 614 (dolist (var gdb-var-list)
560 (dolist (var gdb-var-list) 615 (if (string-equal varnum (cadr var))
561 (if (string-equal varnum (cadr var)) 616 (progn
562 (progn 617 (if changed (setcar (nthcdr 5 var) t))
563 (if changed (setcar (nthcdr 5 var) t)) 618 (setcar (nthcdr 4 var) (read (match-string 1)))
564 (setcar (nthcdr 4 var) (read (match-string 1))) 619 (setcar (nthcdr num gdb-var-list) var)
565 (setcar (nthcdr num gdb-var-list) var) 620 (throw 'var-found nil)))
566 (throw 'var-found nil))) 621 (setq num (+ num 1)))))
567 (setq num (+ num 1))))))
568 (setq gdb-var-changed t)) 622 (setq gdb-var-changed t))
569 623
570 (defun gdb-var-list-children (varnum) 624 (defun gdb-var-list-children (varnum)
571 (gdb-enqueue-input 625 (gdb-enqueue-input
572 (list (concat "server interpreter mi \"-var-list-children " varnum "\"\n") 626 (list (concat "server interpreter mi \"-var-list-children " varnum "\"\n")
575 (defconst gdb-var-list-children-regexp 629 (defconst gdb-var-list-children-regexp
576 "name=\"\\(.*?\\)\",exp=\"\\(.*?\\)\",numchild=\"\\(.*?\\)\",\ 630 "name=\"\\(.*?\\)\",exp=\"\\(.*?\\)\",numchild=\"\\(.*?\\)\",\
577 type=\"\\(.*?\\)\"") 631 type=\"\\(.*?\\)\"")
578 632
579 (defun gdb-var-list-children-handler (varnum) 633 (defun gdb-var-list-children-handler (varnum)
580 (with-current-buffer (gdb-get-create-buffer 'gdb-partial-output-buffer) 634 (goto-char (point-min))
581 (goto-char (point-min)) 635 (let ((var-list nil))
582 (let ((var-list nil)) 636 (catch 'child-already-watched
583 (catch 'child-already-watched 637 (dolist (var gdb-var-list)
584 (dolist (var gdb-var-list) 638 (if (string-equal varnum (cadr var))
585 (if (string-equal varnum (cadr var)) 639 (progn
586 (progn 640 (push var var-list)
587 (push var var-list) 641 (while (re-search-forward gdb-var-list-children-regexp nil t)
588 (while (re-search-forward gdb-var-list-children-regexp nil t) 642 (let ((varchild (list (match-string 2)
589 (let ((varchild (list (match-string 2) 643 (match-string 1)
590 (match-string 1) 644 (match-string 3)
591 (match-string 3) 645 (match-string 4)
592 (match-string 4) 646 nil nil)))
593 nil nil))) 647 (dolist (var1 gdb-var-list)
594 (dolist (var1 gdb-var-list) 648 (if (string-equal (cadr var1) (cadr varchild))
595 (if (string-equal (cadr var1) (cadr varchild)) 649 (throw 'child-already-watched nil)))
596 (throw 'child-already-watched nil))) 650 (push varchild var-list)
597 (push varchild var-list) 651 (gdb-enqueue-input
598 (gdb-enqueue-input 652 (list
599 (list 653 (concat
600 (concat 654 "server interpreter mi \"-var-evaluate-expression "
601 "server interpreter mi \"-var-evaluate-expression " 655 (nth 1 varchild) "\"\n")
602 (nth 1 varchild) "\"\n") 656 `(lambda () (gdb-var-evaluate-expression-handler
603 `(lambda () (gdb-var-evaluate-expression-handler 657 ,(nth 1 varchild) nil)))))))
604 ,(nth 1 varchild) nil))))))) 658 (push var var-list)))
605 (push var var-list))) 659 (setq gdb-var-list (nreverse var-list)))))
606 (setq gdb-var-list (nreverse var-list))))))
607 660
608 (defun gdb-var-update () 661 (defun gdb-var-update ()
609 (when (not (member 'gdb-var-update gdb-pending-triggers)) 662 (when (not (member 'gdb-var-update gdb-pending-triggers))
610 (gdb-enqueue-input 663 (gdb-enqueue-input
611 (list "server interpreter mi \"-var-update *\"\n" 664 (list "server interpreter mi \"-var-update *\"\n"
613 (push 'gdb-var-update gdb-pending-triggers))) 666 (push 'gdb-var-update gdb-pending-triggers)))
614 667
615 (defconst gdb-var-update-regexp "name=\"\\(.*?\\)\"") 668 (defconst gdb-var-update-regexp "name=\"\\(.*?\\)\"")
616 669
617 (defun gdb-var-update-handler () 670 (defun gdb-var-update-handler ()
618 (with-current-buffer (gdb-get-create-buffer 'gdb-partial-output-buffer) 671 (goto-char (point-min))
619 (goto-char (point-min)) 672 (while (re-search-forward gdb-var-update-regexp nil t)
620 (while (re-search-forward gdb-var-update-regexp nil t) 673 (catch 'var-found-1
621 (catch 'var-found-1 674 (let ((varnum (match-string 1)))
622 (let ((varnum (match-string 1))) 675 (dolist (var gdb-var-list)
623 (dolist (var gdb-var-list) 676 (gdb-enqueue-input
624 (gdb-enqueue-input 677 (list
625 (list 678 (concat "server interpreter mi \"-var-evaluate-expression "
626 (concat "server interpreter mi \"-var-evaluate-expression " 679 varnum "\"\n")
627 varnum "\"\n") 680 `(lambda () (gdb-var-evaluate-expression-handler ,varnum t))))
628 `(lambda () (gdb-var-evaluate-expression-handler ,varnum t)))) 681 (throw 'var-found-1 nil)))))
629 (throw 'var-found-1 nil))))))
630 (setq gdb-pending-triggers 682 (setq gdb-pending-triggers
631 (delq 'gdb-var-update gdb-pending-triggers)) 683 (delq 'gdb-var-update gdb-pending-triggers))
632 (when (and (boundp 'speedbar-frame) (frame-live-p speedbar-frame)) 684 (when (and (boundp 'speedbar-frame) (frame-live-p speedbar-frame))
633 ;; Dummy command to update speedbar at right time. 685 ;; Dummy command to update speedbar at right time.
634 (gdb-enqueue-input (list "server pwd\n" 'gdb-speedbar-timer-fn)) 686 (gdb-enqueue-input (list "server pwd\n" 'gdb-speedbar-timer-fn))
635 ;; Keep gdb-pending-triggers non-nil till end. 687 ;; Keep gdb-pending-triggers non-nil till end.
636 (push 'gdb-speedbar-timer gdb-pending-triggers))) 688 (push 'gdb-speedbar-timer gdb-pending-triggers)))
690 TEXT is the text of the button we clicked on, a + or - item. 742 TEXT is the text of the button we clicked on, a + or - item.
691 TOKEN is data related to this node. 743 TOKEN is data related to this node.
692 INDENT is the current indentation depth." 744 INDENT is the current indentation depth."
693 (cond ((string-match "+" text) ;expand this node 745 (cond ((string-match "+" text) ;expand this node
694 (if (eq (buffer-local-value 'gud-minor-mode gud-comint-buffer) 'gdba) 746 (if (eq (buffer-local-value 'gud-minor-mode gud-comint-buffer) 'gdba)
695 (gdb-var-list-children token) 747 (if (string-equal gdb-version "pre-6.4")
748 (gdb-var-list-children token)
749 (gdb-var-list-children-1 token))
696 (progn 750 (progn
697 (gdbmi-var-update) 751 (gdbmi-var-update)
698 (gdbmi-var-list-children token)))) 752 (gdbmi-var-list-children token))))
699 ((string-match "-" text) ;contract this node 753 ((string-match "-" text) ;contract this node
700 (dolist (var gdb-var-list) 754 (dolist (var gdb-var-list)
779 gdb-buffer-rules-assoc)))) 833 gdb-buffer-rules-assoc))))
780 834
781 ;; GUD buffers are an exception to the rules 835 ;; GUD buffers are an exception to the rules
782 (gdb-set-buffer-rules 'gdba 'error) 836 (gdb-set-buffer-rules 'gdba 'error)
783 837
784 ;;
785 ;; Partial-output buffer : This accumulates output from a command executed on 838 ;; Partial-output buffer : This accumulates output from a command executed on
786 ;; behalf of emacs (rather than the user). 839 ;; behalf of emacs (rather than the user).
787 ;; 840 ;;
788 (gdb-set-buffer-rules 'gdb-partial-output-buffer 841 (gdb-set-buffer-rules 'gdb-partial-output-buffer
789 'gdb-partial-output-name) 842 'gdb-partial-output-name)
875 (interactive) 928 (interactive)
876 (process-send-eof 929 (process-send-eof
877 (get-buffer-process gud-comint-buffer))) 930 (get-buffer-process gud-comint-buffer)))
878 931
879 932
880 ;;
881 ;; gdb communications 933 ;; gdb communications
882 ;; 934 ;;
883 935
884 ;; INPUT: things sent to gdb 936 ;; INPUT: things sent to gdb
885 ;; 937 ;;
1029 (error "Phase error in gdb-pre-prompt (got %s)" sink))))) 1081 (error "Phase error in gdb-pre-prompt (got %s)" sink)))))
1030 1082
1031 (defun gdb-prompt (ignored) 1083 (defun gdb-prompt (ignored)
1032 "An annotation handler for `prompt'. 1084 "An annotation handler for `prompt'.
1033 This sends the next command (if any) to gdb." 1085 This sends the next command (if any) to gdb."
1034 (when gdb-first-prompt (gdb-ann3)) 1086 (when gdb-first-prompt
1087 (gdb-init-1)
1088 (setq gdb-first-prompt nil))
1035 (let ((sink gdb-output-sink)) 1089 (let ((sink gdb-output-sink))
1036 (cond 1090 (cond
1037 ((eq sink 'user) t) 1091 ((eq sink 'user) t)
1038 ((eq sink 'post-emacs) 1092 ((eq sink 'post-emacs)
1039 (setq gdb-output-sink 'user) 1093 (setq gdb-output-sink 'user)
1126 1180
1127 (defun gdb-post-prompt (ignored) 1181 (defun gdb-post-prompt (ignored)
1128 "An annotation handler for `post-prompt'. 1182 "An annotation handler for `post-prompt'.
1129 This begins the collection of output from the current command if that 1183 This begins the collection of output from the current command if that
1130 happens to be appropriate." 1184 happens to be appropriate."
1131 (unless gdb-pending-triggers 1185 ;; Don't add to queue if there outstanding items or GDB is not known yet.
1186 (unless (or gdb-pending-triggers gdb-first-post-prompt)
1132 (gdb-get-selected-frame) 1187 (gdb-get-selected-frame)
1133 (gdb-invalidate-frames) 1188 (gdb-invalidate-frames)
1134 (gdb-invalidate-breakpoints) 1189 (gdb-invalidate-breakpoints)
1135 ;; Do this through gdb-get-selected-frame -> gdb-frame-handler 1190 ;; Do this through gdb-get-selected-frame -> gdb-frame-handler
1136 ;; so gdb-frame-address is updated. 1191 ;; so gdb-frame-address is updated.
1137 ;; (gdb-invalidate-assembler) 1192 ;; (gdb-invalidate-assembler)
1138 (gdb-invalidate-registers) 1193
1194 (if (string-equal gdb-version "pre-6.4")
1195 (gdb-invalidate-registers)
1196 (gdb-get-changed-registers)
1197 (gdb-invalidate-registers-1))
1198
1139 (gdb-invalidate-memory) 1199 (gdb-invalidate-memory)
1140 (gdb-invalidate-locals) 1200 (if (string-equal gdb-version "pre-6.4")
1201 (gdb-invalidate-locals)
1202 (gdb-invalidate-locals-1))
1203
1141 (gdb-invalidate-threads) 1204 (gdb-invalidate-threads)
1142 (unless (eq system-type 'darwin) ;Breaks on Darwin's GDB-5.3. 1205 (unless (eq system-type 'darwin) ;Breaks on Darwin's GDB-5.3.
1143 ;; FIXME: with GDB-6 on Darwin, this might very well work. 1206 ;; FIXME: with GDB-6 on Darwin, this might very well work.
1144 ;; Only needed/used with speedbar/watch expressions. 1207 ;; Only needed/used with speedbar/watch expressions.
1145 (when (and (boundp 'speedbar-frame) (frame-live-p speedbar-frame)) 1208 (when (and (boundp 'speedbar-frame) (frame-live-p speedbar-frame))
1146 (setq gdb-var-changed t) ; force update 1209 (setq gdb-var-changed t) ; force update
1147 (dolist (var gdb-var-list) 1210 (dolist (var gdb-var-list)
1148 (setcar (nthcdr 5 var) nil)) 1211 (setcar (nthcdr 5 var) nil))
1149 (gdb-var-update)))) 1212 (if (string-equal gdb-version "pre-6.4")
1213 (gdb-var-update)
1214 (gdb-var-update-1)))))
1215 (setq gdb-first-post-prompt nil)
1150 (let ((sink gdb-output-sink)) 1216 (let ((sink gdb-output-sink))
1151 (cond 1217 (cond
1152 ((eq sink 'user) t) 1218 ((eq sink 'user) t)
1153 ((eq sink 'pre-emacs) 1219 ((eq sink 'pre-emacs)
1154 (setq gdb-output-sink 'emacs)) 1220 (setq gdb-output-sink 'emacs))
1734 (kill-all-local-variables) 1800 (kill-all-local-variables)
1735 (setq major-mode 'gdb-frames-mode) 1801 (setq major-mode 'gdb-frames-mode)
1736 (setq mode-name "Frames") 1802 (setq mode-name "Frames")
1737 (setq buffer-read-only t) 1803 (setq buffer-read-only t)
1738 (use-local-map gdb-frames-mode-map) 1804 (use-local-map gdb-frames-mode-map)
1739 (font-lock-mode -1)
1740 (run-mode-hooks 'gdb-frames-mode-hook) 1805 (run-mode-hooks 'gdb-frames-mode-hook)
1741 (if (eq (buffer-local-value 'gud-minor-mode gud-comint-buffer) 'gdba) 1806 (if (eq (buffer-local-value 'gud-minor-mode gud-comint-buffer) 'gdba)
1742 'gdb-invalidate-frames 1807 'gdb-invalidate-frames
1743 'gdbmi-invalidate-frames)) 1808 'gdbmi-invalidate-frames))
1744 1809
1897 (defvar gdb-registers-mode-map 1962 (defvar gdb-registers-mode-map
1898 (let ((map (make-sparse-keymap))) 1963 (let ((map (make-sparse-keymap)))
1899 (suppress-keymap map) 1964 (suppress-keymap map)
1900 (define-key map "\r" 'gdb-edit-register-value) 1965 (define-key map "\r" 'gdb-edit-register-value)
1901 (define-key map [mouse-2] 'gdb-edit-register-value) 1966 (define-key map [mouse-2] 'gdb-edit-register-value)
1902 (define-key map " " 'toggle-gdb-all-registers) 1967 (define-key map " " 'gdb-all-registers)
1903 (define-key map "q" 'kill-this-buffer) 1968 (define-key map "q" 'kill-this-buffer)
1904 map)) 1969 map))
1905 1970
1906 (defun gdb-registers-mode () 1971 (defun gdb-registers-mode ()
1907 "Major mode for gdb registers. 1972 "Major mode for gdb registers.
1908 1973
1909 \\{gdb-registers-mode-map}" 1974 \\{gdb-registers-mode-map}"
1910 (kill-all-local-variables) 1975 (kill-all-local-variables)
1911 (setq major-mode 'gdb-registers-mode) 1976 (setq major-mode 'gdb-registers-mode)
1912 (setq mode-name "Registers:") 1977 (setq mode-name "Registers")
1913 (setq buffer-read-only t) 1978 (setq buffer-read-only t)
1914 (use-local-map gdb-registers-mode-map) 1979 (use-local-map gdb-registers-mode-map)
1915 (run-mode-hooks 'gdb-registers-mode-hook) 1980 (run-mode-hooks 'gdb-registers-mode-hook)
1916 (if (eq (buffer-local-value 'gud-minor-mode gud-comint-buffer) 'gdba) 1981 (if (string-equal gdb-version "pre-6.4")
1917 'gdb-invalidate-registers 1982 (progn
1918 'gdbmi-invalidate-registers)) 1983 (if gdb-all-registers (setq mode-name "Registers:All"))
1984 'gdb-invalidate-registers)
1985 'gdb-invalidate-registers-1))
1919 1986
1920 (defun gdb-registers-buffer-name () 1987 (defun gdb-registers-buffer-name ()
1921 (with-current-buffer gud-comint-buffer 1988 (with-current-buffer gud-comint-buffer
1922 (concat "*registers of " (gdb-get-target-string) "*"))) 1989 (concat "*registers of " (gdb-get-target-string) "*")))
1923 1990
1932 (interactive) 1999 (interactive)
1933 (let ((special-display-regexps (append special-display-regexps '(".*"))) 2000 (let ((special-display-regexps (append special-display-regexps '(".*")))
1934 (special-display-frame-alist gdb-frame-parameters)) 2001 (special-display-frame-alist gdb-frame-parameters))
1935 (display-buffer (gdb-get-create-buffer 'gdb-registers-buffer)))) 2002 (display-buffer (gdb-get-create-buffer 'gdb-registers-buffer))))
1936 2003
1937 (defun toggle-gdb-all-registers () 2004 (defun gdb-all-registers ()
1938 "Toggle the display of floating-point registers." 2005 "Toggle the display of floating-point registers (pre GDB 6.4 only)."
1939 (interactive) 2006 (interactive)
1940 (if gdb-all-registers 2007 (when (string-equal gdb-version "pre-6.4")
1941 (progn 2008 (if gdb-all-registers
1942 (setq gdb-all-registers nil) 2009 (progn
1943 (with-current-buffer (gdb-get-buffer 'gdb-registers-buffer) 2010 (setq gdb-all-registers nil)
1944 (setq mode-name "Registers:"))) 2011 (with-current-buffer (gdb-get-create-buffer 'gdb-registers-buffer)
1945 (setq gdb-all-registers t) 2012 (setq mode-name "Registers")))
1946 (with-current-buffer (gdb-get-buffer 'gdb-registers-buffer) 2013 (setq gdb-all-registers t)
1947 (setq mode-name "Registers:All"))) 2014 (with-current-buffer (gdb-get-create-buffer 'gdb-registers-buffer)
1948 (gdb-invalidate-registers)) 2015 (setq mode-name "Registers:All")))
2016 (message (format "Display of floating-point registers %sabled"
2017 (if gdb-all-registers "en" "dis")))
2018 (gdb-invalidate-registers)))
1949 2019
1950 2020
1951 ;; Memory buffer. 2021 ;; Memory buffer.
1952 ;; 2022 ;;
1953 (defcustom gdb-memory-repeat-count 32 2023 (defcustom gdb-memory-repeat-count 32
2047 "Set the display format to hexadecimal." 2117 "Set the display format to hexadecimal."
2048 (interactive) 2118 (interactive)
2049 (customize-set-variable 'gdb-memory-format "x") 2119 (customize-set-variable 'gdb-memory-format "x")
2050 (gdb-invalidate-memory)) 2120 (gdb-invalidate-memory))
2051 2121
2052 (defvar gdb-memory-format-keymap 2122 (defvar gdb-memory-format-map
2053 (let ((map (make-sparse-keymap))) 2123 (let ((map (make-sparse-keymap)))
2054 (define-key map [header-line down-mouse-3] 'gdb-memory-format-menu-1) 2124 (define-key map [header-line down-mouse-3] 'gdb-memory-format-menu-1)
2055 map) 2125 map)
2056 "Keymap to select format in the header line.") 2126 "Keymap to select format in the header line.")
2057 2127
2109 "Set the unit size to bytes." 2179 "Set the unit size to bytes."
2110 (interactive) 2180 (interactive)
2111 (customize-set-variable 'gdb-memory-unit "b") 2181 (customize-set-variable 'gdb-memory-unit "b")
2112 (gdb-invalidate-memory)) 2182 (gdb-invalidate-memory))
2113 2183
2114 (defvar gdb-memory-unit-keymap 2184 (defvar gdb-memory-unit-map
2115 (let ((map (make-sparse-keymap))) 2185 (let ((map (make-sparse-keymap)))
2116 (define-key map [header-line down-mouse-3] 'gdb-memory-unit-menu-1) 2186 (define-key map [header-line down-mouse-3] 'gdb-memory-unit-menu-1)
2117 map) 2187 map)
2118 "Keymap to select units in the header line.") 2188 "Keymap to select units in the header line.")
2119 2189
2224 " Display Format: " 2294 " Display Format: "
2225 (propertize gdb-memory-format 2295 (propertize gdb-memory-format
2226 'face font-lock-warning-face 2296 'face font-lock-warning-face
2227 'help-echo "mouse-3: Select display format" 2297 'help-echo "mouse-3: Select display format"
2228 'mouse-face 'mode-line-highlight 2298 'mouse-face 'mode-line-highlight
2229 'local-map gdb-memory-format-keymap) 2299 'local-map gdb-memory-format-map)
2230 " Unit Size: " 2300 " Unit Size: "
2231 (propertize gdb-memory-unit 2301 (propertize gdb-memory-unit
2232 'face font-lock-warning-face 2302 'face font-lock-warning-face
2233 'help-echo "mouse-3: Select unit size" 2303 'help-echo "mouse-3: Select unit size"
2234 'mouse-face 'mode-line-highlight 2304 'mouse-face 'mode-line-highlight
2235 'local-map gdb-memory-unit-keymap)))) 2305 'local-map gdb-memory-unit-map))))
2236 (set (make-local-variable 'font-lock-defaults) 2306 (set (make-local-variable 'font-lock-defaults)
2237 '(gdb-memory-font-lock-keywords)) 2307 '(gdb-memory-font-lock-keywords))
2238 (run-mode-hooks 'gdb-memory-mode-hook) 2308 (run-mode-hooks 'gdb-memory-mode-hook)
2239 'gdb-invalidate-memory) 2309 'gdb-invalidate-memory)
2240 2310
2265 (def-gdb-auto-update-trigger gdb-invalidate-locals 2335 (def-gdb-auto-update-trigger gdb-invalidate-locals
2266 (gdb-get-buffer 'gdb-locals-buffer) 2336 (gdb-get-buffer 'gdb-locals-buffer)
2267 "server info locals\n" 2337 "server info locals\n"
2268 gdb-info-locals-handler) 2338 gdb-info-locals-handler)
2269 2339
2270 (defvar gdb-locals-watch-keymap 2340 (defvar gdb-locals-watch-map
2271 (let ((map (make-sparse-keymap))) 2341 (let ((map (make-sparse-keymap)))
2272 (define-key map "\r" '(lambda () (interactive) 2342 (define-key map "\r" '(lambda () (interactive)
2273 (beginning-of-line) 2343 (beginning-of-line)
2274 (gud-watch))) 2344 (gud-watch)))
2275 (define-key map [mouse-2] '(lambda (event) (interactive "e") 2345 (define-key map [mouse-2] '(lambda (event) (interactive "e")
2281 2351
2282 (defconst gdb-struct-string 2352 (defconst gdb-struct-string
2283 (concat (propertize "[struct/union]" 2353 (concat (propertize "[struct/union]"
2284 'mouse-face 'highlight 2354 'mouse-face 'highlight
2285 'help-echo "mouse-2: create watch expression" 2355 'help-echo "mouse-2: create watch expression"
2286 'local-map gdb-locals-watch-keymap) "\n")) 2356 'local-map gdb-locals-watch-map) "\n"))
2287 2357
2288 (defconst gdb-array-string 2358 (defconst gdb-array-string
2289 (concat " " (propertize "[array]" 2359 (concat " " (propertize "[array]"
2290 'mouse-face 'highlight 2360 'mouse-face 'highlight
2291 'help-echo "mouse-2: create watch expression" 2361 'help-echo "mouse-2: create watch expression"
2292 'local-map gdb-locals-watch-keymap) "\n")) 2362 'local-map gdb-locals-watch-map) "\n"))
2293 2363
2294 ;; Abbreviate for arrays and structures. 2364 ;; Abbreviate for arrays and structures.
2295 ;; These can be expanded using gud-display. 2365 ;; These can be expanded using gud-display.
2296 (defun gdb-info-locals-handler () 2366 (defun gdb-info-locals-handler ()
2297 (setq gdb-pending-triggers (delq 'gdb-invalidate-locals 2367 (setq gdb-pending-triggers (delq 'gdb-invalidate-locals
2323 (let ((map (make-sparse-keymap))) 2393 (let ((map (make-sparse-keymap)))
2324 (suppress-keymap map) 2394 (suppress-keymap map)
2325 (define-key map "q" 'kill-this-buffer) 2395 (define-key map "q" 'kill-this-buffer)
2326 map)) 2396 map))
2327 2397
2328 (defvar gdb-locals-font-lock-keywords
2329 '(
2330 ;; var = (struct struct_tag) value
2331 ( "\\(^\\(\\sw\\|[_.]\\)+\\) += +(\\(struct\\) \\(\\(\\sw\\|[_.]\\)+\\)"
2332 (1 font-lock-variable-name-face)
2333 (3 font-lock-keyword-face)
2334 (4 font-lock-type-face))
2335 ;; var = (type) value
2336 ( "\\(^\\(\\sw\\|[_.]\\)+\\) += +(\\(\\(\\sw\\|[_.]\\)+\\)"
2337 (1 font-lock-variable-name-face)
2338 (3 font-lock-type-face))
2339 ;; var = val
2340 ( "\\(^\\(\\sw\\|[_.]\\)+\\) += +[^(]"
2341 (1 font-lock-variable-name-face))
2342 )
2343 "Font lock keywords used in `gdb-local-mode'.")
2344
2345 (defun gdb-locals-mode () 2398 (defun gdb-locals-mode ()
2346 "Major mode for gdb locals. 2399 "Major mode for gdb locals.
2347 2400
2348 \\{gdb-locals-mode-map}" 2401 \\{gdb-locals-mode-map}"
2349 (kill-all-local-variables) 2402 (kill-all-local-variables)
2353 (use-local-map gdb-locals-mode-map) 2406 (use-local-map gdb-locals-mode-map)
2354 (set (make-local-variable 'font-lock-defaults) 2407 (set (make-local-variable 'font-lock-defaults)
2355 '(gdb-locals-font-lock-keywords)) 2408 '(gdb-locals-font-lock-keywords))
2356 (run-mode-hooks 'gdb-locals-mode-hook) 2409 (run-mode-hooks 'gdb-locals-mode-hook)
2357 (if (eq (buffer-local-value 'gud-minor-mode gud-comint-buffer) 'gdba) 2410 (if (eq (buffer-local-value 'gud-minor-mode gud-comint-buffer) 'gdba)
2358 'gdb-invalidate-locals 2411 (if (string-equal gdb-version "pre-6.4")
2412 'gdb-invalidate-locals
2413 'gdb-invalidate-locals-1)
2359 'gdbmi-invalidate-locals)) 2414 'gdbmi-invalidate-locals))
2360 2415
2361 (defun gdb-locals-buffer-name () 2416 (defun gdb-locals-buffer-name ()
2362 (with-current-buffer gud-comint-buffer 2417 (with-current-buffer gud-comint-buffer
2363 (concat "*locals of " (gdb-get-target-string) "*"))) 2418 (concat "*locals of " (gdb-get-target-string) "*")))
2611 (gdb-put-breakpoint-icon (eq flag ?y) bptno))))) 2666 (gdb-put-breakpoint-icon (eq flag ?y) bptno)))))
2612 2667
2613 (add-hook 'find-file-hook 'gdb-find-file-hook) 2668 (add-hook 'find-file-hook 'gdb-find-file-hook)
2614 2669
2615 (defun gdb-find-file-hook () 2670 (defun gdb-find-file-hook ()
2616 "Set up buffer for debugging if file is part of the source code 2671 "Set up buffer for debugging if file is part of the source code
2617 of the current session." 2672 of the current session."
2618 (if (and (not gdb-find-file-unhook) 2673 (if (and (buffer-name gud-comint-buffer)
2619 ;; in case gud or gdb-ui is just loaded 2674 ;; in case gud or gdb-ui is just loaded
2620 gud-comint-buffer 2675 gud-comint-buffer
2621 (buffer-name gud-comint-buffer)
2622 (eq (buffer-local-value 'gud-minor-mode gud-comint-buffer) 2676 (eq (buffer-local-value 'gud-minor-mode gud-comint-buffer)
2623 'gdba)) 2677 'gdba))
2624 (condition-case nil 2678 (if (member buffer-file-name gdb-source-file-list)
2625 (gdb-enqueue-input 2679 (with-current-buffer (find-buffer-visiting buffer-file-name)
2626 (list (concat gdb-server-prefix "list " 2680 (set (make-local-variable 'gud-minor-mode) 'gdba)
2627 (file-name-nondirectory buffer-file-name) 2681 (set (make-local-variable 'tool-bar-map) gud-tool-bar-map)))))
2628 ":1\n")
2629 `(lambda () (gdb-set-gud-minor-mode ,(current-buffer)))))
2630 (error (setq gdb-find-file-unhook t)))))
2631 2682
2632 ;;from put-image 2683 ;;from put-image
2633 (defun gdb-put-string (putstring pos &optional dprop &rest sprops) 2684 (defun gdb-put-string (putstring pos &optional dprop &rest sprops)
2634 "Put string PUTSTRING in front of POS in the current buffer. 2685 "Put string PUTSTRING in front of POS in the current buffer.
2635 PUTSTRING is displayed by putting an overlay into the current buffer with a 2686 PUTSTRING is displayed by putting an overlay into the current buffer with a
2756 (save-excursion 2807 (save-excursion
2757 (if (not (equal gdb-frame-address "main")) 2808 (if (not (equal gdb-frame-address "main"))
2758 (progn 2809 (progn
2759 (goto-char (point-min)) 2810 (goto-char (point-min))
2760 (if (and gdb-frame-address 2811 (if (and gdb-frame-address
2761 (re-search-forward gdb-frame-address nil t)) 2812 (search-forward gdb-frame-address nil t))
2762 (progn 2813 (progn
2763 (setq pos (point)) 2814 (setq pos (point))
2764 (beginning-of-line) 2815 (beginning-of-line)
2765 (or gdb-overlay-arrow-position 2816 (or gdb-overlay-arrow-position
2766 (setq gdb-overlay-arrow-position (make-marker))) 2817 (setq gdb-overlay-arrow-position (make-marker)))
2780 (setq flag (char-after (match-beginning 2))) 2831 (setq flag (char-after (match-beginning 2)))
2781 (setq address (match-string 3)) 2832 (setq address (match-string 3))
2782 (with-current-buffer buffer 2833 (with-current-buffer buffer
2783 (save-excursion 2834 (save-excursion
2784 (goto-char (point-min)) 2835 (goto-char (point-min))
2785 (if (re-search-forward address nil t) 2836 (if (search-forward address nil t)
2786 (gdb-put-breakpoint-icon (eq flag ?y) bptno)))))))) 2837 (gdb-put-breakpoint-icon (eq flag ?y) bptno))))))))
2787 (if (not (equal gdb-frame-address "main")) 2838 (if (not (equal gdb-frame-address "main"))
2788 (with-current-buffer buffer 2839 (with-current-buffer buffer
2789 (set-window-point (get-buffer-window buffer 0) pos))))) 2840 (set-window-point (get-buffer-window buffer 0) pos)))))
2790 2841
2884 gdb-pending-triggers)))) 2935 gdb-pending-triggers))))
2885 2936
2886 (defun gdb-frame-handler () 2937 (defun gdb-frame-handler ()
2887 (setq gdb-pending-triggers 2938 (setq gdb-pending-triggers
2888 (delq 'gdb-get-selected-frame gdb-pending-triggers)) 2939 (delq 'gdb-get-selected-frame gdb-pending-triggers))
2889 (with-current-buffer (gdb-get-create-buffer 'gdb-partial-output-buffer) 2940 (goto-char (point-min))
2941 (if (re-search-forward "Stack level \\([0-9]+\\)" nil t)
2942 (setq gdb-frame-number (match-string 1)))
2943 (goto-char (point-min))
2944 (if (re-search-forward
2945 ".*=\\s-+0x0*\\(\\S-*\\)\\s-+in\\s-+\\(\\S-*?\\);? " nil t)
2946 (progn
2947 (setq gdb-selected-frame (match-string 2))
2948 (if (gdb-get-buffer 'gdb-locals-buffer)
2949 (with-current-buffer (gdb-get-buffer 'gdb-locals-buffer)
2950 (setq mode-name (concat "Locals:" gdb-selected-frame))))
2951 (if (gdb-get-buffer 'gdb-assembler-buffer)
2952 (with-current-buffer (gdb-get-buffer 'gdb-assembler-buffer)
2953 (setq mode-name (concat "Machine:" gdb-selected-frame))))
2954 (setq gdb-frame-address (match-string 1))))
2955 (goto-char (point-min))
2956 (if (re-search-forward " source language \\(\\S-*\\)\." nil t)
2957 (setq gdb-current-language (match-string 1)))
2958 (gdb-invalidate-assembler))
2959
2960
2961 ;; Code specific to GDB 6.4
2962 (defconst gdb-source-file-regexp-1 "fullname=\"\\(.*?\\)\"")
2963
2964 (defun gdb-set-gud-minor-mode-existing-buffers-1 ()
2965 "Create list of source files for current GDB session."
2966 (goto-char (point-min))
2967 (while (re-search-forward gdb-source-file-regexp-1 nil t)
2968 (push (match-string 1) gdb-source-file-list))
2969 (dolist (buffer (buffer-list))
2970 (with-current-buffer buffer
2971 (when (member buffer-file-name gdb-source-file-list)
2972 (set (make-local-variable 'gud-minor-mode) 'gdba)
2973 (set (make-local-variable 'tool-bar-map) gud-tool-bar-map)
2974 (when gud-tooltip-mode
2975 (make-local-variable 'gdb-define-alist)
2976 (gdb-create-define-alist)
2977 (add-hook 'after-save-hook 'gdb-create-define-alist nil t))))))
2978
2979 ; Uses "-var-list-children --all-values". Needs GDB 6.1 onwards.
2980 (defun gdb-var-list-children-1 (varnum)
2981 (gdb-enqueue-input
2982 (list (concat "server interpreter mi \"-var-update " varnum "\"\n")
2983 'ignore))
2984 (gdb-enqueue-input
2985 (list (concat "server interpreter mi \"-var-list-children --all-values "
2986 varnum "\"\n")
2987 `(lambda () (gdb-var-list-children-handler-1 ,varnum)))))
2988
2989 (defconst gdb-var-list-children-regexp-1
2990 "name=\"\\(.+?\\)\",exp=\"\\(.+?\\)\",numchild=\"\\(.+?\\)\",\
2991 value=\\(\".*?\"\\),type=\"\\(.+?\\)\"}")
2992
2993 (defun gdb-var-list-children-handler-1 (varnum)
2994 (goto-char (point-min))
2995 (let ((var-list nil))
2996 (catch 'child-already-watched
2997 (dolist (var gdb-var-list)
2998 (if (string-equal varnum (cadr var))
2999 (progn
3000 (push var var-list)
3001 (while (re-search-forward gdb-var-list-children-regexp-1 nil t)
3002 (let ((varchild (list (match-string 2)
3003 (match-string 1)
3004 (match-string 3)
3005 (match-string 5)
3006 (read (match-string 4))
3007 nil)))
3008 (dolist (var1 gdb-var-list)
3009 (if (string-equal (cadr var1) (cadr varchild))
3010 (throw 'child-already-watched nil)))
3011 (push varchild var-list))))
3012 (push var var-list)))
3013 (setq gdb-var-changed t)
3014 (setq gdb-var-list (nreverse var-list)))))
3015
3016 ; Uses "-var-update --all-values". Needs GDB 6.4 onwards.
3017 (defun gdb-var-update-1 ()
3018 (if (not (member 'gdb-var-update gdb-pending-triggers))
3019 (progn
3020 (gdb-enqueue-input
3021 (list
3022 (if (with-current-buffer gud-comint-buffer (eq gud-minor-mode 'gdba))
3023 "server interpreter mi \"-var-update --all-values *\"\n"
3024 "-var-update --all-values *\n")
3025 'gdb-var-update-handler-1))
3026 (push 'gdb-var-update gdb-pending-triggers))))
3027
3028 (defconst gdb-var-update-regexp-1 "name=\"\\(.*?\\)\",value=\\(\".*?\"\\),")
3029
3030 (defun gdb-var-update-handler-1 ()
3031 (goto-char (point-min))
3032 (while (re-search-forward gdb-var-update-regexp-1 nil t)
3033 (let ((varnum (match-string 1)))
3034 (catch 'var-found1
3035 (let ((num 0))
3036 (dolist (var gdb-var-list)
3037 (if (string-equal varnum (cadr var))
3038 (progn
3039 (setcar (nthcdr 5 var) t)
3040 (setcar (nthcdr 4 var) (read (match-string 2)))
3041 (setcar (nthcdr num gdb-var-list) var)
3042 (throw 'var-found1 nil)))
3043 (setq num (+ num 1))))))
3044 (setq gdb-var-changed t))
3045 (setq gdb-pending-triggers
3046 (delq 'gdb-var-update gdb-pending-triggers))
3047 (when (and (boundp 'speedbar-frame) (frame-live-p speedbar-frame))
3048 ;; dummy command to update speedbar at right time
3049 (gdb-enqueue-input (list "server pwd\n" 'gdb-speedbar-timer-fn))
3050 ;; keep gdb-pending-triggers non-nil till end
3051 (push 'gdb-speedbar-timer gdb-pending-triggers)))
3052
3053 ;; Registers buffer.
3054 ;;
3055 (gdb-set-buffer-rules 'gdb-registers-buffer
3056 'gdb-registers-buffer-name
3057 'gdb-registers-mode)
3058
3059 (def-gdb-auto-update-trigger gdb-invalidate-registers-1
3060 (gdb-get-buffer 'gdb-registers-buffer)
3061 (if (eq gud-minor-mode 'gdba)
3062 "server interpreter mi \"-data-list-register-values x\"\n"
3063 "-data-list-register-values x\n")
3064 gdb-data-list-register-values-handler)
3065
3066 (defconst gdb-data-list-register-values-regexp
3067 "number=\"\\(.*?\\)\",value=\"\\(.*?\\)\"")
3068
3069 (defun gdb-data-list-register-values-handler ()
3070 (setq gdb-pending-triggers (delq 'gdb-invalidate-registers-1
3071 gdb-pending-triggers))
3072 (goto-char (point-min))
3073 (if (re-search-forward gdb-error-regexp nil t)
3074 (with-current-buffer (gdb-get-buffer 'gdb-registers-buffer)
3075 (let ((buffer-read-only nil))
3076 (erase-buffer)
3077 (insert (match-string 1))
3078 (goto-char (point-min))))
3079 (let ((register-list (reverse gdb-register-names))
3080 (register nil) (register-string nil) (register-values nil))
3081 (goto-char (point-min))
3082 (while (re-search-forward gdb-data-list-register-values-regexp nil t)
3083 (setq register (pop register-list))
3084 (setq register-string (concat register "\t" (match-string 2) "\n"))
3085 (if (member (match-string 1) gdb-changed-registers)
3086 (put-text-property 0 (length register-string)
3087 'face 'font-lock-warning-face
3088 register-string))
3089 (setq register-values
3090 (concat register-values register-string)))
3091 (let ((buf (gdb-get-buffer 'gdb-registers-buffer)))
3092 (with-current-buffer buf
3093 (let ((p (window-point (get-buffer-window buf 0)))
3094 (buffer-read-only nil))
3095 (erase-buffer)
3096 (insert register-values)
3097 (set-window-point (get-buffer-window buf 0) p))))))
3098 (gdb-data-list-register-values-custom))
3099
3100 (defun gdb-data-list-register-values-custom ()
3101 (with-current-buffer (gdb-get-buffer 'gdb-registers-buffer)
3102 (save-excursion
3103 (let ((buffer-read-only nil)
3104 start end)
3105 (goto-char (point-min))
3106 (while (< (point) (point-max))
3107 (setq start (line-beginning-position))
3108 (setq end (line-end-position))
3109 (when (looking-at "^[^\t]+")
3110 (unless (string-equal (match-string 0) "No registers.")
3111 (put-text-property start (match-end 0)
3112 'face font-lock-variable-name-face)
3113 (add-text-properties start end
3114 '(help-echo "mouse-2: edit value"
3115 mouse-face highlight))))
3116 (forward-line 1))))))
3117
3118 ;; Needs GDB 6.4 onwards (used to fail with no stack).
3119 (defun gdb-get-changed-registers ()
3120 (if (not (member 'gdb-get-changed-registers gdb-pending-triggers))
3121 (progn
3122 (gdb-enqueue-input
3123 (list
3124 (if (eq gud-minor-mode 'gdba)
3125 "server interpreter mi -data-list-changed-registers\n"
3126 "-data-list-changed-registers\n")
3127 'gdb-get-changed-registers-handler))
3128 (push 'gdb-get-changed-registers gdb-pending-triggers))))
3129
3130 (defconst gdb-data-list-register-names-regexp "\"\\(.*?\\)\"")
3131
3132 (defun gdb-get-changed-registers-handler ()
3133 (setq gdb-pending-triggers
3134 (delq 'gdb-get-changed-registers gdb-pending-triggers))
3135 (setq gdb-changed-registers nil)
3136 (goto-char (point-min))
3137 (while (re-search-forward gdb-data-list-register-names-regexp nil t)
3138 (push (match-string 1) gdb-changed-registers)))
3139
3140
3141 ;; Locals buffer.
3142 ;;
3143 ;; uses "-stack-list-locals --simple-values". Needs GDB 6.1 onwards.
3144 (gdb-set-buffer-rules 'gdb-locals-buffer
3145 'gdb-locals-buffer-name
3146 'gdb-locals-mode)
3147
3148 (def-gdb-auto-update-trigger gdb-invalidate-locals-1
3149 (gdb-get-buffer 'gdb-locals-buffer)
3150 "server interpreter mi -\"stack-list-locals --simple-values\"\n"
3151 gdb-stack-list-locals-handler)
3152
3153 (defconst gdb-stack-list-locals-regexp
3154 "name=\"\\(.*?\\)\",type=\"\\(.*?\\)\"")
3155
3156 (defvar gdb-locals-watch-map-1
3157 (let ((map (make-sparse-keymap)))
3158 (define-key map [mouse-2] 'gud-watch)
3159 map)
3160 "Keymap to create watch expression of a complex data type local variable.")
3161
3162 ;; Dont display values of arrays or structures.
3163 ;; These can be expanded using gud-watch.
3164 (defun gdb-stack-list-locals-handler ()
3165 (setq gdb-pending-triggers (delq 'gdb-invalidate-locals-1
3166 gdb-pending-triggers))
3167 (let (local locals-list)
2890 (goto-char (point-min)) 3168 (goto-char (point-min))
2891 (if (re-search-forward "Stack level \\([0-9]+\\)" nil t) 3169 (while (re-search-forward gdb-stack-list-locals-regexp nil t)
2892 (setq gdb-frame-number (match-string 1))) 3170 (let ((local (list (match-string 1)
2893 (goto-char (point-min)) 3171 (match-string 2)
2894 (if (re-search-forward 3172 nil)))
2895 ".*=\\s-+0x0*\\(\\S-*\\)\\s-+in\\s-+\\(\\S-*?\\);? " nil t) 3173 (if (looking-at ",value=\\(\".*\"\\)}")
2896 (progn 3174 (setcar (nthcdr 2 local) (read (match-string 1))))
2897 (setq gdb-selected-frame (match-string 2)) 3175 (push local locals-list)))
2898 (if (gdb-get-buffer 'gdb-locals-buffer) 3176 (let ((buf (gdb-get-buffer 'gdb-locals-buffer)))
2899 (with-current-buffer (gdb-get-buffer 'gdb-locals-buffer) 3177 (and buf (with-current-buffer buf
2900 (setq mode-name (concat "Locals:" gdb-selected-frame)))) 3178 (let* ((window (get-buffer-window buf 0))
2901 (if (gdb-get-buffer 'gdb-assembler-buffer) 3179 (p (window-point window))
2902 (with-current-buffer (gdb-get-buffer 'gdb-assembler-buffer) 3180 (buffer-read-only nil))
2903 (setq mode-name (concat "Machine:" gdb-selected-frame)))) 3181 (erase-buffer)
2904 (setq gdb-frame-address (match-string 1)))) 3182 (dolist (local locals-list)
2905 (goto-char (point-min)) 3183 (setq name (car local))
2906 (if (re-search-forward " source language \\(\\S-*\\)\." nil t) 3184 (if (or (not (nth 2 local))
2907 (setq gdb-current-language (match-string 1)))) 3185 (string-match "\\*$" (nth 1 local)))
2908 (gdb-invalidate-assembler)) 3186 (add-text-properties 0 (length name)
3187 `(mouse-face highlight
3188 help-echo "mouse-2: create watch expression"
3189 local-map ,gdb-locals-watch-map-1)
3190 name))
3191 (insert
3192 (concat name "\t" (nth 1 local)
3193 "\t" (nth 2 local) "\n")))
3194 (set-window-point window p)))))))
3195
3196 (defun gdb-get-register-names ()
3197 "Create a list of register names."
3198 (goto-char (point-min))
3199 (setq gdb-register-names nil)
3200 (while (re-search-forward gdb-data-list-register-names-regexp nil t)
3201 (push (match-string 1) gdb-register-names)))
2909 3202
2910 (provide 'gdb-ui) 3203 (provide 'gdb-ui)
2911 3204
2912 ;; arch-tag: e9fb00c5-74ef-469f-a088-37384caae352 3205 ;; arch-tag: e9fb00c5-74ef-469f-a088-37384caae352
2913 ;;; gdb-ui.el ends here 3206 ;;; gdb-ui.el ends here