1 #!/usr/bin/env bash
2
3 #### recursive arith: one level
4 shopt -s eval_unsafe_arith
5 a='b=123'
6 echo $((a))
7 ## stdout: 123
8 ## N-I dash status: 2
9 ## N-I dash stdout-json: ""
10 ## N-I yash stdout: b=123
11
12 #### recursive arith: two levels
13 shopt -s eval_unsafe_arith
14 a='b=c' c='d=123'
15 echo $((a))
16 ## stdout: 123
17 ## N-I dash status: 2
18 ## N-I dash stdout-json: ""
19 ## N-I yash stdout: b=c
20
21 #### recursive arith: short circuit &&, ||
22 # Note: mksh R52 has a bug. Even though it supports a short circuit like
23 # "echo $((cond&&(a=1)))", it doesn't work with "x=a=1; echo
24 # $((cond&&x))". It is fixed at least in mksh R57.
25 # Note: "busybox sh" doesn't support short circuit.
26 shopt -s eval_unsafe_arith
27 a=b=123
28 echo $((1||a)):$((b))
29 echo $((0||a)):$((b))
30 c=d=321
31 echo $((0&&c)):$((d))
32 echo $((1&&c)):$((d))
33 ## stdout-json: "1:0\n1:123\n0:0\n1:321\n"
34 ## BUG mksh stdout-json: "1:123\n1:123\n0:321\n1:321\n"
35 ## N-I ash stdout-json: "1:123\n1:123\n0:321\n1:321\n"
36 ## N-I dash/yash status: 2
37 ## N-I dash/yash stdout-json: "1:0\n"
38
39 #### recursive arith: short circuit ?:
40 # Note: "busybox sh" behaves strangely.
41 shopt -s eval_unsafe_arith
42 y=a=123 n=a=321
43 echo $((1?(y):(n))):$((a))
44 echo $((0?(y):(n))):$((a))
45 ## stdout-json: "123:123\n321:321\n"
46 ## BUG ash stdout-json: "123:123\n321:123\n"
47 ## N-I dash status: 2
48 ## N-I dash stdout-json: ""
49 ## N-I yash stdout-json: "a=123:0\na=321:0\n"
50
51 #### recursive arith: side effects
52 # In Zsh and Busybox sh, the side effect of inner arithmetic
53 # evaluations seems to take effect only after the whole evaluation.
54 shopt -s eval_unsafe_arith
55 a='b=c' c='d=123'
56 echo $((a,d)):$((d))
57 ## stdout: 123:123
58 ## BUG zsh/ash stdout: 0:123
59 ## N-I dash/yash status: 2
60 ## N-I dash/yash stdout-json: ""
61
62 #### recursive arith: recursion
63 shopt -s eval_unsafe_arith
64 loop='i<=100&&(s+=i,i++,loop)' s=0 i=0
65 echo $((a=loop,s))
66 ## stdout: 5050
67 ## N-I mksh status: 1
68 ## N-I mksh stdout-json: ""
69 ## N-I ash/dash/yash status: 2
70 ## N-I ash/dash/yash stdout-json: ""
71
72 #### recursive arith: array elements
73 shopt -s eval_unsafe_arith
74 text[1]='d=123'
75 text[2]='text[1]'
76 text[3]='text[2]'
77 echo $((a=text[3]))
78 ## stdout: 123
79 ## N-I ash/dash/yash status: 2
80 ## N-I ash/dash/yash stdout-json: ""
81
82 #### dynamic arith varname: assign
83 shopt -s parse_dynamic_arith # for LHS
84
85 vec2_set () {
86 local this=$1 x=$2 y=$3
87 : $(( ${this}_x = $2 ))
88 : $(( ${this}_y = y ))
89 }
90 vec2_set a 3 4
91 vec2_set b 5 12
92 echo a_x=$a_x a_y=$a_y
93 echo b_x=$b_x b_y=$b_y
94 ## STDOUT:
95 a_x=3 a_y=4
96 b_x=5 b_y=12
97 ## END
98
99 #### dynamic arith varname: read
100 shopt -s eval_unsafe_arith # for RHS
101
102 vec2_load() {
103 local this=$1
104 x=$(( ${this}_x ))
105 : $(( y = ${this}_y ))
106 }
107 a_x=12 a_y=34
108 vec2_load a
109 echo x=$x y=$y
110 ## STDOUT:
111 x=12 y=34
112 ## END
113
114 #### dynamic arith varname: copy/add
115 shopt -s parse_dynamic_arith # for LHS
116 shopt -s eval_unsafe_arith # for RHS
117
118 vec2_copy () {
119 local this=$1 rhs=$2
120 : $(( ${this}_x = $(( ${rhs}_x )) ))
121 : $(( ${this}_y = ${rhs}_y ))
122 }
123 vec2_add () {
124 local this=$1 rhs=$2
125 : $(( ${this}_x += $(( ${rhs}_x )) ))
126 : $(( ${this}_y += ${rhs}_y ))
127 }
128 a_x=3 a_y=4
129 b_x=4 b_y=20
130 vec2_copy c a
131 echo c_x=$c_x c_y=$c_y
132 vec2_add c b
133 echo c_x=$c_x c_y=$c_y
134 ## STDOUT:
135 c_x=3 c_y=4
136 c_x=7 c_y=24
137 ## END
138
139 #### is-array with ${var@a}
140 case $SH in (mksh|ash|dash|yash) exit 1 ;; esac
141
142 function ble/is-array { [[ ${!1@a} == *a* ]]; }
143
144 ble/is-array undef
145 echo undef $?
146
147 string=''
148 ble/is-array string
149 echo string $?
150
151 array=(one two three)
152 ble/is-array array
153 echo array $?
154 ## STDOUT:
155 undef 1
156 string 1
157 array 0
158 ## END
159 ## N-I zsh/mksh/ash/dash/yash status: 1
160 ## N-I zsh/mksh/ash/dash/yash stdout-json: ""