1 ## compare_shells: bash zsh mksh ash dash yash
2
3 #### [bash_unset] local-unset / dynamic-unset for localvar
4 unlocal() { unset -v "$1"; }
5
6 f1() {
7 local v=local
8 unset v
9 echo "[$1,local,(unset)] v: ${v-(unset)}"
10 }
11 v=global
12 f1 global
13
14 f1() {
15 local v=local
16 unlocal v
17 echo "[$1,local,(unlocal)] v: ${v-(unset)}"
18 }
19 v=global
20 f1 'global'
21
22 ## STDOUT:
23 # bash-unset
24 # local-unset = value-unset
25 # dynamic-unset = cell-unset
26 [global,local,(unset)] v: (unset)
27 [global,local,(unlocal)] v: global
28 ## END
29
30 ## OK osh/mksh/yash STDOUT:
31 # always-cell-unset
32 # local-unset = cell-unset
33 # dynamic-unset = cell-unset
34 [global,local,(unset)] v: global
35 [global,local,(unlocal)] v: global
36 ## END
37
38 ## OK-2 zsh/ash/dash STDOUT:
39 # always-value-unset
40 # local-unset = value-unset
41 # dynamic-unset = value-unset
42 [global,local,(unset)] v: (unset)
43 [global,local,(unlocal)] v: (unset)
44 ## END
45
46
47 #### [bash_unset] local-unset / dynamic-unset for localvar (mutated from tempenv)
48 unlocal() { unset -v "$1"; }
49
50 f1() {
51 local v=local
52 unset v
53 echo "[$1,local,(unset)] v: ${v-(unset)}"
54 }
55 v=global
56 v=tempenv f1 'global,tempenv'
57
58 f1() {
59 local v=local
60 unlocal v
61 echo "[$1,local,(unlocal)] v: ${v-(unset)}"
62 }
63 v=global
64 v=tempenv f1 'global,tempenv'
65
66 ## STDOUT:
67 # bash-unset (bash-5.1)
68 # local-unset = local-unset
69 # dynamic-unset = cell-unset
70 [global,tempenv,local,(unset)] v: (unset)
71 [global,tempenv,local,(unlocal)] v: global
72 ## END
73
74 # Note on bug in bash 4.3 to bash 5.0
75 # [global,tempenv,local,(unset)] v: global
76 # [global,tempenv,local,(unlocal)] v: global
77
78 ## OK osh/mksh/yash STDOUT:
79 # always-cell-unset
80 # local-unset = cell-unset
81 # dynamic-unset = cell-unset
82 [global,tempenv,local,(unset)] v: tempenv
83 [global,tempenv,local,(unlocal)] v: tempenv
84 ## END
85
86 ## OK-2 zsh/ash/dash STDOUT:
87 # always-value-unset
88 # local-unset = value-unset
89 # dynamic-unset = value-unset
90 [global,tempenv,local,(unset)] v: (unset)
91 [global,tempenv,local,(unlocal)] v: (unset)
92 ## END
93
94
95 #### [bash_unset] local-unset / dynamic-unset for tempenv
96 unlocal() { unset -v "$1"; }
97
98 f1() {
99 unset v
100 echo "[$1,(unset)] v: ${v-(unset)}"
101 }
102 v=global
103 v=tempenv f1 'global,tempenv'
104
105 f1() {
106 unlocal v
107 echo "[$1,(unlocal)] v: ${v-(unset)}"
108 }
109 v=global
110 v=tempenv f1 'global,tempenv'
111
112 ## STDOUT:
113 # always-cell-unset, bash-unset
114 # local-unset = cell-unset
115 # dynamic-unset = cell-unset
116 [global,tempenv,(unset)] v: global
117 [global,tempenv,(unlocal)] v: global
118 ## END
119
120 ## OK zsh/ash/dash/mksh STDOUT:
121 # always-value-unset, mksh-unset
122 # local-unset = value-unset
123 # dynamic-unset = value-unset
124 [global,tempenv,(unset)] v: (unset)
125 [global,tempenv,(unlocal)] v: (unset)
126 ## END
127
128 #### [bash_unset] function call with tempenv vs tempenv-eval
129 unlocal() { unset -v "$1"; }
130
131 f5() {
132 echo "[$1] v: ${v-(unset)}"
133 local v
134 echo "[$1,local] v: ${v-(unset)}"
135 ( unset v
136 echo "[$1,local+unset] v: ${v-(unset)}" )
137 ( unlocal v
138 echo "[$1,local+unlocal] v: ${v-(unset)}" )
139 }
140 v=global
141 f5 'global'
142 v=tempenv f5 'global,tempenv'
143 v=tempenv eval 'f5 "global,tempenv,(eval)"'
144
145 ## STDOUT:
146 # bash-unset (bash-5.1)
147 [global] v: global
148 [global,local] v: (unset)
149 [global,local+unset] v: (unset)
150 [global,local+unlocal] v: global
151 [global,tempenv] v: tempenv
152 [global,tempenv,local] v: tempenv
153 [global,tempenv,local+unset] v: (unset)
154 [global,tempenv,local+unlocal] v: global
155 [global,tempenv,(eval)] v: tempenv
156 [global,tempenv,(eval),local] v: tempenv
157 [global,tempenv,(eval),local+unset] v: (unset)
158 [global,tempenv,(eval),local+unlocal] v: tempenv
159 ## END
160
161 # Note on bug in bash 4.3 to bash 5.0
162 # [global] v: global
163 # [global,local] v: (unset)
164 # [global,local+unset] v: (unset)
165 # [global,local+unlocal] v: global
166 # [global,tempenv] v: tempenv
167 # [global,tempenv,local] v: tempenv
168 # [global,tempenv,local+unset] v: global
169 # [global,tempenv,local+unlocal] v: global
170 # [global,tempenv,(eval)] v: tempenv
171 # [global,tempenv,(eval),local] v: tempenv
172 # [global,tempenv,(eval),local+unset] v: (unset)
173 # [global,tempenv,(eval),local+unlocal] v: tempenv
174
175 ## OK-2 ash STDOUT:
176 # always-value-unset x init.unset
177 [global] v: global
178 [global,local] v: (unset)
179 [global,local+unset] v: (unset)
180 [global,local+unlocal] v: (unset)
181 [global,tempenv] v: tempenv
182 [global,tempenv,local] v: tempenv
183 [global,tempenv,local+unset] v: (unset)
184 [global,tempenv,local+unlocal] v: (unset)
185 [global,tempenv,(eval)] v: tempenv
186 [global,tempenv,(eval),local] v: (unset)
187 [global,tempenv,(eval),local+unset] v: (unset)
188 [global,tempenv,(eval),local+unlocal] v: (unset)
189 ## END
190
191 ## OK-3 zsh STDOUT:
192 # always-value-unset x init.empty
193 [global] v: global
194 [global,local] v:
195 [global,local+unset] v: (unset)
196 [global,local+unlocal] v: (unset)
197 [global,tempenv] v: tempenv
198 [global,tempenv,local] v:
199 [global,tempenv,local+unset] v: (unset)
200 [global,tempenv,local+unlocal] v: (unset)
201 [global,tempenv,(eval)] v: tempenv
202 [global,tempenv,(eval),local] v:
203 [global,tempenv,(eval),local+unset] v: (unset)
204 [global,tempenv,(eval),local+unlocal] v: (unset)
205 ## END
206
207 ## OK-4 dash STDOUT:
208 # always-value-unset x init.inherit
209 [global] v: global
210 [global,local] v: global
211 [global,local+unset] v: (unset)
212 [global,local+unlocal] v: (unset)
213 [global,tempenv] v: tempenv
214 [global,tempenv,local] v: tempenv
215 [global,tempenv,local+unset] v: (unset)
216 [global,tempenv,local+unlocal] v: (unset)
217 [global,tempenv,(eval)] v: tempenv
218 [global,tempenv,(eval),local] v: tempenv
219 [global,tempenv,(eval),local+unset] v: (unset)
220 [global,tempenv,(eval),local+unlocal] v: (unset)
221 ## END
222
223 ## OK osh/yash/mksh STDOUT:
224 # always-cell-unset x init.unset
225 [global] v: global
226 [global,local] v: (unset)
227 [global,local+unset] v: global
228 [global,local+unlocal] v: global
229 [global,tempenv] v: tempenv
230 [global,tempenv,local] v: (unset)
231 [global,tempenv,local+unset] v: tempenv
232 [global,tempenv,local+unlocal] v: tempenv
233 [global,tempenv,(eval)] v: tempenv
234 [global,tempenv,(eval),local] v: (unset)
235 [global,tempenv,(eval),local+unset] v: tempenv
236 [global,tempenv,(eval),local+unlocal] v: tempenv
237 ## END
238
239
240 #### [bash_unset] localvar-inherit from tempenv
241 f1() {
242 local v
243 echo "[$1,(local)] v: ${v-(unset)}"
244 }
245 f2() {
246 f1 "$1,(func)"
247 }
248 f3() {
249 local v=local
250 f1 "$1,local,(func)"
251 }
252 v=global
253
254 f1 'global'
255 v=tempenv f1 'global,tempenv'
256 (export v=global; f1 'xglobal')
257
258 f2 'global'
259 v=tempenv f2 'global,tempenv'
260 (export v=global; f2 'xglobal')
261
262 f3 'global'
263
264 ## STDOUT:
265 # init.bash
266 # init.unset for local
267 # init.inherit for tempenv
268 [global,(local)] v: (unset)
269 [global,tempenv,(local)] v: tempenv
270 [xglobal,(local)] v: (unset)
271 [global,(func),(local)] v: (unset)
272 [global,tempenv,(func),(local)] v: tempenv
273 [xglobal,(func),(local)] v: (unset)
274 [global,local,(func),(local)] v: (unset)
275 ## END
276
277 ## OK osh/mksh/yash STDOUT:
278 # init.unset
279 [global,(local)] v: (unset)
280 [global,tempenv,(local)] v: (unset)
281 [xglobal,(local)] v: (unset)
282 [global,(func),(local)] v: (unset)
283 [global,tempenv,(func),(local)] v: (unset)
284 [xglobal,(func),(local)] v: (unset)
285 [global,local,(func),(local)] v: (unset)
286 ## END
287
288 ## OK-2 ash STDOUT:
289 # init.unset x tempenv-in-localctx
290 [global,(local)] v: (unset)
291 [global,tempenv,(local)] v: tempenv
292 [xglobal,(local)] v: (unset)
293 [global,(func),(local)] v: (unset)
294 [global,tempenv,(func),(local)] v: (unset)
295 [xglobal,(func),(local)] v: (unset)
296 [global,local,(func),(local)] v: (unset)
297 ## END
298
299 ## OK-3 zsh STDOUT:
300 # init.empty
301 [global,(local)] v:
302 [global,tempenv,(local)] v:
303 [xglobal,(local)] v:
304 [global,(func),(local)] v:
305 [global,tempenv,(func),(local)] v:
306 [xglobal,(func),(local)] v:
307 [global,local,(func),(local)] v:
308 ## END
309
310 ## OK-4 dash STDOUT:
311 # init.inherit
312 [global,(local)] v: global
313 [global,tempenv,(local)] v: tempenv
314 [xglobal,(local)] v: global
315 [global,(func),(local)] v: global
316 [global,tempenv,(func),(local)] v: tempenv
317 [xglobal,(func),(local)] v: global
318 [global,local,(func),(local)] v: local
319 ## END
320
321
322 #### [compat_array] ${arr} is ${arr[0]}
323 case ${SH##*/} in (dash|ash) exit 1;; esac # dash/ash does not have arrays
324 case ${SH##*/} in (osh) shopt -s compat_array;; esac
325 case ${SH##*/} in (zsh) setopt KSH_ARRAYS;; esac
326 arr=(foo bar baz)
327 argv.py "$arr" "${arr}"
328 ## stdout: ['foo', 'foo']
329
330 ## N-I dash/ash status: 1
331 ## N-I dash/ash stdout-json: ""
332
333 ## OK yash stdout: ['foo', 'bar', 'baz', 'foo', 'bar', 'baz']
334
335 #### [compat_array] scalar write to arrays
336 case ${SH##*/} in
337 (dash|ash) exit 1;; # dash/ash does not have arrays
338 (osh) shopt -s compat_array;;
339 (zsh) setopt KSH_ARRAYS;;
340 esac
341
342 a=(1 0 0)
343 : $(( a++ ))
344 argv.py "${a[@]}"
345 ## stdout: ['2', '0', '0']
346
347 ## N-I dash/ash status: 1
348 ## N-I dash/ash stdout-json: ""
349
350 ## OK yash STDOUT:
351 # yash does not support scalar access. Instead, it replaces the array
352 # with a scalar.
353 ['1']
354 ## END
355
356 #### [compat_array] scalar write to associative arrays
357 case ${SH##*/} in
358 (dash|ash|yash|mksh) exit 1;; # dash/ash/yash/mksh does not have associative arrays
359 (osh) shopt -s compat_array;;
360 (zsh) setopt KSH_ARRAYS;;
361 esac
362
363 declare -A d=()
364 d['0']=1
365 d['foo']=hello
366 d['bar']=world
367 ((d++))
368 argv.py ${d['0']} ${d['foo']} ${d['bar']}
369 ## stdout: ['2', 'hello', 'world']
370
371 ## N-I dash/ash/yash/mksh status: 1
372 ## N-I dash/ash/yash/mksh stdout-json: ""
373
374 ## N-I zsh stdout: ['1', 'hello', 'world']
375
376 #### [compat_array] ${alpha@a}
377 declare -A alpha=(['1']=2)
378 echo type=${alpha@a}
379 shopt -s compat_array
380 echo type=${alpha@a}
381 ## STDOUT:
382 type=A
383 type=A
384 ## END
385 ## N-I mksh/zsh status: 1
386 ## N-I dash/ash/yash status: 2
387 ## N-I dash/ash/yash/mksh/zsh stdout-json: ""