9a9aa495163ddd6a5d1cffb6cf2458e8aeaf991e
[platform/upstream/bash.git] / examples / bashdb / bashdb.fns
1 # bashdb.fns - Bourne-Again Shell Debugger functions
2
3 _BUFSIZ=100
4
5 # Here after each statement in script being debugged.
6 # Handle single-step and breakpoints.
7 _steptrap() {
8         let _curline=$1-1               # no. of line that just ran
9         let "$_curline < 1" && let _curline=1
10
11         let "$_curline > $_firstline+$_BUFSIZ" && _readin $_curline
12
13         let " $_trace" &&
14                 _msg "$PS4, line $_curline: ${_lines[$(($_curline-$_firstline+1))]}"
15
16         # if in step mode, decrement counter
17         let " $_steps >= 0" && let _steps="$_steps - 1"
18
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
23
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
28
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
33         fi
34 }
35
36
37 # Debugger command loop.
38 # Here at start of debugger session, when brkpt. reached, or after single-step.
39 _cmdloop() {
40         local cmd args
41
42 # added support for default command (last one entered)
43
44         while read -e -p "bashdb> [$lastcmd $lastargs] " cmd args; do
45                 if [ -z "$cmd" ]; then
46                         cmd=$lastcmd
47                         args=$lastargs 
48                 fi
49
50                 lastcmd="$cmd"
51                 lastargs=$args
52
53 # made commands to be debugger commands by default, no need for '*' prefix
54
55                 case $cmd in
56                 bp ) _setbp $args ;;    #set brkpt at line num or string
57
58                 bc ) _setbc $args ;;    # set break condition
59
60                 cb ) _clearbp ;;        # clear all brkpts.
61
62                 g ) return ;;           # start/resume execution
63
64                 s ) let _steps=${args:-1} 
65                     return ;;           # single-step N times(default 1)
66
67                 x ) _xtrace ;;  # toggle execution trace
68
69                 pr ) _print $args ;;    # print lines in file
70
71                 \? | h | help ) _menu ;; # print command menu
72
73                 hi ) history ;;         # show command history
74
75                 q ) _cleanup; exit ;;           # quit
76
77                 \! ) eval $args ;;      # run shell command
78
79                 * ) _msg "\aInvalid command: $cmd" ; _menu ;;
80                 esac
81         done
82 }
83
84
85 # see if next line no. is a brkpt.
86 _at_linenumbp() {
87         if [ -z "${_linebp}" ]; then
88                 return 1
89         fi
90         echo "${curline}" | egrep -s "(${linebp%\|})" >/dev/null 2>&1
91         return $?
92 }
93
94
95 # search string brkpts to see if next line in script matches.
96 _at_stringbp() {
97         local l;
98         if [ -z "$_stringbp" ]; then
99                 return 1;
100         fi
101         l=${_lines[$_curline-$_firstline+1]}
102         echo "${l} | egrep -s "*(${stringbp%\|})*" >/dev/null 2>&1
103         return $?
104 }
105
106
107 # print message to stderr
108 _msg() {
109         echo -e "$@" >&2
110 }
111
112
113 # set brkpt(s) at given line numbers and/or strings
114 # by appending lines to brkpt file
115 _setbp() {
116         declare -i n
117         case "$1" in
118         "")     _listbp ;;
119         [0-9]*) #number, set brkpt at that line
120                 n=$1
121                 _linebp="${_linebp}$n|"
122                 _msg "Breakpoint at line " $1
123                 ;;
124         *)      #string, set brkpt at next line w/string
125                 _stringbp="${_stringbp}$@|"
126                 _msg "Breakpoint at next line containing $@."
127                 ;;
128         esac
129 }
130
131
132 # list brkpts and break condition.
133 _listbp() {
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:"
139         _msg "$_brcond"
140 }
141
142
143 # set or clear break condition
144 _setbc() {
145         if [ -n "$@" ] ; then
146                 _brcond=$args
147                 _msg "Break when true: $_brcond"
148         else
149                 _brcond=
150                 _msg "Break condition cleared"
151         fi
152 }
153
154
155 # clear all brkpts
156 _clearbp() {
157         _linebp=
158         _stringbp=
159         _msg "All breakpoints cleared"
160 }
161
162
163 # toggle execution trace feature
164 _xtrace() {
165         let _trace="! $_trace"
166
167         _msg "Execution trace \c"
168         let " $_trace" && _msg "on." || _msg "off."
169 }
170
171
172 # print command menu
173 _menu() {
174
175 # made commands to be debugger commands by default, no need for '*' prefix
176
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    
190         q                       quit
191
192         ! cmd [args]            execute command "cmd" with "args"
193
194         default:                last command (in "[ ]" at the prompt)
195
196         Readline command line editing (emacs/vi mode) is available'
197 }
198
199
200 # erase temp files before exiting
201 _cleanup() {
202         rm $_dbgfile 2>/dev/null
203 }
204
205
206 # read $_BUFSIZ lines from $_guineapig into _lines array, starting from line $1
207 # save number of first line read in _firstline
208 _readin() {
209         declare -i _i=1                 
210         let _firstline=$1
211
212         SEDCMD="$_firstline,$(($_firstline+$_BUFSIZ))p"
213
214         sed -n "$SEDCMD" $_guineapig > /tmp/_script.$$
215         while read -r _lines[$_i]; do
216                 _i=_i+1
217         done  < /tmp/_script.$$
218         rm -f /tmp/_script.$$ 2>/dev/null
219 }
220
221 _print() {
222         typeset _start _cnt
223
224         if [ -z "$1" ] || [ "$1" = . ]; then
225                 _start=$_curline
226         else
227                 _start=$1
228         fi
229
230         _cnt=${2:-9}
231
232         SEDCMD="$_start,$(($_start+$_cnt))p"
233
234         pr -tn $_guineapig | sed -n "$SEDCMD"
235 }