From: R. B. <ro...@pa...> - 2006-12-26 18:08:17
|
Since bashdb-3.1-0.06 the bash debugger has had the ability to do line tracing sort of like set -x, but adding a little more information, namely position information and BASH_LEVEL information. Recently I added string expansion of before printing lines. This is controlled by the debugger command "set linetrace expand", and from the bashdb script using option -Y (or long-option --vtrace if you have a working getopt). Here's a small example using a recursive factorial program. (Sure there's a simpler, non-recursive way to write this - I just wanted a small example.) Here's the program #!/bin/bash fact() { local -i n=$1 ((n==0)) && echo 1 && return ((nm1=n-1)) ((result=n*`fact $nm1`)) echo $result } typeset -i n=${1:-4} echo fact $n is: `fact $n` Running with line tracing and variable substitution, you get: bashdb -B -Y fact.sh 2 Bourne-Again Shell Debugger, release bash-3.1-0.08cvs Copyright 2002, 2003, 2004, 2006 Rocky Bernstein This is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. (bashdb:277): level 1, subshell 0, depth -1: . $_source_file . fact.sh (fact.sh:11): level 1, subshell 0, depth 0: typeset -i n=${1:-4} typeset -i n=2 (fact.sh:12): level 1, subshell 0, depth 0: echo fact $n is: `fact $n` echo fact 2 is: 2 (fact.sh:12): level 1, subshell 1, depth 0: echo fact $n is: `fact $n` echo fact 2 is: 2 fact $n (fact.sh:3): level 1, subshell 1, depth 1: fact() { fact() { (fact.sh:4): level 1, subshell 1, depth 1: local -i n=$1 local -i n=2 (fact.sh:5): level 1, subshell 1, depth 1: ((n==0)) && echo 1 && return ((n==0)) && echo 1 && return (fact.sh:6): level 1, subshell 1, depth 1: ((nm1=n-1)) ((nm1=n-1)) (fact.sh:7): level 1, subshell 1, depth 1: ((result=n*`fact $nm1`)) ((result=n*1)) (fact.sh:7): level 1, subshell 2, depth 1: ((result=n*`fact $nm1`)) ((result=n*1)) fact $nm1 (fact.sh:3): level 1, subshell 2, depth 2: fact() { fact() { (fact.sh:4): level 1, subshell 2, depth 2: local -i n=$1 local -i n=1 (fact.sh:5): level 1, subshell 2, depth 2: ((n==0)) && echo 1 && return ((n==0)) && echo 1 && return (fact.sh:6): level 1, subshell 2, depth 2: ((nm1=n-1)) ((nm1=n-1)) (fact.sh:7): level 1, subshell 2, depth 2: ((result=n*`fact $nm1`)) ((result=n*1)) (fact.sh:7): level 1, subshell 3, depth 2: ((result=n*`fact $nm1`)) ((result=n*1)) fact $nm1 (fact.sh:3): level 1, subshell 3, depth 3: fact() { fact() { (fact.sh:4): level 1, subshell 3, depth 3: local -i n=$1 local -i n=0 (fact.sh:5): level 1, subshell 3, depth 3: ((n==0)) && echo 1 && return ((n==0)) && echo 1 && return (fact.sh:5): level 1, subshell 3, depth 3: ((n==0)) && echo 1 && return ((n==0)) && echo 1 && return echo 1 (fact.sh:5): level 1, subshell 3, depth 3: ((n==0)) && echo 1 && return ((n==0)) && echo 1 && return return (fact.sh:8): level 1, subshell 2, depth 2: echo $result echo 1 (fact.sh:8): level 1, subshell 1, depth 1: echo $result echo 2 fact 2 is: 2 (bashdb:290): level 1, subshell 0, depth -1: Using -V (long option --trace), omits the substitution line getting printed out. That is this would start out instead: (bashdb:277): level 1, subshell 0, depth -1: . $_source_file (fact.sh:11): level 1, subshell 0, depth 0: typeset -i n=${1:-4} (fact.sh:12): level 1, subshell 0, depth 0: echo fact $n is: `fact $n` That very first line (bashdb:277) I'm not happy about but I don't know how to remove it for now - and it *does* reflect what's really going on. Another thing to note is that the program really doesn't have deep knowledge about what is a variable and what isn't. It is just asks bash to expanding the source line as a string and prints the result So in a statement like ((nm1-n-1)) nothing gets substituted. Similarly it's possible to have a source line like echo "Now is \ the time" And what will happen here is invariable the debugger will see an open/close quote (or a back tick) without the matching one. What happens here is that the string substitute fails and nothing gets printed. Still, even with these caveats, I've found this addition useful. Things are not cast in concrete right now, so if folks want to try it out and give feedback, now would be a good time. Thanks. |