| 1 | ## compare_shells: bash
|
| 2 |
|
| 3 | # Test call stack introspection. There are a bunch of special variables
|
| 4 | # defined here:
|
| 5 | #
|
| 6 | # https://www.gnu.org/software/bash/manual/html_node/Bash-Variables.html
|
| 7 | #
|
| 8 | # - The shell function ${FUNCNAME[$i]} is defined in the file
|
| 9 | # ${BASH_SOURCE[$i]} and called from ${BASH_SOURCE[$i+1]}
|
| 10 | #
|
| 11 | # - ${BASH_LINENO[$i]} is the line number in the source file
|
| 12 | # (${BASH_SOURCE[$i+1]}) where ${FUNCNAME[$i]} was called (or
|
| 13 | # ${BASH_LINENO[$i-1]} if referenced within another shell function).
|
| 14 | #
|
| 15 | # - For instance, ${FUNCNAME[$i]} was called from the file
|
| 16 | # ${BASH_SOURCE[$i+1]} at line number ${BASH_LINENO[$i]}. The caller builtin
|
| 17 | # displays the current call stack using this information.
|
| 18 | #
|
| 19 | # So ${BASH_SOURCE[@]} doesn't line up with ${BASH_LINENO}. But
|
| 20 | # ${BASH_SOURCE[0]} does line up with $LINENO!
|
| 21 | #
|
| 22 | # Geez.
|
| 23 | #
|
| 24 | # In other words, BASH_SOURCE is about the DEFINITION. While FUNCNAME and
|
| 25 | # BASH_LINENO are about the CALL.
|
| 26 |
|
| 27 |
|
| 28 | #### ${FUNCNAME[@]} array
|
| 29 | g() {
|
| 30 | argv.py "${FUNCNAME[@]}"
|
| 31 | }
|
| 32 | f() {
|
| 33 | argv.py "${FUNCNAME[@]}"
|
| 34 | g
|
| 35 | argv.py "${FUNCNAME[@]}"
|
| 36 | }
|
| 37 | f
|
| 38 | ## STDOUT:
|
| 39 | ['f']
|
| 40 | ['g', 'f']
|
| 41 | ['f']
|
| 42 | ## END
|
| 43 |
|
| 44 | #### FUNCNAME with source (scalar or array)
|
| 45 | cd $REPO_ROOT
|
| 46 |
|
| 47 | # Comments on bash quirk:
|
| 48 | # https://github.com/oilshell/oil/pull/656#issuecomment-599162211
|
| 49 |
|
| 50 | f() {
|
| 51 | . spec/testdata/echo-funcname.sh
|
| 52 | }
|
| 53 | g() {
|
| 54 | f
|
| 55 | }
|
| 56 |
|
| 57 | g
|
| 58 | echo -----
|
| 59 |
|
| 60 | . spec/testdata/echo-funcname.sh
|
| 61 | echo -----
|
| 62 |
|
| 63 | argv.py "${FUNCNAME[@]}"
|
| 64 |
|
| 65 | # Show bash inconsistency. FUNCNAME doesn't behave like a normal array.
|
| 66 | case $SH in
|
| 67 | (bash)
|
| 68 | echo -----
|
| 69 | a=('A')
|
| 70 | argv.py ' @' "${a[@]}"
|
| 71 | argv.py ' 0' "${a[0]}"
|
| 72 | argv.py '${}' "${a}"
|
| 73 | argv.py ' $' "$a"
|
| 74 | ;;
|
| 75 | esac
|
| 76 |
|
| 77 | ## STDOUT:
|
| 78 | [' @', 'source', 'f', 'g']
|
| 79 | [' 0', 'source']
|
| 80 | ['${}', 'source']
|
| 81 | [' $', 'source']
|
| 82 | -----
|
| 83 | [' @', 'source']
|
| 84 | [' 0', 'source']
|
| 85 | ['${}', 'source']
|
| 86 | [' $', 'source']
|
| 87 | -----
|
| 88 | []
|
| 89 | ## END
|
| 90 | ## BUG bash STDOUT:
|
| 91 | [' @', 'source', 'f', 'g']
|
| 92 | [' 0', 'source']
|
| 93 | ['${}', 'source']
|
| 94 | [' $', 'source']
|
| 95 | -----
|
| 96 | [' @']
|
| 97 | [' 0', '']
|
| 98 | ['${}', '']
|
| 99 | [' $', '']
|
| 100 | -----
|
| 101 | []
|
| 102 | -----
|
| 103 | [' @', 'A']
|
| 104 | [' 0', 'A']
|
| 105 | ['${}', 'A']
|
| 106 | [' $', 'A']
|
| 107 | ## END
|
| 108 |
|
| 109 |
|
| 110 | #### BASH_SOURCE and BASH_LINENO scalar or array (e.g. for virtualenv)
|
| 111 | cd $REPO_ROOT
|
| 112 |
|
| 113 | # https://github.com/pypa/virtualenv/blob/master/virtualenv_embedded/activate.sh
|
| 114 | # https://github.com/akinomyoga/ble.sh/blob/6f6c2e5/ble.pp#L374
|
| 115 |
|
| 116 | argv.py "$BASH_SOURCE" # SimpleVarSub
|
| 117 | argv.py "${BASH_SOURCE}" # BracedVarSub
|
| 118 | argv.py "$BASH_LINENO" # SimpleVarSub
|
| 119 | argv.py "${BASH_LINENO}" # BracedVarSub
|
| 120 | argv.py "$FUNCNAME" # SimpleVarSub
|
| 121 | argv.py "${FUNCNAME}" # BracedVarSub
|
| 122 | echo __
|
| 123 | source spec/testdata/bash-source-string.sh
|
| 124 |
|
| 125 | ## STDOUT:
|
| 126 | ['']
|
| 127 | ['']
|
| 128 | ['']
|
| 129 | ['']
|
| 130 | ['']
|
| 131 | ['']
|
| 132 | __
|
| 133 | ['spec/testdata/bash-source-string.sh']
|
| 134 | ['spec/testdata/bash-source-string.sh']
|
| 135 | ['11']
|
| 136 | ['11']
|
| 137 | ____
|
| 138 | ['spec/testdata/bash-source-string2.sh']
|
| 139 | ['spec/testdata/bash-source-string2.sh']
|
| 140 | ['11']
|
| 141 | ['11']
|
| 142 | ## END
|
| 143 |
|
| 144 |
|
| 145 | #### ${FUNCNAME} with prefix/suffix operators
|
| 146 |
|
| 147 | check() {
|
| 148 | argv.py "${#FUNCNAME}"
|
| 149 | argv.py "${FUNCNAME::1}"
|
| 150 | argv.py "${FUNCNAME:1}"
|
| 151 | }
|
| 152 | check
|
| 153 | ## STDOUT:
|
| 154 | ['5']
|
| 155 | ['c']
|
| 156 | ['heck']
|
| 157 | ## END
|
| 158 |
|
| 159 | #### operators on FUNCNAME
|
| 160 | check() {
|
| 161 | argv.py "${FUNCNAME}"
|
| 162 | argv.py "${#FUNCNAME}"
|
| 163 | argv.py "${FUNCNAME::1}"
|
| 164 | argv.py "${FUNCNAME:1}"
|
| 165 | }
|
| 166 | check
|
| 167 | ## status: 0
|
| 168 | ## STDOUT:
|
| 169 | ['check']
|
| 170 | ['5']
|
| 171 | ['c']
|
| 172 | ['heck']
|
| 173 | ## END
|
| 174 |
|
| 175 | #### ${FUNCNAME} and "set -u" (OSH regression)
|
| 176 | set -u
|
| 177 | argv.py "$FUNCNAME"
|
| 178 | ## status: 1
|
| 179 | ## stdout-json: ""
|
| 180 |
|
| 181 | #### $((BASH_LINENO)) (scalar form in arith)
|
| 182 | check() {
|
| 183 | echo $((BASH_LINENO))
|
| 184 | }
|
| 185 | check
|
| 186 | ## stdout: 4
|
| 187 |
|
| 188 | #### ${BASH_SOURCE[@]} with source and function name
|
| 189 | cd $REPO_ROOT
|
| 190 |
|
| 191 | argv.py "${BASH_SOURCE[@]}"
|
| 192 | source spec/testdata/bash-source-simple.sh
|
| 193 | f
|
| 194 | ## STDOUT:
|
| 195 | []
|
| 196 | ['spec/testdata/bash-source-simple.sh']
|
| 197 | ['spec/testdata/bash-source-simple.sh']
|
| 198 | ## END
|
| 199 |
|
| 200 | #### ${BASH_SOURCE[@]} with line numbers
|
| 201 | cd $REPO_ROOT
|
| 202 |
|
| 203 | $SH spec/testdata/bash-source.sh
|
| 204 | ## STDOUT:
|
| 205 | ['begin F funcs', 'f', 'main']
|
| 206 | ['begin F files', 'spec/testdata/bash-source.sh', 'spec/testdata/bash-source.sh']
|
| 207 | ['begin F lines', '21', '0']
|
| 208 | ['G funcs', 'g', 'f', 'main']
|
| 209 | ['G files', 'spec/testdata/bash-source-2.sh', 'spec/testdata/bash-source.sh', 'spec/testdata/bash-source.sh']
|
| 210 | ['G lines', '15', '21', '0']
|
| 211 | ['end F funcs', 'f', 'main']
|
| 212 | ['end F', 'spec/testdata/bash-source.sh', 'spec/testdata/bash-source.sh']
|
| 213 | ['end F lines', '21', '0']
|
| 214 | ## END
|
| 215 |
|
| 216 | #### ${BASH_LINENO[@]} is a stack of line numbers for function calls
|
| 217 | # note: it's CALLS, not DEFINITIONS.
|
| 218 | g() {
|
| 219 | argv.py G "${BASH_LINENO[@]}"
|
| 220 | }
|
| 221 | f() {
|
| 222 | argv.py 'begin F' "${BASH_LINENO[@]}"
|
| 223 | g # line 6
|
| 224 | argv.py 'end F' "${BASH_LINENO[@]}"
|
| 225 | }
|
| 226 | argv.py ${BASH_LINENO[@]}
|
| 227 | f # line 9
|
| 228 | ## STDOUT:
|
| 229 | []
|
| 230 | ['begin F', '10']
|
| 231 | ['G', '6', '10']
|
| 232 | ['end F', '10']
|
| 233 | ## END
|
| 234 |
|
| 235 | #### Locations with temp frame
|
| 236 |
|
| 237 | cd $REPO_ROOT
|
| 238 |
|
| 239 | $SH spec/testdata/bash-source-pushtemp.sh
|
| 240 |
|
| 241 | ## STDOUT:
|
| 242 | F
|
| 243 | G
|
| 244 | STACK:spec/testdata/bash-source-pushtemp.sh:g:3
|
| 245 | STACK:spec/testdata/bash-source-pushtemp.sh:f:19
|
| 246 | STACK:spec/testdata/bash-source-pushtemp.sh:main:0
|
| 247 | ## END
|
| 248 |
|
| 249 | #### Locations when sourcing
|
| 250 |
|
| 251 | cd $REPO_ROOT
|
| 252 |
|
| 253 | # like above test case, but we source
|
| 254 |
|
| 255 | # bash location doesn't make sense:
|
| 256 | # - It says 'source' happens at line 1 of bash-source-pushtemp. Well I think
|
| 257 | # - It really happens at line 2 of '-c' ! I guess that's to line up
|
| 258 | # with the 'main' frame
|
| 259 |
|
| 260 | $SH -c 'true;
|
| 261 | source spec/testdata/bash-source-pushtemp.sh'
|
| 262 |
|
| 263 | ## STDOUT:
|
| 264 | F
|
| 265 | G
|
| 266 | STACK:spec/testdata/bash-source-pushtemp.sh:g:3
|
| 267 | STACK:spec/testdata/bash-source-pushtemp.sh:f:19
|
| 268 | STACK:spec/testdata/bash-source-pushtemp.sh:source:2
|
| 269 | ## END
|
| 270 |
|
| 271 | #### Sourcing inside function grows the debug stack
|
| 272 |
|
| 273 | cd $REPO_ROOT
|
| 274 |
|
| 275 | $SH spec/testdata/bash-source-source.sh
|
| 276 |
|
| 277 | ## STDOUT:
|
| 278 | F
|
| 279 | G
|
| 280 | STACK:spec/testdata/bash-source-pushtemp.sh:g:3
|
| 281 | STACK:spec/testdata/bash-source-pushtemp.sh:f:19
|
| 282 | STACK:spec/testdata/bash-source-pushtemp.sh:source:2
|
| 283 | STACK:spec/testdata/bash-source-source.sh:mainfunc:6
|
| 284 | STACK:spec/testdata/bash-source-source.sh:main2:10
|
| 285 | STACK:spec/testdata/bash-source-source.sh:main1:13
|
| 286 | STACK:spec/testdata/bash-source-source.sh:main:0
|
| 287 | ## END
|