1
2 #### implicit for loop
3 # This is like "for i in $@".
4 fun() {
5 for i; do
6 echo $i
7 done
8 }
9 fun 1 2 3
10 ## STDOUT:
11 1
12 2
13 3
14 ## END
15
16 #### empty for loop (has "in")
17 set -- 1 2 3
18 for i in ; do
19 echo $i
20 done
21 ## stdout-json: ""
22
23 #### for loop with invalid identifier
24 # should be compile time error, but runtime error is OK too
25 for - in a b c; do
26 echo hi
27 done
28 ## stdout-json: ""
29 ## status: 2
30 ## OK bash/mksh status: 1
31 ## BUG zsh stdout: hi
32 ## BUG zsh status: 1
33
34 #### Tilde expansion within for loop
35 HOME=/home/bob
36 for name in ~/src ~/git; do
37 echo $name
38 done
39 ## STDOUT:
40 /home/bob/src
41 /home/bob/git
42 ## END
43
44 #### Brace Expansion within Array
45 for i in -{a,b} {c,d}-; do
46 echo $i
47 done
48 ## STDOUT:
49 -a
50 -b
51 c-
52 d-
53 ## END
54 ## N-I dash STDOUT:
55 -{a,b}
56 {c,d}-
57 ## END
58
59 #### using loop var outside loop
60 fun() {
61 for i in a b c; do
62 echo $i
63 done
64 echo $i
65 }
66 fun
67 ## status: 0
68 ## STDOUT:
69 a
70 b
71 c
72 c
73 ## END
74
75 #### continue
76 for i in a b c; do
77 echo $i
78 if test $i = b; then
79 continue
80 fi
81 echo $i
82 done
83 ## status: 0
84 ## STDOUT:
85 a
86 a
87 b
88 c
89 c
90 ## END
91
92 #### break
93 for i in a b c; do
94 echo $i
95 if test $i = b; then
96 break
97 fi
98 done
99 ## status: 0
100 ## STDOUT:
101 a
102 b
103 ## END
104
105 #### dynamic control flow (KNOWN INCOMPATIBILITY)
106 # hm would it be saner to make FATAL builtins called break/continue/etc.?
107 # On the other hand, this spits out errors loudly.
108 b=break
109 for i in 1 2 3; do
110 echo $i
111 $b
112 done
113 ## STDOUT:
114 1
115 ## END
116 ## OK osh STDOUT:
117 1
118 2
119 3
120 ## END
121 ## OK osh status: 127
122
123 #### while in while condition
124 # This is a consequence of the grammar
125 while while true; do echo cond; break; done
126 do
127 echo body
128 break
129 done
130 ## STDOUT:
131 cond
132 body
133 ## END
134
135 #### while in pipe
136 x=$(find spec/ | wc -l)
137 y=$(find spec/ | while read path; do
138 echo $path
139 done | wc -l
140 )
141 test $x -eq $y
142 echo status=$?
143 ## stdout: status=0
144
145 #### while in pipe with subshell
146 i=0
147 seq 3 | ( while read foo; do
148 i=$((i+1))
149 #echo $i
150 done
151 echo $i )
152 ## stdout: 3
153
154 #### until loop
155 # This is just the opposite of while? while ! cond?
156 until false; do
157 echo hi
158 break
159 done
160 ## stdout: hi
161
162 #### continue at top level
163 if true; then
164 echo one
165 continue
166 echo two
167 fi
168 ## status: 0
169 ## STDOUT:
170 one
171 two
172 ## END
173 # zsh behaves like strict_control_flow!
174 ## OK zsh status: 1
175 ## OK zsh STDOUT:
176 one
177 ## END
178
179 #### continue in subshell
180 for i in $(seq 2); do
181 echo "> $i"
182 ( if true; then continue; fi; echo "Should not print" )
183 echo subshell status=$?
184 echo ". $i"
185 done
186 ## STDOUT:
187 # osh lets you fail
188 > 1
189 subshell status=1
190 . 1
191 > 2
192 subshell status=1
193 . 2
194 ## END
195 ## OK dash/bash/zsh STDOUT:
196 > 1
197 subshell status=0
198 . 1
199 > 2
200 subshell status=0
201 . 2
202 ## END
203 ## BUG mksh STDOUT:
204 > 1
205 Should not print
206 subshell status=0
207 . 1
208 > 2
209 Should not print
210 subshell status=0
211 . 2
212 ## END
213
214 #### continue in subshell aborts with errexit
215 # The other shells don't let you recover from this programming error!
216 set -o errexit
217 for i in $(seq 2); do
218 echo "> $i"
219 ( if true; then continue; fi; echo "Should not print" )
220 echo 'should fail after subshell'
221 echo ". $i"
222 done
223 ## STDOUT:
224 > 1
225 ## END
226 ## status: 1
227 ## BUG dash/bash/zsh STDOUT:
228 > 1
229 should fail after subshell
230 . 1
231 > 2
232 should fail after subshell
233 . 2
234 ## END
235 ## BUG dash/bash/zsh status: 0
236 ## BUG mksh STDOUT:
237 > 1
238 Should not print
239 should fail after subshell
240 . 1
241 > 2
242 Should not print
243 should fail after subshell
244 . 2
245 ## END
246 ## BUG mksh status: 0
247
248 #### bad arg to break
249 x=oops
250 while true; do
251 echo hi
252 break $x
253 sleep 0.1
254 done
255 ## stdout: hi
256 ## status: 1
257 ## OK dash status: 2
258 ## OK bash status: 128
259
260 #### too many args to continue
261 # OSH treats this as a parse error
262 for x in a b c; do
263 echo $x
264 # bash breaks rather than continue or fatal error!!!
265 continue 1 2 3
266 done
267 echo --
268 ## stdout-json: ""
269 ## status: 2
270 ## BUG bash STDOUT:
271 a
272 --
273 ## END
274 ## OK bash status: 0
275 ## BUG dash/mksh/zsh STDOUT:
276 a
277 b
278 c
279 --
280 ## END
281 ## BUG dash/mksh/zsh status: 0
282
283 #### break in condition of loop
284 while break; do
285 echo x
286 done
287 echo done
288 ## STDOUT:
289 done
290 ## END
291
292
293 #### break in condition of nested loop
294 for i in 1 2 3; do
295 echo i=$i
296 while break; do
297 echo x
298 done
299 done
300 echo done
301 ## STDOUT:
302 i=1
303 i=2
304 i=3
305 done
306 ## END
307
308 #### return within eval
309 f() {
310 echo one
311 eval 'return'
312 echo two
313 }
314 f
315 ## STDOUT:
316 one
317 ## END
318
319 #### break/continue within eval
320 # NOTE: This changes things
321 # set -e
322 f() {
323 for i in $(seq 5); do
324 if test $i = 2; then
325 eval continue
326 fi
327 if test $i = 4; then
328 eval break
329 fi
330 echo $i
331 done
332
333 eval 'return'
334 echo 'done'
335 }
336 f
337 ## STDOUT:
338 1
339 3
340 ## END
341 ## BUG mksh STDOUT:
342 1
343 2
344 3
345 4
346 5
347 ## END
348
349 #### break/continue within source
350 # NOTE: This changes things
351 # set -e
352
353 cd $REPO_ROOT
354 f() {
355 for i in $(seq 5); do
356 if test $i = 2; then
357 . spec/testdata/continue.sh
358 fi
359 if test $i = 4; then
360 . spec/testdata/break.sh
361 fi
362 echo $i
363 done
364
365 # Return is different!
366 . spec/testdata/return.sh
367 echo done
368 }
369 f
370 ## STDOUT:
371 1
372 3
373 done
374 ## END
375 ## BUG zsh/mksh STDOUT:
376 1
377 2
378 3
379 4
380 5
381 done
382 ## END
383
384 #### top-level break/continue/return (without strict_control_flow)
385 $SH -c 'break; echo break=$?'
386 $SH -c 'continue; echo continue=$?'
387 $SH -c 'return; echo return=$?'
388 ## STDOUT:
389 break=0
390 continue=0
391 ## END
392 ## BUG zsh stdout-json: ""
393 ## BUG bash STDOUT:
394 break=0
395 continue=0
396 return=1
397 ## END