X-Git-Url: http://git.hcoop.net/bpt/emacs.git/blobdiff_plain/acb50e3cd42d5714272b9a0b449648662a145fe6..5553563924453df2e3c5bf011bf5b7527172b2f6:/lisp/gud.el diff --git a/lisp/gud.el b/lisp/gud.el index daa40daa6d..52bfacf633 100644 --- a/lisp/gud.el +++ b/lisp/gud.el @@ -4,7 +4,7 @@ ;; Maintainer: FSF ;; Keywords: unix, tools -;; Copyright (C) 1992, 93, 94, 95, 96, 1998 Free Software Foundation, Inc. +;; Copyright (C) 1992, 93, 94, 95, 96, 1998, 2000 Free Software Foundation, Inc. ;; This file is part of GNU Emacs. @@ -68,28 +68,67 @@ Supported debuggers include gdb, sdb, dbx, xdb, perldb, pdb (Python), and jdb." (defun gud-marker-filter (&rest args) (apply gud-marker-filter args)) +(defvar gud-minor-mode nil) +(put 'gud-minor-mode 'permanent-local t) + +(defun gud-symbol (sym &optional soft minor-mode) + "Return the symbol used for SYM in MINOR-MODE. +MINOR-MODE defaults to `gud-minor-mode. +The symbol returned is `gud--'. +If SOFT is non-nil, returns nil if the symbol doesn't already exist." + (unless (or minor-mode gud-minor-mode) (error "Gud internal error")) + (funcall (if soft 'intern-soft 'intern) + (format "gud-%s-%s" (or minor-mode gud-minor-mode) sym))) + +(defun gud-val (sym &optional minor-mode) + "Return the value of `gud-symbol' SYM. Default to nil." + (let ((sym (gud-symbol sym t minor-mode))) + (if (boundp sym) (symbol-value sym)))) + (defun gud-find-file (file) ;; Don't get confused by double slashes in the name that comes from GDB. (while (string-match "//+" file) (setq file (replace-match "/" t t file))) - (funcall gud-find-file file)) - -;; Keymap definitions for menu bar entries common to all debuggers and -;; slots for debugger-dependent ones in sensible places. (Defined here -;; before use.) -(defvar gud-menu-map (make-sparse-keymap "Gud") nil) -(define-key gud-menu-map [refresh] '("Refresh" . gud-refresh)) -(define-key gud-menu-map [remove] '("Remove Breakpoint" . gud-remove)) -(define-key gud-menu-map [tbreak] nil) ; gdb, sdb and xdb -(define-key gud-menu-map [break] '("Set Breakpoint" . gud-break)) -(define-key gud-menu-map [up] nil) ; gdb, dbx, and xdb -(define-key gud-menu-map [down] nil) ; gdb, dbx, and xdb -(define-key gud-menu-map [print] '("Print Expression" . gud-print)) -(define-key gud-menu-map [finish] nil) ; gdb or xdb -(define-key gud-menu-map [stepi] '("Step Instruction" . gud-stepi)) -(define-key gud-menu-map [step] '("Step Line" . gud-step)) -(define-key gud-menu-map [next] '("Next Line" . gud-next)) -(define-key gud-menu-map [cont] '("Continue" . gud-cont)) + (let ((minor-mode gud-minor-mode) + (buf (funcall gud-find-file file))) + (when buf + ;; Copy `gud-minor-mode' to the found buffer to turn on the menu. + (with-current-buffer buf + (set (make-local-variable 'gud-minor-mode) minor-mode)) + buf))) + +(easy-mmode-defmap gud-menu-map + '(([refresh] "Refresh" . gud-refresh) + ([remove] "Remove Breakpoint" . gud-remove) + ([tbreak] menu-item "Temporary Breakpoint" gud-tbreak + :enable (memq gud-minor-mode '(gdb sdb xdb))) + ([break] "Set Breakpoint" . gud-break) + ([up] menu-item "Up Stack" gud-up + :enable (memq gud-minor-mode '(gdb dbx xdb))) + ([down] menu-item "Down Stack" gud-down + :enable (memq gud-minor-mode '(gdb dbx xdb))) + ([print] "Print Expression" . gud-print) + ([finish] menu-item "Finish Function" gud-finish + :enable (memq gud-minor-mode '(gdb xdb))) + ([stepi] "Step Instruction" . gud-stepi) + ([step] "Step Line" . gud-step) + ([next] "Next Line" . gud-next) + ([cont] "Continue" . gud-cont)) + "Menu for `gud-mode'." + :name "Gud") + +(easy-mmode-defmap gud-minor-mode-map + `(([menu-bar debug] . ("Gud" . ,gud-menu-map))) + "Map used in visited files.") + +(let ((m (assq 'gud-minor-mode minor-mode-map-alist))) + (if m (setcdr m gud-minor-mode-map) + (push (cons 'gud-minor-mode gud-minor-mode-map) minor-mode-map-alist))) + +(defvar gud-mode-map + ;; Will inherit from comint-mode via define-derived-mode. + (make-sparse-keymap) + "`gud-mode' keymap.") ;; ====================================================================== ;; command definition @@ -110,6 +149,7 @@ optional doc string DOC. Certain %-escapes in the string arguments are interpreted specially if present. These are: %f name (without directory) of current source file. + %F name (without directory or extension) of current source file. %d directory of current source file. %l number of current source line %e text of the C lvalue or function-call expression surrounding point. @@ -170,7 +210,7 @@ we're in the GUD buffer)." ;; ;; The job of the find-file method is to visit and return the buffer indicated ;; by the car of gud-tag-frame. This may be a file name, a tag name, or -;; something else. It would be good if it also copied the Gud menubar entry. +;; something else. ;; ====================================================================== ;; speedbar support functions and variables. @@ -249,13 +289,13 @@ off the specialized speedbar mode." 'speedbar-highlight-face (cond ((eq ff 'gud-gdb-find-file) 'gud-gdb-goto-stackframe) - (t (error "Should never be here."))) + (t (error "Should never be here"))) (car frames) t)) (setq frames (cdr frames))) ; (let ((selected-frame ; (cond ((eq ff 'gud-gdb-find-file) ; (gud-gdb-selected-frame-info buffer)) -; (t (error "Should never be here.")))))) +; (t (error "Should never be here")))))) ) (setq gud-last-speedbar-stackframe gud-last-last-frame))) @@ -329,40 +369,34 @@ off the specialized speedbar mode." output)) (defun gud-gdb-find-file (f) - (save-excursion - (let ((buf (find-file-noselect f))) - (set-buffer buf) - (gud-make-debug-menu) - (local-set-key [menu-bar debug tbreak] - '("Temporary Breakpoint" . gud-tbreak)) - (local-set-key [menu-bar debug finish] '("Finish Function" . gud-finish)) - (local-set-key [menu-bar debug up] '("Up Stack" . gud-up)) - (local-set-key [menu-bar debug down] '("Down Stack" . gud-down)) - buf))) - -(defvar gdb-minibuffer-local-map nil - "Keymap for minibuffer prompting of gdb startup command.") -(if gdb-minibuffer-local-map - () - (setq gdb-minibuffer-local-map (copy-keymap minibuffer-local-map)) - (define-key - gdb-minibuffer-local-map "\C-i" 'comint-dynamic-complete-filename)) + (find-file-noselect f 'nowarn)) + +(easy-mmode-defmap gud-minibuffer-local-map + '(("\C-i" . comint-dynamic-complete-filename)) + "Keymap for minibuffer prompting of gud startup command." + :inherit minibuffer-local-map) + +(defun gud-query-cmdline (minor-mode &optional init) + (let* ((hist-sym (gud-symbol 'history nil minor-mode)) + (cmd-name (gud-val 'command-name minor-mode))) + (unless (boundp hist-sym) (set hist-sym nil)) + (read-from-minibuffer + (format "Run %s (like this): " minor-mode) + (or (car-safe (symbol-value hist-sym)) + (concat (or cmd-name (symbol-name minor-mode)) " " init)) + gud-minibuffer-local-map nil + hist-sym))) ;;;###autoload (defun gdb (command-line) "Run gdb on program FILE in buffer *gud-FILE*. The directory containing FILE becomes the initial working directory and source-file directory for your debugger." - (interactive - (list (read-from-minibuffer "Run gdb (like this): " - (if (consp gud-gdb-history) - (car gud-gdb-history) - "gdb ") - gdb-minibuffer-local-map nil - '(gud-gdb-history . 1)))) + (interactive (list (gud-query-cmdline 'gdb))) (gud-common-init command-line 'gud-gdb-massage-args 'gud-gdb-marker-filter 'gud-gdb-find-file) + (set (make-local-variable 'gud-minor-mode) 'gdb) (gud-def gud-break "break %f:%l" "\C-b" "Set breakpoint at current line.") (gud-def gud-tbreak "tbreak %f:%l" "\C-t" "Set temporary breakpoint at current line.") @@ -410,11 +444,7 @@ This is implemented using the GDB `complete' command which isn't available with older versions of GDB." (interactive) (let* ((end (point)) - (command (save-excursion - (beginning-of-line) - (and (looking-at comint-prompt-regexp) - (goto-char (match-end 0))) - (buffer-substring (point) end))) + (command (buffer-substring (comint-line-beginning-position) end)) command-word) ;; Find the word break. This match will always succeed. (string-match "\\(\\`\\| \\)\\([^ ]*\\)\\'" command) @@ -434,7 +464,7 @@ available with older versions of GDB." (and gud-gdb-complete-list (string-match "^Undefined command: \"complete\"" (car gud-gdb-complete-list)) - (error "This version of GDB doesn't support the `complete' command.")) + (error "This version of GDB doesn't support the `complete' command")) ;; Sort the list like readline. (setq gud-gdb-complete-list (sort gud-gdb-complete-list (function string-lessp))) @@ -550,7 +580,7 @@ BUFFER is the GUD buffer in which to run the command." (set-buffer buffer) (if (save-excursion (goto-char (point-max)) - (beginning-of-line) + (forward-line 0) (not (looking-at comint-prompt-regexp))) nil ;; Much of this copied from GDB complete, but I'm grabbing the stack @@ -649,35 +679,24 @@ BUFFER is the GUD buffer in which to run the command." string) (defun gud-sdb-find-file (f) - (save-excursion - (let ((buf (if gud-sdb-needs-tags - (find-tag-noselect f) - (find-file-noselect f)))) - (set-buffer buf) - (gud-make-debug-menu) - (local-set-key [menu-bar debug tbreak] '("Temporary Breakpoint" . gud-tbreak)) - buf))) + (if gud-sdb-needs-tags (find-tag-noselect f) (find-file-noselect f))) ;;;###autoload (defun sdb (command-line) "Run sdb on program FILE in buffer *gud-FILE*. The directory containing FILE becomes the initial working directory and source-file directory for your debugger." - (interactive - (list (read-from-minibuffer "Run sdb (like this): " - (if (consp gud-sdb-history) - (car gud-sdb-history) - "sdb ") - nil nil - '(gud-sdb-history . 1)))) + (interactive (list (gud-query-cmdline 'sdb))) + (if (and gud-sdb-needs-tags (not (and (boundp 'tags-file-name) (stringp tags-file-name) (file-exists-p tags-file-name)))) - (error "The sdb support requires a valid tags table to work.")) + (error "The sdb support requires a valid tags table to work")) (gud-common-init command-line 'gud-sdb-massage-args 'gud-sdb-marker-filter 'gud-sdb-find-file) + (set (make-local-variable 'gud-minor-mode) 'sdb) (gud-def gud-break "%l b" "\C-b" "Set breakpoint at current line.") (gud-def gud-tbreak "%l c" "\C-t" "Set temporary breakpoint at current line.") @@ -984,26 +1003,14 @@ This was tested using R4.11.") (save-excursion (let ((realf (gud-dbx-file-name f))) (if realf - (let ((buf (find-file-noselect realf))) - (set-buffer buf) - (gud-make-debug-menu) - (local-set-key [menu-bar debug up] '("Up Stack" . gud-up)) - (local-set-key [menu-bar debug down] '("Down Stack" . gud-down)) - buf) - nil)))) + (find-file-noselect realf))))) ;;;###autoload (defun dbx (command-line) "Run dbx on program FILE in buffer *gud-FILE*. The directory containing FILE becomes the initial working directory and source-file directory for your debugger." - (interactive - (list (read-from-minibuffer "Run dbx (like this): " - (if (consp gud-dbx-history) - (car gud-dbx-history) - "dbx ") - nil nil - '(gud-dbx-history . 1)))) + (interactive (list (gud-query-cmdline 'dbx))) (cond (gud-mips-p @@ -1019,6 +1026,8 @@ and source-file directory for your debugger." (gud-common-init command-line 'gud-dbx-massage-args 'gud-dbx-marker-filter 'gud-dbx-find-file))) + (set (make-local-variable 'gud-minor-mode) 'dbx) + (cond (gud-mips-p (gud-def gud-up "up %p" "<" "Up (numeric arg) stack frames.") @@ -1126,17 +1135,7 @@ containing the executable being debugged." (save-excursion (let ((realf (gud-xdb-file-name f))) (if realf - (let ((buf (find-file-noselect realf))) - (set-buffer buf) - (gud-make-debug-menu) - (local-set-key [menu-bar debug tbreak] - '("Temporary Breakpoint" . gud-tbreak)) - (local-set-key [menu-bar debug finish] - '("Finish Function" . gud-finish)) - (local-set-key [menu-bar debug up] '("Up Stack" . gud-up)) - (local-set-key [menu-bar debug down] '("Down Stack" . gud-down)) - buf) - nil)))) + (find-file-noselect realf))))) ;;;###autoload (defun xdb (command-line) @@ -1146,16 +1145,11 @@ and source-file directory for your debugger. You can set the variable 'gud-xdb-directories' to a list of program source directories if your program contains sources from more than one directory." - (interactive - (list (read-from-minibuffer "Run xdb (like this): " - (if (consp gud-xdb-history) - (car gud-xdb-history) - "xdb ") - nil nil - '(gud-xdb-history . 1)))) + (interactive (list (gud-query-cmdline 'xdb))) (gud-common-init command-line 'gud-xdb-massage-args 'gud-xdb-marker-filter 'gud-xdb-find-file) + (set (make-local-variable 'gud-minor-mode) 'xdb) (gud-def gud-break "b %f:%l" "\C-b" "Set breakpoint at current line.") (gud-def gud-tbreak "b %f:%l\\t" "\C-t" @@ -1183,14 +1177,48 @@ directories if your program contains sources from more than one directory." ;;; History of argument lists passed to perldb. (defvar gud-perldb-history nil) +;; Convert a command line as would be typed normally to run a script +;; into one that invokes an Emacs-enabled debugging session. +;; "-d" in inserted as the first switch, and "-emacs" is inserted where +;; it will be $ARGV[0] (see perl5db.pl). (defun gud-perldb-massage-args (file args) - (cond ((equal (car args) "-e") - (cons "-d" - (cons (car args) - (cons (nth 1 args) - (cons "--" (cons "-emacs" (cdr (cdr args)))))))) - (t - (cons "-d" (cons (car args) (cons "-emacs" (cdr args))))))) + (let* ((new-args (list "-d")) + (seen-e nil) + (shift (lambda () + (setq new-args (cons (car args) new-args)) + (setq args (cdr args))))) + + ;; Pass all switches and -e scripts through. + (while (and args + (string-match "^-" (car args)) + (not (equal "-" (car args))) + (not (equal "--" (car args)))) + (when (equal "-e" (car args)) + ;; -e goes with the next arg, so shift one extra. + (or (funcall shift) + ;; -e as the last arg is an error in Perl. + (error "No code specified for -e")) + (setq seen-e t)) + (funcall shift)) + + (unless seen-e + (if (or (not args) + (string-match "^-" (car args))) + (error "Can't use stdin as the script to debug")) + ;; This is the program name. + (funcall shift)) + + ;; If -e specified, make sure there is a -- so -emacs is not taken + ;; as -e macs. + (if (and args (equal "--" (car args))) + (funcall shift) + (and seen-e (push "--" new-args))) + + (push "-emacs" new-args) + (while args + (funcall shift)) + + (nreverse new-args))) ;; There's no guarantee that Emacs will hand the filter the entire ;; marker at once; it could be broken up across several strings. We @@ -1243,11 +1271,7 @@ directories if your program contains sources from more than one directory." output)) (defun gud-perldb-find-file (f) - (save-excursion - (let ((buf (find-file-noselect f))) - (set-buffer buf) - (gud-make-debug-menu) - buf))) + (find-file-noselect f)) (defcustom gud-perldb-command-name "perl" "File name for executing Perl." @@ -1260,19 +1284,12 @@ directories if your program contains sources from more than one directory." The directory containing FILE becomes the initial working directory and source-file directory for your debugger." (interactive - (list (read-from-minibuffer "Run perldb (like this): " - (if (consp gud-perldb-history) - (car gud-perldb-history) - (concat gud-perldb-command-name - " " - (or (buffer-file-name) - "-e 0") - " ")) - nil nil - '(gud-perldb-history . 1)))) + (list (gud-query-cmdline 'perldb + (concat (or (buffer-file-name) "-e 0") " ")))) (gud-common-init command-line 'gud-perldb-massage-args 'gud-perldb-marker-filter 'gud-perldb-find-file) + (set (make-local-variable 'gud-minor-mode) 'perldb) (gud-def gud-break "b %l" "\C-b" "Set breakpoint at current line.") (gud-def gud-remove "d %l" "\C-d" "Remove breakpoint at current line") @@ -1286,8 +1303,7 @@ and source-file directory for your debugger." (setq comint-prompt-regexp "^ DB<+[0-9]+>+ ") (setq paragraph-start comint-prompt-regexp) - (run-hooks 'perldb-mode-hook) - ) + (run-hooks 'perldb-mode-hook)) ;; ====================================================================== ;; pdb (Python debugger) functions @@ -1364,22 +1380,7 @@ and source-file directory for your debugger." output)) (defun gud-pdb-find-file (f) - (save-excursion - (let ((buf (find-file-noselect f))) - (set-buffer buf) - (gud-make-debug-menu) - ;; (local-set-key [menu-bar debug finish] '("Finish Function" . gud-finish)) - ;; (local-set-key [menu-bar debug up] '("Up Stack" . gud-up)) - ;; (local-set-key [menu-bar debug down] '("Down Stack" . gud-down)) - buf))) - -(defvar pdb-minibuffer-local-map nil - "Keymap for minibuffer prompting of pdb startup command.") -(if pdb-minibuffer-local-map - () - (setq pdb-minibuffer-local-map (copy-keymap minibuffer-local-map)) - (define-key - pdb-minibuffer-local-map "\C-i" 'comint-dynamic-complete-filename)) + (find-file-noselect f)) (defcustom gud-pdb-command-name "pdb" "File name for executing the Python debugger. @@ -1393,15 +1394,11 @@ This should be an executable on your path, or an absolute file name." The directory containing FILE becomes the initial working directory and source-file directory for your debugger." (interactive - (list (read-from-minibuffer "Run pdb (like this): " - (if (consp gud-pdb-history) - (car gud-pdb-history) - (concat gud-pdb-command-name " ")) - pdb-minibuffer-local-map nil - '(gud-pdb-history . 1)))) + (list (gud-query-cmdline 'pdb))) (gud-common-init command-line 'gud-pdb-massage-args 'gud-pdb-marker-filter 'gud-pdb-find-file) + (set (make-local-variable 'gud-minor-mode) 'pdb) (gud-def gud-break "break %l" "\C-b" "Set breakpoint at current line.") (gud-def gud-remove "clear %l" "\C-d" "Remove breakpoint at current line") @@ -1510,7 +1507,15 @@ and source-file directory for your debugger." ;; List of Java source file directories. (defvar gud-jdb-directories (list ".") "*A list of directories that gud jdb should search for source code. -The file names should be absolute, or relative to the current directory.") +The file names should be absolute, or relative to the current +directory. + +The set of .java files residing in the directories listed are +syntactically analyzed to determine the classes they define and the +packages in which these classes belong. In this way gud jdb maps the +package-qualified class names output by the jdb debugger to the source +file from which the class originated. This allows gud mode to keep +the source code display in sync with the debugging session.") ;; List of the java source files for this debugging session. (defvar gud-jdb-source-files nil) @@ -1526,7 +1531,10 @@ The file names should be absolute, or relative to the current directory.") ;; which to search for files with extension EXTN. Normally EXTN is ;; given as the regular expression "\\.java$" . (defun gud-jdb-build-source-files-list (path extn) - (apply 'nconc (mapcar (lambda (d) (directory-files d t extn nil)) path))) + (apply 'nconc (mapcar (lambda (d) + (when (file-directory-p d) + (directory-files d t extn nil))) + path))) ;; Move point past whitespace. (defun gud-jdb-skip-whitespace () @@ -1574,11 +1582,10 @@ The file names should be absolute, or relative to the current directory.") ;; Move point past a string literal. (defun gud-jdb-skip-string-literal () (forward-char) - (while - (progn - (if (eq (following-char) ?\\) - (forward-char 2)) - (not (eq (following-char) ?\042))) + (while (not (cond + ((eq (following-char) ?\\) + (forward-char)) + ((eq (following-char) ?\042)))) (forward-char)) (forward-char)) @@ -1727,7 +1734,7 @@ The file names should be absolute, or relative to the current directory.") ;; holding their definitions. SOURCES holds a list of all the source ;; files to examine. (defun gud-jdb-build-class-source-alist (sources) - (setq gud-jdb-analysis-buffer (get-buffer-create "*gud-jdb-scratch*")) + (setq gud-jdb-analysis-buffer (get-buffer-create " *gud-jdb-scratch*")) (prog1 (apply 'nconc @@ -1766,7 +1773,7 @@ The file names should be absolute, or relative to the current directory.") (if user-error (progn (kill-buffer (current-buffer)) - (error "Error: Omit whitespace between '-classpath' and it's value"))) + (error "Error: Omit whitespace between '-classpath' and its value"))) (if args (setq massaged-args @@ -1871,23 +1878,19 @@ The file names should be absolute, or relative to the current directory.") if there is. If the \"-classpath\" switch is given, omit all whitespace between it and it's value." (interactive - (list (read-from-minibuffer "Run jdb (like this): " - (if (consp gud-jdb-history) - (car gud-jdb-history) - (concat gud-jdb-command-name " ")) - nil nil - '(gud-jdb-history . 1)))) + (list (gud-query-cmdline 'jdb))) (gud-common-init command-line 'gud-jdb-massage-args 'gud-jdb-marker-filter 'gud-jdb-find-file) + (set (make-local-variable 'gud-minor-mode) 'jdb) - (gud-def gud-break "stop at %l" "\C-b" "Set breakpoint at current line.") + (gud-def gud-break "stop at %F:%l" "\C-b" "Set breakpoint at current line.") (gud-def gud-remove "clear %l" "\C-d" "Remove breakpoint at current line") (gud-def gud-step "step" "\C-s" "Step one source line with display.") (gud-def gud-next "next" "\C-n" "Step one line (skip functions).") (gud-def gud-cont "cont" "\C-r" "Continue with display.") - (setq comint-prompt-regexp "^> \|^.+\[[0-9]+\] ") + (setq comint-prompt-regexp "^> \\|^.+\\[[0-9]+\\] ") (setq paragraph-start comint-prompt-regexp) (run-hooks 'jdb-mode-hook) @@ -1951,7 +1954,7 @@ between it and it's value." (put 'gud-mode 'mode-class 'special) -(defun gud-mode () +(define-derived-mode gud-mode comint-mode "Debugger" "Major mode for interacting with an inferior debugger process. You start it up with one of the commands M-x gdb, M-x sdb, M-x dbx, @@ -2005,50 +2008,31 @@ commands. Other commands for interacting with the debugger process are inherited from comint mode, which see." - (interactive) - (comint-mode) - (setq major-mode 'gud-mode) - (setq mode-name "Debugger") (setq mode-line-process '(":%s")) - (use-local-map comint-mode-map) - (gud-make-debug-menu) (define-key (current-local-map) "\C-c\C-l" 'gud-refresh) - (make-local-variable 'gud-last-frame) - (setq gud-last-frame nil) + (set (make-local-variable 'gud-last-frame) nil) (make-local-variable 'comint-prompt-regexp) ;; Don't put repeated commands in command history many times. - (make-local-variable 'comint-input-ignoredups) - (setq comint-input-ignoredups t) + (set (make-local-variable 'comint-input-ignoredups) t) (make-local-variable 'paragraph-start) - (make-local-variable 'gud-delete-prompt-marker) - (setq gud-delete-prompt-marker (make-marker)) - (run-hooks 'gud-mode-hook)) - -;; Chop STRING into words separated by SPC or TAB and return a list of them. -(defun gud-chop-words (string) - (let ((i 0) (beg 0) - (len (length string)) - (words nil)) - (while (< i len) - (if (memq (aref string i) '(?\t ? )) - (progn - (setq words (cons (substring string beg i) words) - beg (1+ i)) - (while (and (< beg len) (memq (aref string beg) '(?\t ? ))) - (setq beg (1+ beg))) - (setq i (1+ beg))) - (setq i (1+ i)))) - (if (< beg len) - (setq words (cons (substring string beg) words))) - (nreverse words))) + (set (make-local-variable 'gud-delete-prompt-marker) (make-marker))) + +;; Cause our buffers to be displayed, by default, +;; in the selected window. +;;;###autoload (add-hook 'same-window-regexps "\\*gud-.*\\*\\(\\|<[0-9]+>\\)") + +(defcustom gud-chdir-before-run t + "Non-nil if GUD should `cd' to the debugged executable." + :group 'gud + :type 'boolean) ;; Perform initializations common to all debuggers. ;; The first arg is the specified command line, ;; which starts with the program to debug. ;; The other three args specify the values to use ;; for local variables in the debugger buffer. -(defun gud-common-init (command-line massage-args marker-filter find-file) - (let* ((words (gud-chop-words command-line)) +(defun gud-common-init (command-line massage-args marker-filter &optional find-file) + (let* ((words (split-string command-line)) (program (car words)) ;; Extract the file name from WORDS ;; and put t in its place. @@ -2072,9 +2056,10 @@ comint mode, which see." (expand-file-name file-subst) file-subst))) (filepart (and file-word (concat "-" (file-name-nondirectory file))))) - (switch-to-buffer (concat "*gud" filepart "*")) + (pop-to-buffer (concat "*gud" filepart "*")) ;; Set default-directory to the file's directory. (and file-word + gud-chdir-before-run ;; Don't set default-directory if no directory was specified. ;; In that case, either the file is found in the current directory, ;; in which case this setq is a no-op, @@ -2096,17 +2081,15 @@ comint mode, which see." (gud-mode) (make-local-variable 'gud-marker-filter) (setq gud-marker-filter marker-filter) - (make-local-variable 'gud-find-file) - (setq gud-find-file find-file) + (if find-file (set (make-local-variable 'gud-find-file) find-file)) (set-process-filter (get-buffer-process (current-buffer)) 'gud-filter) (set-process-sentinel (get-buffer-process (current-buffer)) 'gud-sentinel) - (gud-set-buffer) - ) + (gud-set-buffer)) (defun gud-set-buffer () - (cond ((eq major-mode 'gud-mode) - (setq gud-comint-buffer (current-buffer))))) + (when (eq major-mode 'gud-mode) + (setq gud-comint-buffer (current-buffer)))) (defvar gud-filter-defer-flag nil "Non-nil means don't process anything from the debugger right now. @@ -2137,23 +2120,26 @@ It is saved for when this flag is not set.") (if gud-filter-pending-text (setq string (concat gud-filter-pending-text string) gud-filter-pending-text nil)) - (save-excursion - (set-buffer (process-buffer proc)) + + (with-current-buffer (process-buffer proc) ;; If we have been so requested, delete the debugger prompt. - (if (marker-buffer gud-delete-prompt-marker) - (progn - (delete-region (process-mark proc) gud-delete-prompt-marker) - (set-marker gud-delete-prompt-marker nil))) - ;; Save the process output, checking for source file markers. - (setq output (gud-marker-filter string)) - ;; Check for a filename-and-line number. - ;; Don't display the specified file - ;; unless (1) point is at or after the position where output appears - ;; and (2) this buffer is on the screen. - (setq process-window - (and gud-last-frame - (>= (point) (process-mark proc)) - (get-buffer-window (current-buffer)))) + (save-restriction + (widen) + (if (marker-buffer gud-delete-prompt-marker) + (progn + (delete-region (process-mark proc) + gud-delete-prompt-marker) + (set-marker gud-delete-prompt-marker nil))) + ;; Save the process output, checking for source file markers. + (setq output (gud-marker-filter string)) + ;; Check for a filename-and-line number. + ;; Don't display the specified file + ;; unless (1) point is at or after the position where output appears + ;; and (2) this buffer is on the screen. + (setq process-window + (and gud-last-frame + (>= (point) (process-mark proc)) + (get-buffer-window (current-buffer))))) ;; Let the comint filter do the actual insertion. ;; That lets us inherit various comint features. @@ -2275,6 +2261,11 @@ Obeying it means displaying in another window the specified file and line." (setq subst (file-name-nondirectory (if insource (buffer-file-name) (car frame))))) + ((eq key ?F) + (setq subst (file-name-sans-extension + (file-name-nondirectory (if insource + (buffer-file-name) + (car frame)))))) ((eq key ?d) (setq subst (file-name-directory (if insource (buffer-file-name) @@ -2283,18 +2274,17 @@ Obeying it means displaying in another window the specified file and line." (setq subst (if insource (save-excursion (beginning-of-line) - (save-restriction (widen) - (1+ (count-lines 1 (point))))) + (save-restriction + (widen) + (int-to-string (1+ (count-lines 1 (point)))))) (cdr frame)))) ((eq key ?e) (setq subst (gud-find-c-expr))) ((eq key ?a) (setq subst (gud-read-address))) ((eq key ?p) - (setq subst (if arg (int-to-string arg) "")))) - (setq result (concat result - (substring str (match-beginning 1) (match-end 1)) - subst))) + (setq subst (if arg (int-to-string arg))))) + (setq result (concat result (match-string 1 str) subst))) (setq str (substring str (match-end 2)))) ;; There might be text left in STR when the loop ends. (concat result str))) @@ -2334,10 +2324,12 @@ Obeying it means displaying in another window the specified file and line." ;; Arrange for the current prompt to get deleted. (save-excursion (set-buffer gud-comint-buffer) - (goto-char (process-mark proc)) - (beginning-of-line) - (if (looking-at comint-prompt-regexp) - (set-marker gud-delete-prompt-marker (point)))) + (save-restriction + (widen) + (goto-char (process-mark proc)) + (forward-line 0) + (if (looking-at comint-prompt-regexp) + (set-marker gud-delete-prompt-marker (point))))) (process-send-string proc command))) (defun gud-refresh (&optional arg) @@ -2347,22 +2339,6 @@ Obeying it means displaying in another window the specified file and line." (or gud-last-frame (setq gud-last-frame gud-last-last-frame)) (gud-display-frame)) - -(defun gud-new-keymap (map) - "Return a new keymap which inherits from MAP and has name `Gud'." - (nconc (make-sparse-keymap "Gud") map)) - -(defun gud-make-debug-menu () - "Make sure the current local map has a [menu-bar debug] submap. -If it doesn't, replace it with a new map that inherits it, -and create such a submap in that new map." - (if (and (current-local-map) - (lookup-key (current-local-map) [menu-bar debug])) - nil - (use-local-map (gud-new-keymap (current-local-map))) - (define-key (current-local-map) [menu-bar debug] - (cons "Gud" (gud-new-keymap gud-menu-map))))) - ;;; Code for parsing expressions out of C code. The single entry point is ;;; find-c-expr, which tries to return an lvalue expression from around point. ;;; @@ -2393,8 +2369,7 @@ and create such a submap in that new map." (setq test-expr (gud-next-expr)) (while (gud-expr-compound expr test-expr) (setq expr (cons (car expr) (cdr test-expr))) - (setq test-expr (gud-next-expr)) - ) + (setq test-expr (gud-next-expr))) (buffer-substring (car expr) (cdr expr))))) (defun gud-innermost-expr ()