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 source --builtin ysh/shvar.ysh
241
242 while true {
243 shvar FOO=foo {
244 echo shvar
245 continue
246 }
247 }
248 '
249 echo shvar continue $?
250
251
252 eval '
253 while true {
254 try {
255 echo try
256 break
257 }
258 }
259 '
260 echo try break $?
261
262 ## STDOUT:
263 cd
264 cd no loop 0
265 cd
266 cd loop 1
267 shopt
268 shopt continue 1
269 shvar
270 shvar continue 1
271 try
272 try break 1
273 ## END
274
275 #### Consistency: Exit Status and Blocks
276 shopt --set parse_brace
277
278 source --builtin ysh/shvar.ysh
279
280 cd / {
281 false
282 }
283 echo cd=$?
284
285 shopt --unset errexit {
286 false
287 }
288 echo shopt=$?
289
290 shvar FOO=foo {
291 echo " FOO=$FOO"
292 false
293 }
294 echo shvar=$?
295
296 try {
297 false
298 }
299 echo try=$?
300
301 ## STDOUT:
302 cd=0
303 shopt=0
304 FOO=foo
305 shvar=0
306 try=0
307 ## END
308
309 #### Consistency: Unwanted Blocks Are Errors
310 shopt --set parse_brace
311
312 true { echo BAD }
313 echo true $?
314
315 false ( 42, 43 )
316 echo false $?
317
318 echo { echo BAD }
319 echo echo block $?
320
321 echo ( 42, 43 )
322 echo echo args $?
323
324 command echo 'command block' { echo BAD }
325 echo command echo $?
326
327 builtin echo 'builtin block' { echo BAD }
328 echo builtin echo $?
329
330 pushd $TMP { echo BAD }
331 echo pushd $?
332
333 ## STDOUT:
334 true 2
335 false 2
336 echo block 2
337 echo args 2
338 command echo 2
339 builtin echo 2
340 pushd 2
341 ## END
342
343 #### Block with Bare Assignments
344
345 # oil:all has parse_equals
346 # is there any way to turn on parse_equals only in config blocks?
347 # but we don't know what's a block ahead of time
348 # I think we would have to check at runtime. Look at VarChecker
349
350 shopt --set oil:all
351
352 proc Rule(s ; ; ; b) {
353 echo "rule $s"
354 }
355
356 proc myrules(name) {
357 Rule $name-python {
358 kind = 'python'
359 }
360
361 Rule $name-cc {
362 kind = 'cc' # should NOT conflict
363 }
364 }
365
366 myrules foo
367 myrules bar
368
369 ## STDOUT:
370 rule foo-python
371 rule foo-cc
372 rule bar-python
373 rule bar-cc
374 ## END
375
376 #### Proc that doesn't take a block
377 shopt --set parse_brace parse_proc parse_paren
378
379 proc task(name ; ; ; b = null) {
380 echo "task name=$name"
381 if (b) {
382 eval (b)
383 return 33
384 } else {
385 echo 'no block'
386 return 44
387 }
388 }
389
390 task spam
391 echo status=$?
392
393 echo
394
395 task foo {
396 echo 'running'
397 echo 'block'
398 }
399 echo status=$?
400
401 ## STDOUT:
402 task name=spam
403 no block
404 status=44
405
406 task name=foo
407 running
408 block
409 status=33
410 ## END
411