1 #### cd accepts a block, runs it in different dir
2 shopt -s ysh:all
3
4 const saved = "$PWD"
5
6 # OLDPWD is NOT defined
7 cd / { echo $PWD; echo OLDPWD=${OLDPWD:-} }; echo done
8
9 if ! test "$saved" = $PWD; then
10 echo FAIL
11 fi
12
13 cd /tmp {
14 write PWD=$PWD
15 write --sep ' ' pwd builtin: $(pwd)
16 }
17
18 if ! test "$saved" = $PWD; then
19 echo FAIL
20 fi
21
22 ## STDOUT:
23 /
24 OLDPWD=
25 done
26 PWD=/tmp
27 pwd builtin: /tmp
28 ## END
29
30 #### cd with block: requires explicit command
31 shopt --set ysh:upgrade
32
33 cd /tmp { echo $PWD }
34
35 HOME=~
36 cd { echo $PWD }
37
38 ## status: 2
39 ## STDOUT:
40 /tmp
41 ## END
42
43 #### cd with block: fatal error in block
44 shopt -s ysh:all
45 cd / {
46 echo one
47 false
48 echo two
49 }
50 ## status: 1
51 ## STDOUT:
52 one
53 ## END
54
55
56 #### cd with block: return in block
57 shopt -s oil:all
58 f() {
59 cd / {
60 echo one
61 return
62 echo two
63 }
64 echo 'end func'
65 }
66 f
67 ## STDOUT:
68 one
69 end func
70 ## END
71
72 #### cd with block: break in block
73 shopt -s oil:all
74 f() {
75 cd / {
76 echo one
77 for i in 1 2; do
78 echo $i
79 break # break out of loop
80 done
81
82 break # break out of block isn't valid
83 echo two
84 }
85 echo end func
86 }
87 f
88 ## status: 1
89 ## STDOUT:
90 one
91 1
92 ## END
93
94 #### cd with block exits with status 0
95 shopt -s ysh:all
96 cd / {
97 echo block
98
99 # This return value is ignored.
100 # Or maybe this should be a runtime error?
101 return 1
102 }
103 echo status=$?
104 ## STDOUT:
105 block
106 status=0
107 ## END
108
109 #### block doesn't have its own scope
110 shopt -s ysh:all
111 var x = 1
112 echo "x=$x"
113 cd / {
114 #set y = 5 # This would be an error because set doesn't do dynamic lookup
115 var x = 42
116 echo "x=$x"
117 }
118 echo "x=$x"
119 ## STDOUT:
120 x=1
121 x=42
122 x=42
123 ## END
124
125 #### redirects allowed in words, typed args, and after block
126 shopt -s ysh:upgrade
127
128 rm -f out
129 touch out
130
131 cd /tmp >>out {
132 echo 1 $PWD
133 }
134
135 cd /tmp >>out (; ; ^(echo 2 $PWD))
136
137 cd /tmp (; ; ^(echo 3 $PWD)) >>out
138
139 cd /tmp {
140 echo 4 $PWD
141 } >> out
142
143 cat out
144
145 ## STDOUT:
146 1 /tmp
147 2 /tmp
148 3 /tmp
149 4 /tmp
150 ## END
151
152 #### block literal in expression mode: ^(echo $PWD)
153 shopt -s oil:all
154
155 const myblock = ^(echo $PWD | wc -l)
156 eval (myblock)
157
158 const b2 = ^(echo one; echo two)
159 eval (b2)
160
161 ## STDOUT:
162 1
163 one
164 two
165 ## END
166
167 #### block arg as typed expression
168
169 shopt -s oil:all
170
171 # literal
172 cd /tmp (; ; ^(echo $PWD))
173
174 const myblock = ^(echo $PWD)
175 cd /tmp (; ; myblock)
176
177 ## STDOUT:
178 /tmp
179 /tmp
180 ## END
181
182 #### Pass invalid typed args
183
184 cd /tmp (42) # should be a block
185 ## status: 3
186
187 #### Pass too many typed args
188
189 cd /tmp (1, 2)
190 ## status: 3
191
192 #### 'builtin' and 'command' with block
193 shopt --set oil:upgrade
194 builtin cd / {
195 echo "builtin $PWD"
196 }
197 command cd / {
198 echo "command $PWD"
199 }
200 ## STDOUT:
201 builtin /
202 command /
203 ## END
204
205
206 #### Consistency: Control Flow and Blocks
207 shopt --set parse_brace
208
209 # "Invalid control flow at top level"
210 eval '
211 cd / {
212 echo cd
213 break
214 }
215 '
216 echo cd no loop $?
217
218 # warning: "Unexpected control flow in block" (strict_control_flow)
219 eval '
220 while true {
221 cd / {
222 echo cd
223 break
224 }
225 }
226 '
227 echo cd loop $?
228
229 eval '
230 while true {
231 shopt --unset errexit {
232 echo shopt
233 continue
234 }
235 }
236 '
237 echo shopt continue $?
238
239 eval '
240 while true {
241 shvar FOO=foo {
242 echo shvar
243 continue
244 }
245 }
246 '
247 echo shvar continue $?
248
249
250 eval '
251 while true {
252 try {
253 echo try
254 break
255 }
256 }
257 '
258 echo try break $?
259
260 ## STDOUT:
261 cd
262 cd no loop 0
263 cd
264 cd loop 1
265 shopt
266 shopt continue 1
267 shvar
268 shvar continue 1
269 try
270 try break 1
271 ## END
272
273 #### Consistency: Exit Status and Blocks
274 shopt --set parse_brace
275
276 cd / {
277 false
278 }
279 echo cd=$?
280
281 shopt --unset errexit {
282 false
283 }
284 echo shopt=$?
285
286 shvar FOO=foo {
287 echo " FOO=$FOO"
288 false
289 }
290 echo shvar=$?
291
292 try {
293 false
294 }
295 echo try=$?
296
297 ## STDOUT:
298 cd=0
299 shopt=0
300 FOO=foo
301 shvar=0
302 try=0
303 ## END
304
305 #### Consistency: Unwanted Blocks Are Errors
306 shopt --set parse_brace
307
308 true { echo BAD }
309 echo true $?
310
311 false ( 42, 43 )
312 echo false $?
313
314 echo { echo BAD }
315 echo echo block $?
316
317 echo ( 42, 43 )
318 echo echo args $?
319
320 command echo 'command block' { echo BAD }
321 echo command echo $?
322
323 builtin echo 'builtin block' { echo BAD }
324 echo builtin echo $?
325
326 pushd $TMP { echo BAD }
327 echo pushd $?
328
329 ## STDOUT:
330 true 2
331 false 2
332 echo block 2
333 echo args 2
334 command echo 2
335 builtin echo 2
336 pushd 2
337 ## END
338
339 #### Block with Bare Assignments
340
341 # oil:all has parse_equals
342 # is there any way to turn on parse_equals only in config blocks?
343 # but we don't know what's a block ahead of time
344 # I think we would have to check at runtime. Look at VarChecker
345
346 shopt --set oil:all
347
348 proc Rule(s ; ; ; b) {
349 echo "rule $s"
350 }
351
352 proc myrules(name) {
353 Rule $name-python {
354 kind = 'python'
355 }
356
357 Rule $name-cc {
358 kind = 'cc' # should NOT conflict
359 }
360 }
361
362 myrules foo
363 myrules bar
364
365 ## STDOUT:
366 rule foo-python
367 rule foo-cc
368 rule bar-python
369 rule bar-cc
370 ## END
371
372 #### Proc that doesn't take a block
373 shopt --set parse_brace parse_proc parse_paren
374
375 proc task(name ; ; ; b = null) {
376 echo "task name=$name"
377 if (b) {
378 eval (b)
379 return 33
380 } else {
381 echo 'no block'
382 return 44
383 }
384 }
385
386 task spam
387 echo status=$?
388
389 echo
390
391 task foo {
392 echo 'running'
393 echo 'block'
394 }
395 echo status=$?
396
397 ## STDOUT:
398 task name=spam
399 no block
400 status=44
401
402 task name=foo
403 running
404 block
405 status=33
406 ## END
407