Permalink
Please sign in to comment.
Browse files
Figuring out call stack introspection in bash via spec tests.
It appears the variables that collectively store the call stack don't
line up! ${BASH_SOURCE[i]} and ${BASH_LINENO[i]} are out of whack!
But the current position is ${BASH_SOURCE[0]} and $LINENO. Sigh.
This was good to test out, but I don't think Oil will compatible with
bash (and hence debuggers like bashdb).
Also:
- Test the values of $$ and $BASHPID in command subs too.- Loading branch information...
Showing
with
142 additions
and 16 deletions.
- +3 −3 core/alloc.py
- +1 −1 core/cmd_exec.py
- +74 −4 spec/introspect.test.sh
- +36 −8 spec/special-vars.test.sh
- +7 −0 spec/testdata/bash-source-2.sh
- +21 −0 spec/testdata/bash-source.sh
| @@ -1,16 +1,86 @@ | ||
| #!/usr/bin/env bash | ||
| # | ||
| # TODO: | ||
| # BASH_SOURCE, BASH_LINENO, caller builtin | ||
| # Test call stack introspection. There are a bunch of special variables | ||
| # defined here: | ||
| # | ||
| # https://www.gnu.org/software/bash/manual/html_node/Bash-Variables.html | ||
| # | ||
| # - The shell function ${FUNCNAME[$i]} is defined in the file | ||
| # ${BASH_SOURCE[$i]} and called from ${BASH_SOURCE[$i+1]} | ||
| # | ||
| # - ${BASH_LINENO[$i]} is the line number in the source file | ||
| # (${BASH_SOURCE[$i+1]}) where ${FUNCNAME[$i]} was called (or | ||
| # ${BASH_LINENO[$i-1]} if referenced within another shell function). | ||
| # | ||
| # - For instance, ${FUNCNAME[$i]} was called from the file | ||
| # ${BASH_SOURCE[$i+1]} at line number ${BASH_LINENO[$i]}. The caller builtin | ||
| # displays the current call stack using this information. | ||
| # | ||
| # So ${BASH_SOURCE[@]} doesn't line up with ${BASH_LINENO}. But | ||
| # ${BASH_SOURCE[0]} does line up with $LINENO! | ||
| # | ||
| # Geez. | ||
| ### ${FUNCNAME[@]} array | ||
| g() { | ||
| argv.py "${FUNCNAME[@]}" | ||
| } | ||
| f() { | ||
| argv.py "${FUNCNAME[@]}" | ||
| g | ||
| argv.py "${FUNCNAME[@]}" | ||
| } | ||
| f | ||
| ## STDOUT: | ||
| ['f'] | ||
| ['g', 'f'] | ||
| ['f'] | ||
| ## END | ||
| ### ${BASH_SOURCE[@]} is a stack of source files for function calls | ||
| $SH spec/testdata/bash-source.sh | ||
| ## STDOUT: | ||
| ['begin F funcs', 'f', 'main'] | ||
| ['begin F files', 'spec/testdata/bash-source.sh', 'spec/testdata/bash-source.sh'] | ||
| ['begin F lines', '21', '0'] | ||
| ['G funcs', 'g', 'f', 'main'] | ||
| ['G files', 'spec/testdata/bash-source-2.sh', 'spec/testdata/bash-source.sh', 'spec/testdata/bash-source.sh'] | ||
| ['G lines', '15', '21', '0'] | ||
| ['end F funcs', 'f', 'main'] | ||
| ['end F', 'spec/testdata/bash-source.sh', 'spec/testdata/bash-source.sh'] | ||
| ['end F lines', '21', '0'] | ||
| ## END | ||
| ### ${BASH_LINENO[@]} is a stack of line numbers for function calls | ||
| # note: it's CALLS, not DEFINITIONS. | ||
| g() { | ||
| argv.py "${FUNCNAME[@]}" | ||
| argv.py G "${BASH_LINENO[@]}" | ||
| } | ||
| f() { | ||
| argv.py 'begin F' "${BASH_LINENO[@]}" | ||
| g # line 6 | ||
| argv.py 'end F' "${BASH_LINENO[@]}" | ||
| } | ||
| f # line 9 | ||
| ## STDOUT: | ||
| ['begin F', '9'] | ||
| ['G', '6', '9'] | ||
| ['end F', '9'] | ||
| ## END | ||
| ### $LINENO is the current line, not line of function call | ||
| g() { | ||
| argv.py $LINENO # line 2 | ||
| } | ||
| f() { | ||
| argv.py $LINENO # line 5 | ||
| g | ||
| argv.py $LINENO # line 7 | ||
| } | ||
| f | ||
| # stdout-json: "['f']\n['g', 'f']\n['f']\n" | ||
| ## STDOUT: | ||
| ['5'] | ||
| ['2'] | ||
| ['7'] | ||
| ## END |
| @@ -0,0 +1,7 @@ | ||
| #!/bin/bash | ||
| g() { | ||
| argv 'G funcs' "${FUNCNAME[@]}" | ||
| argv 'G files' "${BASH_SOURCE[@]}" | ||
| argv 'G lines' "${BASH_LINENO[@]}" | ||
| } |
| @@ -0,0 +1,21 @@ | ||
| #!/usr/bin/env bash | ||
| # | ||
| # For spec/introspect.test.sh. | ||
| source spec/testdata/bash-source-2.sh | ||
| argv() { | ||
| spec/bin/argv.py "$@" | ||
| } | ||
| f() { | ||
| argv 'begin F funcs' "${FUNCNAME[@]}" | ||
| argv 'begin F files' "${BASH_SOURCE[@]}" | ||
| argv 'begin F lines' "${BASH_LINENO[@]}" | ||
| g | ||
| argv 'end F funcs' "${FUNCNAME[@]}" | ||
| argv 'end F' "${BASH_SOURCE[@]}" | ||
| argv 'end F lines' "${BASH_LINENO[@]}" | ||
| } | ||
| f # call a function it defines |
0 comments on commit
cf95049