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