1 ## oils_cpp_failures_allowed: 2
2
3 #### recursive arith: one level
4 a='b=123'
5 echo $((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
12 a='b=c' c='d=123'
13 echo $((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.
24 a=b=123
25 echo $((1||a)):$((b))
26 echo $((0||a)):$((b))
27 c=d=321
28 echo $((0&&c)):$((d))
29 echo $((1&&c)):$((d))
30 ## STDOUT:
31 1:0
32 1:123
33 0:0
34 1:321
35 ## END
36
37 ## BUG mksh/ash STDOUT:
38 1:123
39 1:123
40 0:321
41 1:321
42 ## END
43
44 ## N-I dash/yash status: 2
45 ## N-I dash/yash STDOUT:
46 1:0
47 ## END
48
49 #### recursive arith: short circuit ?:
50 # Note: "busybox sh" behaves strangely.
51 y=a=123 n=a=321
52 echo $((1?(y):(n))):$((a))
53 echo $((0?(y):(n))):$((a))
54 ## STDOUT:
55 123:123
56 321:321
57 ## END
58 ## BUG ash STDOUT:
59 123:321
60 321:321
61 ## END
62 ## N-I dash status: 2
63 ## N-I dash stdout-json: ""
64 ## N-I yash STDOUT:
65 a=123:0
66 a=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.
72 a='b=c' c='d=123'
73 echo $((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
80 loop='i<=100&&(s+=i,i++,loop)' s=0 i=0
81 echo $((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
89 text[1]='d=123'
90 text[2]='text[1]'
91 text[3]='text[2]'
92 echo $((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
98 vec2_set () {
99 local this=$1 x=$2 y=$3
100 : $(( ${this}_x = $2 ))
101 : $(( ${this}_y = y ))
102 }
103 vec2_set a 3 4
104 vec2_set b 5 12
105 echo a_x=$a_x a_y=$a_y
106 echo b_x=$b_x b_y=$b_y
107 ## STDOUT:
108 a_x=3 a_y=4
109 b_x=5 b_y=12
110 ## END
111
112 #### dynamic arith varname: read
113
114 vec2_load() {
115 local this=$1
116 x=$(( ${this}_x ))
117 : $(( y = ${this}_y ))
118 }
119 a_x=12 a_y=34
120 vec2_load a
121 echo x=$x y=$y
122 ## STDOUT:
123 x=12 y=34
124 ## END
125
126 #### dynamic arith varname: copy/add
127 shopt -s eval_unsafe_arith # for RHS
128
129 vec2_copy () {
130 local this=$1 rhs=$2
131 : $(( ${this}_x = $(( ${rhs}_x )) ))
132 : $(( ${this}_y = ${rhs}_y ))
133 }
134 vec2_add () {
135 local this=$1 rhs=$2
136 : $(( ${this}_x += $(( ${rhs}_x )) ))
137 : $(( ${this}_y += ${rhs}_y ))
138 }
139 a_x=3 a_y=4
140 b_x=4 b_y=20
141 vec2_copy c a
142 echo c_x=$c_x c_y=$c_y
143 vec2_add c b
144 echo c_x=$c_x c_y=$c_y
145 ## STDOUT:
146 c_x=3 c_y=4
147 c_x=7 c_y=24
148 ## END
149
150 #### is-array with ${var@a}
151 case $SH in (mksh|ash|dash|yash) exit 1 ;; esac
152
153 function ble/is-array { [[ ${!1@a} == *a* ]]; }
154
155 ble/is-array undef
156 echo undef $?
157
158 string=''
159 ble/is-array string
160 echo string $?
161
162 array=(one two three)
163 ble/is-array array
164 echo array $?
165 ## STDOUT:
166 undef 1
167 string 1
168 array 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
178 a=()
179
180 if false; then
181 # This takes too long! # From Zulip
182 i=$(( 0x0100000000000000 ))
183 else
184 # smaller number that's OK
185 i=$(( 0x0100000 ))
186 fi
187
188 a[i]=1
189
190 echo len=${#a[@]}
191
192 ## STDOUT:
193 len=1
194 ## END
195
196 ## N-I ash status: 2
197 ## N-I ash STDOUT:
198 ## END
199
200 ## BUG zsh STDOUT:
201 len=1048576
202 ## END
203
204
205 #### shift unshift reverse
206
207 case $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...
212 function ble/array#unshift {
213 builtin eval -- "$1=(\"\${@:2}\" \"\${$1[@]}\")"
214 }
215 # @fn ble/array#shift arr count
216 function 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
222 function 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
229 a=( {1..6} )
230 echo "${a[@]}"
231
232 ble/array#shift a 1
233 echo "${a[@]}"
234
235 ble/array#shift a 2
236 echo "${a[@]}"
237
238 echo ---
239
240 ble/array#unshift a 99
241 echo "${a[@]}"
242
243 echo ---
244
245 # doesn't work in zsh!
246 ble/array#reverse a
247 echo "${a[@]}"
248
249
250 ## STDOUT:
251 1 2 3 4 5 6
252 2 3 4 5 6
253 4 5 6
254 ---
255 99 4 5 6
256 ---
257 6 5 4 99
258 ## END
259
260 ## BUG zsh STDOUT:
261 1 2 3 4 5 6
262 2 3 4 5 6
263 4 5 6
264 ---
265 99 4 5 6
266 ---
267 5 4 99
268 ## END
269
270 ## N-I mksh/ash STDOUT:
271 ## END
272
273
274 #### SparseArray Performance demo
275
276 case $SH in bash|zsh|mksh|ash) exit ;; esac
277
278 #pp test_ (a)
279
280 a=( foo {25..27} bar )
281
282 a[10]='sparse'
283
284 var sp = _a2sp(a)
285 echo $[type(sp)]
286
287 echo len: $[_opsp(sp, 'len')]
288
289 #echo $[len(sp)]
290
291 shopt -s ysh:upgrade
292
293 echo subst: @[_opsp(sp, 'subst')]
294 echo keys: @[_opsp(sp, 'keys')]
295
296 echo slice: @[_opsp(sp, 'slice', 2, 5)]
297
298 call _opsp(sp, 'set', 0, 'set0')
299
300 echo get0: $[_opsp(sp, 'get', 0)]
301 echo get1: $[_opsp(sp, 'get', 1)]
302 echo ---
303
304 to_append=(x y)
305 echo append
306 call _opsp(sp, 'append', to_append)
307 echo subst: @[_opsp(sp, 'subst')]
308 echo keys: @[_opsp(sp, 'keys')]
309 echo ---
310
311 echo unset
312 call _opsp(sp, 'unset', 11)
313 echo subst: @[_opsp(sp, 'subst')]
314 echo keys: @[_opsp(sp, 'keys')]
315
316 ## STDOUT:
317 SparseArray
318 len: 6
319 subst: foo 25 26 27 bar sparse
320 keys: 0 1 2 3 4 10
321 slice: 26 27 bar
322 get0: set0
323 get1: 25
324 ---
325 append
326 subst: set0 25 26 27 bar sparse x y
327 keys: 0 1 2 3 4 10 11 12
328 ---
329 unset
330 subst: set0 25 26 27 bar sparse y
331 keys: 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
339 case $SH in bash|zsh|mksh|ash) exit ;; esac
340
341 declare -a a=(x y z)
342
343 a[5]=z
344 var sp = _a2sp(a)
345
346 echo len=${#sp[@]}
347
348 a[10]=z
349 var sp = _a2sp(a)
350
351 echo len=${#sp[@]}
352
353
354 ## STDOUT:
355 len=4
356 len=5
357 ## END
358
359 ## N-I bash/zsh/mksh/ash STDOUT:
360 ## END
361
362
363 #### SparseArray: test "declare -p sp"
364 case $SH in zsh|ash) exit ;; esac
365
366 a0=()
367 a1=(1)
368 a2=(1 2)
369 a=(x y z w)
370 a[500]=100
371 a[1000]=100
372
373 case $SH in
374 bash|mksh)
375 typeset -p a0 a1 a2 a
376 exit ;;
377 esac
378
379 var a0 = _a2sp(a0)
380 var a1 = _a2sp(a1)
381 var a2 = _a2sp(a2)
382 var sp = _a2sp(a)
383 declare -p a0 a1 a2 sp
384
385 ## STDOUT:
386 declare -a a0=()
387 declare -a a1=([0]=1)
388 declare -a a2=([0]=1 [1]=2)
389 declare -a sp=([0]=x [1]=y [2]=z [3]=w [500]=100 [1000]=100)
390 ## END
391
392 ## OK bash STDOUT:
393 declare -a a0=()
394 declare -a a1=([0]="1")
395 declare -a a2=([0]="1" [1]="2")
396 declare -a a=([0]="x" [1]="y" [2]="z" [3]="w" [500]="100" [1000]="100")
397 ## END
398
399 ## OK mksh STDOUT:
400 set -A a1
401 typeset a1[0]=1
402 set -A a2
403 typeset a2[0]=1
404 typeset a2[1]=2
405 set -A a
406 typeset a[0]=x
407 typeset a[1]=y
408 typeset a[2]=z
409 typeset a[3]=w
410 typeset a[500]=100
411 typeset a[1000]=100
412 ## END
413
414 ## N-I zsh/ash STDOUT:
415 ## END
416
417 #### SparseArray: +=
418 case $SH in bash|zsh|mksh|ash) exit ;; esac
419
420 sp1[10]=a
421 sp1[20]=b
422 sp1[99]=c
423 var sp1 = _a2sp(sp1)
424 declare -p sp1
425 sp1+=(1 2 3)
426 declare -p sp1
427
428 ## STDOUT:
429 declare -a sp1=([10]=a [20]=b [99]=c)
430 declare -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
438 case $SH in bash|zsh|mksh|ash) exit ;; esac
439
440 sp1[10]=a
441 sp1[20]=b
442 sp1[30]=c
443 var sp1 = _a2sp(sp1)
444 declare -p sp1
445 sp1[10]=X
446 sp1[25]=Y
447 sp1[90]=Z
448 declare -p sp1
449
450 ## STDOUT:
451 declare -a sp1=([10]=a [20]=b [30]=c)
452 declare -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
460 case $SH in bash|zsh|mksh|ash) exit ;; esac
461
462 sp1[9]=x
463 var sp1 = _a2sp(sp1)
464
465 declare -p sp1
466 sp1[-1]=A
467 sp1[-4]=B
468 sp1[-8]=C
469 sp1[-10]=D
470 declare -p sp1
471
472 ## STDOUT:
473 declare -a sp1=([9]=x)
474 declare -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
482 case $SH in zsh|mksh|ash) exit ;; esac
483
484 sp1[1]=x
485 sp1[5]=y
486 sp1[9]=z
487 case ${SH##*/} in osh) eval 'var sp1 = _a2sp(sp1)' ;; esac
488
489 echo "${#sp1[@]}"
490 sp1[0x7FFFFFFFFFFFFFFF]=a
491 echo "${#sp1[@]}"
492 sp1[0x7FFFFFFFFFFFFFFE]=b
493 echo "${#sp1[@]}"
494 sp1[0x7FFFFFFFFFFFFFFD]=c
495 echo "${#sp1[@]}"
496
497 ## STDOUT:
498 3
499 4
500 5
501 6
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)
509 case $SH in bash|zsh|mksh|ash) exit ;; esac
510
511 sp1[9]=x
512 var sp1 = _a2sp(sp1)
513
514 sp1[-11]=E
515 declare -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)
532 case $SH in bash|zsh|mksh|ash) exit ;; esac
533
534 sp1[9]=x
535 var sp1 = _a2sp(sp1)
536
537 sp1[-21]=F
538 declare -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+=()
555 case $SH in bash|zsh|mksh|ash) exit ;; esac
556
557 sp1=(1)
558 var sp1 = _a2sp(sp1)
559 set -x
560 sp1+=(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]
571 case $SH in bash|zsh|mksh|ash) exit ;; esac
572
573 a=({1..9})
574 var a = _a2sp(a)
575
576 declare -p a
577 unset -v "a[1]"
578 declare -p a
579 unset -v "a[9]"
580 declare -p a
581 unset -v "a[0]"
582 declare -p a
583
584 ## STDOUT:
585 declare -a a=([0]=1 [1]=2 [2]=3 [3]=4 [4]=5 [5]=6 [6]=7 [7]=8 [8]=9)
586 declare -a a=([0]=1 [2]=3 [3]=4 [4]=5 [5]=6 [6]=7 [7]=8 [8]=9)
587 declare -a a=([0]=1 [2]=3 [3]=4 [4]=5 [5]=6 [6]=7 [7]=8 [8]=9)
588 declare -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
596 case $SH in bash|zsh|mksh|ash) exit ;; esac
597
598 a=(1)
599 var a = _a2sp(a)
600
601 unset -v "a[-2]"
602 unset -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
622 case $SH in bash|zsh|mksh|ash) exit ;; esac
623
624 a=({1..9})
625 unset -v 'a[-1]'
626 a[-1]=x
627 declare -p a
628 unset -v 'a[-1]'
629 a[-1]=x
630 declare -p a
631
632 ## STDOUT:
633 declare -a a=(1 2 3 4 5 6 7 x)
634 declare -a a=(1 2 3 4 5 6 x)
635 ## END
636
637 ## N-I bash/zsh/mksh/ash STDOUT:
638 ## END
639
640
641 #### SparseArray: [[ -v a[i] ]]
642 case $SH in bash|zsh|mksh|ash) exit ;; esac
643
644 a=()
645 var sp1 = _a2sp(a)
646 [[ -v sp1[0] ]]; echo "$? (expect 1)"
647 [[ -v sp1[9] ]]; echo "$? (expect 1)"
648
649 a=({1..9})
650 var sp2 = _a2sp(a)
651 [[ -v sp2[0] ]]; echo "$? (expect 0)"
652 [[ -v sp2[8] ]]; echo "$? (expect 0)"
653 [[ -v sp2[9] ]]; echo "$? (expect 1)"
654 [[ -v sp2[-1] ]]; echo "$? (expect 0)"
655 [[ -v sp2[-2] ]]; echo "$? (expect 0)"
656 [[ -v sp2[-9] ]]; echo "$? (expect 0)"
657
658 unset -v 'a[4]'
659 var sp3 = _a2sp(a)
660 [[ -v sp3[3] ]]; echo "$? (expect 0)"
661 [[ -v sp3[4] ]]; echo "$? (expect 1)"
662 [[ -v sp3[5] ]]; echo "$? (expect 0)"
663 [[ -v sp3[-1] ]]; echo "$? (expect 0)"
664 [[ -v sp3[-4] ]]; echo "$? (expect 0)"
665 [[ -v sp3[-5] ]]; echo "$? (expect 1)"
666 [[ -v sp3[-6] ]]; echo "$? (expect 0)"
667 [[ -v sp3[-9] ]]; echo "$? (expect 0)"
668
669 ## STDOUT:
670 1 (expect 1)
671 1 (expect 1)
672 0 (expect 0)
673 0 (expect 0)
674 1 (expect 1)
675 0 (expect 0)
676 0 (expect 0)
677 0 (expect 0)
678 0 (expect 0)
679 1 (expect 1)
680 0 (expect 0)
681 0 (expect 0)
682 0 (expect 0)
683 1 (expect 1)
684 0 (expect 0)
685 0 (expect 0)
686 ## END
687
688 ## N-I bash/zsh/mksh/ash STDOUT:
689 ## END
690
691
692 #### SparseArray: [[ -v a[i] ]] with invalid negative index
693 case $SH in bash|zsh|mksh|ash) exit ;; esac
694
695 a=()
696 var sp1 = _a2sp(a)
697 ([[ -v sp1[-1] ]]; echo "$? (expect 1)")
698 a=({1..9})
699 var sp2 = _a2sp(a)
700 ([[ -v sp2[-10] ]]; echo "$? (expect 1)")
701 var sp3 = _a2sp(a)
702 ([[ -v sp3[-10] ]]; echo "$? (expect 1)")
703
704 ## status: 1
705 ## STDOUT:
706 ## END
707 ## STDERR:
708 ([[ -v sp1[-1] ]]; echo "$? (expect 1)")
709 ^~~
710 [ stdin ]:5: fatal: -v got index -1, which is out of bounds for array of length 0
711 ([[ -v sp2[-10] ]]; echo "$? (expect 1)")
712 ^~~
713 [ stdin ]:8: fatal: -v got index -10, which is out of bounds for array of length 9
714 ([[ -v sp3[-10] ]]; echo "$? (expect 1)")
715 ^~~
716 [ stdin ]:10: fatal: -v got index -10, which is out of bounds for array of length 9
717 ## END
718
719 ## N-I bash/zsh/mksh/ash status: 0
720 ## N-I bash/zsh/mksh/ash STDERR:
721 ## END
722
723
724 #### SparseArray: ((sp[i])) and ((sp[i]++))
725 case $SH in zsh|mksh|ash) exit ;; esac
726
727 a=({1..9})
728 unset -v 'a[2]' 'a[3]' 'a[7]'
729 case $SH in osh) eval 'var a = _a2sp(a)' ;; esac
730
731 echo $((a[0]))
732 echo $((a[1]))
733 echo $((a[2]))
734 echo $((a[3]))
735 echo $((a[7]))
736
737 echo $((a[1]++))
738 echo $((a[2]++))
739 echo $((a[3]++))
740 echo $((a[7]++))
741
742 echo $((++a[1]))
743 echo $((++a[2]))
744 echo $((++a[3]))
745 echo $((++a[7]))
746
747 echo $((a[1] = 100, a[1]))
748 echo $((a[2] = 100, a[2]))
749 echo $((a[3] = 100, a[3]))
750 echo $((a[7] = 100, a[7]))
751
752 ## STDOUT:
753 1
754 2
755 0
756 0
757 0
758 2
759 0
760 0
761 0
762 4
763 2
764 2
765 2
766 100
767 100
768 100
769 100
770 ## END
771
772 ## N-I zsh/mksh/ash STDOUT:
773 ## END
774
775
776 #### SparseArray: ((sp[i])) and ((sp[i]++)) with invalid negative index
777 case $SH in zsh|mksh|ash) exit ;; esac
778
779 a=({1..9})
780 unset -v 'a[2]' 'a[3]' 'a[7]'
781 case $SH in osh) eval 'var a = _a2sp(a)' ;; esac
782
783 echo $((a[-10]))
784
785 ## STDOUT:
786 0
787 ## END
788 ## STDERR:
789 echo $((a[-10]))
790 ^
791 [ stdin ]:7: Index -10 out of bounds for array of length 9
792 ## END
793
794 ## OK bash STDERR:
795 bash: line 7: a: bad array subscript
796 ## END
797
798 ## N-I zsh/mksh/ash STDOUT:
799 ## END
800 ## N-I zsh/mksh/ash STDERR:
801 ## END
802
803
804 #### SparseArray: ${sp[i]}
805 case $SH in bash|zsh|mksh|ash) exit ;; esac
806
807 a=({1..9})
808 unset -v 'a[2]'
809 unset -v 'a[3]'
810 unset -v 'a[7]'
811 var sp = _a2sp(a)
812
813 echo "sp[0]: '${sp[0]}', ${sp[0]:-(empty)}, ${sp[0]+set}."
814 echo "sp[1]: '${sp[1]}', ${sp[1]:-(empty)}, ${sp[1]+set}."
815 echo "sp[8]: '${sp[8]}', ${sp[8]:-(empty)}, ${sp[8]+set}."
816 echo "sp[2]: '${sp[2]}', ${sp[2]:-(empty)}, ${sp[2]+set}."
817 echo "sp[3]: '${sp[3]}', ${sp[3]:-(empty)}, ${sp[3]+set}."
818 echo "sp[7]: '${sp[7]}', ${sp[7]:-(empty)}, ${sp[7]+set}."
819
820 echo "sp[-1]: '${sp[-1]}'."
821 echo "sp[-2]: '${sp[-2]}'."
822 echo "sp[-3]: '${sp[-3]}'."
823 echo "sp[-4]: '${sp[-4]}'."
824 echo "sp[-9]: '${sp[-9]}'."
825
826 ## STDOUT:
827 sp[0]: '1', 1, set.
828 sp[1]: '2', 2, set.
829 sp[8]: '9', 9, set.
830 sp[2]: '', (empty), .
831 sp[3]: '', (empty), .
832 sp[7]: '', (empty), .
833 sp[-1]: '9'.
834 sp[-2]: ''.
835 sp[-3]: '7'.
836 sp[-4]: '6'.
837 sp[-9]: '1'.
838 ## END
839
840 ## N-I bash/zsh/mksh/ash STDOUT:
841 ## END
842
843
844 #### SparseArray: ${sp[i]} with negative invalid index
845 case $SH in bash|zsh|mksh|ash) exit ;; esac
846
847 a=({1..9})
848 unset -v 'a[2]'
849 unset -v 'a[3]'
850 unset -v 'a[7]'
851 var sp = _a2sp(a)
852
853 echo "sp[-10]: '${sp[-10]}'."
854 echo "sp[-11]: '${sp[-11]}'."
855 echo "sp[-19]: '${sp[-19]}'."
856
857 ## STDOUT:
858 sp[-10]: ''.
859 sp[-11]: ''.
860 sp[-19]: ''.
861 ## END
862 ## STDERR:
863 echo "sp[-10]: '${sp[-10]}'."
864 ^~
865 [ stdin ]:9: Index -10 out of bounds for array of length 9
866 echo "sp[-11]: '${sp[-11]}'."
867 ^~
868 [ stdin ]:10: Index -11 out of bounds for array of length 9
869 echo "sp[-19]: '${sp[-19]}'."
870 ^~
871 [ stdin ]:11: Index -19 out of bounds for array of length 9
872 ## END
873
874 ## N-I bash/zsh/mksh/ash STDOUT:
875 ## END
876 ## N-I bash/zsh/mksh/ash STDERR:
877 ## END
878
879
880 #### SparseArray (YSH): @[sp] and @sp
881 case $SH in bash|zsh|mksh|ash) exit ;; esac
882
883 a=({0..5})
884 unset -v 'a[1]' 'a[2]' 'a[4]'
885 var a = _a2sp(a)
886
887 shopt -s parse_at
888 argv.py @[a]
889 argv.py @a
890 ## STDOUT:
891 ['0', '3', '5']
892 ['0', '3', '5']
893 ## END
894
895 ## N-I bash/zsh/mksh/ash STDOUT:
896 ## END
897
898
899 #### SparseArray: ${a[@]:offset:length}
900 case $SH in zsh|mksh|ash) exit ;; esac
901
902 a=(v{0..9})
903 unset -v 'a[2]' 'a[3]' 'a[4]' 'a[7]'
904 case ${SH##*/} in osh) eval 'var a = _a2sp(a)' ;; esac
905
906 echo '==== ${a[@]:offset} ===='
907 echo "[${a[@]:0}][${a[*]:0}]"
908 echo "[${a[@]:2}][${a[*]:2}]"
909 echo "[${a[@]:3}][${a[*]:3}]"
910 echo "[${a[@]:5}][${a[*]:5}]"
911 echo "[${a[@]:9}][${a[*]:9}]"
912 echo "[${a[@]:10}][${a[*]:10}]"
913 echo "[${a[@]:11}][${a[*]:11}]"
914
915 echo '==== ${a[@]:negative} ===='
916 echo "[${a[@]: -1}][${a[*]: -1}]"
917 echo "[${a[@]: -2}][${a[*]: -2}]"
918 echo "[${a[@]: -5}][${a[*]: -5}]"
919 echo "[${a[@]: -9}][${a[*]: -9}]"
920 echo "[${a[@]: -10}][${a[*]: -10}]"
921 echo "[${a[@]: -11}][${a[*]: -11}]"
922 echo "[${a[@]: -21}][${a[*]: -21}]"
923
924 echo '==== ${a[@]:offset:length} ===='
925 echo "[${a[@]:0:0}][${a[*]:0:0}]"
926 echo "[${a[@]:0:1}][${a[*]:0:1}]"
927 echo "[${a[@]:0:3}][${a[*]:0:3}]"
928 echo "[${a[@]:2:1}][${a[*]:2:1}]"
929 echo "[${a[@]:2:4}][${a[*]:2:4}]"
930 echo "[${a[@]:3:4}][${a[*]:3:4}]"
931 echo "[${a[@]:5:4}][${a[*]:5:4}]"
932 echo "[${a[@]:5:0}][${a[*]:5:0}]"
933 echo "[${a[@]:9:1}][${a[*]:9:1}]"
934 echo "[${a[@]:9:2}][${a[*]:9:2}]"
935 echo "[${a[@]:10:1}][${a[*]:10:1}]"
936
937 ## STDOUT:
938 ==== ${a[@]:offset} ====
939 [v0 v1 v5 v6 v8 v9][v0 v1 v5 v6 v8 v9]
940 [v5 v6 v8 v9][v5 v6 v8 v9]
941 [v5 v6 v8 v9][v5 v6 v8 v9]
942 [v5 v6 v8 v9][v5 v6 v8 v9]
943 [v9][v9]
944 [][]
945 [][]
946 ==== ${a[@]:negative} ====
947 [v9][v9]
948 [v8 v9][v8 v9]
949 [v5 v6 v8 v9][v5 v6 v8 v9]
950 [v1 v5 v6 v8 v9][v1 v5 v6 v8 v9]
951 [v0 v1 v5 v6 v8 v9][v0 v1 v5 v6 v8 v9]
952 [][]
953 [][]
954 ==== ${a[@]:offset:length} ====
955 [][]
956 [v0][v0]
957 [v0 v1 v5][v0 v1 v5]
958 [v5][v5]
959 [v5 v6 v8 v9][v5 v6 v8 v9]
960 [v5 v6 v8 v9][v5 v6 v8 v9]
961 [v5 v6 v8 v9][v5 v6 v8 v9]
962 [][]
963 [v9][v9]
964 [v9][v9]
965 [][]
966 ## END
967
968 ## N-I zsh/mksh/ash STDOUT:
969 ## END
970
971
972 #### ${@:offset:length}
973 case $SH in zsh|mksh|ash) exit ;; esac
974
975 set -- v{1..9}
976
977 {
978 echo '==== ${@:offset:length} ===='
979 echo "[${*:0:3}][${*:0:3}]"
980 echo "[${*:1:3}][${*:1:3}]"
981 echo "[${*:3:3}][${*:3:3}]"
982 echo "[${*:5:10}][${*:5:10}]"
983
984 echo '==== ${@:negative} ===='
985 echo "[${*: -1}][${*: -1}]"
986 echo "[${*: -3}][${*: -3}]"
987 echo "[${*: -9}][${*: -9}]"
988 echo "[${*: -10}][${*: -10}]"
989 echo "[${*: -11}][${*: -11}]"
990 echo "[${*: -3:2}][${*: -3:2}]"
991 echo "[${*: -9:4}][${*: -9:4}]"
992 echo "[${*: -10:4}][${*: -10:4}]"
993 echo "[${*: -11:4}][${*: -11:4}]"
994 } | sed "s:$SH:\$SH:g;s:${SH##*/}:\$SH:g"
995
996 ## STDOUT:
997 ==== ${@:offset:length} ====
998 [$SH v1 v2][$SH v1 v2]
999 [v1 v2 v3][v1 v2 v3]
1000 [v3 v4 v5][v3 v4 v5]
1001 [v5 v6 v7 v8 v9][v5 v6 v7 v8 v9]
1002 ==== ${@:negative} ====
1003 [v9][v9]
1004 [v7 v8 v9][v7 v8 v9]
1005 [v1 v2 v3 v4 v5 v6 v7 v8 v9][v1 v2 v3 v4 v5 v6 v7 v8 v9]
1006 [$SH v1 v2 v3 v4 v5 v6 v7 v8 v9][$SH v1 v2 v3 v4 v5 v6 v7 v8 v9]
1007 [][]
1008 [v7 v8][v7 v8]
1009 [v1 v2 v3 v4][v1 v2 v3 v4]
1010 [$SH v1 v2 v3][$SH v1 v2 v3]
1011 [][]
1012 ## END
1013
1014 ## N-I zsh/mksh/ash STDOUT:
1015 ## END
1016
1017
1018 #### SparseArray: ${a[@]:BigInt}
1019 case $SH in zsh|mksh|ash) exit ;; esac
1020
1021 case $SH in
1022 bash)
1023 # Work around bash integer overflow bug that only happens on say Debian 10,
1024 # but NOT Debian 12. The bug exists in bash 5.2. It's unclear why it
1025 # depends on the OS version.
1026 v='/etc/debian_version'
1027 # debian version 10 / debian buster
1028 if test -f $v && grep -E 'buster/sid|^10' $v >/dev/null; then
1029 cat << 'EOF'
1030 [x][x]
1031 [y x][y x]
1032 [z y x][z y x]
1033 [z y x][z y x]
1034 EOF
1035 exit
1036 fi
1037 # Actual STDOUT of buggy bash builds:
1038 # [][]
1039 # [][]
1040 # [][]
1041 # [][]
1042 ;;
1043 esac
1044
1045 a=(1 2 3)
1046 case ${SH##*/} in osh) eval 'var a = _a2sp(a)' ;; esac
1047 a[0x7FFFFFFFFFFFFFFF]=x
1048 a[0x7FFFFFFFFFFFFFFE]=y
1049 a[0x7FFFFFFFFFFFFFFD]=z
1050
1051 echo "[${a[@]: -1}][${a[*]: -1}]"
1052 echo "[${a[@]: -2}][${a[*]: -2}]"
1053 echo "[${a[@]: -3}][${a[*]: -3}]"
1054 echo "[${a[@]: -4}][${a[*]: -4}]"
1055
1056 ## STDOUT:
1057 [x][x]
1058 [y x][y x]
1059 [z y x][z y x]
1060 [z y x][z y x]
1061 ## END
1062
1063 ## N-I zsh/mksh/ash STDOUT:
1064 ## END
1065
1066
1067 #### SparseArray: ${a[@]}
1068
1069 case $SH in zsh|mksh|ash) exit ;; esac
1070
1071 a=(v{0..9})
1072 unset -v 'a[2]' 'a[3]' 'a[4]' 'a[7]'
1073 case ${SH##*/} in osh) eval 'var a = _a2sp(a)' ;; esac
1074
1075 argv.py "${a[@]}"
1076 argv.py "abc${a[@]}xyz"
1077
1078 ## STDOUT:
1079 ['v0', 'v1', 'v5', 'v6', 'v8', 'v9']
1080 ['abcv0', 'v1', 'v5', 'v6', 'v8', 'v9xyz']
1081 ## END
1082
1083 ## N-I zsh/mksh/ash STDOUT:
1084 ## END
1085
1086
1087 #### SparseArray: ${a[@]#...}
1088
1089 case $SH in zsh|mksh|ash) exit ;; esac
1090
1091 a=(v{0..9})
1092 unset -v 'a[2]' 'a[3]' 'a[4]' 'a[7]'
1093 case ${SH##*/} in osh) eval 'var a = _a2sp(a)' ;; esac
1094
1095 argv.py "${a[@]#v}"
1096 argv.py "abc${a[@]#v}xyz"
1097 argv.py "${a[@]%[0-5]}"
1098 argv.py "abc${a[@]%[0-5]}xyz"
1099 argv.py "${a[@]#v?}"
1100
1101 ## STDOUT:
1102 ['0', '1', '5', '6', '8', '9']
1103 ['abc0', '1', '5', '6', '8', '9xyz']
1104 ['v', 'v', 'v', 'v6', 'v8', 'v9']
1105 ['abcv', 'v', 'v', 'v6', 'v8', 'v9xyz']
1106 ['', '', '', '', '', '']
1107 ## END
1108
1109 ## N-I zsh/mksh/ash STDOUT:
1110 ## END
1111
1112
1113 #### SparseArray: ${a[@]/pat/rep}
1114
1115 case $SH in zsh|mksh|ash) exit ;; esac
1116
1117 a=(v{0..9})
1118 unset -v 'a[2]' 'a[3]' 'a[4]' 'a[7]'
1119 case ${SH##*/} in osh) eval 'var a = _a2sp(a)' ;; esac
1120
1121 argv.py "${a[@]/?}"
1122 argv.py "${a[@]//?}"
1123 argv.py "${a[@]/#?}"
1124 argv.py "${a[@]/%?}"
1125
1126 argv.py "${a[@]/v/x}"
1127 argv.py "${a[@]//v/x}"
1128 argv.py "${a[@]/[0-5]/D}"
1129 argv.py "${a[@]//[!0-5]/_}"
1130
1131 ## STDOUT:
1132 ['0', '1', '5', '6', '8', '9']
1133 ['', '', '', '', '', '']
1134 ['0', '1', '5', '6', '8', '9']
1135 ['v', 'v', 'v', 'v', 'v', 'v']
1136 ['x0', 'x1', 'x5', 'x6', 'x8', 'x9']
1137 ['x0', 'x1', 'x5', 'x6', 'x8', 'x9']
1138 ['vD', 'vD', 'vD', 'v6', 'v8', 'v9']
1139 ['_0', '_1', '_5', '__', '__', '__']
1140 ## END
1141
1142 ## N-I zsh/mksh/ash STDOUT:
1143 ## END
1144
1145
1146 #### SparseArray: ${a[@]@P}, ${a[@]@Q}, and ${a[@]@a}
1147 case $SH in zsh|mksh|ash) exit ;; esac
1148
1149 a=(v{0..9})
1150 unset -v 'a[2]' 'a[3]' 'a[4]' 'a[7]'
1151 case ${SH##*/} in osh) eval 'var a = _a2sp(a)' ;; esac
1152
1153 argv.py "${a[@]@P}"
1154 argv.py "${a[*]@P}"
1155 argv.py "${a[@]@Q}"
1156 argv.py "${a[*]@Q}"
1157 argv.py "${a[@]@a}"
1158 argv.py "${a[*]@a}"
1159
1160 ## STDOUT:
1161 ['v0', 'v1', 'v5', 'v6', 'v8', 'v9']
1162 ['v0 v1 v5 v6 v8 v9']
1163 ['v0', 'v1', 'v5', 'v6', 'v8', 'v9']
1164 ['v0 v1 v5 v6 v8 v9']
1165 ['a', 'a', 'a', 'a', 'a', 'a']
1166 ['a a a a a a']
1167 ## END
1168
1169 ## OK bash STDOUT:
1170 ['v0', 'v1', 'v5', 'v6', 'v8', 'v9']
1171 ['v0 v1 v5 v6 v8 v9']
1172 ["'v0'", "'v1'", "'v5'", "'v6'", "'v8'", "'v9'"]
1173 ["'v0' 'v1' 'v5' 'v6' 'v8' 'v9'"]
1174 ['a', 'a', 'a', 'a', 'a', 'a']
1175 ['a a a a a a']
1176 ## END
1177
1178 ## N-I zsh/mksh/ash STDOUT:
1179 ## END
1180
1181
1182 #### SparseArray: ${a[@]-unset}, ${a[@]:-empty}, etc.
1183 case $SH in zsh|mksh|ash) exit ;; esac
1184
1185 a1=()
1186 a2=("")
1187 a3=("" "")
1188
1189 case $SH in
1190 bash) ;;
1191 *) eval "var a1 = _a2sp(a1); var a2 = _a2sp(a2); var a3 = _a2sp(a3)" ;;
1192 esac
1193
1194 echo "a1 unset: [${a1[@]-unset}]"
1195 echo "a1 empty: [${a1[@]:-empty}]"
1196 echo "a2 unset: [${a2[@]-unset}]"
1197 echo "a2 empty: [${a2[@]:-empty}]"
1198 echo "a3 unset: [${a3[@]-unset}]"
1199 echo "a3 empty: [${a3[@]:-empty}]"
1200
1201 ## STDOUT:
1202 a1 unset: [unset]
1203 a1 empty: [empty]
1204 a2 unset: []
1205 a2 empty: [empty]
1206 a3 unset: [ ]
1207 a3 empty: [ ]
1208 ## END
1209
1210 ## N-I zsh/mksh/ash STDOUT:
1211 ## END
1212
1213
1214 #### SparseArray: compgen -F _set_COMPREPLY
1215 case $SH in zsh|mksh|ash) exit ;; esac
1216
1217 a=({0..9})
1218 unset -v 'a[2]' 'a[4]' 'a[6]'
1219
1220 case ${SH##*/} in
1221 osh)
1222 eval '_set_COMPREPLY() { setglobal COMPREPLY = _a2sp(a); }'
1223 ;;
1224 *)
1225 _set_COMPREPLY() { COMPREPLY=("${a[@]}"); }
1226 ;;
1227 esac
1228
1229 compgen -F _set_COMPREPLY
1230
1231 ## STDOUT:
1232 0
1233 1
1234 3
1235 5
1236 7
1237 8
1238 9
1239 ## END
1240
1241 ## N-I zsh/mksh/ash STDOUT:
1242 ## END
1243
1244
1245 #### SparseArray: compgen -F _set_COMPREPLY
1246 case $SH in bash|zsh|mksh|ash) exit ;; esac
1247
1248 a=(echo 'Hello,' 'Bash' 'world!')
1249 var COMP_ARGV = _a2sp(a)
1250 compadjust cur prev words cword
1251 argv.py "$cur" "$prev" "$cword"
1252 argv.py "${words[@]}"
1253
1254 ## STDOUT:
1255 ['world!', 'Bash', '3']
1256 ['echo', 'Hello,', 'Bash', 'world!']
1257 ## END
1258
1259 ## N-I bash/zsh/mksh/ash STDOUT:
1260 ## END
1261
1262
1263 #### SparseArray (YSH): $[a1 === a2]
1264 case $SH in bash|zsh|mksh|ash) exit ;; esac
1265
1266 a1=(1 2 3)
1267 unset -v 'a1[1]'
1268 a2=(1 2 3)
1269 unset -v 'a2[1]'
1270 a3=(1 2 4)
1271 unset -v 'a3[1]'
1272 a4=(1 2 3)
1273 var a1 = _a2sp(a1)
1274 var a2 = _a2sp(a2)
1275 var a3 = _a2sp(a3)
1276 var a4 = _a2sp(a4)
1277
1278 echo $[a1 === a1]
1279 echo $[a1 === a2]
1280 echo $[a1 === a3]
1281 echo $[a1 === a4]
1282 echo $[a2 === a1]
1283 echo $[a3 === a1]
1284 echo $[a4 === a1]
1285
1286 ## STDOUT:
1287 true
1288 true
1289 false
1290 false
1291 true
1292 false
1293 false
1294 ## END
1295
1296 ## N-I bash/zsh/mksh/ash STDOUT:
1297 ## END
1298
1299
1300 #### SparseArray (YSH): append v1 v2... (a)
1301 case $SH in bash|zsh|mksh|ash) exit ;; esac
1302
1303 a=(1 2 3)
1304 unset -v 'a[1]'
1305 var a = _a2sp(a)
1306 append 'x' 'y' 'z' (a)
1307 = a
1308
1309 ## STDOUT:
1310 (SparseArray [0]='1' [2]='3' [3]='x' [4]='y' [5]='z')
1311 ## END
1312
1313 ## N-I bash/zsh/mksh/ash STDOUT:
1314 ## END
1315
1316
1317 #### SparseArray (YSH): $[bool(a)]
1318 case $SH in bash|zsh|mksh|ash) exit ;; esac
1319
1320 a1=()
1321 a2=(0)
1322 a3=(0 1 2)
1323 a4=(0 0)
1324 unset -v 'a4[0]'
1325 var a1 = _a2sp(a1)
1326 var a2 = _a2sp(a2)
1327 var a3 = _a2sp(a3)
1328 var a4 = _a2sp(a4)
1329
1330 echo $[bool(a1)]
1331 echo $[bool(a2)]
1332 echo $[bool(a3)]
1333 echo $[bool(a4)]
1334
1335 ## STDOUT:
1336 false
1337 true
1338 true
1339 true
1340 ## END
1341
1342 ## N-I bash/zsh/mksh/ash STDOUT:
1343 ## END
1344
1345
1346 #### SparseArray: crash dump
1347 case $SH in bash|zsh|mksh|ash) exit ;; esac
1348
1349 OILS_CRASH_DUMP_DIR=$TMP $SH -ec 'a=({0..3}); unset -v "a[2]"; var a = _a2sp(a); false'
1350 json read (&crash_dump) < $TMP/*.json
1351 json write (crash_dump.var_stack[0].a)
1352
1353 ## STDOUT:
1354 {
1355 "val": {
1356 "type": "SparseArray",
1357 "data": {
1358 "0": "0",
1359 "1": "1",
1360 "3": "3"
1361 }
1362 }
1363 }
1364 ## END
1365
1366 ## N-I bash/zsh/mksh/ash STDOUT:
1367 ## END