changeset 48657:81f6fbdaa117

(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.
author Richard M. Stallman <rms@gnu.org>
date Wed, 04 Dec 2002 11:56:55 +0000
parents 546d8af61357
children 9994fce2e427
files lisp/gud.el
diffstat 1 files changed, 173 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- 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 <rocky@panix.com>
+;;
+;; CREATED:	Sun Nov 10 10:46:38 2002 Rocky Bernstein.
+;;
+;; INVOCATION NOTES:
+;;
+;; You invoke bashdb-mode with:
+;;
+;;    M-x bashdb <enter>
+;;
+;; 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
 ;;