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

1428 lines, 808 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=(1)
388declare -a a2=(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=(1 2 3 4 5 6 7 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=(1 2 3 4 5 6 7 x)
635declare -a a=(1 2 3 4 5 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: ${!a[0]}
1239case $SH in zsh|mksh|ash) exit ;; esac
1240
1241v1=hello v2=world
1242a=(v1 v2)
1243
1244case ${SH##*/} in osh) eval 'var a = _a2sp(a)' ;; esac
1245
1246echo "${!a[0]}, ${!a[1]}"
1247
1248## STDOUT:
1249hello, world
1250## END
1251
1252## N-I zsh/mksh/ash STDOUT:
1253## END
1254
1255
1256#### SparseArray: ${!a[0]}
1257case $SH in zsh|mksh|ash) exit ;; esac
1258
1259a=(v{0..9})
1260unset -v 'a[3]' 'a[4]' 'a[7]' 'a[9]'
1261
1262case ${SH##*/} in osh) eval 'var a = _a2sp(a)' ;; esac
1263
1264argv.py "${!a[@]}"
1265
1266
1267## STDOUT:
1268['0', '1', '2', '5', '6', '8']
1269## END
1270
1271## N-I zsh/mksh/ash STDOUT:
1272## END
1273
1274
1275#### SparseArray: compgen -F _set_COMPREPLY
1276case $SH in zsh|mksh|ash) exit ;; esac
1277
1278a=({0..9})
1279unset -v 'a[2]' 'a[4]' 'a[6]'
1280
1281case ${SH##*/} in
1282osh)
1283 eval '_set_COMPREPLY() { setglobal COMPREPLY = _a2sp(a); }'
1284 ;;
1285*)
1286 _set_COMPREPLY() { COMPREPLY=("${a[@]}"); }
1287 ;;
1288esac
1289
1290compgen -F _set_COMPREPLY
1291
1292## STDOUT:
12930
12941
12953
12965
12977
12988
12999
1300## END
1301
1302## N-I zsh/mksh/ash STDOUT:
1303## END
1304
1305
1306#### SparseArray: compgen -F _set_COMPREPLY
1307case $SH in bash|zsh|mksh|ash) exit ;; esac
1308
1309a=(echo 'Hello,' 'Bash' 'world!')
1310var COMP_ARGV = _a2sp(a)
1311compadjust cur prev words cword
1312argv.py "$cur" "$prev" "$cword"
1313argv.py "${words[@]}"
1314
1315## STDOUT:
1316['world!', 'Bash', '3']
1317['echo', 'Hello,', 'Bash', 'world!']
1318## END
1319
1320## N-I bash/zsh/mksh/ash STDOUT:
1321## END
1322
1323
1324#### SparseArray (YSH): $[a1 === a2]
1325case $SH in bash|zsh|mksh|ash) exit ;; esac
1326
1327a1=(1 2 3)
1328unset -v 'a1[1]'
1329a2=(1 2 3)
1330unset -v 'a2[1]'
1331a3=(1 2 4)
1332unset -v 'a3[1]'
1333a4=(1 2 3)
1334var a1 = _a2sp(a1)
1335var a2 = _a2sp(a2)
1336var a3 = _a2sp(a3)
1337var a4 = _a2sp(a4)
1338
1339echo $[a1 === a1]
1340echo $[a1 === a2]
1341echo $[a1 === a3]
1342echo $[a1 === a4]
1343echo $[a2 === a1]
1344echo $[a3 === a1]
1345echo $[a4 === a1]
1346
1347## STDOUT:
1348true
1349true
1350false
1351false
1352true
1353false
1354false
1355## END
1356
1357## N-I bash/zsh/mksh/ash STDOUT:
1358## END
1359
1360
1361#### SparseArray (YSH): append v1 v2... (a)
1362case $SH in bash|zsh|mksh|ash) exit ;; esac
1363
1364a=(1 2 3)
1365unset -v 'a[1]'
1366var a = _a2sp(a)
1367append 'x' 'y' 'z' (a)
1368= a
1369
1370## STDOUT:
1371(SparseArray [0]='1' [2]='3' [3]='x' [4]='y' [5]='z')
1372## END
1373
1374## N-I bash/zsh/mksh/ash STDOUT:
1375## END
1376
1377
1378#### SparseArray (YSH): $[bool(a)]
1379case $SH in bash|zsh|mksh|ash) exit ;; esac
1380
1381a1=()
1382a2=(0)
1383a3=(0 1 2)
1384a4=(0 0)
1385unset -v 'a4[0]'
1386var a1 = _a2sp(a1)
1387var a2 = _a2sp(a2)
1388var a3 = _a2sp(a3)
1389var a4 = _a2sp(a4)
1390
1391echo $[bool(a1)]
1392echo $[bool(a2)]
1393echo $[bool(a3)]
1394echo $[bool(a4)]
1395
1396## STDOUT:
1397false
1398true
1399true
1400true
1401## END
1402
1403## N-I bash/zsh/mksh/ash STDOUT:
1404## END
1405
1406
1407#### SparseArray: crash dump
1408case $SH in bash|zsh|mksh|ash) exit ;; esac
1409
1410OILS_CRASH_DUMP_DIR=$TMP $SH -ec 'a=({0..3}); unset -v "a[2]"; var a = _a2sp(a); false'
1411json read (&crash_dump) < $TMP/*.json
1412json write (crash_dump.var_stack[0].a)
1413
1414## STDOUT:
1415{
1416 "val": {
1417 "type": "SparseArray",
1418 "data": {
1419 "0": "0",
1420 "1": "1",
1421 "3": "3"
1422 }
1423 }
1424}
1425## END
1426
1427## N-I bash/zsh/mksh/ash STDOUT:
1428## END