From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 13281 invoked by alias); 2 Mar 2005 08:18:04 -0000 Mailing-List: contact gdb-patches-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sources.redhat.com Received: (qmail 12953 invoked from network); 2 Mar 2005 08:17:17 -0000 Received: from unknown (HELO viper.snap.net.nz) (202.37.101.8) by sourceware.org with SMTP; 2 Mar 2005 08:17:17 -0000 Received: from farnswood.snap.net.nz (p213-tnt1.snap.net.nz [202.124.110.213]) by viper.snap.net.nz (Postfix) with ESMTP id 01EAA4842F8 for ; Wed, 2 Mar 2005 21:17:13 +1300 (NZDT) Received: by farnswood.snap.net.nz (Postfix, from userid 501) id E0B3D62FBE; Wed, 2 Mar 2005 08:15:35 +0000 (GMT) From: Nick Roberts MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Message-ID: <16933.30246.584286.198915@farnswood.snap.net.nz> Date: Wed, 02 Mar 2005 08:18:00 -0000 To: gdb-patches@sources.redhat.com Subject: [PATCH: gdb/mi] gdb-mi.el X-SW-Source: 2005-03/txt/msg00014.txt.bz2 This patch updates gdb-mi.el so that it works again with Emacs in the CVS repository at Savannah (Emacs 22.0.50) which, hopefully, will be released, one day, as Emacs 22. I plan to update this file to reflect the current and future changes I make for MI in GDB. The slow release cycle of Emacs makes it impossible to track these changes from the Emacs side. Nick Comment from gdb-mi.el: ;; This file uses GDB/MI as the primary interface to GDB. It is still under ;; development and is part of a process to migrate Emacs from annotations ;; (as used in gdb-ui.el) to GDB/MI. *** /home/nick/src/gdb/mi/gdb-mi.el.~1.1.~ 2004-07-27 09:52:34.000000000 +1200 --- /home/nick/src/gdb/mi/gdb-mi.el 2005-03-02 20:53:40.000000000 +1300 *************** *** 1,4 **** ! ;;; gdb-mi.el (internally gdbmi6.el) - (24th May 2004) ;; Run gdb with GDB/MI (-interp=mi) and access CLI using "cli-command" ;; (could use "-interpreter-exec console cli-command") --- 1,4 ---- ! ;;; gdb-mi.el ;; Run gdb with GDB/MI (-interp=mi) and access CLI using "cli-command" ;; (could use "-interpreter-exec console cli-command") *************** *** 7,13 **** ;; Maintainer: Nick Roberts ;; Keywords: unix, tools ! ;; Copyright (C) 2004 Free Software Foundation, Inc. ;; This file is part of GNU GDB. --- 7,13 ---- ;; Maintainer: Nick Roberts ;; Keywords: unix, tools ! ;; Copyright (C) 2004, 2005 Free Software Foundation, Inc. ;; This file is part of GNU GDB. *************** *** 23,36 **** ;;; Commentary: ! ;; This mode acts as a graphical user interface to GDB and requires GDB 6.1 ! ;; onwards. You can interact with GDB through the GUD buffer in the usual way, ! ;; but there are also buffers which control the execution and describe the ! ;; state of your program. It separates the input/output of your program from ! ;; that of GDB and displays expressions and their current values in their own ! ;; buffers. It also uses features of Emacs 21 such as the fringe/display ! ;; margin for breakpoints, and the toolbar (see the GDB Graphical Interface ! ;; section in the Emacs info manual). ;; Start the debugger with M-x gdbmi. --- 23,37 ---- ;;; Commentary: ! ;; This mode acts as a graphical user interface to GDB and should work with ! ;; Emacs 22.0 and the version of GDB with which it is distributed. You can ! ;; interact with GDB through the GUD buffer in the usual way, but there are ! ;; also buffers which control the execution and describe the state of your ! ;; program. It separates the input/output of your program from that of GDB and ! ;; displays expressions and their current values in their own buffers. It also ! ;; uses features of Emacs 21 such as the fringe/display margin for ! ;; breakpoints, and the toolbar (see the GDB Graphical Interface section in ! ;; the Emacs info manual). ;; Start the debugger with M-x gdbmi. *************** *** 40,46 **** ;; Known Bugs: ;; ! ;;; Code: (require 'gud) --- 41,53 ---- ;; Known Bugs: ;; ! ;; 1) You cannot use run, step, next or continue in the GUD buffer but ! ;; must use their MI counterparts by clicking on the appropriate icon ! ;; in the toolbar. ! ;; ! ;; 2) Cannot display correct frame with gdb-frames-select (mouse-2 in Frames ! ;; buffer) or up/down in GUD buffer. Needs event notification in MI. ! ;; ;;; Code: (require 'gud) *************** *** 106,111 **** --- 113,129 ---- (set (make-local-variable 'gud-minor-mode) 'gdbmi) (set (make-local-variable 'gud-marker-filter) 'gud-gdbmi-marker-filter) ;; + (gud-def gud-step "-exec-step %p" "\C-s" + "Step one source line with display.") + (gud-def gud-stepi "-exec-step-instruction %p" "\C-i" + "Step one instruction with display.") + (gud-def gud-next "-exec-next %p" "\C-n" + "Step one line (skip functions).") + (gud-def gud-cont "-exec-continue" "\C-r" + "Continue with display.") + (gud-def gud-finish "-exec-finish" "\C-f" + "Finish executing current function.") + (gud-def gud-run "-exec-run" nil "Run the program.") (gud-def gud-break (if (not (string-equal mode-name "Machine")) (gud-call "-break-insert %f:%l" arg) (save-excursion *************** *** 152,157 **** --- 170,179 ---- (setq gdb-pending-triggers nil) (setq gdb-output-sink 'user) (setq gdb-server-prefix nil) + (setq gdb-flush-pending-output nil) + (setq gdb-location-list nil) + (setq gdb-find-file-unhook nil) + (setq gdb-source-file-list nil) ;; (setq gdb-buffer-type 'gdbmi) ;; *************** *** 160,187 **** ;; (if (eq window-system 'w32) (gdb-enqueue-input (list "-gdb-set new-console off\n" 'ignore))) ;; find source file and compilation directory here ! (gdb-enqueue-input (list "list main\n" 'ignore)) ; C program ! (gdb-enqueue-input (list "list MAIN__\n" 'ignore)) ; Fortran program ! (gdb-enqueue-input (list "info source\n" 'gdbmi-source-info)) ;; (run-hooks 'gdbmi-mode-hook)) ; Force nil till fixed. (defconst gdbmi-use-inferior-io-buffer nil) ! ; uses --all-values Needs GDB 6.1 onwards. (defun gdbmi-var-list-children (varnum) (gdb-enqueue-input (list (concat "-var-update " varnum "\n") 'ignore)) (gdb-enqueue-input ! (list (concat "-var-list-children --all-values " varnum "\n") `(lambda () (gdbmi-var-list-children-handler ,varnum))))) (defconst gdbmi-var-list-children-regexp ! "name=\"\\(.*?\\)\",exp=\"\\(.*?\\)\",numchild=\"\\(.*?\\)\",value=\"\\(.*?\\)\"" ! ) (defun gdbmi-var-list-children-handler (varnum) (with-current-buffer (gdb-get-create-buffer 'gdb-partial-output-buffer) --- 182,211 ---- ;; (if (eq window-system 'w32) (gdb-enqueue-input (list "-gdb-set new-console off\n" 'ignore))) + (gdb-enqueue-input (list "-gdb-set height 0\n" 'ignore)) ;; find source file and compilation directory here ! (gdb-enqueue-input ! (list "-file-list-exec-source-files\n" 'gdb-get-source-file-list)) ! (gdb-enqueue-input ! (list "-file-list-exec-source-file\n" 'gdb-get-source-file)) ;; (run-hooks 'gdbmi-mode-hook)) ; Force nil till fixed. (defconst gdbmi-use-inferior-io-buffer nil) ! ; uses -var-list-children 1 (= --with-values) Needs GDB 6.1 onwards. (defun gdbmi-var-list-children (varnum) (gdb-enqueue-input (list (concat "-var-update " varnum "\n") 'ignore)) (gdb-enqueue-input ! (list (concat "-var-list-children 1 " varnum "\n") `(lambda () (gdbmi-var-list-children-handler ,varnum))))) (defconst gdbmi-var-list-children-regexp ! "name=\"\\(.*?\\)\",exp=\"\\(.*?\\)\",numchild=\"\\(.*?\\)\",\ ! value=\"\\(.*?\\)\"") (defun gdbmi-var-list-children-handler (varnum) (with-current-buffer (gdb-get-create-buffer 'gdb-partial-output-buffer) *************** *** 226,233 **** :type 'string :group 'gud) ! (defconst gdb-stopped-regexp ! "\\((gdb) \n\\*stopped\\|^\\^done\\),reason=.*,file=\"\\(.*\\)\",line=\"\\(.*\\)\".*") (defconst gdb-console-regexp "~\"\\(.*\\)\\\\n\"") --- 250,257 ---- :type 'string :group 'gud) ! (defconst gdb-stopped-regexp ! "\\(\\*stopped\\|^\\^done\\),reason=.*,file=\"\\(.*\\)\",line=\"\\(.*\\)\".*") (defconst gdb-console-regexp "~\"\\(.*\\)\\\\n\"") *************** *** 245,256 **** (gdbmi-invalidate-frames) (gdbmi-invalidate-breakpoints) (gdbmi-invalidate-locals) ! (dolist (frame (frame-list)) ! (when (string-equal (frame-parameter frame 'name) "Speedbar") ! (setq gdb-var-changed t) ; force update ! (dolist (var gdb-var-list) ! (setcar (nthcdr 5 var) nil)))) ! (gdb-var-update)) (let ((sink gdb-output-sink)) (when (eq sink 'emacs) (let ((handler --- 269,279 ---- (gdbmi-invalidate-frames) (gdbmi-invalidate-breakpoints) (gdbmi-invalidate-locals) ! (when (and (boundp 'speedbar-frame) (frame-live-p speedbar-frame)) ! (setq gdb-var-changed t) ; force update ! (dolist (var gdb-var-list) ! (setcar (nthcdr 5 var) nil)) ! (gdb-var-update))) (let ((sink gdb-output-sink)) (when (eq sink 'emacs) (let ((handler *************** *** 267,325 **** (defun gud-gdbmi-marker-filter (string) "Filter GDB/MI output." ! (if gdb-enable-debug-log (push (cons 'recv string) gdb-debug-log)) ! ;; Recall the left over gud-marker-acc from last time ! (setq gud-marker-acc (concat gud-marker-acc string)) ! ;; Start accumulating output for the GUD buffer ! (let ((output "")) ! ! (if (string-match gdb-running-regexp gud-marker-acc) ! (setq gud-marker-acc (substring gud-marker-acc (match-end 0)) ! gud-running t)) ! ! ;; Remove the trimmings from the console stream. ! (while (string-match gdb-console-regexp gud-marker-acc) ! (setq ! gud-marker-acc (concat (substring gud-marker-acc 0 (match-beginning 0)) ! (match-string 1 gud-marker-acc) ! (substring gud-marker-acc (match-end 0))))) ! ! ;; Remove log stream containing debugging messages being produced by GDB's ! ;; internals. ! (while (string-match gdb-internals-regexp gud-marker-acc) ! (setq gud-marker-acc (concat (substring gud-marker-acc 0 (match-beginning 0)) (substring gud-marker-acc (match-end 0))))) ! (if (string-match gdb-stopped-regexp gud-marker-acc) ! (setq ! ;; Extract the frame position from the marker. ! gud-last-frame (cons (match-string 2 gud-marker-acc) ! (string-to-int (match-string 3 gud-marker-acc))) ! ! ;; Append any text before the marker to the output we're going ! ;; to return - we don't include the marker in this text. ! output (gdbmi-concat-output output ! (substring gud-marker-acc 0 (match-beginning 0))) ! ;; Set the accumulator to the remaining text. ! gud-marker-acc (substring gud-marker-acc (match-end 0)))) ! ! (while (string-match gdb-gdb-regexp gud-marker-acc) ! (setq ! ;; Append any text up to and including prompt less \n to the output. ! output (gdbmi-concat-output output ! (substring gud-marker-acc 0 (- (match-end 0) 1))) ! ! ;; Set the accumulator to the remaining text. ! gud-marker-acc (substring gud-marker-acc (match-end 0))) ! (gdbmi-prompt)) ! ! (setq output (gdbmi-concat-output output gud-marker-acc)) ! (setq gud-marker-acc "") ! output)) (defun gdbmi-concat-output (so-far new) (let ((sink gdb-output-sink)) --- 290,351 ---- (defun gud-gdbmi-marker-filter (string) "Filter GDB/MI output." ! (if gdb-flush-pending-output ! nil ! (if gdb-enable-debug-log (push (cons 'recv string) gdb-debug-log)) ! ;; Recall the left over gud-marker-acc from last time ! (setq gud-marker-acc (concat gud-marker-acc string)) ! ;; Start accumulating output for the GUD buffer ! (let ((output "")) ! ! (if (string-match gdb-running-regexp gud-marker-acc) ! (setq gud-marker-acc (substring gud-marker-acc (match-end 0)) ! gud-running t)) ! ! ;; Remove the trimmings from the console stream. ! (while (string-match gdb-console-regexp gud-marker-acc) ! (setq gud-marker-acc (concat (substring gud-marker-acc 0 (match-beginning 0)) + (match-string 1 gud-marker-acc) (substring gud-marker-acc (match-end 0))))) ! ;; Remove log stream containing debugging messages being produced by GDB's ! ;; internals. ! (while (string-match gdb-internals-regexp gud-marker-acc) ! (setq ! gud-marker-acc (concat (substring gud-marker-acc 0 (match-beginning 0)) ! (substring gud-marker-acc (match-end 0))))) ! (if (string-match gdb-stopped-regexp gud-marker-acc) ! (setq ! ;; Extract the frame position from the marker. ! gud-last-frame (cons (match-string 2 gud-marker-acc) ! (string-to-int (match-string 3 gud-marker-acc))) ! ! ;; Append any text before the marker to the output we're going ! ;; to return - we don't include the marker in this text. ! output (gdbmi-concat-output output ! (substring gud-marker-acc 0 (match-beginning 0))) ! ;; Set the accumulator to the remaining text. ! gud-marker-acc (substring gud-marker-acc (match-end 0)))) ! ! (if (string-match gdb-gdb-regexp gud-marker-acc) ! (progn ! (setq ! ! ;; Append any text up to and including prompt less \n to the output. ! output (gdbmi-concat-output ! output (substring gud-marker-acc 0 (- (match-end 0) 1))) ! ! ;; Set the accumulator to the remaining text. ! gud-marker-acc (substring gud-marker-acc (match-end 0))) ! (gdbmi-prompt)) ! ! (setq output (gdbmi-concat-output output gud-marker-acc)) ! (setq gud-marker-acc "")) ! output))) (defun gdbmi-concat-output (so-far new) (let ((sink gdb-output-sink)) *************** *** 354,366 **** gdb-break-list-custom) (defconst gdb-break-list-regexp ! "number=\"\\(.*?\\)\",type=\"\\(.*?\\)\",disp=\"\\(.*?\\)\",enabled=\"\\(.\\)\",addr=\"\\(.*?\\)\",func=\"\\(.*?\\)\",file=\"\\(.*?\\)\",line=\"\\(.*?\\)\"") (defun gdb-break-list-handler () (setq gdb-pending-triggers (delq 'gdbmi-invalidate-breakpoints gdb-pending-triggers)) ! (let ((breakpoint nil) ! (breakpoints-list nil)) (with-current-buffer (gdb-get-create-buffer 'gdb-partial-output-buffer) (goto-char (point-min)) (while (re-search-forward gdb-break-list-regexp nil t) --- 380,392 ---- gdb-break-list-custom) (defconst gdb-break-list-regexp ! "number=\"\\(.*?\\)\",type=\"\\(.*?\\)\",disp=\"\\(.*?\\)\",enabled=\"\\(.\\)\",\ ! addr=\"\\(.*?\\)\",func=\"\\(.*?\\)\",file=\"\\(.*?\\)\",line=\"\\(.*?\\)\"") (defun gdb-break-list-handler () (setq gdb-pending-triggers (delq 'gdbmi-invalidate-breakpoints gdb-pending-triggers)) ! (let ((breakpoint) (breakpoints-list)) (with-current-buffer (gdb-get-create-buffer 'gdb-partial-output-buffer) (goto-char (point-min)) (while (re-search-forward gdb-break-list-regexp nil t) *************** *** 393,399 **** ;;-put breakpoint icons in relevant margins (even those set in the GUD buffer) (defun gdb-break-list-custom () ! (let ((flag)(address)) ;; ;; remove all breakpoint-icons in source buffers but not assembler buffer (dolist (buffer (buffer-list)) --- 419,425 ---- ;;-put breakpoint icons in relevant margins (even those set in the GUD buffer) (defun gdb-break-list-custom () ! (let ((flag) (bptno)) ;; ;; remove all breakpoint-icons in source buffers but not assembler buffer (dolist (buffer (buffer-list)) *************** *** 406,434 **** (goto-char (point-min)) (while (< (point) (- (point-max) 1)) (forward-line 1) ! (if (looking-at "[0-9]*\\s-*\\S-*\\s-*\\S-*\\s-*\\(.\\)\\s-*\\S-*\\s-*\\(\\S-*\\):\\([0-9]+\\)") (progn ! (setq flag (char-after (match-beginning 1))) ! (let ((line (match-string 3)) (buffer-read-only nil) ! (file (match-string 2))) (add-text-properties (point-at-bol) (point-at-eol) ! '(mouse-face highlight ! help-echo "mouse-2, RET: visit breakpoint")) ! (with-current-buffer ! (find-file-noselect ! (if (file-exists-p file) file ! (expand-file-name file gdb-cdir))) ! (save-current-buffer ! (set (make-local-variable 'gud-minor-mode) 'gdbmi) ! (set (make-local-variable 'tool-bar-map) ! gud-tool-bar-map)) ! ;; only want one breakpoint icon at each location ! (save-excursion ! (goto-line (string-to-number line)) ! (gdb-put-breakpoint-icon (eq flag ?y))))))))) ! (end-of-line))) (if (gdb-get-buffer 'gdb-assembler-buffer) (gdb-assembler-custom))) ;; Frames buffer. This displays a perpetually correct bactrack trace. ;; (def-gdb-auto-updated-buffer gdb-stack-buffer --- 432,492 ---- (goto-char (point-min)) (while (< (point) (- (point-max) 1)) (forward-line 1) ! (if (looking-at ! "\\([0-9]+\\)\\s-+\\S-+\\s-+\\S-+\\s-+\\(.\\)\\s-+\\S-+\\s-+\ ! \\(\\S-+\\):\\([0-9]+\\)") (progn ! (setq bptno (match-string 1)) ! (setq flag (char-after (match-beginning 2))) ! (let ((line (match-string 4)) (buffer-read-only nil) ! (file (match-string 3))) (add-text-properties (point-at-bol) (point-at-eol) ! '(mouse-face highlight ! help-echo "mouse-2, RET: visit breakpoint")) ! (unless (file-exists-p file) ! (setq file (cdr (assoc bptno gdb-location-list)))) ! (unless (string-equal file "File not found") ! (if file ! (with-current-buffer (find-file-noselect file) ! (set (make-local-variable 'gud-minor-mode) ! 'gdbmi) ! (set (make-local-variable 'tool-bar-map) ! gud-tool-bar-map) ! ;; only want one breakpoint icon at each location ! (save-excursion ! (goto-line (string-to-number line)) ! (gdb-put-breakpoint-icon (eq flag ?y) bptno))) ! (gdb-enqueue-input ! (list (concat "list " ! (match-string-no-properties 3) ":1\n") ! 'ignore)) ! (gdb-enqueue-input ! (list "-file-list-exec-source-file\n" ! `(lambda () (gdbmi-get-location ! ,bptno ,line ,flag))))))))))) ! (end-of-line))) (if (gdb-get-buffer 'gdb-assembler-buffer) (gdb-assembler-custom))) + (defun gdbmi-get-location (bptno line flag) + "Find the directory containing the relevant source file. + Put in buffer and place breakpoint icon." + (goto-char (point-min)) + (if (re-search-forward gdb-source-file-regexp nil t) + (push (cons bptno (match-string 1)) gdb-location-list) + (gdb-resync) + (push (cons bptno "File not found") gdb-location-list) + (error "Cannot find source file for breakpoint location. + Add directory to search path for source files using the GDB command, dir.")) + (with-current-buffer + (find-file-noselect (match-string 0)) + (save-current-buffer + (set (make-local-variable 'gud-minor-mode) 'gdbmi) + (set (make-local-variable 'tool-bar-map) gud-tool-bar-map)) + ;; only want one breakpoint icon at each location + (save-excursion + (goto-line (string-to-number line)) + (gdb-put-breakpoint-icon (eq flag ?y) bptno)))) + ;; Frames buffer. This displays a perpetually correct bactrack trace. ;; (def-gdb-auto-updated-buffer gdb-stack-buffer *************** *** 438,444 **** gdb-stack-list-frames-custom) (defconst gdb-stack-list-frames-regexp ! "level=\"\\(.*?\\)\",addr=\"\\(.*?\\)\",func=\"\\(.*?\\)\",file=\"\\(.*?\\)\",line=\"\\(.*?\\)\"") (defun gdb-stack-list-frames-handler () (setq gdb-pending-triggers (delq 'gdbmi-invalidate-frames --- 496,503 ---- gdb-stack-list-frames-custom) (defconst gdb-stack-list-frames-regexp ! "level=\"\\(.*?\\)\",addr=\"\\(.*?\\)\",func=\"\\(.*?\\)\",\ ! file=\"\\(.*?\\)\",line=\"\\(.*?\\)\"") (defun gdb-stack-list-frames-handler () (setq gdb-pending-triggers (delq 'gdbmi-invalidate-frames *************** *** 564,568 **** --- 623,654 ---- (gdb-get-create-buffer 'gdb-assembler-buffer))) (other-window 1)))) + + ;; these functions/variables may go into gdb-ui.el in the near future + ;; (from gdb-nui.el) + + (defvar gdb-source-file-list nil) + (defvar gdb-source-file-regexp "fullname=\"\\(.*?\\)\"") + + (defun gdb-get-source-file () + "Find the source file where the program starts and display it with related + buffers, if required." + (goto-char (point-min)) + (if (re-search-forward gdb-source-file-regexp nil t) + (setq gdb-main-file (match-string 1))) + (if gdb-many-windows + (gdb-setup-windows) + (gdb-get-create-buffer 'gdb-breakpoints-buffer) + (if gdb-show-main + (let ((pop-up-windows t)) + (display-buffer (gud-find-file gdb-main-file)))))) + + (defun gdb-get-source-file-list () + "Create list of source files for current GDB session." + (goto-char (point-min)) + (while (re-search-forward gdb-source-file-regexp nil t) + (push (match-string 1) gdb-source-file-list))) + + (provide 'gdb-mi) ;;; gdbmi.el ends here