1;;; bashdb.el --- Grand Unified Debugger mode for running bashdb
2;; Copyright (C) 2000, 2001 Masatake YAMATO
3
4;; Author: Masatake YAMATO <jet@gyve.org>
5
6;; This program is free software; you can redistribute it and/or modify it
7;; under the terms of the GNU General Public License as published by
8;; the Free Software Foundation; either version 2 of the License, or
9;; (at your option) any later version.
10
11;; This program is distributed in the hope that it will be useful, but
12;; WITHOUT ANY WARRANTY; without even the implied warranty of
13;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14;; GNU General Public License for more details.
15
16;; You should have received a copy of the GNU General Public License
17;; along with this program; if not, write to the Free Software Foundation,
18;; Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
20;; Commentary:
21;; This program may run on Emacs 21.0.91 and XEmacs 21.1.
22;;
23;; Put
24;; (autoload 'bashdb "bashdb" "Run bashdb" t nil)
25;;  to your .emacs.
26;; M-x bashdb
27;; Run bashdb (like this): bashdb target.sh
28;;
29;; About bashdb:
30;; You can get bashdb from
31;; http://www.oranda.demon.co.uk/development.html
32;;
33;; bashdb.el is based on perldb in gud.el in XEmacs 21.1.
34
35;; Revision:
36;; $Revision: 1.6 $
37;; $Log: bashdb.el,v $
38;; Revision 1.6  2001/01/06 12:18:06  masata-y
39;; Write note about XEmacs.
40;;
41;;
42
43
44;;; Code:
45(require 'gud)
46
47;; User customizable variable
48(defcustom gud-bashdb-command-name "bashdb"
49  "File name for executing Bashdb."
50  :type 'string
51  :group 'gud)
52
53;; History of argument lists passed to bashdb.
54(defvar gud-bashdb-history nil)
55
56(defun gud-bashdb-massage-args (file args)
57  (if xemacsp
58      (cons (file-name-nondirectory file) args)
59    args))
60
61;; There's no guarantee that Emacs will hand the filter the entire
62;; marker at once; it could be broken up across several strings.  We
63;; might even receive a big chunk with several markers in it.  If we
64;; receive a chunk of text which looks like it might contain the
65;; beginning of a marker, we save it here between calls to the
66;; filter.
67(if xemacsp
68    (defvar gud-bashdb-marker-acc ""))
69(defun gud-bashdb-marker-acc ()
70  (if xemacsp
71      gud-bashdb-marker-acc
72    gud-marker-acc))
73(defun gud-bashdb-marker-acc-quote ()
74  (if xemacsp
75      'gud-bashdb-marker-acc
76    'gud-marker-acc))
77
78(defun gud-bashdb-marker-filter (string)
79  (save-match-data
80    (set (gud-bashdb-marker-acc-quote)
81	 (concat (gud-bashdb-marker-acc) string))
82    (let ((output ""))
83      ;; Process all the complete markers in this chunk.
84      (while (string-match "^\\([^:\n]+\\):\\([0-9]+\\)[ *]*>.*\n"
85			   (gud-bashdb-marker-acc))
86	(setq
87	 ;; Extract the frame position from the marker.
88	 gud-last-frame (cons
89			 (substring (gud-bashdb-marker-acc)
90				    (match-beginning 1)
91				    (match-end 1))
92			 (string-to-int
93			  (substring (gud-bashdb-marker-acc)
94				     (match-beginning 2)
95				     (match-end 2))))
96	 ;; Append any text before the marker to the output we're going
97	 ;; to return - we don't include the marker in this text.
98	 output (concat output
99			(substring (gud-bashdb-marker-acc) 0 (match-beginning 0))))
100	 ;; Set the accumulator to the remaining text.
101	(set
102	 (gud-bashdb-marker-acc-quote) (substring
103					(gud-bashdb-marker-acc) (match-end 0))))
104
105      ;; Does the remaining text look like it might end with the
106      ;; beginning of another marker?  If it does, then keep it in
107      ;; (gud-bashdb-marker-acc) until we receive the rest of it.  Since we
108      ;; know the full marker regexp above failed, it's pretty simple to
109      ;; test for marker starts.
110      (if (string-match "^\\([^:\n]+\\):\\([0-9]+\\)[ *]*>" (gud-bashdb-marker-acc))
111	  (progn
112	    ;; Everything before the potential marker start can be output.
113	    (setq output (concat output (substring (gud-bashdb-marker-acc)
114						   0 (match-beginning 0))))
115	    ;; Everything after, we save, to combine with later input.
116	    (set (gud-bashdb-marker-acc-quote)
117		 (substring (gud-bashdb-marker-acc) (match-beginning 0))))
118
119	(setq output (concat output (gud-bashdb-marker-acc)))
120	(set (gud-bashdb-marker-acc-quote) ""))
121
122      output)))
123
124(defun gud-bashdb-find-file (f)
125  (find-file-noselect f))
126
127;;;###autoload
128(defun bashdb (command-line)
129  "Run bashdb on program FILE in buffer *gud-FILE*.
130The directory containing FILE becomes the initial working directory
131and source-file directory for your debugger."
132  (interactive
133   (if xemacsp
134       (list (read-from-minibuffer "Run bashdb (like this): "
135				   (if (consp gud-bashdb-history)
136				       (car gud-bashdb-history)
137				     (format "%s " gud-bashdb-command-name))
138				   nil nil
139				   '(gud-bashdb-history . 1)))
140     (list (gud-query-cmdline 'bashdb))
141     ))
142
143  (if xemacsp
144      (progn
145	(gud-overload-functions '((gud-massage-args . gud-bashdb-massage-args)
146				  (gud-marker-filter . gud-bashdb-marker-filter)
147				  (gud-find-file . gud-bashdb-find-file)))
148	(gud-common-init command-line gud-bashdb-command-name))
149    (gud-common-init command-line 'gud-bashdb-massage-args
150		     'gud-bashdb-marker-filter 'gud-bashdb-find-file)
151    (set (make-local-variable 'gud-minor-mode) 'bashdb))
152
153;; Unsupported commands
154;;  condition foo	set break condition to foo
155;;  condition	clear break condition
156;;  display EXP	evaluate and display EXP for each debug step
157;;  display		show a list of display expressions
158;;  undisplay N	remove display expression N
159;;  ! string	passes string to a shell
160;;  quit		quit
161
162  (gud-def gud-break       "break %l"     "\C-b" "Set breakpoint at current line.")
163  (gud-def gud-list-break  "break"        "b"    "List breakpoints & break condition.")
164  (gud-def gud-remove      "delete %l"    "\C-d" "Remove breakpoint at current line")
165  (gud-def gud-remove-all  "delete"       "d"    "Clear all breakpoints")
166  (gud-def gud-cont   "continue"          "\C-r" "Continue with display.")
167  (gud-def gud-next   "next"              "\C-n" "Step one line (skip functions).")
168  (gud-def gud-print  "print %e"          "\C-p" "Evaluate bash expression at point.")
169  (gud-def gud-help   "help"              "h"    "Show all commands.")
170  (gud-def gud-trace  "trace"             "t"    "Toggle execution trace on/off")
171
172  (setq comint-prompt-regexp "^bashdb> ")
173  (setq paragraph-start comint-prompt-regexp)
174  (run-hooks 'bashdb-mode-hook))
175
176(provide 'bashdb)
177;; bashdb.el ends here
178