OILS / spec / ble-idioms.test.sh View on Github | oils.pub

1391 lines, 796 significant
1## oils_cpp_failures_allowed: 2
2
3#### recursive arith: one level
4a='b=123'
5echo $((a))
6## stdout: 123
7## N-I dash status: 2
8## N-I dash stdout-json: ""
9## N-I yash stdout: b=123
10
11#### recursive arith: two levels
12a='b=c' c='d=123'
13echo $((a))
14## stdout: 123
15## N-I dash status: 2
16## N-I dash stdout-json: ""
17## N-I yash stdout: b=c
18
19#### recursive arith: short circuit &&, ||
20# Note: mksh R52 has a bug. Even though it supports a short circuit like
21# "echo $((cond&&(a=1)))", it doesn't work with "x=a=1; echo
22# $((cond&&x))". It is fixed at least in mksh R57.
23# Note: "busybox sh" doesn't support short circuit.
24a=b=123
25echo $((1||a)):$((b))
26echo $((0||a)):$((b))
27c=d=321
28echo $((0&&c)):$((d))
29echo $((1&&c)):$((d))
30## STDOUT:
311:0
321:123
330:0
341:321
35## END
36
37## BUG mksh/ash STDOUT:
381:123
391:123
400:321
411:321
42## END
43
44## N-I dash/yash status: 2
45## N-I dash/yash STDOUT:
461:0
47## END
48
49#### recursive arith: short circuit ?:
50# Note: "busybox sh" behaves strangely.
51y=a=123 n=a=321
52echo $((1?(y):(n))):$((a))
53echo $((0?(y):(n))):$((a))
54## STDOUT:
55123:123
56321:321
57## END
58## BUG ash STDOUT:
59123:321
60321:321
61## END
62## N-I dash status: 2
63## N-I dash stdout-json: ""
64## N-I yash STDOUT:
65a=123:0
66a=321:0
67## END
68
69#### recursive arith: side effects
70# In Zsh and Busybox sh, the side effect of inner arithmetic
71# evaluations seems to take effect only after the whole evaluation.
72a='b=c' c='d=123'
73echo $((a,d)):$((d))
74## stdout: 123:123
75## BUG zsh/ash stdout: 0:123
76## N-I dash/yash status: 2
77## N-I dash/yash stdout-json: ""
78
79#### recursive arith: recursion
80loop='i<=100&&(s+=i,i++,loop)' s=0 i=0
81echo $((a=loop,s))
82## stdout: 5050
83## N-I mksh status: 1
84## N-I mksh stdout-json: ""
85## N-I ash/dash/yash status: 2
86## N-I ash/dash/yash stdout-json: ""
87
88#### recursive arith: array elements
89text[1]='d=123'
90text[2]='text[1]'
91text[3]='text[2]'
92echo $((a=text[3]))
93## stdout: 123
94## N-I ash/dash/yash status: 2
95## N-I ash/dash/yash stdout-json: ""
96
97#### dynamic arith varname: assign
98vec2_set () {
99 local this=$1 x=$2 y=$3
100 : $(( ${this}_x = $2 ))
101 : $(( ${this}_y = y ))
102}
103vec2_set a 3 4
104vec2_set b 5 12
105echo a_x=$a_x a_y=$a_y
106echo b_x=$b_x b_y=$b_y
107## STDOUT:
108a_x=3 a_y=4
109b_x=5 b_y=12
110## END
111
112#### dynamic arith varname: read
113
114vec2_load() {
115 local this=$1
116 x=$(( ${this}_x ))
117 : $(( y = ${this}_y ))
118}
119a_x=12 a_y=34
120vec2_load a
121echo x=$x y=$y
122## STDOUT:
123x=12 y=34
124## END
125
126#### dynamic arith varname: copy/add
127shopt -s eval_unsafe_arith # for RHS
128
129vec2_copy () {
130 local this=$1 rhs=$2
131 : $(( ${this}_x = $(( ${rhs}_x )) ))
132 : $(( ${this}_y = ${rhs}_y ))
133}
134vec2_add () {
135 local this=$1 rhs=$2
136 : $(( ${this}_x += $(( ${rhs}_x )) ))
137 : $(( ${this}_y += ${rhs}_y ))
138}
139a_x=3 a_y=4
140b_x=4 b_y=20
141vec2_copy c a
142echo c_x=$c_x c_y=$c_y
143vec2_add c b
144echo c_x=$c_x c_y=$c_y
145## STDOUT:
146c_x=3 c_y=4
147c_x=7 c_y=24
148## END
149
150#### is-array with ${var@a}
151case $SH in (mksh|ash|dash|yash) exit 1 ;; esac
152
153function ble/is-array { [[ ${!1@a} == *a* ]]; }
154
155ble/is-array undef
156echo undef $?
157
158string=''
159ble/is-array string
160echo string $?
161
162array=(one two three)
163ble/is-array array
164echo array $?
165## STDOUT:
166undef 1
167string 1
168array 0
169## END
170## N-I zsh/mksh/ash/dash/yash status: 1
171## N-I zsh/mksh/ash/dash/yash stdout-json: ""
172
173
174#### Sparse array with big index
175
176# TODO: more BashArray idioms / stress tests ?
177
178a=()
179
180if false; then
181 # This takes too long! # From Zulip
182 i=$(( 0x0100000000000000 ))
183else
184 # smaller number that's OK
185 i=$(( 0x0100000 ))
186fi
187
188a[i]=1
189
190echo len=${#a[@]}
191
192## STDOUT:
193len=1
194## END
195
196## N-I ash status: 2
197## N-I ash STDOUT:
198## END
199
200## BUG zsh STDOUT:
201len=1048576
202## END
203
204
205#### shift unshift reverse
206
207case $SH in mksh|ash) exit ;; esac
208
209# https://github.com/akinomyoga/ble.sh/blob/79beebd928cf9f6506a687d395fd450d027dc4cd/src/util.sh#L578-L582
210
211# @fn ble/array#unshift arr value...
212function ble/array#unshift {
213 builtin eval -- "$1=(\"\${@:2}\" \"\${$1[@]}\")"
214}
215# @fn ble/array#shift arr count
216function ble/array#shift {
217 # Note: Bash 4.3 以下では ${arr[@]:${2:-1}} が offset='${2'
218 # length='-1' に解釈されるので、先に算術式展開させる。
219 builtin eval -- "$1=(\"\${$1[@]:$((${2:-1}))}\")"
220}
221# @fn ble/array#reverse arr
222function ble/array#reverse {
223 builtin eval "
224 set -- \"\${$1[@]}\"; $1=()
225 local e$1 i$1=\$#
226 for e$1; do $1[--i$1]=\"\$e$1\"; done"
227}
228
229a=( {1..6} )
230echo "${a[@]}"
231
232ble/array#shift a 1
233echo "${a[@]}"
234
235ble/array#shift a 2
236echo "${a[@]}"
237
238echo ---
239
240ble/array#unshift a 99
241echo "${a[@]}"
242
243echo ---
244
245# doesn't work in zsh!
246ble/array#reverse a
247echo "${a[@]}"
248
249
250## STDOUT:
2511 2 3 4 5 6
2522 3 4 5 6
2534 5 6
254---
25599 4 5 6
256---
2576 5 4 99
258## END
259
260## BUG zsh STDOUT:
2611 2 3 4 5 6
2622 3 4 5 6
2634 5 6
264---
26599 4 5 6
266---
2675 4 99
268## END
269
270## N-I mksh/ash STDOUT:
271## END
272
273
274#### SparseArray Performance demo
275
276case $SH in bash|zsh|mksh|ash) exit ;; esac
277
278#pp test_ (a)
279
280a=( foo {25..27} bar )
281
282a[10]='sparse'
283
284var sp = _a2sp(a)
285echo $[type(sp)]
286
287echo len: $[_opsp(sp, 'len')]
288
289#echo $[len(sp)]
290
291shopt -s ysh:upgrade
292
293echo subst: @[_opsp(sp, 'subst')]
294echo keys: @[_opsp(sp, 'keys')]
295
296echo slice: @[_opsp(sp, 'slice', 2, 5)]
297
298call _opsp(sp, 'set', 0, 'set0')
299
300echo get0: $[_opsp(sp, 'get', 0)]
301echo get1: $[_opsp(sp, 'get', 1)]
302echo ---
303
304to_append=(x y)
305echo append
306call _opsp(sp, 'append', to_append)
307echo subst: @[_opsp(sp, 'subst')]
308echo keys: @[_opsp(sp, 'keys')]
309echo ---
310
311echo unset
312call _opsp(sp, 'unset', 11)
313echo subst: @[_opsp(sp, 'subst')]
314echo keys: @[_opsp(sp, 'keys')]
315
316## STDOUT:
317SparseArray
318len: 6
319subst: foo 25 26 27 bar sparse
320keys: 0 1 2 3 4 10
321slice: 26 27 bar
322get0: set0
323get1: 25
324---
325append
326subst: set0 25 26 27 bar sparse x y
327keys: 0 1 2 3 4 10 11 12
328---
329unset
330subst: set0 25 26 27 bar sparse y
331keys: 0 1 2 3 4 10 12
332## END
333
334## N-I bash/zsh/mksh/ash STDOUT:
335## END
336
337
338#### SparseArray: test length
339case $SH in bash|zsh|mksh|ash) exit ;; esac
340
341declare -a a=(x y z)
342
343a[5]=z
344var sp = _a2sp(a)
345
346echo len=${#sp[@]}
347
348a[10]=z
349var sp = _a2sp(a)
350
351echo len=${#sp[@]}
352
353
354## STDOUT:
355len=4
356len=5
357## END
358
359## N-I bash/zsh/mksh/ash STDOUT:
360## END
361
362
363#### SparseArray: test "declare -p sp"
364case $SH in zsh|ash) exit ;; esac
365
366a0=()
367a1=(1)
368a2=(1 2)
369a=(x y z w)
370a[500]=100
371a[1000]=100
372
373case $SH in
374bash|mksh)
375 typeset -p a0 a1 a2 a
376 exit ;;
377esac
378
379var a0 = _a2sp(a0)
380var a1 = _a2sp(a1)
381var a2 = _a2sp(a2)
382var sp = _a2sp(a)
383declare -p a0 a1 a2 sp
384
385## STDOUT:
386declare -a a0=()
387declare -a a1=([0]=1)
388declare -a a2=([0]=1 [1]=2)
389declare -a sp=([0]=x [1]=y [2]=z [3]=w [500]=100 [1000]=100)
390## END
391
392## OK bash STDOUT:
393declare -a a0=()
394declare -a a1=([0]="1")
395declare -a a2=([0]="1" [1]="2")
396declare -a a=([0]="x" [1]="y" [2]="z" [3]="w" [500]="100" [1000]="100")
397## END
398
399## OK mksh STDOUT:
400set -A a1
401typeset a1[0]=1
402set -A a2
403typeset a2[0]=1
404typeset a2[1]=2
405set -A a
406typeset a[0]=x
407typeset a[1]=y
408typeset a[2]=z
409typeset a[3]=w
410typeset a[500]=100
411typeset a[1000]=100
412## END
413
414## N-I zsh/ash STDOUT:
415## END
416
417#### SparseArray: +=
418case $SH in bash|zsh|mksh|ash) exit ;; esac
419
420sp1[10]=a
421sp1[20]=b
422sp1[99]=c
423var sp1 = _a2sp(sp1)
424declare -p sp1
425sp1+=(1 2 3)
426declare -p sp1
427
428## STDOUT:
429declare -a sp1=([10]=a [20]=b [99]=c)
430declare -a sp1=([10]=a [20]=b [99]=c [100]=1 [101]=2 [102]=3)
431## END
432
433## N-I bash/zsh/mksh/ash STDOUT:
434## END
435
436
437#### SparseArray: a[i]=v
438case $SH in bash|zsh|mksh|ash) exit ;; esac
439
440sp1[10]=a
441sp1[20]=b
442sp1[30]=c
443var sp1 = _a2sp(sp1)
444declare -p sp1
445sp1[10]=X
446sp1[25]=Y
447sp1[90]=Z
448declare -p sp1
449
450## STDOUT:
451declare -a sp1=([10]=a [20]=b [30]=c)
452declare -a sp1=([10]=X [20]=b [25]=Y [30]=c [90]=Z)
453## END
454
455## N-I bash/zsh/mksh/ash STDOUT:
456## END
457
458
459#### SparseArray: Negative index with a[i]=v
460case $SH in bash|zsh|mksh|ash) exit ;; esac
461
462sp1[9]=x
463var sp1 = _a2sp(sp1)
464
465declare -p sp1
466sp1[-1]=A
467sp1[-4]=B
468sp1[-8]=C
469sp1[-10]=D
470declare -p sp1
471
472## STDOUT:
473declare -a sp1=([9]=x)
474declare -a sp1=([0]=D [2]=C [6]=B [9]=A)
475## END
476
477## N-I bash/zsh/mksh/ash STDOUT:
478## END
479
480
481#### SparseArray: a[i]=v with BigInt
482case $SH in zsh|mksh|ash) exit ;; esac
483
484sp1[1]=x
485sp1[5]=y
486sp1[9]=z
487case ${SH##*/} in osh) eval 'var sp1 = _a2sp(sp1)' ;; esac
488
489echo "${#sp1[@]}"
490sp1[0x7FFFFFFFFFFFFFFF]=a
491echo "${#sp1[@]}"
492sp1[0x7FFFFFFFFFFFFFFE]=b
493echo "${#sp1[@]}"
494sp1[0x7FFFFFFFFFFFFFFD]=c
495echo "${#sp1[@]}"
496
497## STDOUT:
4983
4994
5005
5016
502## END
503
504## N-I zsh/mksh/ash STDOUT:
505## END
506
507
508#### SparseArray: Negative out-of-bound index with a[i]=v (1/2)
509case $SH in bash|zsh|mksh|ash) exit ;; esac
510
511sp1[9]=x
512var sp1 = _a2sp(sp1)
513
514sp1[-11]=E
515declare -p sp1
516
517## status: 1
518## STDOUT:
519## END
520## STDERR:
521 sp1[-11]=E
522 ^~~~
523[ stdin ]:6: fatal: Index -11 is out of bounds for array of length 10
524## END
525
526## N-I bash/zsh/mksh/ash status: 0
527## N-I bash/zsh/mksh/ash STDERR:
528## END
529
530
531#### SparseArray: Negative out-of-bound index with a[i]=v (2/2)
532case $SH in bash|zsh|mksh|ash) exit ;; esac
533
534sp1[9]=x
535var sp1 = _a2sp(sp1)
536
537sp1[-21]=F
538declare -p sp1
539
540## status: 1
541## STDOUT:
542## END
543## STDERR:
544 sp1[-21]=F
545 ^~~~
546[ stdin ]:6: fatal: Index -21 is out of bounds for array of length 10
547## END
548
549## N-I bash/zsh/mksh/ash status: 0
550## N-I bash/zsh/mksh/ash STDERR:
551## END
552
553
554#### SparseArray: xtrace a+=()
555case $SH in bash|zsh|mksh|ash) exit ;; esac
556
557sp1=(1)
558var sp1 = _a2sp(sp1)
559set -x
560sp1+=(2)
561
562## STDERR:
563+ sp1+=(2)
564## END
565
566## N-I bash/zsh/mksh/ash STDERR:
567## END
568
569
570#### SparseArray: unset -v a[i]
571case $SH in bash|zsh|mksh|ash) exit ;; esac
572
573a=({1..9})
574var a = _a2sp(a)
575
576declare -p a
577unset -v "a[1]"
578declare -p a
579unset -v "a[9]"
580declare -p a
581unset -v "a[0]"
582declare -p a
583
584## STDOUT:
585declare -a a=([0]=1 [1]=2 [2]=3 [3]=4 [4]=5 [5]=6 [6]=7 [7]=8 [8]=9)
586declare -a a=([0]=1 [2]=3 [3]=4 [4]=5 [5]=6 [6]=7 [7]=8 [8]=9)
587declare -a a=([0]=1 [2]=3 [3]=4 [4]=5 [5]=6 [6]=7 [7]=8 [8]=9)
588declare -a a=([2]=3 [3]=4 [4]=5 [5]=6 [6]=7 [7]=8 [8]=9)
589## END
590
591## N-I bash/zsh/mksh/ash STDOUT:
592## END
593
594
595#### SparseArray: unset -v a[i] with out-of-bound negative index
596case $SH in bash|zsh|mksh|ash) exit ;; esac
597
598a=(1)
599var a = _a2sp(a)
600
601unset -v "a[-2]"
602unset -v "a[-3]"
603
604## status: 1
605## STDOUT:
606## END
607## STDERR:
608 unset -v "a[-2]"
609 ^
610[ stdin ]:6: a[-2]: Index is out of bounds for array of length 1
611 unset -v "a[-3]"
612 ^
613[ stdin ]:7: a[-3]: Index is out of bounds for array of length 1
614## END
615
616## N-I bash/zsh/mksh/ash status: 0
617## N-I bash/zsh/mksh/ash STDERR:
618## END
619
620
621#### SparseArray: unset -v a[i] for max index
622case $SH in bash|zsh|mksh|ash) exit ;; esac
623
624a=({1..9})
625var a = _a2sp(a)
626unset -v 'a[-1]'
627a[-1]=x
628declare -p a
629unset -v 'a[-1]'
630a[-1]=x
631declare -p a
632
633## STDOUT:
634declare -a a=([0]=1 [1]=2 [2]=3 [3]=4 [4]=5 [5]=6 [6]=7 [7]=x)
635declare -a a=([0]=1 [1]=2 [2]=3 [3]=4 [4]=5 [5]=6 [6]=x)
636## END
637
638## N-I bash/zsh/mksh/ash STDOUT:
639## END
640
641
642#### SparseArray: [[ -v a[i] ]]
643case $SH in bash|zsh|mksh|ash) exit ;; esac
644
645a=()
646var sp1 = _a2sp(a)
647[[ -v sp1[0] ]]; echo "$? (expect 1)"
648[[ -v sp1[9] ]]; echo "$? (expect 1)"
649
650a=({1..9})
651var sp2 = _a2sp(a)
652[[ -v sp2[0] ]]; echo "$? (expect 0)"
653[[ -v sp2[8] ]]; echo "$? (expect 0)"
654[[ -v sp2[9] ]]; echo "$? (expect 1)"
655[[ -v sp2[-1] ]]; echo "$? (expect 0)"
656[[ -v sp2[-2] ]]; echo "$? (expect 0)"
657[[ -v sp2[-9] ]]; echo "$? (expect 0)"
658
659unset -v 'a[4]'
660var sp3 = _a2sp(a)
661[[ -v sp3[3] ]]; echo "$? (expect 0)"
662[[ -v sp3[4] ]]; echo "$? (expect 1)"
663[[ -v sp3[5] ]]; echo "$? (expect 0)"
664[[ -v sp3[-1] ]]; echo "$? (expect 0)"
665[[ -v sp3[-4] ]]; echo "$? (expect 0)"
666[[ -v sp3[-5] ]]; echo "$? (expect 1)"
667[[ -v sp3[-6] ]]; echo "$? (expect 0)"
668[[ -v sp3[-9] ]]; echo "$? (expect 0)"
669
670## STDOUT:
6711 (expect 1)
6721 (expect 1)
6730 (expect 0)
6740 (expect 0)
6751 (expect 1)
6760 (expect 0)
6770 (expect 0)
6780 (expect 0)
6790 (expect 0)
6801 (expect 1)
6810 (expect 0)
6820 (expect 0)
6830 (expect 0)
6841 (expect 1)
6850 (expect 0)
6860 (expect 0)
687## END
688
689## N-I bash/zsh/mksh/ash STDOUT:
690## END
691
692
693#### SparseArray: [[ -v a[i] ]] with invalid negative index
694case $SH in bash|zsh|mksh|ash) exit ;; esac
695
696a=()
697var sp1 = _a2sp(a)
698([[ -v sp1[-1] ]]; echo "$? (expect 1)")
699a=({1..9})
700var sp2 = _a2sp(a)
701([[ -v sp2[-10] ]]; echo "$? (expect 1)")
702var sp3 = _a2sp(a)
703([[ -v sp3[-10] ]]; echo "$? (expect 1)")
704
705## status: 1
706## STDOUT:
707## END
708## STDERR:
709 ([[ -v sp1[-1] ]]; echo "$? (expect 1)")
710 ^~~
711[ stdin ]:5: fatal: -v got index -1, which is out of bounds for array of length 0
712 ([[ -v sp2[-10] ]]; echo "$? (expect 1)")
713 ^~~
714[ stdin ]:8: fatal: -v got index -10, which is out of bounds for array of length 9
715 ([[ -v sp3[-10] ]]; echo "$? (expect 1)")
716 ^~~
717[ stdin ]:10: fatal: -v got index -10, which is out of bounds for array of length 9
718## END
719
720## N-I bash/zsh/mksh/ash status: 0
721## N-I bash/zsh/mksh/ash STDERR:
722## END
723
724
725#### SparseArray: ((sp[i])) and ((sp[i]++))
726case $SH in zsh|mksh|ash) exit ;; esac
727
728a=({1..9})
729unset -v 'a[2]' 'a[3]' 'a[7]'
730case $SH in osh) eval 'var a = _a2sp(a)' ;; esac
731
732echo $((a[0]))
733echo $((a[1]))
734echo $((a[2]))
735echo $((a[3]))
736echo $((a[7]))
737
738echo $((a[1]++))
739echo $((a[2]++))
740echo $((a[3]++))
741echo $((a[7]++))
742
743echo $((++a[1]))
744echo $((++a[2]))
745echo $((++a[3]))
746echo $((++a[7]))
747
748echo $((a[1] = 100, a[1]))
749echo $((a[2] = 100, a[2]))
750echo $((a[3] = 100, a[3]))
751echo $((a[7] = 100, a[7]))
752
753## STDOUT:
7541
7552
7560
7570
7580
7592
7600
7610
7620
7634
7642
7652
7662
767100
768100
769100
770100
771## END
772
773## N-I zsh/mksh/ash STDOUT:
774## END
775
776
777#### SparseArray: ((sp[i])) and ((sp[i]++)) with invalid negative index
778case $SH in zsh|mksh|ash) exit ;; esac
779
780a=({1..9})
781unset -v 'a[2]' 'a[3]' 'a[7]'
782case $SH in osh) eval 'var a = _a2sp(a)' ;; esac
783
784echo $((a[-10]))
785
786## STDOUT:
7870
788## END
789## STDERR:
790 echo $((a[-10]))
791 ^
792[ stdin ]:7: Index -10 out of bounds for array of length 9
793## END
794
795## OK bash STDERR:
796bash: line 7: a: bad array subscript
797## END
798
799## N-I zsh/mksh/ash STDOUT:
800## END
801## N-I zsh/mksh/ash STDERR:
802## END
803
804
805#### SparseArray: ${sp[i]}
806case $SH in bash|zsh|mksh|ash) exit ;; esac
807
808a=({1..9})
809unset -v 'a[2]'
810unset -v 'a[3]'
811unset -v 'a[7]'
812var sp = _a2sp(a)
813
814echo "sp[0]: '${sp[0]}', ${sp[0]:-(empty)}, ${sp[0]+set}."
815echo "sp[1]: '${sp[1]}', ${sp[1]:-(empty)}, ${sp[1]+set}."
816echo "sp[8]: '${sp[8]}', ${sp[8]:-(empty)}, ${sp[8]+set}."
817echo "sp[2]: '${sp[2]}', ${sp[2]:-(empty)}, ${sp[2]+set}."
818echo "sp[3]: '${sp[3]}', ${sp[3]:-(empty)}, ${sp[3]+set}."
819echo "sp[7]: '${sp[7]}', ${sp[7]:-(empty)}, ${sp[7]+set}."
820
821echo "sp[-1]: '${sp[-1]}'."
822echo "sp[-2]: '${sp[-2]}'."
823echo "sp[-3]: '${sp[-3]}'."
824echo "sp[-4]: '${sp[-4]}'."
825echo "sp[-9]: '${sp[-9]}'."
826
827## STDOUT:
828sp[0]: '1', 1, set.
829sp[1]: '2', 2, set.
830sp[8]: '9', 9, set.
831sp[2]: '', (empty), .
832sp[3]: '', (empty), .
833sp[7]: '', (empty), .
834sp[-1]: '9'.
835sp[-2]: ''.
836sp[-3]: '7'.
837sp[-4]: '6'.
838sp[-9]: '1'.
839## END
840
841## N-I bash/zsh/mksh/ash STDOUT:
842## END
843
844
845#### SparseArray: ${sp[i]} with negative invalid index
846case $SH in bash|zsh|mksh|ash) exit ;; esac
847
848a=({1..9})
849unset -v 'a[2]'
850unset -v 'a[3]'
851unset -v 'a[7]'
852var sp = _a2sp(a)
853
854echo "sp[-10]: '${sp[-10]}'."
855echo "sp[-11]: '${sp[-11]}'."
856echo "sp[-19]: '${sp[-19]}'."
857
858## STDOUT:
859sp[-10]: ''.
860sp[-11]: ''.
861sp[-19]: ''.
862## END
863## STDERR:
864 echo "sp[-10]: '${sp[-10]}'."
865 ^~
866[ stdin ]:9: Index -10 out of bounds for array of length 9
867 echo "sp[-11]: '${sp[-11]}'."
868 ^~
869[ stdin ]:10: Index -11 out of bounds for array of length 9
870 echo "sp[-19]: '${sp[-19]}'."
871 ^~
872[ stdin ]:11: Index -19 out of bounds for array of length 9
873## END
874
875## N-I bash/zsh/mksh/ash STDOUT:
876## END
877## N-I bash/zsh/mksh/ash STDERR:
878## END
879
880
881#### SparseArray (YSH): @[sp] and @sp
882case $SH in bash|zsh|mksh|ash) exit ;; esac
883
884a=({0..5})
885unset -v 'a[1]' 'a[2]' 'a[4]'
886var a = _a2sp(a)
887
888shopt -s parse_at
889argv.py @[a]
890argv.py @a
891## STDOUT:
892['0', '3', '5']
893['0', '3', '5']
894## END
895
896## N-I bash/zsh/mksh/ash STDOUT:
897## END
898
899
900#### SparseArray: ${a[@]:offset:length}
901case $SH in zsh|mksh|ash) exit ;; esac
902
903a=(v{0..9})
904unset -v 'a[2]' 'a[3]' 'a[4]' 'a[7]'
905case ${SH##*/} in osh) eval 'var a = _a2sp(a)' ;; esac
906
907echo '==== ${a[@]:offset} ===='
908echo "[${a[@]:0}][${a[*]:0}]"
909echo "[${a[@]:2}][${a[*]:2}]"
910echo "[${a[@]:3}][${a[*]:3}]"
911echo "[${a[@]:5}][${a[*]:5}]"
912echo "[${a[@]:9}][${a[*]:9}]"
913echo "[${a[@]:10}][${a[*]:10}]"
914echo "[${a[@]:11}][${a[*]:11}]"
915
916echo '==== ${a[@]:negative} ===='
917echo "[${a[@]: -1}][${a[*]: -1}]"
918echo "[${a[@]: -2}][${a[*]: -2}]"
919echo "[${a[@]: -5}][${a[*]: -5}]"
920echo "[${a[@]: -9}][${a[*]: -9}]"
921echo "[${a[@]: -10}][${a[*]: -10}]"
922echo "[${a[@]: -11}][${a[*]: -11}]"
923echo "[${a[@]: -21}][${a[*]: -21}]"
924
925echo '==== ${a[@]:offset:length} ===='
926echo "[${a[@]:0:0}][${a[*]:0:0}]"
927echo "[${a[@]:0:1}][${a[*]:0:1}]"
928echo "[${a[@]:0:3}][${a[*]:0:3}]"
929echo "[${a[@]:2:1}][${a[*]:2:1}]"
930echo "[${a[@]:2:4}][${a[*]:2:4}]"
931echo "[${a[@]:3:4}][${a[*]:3:4}]"
932echo "[${a[@]:5:4}][${a[*]:5:4}]"
933echo "[${a[@]:5:0}][${a[*]:5:0}]"
934echo "[${a[@]:9:1}][${a[*]:9:1}]"
935echo "[${a[@]:9:2}][${a[*]:9:2}]"
936echo "[${a[@]:10:1}][${a[*]:10:1}]"
937
938## STDOUT:
939==== ${a[@]:offset} ====
940[v0 v1 v5 v6 v8 v9][v0 v1 v5 v6 v8 v9]
941[v5 v6 v8 v9][v5 v6 v8 v9]
942[v5 v6 v8 v9][v5 v6 v8 v9]
943[v5 v6 v8 v9][v5 v6 v8 v9]
944[v9][v9]
945[][]
946[][]
947==== ${a[@]:negative} ====
948[v9][v9]
949[v8 v9][v8 v9]
950[v5 v6 v8 v9][v5 v6 v8 v9]
951[v1 v5 v6 v8 v9][v1 v5 v6 v8 v9]
952[v0 v1 v5 v6 v8 v9][v0 v1 v5 v6 v8 v9]
953[][]
954[][]
955==== ${a[@]:offset:length} ====
956[][]
957[v0][v0]
958[v0 v1 v5][v0 v1 v5]
959[v5][v5]
960[v5 v6 v8 v9][v5 v6 v8 v9]
961[v5 v6 v8 v9][v5 v6 v8 v9]
962[v5 v6 v8 v9][v5 v6 v8 v9]
963[][]
964[v9][v9]
965[v9][v9]
966[][]
967## END
968
969## N-I zsh/mksh/ash STDOUT:
970## END
971
972
973#### ${@:offset:length}
974case $SH in zsh|mksh|ash) exit ;; esac
975
976set -- v{1..9}
977
978{
979 echo '==== ${@:offset:length} ===='
980 echo "[${*:0:3}][${*:0:3}]"
981 echo "[${*:1:3}][${*:1:3}]"
982 echo "[${*:3:3}][${*:3:3}]"
983 echo "[${*:5:10}][${*:5:10}]"
984
985 echo '==== ${@:negative} ===='
986 echo "[${*: -1}][${*: -1}]"
987 echo "[${*: -3}][${*: -3}]"
988 echo "[${*: -9}][${*: -9}]"
989 echo "[${*: -10}][${*: -10}]"
990 echo "[${*: -11}][${*: -11}]"
991 echo "[${*: -3:2}][${*: -3:2}]"
992 echo "[${*: -9:4}][${*: -9:4}]"
993 echo "[${*: -10:4}][${*: -10:4}]"
994 echo "[${*: -11:4}][${*: -11:4}]"
995} | sed "s:$SH:\$SH:g;s:${SH##*/}:\$SH:g"
996
997## STDOUT:
998==== ${@:offset:length} ====
999[$SH v1 v2][$SH v1 v2]
1000[v1 v2 v3][v1 v2 v3]
1001[v3 v4 v5][v3 v4 v5]
1002[v5 v6 v7 v8 v9][v5 v6 v7 v8 v9]
1003==== ${@:negative} ====
1004[v9][v9]
1005[v7 v8 v9][v7 v8 v9]
1006[v1 v2 v3 v4 v5 v6 v7 v8 v9][v1 v2 v3 v4 v5 v6 v7 v8 v9]
1007[$SH v1 v2 v3 v4 v5 v6 v7 v8 v9][$SH v1 v2 v3 v4 v5 v6 v7 v8 v9]
1008[][]
1009[v7 v8][v7 v8]
1010[v1 v2 v3 v4][v1 v2 v3 v4]
1011[$SH v1 v2 v3][$SH v1 v2 v3]
1012[][]
1013## END
1014
1015## N-I zsh/mksh/ash STDOUT:
1016## END
1017
1018
1019#### SparseArray: ${a[@]:BigInt}
1020case $SH in zsh|mksh|ash) exit ;; esac
1021
1022case $SH in
1023 bash)
1024 # Work around bash integer overflow bug that only happens on say Debian 10,
1025 # but NOT Debian 12. The bug exists in bash 5.2. It's unclear why it
1026 # depends on the OS version.
1027 v='/etc/debian_version'
1028 # debian version 10 / debian buster
1029 if test -f $v && grep -E 'buster/sid|^10' $v >/dev/null; then
1030 cat << 'EOF'
1031[x][x]
1032[y x][y x]
1033[z y x][z y x]
1034[z y x][z y x]
1035EOF
1036 exit
1037 fi
1038 # Actual STDOUT of buggy bash builds:
1039 # [][]
1040 # [][]
1041 # [][]
1042 # [][]
1043 ;;
1044esac
1045
1046a=(1 2 3)
1047case ${SH##*/} in osh) eval 'var a = _a2sp(a)' ;; esac
1048a[0x7FFFFFFFFFFFFFFF]=x
1049a[0x7FFFFFFFFFFFFFFE]=y
1050a[0x7FFFFFFFFFFFFFFD]=z
1051
1052echo "[${a[@]: -1}][${a[*]: -1}]"
1053echo "[${a[@]: -2}][${a[*]: -2}]"
1054echo "[${a[@]: -3}][${a[*]: -3}]"
1055echo "[${a[@]: -4}][${a[*]: -4}]"
1056
1057## STDOUT:
1058[x][x]
1059[y x][y x]
1060[z y x][z y x]
1061[z y x][z y x]
1062## END
1063
1064## N-I zsh/mksh/ash STDOUT:
1065## END
1066
1067
1068#### SparseArray: ${a[@]}
1069
1070case $SH in zsh|mksh|ash) exit ;; esac
1071
1072a=(v{0..9})
1073unset -v 'a[2]' 'a[3]' 'a[4]' 'a[7]'
1074case ${SH##*/} in osh) eval 'var a = _a2sp(a)' ;; esac
1075
1076argv.py "${a[@]}"
1077argv.py "abc${a[@]}xyz"
1078
1079## STDOUT:
1080['v0', 'v1', 'v5', 'v6', 'v8', 'v9']
1081['abcv0', 'v1', 'v5', 'v6', 'v8', 'v9xyz']
1082## END
1083
1084## N-I zsh/mksh/ash STDOUT:
1085## END
1086
1087
1088#### SparseArray: ${a[@]#...}
1089
1090case $SH in zsh|mksh|ash) exit ;; esac
1091
1092a=(v{0..9})
1093unset -v 'a[2]' 'a[3]' 'a[4]' 'a[7]'
1094case ${SH##*/} in osh) eval 'var a = _a2sp(a)' ;; esac
1095
1096argv.py "${a[@]#v}"
1097argv.py "abc${a[@]#v}xyz"
1098argv.py "${a[@]%[0-5]}"
1099argv.py "abc${a[@]%[0-5]}xyz"
1100argv.py "${a[@]#v?}"
1101
1102## STDOUT:
1103['0', '1', '5', '6', '8', '9']
1104['abc0', '1', '5', '6', '8', '9xyz']
1105['v', 'v', 'v', 'v6', 'v8', 'v9']
1106['abcv', 'v', 'v', 'v6', 'v8', 'v9xyz']
1107['', '', '', '', '', '']
1108## END
1109
1110## N-I zsh/mksh/ash STDOUT:
1111## END
1112
1113
1114#### SparseArray: ${a[@]/pat/rep}
1115
1116case $SH in zsh|mksh|ash) exit ;; esac
1117
1118a=(v{0..9})
1119unset -v 'a[2]' 'a[3]' 'a[4]' 'a[7]'
1120case ${SH##*/} in osh) eval 'var a = _a2sp(a)' ;; esac
1121
1122argv.py "${a[@]/?}"
1123argv.py "${a[@]//?}"
1124argv.py "${a[@]/#?}"
1125argv.py "${a[@]/%?}"
1126
1127argv.py "${a[@]/v/x}"
1128argv.py "${a[@]//v/x}"
1129argv.py "${a[@]/[0-5]/D}"
1130argv.py "${a[@]//[!0-5]/_}"
1131
1132## STDOUT:
1133['0', '1', '5', '6', '8', '9']
1134['', '', '', '', '', '']
1135['0', '1', '5', '6', '8', '9']
1136['v', 'v', 'v', 'v', 'v', 'v']
1137['x0', 'x1', 'x5', 'x6', 'x8', 'x9']
1138['x0', 'x1', 'x5', 'x6', 'x8', 'x9']
1139['vD', 'vD', 'vD', 'v6', 'v8', 'v9']
1140['_0', '_1', '_5', '__', '__', '__']
1141## END
1142
1143## N-I zsh/mksh/ash STDOUT:
1144## END
1145
1146
1147#### SparseArray: ${a[@]@P}, ${a[@]@Q}, and ${a[@]@a}
1148case $SH in zsh|mksh|ash) exit ;; esac
1149
1150a=(v{0..9})
1151unset -v 'a[2]' 'a[3]' 'a[4]' 'a[7]'
1152case ${SH##*/} in osh) eval 'var a = _a2sp(a)' ;; esac
1153
1154argv.py "${a[@]@P}"
1155argv.py "${a[*]@P}"
1156argv.py "${a[@]@Q}"
1157argv.py "${a[*]@Q}"
1158argv.py "${a[@]@a}"
1159argv.py "${a[*]@a}"
1160
1161## STDOUT:
1162['v0', 'v1', 'v5', 'v6', 'v8', 'v9']
1163['v0 v1 v5 v6 v8 v9']
1164['v0', 'v1', 'v5', 'v6', 'v8', 'v9']
1165['v0 v1 v5 v6 v8 v9']
1166['a', 'a', 'a', 'a', 'a', 'a']
1167['a a a a a a']
1168## END
1169
1170## OK bash STDOUT:
1171['v0', 'v1', 'v5', 'v6', 'v8', 'v9']
1172['v0 v1 v5 v6 v8 v9']
1173["'v0'", "'v1'", "'v5'", "'v6'", "'v8'", "'v9'"]
1174["'v0' 'v1' 'v5' 'v6' 'v8' 'v9'"]
1175['a', 'a', 'a', 'a', 'a', 'a']
1176['a a a a a a']
1177## END
1178
1179## N-I zsh/mksh/ash STDOUT:
1180## END
1181
1182
1183#### SparseArray: ${a[@]-unset}, ${a[@]:-empty}, etc.
1184case $SH in zsh|mksh|ash) exit ;; esac
1185
1186a1=()
1187a2=("")
1188a3=("" "")
1189
1190case $SH in
1191bash) ;;
1192*) eval "var a1 = _a2sp(a1); var a2 = _a2sp(a2); var a3 = _a2sp(a3)" ;;
1193esac
1194
1195echo "a1 unset: [${a1[@]-unset}]"
1196echo "a1 empty: [${a1[@]:-empty}]"
1197echo "a2 unset: [${a2[@]-unset}]"
1198echo "a2 empty: [${a2[@]:-empty}]"
1199echo "a3 unset: [${a3[@]-unset}]"
1200echo "a3 empty: [${a3[@]:-empty}]"
1201
1202## STDOUT:
1203a1 unset: [unset]
1204a1 empty: [empty]
1205a2 unset: []
1206a2 empty: [empty]
1207a3 unset: [ ]
1208a3 empty: [ ]
1209## END
1210
1211## N-I zsh/mksh/ash STDOUT:
1212## END
1213
1214
1215#### SparseArray: ${a-}
1216case $SH in zsh|mksh|ash) exit ;; esac
1217
1218a1=()
1219a2=("" "")
1220a3=(foo bar)
1221
1222case ${SH##*/} in osh) eval 'var a1 = _a2sp(a1); var a2 = _a2sp(a2); var a3 = _a2sp(a3)' ;; esac
1223
1224echo "$a1, ${a1-(unset)}, ${a1:-(empty)};"
1225echo "$a2, ${a2-(unset)}, ${a2:-(empty)};"
1226echo "$a3, ${a3-(unset)}, ${a3:-(empty)};"
1227
1228## STDOUT:
1229, (unset), (empty);
1230, , (empty);
1231foo, foo, foo;
1232## END
1233
1234## N-I zsh/mksh/ash STDOUT:
1235## END
1236
1237
1238#### SparseArray: compgen -F _set_COMPREPLY
1239case $SH in zsh|mksh|ash) exit ;; esac
1240
1241a=({0..9})
1242unset -v 'a[2]' 'a[4]' 'a[6]'
1243
1244case ${SH##*/} in
1245osh)
1246 eval '_set_COMPREPLY() { setglobal COMPREPLY = _a2sp(a); }'
1247 ;;
1248*)
1249 _set_COMPREPLY() { COMPREPLY=("${a[@]}"); }
1250 ;;
1251esac
1252
1253compgen -F _set_COMPREPLY
1254
1255## STDOUT:
12560
12571
12583
12595
12607
12618
12629
1263## END
1264
1265## N-I zsh/mksh/ash STDOUT:
1266## END
1267
1268
1269#### SparseArray: compgen -F _set_COMPREPLY
1270case $SH in bash|zsh|mksh|ash) exit ;; esac
1271
1272a=(echo 'Hello,' 'Bash' 'world!')
1273var COMP_ARGV = _a2sp(a)
1274compadjust cur prev words cword
1275argv.py "$cur" "$prev" "$cword"
1276argv.py "${words[@]}"
1277
1278## STDOUT:
1279['world!', 'Bash', '3']
1280['echo', 'Hello,', 'Bash', 'world!']
1281## END
1282
1283## N-I bash/zsh/mksh/ash STDOUT:
1284## END
1285
1286
1287#### SparseArray (YSH): $[a1 === a2]
1288case $SH in bash|zsh|mksh|ash) exit ;; esac
1289
1290a1=(1 2 3)
1291unset -v 'a1[1]'
1292a2=(1 2 3)
1293unset -v 'a2[1]'
1294a3=(1 2 4)
1295unset -v 'a3[1]'
1296a4=(1 2 3)
1297var a1 = _a2sp(a1)
1298var a2 = _a2sp(a2)
1299var a3 = _a2sp(a3)
1300var a4 = _a2sp(a4)
1301
1302echo $[a1 === a1]
1303echo $[a1 === a2]
1304echo $[a1 === a3]
1305echo $[a1 === a4]
1306echo $[a2 === a1]
1307echo $[a3 === a1]
1308echo $[a4 === a1]
1309
1310## STDOUT:
1311true
1312true
1313false
1314false
1315true
1316false
1317false
1318## END
1319
1320## N-I bash/zsh/mksh/ash STDOUT:
1321## END
1322
1323
1324#### SparseArray (YSH): append v1 v2... (a)
1325case $SH in bash|zsh|mksh|ash) exit ;; esac
1326
1327a=(1 2 3)
1328unset -v 'a[1]'
1329var a = _a2sp(a)
1330append 'x' 'y' 'z' (a)
1331= a
1332
1333## STDOUT:
1334(SparseArray [0]='1' [2]='3' [3]='x' [4]='y' [5]='z')
1335## END
1336
1337## N-I bash/zsh/mksh/ash STDOUT:
1338## END
1339
1340
1341#### SparseArray (YSH): $[bool(a)]
1342case $SH in bash|zsh|mksh|ash) exit ;; esac
1343
1344a1=()
1345a2=(0)
1346a3=(0 1 2)
1347a4=(0 0)
1348unset -v 'a4[0]'
1349var a1 = _a2sp(a1)
1350var a2 = _a2sp(a2)
1351var a3 = _a2sp(a3)
1352var a4 = _a2sp(a4)
1353
1354echo $[bool(a1)]
1355echo $[bool(a2)]
1356echo $[bool(a3)]
1357echo $[bool(a4)]
1358
1359## STDOUT:
1360false
1361true
1362true
1363true
1364## END
1365
1366## N-I bash/zsh/mksh/ash STDOUT:
1367## END
1368
1369
1370#### SparseArray: crash dump
1371case $SH in bash|zsh|mksh|ash) exit ;; esac
1372
1373OILS_CRASH_DUMP_DIR=$TMP $SH -ec 'a=({0..3}); unset -v "a[2]"; var a = _a2sp(a); false'
1374json read (&crash_dump) < $TMP/*.json
1375json write (crash_dump.var_stack[0].a)
1376
1377## STDOUT:
1378{
1379 "val": {
1380 "type": "SparseArray",
1381 "data": {
1382 "0": "0",
1383 "1": "1",
1384 "3": "3"
1385 }
1386 }
1387}
1388## END
1389
1390## N-I bash/zsh/mksh/ash STDOUT:
1391## END