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 |
|
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 |
|
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 |
[' @', 'source']
|
97 |
[' 0', 'source']
|
98 |
['${}', '']
|
99 |
[' $', '']
|
100 |
-----
|
101 |
[]
|
102 |
-----
|
103 |
[' @', 'A']
|
104 |
[' 0', 'A']
|
105 |
['${}', 'A']
|
106 |
[' $', 'A']
|
107 |
## END
|
108 |
|
109 |
|
110 |
|
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 |
|
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 |
|
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 |
|
176 |
set -u
|
177 |
argv.py "$FUNCNAME"
|
178 |
## status: 1
|
179 |
## stdout-json: ""
|
180 |
|
181 |
|
182 |
check() {
|
183 |
echo $((BASH_LINENO))
|
184 |
}
|
185 |
check
|
186 |
## stdout: 4
|
187 |
|
188 |
|
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 |
|
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 |
|
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 |
|
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 |
|
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 |
## BUG bash 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:1
|
269 |
## END
|
270 |
|
271 |
## OK osh STDOUT:
|
272 |
F
|
273 |
G
|
274 |
STACK:spec/testdata/bash-source-pushtemp.sh:g:3
|
275 |
STACK:spec/testdata/bash-source-pushtemp.sh:f:19
|
276 |
STACK:spec/testdata/bash-source-pushtemp.sh:source:2
|
277 |
## END
|
278 |
|
279 |
|
280 |
|
281 |
cd $REPO_ROOT
|
282 |
|
283 |
$SH spec/testdata/bash-source-source.sh
|
284 |
|
285 |
## STDOUT:
|
286 |
F
|
287 |
G
|
288 |
STACK:spec/testdata/bash-source-pushtemp.sh:g:3
|
289 |
STACK:spec/testdata/bash-source-pushtemp.sh:f:19
|
290 |
STACK:spec/testdata/bash-source-pushtemp.sh:source:2
|
291 |
STACK:spec/testdata/bash-source-source.sh:mainfunc:6
|
292 |
STACK:spec/testdata/bash-source-source.sh:main2:10
|
293 |
STACK:spec/testdata/bash-source-source.sh:main1:13
|
294 |
STACK:spec/testdata/bash-source-source.sh:main:0
|
295 |
## END
|