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 var a = _a2sp(a)
626 unset -v 'a[-1]'
627 a[-1]=x
628 declare -p a
629 unset -v 'a[-1]'
630 a[-1]=x
631 declare -p a
632
633 ## STDOUT:
634 declare -a a=([0]=1 [1]=2 [2]=3 [3]=4 [4]=5 [5]=6 [6]=7 [7]=x)
635 declare -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] ]]
643 case $SH in bash|zsh|mksh|ash) exit ;; esac
644
645 a=()
646 var sp1 = _a2sp(a)
647 [[ -v sp1[0] ]]; echo "$? (expect 1)"
648 [[ -v sp1[9] ]]; echo "$? (expect 1)"
649
650 a=({1..9})
651 var 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
659 unset -v 'a[4]'
660 var 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:
671 1 (expect 1)
672 1 (expect 1)
673 0 (expect 0)
674 0 (expect 0)
675 1 (expect 1)
676 0 (expect 0)
677 0 (expect 0)
678 0 (expect 0)
679 0 (expect 0)
680 1 (expect 1)
681 0 (expect 0)
682 0 (expect 0)
683 0 (expect 0)
684 1 (expect 1)
685 0 (expect 0)
686 0 (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
694 case $SH in bash|zsh|mksh|ash) exit ;; esac
695
696 a=()
697 var sp1 = _a2sp(a)
698 ([[ -v sp1[-1] ]]; echo "$? (expect 1)")
699 a=({1..9})
700 var sp2 = _a2sp(a)
701 ([[ -v sp2[-10] ]]; echo "$? (expect 1)")
702 var 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]++))
726 case $SH in zsh|mksh|ash) exit ;; esac
727
728 a=({1..9})
729 unset -v 'a[2]' 'a[3]' 'a[7]'
730 case $SH in osh) eval 'var a = _a2sp(a)' ;; esac
731
732 echo $((a[0]))
733 echo $((a[1]))
734 echo $((a[2]))
735 echo $((a[3]))
736 echo $((a[7]))
737
738 echo $((a[1]++))
739 echo $((a[2]++))
740 echo $((a[3]++))
741 echo $((a[7]++))
742
743 echo $((++a[1]))
744 echo $((++a[2]))
745 echo $((++a[3]))
746 echo $((++a[7]))
747
748 echo $((a[1] = 100, a[1]))
749 echo $((a[2] = 100, a[2]))
750 echo $((a[3] = 100, a[3]))
751 echo $((a[7] = 100, a[7]))
752
753 ## STDOUT:
754 1
755 2
756 0
757 0
758 0
759 2
760 0
761 0
762 0
763 4
764 2
765 2
766 2
767 100
768 100
769 100
770 100
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
778 case $SH in zsh|mksh|ash) exit ;; esac
779
780 a=({1..9})
781 unset -v 'a[2]' 'a[3]' 'a[7]'
782 case $SH in osh) eval 'var a = _a2sp(a)' ;; esac
783
784 echo $((a[-10]))
785
786 ## STDOUT:
787 0
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:
796 bash: 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]}
806 case $SH in bash|zsh|mksh|ash) exit ;; esac
807
808 a=({1..9})
809 unset -v 'a[2]'
810 unset -v 'a[3]'
811 unset -v 'a[7]'
812 var sp = _a2sp(a)
813
814 echo "sp[0]: '${sp[0]}', ${sp[0]:-(empty)}, ${sp[0]+set}."
815 echo "sp[1]: '${sp[1]}', ${sp[1]:-(empty)}, ${sp[1]+set}."
816 echo "sp[8]: '${sp[8]}', ${sp[8]:-(empty)}, ${sp[8]+set}."
817 echo "sp[2]: '${sp[2]}', ${sp[2]:-(empty)}, ${sp[2]+set}."
818 echo "sp[3]: '${sp[3]}', ${sp[3]:-(empty)}, ${sp[3]+set}."
819 echo "sp[7]: '${sp[7]}', ${sp[7]:-(empty)}, ${sp[7]+set}."
820
821 echo "sp[-1]: '${sp[-1]}'."
822 echo "sp[-2]: '${sp[-2]}'."
823 echo "sp[-3]: '${sp[-3]}'."
824 echo "sp[-4]: '${sp[-4]}'."
825 echo "sp[-9]: '${sp[-9]}'."
826
827 ## STDOUT:
828 sp[0]: '1', 1, set.
829 sp[1]: '2', 2, set.
830 sp[8]: '9', 9, set.
831 sp[2]: '', (empty), .
832 sp[3]: '', (empty), .
833 sp[7]: '', (empty), .
834 sp[-1]: '9'.
835 sp[-2]: ''.
836 sp[-3]: '7'.
837 sp[-4]: '6'.
838 sp[-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
846 case $SH in bash|zsh|mksh|ash) exit ;; esac
847
848 a=({1..9})
849 unset -v 'a[2]'
850 unset -v 'a[3]'
851 unset -v 'a[7]'
852 var sp = _a2sp(a)
853
854 echo "sp[-10]: '${sp[-10]}'."
855 echo "sp[-11]: '${sp[-11]}'."
856 echo "sp[-19]: '${sp[-19]}'."
857
858 ## STDOUT:
859 sp[-10]: ''.
860 sp[-11]: ''.
861 sp[-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
882 case $SH in bash|zsh|mksh|ash) exit ;; esac
883
884 a=({0..5})
885 unset -v 'a[1]' 'a[2]' 'a[4]'
886 var a = _a2sp(a)
887
888 shopt -s parse_at
889 argv.py @[a]
890 argv.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}
901 case $SH in zsh|mksh|ash) exit ;; esac
902
903 a=(v{0..9})
904 unset -v 'a[2]' 'a[3]' 'a[4]' 'a[7]'
905 case ${SH##*/} in osh) eval 'var a = _a2sp(a)' ;; esac
906
907 echo '==== ${a[@]:offset} ===='
908 echo "[${a[@]:0}][${a[*]:0}]"
909 echo "[${a[@]:2}][${a[*]:2}]"
910 echo "[${a[@]:3}][${a[*]:3}]"
911 echo "[${a[@]:5}][${a[*]:5}]"
912 echo "[${a[@]:9}][${a[*]:9}]"
913 echo "[${a[@]:10}][${a[*]:10}]"
914 echo "[${a[@]:11}][${a[*]:11}]"
915
916 echo '==== ${a[@]:negative} ===='
917 echo "[${a[@]: -1}][${a[*]: -1}]"
918 echo "[${a[@]: -2}][${a[*]: -2}]"
919 echo "[${a[@]: -5}][${a[*]: -5}]"
920 echo "[${a[@]: -9}][${a[*]: -9}]"
921 echo "[${a[@]: -10}][${a[*]: -10}]"
922 echo "[${a[@]: -11}][${a[*]: -11}]"
923 echo "[${a[@]: -21}][${a[*]: -21}]"
924
925 echo '==== ${a[@]:offset:length} ===='
926 echo "[${a[@]:0:0}][${a[*]:0:0}]"
927 echo "[${a[@]:0:1}][${a[*]:0:1}]"
928 echo "[${a[@]:0:3}][${a[*]:0:3}]"
929 echo "[${a[@]:2:1}][${a[*]:2:1}]"
930 echo "[${a[@]:2:4}][${a[*]:2:4}]"
931 echo "[${a[@]:3:4}][${a[*]:3:4}]"
932 echo "[${a[@]:5:4}][${a[*]:5:4}]"
933 echo "[${a[@]:5:0}][${a[*]:5:0}]"
934 echo "[${a[@]:9:1}][${a[*]:9:1}]"
935 echo "[${a[@]:9:2}][${a[*]:9:2}]"
936 echo "[${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}
974 case $SH in zsh|mksh|ash) exit ;; esac
975
976 set -- 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}
1020 case $SH in zsh|mksh|ash) exit ;; esac
1021
1022 case $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]
1035 EOF
1036 exit
1037 fi
1038 # Actual STDOUT of buggy bash builds:
1039 # [][]
1040 # [][]
1041 # [][]
1042 # [][]
1043 ;;
1044 esac
1045
1046 a=(1 2 3)
1047 case ${SH##*/} in osh) eval 'var a = _a2sp(a)' ;; esac
1048 a[0x7FFFFFFFFFFFFFFF]=x
1049 a[0x7FFFFFFFFFFFFFFE]=y
1050 a[0x7FFFFFFFFFFFFFFD]=z
1051
1052 echo "[${a[@]: -1}][${a[*]: -1}]"
1053 echo "[${a[@]: -2}][${a[*]: -2}]"
1054 echo "[${a[@]: -3}][${a[*]: -3}]"
1055 echo "[${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
1070 case $SH in zsh|mksh|ash) exit ;; esac
1071
1072 a=(v{0..9})
1073 unset -v 'a[2]' 'a[3]' 'a[4]' 'a[7]'
1074 case ${SH##*/} in osh) eval 'var a = _a2sp(a)' ;; esac
1075
1076 argv.py "${a[@]}"
1077 argv.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
1090 case $SH in zsh|mksh|ash) exit ;; esac
1091
1092 a=(v{0..9})
1093 unset -v 'a[2]' 'a[3]' 'a[4]' 'a[7]'
1094 case ${SH##*/} in osh) eval 'var a = _a2sp(a)' ;; esac
1095
1096 argv.py "${a[@]#v}"
1097 argv.py "abc${a[@]#v}xyz"
1098 argv.py "${a[@]%[0-5]}"
1099 argv.py "abc${a[@]%[0-5]}xyz"
1100 argv.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
1116 case $SH in zsh|mksh|ash) exit ;; esac
1117
1118 a=(v{0..9})
1119 unset -v 'a[2]' 'a[3]' 'a[4]' 'a[7]'
1120 case ${SH##*/} in osh) eval 'var a = _a2sp(a)' ;; esac
1121
1122 argv.py "${a[@]/?}"
1123 argv.py "${a[@]//?}"
1124 argv.py "${a[@]/#?}"
1125 argv.py "${a[@]/%?}"
1126
1127 argv.py "${a[@]/v/x}"
1128 argv.py "${a[@]//v/x}"
1129 argv.py "${a[@]/[0-5]/D}"
1130 argv.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}
1148 case $SH in zsh|mksh|ash) exit ;; esac
1149
1150 a=(v{0..9})
1151 unset -v 'a[2]' 'a[3]' 'a[4]' 'a[7]'
1152 case ${SH##*/} in osh) eval 'var a = _a2sp(a)' ;; esac
1153
1154 argv.py "${a[@]@P}"
1155 argv.py "${a[*]@P}"
1156 argv.py "${a[@]@Q}"
1157 argv.py "${a[*]@Q}"
1158 argv.py "${a[@]@a}"
1159 argv.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.
1184 case $SH in zsh|mksh|ash) exit ;; esac
1185
1186 a1=()
1187 a2=("")
1188 a3=("" "")
1189
1190 case $SH in
1191 bash) ;;
1192 *) eval "var a1 = _a2sp(a1); var a2 = _a2sp(a2); var a3 = _a2sp(a3)" ;;
1193 esac
1194
1195 echo "a1 unset: [${a1[@]-unset}]"
1196 echo "a1 empty: [${a1[@]:-empty}]"
1197 echo "a2 unset: [${a2[@]-unset}]"
1198 echo "a2 empty: [${a2[@]:-empty}]"
1199 echo "a3 unset: [${a3[@]-unset}]"
1200 echo "a3 empty: [${a3[@]:-empty}]"
1201
1202 ## STDOUT:
1203 a1 unset: [unset]
1204 a1 empty: [empty]
1205 a2 unset: []
1206 a2 empty: [empty]
1207 a3 unset: [ ]
1208 a3 empty: [ ]
1209 ## END
1210
1211 ## N-I zsh/mksh/ash STDOUT:
1212 ## END
1213
1214
1215 #### SparseArray: ${a-}
1216 case $SH in zsh|mksh|ash) exit ;; esac
1217
1218 a1=()
1219 a2=("" "")
1220 a3=(foo bar)
1221
1222 case ${SH##*/} in osh) eval 'var a1 = _a2sp(a1); var a2 = _a2sp(a2); var a3 = _a2sp(a3)' ;; esac
1223
1224 echo "$a1, ${a1-(unset)}, ${a1:-(empty)};"
1225 echo "$a2, ${a2-(unset)}, ${a2:-(empty)};"
1226 echo "$a3, ${a3-(unset)}, ${a3:-(empty)};"
1227
1228 ## STDOUT:
1229 , (unset), (empty);
1230 , , (empty);
1231 foo, foo, foo;
1232 ## END
1233
1234 ## N-I zsh/mksh/ash STDOUT:
1235 ## END
1236
1237
1238 #### SparseArray: compgen -F _set_COMPREPLY
1239 case $SH in zsh|mksh|ash) exit ;; esac
1240
1241 a=({0..9})
1242 unset -v 'a[2]' 'a[4]' 'a[6]'
1243
1244 case ${SH##*/} in
1245 osh)
1246 eval '_set_COMPREPLY() { setglobal COMPREPLY = _a2sp(a); }'
1247 ;;
1248 *)
1249 _set_COMPREPLY() { COMPREPLY=("${a[@]}"); }
1250 ;;
1251 esac
1252
1253 compgen -F _set_COMPREPLY
1254
1255 ## STDOUT:
1256 0
1257 1
1258 3
1259 5
1260 7
1261 8
1262 9
1263 ## END
1264
1265 ## N-I zsh/mksh/ash STDOUT:
1266 ## END
1267
1268
1269 #### SparseArray: compgen -F _set_COMPREPLY
1270 case $SH in bash|zsh|mksh|ash) exit ;; esac
1271
1272 a=(echo 'Hello,' 'Bash' 'world!')
1273 var COMP_ARGV = _a2sp(a)
1274 compadjust cur prev words cword
1275 argv.py "$cur" "$prev" "$cword"
1276 argv.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]
1288 case $SH in bash|zsh|mksh|ash) exit ;; esac
1289
1290 a1=(1 2 3)
1291 unset -v 'a1[1]'
1292 a2=(1 2 3)
1293 unset -v 'a2[1]'
1294 a3=(1 2 4)
1295 unset -v 'a3[1]'
1296 a4=(1 2 3)
1297 var a1 = _a2sp(a1)
1298 var a2 = _a2sp(a2)
1299 var a3 = _a2sp(a3)
1300 var a4 = _a2sp(a4)
1301
1302 echo $[a1 === a1]
1303 echo $[a1 === a2]
1304 echo $[a1 === a3]
1305 echo $[a1 === a4]
1306 echo $[a2 === a1]
1307 echo $[a3 === a1]
1308 echo $[a4 === a1]
1309
1310 ## STDOUT:
1311 true
1312 true
1313 false
1314 false
1315 true
1316 false
1317 false
1318 ## END
1319
1320 ## N-I bash/zsh/mksh/ash STDOUT:
1321 ## END
1322
1323
1324 #### SparseArray (YSH): append v1 v2... (a)
1325 case $SH in bash|zsh|mksh|ash) exit ;; esac
1326
1327 a=(1 2 3)
1328 unset -v 'a[1]'
1329 var a = _a2sp(a)
1330 append '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)]
1342 case $SH in bash|zsh|mksh|ash) exit ;; esac
1343
1344 a1=()
1345 a2=(0)
1346 a3=(0 1 2)
1347 a4=(0 0)
1348 unset -v 'a4[0]'
1349 var a1 = _a2sp(a1)
1350 var a2 = _a2sp(a2)
1351 var a3 = _a2sp(a3)
1352 var a4 = _a2sp(a4)
1353
1354 echo $[bool(a1)]
1355 echo $[bool(a2)]
1356 echo $[bool(a3)]
1357 echo $[bool(a4)]
1358
1359 ## STDOUT:
1360 false
1361 true
1362 true
1363 true
1364 ## END
1365
1366 ## N-I bash/zsh/mksh/ash STDOUT:
1367 ## END
1368
1369
1370 #### SparseArray: crash dump
1371 case $SH in bash|zsh|mksh|ash) exit ;; esac
1372
1373 OILS_CRASH_DUMP_DIR=$TMP $SH -ec 'a=({0..3}); unset -v "a[2]"; var a = _a2sp(a); false'
1374 json read (&crash_dump) < $TMP/*.json
1375 json 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