# HG changeset patch # User Richard M. Stallman # Date 1039003015 0 # Node ID 81f6fbdaa1179d5a495a94d67bc2d55046923467 # Parent 546d8af61357948f6512dbf8aa257e0c7e86a843 (gud-menu-map): Update for bashdb. (perldb): Change prompt regexp. (gud-bashdb-history, gud-bashdb-massage-args, gud-bashdb-marker-filter) (gud-bashdb-find-file, gud-bashdb-command-name, bashdb): New. diff -r 546d8af61357 -r 81f6fbdaa117 lisp/gud.el --- a/lisp/gud.el Wed Dec 04 11:49:10 2002 +0000 +++ b/lisp/gud.el Wed Dec 04 11:56:55 2002 +0000 @@ -47,7 +47,7 @@ (defgroup gud nil "Grand Unified Debugger mode for gdb and other debuggers under Emacs. -Supported debuggers include gdb, sdb, dbx, xdb, perldb, pdb (Python), and jdb." +Supported debuggers include gdb, sdb, dbx, xdb, perldb, pdb (Python), jdb, and bash." :group 'unix :group 'tools) @@ -100,23 +100,26 @@ ([remove] menu-item "Remove Breakpoint" gud-remove :enable (not gud-running)) ([tbreak] menu-item "Temporary Breakpoint" gud-tbreak - :enable (memq gud-minor-mode '(gdba gdb sdb xdb))) + :enable (memq gud-minor-mode '(gdba gdb sdb xdb bashdb))) ([break] menu-item "Set Breakpoint" gud-break :enable (not gud-running)) ([up] menu-item "Up Stack" gud-up - :enable (and (not gud-running) - (memq gud-minor-mode '(gdba gdb dbx xdb jdb)))) + :enable (and (not gdb-running) + (memq gud-minor-mode + '(gdba gdb dbx xdb jdb bashdb)))) ([down] menu-item "Down Stack" gud-down - :enable (and (not gud-running) - (memq gud-minor-mode '(gdba gdb dbx xdb jdb)))) + :enable (and (not gdb-running) + (memq gud-minor-mode + '(gdba gdb dbx xdb jdb bashdb)))) ([print] menu-item "Print Expression" gud-print :enable (not gud-running)) ([display] menu-item "Display Expression" gud-display :enable (and (not gud-running) (eq gud-minor-mode 'gdba))) ([finish] menu-item "Finish Function" gud-finish - :enable (and (not gud-running) - (memq gud-minor-mode '(gdba gdb xdb jdb)))) + :enable (and (not gdb-running) + (memq gud-minor-mode + '(gdba gdb xdb jdb bashdb)))) ([stepi] "Step Instruction" . gud-stepi) ([step] menu-item "Step Line" gud-step :enable (not gud-running)) @@ -1318,7 +1321,7 @@ ; (gud-def gud-down "down %p" ">" "Down N stack frames (numeric arg).") (gud-def gud-print "%e" "\C-p" "Evaluate perl expression at point.") - (setq comint-prompt-regexp "^ DB<+[0-9]+>+ ") + (setq comint-prompt-regexp "^ DB<+(*[0-9])*+>+ ") (setq paragraph-start comint-prompt-regexp) (run-hooks 'perldb-mode-hook)) @@ -2104,6 +2107,167 @@ (fset 'gud-jdb-find-source 'gud-jdb-find-source-file))) +;; ====================================================================== +;; +;; BASHDB support. See http://bashdb.sourceforge.net +;; +;; AUTHOR: Rocky Bernstein +;; +;; CREATED: Sun Nov 10 10:46:38 2002 Rocky Bernstein. +;; +;; INVOCATION NOTES: +;; +;; You invoke bashdb-mode with: +;; +;; M-x bashdb +;; +;; It responds with: +;; +;; Run bashdb (like this): bash +;; + +;;; History of argument lists passed to bashdb. +(defvar gud-bashdb-history nil) + +;; Convert a command line as would be typed normally to run a script +;; into one that invokes an Emacs-enabled debugging session. +;; "--debugger" in inserted as the first switch. + +(defun gud-bashdb-massage-args (file args) + (let* ((new-args (list "--debugger")) + (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)))) + (funcall shift)) + + (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) + + (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 +;; might even receive a big chunk with several markers in it. If we +;; receive a chunk of text which looks like it might contain the +;; beginning of a marker, we save it here between calls to the +;; filter. +(defun gud-bashdb-marker-filter (string) + (setq gud-marker-acc (concat gud-marker-acc string)) + (let ((output "")) + + ;; Process all the complete markers in this chunk. + ;; Format of line looks like this: + ;; (/etc/init.d/ntp.init:16): + ;; but we also allow DOS drive letters + ;; (d:/etc/init.d/ntp.init:16): + (while (string-match "\\(^\\|\n\\)(\\(\\([a-zA-Z]:\\)?[^:\n]*\\):\\([0-9]*\\)):.*\n" + gud-marker-acc) + (setq + + ;; Extract the frame position from the marker. + gud-last-frame + (cons (substring gud-marker-acc (match-beginning 2) (match-end 2)) + (string-to-int (substring gud-marker-acc + (match-beginning 4) + (match-end 4)))) + + ;; Append any text before the marker to the output we're going + ;; to return - we don't include the marker in this text. + output (concat 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)))) + + ;; Does the remaining text look like it might end with the + ;; beginning of another marker? If it does, then keep it in + ;; gud-marker-acc until we receive the rest of it. Since we + ;; know the full marker regexp above failed, it's pretty simple to + ;; test for marker starts. + (if (string-match "\032.*\\'" gud-marker-acc) + (progn + ;; Everything before the potential marker start can be output. + (setq output (concat output (substring gud-marker-acc + 0 (match-beginning 0)))) + + ;; Everything after, we save, to combine with later input. + (setq gud-marker-acc + (substring gud-marker-acc (match-beginning 0)))) + + (setq output (concat output gud-marker-acc) + gud-marker-acc "")) + + output)) + +(defun gud-bashdb-find-file (f) + (save-excursion + (let ((buf (find-file-noselect f 'nowarn))) + (set-buffer buf) + buf))) + +(defcustom gud-bashdb-command-name "bash" + "File name for executing bash debugger." + :type 'string + :group 'gud) + +;;;###autoload +(defun bashdb (command-line) + "Run bashdb 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 bashdb (like this): " + (if (consp gud-bashdb-history) + (car gud-bashdb-history) + (concat gud-bashdb-command-name + " ")) + gud-minibuffer-local-map nil + '(gud-bashdb-history . 1)))) + + (gud-common-init command-line 'gud-bashdb-massage-args + 'gud-bashdb-marker-filter 'gud-bashdb-find-file) + + (set (make-local-variable 'gud-minor-mode) 'bashdb) + + (gud-def gud-break "break %l" "\C-b" "Set breakpoint at current line.") + (gud-def gud-tbreak "tbreak %l" "\C-t" "Set temporary 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 "continue" "\C-r" "Continue with display.") + (gud-def gud-finish "finish" "\C-f" "Finish executing current function.") + (gud-def gud-up "up %p" "<" "Up N stack frames (numeric arg).") + (gud-def gud-down "down %p" ">" "Down N stack frames (numeric arg).") + (gud-def gud-print "pe %e" "\C-p" "Evaluate bash expression at point.") + + ;; Is this right? + (gud-def gud-statement "eval %e" "\C-e" "Execute Python statement at point.") + + (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)) + + (setq comint-prompt-regexp "^bashdb<+[0-9]*>+ ") + (setq paragraph-start comint-prompt-regexp) + (run-hooks 'bashdb-mode-hook) + ) + +(provide 'bashdb) + ;; ;; End of debugger-specific information ;;