1 ## compare_shells: bash dash mksh zsh
2 ## oils_failures_allowed: 0
3
4 #### can continue after unknown option
5 #
6 # TODO: this is the posix special builtin logic?
7 # dash and mksh make this a fatal error no matter what.
8
9 set -o errexit
10 set -o STRICT || true # unknown option
11 echo hello
12 ## stdout: hello
13 ## status: 0
14 ## BUG dash/mksh/zsh stdout-json: ""
15 ## BUG dash status: 2
16 ## BUG mksh/zsh status: 1
17
18 #### set with both options and argv
19 set -o errexit a b c
20 echo "$@"
21 false
22 echo done
23 ## stdout: a b c
24 ## status: 1
25
26 #### nounset with "$@"
27 set a b c
28 set -u # shouldn't touch argv
29 echo "$@"
30 ## stdout: a b c
31
32 #### set -u -- clears argv
33 set a b c
34 set -u -- # shouldn't touch argv
35 echo "$@"
36 ## stdout:
37
38 #### set -u -- x y z
39 set a b c
40 set -u -- x y z
41 echo "$@"
42 ## stdout: x y z
43
44 #### set -u error in eval should exit when non-interactive
45 $SH -c '
46 set -u
47 test_function() {
48 x=$1
49 }
50
51 echo before
52 eval test_function
53 # bash spec says that set -u failures should exit the shell
54 # posix spec says that eval shall read and execute a command by the current shell, so the
55 # running shell should exit too
56
57 echo after
58 '
59 # status must be non-zero: bash uses 1, ash/dash exit 2
60 if test $? -ne 0; then
61 echo OK
62 fi
63
64 ## STDOUT:
65 before
66 OK
67 ## END
68 ## BUG zsh/mksh STDOUT:
69 before
70 after
71 ## END
72
73 #### set -u nested evals
74 $SH -c '
75 set -u
76 test_function_2() {
77 x=$blarg
78 }
79 test_function() {
80 eval "test_function_2"
81 }
82
83 echo before
84 eval test_function
85 echo after
86 '
87 # status must be non-zero: bash uses 1, ash/dash exit 2
88 if test $? -ne 0; then
89 echo OK
90 fi
91
92 ## STDOUT:
93 before
94 OK
95 ## END
96 ## BUG zsh/mksh STDOUT:
97 before
98 after
99 ## END
100
101 #### set -u no eval
102 $SH -c '
103 set -u
104
105 echo "before"
106 x=$blarg
107 echo "after"
108 '
109 # status must be non-zero: bash uses 1, ash/dash exit 2
110 if test $? -ne 0; then
111 echo OK
112 fi
113
114 ## STDOUT:
115 before
116 OK
117 ## END
118
119 #### reset option with long flag
120 set -o errexit
121 set +o errexit
122 echo "[$unset]"
123 ## stdout: []
124 ## status: 0
125
126 #### reset option with short flag
127 set -u
128 set +u
129 echo "[$unset]"
130 ## stdout: []
131 ## status: 0
132
133 #### set -eu (flag parsing)
134 set -eu
135 echo "[$unset]"
136 echo status=$?
137 ## stdout-json: ""
138 ## status: 1
139 ## OK dash status: 2
140
141 #### set -o lists options
142 # NOTE: osh doesn't use the same format yet.
143 set -o | grep -o noexec
144 ## STDOUT:
145 noexec
146 ## END
147
148 #### 'set' and 'eval' round trip
149
150 # NOTE: not testing arrays and associative arrays!
151 _space='[ ]'
152 _whitespace=$'[\t\r\n]'
153 _sq="'single quotes'"
154 _backslash_dq="\\ \""
155 _unicode=$'[\u03bc]'
156
157 # Save the variables
158 varfile=$TMP/vars-$(basename $SH).txt
159
160 set | grep '^_' > "$varfile"
161
162 # Unset variables
163 unset _space _whitespace _sq _backslash_dq _unicode
164 echo [ $_space $_whitespace $_sq $_backslash_dq $_unicode ]
165
166 # Restore them
167
168 . $varfile
169 echo "Code saved to $varfile" 1>&2 # for debugging
170
171 test "$_space" = '[ ]' && echo OK
172 test "$_whitespace" = $'[\t\r\n]' && echo OK
173 test "$_sq" = "'single quotes'" && echo OK
174 test "$_backslash_dq" = "\\ \"" && echo OK
175 test "$_unicode" = $'[\u03bc]' && echo OK
176
177 ## STDOUT:
178 [ ]
179 OK
180 OK
181 OK
182 OK
183 OK
184 ## END
185
186 ## BUG zsh status: 1
187 ## BUG zsh STDOUT:
188 [ ]
189 ## END
190
191 #### set - - and so forth
192 set a b
193 echo "$@"
194
195 set - a b
196 echo "$@"
197
198 set -- a b
199 echo "$@"
200
201 set - -
202 echo "$@"
203
204 set -- --
205 echo "$@"
206
207 # note: zsh is different, and yash is totally different
208 ## STDOUT:
209 a b
210 a b
211 a b
212 -
213 --
214 ## END
215 ## N-I yash STDOUT:
216 a b
217 - a b
218 a b
219 - -
220 --
221 ## END
222 ## BUG zsh STDOUT:
223 a b
224 a b
225 a b
226
227 --
228 ## END
229
230 #### set - leading single dash is ignored, turns off xtrace verbose (#2364)
231
232 show_options() {
233 case $- in
234 *v*) echo verbose-on ;;
235 esac
236 case $- in
237 *x*) echo xtrace-on ;;
238 esac
239 }
240
241 set -x -v
242 show_options
243 echo
244
245 set - a b c
246 echo "$@"
247 show_options
248 echo
249
250 # dash that's not leading is not special
251 set x - y z
252 echo "$@"
253
254 ## STDOUT:
255 verbose-on
256 xtrace-on
257
258 a b c
259
260 x - y z
261 ## END
262
263 ## BUG zsh STDOUT:
264 verbose-on
265 xtrace-on
266
267 a b c
268 verbose-on
269 xtrace-on
270
271 x - y z
272 ## END
273
274 #### set - stops option processing like set --
275 case $SH in zsh) exit ;; esac
276
277 show_options() {
278 case $- in
279 *v*) echo verbose-on ;;
280 esac
281 case $- in
282 *x*) echo xtrace-on ;;
283 esac
284 }
285
286 set -x - -v
287
288 show_options
289 echo argv "$@"
290
291 ## STDOUT:
292 argv -v
293 ## END
294
295 ## N-I zsh STDOUT:
296 ## END
297
298 #### A single + is an ignored flag; not an argument
299 case $SH in zsh) exit ;; esac
300
301 show_options() {
302 case $- in
303 *v*) echo verbose-on ;;
304 esac
305 case $- in
306 *x*) echo xtrace-on ;;
307 esac
308 }
309
310 set +
311 echo plus "$@"
312
313 set -x + -v x y
314 show_options
315 echo plus "$@"
316
317 ## STDOUT:
318 plus
319 verbose-on
320 xtrace-on
321 plus x y
322 ## END
323
324 ## BUG mksh STDOUT:
325 plus
326 xtrace-on
327 plus -v x y
328 ## END
329
330 ## N-I zsh STDOUT:
331 ## END
332
333 #### set - + and + -
334 set - +
335 echo "$@"
336
337 set + -
338 echo "$@"
339
340 ## STDOUT:
341 +
342 +
343 ## END
344
345 ## BUG mksh STDOUT:
346 +
347 -
348 ## END
349
350 ## OK zsh/osh STDOUT:
351 +
352
353 ## END
354
355 #### set -a exports variables
356 set -a
357 FOO=bar
358 BAZ=qux
359 printenv.py FOO BAZ
360 ## STDOUT:
361 bar
362 qux
363 ## END
364
365 #### set +a stops exporting
366 set -a
367 FOO=exported
368 set +a
369 BAR=not_exported
370 printenv.py FOO BAR
371 ## STDOUT:
372 exported
373 None
374 ## END
375
376 #### set -o allexport (long form)
377 set -o allexport
378 VAR1=value1
379 set +o allexport
380 VAR2=value2
381 printenv.py VAR1 VAR2
382 ## STDOUT:
383 value1
384 None
385 ## END
386
387 #### variables set before set -a are not exported
388 BEFORE=before_value
389 set -a
390 AFTER=after_value
391 printenv.py BEFORE AFTER
392 ## STDOUT:
393 None
394 after_value
395 ## END
396
397 #### set -a exports local variables
398 set -a
399 f() {
400 local ZZZ=zzz
401 printenv.py ZZZ
402 }
403 f
404 ## STDOUT:
405 zzz
406 ## END
407 ## BUG mksh stdout: None
408
409 #### set -a exports declare variables
410 set -a
411 declare ZZZ=zzz
412 printenv.py ZZZ
413 ## STDOUT:
414 zzz
415 ## END
416 ## N-I dash/mksh stdout: None