1 # bashdb.fns - Bourne-Again Shell Debugger functions
5 # Here after each statement in script being debugged.
6 # Handle single-step and breakpoints.
8 let _curline=$1-1 # no. of line that just ran
9 let "$_curline < 1" && let _curline=1
11 let "$_curline > $_firstline+$_BUFSIZ" && _readin $_curline
14 _msg "$PS4, line $_curline: ${_lines[$(($_curline-$_firstline+1))]}"
16 # if in step mode, decrement counter
17 let " $_steps >= 0" && let _steps="$_steps - 1"
19 # first check if line num or string brkpt. reached
20 if _at_linenumbp || _at_stringbp; then
21 _msg "Reached breakpoint at line $_curline"
22 _cmdloop # enter debugger
24 # if not, check whether break condition exists and is true
25 elif [ -n "$_brcond" ] && eval $_brcond; then
26 _msg "Break condition $_brcond true at line $_curline"
27 _cmdloop # enter debugger
29 # next, check if step mode and no. of steps is up
30 elif let "$_steps == 0"; then
31 _msg "Stopped at line $_curline"
32 _cmdloop # enter debugger
37 # Debugger command loop.
38 # Here at start of debugger session, when brkpt. reached, or after single-step.
42 # added support for default command (last one entered)
44 while read -e -p "bashdb> [$lastcmd $lastargs] " cmd args; do
45 if [ -z "$cmd" ]; then
53 # made commands to be debugger commands by default, no need for '*' prefix
56 bp ) _setbp $args ;; #set brkpt at line num or string
58 bc ) _setbc $args ;; # set break condition
60 cb ) _clearbp ;; # clear all brkpts.
62 g ) return ;; # start/resume execution
64 s ) let _steps=${args:-1}
65 return ;; # single-step N times(default 1)
67 x ) _xtrace ;; # toggle execution trace
69 pr ) _print $args ;; # print lines in file
71 \? | h | help ) _menu ;; # print command menu
73 hi ) history ;; # show command history
75 q ) _cleanup; exit ;; # quit
77 \! ) eval $args ;; # run shell command
79 * ) _msg "
\aInvalid command: $cmd" ; _menu ;;
85 # see if next line no. is a brkpt.
87 if [ -z "${_linebp}" ]; then
90 echo "${curline}" | egrep -s "(${linebp%\|})" >/dev/null 2>&1
95 # search string brkpts to see if next line in script matches.
98 if [ -z "$_stringbp" ]; then
101 l=${_lines[$_curline-$_firstline+1]}
102 echo "${l} | egrep -s "*(${stringbp%\|})*" >/dev/null 2>&1
107 # print message to stderr
113 # set brkpt(s) at given line numbers and/or strings
114 # by appending lines to brkpt file
119 [0-9]*) #number, set brkpt at that line
121 _linebp="${_linebp}$n|"
122 _msg "Breakpoint at line " $1
124 *) #string, set brkpt at next line w/string
125 _stringbp="${_stringbp}$@|"
126 _msg "Breakpoint at next line containing $@."
132 # list brkpts and break condition.
134 _msg "Breakpoints at lines:"
135 _msg "$(echo $_linebp | tr '|' ' ')"
136 _msg "Breakpoints at strings:"
137 _msg "$(echo $_stringbp | tr '|' ' ')"
138 _msg "Break on condition:"
143 # set or clear break condition
145 if [ -n "$@" ] ; then
147 _msg "Break when true: $_brcond"
150 _msg "Break condition cleared"
159 _msg "All breakpoints cleared"
163 # toggle execution trace feature
165 let _trace="! $_trace"
167 _msg "Execution trace \c"
168 let " $_trace" && _msg "on." || _msg "off."
175 # made commands to be debugger commands by default, no need for '*' prefix
177 _msg 'bashdb commands:
178 bp N set breakpoint at line N
179 bp string set breakpoint at next line containing "string"
180 bp list breakpoints and break condition
181 bc string set break condition to "string"
182 bc clear break condition
183 cb clear all breakpoints
184 g start/resume execution
185 s [N] execute N statements (default 1)
186 x toggle execution trace on/off (default on)
187 pr [start|.] [cnt] print "cnt" lines from line no. "start"
188 ?, h, help print this menu
189 hi show command history
192 ! cmd [args] execute command "cmd" with "args"
194 default: last command (in "[ ]" at the prompt)
196 Readline command line editing (emacs/vi mode) is available'
200 # erase temp files before exiting
202 rm $_dbgfile 2>/dev/null
206 # read $_BUFSIZ lines from $_guineapig into _lines array, starting from line $1
207 # save number of first line read in _firstline
212 SEDCMD="$_firstline,$(($_firstline+$_BUFSIZ))p"
214 sed -n "$SEDCMD" $_guineapig > /tmp/_script.$$
215 while read -r _lines[$_i]; do
217 done < /tmp/_script.$$
218 rm -f /tmp/_script.$$ 2>/dev/null
224 if [ -z "$1" ] || [ "$1" = . ]; then
232 SEDCMD="$_start,$(($_start+$_cnt))p"
234 pr -tn $_guineapig | sed -n "$SEDCMD"