diff options
author | Stephen Hemminger <stephen.hemminger@vyatta.com> | 2010-10-11 14:49:26 -0700 |
---|---|---|
committer | Stephen Hemminger <stephen.hemminger@vyatta.com> | 2010-10-11 15:19:40 -0700 |
commit | 011c1d1c0766c65517ebd495465c99e86edb63ec (patch) | |
tree | 30d8f6a13235af90897c3223554871ef52225462 /examples/obashdb | |
parent | 40cfaccf7b178b6239b5cd0013ef80b7ff8e503e (diff) | |
download | vyatta-bash-011c1d1c0766c65517ebd495465c99e86edb63ec.tar.gz vyatta-bash-011c1d1c0766c65517ebd495465c99e86edb63ec.zip |
Update to bash-4.1
Diffstat (limited to 'examples/obashdb')
-rw-r--r-- | examples/obashdb/README | 15 | ||||
-rwxr-xr-x[-rw-r--r--] | examples/obashdb/bashdb | 596 | ||||
-rw-r--r-- | examples/obashdb/bashdb.el | 177 | ||||
-rw-r--r-- | examples/obashdb/bashdb.fns | 237 | ||||
-rw-r--r-- | examples/obashdb/bashdb.pre | 37 |
5 files changed, 752 insertions, 310 deletions
diff --git a/examples/obashdb/README b/examples/obashdb/README index 3373f5f..2f643d1 100644 --- a/examples/obashdb/README +++ b/examples/obashdb/README @@ -1,12 +1,3 @@ -This is a modified version of the Korn Shell debugger from Bill -Rosenblatt's `Learning the Korn Shell', published by O'Reilly -and Associates (ISBN 1-56592-054-6). - -The original `kshdb' is available for anonymous FTP with the URL - -http://examples.oreilly.com/korn/ksh.tar.Z - -A revised edition is available at: - -http://examples.oreilly.com/korn2/korn2_examples.tar.gz - +This is a sample implementation of a bash debugger. It is not the same +as the project available from http://bashdb.sourceforge.net, and has been +deprecated in favor of that implementation. diff --git a/examples/obashdb/bashdb b/examples/obashdb/bashdb index 97d287d..560cb7c 100644..100755 --- a/examples/obashdb/bashdb +++ b/examples/obashdb/bashdb @@ -1,33 +1,581 @@ -# kshdb - Korn Shell Debugger main file -# adapted from 'Learning the Korn Shell' by Bill Rosenblatt (O'Reilly) -# by Cigy Cyriac (cigy@felix.tulblr.unisys.com) -# Main driver: constructs full script (with preamble) and runs it +#! /bin/bash +# bashdb - Bash shell debugger +# +# Adapted from an idea in O'Reilly's `Learning the Korn Shell' +# Copyright (C) 1993-1994 O'Reilly and Associates, Inc. +# Copyright (C) 1998, 1999, 2001 Gary V. Vaughan <gvv@techie.com>> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. -echo 'Bourne-Again Shell Debugger version 0.1' +# NOTE: +# +# This program requires bash 2.x. +# If bash 2.x is installed as "bash2", you can invoke bashdb like this: +# +# DEBUG_SHELL=/bin/bash2 /bin/bash2 bashdb script.sh -_pname=${0##*/} +# TODO: +# +# break [regexp] +# cond [break] [condition] +# tbreak [regexp|+lines] +# restart +# Variable watchpoints +# Instrument `source' and `.' files in $_potbelliedpig +# be cleverer about lines we allow breakpoints to be set on +# break [function_name] -[ $# -eq 0 ] && { - echo "${_pname}: usage: ${_pname} <script_file>" - exit 1 -} +echo 'Bash Debugger version 1.2.4' + +export _dbname=${0##*/} + +if test $# -lt 1; then + echo "$_dbname: Usage: $_dbname filename" >&2 + exit 1 +fi _guineapig=$1 -[ -r $_guineapig ] || { - echo "${_pname}: cannot read $_guineapig." >&2 - exit 1 -} +if test ! -r $1; then + echo "$_dbname: Cannot read file '$_guineapig'." >&2 + exit 1 +fi + shift -_tmpdir=/tmp -_libdir=. -_dbgfile=$_tmpdir/bashdb$$ #temp file for script being debugged +__debug=${TMPDIR-/tmp}/bashdb.$$ +sed -e '/^# bashdb - Bash shell debugger/,/^# -- DO NOT DELETE THIS LINE -- /d' "$0" > $__debug +cat $_guineapig >> $__debug +exec ${DEBUG_SHELL-bash} $__debug $_guineapig "$@" -cat $_libdir/bashdb.pre $_guineapig > $_dbgfile -if [ -f "$BASH" ]; then - exec $BASH $_dbgfile $_guineapig $_tmpdir $_libdir "$@" -else - exec bash $_dbgfile $_guineapig $_tmpdir $_libdir "$@" -fi -# end of bashdb +exit 1 + +# -- DO NOT DELETE THIS LINE -- The program depends on it + +#bashdb preamble +# $1 name of the original guinea pig script + +__debug=$0 +_guineapig=$1 +__steptrap_calls=0 + +shift + +shopt -s extglob # turn on extglob so we can parse the debugger funcs + +function _steptrap +{ + local i=0 + + _curline=$1 + + if (( ++__steptrap_calls > 1 && $_curline == 1 )); then + return + fi + + if [ -n "$_disps" ]; then + while (( $i < ${#_disps[@]} )) + do + if [ -n "${_disps[$i]}" ]; then + _msg "${_disps[$i]}: \c" + eval _msg ${_disps[$i]} + fi + let i=$i+1 + done + fi + + if (( $_trace )); then + _showline $_curline + fi + + if (( $_steps >= 0 )); then + let _steps="$_steps - 1" + fi + + if _at_linenumbp ; then + _msg "Reached breakpoint at line $_curline" + _showline $_curline + _cmdloop + elif [ -n "$_brcond" ] && eval $_brcond; then + _msg "Break condition $_brcond true at line $_curline" + _showline $_curline + _cmdloop + elif (( $_steps == 0 )); then + # Assuming a real script will have the "#! /bin/sh" at line 1, + # assume that when $_curline == 1 we are inside backticks. + if (( ! $_trace )); then + _msg "Stopped at line $_curline" + _showline $_curline + fi + _cmdloop + fi +} + +function _setbp +{ + local i f line _x + + if [ -z "$1" ]; then + _listbp + return + fi + + eval "$_seteglob" + + if [[ $1 == *(\+)[1-9]*([0-9]) ]]; then + case $1 in + +*) + # normalize argument, then double it (+2 -> +2 + 2 = 4) + _x=${1##*([!1-9])} # cut off non-numeric prefix + _x=${x%%*([!0-9])} # cut off non-numeric suffix + f=$(( $1 + $_x )) + ;; + *) + f=$(( $1 )) + ;; + esac + + # find the next valid line + line="${_lines[$f]}" + while _invalidbreakp $f + do + (( f++ )) + line="${_lines[$f]}" + done + + if (( $f != $1 )) + then + _msg "Line $1 is not a valid breakpoint" + fi + + if [ -n "${_lines[$f]}" ]; then + _linebp[$1]=$1; + _msg "Breakpoint set at line $f" + else + _msg "Breakpoints can only be set on executable lines" + fi + else + _msg "Please specify a numeric line number" + fi + + eval "$_resteglob" +} + +function _listbp +{ + local i + + if [ -n "$_linebp" ]; then + _msg "Breakpoints:" + for i in ${_linebp[*]}; do + _showline $i + done + else + _msg "No breakpoints have been set" + fi +} + +function _clearbp +{ + local i + + if [ -z "$1" ]; then + read -e -p "Delete all breakpoints? " + case $REPLY in + [yY]*) + unset _linebp[*] + _msg "All breakpoints have been cleared" + ;; + esac + return 0 + fi + + eval "$_seteglob" + + if [[ $1 == [1-9]*([0-9]) ]]; then + unset _linebp[$1] + _msg "Breakpoint cleared at line $1" + else + _msg "Please specify a numeric line number" + fi + + eval "$_resteglob" +} + +function _setbc +{ + if (( $# > 0 )); then + _brcond=$@ + _msg "Break when true: $_brcond" + else + _brcond= + _msg "Break condition cleared" + fi +} + +function _setdisp +{ + if [ -z "$1" ]; then + _listdisp + else + _disps[${#_disps[@]}]="$1" + if (( ${#_disps[@]} < 10 )) + then + _msg " ${#_disps[@]}: $1" + else + _msg "${#_disps[@]}: $1" + fi + fi +} + +function _listdisp +{ + local i=0 j + + if [ -n "$_disps" ]; then + while (( $i < ${#_disps[@]} )) + do + let j=$i+1 + if (( ${#_disps[@]} < 10 )) + then + _msg " $j: ${_disps[$i]}" + else + _msg "$j: ${_disps[$i]}" + fi + let i=$j + done + else + _msg "No displays have been set" + fi +} + +function _cleardisp +{ + if (( $# < 1 )) ; then + read -e -p "Delete all display expressions? " + case $REPLY in + [Yy]*) + unset _disps[*] + _msg "All breakpoints have been cleared" + ;; + esac + return 0 + fi + + eval "$_seteglob" + + if [[ $1 == [1-9]*([0-9]) ]]; then + unset _disps[$1] + _msg "Display $i has been cleared" + else + _listdisp + _msg "Please specify a numeric display number" + fi + + eval "$_resteglob" +} + +# usage _ftrace -u funcname [funcname...] +function _ftrace +{ + local _opt=-t _tmsg="enabled" _func + if [[ $1 == -u ]]; then + _opt=+t + _tmsg="disabled" + shift + fi + for _func; do + declare -f $_opt $_func + _msg "Tracing $_tmsg for function $_func" + done +} + +function _cmdloop +{ + local cmd args + + while read -e -p "bashdb> " cmd args; do + test -n "$cmd" && history -s "$cmd $args" # save on history list + test -n "$cmd" || { set $_lastcmd; cmd=$1; shift; args=$*; } + if [ -n "$cmd" ] + then + case $cmd in + b|br|bre|brea|break) + _setbp $args + _lastcmd="break $args" + ;; + co|con) + _msg "ambiguous command: '$cmd', condition, continue?" + ;; + cond|condi|condit|conditi|conditio|condition) + _setbc $args + _lastcmd="condition $args" + ;; + c|cont|conti|contin|continu|continue) + _lastcmd="continue" + return + ;; + d) + _msg "ambiguous command: '$cmd', delete, display?" + ;; + de|del|dele|delet|delete) + _clearbp $args + _lastcmd="delete $args" + ;; + di|dis|disp|displ|displa|display) + _setdisp $args + _lastcmd="display $args" + ;; + f|ft|ftr|ftra|ftrace) + _ftrace $args + _lastcmd="ftrace $args" + ;; + \?|h|he|hel|help) + _menu + _lastcmd="help" + ;; + l|li|lis|list) + _displayscript $args + # _lastcmd is set in the _displayscript function + ;; + p|pr|pri|prin|print) + _examine $args + _lastcmd="print $args" + ;; + q|qu|qui|quit) + exit + ;; + s|st|ste|step|n|ne|nex|next) + let _steps=${args:-1} + _lastcmd="next $args" + return + ;; + t|tr|tra|trac|trace) + _xtrace + ;; + u|un|und|undi|undis|undisp|undispl|undispla|undisplay) + _cleardisp $args + _lastcmd="undisplay $args" + ;; + !*) + eval ${cmd#!} $args + _lastcmd="$cmd $args" + ;; + *) + _msg "Invalid command: '$cmd'" + ;; + esac + fi + done +} + +function _at_linenumbp +{ + [[ -n ${_linebp[$_curline]} ]] +} + +function _invalidbreakp +{ + local line=${_lines[$1]} + + # XXX - should use shell patterns + if test -z "$line" \ + || expr "$line" : '[ \t]*#.*' > /dev/null \ + || expr "$line" : '[ \t]*;;[ \t]*$' > /dev/null \ + || expr "$line" : '[ \t]*[^)]*)[ \t]*$' > /dev/null \ + || expr "$line" : '[ \t]*;;[ \t]*#.**$' > /dev/null \ + || expr "$line" : '[ \t]*[^)]*)[ \t]*;;[ \t]*$' > /dev/null \ + || expr "$line" : '[ \t]*[^)]*)[ \t]*;;*[ \t]*#.*$' > /dev/null + then + return 0 + fi + + return 1 +} + +function _examine +{ + if [ -n "$*" ]; then + _msg "$args: \c" + eval _msg $args + else + _msg "Nothing to print" + fi +} + +function _displayscript +{ + local i j start end bp cl + + if (( $# == 1 )); then # list 5 lines on either side of $1 + if [ $1 = "%" ]; then + let start=1 + let end=${#_lines[@]} + else + let start=$1-5 + let end=$1+5 + fi + elif (( $# > 1 )); then # list between start and end + if [ $1 = "^" ]; then + let start=1 + else + let start=$1 + fi + + if [ $2 = "\$" ]; then + let end=${#_lines[@]} + else + let end=$2 + fi + else # list 5 lines on either side of current line + let start=$_curline-5 + let end=$_curline+5 + fi + + # normalize start and end + if (( $start < 1 )); then + start=1 + fi + if (( $end > ${#_lines[@]} )); then + end=${#_lines[@]} + fi + + cl=$(( $end - $start )) + if (( $cl > ${LINES-24} )); then + pager=${PAGER-more} + else + pager=cat + fi + + i=$start + ( while (( $i <= $end )); do + _showline $i + let i=$i+1 + done ) 2>&1 | $pager + + # calculate the next block of lines + start=$(( $end + 1 )) + end=$(( $start + 11 )) + if (( $end > ${#_lines[@]} )) + then + end=${#_lines[@]} + fi + + _lastcmd="list $start $end" +} + +function _xtrace +{ + let _trace="! $_trace" + if (( $_trace )); then + _msg "Execution trace on" + else + _msg "Execution trace off" + fi +} + +function _msg +{ + echo -e "$@" >&2 +} + +function _showline +{ + local i=0 bp=' ' line=$1 cl=' ' + + if [[ -n ${_linebp[$line]} ]]; then + bp='*' + fi + + if (( $_curline == $line )); then + cl=">" + fi + + if (( $line < 100 )); then + _msg "${_guineapig/*\//}:$line $bp $cl${_lines[$line]}" + elif (( $line < 10 )); then + _msg "${_guineapig/*\//}:$line $bp $cl${_lines[$line]}" + elif (( $line > 0 )); then + _msg "${_guineapig/*\//}:$line $bp $cl${_lines[$line]}" + fi +} + +function _cleanup +{ + rm -f $__debug $_potbelliedpig 2> /dev/null +} + +function _menu +{ + _msg 'bashdb commands: + break N set breakpoint at line N + break list breakpoints & break condition + condition foo set break condition to foo + condition clear break condition + delete N clear breakpoint at line N + delete clear all breakpoints + display EXP evaluate and display EXP for each debug step + display show a list of display expressions + undisplay N remove display expression N + list N M display all lines of script between N and M + list N display 5 lines of script either side of line N + list display 5 lines if script either side of current line + continue continue execution upto next breakpoint + next [N] execute [N] statements (default 1) + print expr prints the value of an expression + trace toggle execution trace on/off + ftrace [-u] func make the debugger step into function FUNC + (-u turns off tracing FUNC) + help print this menu + ! string passes string to a shell + quit quit' +} + +shopt -u extglob + +HISTFILE=~/.bashdb_history +set -o history +set +H + +# strings to save and restore the setting of `extglob' in debugger functions +# that need it +_seteglob='local __eopt=-u ; shopt -q extglob && __eopt=-s ; shopt -s extglob' +_resteglob='shopt $__eopt extglob' + +_linebp=() +let _trace=0 +let _i=1 + +# Be careful about quoted newlines +_potbelliedpig=${TMPDIR-/tmp}/${_guineapig/*\//}.$$ +sed 's,\\$,\\\\,' $_guineapig > $_potbelliedpig + +_msg "Reading source from file: $_guineapig" +while read; do + _lines[$_i]=$REPLY + let _i=$_i+1 +done < $_potbelliedpig + +trap _cleanup EXIT +# Assuming a real script will have the "#! /bin/sh" at line 1, +# don't stop at line 1 on the first run +let _steps=1 +LINENO=-1 +trap '_steptrap $LINENO' DEBUG diff --git a/examples/obashdb/bashdb.el b/examples/obashdb/bashdb.el new file mode 100644 index 0000000..40584dd --- /dev/null +++ b/examples/obashdb/bashdb.el @@ -0,0 +1,177 @@ +;;; bashdb.el --- Grand Unified Debugger mode for running bashdb +;; Copyright (C) 2000, 2001 Masatake YAMATO + +;; Author: Masatake YAMATO <jet@gyve.org> + +;; This program is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, but +;; WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program; if not, write to the Free Software Foundation, +;; Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +;; Commentary: +;; This program may run on Emacs 21.0.91 and XEmacs 21.1. +;; +;; Put +;; (autoload 'bashdb "bashdb" "Run bashdb" t nil) +;; to your .emacs. +;; M-x bashdb +;; Run bashdb (like this): bashdb target.sh +;; +;; About bashdb: +;; You can get bashdb from +;; http://www.oranda.demon.co.uk/development.html +;; +;; bashdb.el is based on perldb in gud.el in XEmacs 21.1. + +;; Revision: +;; $Revision: 1.6 $ +;; $Log: bashdb.el,v $ +;; Revision 1.6 2001/01/06 12:18:06 masata-y +;; Write note about XEmacs. +;; +;; + + +;;; Code: +(require 'gud) + +;; User customizable variable +(defcustom gud-bashdb-command-name "bashdb" + "File name for executing Bashdb." + :type 'string + :group 'gud) + +;; History of argument lists passed to bashdb. +(defvar gud-bashdb-history nil) + +(defun gud-bashdb-massage-args (file args) + (if xemacsp + (cons (file-name-nondirectory file) args) + 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. +(if xemacsp + (defvar gud-bashdb-marker-acc "")) +(defun gud-bashdb-marker-acc () + (if xemacsp + gud-bashdb-marker-acc + gud-marker-acc)) +(defun gud-bashdb-marker-acc-quote () + (if xemacsp + 'gud-bashdb-marker-acc + 'gud-marker-acc)) + +(defun gud-bashdb-marker-filter (string) + (save-match-data + (set (gud-bashdb-marker-acc-quote) + (concat (gud-bashdb-marker-acc) string)) + (let ((output "")) + ;; Process all the complete markers in this chunk. + (while (string-match "^\\([^:\n]+\\):\\([0-9]+\\)[ *]*>.*\n" + (gud-bashdb-marker-acc)) + (setq + ;; Extract the frame position from the marker. + gud-last-frame (cons + (substring (gud-bashdb-marker-acc) + (match-beginning 1) + (match-end 1)) + (string-to-int + (substring (gud-bashdb-marker-acc) + (match-beginning 2) + (match-end 2)))) + ;; 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-bashdb-marker-acc) 0 (match-beginning 0)))) + ;; Set the accumulator to the remaining text. + (set + (gud-bashdb-marker-acc-quote) (substring + (gud-bashdb-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-bashdb-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 "^\\([^:\n]+\\):\\([0-9]+\\)[ *]*>" (gud-bashdb-marker-acc)) + (progn + ;; Everything before the potential marker start can be output. + (setq output (concat output (substring (gud-bashdb-marker-acc) + 0 (match-beginning 0)))) + ;; Everything after, we save, to combine with later input. + (set (gud-bashdb-marker-acc-quote) + (substring (gud-bashdb-marker-acc) (match-beginning 0)))) + + (setq output (concat output (gud-bashdb-marker-acc))) + (set (gud-bashdb-marker-acc-quote) "")) + + output))) + +(defun gud-bashdb-find-file (f) + (find-file-noselect f)) + +;;;###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 + (if xemacsp + (list (read-from-minibuffer "Run bashdb (like this): " + (if (consp gud-bashdb-history) + (car gud-bashdb-history) + (format "%s " gud-bashdb-command-name)) + nil nil + '(gud-bashdb-history . 1))) + (list (gud-query-cmdline 'bashdb)) + )) + + (if xemacsp + (progn + (gud-overload-functions '((gud-massage-args . gud-bashdb-massage-args) + (gud-marker-filter . gud-bashdb-marker-filter) + (gud-find-file . gud-bashdb-find-file))) + (gud-common-init command-line gud-bashdb-command-name)) + (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)) + +;; Unsupported commands +;; condition foo set break condition to foo +;; condition clear break condition +;; display EXP evaluate and display EXP for each debug step +;; display show a list of display expressions +;; undisplay N remove display expression N +;; ! string passes string to a shell +;; quit quit + + (gud-def gud-break "break %l" "\C-b" "Set breakpoint at current line.") + (gud-def gud-list-break "break" "b" "List breakpoints & break condition.") + (gud-def gud-remove "delete %l" "\C-d" "Remove breakpoint at current line") + (gud-def gud-remove-all "delete" "d" "Clear all breakpoints") + (gud-def gud-cont "continue" "\C-r" "Continue with display.") + (gud-def gud-next "next" "\C-n" "Step one line (skip functions).") + (gud-def gud-print "print %e" "\C-p" "Evaluate bash expression at point.") + (gud-def gud-help "help" "h" "Show all commands.") + (gud-def gud-trace "trace" "t" "Toggle execution trace on/off") + + (setq comint-prompt-regexp "^bashdb> ") + (setq paragraph-start comint-prompt-regexp) + (run-hooks 'bashdb-mode-hook)) + +(provide 'bashdb) +;; bashdb.el ends here diff --git a/examples/obashdb/bashdb.fns b/examples/obashdb/bashdb.fns deleted file mode 100644 index ac0612c..0000000 --- a/examples/obashdb/bashdb.fns +++ /dev/null @@ -1,237 +0,0 @@ -# bashdb.fns - Bourne-Again Shell Debugger functions - -_BUFSIZ=100 - -# Here after each statement in script being debugged. -# Handle single-step and breakpoints. -_steptrap() { - let _curline=$1-1 # no. of line that just ran - let "$_curline < 1" && let _curline=1 - - let "$_curline > $_firstline+$_BUFSIZ" && _readin $_curline - - let " $_trace" && - _msg "$PS4, line $_curline: ${_lines[$(($_curline-$_firstline+1))]}" - - - # if in step mode, decrement counter - let " $_steps >= 0" && let _steps="$_steps - 1" - - # first check if line num or string brkpt. reached - if _at_linenumbp || _at_stringbp; then - _msg "Reached breakpoint at line $_curline" - _cmdloop # enter debugger - - # if not, check whether break condition exists and is true - elif [ -n "$_brcond" ] && eval $_brcond; then - _msg "Break condition $_brcond true at line $_curline" - _cmdloop # enter debugger - - # next, check if step mode and no. of steps is up - elif let "$_steps == 0"; then - _msg "Stopped at line $_curline" - _cmdloop # enter debugger - fi -} - - -# Debugger command loop. -# Here at start of debugger session, when brkpt. reached, or after single-step. -_cmdloop() { - local cmd args - -# added support for default command (last one entered) - - while read -e -p "bashdb> [$lastcmd $lastargs] " cmd args; do - if [ -z "$cmd" ]; then - cmd=$lastcmd - args=$lastargs - fi - - lastcmd="$cmd" - lastargs=$args - -# made commands to be debugger commands by default, no need for '*' prefix - - case $cmd in - bp ) _setbp $args ;; #set brkpt at line num or string - - bc ) _setbc $args ;; # set break condition - - cb ) _clearbp ;; # clear all brkpts. - - g ) return ;; # start/resume execution - - s ) let _steps=${args:-1} - return ;; # single-step N times(default 1) - - x ) _xtrace ;; # toggle execution trace - - pr ) _print $args ;; # print lines in file - - \? | h | help ) _menu ;; # print command menu - - hi ) history ;; # show command history - - q ) _cleanup; exit ;; # quit - - \! ) eval $args ;; # run shell command - - * ) _msg "Invalid command: $cmd" ; _menu ;; - esac - done -} - - -# see if next line no. is a brkpt. -_at_linenumbp() { - if [ -z "${_linebp}" ]; then - return 1 - fi - echo "${_curline}" | grep -E "(${_linebp%\|})" >/dev/null 2>&1 - return $? -} - - -# search string brkpts to see if next line in script matches. -_at_stringbp() { - local l; - - if [ -z "$_stringbp" ]; then - return 1; - fi - l=${_lines[$_curline-$_firstline+1]} - echo "${l}" | grep -E "\\*(${_stringbp%\|})\\*" >/dev/null 2>&1 - return $? -} - - -# print message to stderr -_msg() { - echo -e "$@" >&2 -} - - -# set brkpt(s) at given line numbers and/or strings -# by appending lines to brkpt file -_setbp() { - declare -i n - case "$1" in - "") _listbp ;; - [0-9]*) #number, set brkpt at that line - n=$1 - _linebp="${_linebp}$n|" - _msg "Breakpoint at line " $1 - ;; - *) #string, set brkpt at next line w/string - _stringbp="${_stringbp}$@|" - _msg "Breakpoint at next line containing $@." - ;; - esac -} - - -# list brkpts and break condition. -_listbp() { - _msg "Breakpoints at lines:" - _msg "${_linebp//\|/ }" - _msg "Breakpoints at strings:" - _msg "${_stringbp//\|/ }" - _msg "Break on condition:" - _msg "$_brcond" -} - - -# set or clear break condition -_setbc() { - if [ -n "$@" ] ; then - _brcond=$args - _msg "Break when true: $_brcond" - else - _brcond= - _msg "Break condition cleared" - fi -} - - -# clear all brkpts -_clearbp() { - _linebp= - _stringbp= - _msg "All breakpoints cleared" -} - - -# toggle execution trace feature -_xtrace() { - let _trace="! $_trace" - - _msg "Execution trace \c" - let " $_trace" && _msg "on." || _msg "off." -} - - -# print command menu -_menu() { - -# made commands to be debugger commands by default, no need for '*' prefix - - _msg 'bashdb commands: - bp N set breakpoint at line N - bp string set breakpoint at next line containing "string" - bp list breakpoints and break condition - bc string set break condition to "string" - bc clear break condition - cb clear all breakpoints - g start/resume execution - s [N] execute N statements (default 1) - x toggle execution trace on/off (default on) - pr [start|.] [cnt] print "cnt" lines from line no. "start" - ?, h, help print this menu - hi show command history - q quit - - ! cmd [args] execute command "cmd" with "args" - - default: last command (in "[ ]" at the prompt) - - Readline command line editing (emacs/vi mode) is available' -} - - -# erase temp files before exiting -_cleanup() { - rm $_dbgfile 2>/dev/null -} - - -# read $_BUFSIZ lines from $_guineapig into _lines array, starting from line $1 -# save number of first line read in _firstline -_readin() { - declare -i _i=1 - let _firstline=$1 - - SEDCMD="$_firstline,$(($_firstline+$_BUFSIZ))p" - - sed -n "$SEDCMD" $_guineapig > /tmp/_script.$$ - while read -r _lines[$_i]; do - _i=_i+1 - done < /tmp/_script.$$ - rm -f /tmp/_script.$$ 2>/dev/null -} - -_print() { - typeset _start _cnt - - if [ -z "$1" ] || [ "$1" = . ]; then - _start=$_curline - else - _start=$1 - fi - - _cnt=${2:-9} - - SEDCMD="$_start,$(($_start+$_cnt))p" - - pr -tn $_guineapig | sed -n "$SEDCMD" -} diff --git a/examples/obashdb/bashdb.pre b/examples/obashdb/bashdb.pre deleted file mode 100644 index c9cdb72..0000000 --- a/examples/obashdb/bashdb.pre +++ /dev/null @@ -1,37 +0,0 @@ -# bashdb.pre - Bourne-Again Shell Debugger preamble file -# prepended to script being ddebugged -#arguments: -# $1 = name of original guineapig script -# $2 = dir where temp files are stored -# $3 = dir where bashdb.pre and bashdb.fns are stored - -# separate history file for bashdb -HISTFILE=~/.bashdb_history -set -o history -set +H - -# prompt for trace line -PS4="${1}" - -_dbgfile=$0 -_guineapig=$1 -_tmpdir=$2 -_libdir=$3 -shift 3 #move user's args into place - -. $_libdir/bashdb.fns #read in the debugger functions - -_linebp= -_stringbp= -let _trace=1 #init execution trace flag to on - -#read guineapig file into _lines array -_readin 1 - -trap _cleanup EXIT #erase files before exiting - -let _steps=1 #no. of statements to run after setting trap -#set LINENO, gets incremented to 1 -LINENO=0 -trap '_steptrap $LINENO' DEBUG -: |