# $MirOS: src/bin/mksh/check.t,v 1.759 2017/03/12 02:35:32 tg Exp $ # -*- mode: sh -*- #- # Copyright © 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, # 2011, 2012, 2013, 2014, 2015, 2016, 2017 # mirabilos # # Provided that these terms and disclaimer and all copyright notices # are retained or reproduced in an accompanying document, permission # is granted to deal in this work without restriction, including un‐ # limited rights to use, publicly perform, distribute, sell, modify, # merge, give away, or sublicence. # # This work is provided “AS IS” and WITHOUT WARRANTY of any kind, to # the utmost extent permitted by applicable law, neither express nor # implied; without malicious intent or gross negligence. In no event # may a licensor, author or contributor be held liable for indirect, # direct, other damage, loss, or other issues arising in any way out # of dealing in the work, even if advised of the possibility of such # damage or existence of a defect, except proven that it results out # of said person’s immediate fault when using the work as intended. #- # You may also want to test IFS with the script at # http://www.research.att.com/~gsf/public/ifs.sh # # More testsuites at: # http://svnweb.freebsd.org/base/head/bin/test/tests/legacy_test.sh?view=co&content-type=text%2Fplain # # Integrated testsuites from: # (2013/12/02 20:39:44) http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/regress/bin/ksh/?sortby=date expected-stdout: @(#)MIRBSD KSH R54 2017/03/11 description: Check version of shell. stdin: echo $KSH_VERSION name: KSH_VERSION category: shell:legacy-no --- expected-stdout: @(#)LEGACY KSH R54 2017/03/11 description: Check version of legacy shell. stdin: echo $KSH_VERSION name: KSH_VERSION-legacy category: shell:legacy-yes --- name: selftest-1 description: Regression test self-testing stdin: echo ${foo:-baz} expected-stdout: baz --- name: selftest-2 description: Regression test self-testing env-setup: !foo=bar! stdin: echo ${foo:-baz} expected-stdout: bar --- name: selftest-3 description: Regression test self-testing env-setup: !ENV=fnord! stdin: echo "<$ENV>" expected-stdout: --- name: selftest-exec description: Ensure that the test run directory (default /tmp but can be changed with check.pl flag -T or test.sh $TMPDIR) is not mounted noexec, as we execute scripts from the scratch directory during several tests. stdin: print '#!'"$__progname"'\necho tf' >lq chmod +x lq ./lq expected-stdout: tf --- name: selftest-env description: Just output the environment variables set (always fails) category: disabled stdin: set --- name: selftest-direct-builtin-call description: Check that direct builtin calls work stdin: ln -s "$__progname" cat || cp "$__progname" cat ln -s "$__progname" echo || cp "$__progname" echo ./echo -c 'echo foo' | ./cat -u expected-stdout: -c echo foo --- name: alias-1 description: Check that recursion is detected/avoided in aliases. stdin: alias fooBar=fooBar fooBar exit 0 expected-stderr-pattern: /fooBar.*not found.*/ --- name: alias-2 description: Check that recursion is detected/avoided in aliases. stdin: alias fooBar=barFoo alias barFoo=fooBar fooBar barFoo exit 0 expected-stderr-pattern: /fooBar.*not found.*\n.*barFoo.*not found/ --- name: alias-3 description: Check that recursion is detected/avoided in aliases. stdin: alias Echo='echo ' alias fooBar=barFoo alias barFoo=fooBar Echo fooBar unalias barFoo Echo fooBar expected-stdout: fooBar barFoo --- name: alias-4 description: Check that alias expansion isn't done on keywords (in keyword postitions). stdin: alias Echo='echo ' alias while=While while false; do echo hi ; done Echo while expected-stdout: While --- name: alias-5 description: Check that alias expansion done after alias with trailing space. stdin: alias Echo='echo ' alias foo='bar stuff ' alias bar='Bar1 Bar2 ' alias stuff='Stuff' alias blah='Blah' Echo foo blah expected-stdout: Bar1 Bar2 Stuff Blah --- name: alias-6 description: Check that alias expansion done after alias with trailing space. stdin: alias Echo='echo ' alias foo='bar bar' alias bar='Bar ' alias blah=Blah Echo foo blah expected-stdout: Bar Bar Blah --- name: alias-7 description: Check that alias expansion done after alias with trailing space after a keyword. stdin: alias X='case ' alias Y=Z X Y in 'Y') echo is y ;; Z) echo is z ;; esac expected-stdout: is z --- name: alias-8 description: Check that newlines in an alias don't cause the command to be lost. stdin: alias foo=' echo hi echo there ' foo expected-stdout: hi there --- name: alias-9 description: Check that recursion is detected/avoided in aliases. This check fails for slow machines or Cygwin, raise the time-limit clause (e.g. to 7) if this occurs. time-limit: 3 stdin: print '#!'"$__progname"'\necho tf' >lq chmod +x lq PATH=$PWD$PATHSEP$PATH alias lq=lq lq echo = now i=`lq` print -r -- $i echo = out exit 0 expected-stdout: tf = now tf = out --- name: alias-10 description: Check that recursion is detected/avoided in aliases. Regression, introduced during an old bugfix. stdin: alias foo='print hello ' alias bar='foo world' echo $(bar) expected-stdout: hello world --- name: alias-11 description: Check that special argument handling still applies with escaped aliases stdin: alias local='\typeset' function foo { local x=$1 y=z print -r -- "$x,$y" } foo 'bar - baz' expected-stdout: bar - baz,z --- name: arith-compound description: Check that arithmetic expressions are compound constructs stdin: { ! (( 0$(cat >&2) )) <<<1; } <<<2 expected-stderr: 1 --- name: arith-lazy-1 description: Check that only one side of ternary operator is evaluated stdin: x=i+=2 y=j+=2 typeset -i i=1 j=1 echo $((1 ? 20 : (x+=2))) echo $i,$x echo $((0 ? (y+=2) : 30)) echo $j,$y expected-stdout: 20 1,i+=2 30 1,j+=2 --- name: arith-lazy-2 description: Check that assignments not done on non-evaluated side of ternary operator stdin: x=i+=2 y=j+=2 typeset -i i=1 j=1 echo $((1 ? 20 : (x+=2))) echo $i,$x echo $((0 ? (y+=2) : 30)) echo $i,$y expected-stdout: 20 1,i+=2 30 1,j+=2 --- name: arith-lazy-3 description: Check that assignments not done on non-evaluated side of ternary operator and this construct is parsed correctly (Debian #445651) stdin: x=4 y=$((0 ? x=1 : 2)) echo = $x $y = expected-stdout: = 4 2 = --- name: arith-lazy-4 description: Check that preun/postun not done on non-evaluated side of ternary operator stdin: (( m = n = 0, 1 ? n++ : m++ ? 2 : 3 )) echo "($n, $m)" m=0; echo $(( 0 ? ++m : 2 )); echo $m m=0; echo $(( 0 ? m++ : 2 )); echo $m expected-stdout: (1, 0) 2 0 2 0 --- name: arith-lazy-5-arr-n description: Check lazy evaluation with side effects stdin: a=0; echo "$((0&&b[a++],a))" expected-stdout: 0 --- name: arith-lazy-5-arr-p description: Check lazy evaluation with side effects stdin: a=0; echo "$((0&&(b[a++]),a))" expected-stdout: 0 --- name: arith-lazy-5-str-n description: Check lazy evaluation with side effects stdin: a=0 b=a++; ((0&&b)); echo $a expected-stdout: 0 --- name: arith-lazy-5-str-p description: Check lazy evaluation with side effects stdin: a=0 b=a++; ((0&&(b))); echo $a expected-stdout: 0 --- name: arith-lazy-5-tern-l-n description: Check lazy evaluation with side effects stdin: a=0; echo "$((0?b[a++]:999,a))" expected-stdout: 0 --- name: arith-lazy-5-tern-l-p description: Check lazy evaluation with side effects stdin: a=0; echo "$((0?(b[a++]):999,a))" expected-stdout: 0 --- name: arith-lazy-5-tern-r-n description: Check lazy evaluation with side effects stdin: a=0; echo "$((1?999:b[a++],a))" expected-stdout: 0 --- name: arith-lazy-5-tern-r-p description: Check lazy evaluation with side effects stdin: a=0; echo "$((1?999:(b[a++]),a))" expected-stdout: 0 --- name: arith-ternary-prec-1 description: Check precedence of ternary operator vs assignment stdin: typeset -i x=2 y=$((1 ? 20 : x+=2)) expected-exit: e != 0 expected-stderr-pattern: /.*:.*1 \? 20 : x\+=2.*lvalue.*\n$/ --- name: arith-ternary-prec-2 description: Check precedence of ternary operator vs assignment stdin: typeset -i x=2 echo $((0 ? x+=2 : 20)) expected-stdout: 20 --- name: arith-prec-1 description: Prove arithmetic expressions with embedded parameter substitutions cannot be parsed ahead of time stdin: a='3 + 4' print 1 $((2 * a)) . print 2 $((2 * $a)) . expected-stdout: 1 14 . 2 10 . --- name: arith-div-assoc-1 description: Check associativity of division operator stdin: echo $((20 / 2 / 2)) expected-stdout: 5 --- name: arith-div-byzero description: Check division by zero errors out stdin: x=$(echo $((1 / 0))) echo =$?:$x. expected-stdout: =1:. expected-stderr-pattern: /.*divisor/ --- name: arith-div-intmin-by-minusone description: Check division overflow wraps around silently category: int:32 stdin: echo signed:$((-2147483648 / -1))r$((-2147483648 % -1)). echo unsigned:$((# -2147483648 / -1))r$((# -2147483648 % -1)). expected-stdout: signed:-2147483648r0. unsigned:0r2147483648. --- name: arith-div-intmin-by-minusone-64 description: Check division overflow wraps around silently category: int:64 stdin: echo signed:$((-9223372036854775808 / -1))r$((-9223372036854775808 % -1)). echo unsigned:$((# -9223372036854775808 / -1))r$((# -9223372036854775808 % -1)). expected-stdout: signed:-9223372036854775808r0. unsigned:0r9223372036854775808. --- name: arith-assop-assoc-1 description: Check associativity of assignment-operator operator stdin: typeset -i i=1 j=2 k=3 echo $((i += j += k)) echo $i,$j,$k expected-stdout: 6 6,5,3 --- name: arith-mandatory description: Passing of this test is *mandatory* for a valid mksh executable! category: shell:legacy-no stdin: typeset -i sari=0 typeset -Ui uari=0 typeset -i x=0 print -r -- $((x++)):$sari=$uari. #0 let --sari --uari print -r -- $((x++)):$sari=$uari. #1 sari=2147483647 uari=2147483647 print -r -- $((x++)):$sari=$uari. #2 let ++sari ++uari print -r -- $((x++)):$sari=$uari. #3 let --sari --uari let 'sari *= 2' 'uari *= 2' let ++sari ++uari print -r -- $((x++)):$sari=$uari. #4 let ++sari ++uari print -r -- $((x++)):$sari=$uari. #5 sari=-2147483648 uari=-2147483648 print -r -- $((x++)):$sari=$uari. #6 let --sari --uari print -r -- $((x++)):$sari=$uari. #7 (( sari = -5 >> 1 )) ((# uari = -5 >> 1 )) print -r -- $((x++)):$sari=$uari. #8 (( sari = -2 )) ((# uari = sari )) print -r -- $((x++)):$sari=$uari. #9 expected-stdout: 0:0=0. 1:-1=4294967295. 2:2147483647=2147483647. 3:-2147483648=2147483648. 4:-1=4294967295. 5:0=0. 6:-2147483648=2147483648. 7:2147483647=2147483647. 8:-3=2147483645. 9:-2=4294967294. --- name: arith-unsigned-1 description: Check if unsigned arithmetics work category: int:32 stdin: # signed vs unsigned echo x1 $((-1)) $((#-1)) # calculating typeset -i vs typeset -Ui vu vs=4123456789; vu=4123456789 echo x2 $vs $vu (( vs %= 2147483647 )) (( vu %= 2147483647 )) echo x3 $vs $vu vs=4123456789; vu=4123456789 (( # vs %= 2147483647 )) (( # vu %= 2147483647 )) echo x4 $vs $vu # make sure the calculation does not change unsigned flag vs=4123456789; vu=4123456789 echo x5 $vs $vu # short form echo x6 $((# vs % 2147483647)) $((# vu % 2147483647)) # array refs set -A va va[1975973142]=right va[4123456789]=wrong echo x7 ${va[#4123456789%2147483647]} # make sure multiple calculations don't interfere with each other let '# mca = -4 % -2' ' mcb = -4 % -2' echo x8 $mca $mcb expected-stdout: x1 -1 4294967295 x2 -171510507 4123456789 x3 -171510507 4123456789 x4 1975973142 1975973142 x5 -171510507 4123456789 x6 1975973142 1975973142 x7 right x8 -4 0 --- name: arith-limit32-1 description: Check if arithmetics are 32 bit category: int:32 stdin: # signed vs unsigned echo x1 $((-1)) $((#-1)) # calculating typeset -i vs typeset -Ui vu vs=2147483647; vu=2147483647 echo x2 $vs $vu let vs++ vu++ echo x3 $vs $vu vs=4294967295; vu=4294967295 echo x4 $vs $vu let vs++ vu++ echo x5 $vs $vu let vs++ vu++ echo x6 $vs $vu expected-stdout: x1 -1 4294967295 x2 2147483647 2147483647 x3 -2147483648 2147483648 x4 -1 4294967295 x5 0 0 x6 1 1 --- name: arith-limit64-1 description: Check if arithmetics are 64 bit category: int:64 stdin: # signed vs unsigned echo x1 $((-1)) $((#-1)) # calculating typeset -i vs typeset -Ui vu vs=9223372036854775807; vu=9223372036854775807 echo x2 $vs $vu let vs++ vu++ echo x3 $vs $vu vs=18446744073709551615; vu=18446744073709551615 echo x4 $vs $vu let vs++ vu++ echo x5 $vs $vu let vs++ vu++ echo x6 $vs $vu expected-stdout: x1 -1 18446744073709551615 x2 9223372036854775807 9223372036854775807 x3 -9223372036854775808 9223372036854775808 x4 -1 18446744073709551615 x5 0 0 x6 1 1 --- name: bksl-nl-ign-1 description: Check that \newline is not collapsed after # stdin: echo hi #there \ echo folks expected-stdout: hi folks --- name: bksl-nl-ign-2 description: Check that \newline is not collapsed inside single quotes stdin: echo 'hi \ there' echo folks expected-stdout: hi \ there folks --- name: bksl-nl-ign-3 description: Check that \newline is not collapsed inside single quotes stdin: cat << \EOF hi \ there EOF expected-stdout: hi \ there --- name: bksl-nl-ign-4 description: Check interaction of aliases, single quotes and here-documents with backslash-newline (don't know what POSIX has to say about this) stdin: a=2 alias x='echo hi cat << "EOF" foo\ bar some' x more\ stuff$a EOF expected-stdout: hi foo\ bar some more\ stuff$a --- name: bksl-nl-ign-5 description: Check what happens with backslash at end of input (the old Bourne shell trashes them; so do we) stdin: ! echo `echo foo\\`bar echo hi\ expected-stdout: foobar hi --- # # Places \newline should be collapsed # name: bksl-nl-1 description: Check that \newline is collapsed before, in the middle of, and after words stdin: \ echo hi\ There, \ folks expected-stdout: hiThere, folks --- name: bksl-nl-2 description: Check that \newline is collapsed in $ sequences (ksh93 fails this) stdin: a=12 ab=19 echo $\ a echo $a\ b echo $\ {a} echo ${a\ b} echo ${ab\ } expected-stdout: 12 19 12 19 19 --- name: bksl-nl-3 description: Check that \newline is collapsed in $(..) and `...` sequences (ksh93 fails this) stdin: echo $\ (echo foobar1) echo $(\ echo foobar2) echo $(echo foo\ bar3) echo $(echo foobar4\ ) echo ` echo stuff1` echo `echo st\ uff2` expected-stdout: foobar1 foobar2 foobar3 foobar4 stuff1 stuff2 --- name: bksl-nl-4 description: Check that \newline is collapsed in $((..)) sequences (ksh93 fails this) stdin: echo $\ ((1+2)) echo $(\ (1+2+3)) echo $((\ 1+2+3+4)) echo $((1+\ 2+3+4+5)) echo $((1+2+3+4+5+6)\ ) expected-stdout: 3 6 10 15 21 --- name: bksl-nl-5 description: Check that \newline is collapsed in double quoted strings stdin: echo "\ hi" echo "foo\ bar" echo "folks\ " expected-stdout: hi foobar folks --- name: bksl-nl-6 description: Check that \newline is collapsed in here document delimiters (ksh93 fails second part of this) stdin: a=12 cat << EO\ F a=$a foo\ bar EOF cat << E_O_F foo E_O_\ F echo done expected-stdout: a=12 foobar foo done --- name: bksl-nl-7 description: Check that \newline is collapsed in double-quoted here-document delimiter. stdin: a=12 cat << "EO\ F" a=$a foo\ bar EOF echo done expected-stdout: a=$a foo\ bar done --- name: bksl-nl-8 description: Check that \newline is collapsed in various 2+ character tokens delimiter. (ksh93 fails this) stdin: echo hi &\ & echo there echo foo |\ | echo bar cat <\ < EOF stuff EOF cat <\ <\ - EOF more stuff EOF cat <<\ EOF abcdef EOF echo hi >\ > /dev/null echo $? i=1 case $i in (\ x|\ 1\ ) echo hi;\ ; (*) echo oops esac expected-stdout: hi there foo stuff more stuff abcdef 0 hi --- name: bksl-nl-9 description: Check that \ at the end of an alias is collapsed when followed by a newline (don't know what POSIX has to say about this) stdin: alias x='echo hi\' x echo there expected-stdout: hiecho there --- name: bksl-nl-10 description: Check that \newline in a keyword is collapsed stdin: i\ f true; then\ echo pass; el\ se echo fail; fi expected-stdout: pass --- # # Places \newline should be collapsed (ksh extensions) # name: bksl-nl-ksh-1 description: Check that \newline is collapsed in extended globbing (ksh93 fails this) stdin: xxx=foo case $xxx in (f*\ (\ o\ )\ ) echo ok ;; *) echo bad esac expected-stdout: ok --- name: bksl-nl-ksh-2 description: Check that \newline is collapsed in ((...)) expressions (ksh93 fails this) stdin: i=1 (\ (\ i=i+2\ )\ ) echo $i expected-stdout: 3 --- name: break-1 description: See if break breaks out of loops stdin: for i in a b c; do echo $i; break; echo bad-$i; done echo end-1 for i in a b c; do echo $i; break 1; echo bad-$i; done echo end-2 for i in a b c; do for j in x y z; do echo $i:$j break echo bad-$i done echo end-$i done echo end-3 expected-stdout: a end-1 a end-2 a:x end-a b:x end-b c:x end-c end-3 --- name: break-2 description: See if break breaks out of nested loops stdin: for i in a b c; do for j in x y z; do echo $i:$j break 2 echo bad-$i done echo end-$i done echo end expected-stdout: a:x end --- name: break-3 description: What if break used outside of any loops (ksh88,ksh93 don't print error messages here) stdin: break expected-stderr-pattern: /.*break.*/ --- name: break-4 description: What if break N used when only N-1 loops (ksh88,ksh93 don't print error messages here) stdin: for i in a b c; do echo $i; break 2; echo bad-$i; done echo end expected-stdout: a end expected-stderr-pattern: /.*break.*/ --- name: break-5 description: Error if break argument isn't a number stdin: for i in a b c; do echo $i; break abc; echo more-$i; done echo end expected-stdout: a expected-exit: e != 0 expected-stderr-pattern: /.*break.*/ --- name: continue-1 description: See if continue continues loops stdin: for i in a b c; do echo $i; continue; echo bad-$i ; done echo end-1 for i in a b c; do echo $i; continue 1; echo bad-$i; done echo end-2 for i in a b c; do for j in x y z; do echo $i:$j continue echo bad-$i-$j done echo end-$i done echo end-3 expected-stdout: a b c end-1 a b c end-2 a:x a:y a:z end-a b:x b:y b:z end-b c:x c:y c:z end-c end-3 --- name: continue-2 description: See if continue breaks out of nested loops stdin: for i in a b c; do for j in x y z; do echo $i:$j continue 2 echo bad-$i-$j done echo end-$i done echo end expected-stdout: a:x b:x c:x end --- name: continue-3 description: What if continue used outside of any loops (ksh88,ksh93 don't print error messages here) stdin: continue expected-stderr-pattern: /.*continue.*/ --- name: continue-4 description: What if continue N used when only N-1 loops (ksh88,ksh93 don't print error messages here) stdin: for i in a b c; do echo $i; continue 2; echo bad-$i; done echo end expected-stdout: a b c end expected-stderr-pattern: /.*continue.*/ --- name: continue-5 description: Error if continue argument isn't a number stdin: for i in a b c; do echo $i; continue abc; echo more-$i; done echo end expected-stdout: a expected-exit: e != 0 expected-stderr-pattern: /.*continue.*/ --- name: cd-history description: Test someone's CD history package (uses arrays) stdin: # go to known place before doing anything cd / alias cd=_cd function _cd { typeset -i cdlen i typeset t if [ $# -eq 0 ] then set -- $HOME fi if [ "$CDHISTFILE" -a -r "$CDHISTFILE" ] # if directory history exists then typeset CDHIST i=-1 while read -r t # read directory history file do CDHIST[i=i+1]=$t done <$CDHISTFILE fi if [ "${CDHIST[0]}" != "$PWD" -a "$PWD" != "" ] then _cdins # insert $PWD into cd history fi cdlen=${#CDHIST[*]} # number of elements in history case "$@" in -) # cd to new dir if [ "$OLDPWD" = "" ] && ((cdlen>1)) then 'print' ${CDHIST[1]} 'cd' ${CDHIST[1]} _pwd else 'cd' $@ _pwd fi ;; -l) # print directory list typeset -R3 num ((i=cdlen)) while (((i=i-1)>=0)) do num=$i 'print' "$num ${CDHIST[i]}" done return ;; -[0-9]|-[0-9][0-9]) # cd to dir in list if (((i=${1#-})=cdlen)) then 'cd' $@ _pwd fi ;; *) # cd to new dir 'cd' $@ _pwd ;; esac _cdins # insert $PWD into cd history if [ "$CDHISTFILE" ] then cdlen=${#CDHIST[*]} # number of elements in history i=0 while ((i$CDHISTFILE fi } function _cdins # insert $PWD into cd history { # meant to be called only by _cd typeset -i i ((i=0)) while ((i<${#CDHIST[*]})) # see if dir is already in list do if [ "${CDHIST[$i]}" = "$PWD" ] then break fi ((i=i+1)) done if ((i>22)) # limit max size of list then i=22 fi while (((i=i-1)>=0)) # bump old dirs in list do CDHIST[i+1]=${CDHIST[i]} done CDHIST[0]=$PWD # insert new directory in list } function _pwd { if [ -n "$ECD" ] then pwd 1>&6 fi } # Start of test cd /tmp cd /bin cd /etc cd - cd -2 cd -l expected-stdout: /bin /tmp 3 / 2 /etc 1 /bin 0 /tmp --- name: cd-pe description: Check package for cd -Pe need-pass: no # the mv command fails on Cygwin # Hurd aborts the testsuite (permission denied) # QNX does not find subdir to cd into category: !os:cygwin,!os:gnu,!os:msys,!os:nto,!os:os390,!nosymlink file-setup: file 644 "x" mkdir noread noread/target noread/target/subdir ln -s noread link chmod 311 noread cd -P$1 . echo 0=$? bwd=$PWD cd -P$1 link/target echo 1=$?,${PWD#$bwd/} epwd=$($TSHELL -c pwd 2>/dev/null) # This unexpectedly succeeds on GNU/Linux and MidnightBSD #echo pwd=$?,$epwd # expect: pwd=1, mv ../../noread ../../renamed cd -P$1 subdir echo 2=$?,${PWD#$bwd/} cd $bwd chmod 755 renamed rm -rf noread link renamed stdin: export TSHELL="$__progname" "$__progname" x echo "now with -e:" "$__progname" x e expected-stdout: 0=0 1=0,noread/target 2=0,noread/target/subdir now with -e: 0=0 1=0,noread/target 2=1,noread/target/subdir --- name: env-prompt description: Check that prompt not printed when processing ENV env-setup: !ENV=./foo! file-setup: file 644 "foo" XXX=_ PS1=X false && echo hmmm need-ctty: yes arguments: !-i! stdin: echo hi${XXX}there expected-stdout: hi_there expected-stderr: ! XX --- name: expand-ugly description: Check that weird ${foo+bar} constructs are parsed correctly stdin: print '#!'"$__progname"'\nfor x in "$@"; do print -r -- "$x"; done' >pfn print '#!'"$__progname"'\nfor x in "$@"; do print -nr -- "<$x> "; done' >pfs chmod +x pfn pfs (echo 1 ${IFS+'}'z}) 2>/dev/null || echo failed in 1 (echo 2 "${IFS+'}'z}") 2>/dev/null || echo failed in 2 (echo 3 "foo ${IFS+'bar} baz") 2>/dev/null || echo failed in 3 (echo -n '4 '; ./pfn "foo ${IFS+"b c"} baz") 2>/dev/null || echo failed in 4 (echo -n '5 '; ./pfn "foo ${IFS+b c} baz") 2>/dev/null || echo failed in 5 (echo 6 ${IFS+"}"z}) 2>/dev/null || echo failed in 6 (echo 7 "${IFS+"}"z}") 2>/dev/null || echo failed in 7 (echo 8 "${IFS+\"}\"z}") 2>/dev/null || echo failed in 8 (echo 9 "${IFS+\"\}\"z}") 2>/dev/null || echo failed in 9 (echo 10 foo ${IFS+'bar} baz'}) 2>/dev/null || echo failed in 10 (echo 11 "$(echo "${IFS+'}'z}")") 2>/dev/null || echo failed in 11 (echo 12 "$(echo ${IFS+'}'z})") 2>/dev/null || echo failed in 12 (echo 13 ${IFS+\}z}) 2>/dev/null || echo failed in 13 (echo 14 "${IFS+\}z}") 2>/dev/null || echo failed in 14 u=x; (echo -n '15 '; ./pfs "foo ${IFS+a"b$u{ {"{{\}b} c ${IFS+d{}} bar" ${IFS-e{}} baz; echo .) 2>/dev/null || echo failed in 15 l=t; (echo 16 ${IFS+h`echo -n i ${IFS+$l}h`ere}) 2>/dev/null || echo failed in 16 l=t; (echo 17 ${IFS+h$(echo -n i ${IFS+$l}h)ere}) 2>/dev/null || echo failed in 17 l=t; (echo 18 "${IFS+h`echo -n i ${IFS+$l}h`ere}") 2>/dev/null || echo failed in 18 l=t; (echo 19 "${IFS+h$(echo -n i ${IFS+$l}h)ere}") 2>/dev/null || echo failed in 19 l=t; (echo 20 ${IFS+h`echo -n i "${IFS+$l}"h`ere}) 2>/dev/null || echo failed in 20 l=t; (echo 21 ${IFS+h$(echo -n i "${IFS+$l}"h)ere}) 2>/dev/null || echo failed in 21 l=t; (echo 22 "${IFS+h`echo -n i "${IFS+$l}"h`ere}") 2>/dev/null || echo failed in 22 l=t; (echo 23 "${IFS+h$(echo -n i "${IFS+$l}"h)ere}") 2>/dev/null || echo failed in 23 key=value; (echo -n '24 '; ./pfn "${IFS+'$key'}") 2>/dev/null || echo failed in 24 key=value; (echo -n '25 '; ./pfn "${IFS+"'$key'"}") 2>/dev/null || echo failed in 25 # ksh93: “'$key'” key=value; (echo -n '26 '; ./pfn ${IFS+'$key'}) 2>/dev/null || echo failed in 26 key=value; (echo -n '27 '; ./pfn ${IFS+"'$key'"}) 2>/dev/null || echo failed in 27 (echo -n '28 '; ./pfn "${IFS+"'"x ~ x'}'x"'}"x}" #') 2>/dev/null || echo failed in 28 u=x; (echo -n '29 '; ./pfs foo ${IFS+a"b$u{ {"{ {\}b} c ${IFS+d{}} bar ${IFS-e{}} baz; echo .) 2>/dev/null || echo failed in 29 (echo -n '30 '; ./pfs ${IFS+foo 'b\ ar' baz}; echo .) 2>/dev/null || (echo failed in 30; echo failed in 31) (echo -n '32 '; ./pfs ${IFS+foo "b\ ar" baz}; echo .) 2>/dev/null || echo failed in 32 (echo -n '33 '; ./pfs "${IFS+foo 'b\ ar' baz}"; echo .) 2>/dev/null || echo failed in 33 (echo -n '34 '; ./pfs "${IFS+foo "b\ ar" baz}"; echo .) 2>/dev/null || echo failed in 34 (echo -n '35 '; ./pfs ${v=a\ b} x ${v=c\ d}; echo .) 2>/dev/null || echo failed in 35 (echo -n '36 '; ./pfs "${v=a\ b}" x "${v=c\ d}"; echo .) 2>/dev/null || echo failed in 36 (echo -n '37 '; ./pfs ${v-a\ b} x ${v-c\ d}; echo .) 2>/dev/null || echo failed in 37 (echo 38 ${IFS+x'a'y} / "${IFS+x'a'y}" .) 2>/dev/null || echo failed in 38 foo="x'a'y"; (echo 39 ${foo%*'a'*} / "${foo%*'a'*}" .) 2>/dev/null || echo failed in 39 foo="a b c"; (echo -n '40 '; ./pfs "${foo#a}"; echo .) 2>/dev/null || echo failed in 40 (foo() { return 100; }; foo; echo 41 ${#+${#:+${#?}}\ \}\}\}}) 2>/dev/null || echo failed in 41 expected-stdout: 1 }z 2 ''z} 3 foo 'bar baz 4 foo b c baz 5 foo b c baz 6 }z 7 }z 8 ""z} 9 "}"z 10 foo bar} baz 11 ''z} 12 }z 13 }z 14 }z 15 <}> . 16 hi there 17 hi there 18 hi there 19 hi there 20 hi there 21 hi there 22 hi there 23 hi there 24 'value' 25 'value' 26 $key 27 'value' 28 'x ~ x''x}"x}" # 29 <{}b> <}> . 30 . 32 . 33 . 34 . 35 . 36 . 37 . 38 xay / x'a'y . 39 x' / x' . 40 < b c> . 41 3 }}} --- name: expand-unglob-dblq description: Check that regular "${foo+bar}" constructs are parsed correctly stdin: u=x tl_norm() { v=$2 test x"$v" = x"-" && unset v (echo "$1 plus norm foo ${v+'bar'} baz") (echo "$1 dash norm foo ${v-'bar'} baz") (echo "$1 eqal norm foo ${v='bar'} baz") (echo "$1 qstn norm foo ${v?'bar'} baz") 2>/dev/null || \ echo "$1 qstn norm -> error" (echo "$1 PLUS norm foo ${v:+'bar'} baz") (echo "$1 DASH norm foo ${v:-'bar'} baz") (echo "$1 EQAL norm foo ${v:='bar'} baz") (echo "$1 QSTN norm foo ${v:?'bar'} baz") 2>/dev/null || \ echo "$1 QSTN norm -> error" } tl_paren() { v=$2 test x"$v" = x"-" && unset v (echo "$1 plus parn foo ${v+(bar)} baz") (echo "$1 dash parn foo ${v-(bar)} baz") (echo "$1 eqal parn foo ${v=(bar)} baz") (echo "$1 qstn parn foo ${v?(bar)} baz") 2>/dev/null || \ echo "$1 qstn parn -> error" (echo "$1 PLUS parn foo ${v:+(bar)} baz") (echo "$1 DASH parn foo ${v:-(bar)} baz") (echo "$1 EQAL parn foo ${v:=(bar)} baz") (echo "$1 QSTN parn foo ${v:?(bar)} baz") 2>/dev/null || \ echo "$1 QSTN parn -> error" } tl_brace() { v=$2 test x"$v" = x"-" && unset v (echo "$1 plus brac foo ${v+a$u{{{\}b} c ${v+d{}} baz") (echo "$1 dash brac foo ${v-a$u{{{\}b} c ${v-d{}} baz") (echo "$1 eqal brac foo ${v=a$u{{{\}b} c ${v=d{}} baz") (echo "$1 qstn brac foo ${v?a$u{{{\}b} c ${v?d{}} baz") 2>/dev/null || \ echo "$1 qstn brac -> error" (echo "$1 PLUS brac foo ${v:+a$u{{{\}b} c ${v:+d{}} baz") (echo "$1 DASH brac foo ${v:-a$u{{{\}b} c ${v:-d{}} baz") (echo "$1 EQAL brac foo ${v:=a$u{{{\}b} c ${v:=d{}} baz") (echo "$1 QSTN brac foo ${v:?a$u{{{\}b} c ${v:?d{}} baz") 2>/dev/null || \ echo "$1 QSTN brac -> error" } : '}}}' '}}}' '}}}' '}}}' '}}}' '}}}' '}}}' '}}}' tl_norm 1 - tl_norm 2 '' tl_norm 3 x tl_paren 4 - tl_paren 5 '' tl_paren 6 x tl_brace 7 - tl_brace 8 '' tl_brace 9 x expected-stdout: 1 plus norm foo baz 1 dash norm foo 'bar' baz 1 eqal norm foo 'bar' baz 1 qstn norm -> error 1 PLUS norm foo baz 1 DASH norm foo 'bar' baz 1 EQAL norm foo 'bar' baz 1 QSTN norm -> error 2 plus norm foo 'bar' baz 2 dash norm foo baz 2 eqal norm foo baz 2 qstn norm foo baz 2 PLUS norm foo baz 2 DASH norm foo 'bar' baz 2 EQAL norm foo 'bar' baz 2 QSTN norm -> error 3 plus norm foo 'bar' baz 3 dash norm foo x baz 3 eqal norm foo x baz 3 qstn norm foo x baz 3 PLUS norm foo 'bar' baz 3 DASH norm foo x baz 3 EQAL norm foo x baz 3 QSTN norm foo x baz 4 plus parn foo baz 4 dash parn foo (bar) baz 4 eqal parn foo (bar) baz 4 qstn parn -> error 4 PLUS parn foo baz 4 DASH parn foo (bar) baz 4 EQAL parn foo (bar) baz 4 QSTN parn -> error 5 plus parn foo (bar) baz 5 dash parn foo baz 5 eqal parn foo baz 5 qstn parn foo baz 5 PLUS parn foo baz 5 DASH parn foo (bar) baz 5 EQAL parn foo (bar) baz 5 QSTN parn -> error 6 plus parn foo (bar) baz 6 dash parn foo x baz 6 eqal parn foo x baz 6 qstn parn foo x baz 6 PLUS parn foo (bar) baz 6 DASH parn foo x baz 6 EQAL parn foo x baz 6 QSTN parn foo x baz 7 plus brac foo c } baz 7 dash brac foo ax{{{}b c d{} baz 7 eqal brac foo ax{{{}b c ax{{{}b} baz 7 qstn brac -> error 7 PLUS brac foo c } baz 7 DASH brac foo ax{{{}b c d{} baz 7 EQAL brac foo ax{{{}b c ax{{{}b} baz 7 QSTN brac -> error 8 plus brac foo ax{{{}b c d{} baz 8 dash brac foo c } baz 8 eqal brac foo c } baz 8 qstn brac foo c } baz 8 PLUS brac foo c } baz 8 DASH brac foo ax{{{}b c d{} baz 8 EQAL brac foo ax{{{}b c ax{{{}b} baz 8 QSTN brac -> error 9 plus brac foo ax{{{}b c d{} baz 9 dash brac foo x c x} baz 9 eqal brac foo x c x} baz 9 qstn brac foo x c x} baz 9 PLUS brac foo ax{{{}b c d{} baz 9 DASH brac foo x c x} baz 9 EQAL brac foo x c x} baz 9 QSTN brac foo x c x} baz --- name: expand-unglob-unq description: Check that regular ${foo+bar} constructs are parsed correctly stdin: u=x tl_norm() { v=$2 test x"$v" = x"-" && unset v (echo $1 plus norm foo ${v+'bar'} baz) (echo $1 dash norm foo ${v-'bar'} baz) (echo $1 eqal norm foo ${v='bar'} baz) (echo $1 qstn norm foo ${v?'bar'} baz) 2>/dev/null || \ echo "$1 qstn norm -> error" (echo $1 PLUS norm foo ${v:+'bar'} baz) (echo $1 DASH norm foo ${v:-'bar'} baz) (echo $1 EQAL norm foo ${v:='bar'} baz) (echo $1 QSTN norm foo ${v:?'bar'} baz) 2>/dev/null || \ echo "$1 QSTN norm -> error" } tl_paren() { v=$2 test x"$v" = x"-" && unset v (echo $1 plus parn foo ${v+\(bar')'} baz) (echo $1 dash parn foo ${v-\(bar')'} baz) (echo $1 eqal parn foo ${v=\(bar')'} baz) (echo $1 qstn parn foo ${v?\(bar')'} baz) 2>/dev/null || \ echo "$1 qstn parn -> error" (echo $1 PLUS parn foo ${v:+\(bar')'} baz) (echo $1 DASH parn foo ${v:-\(bar')'} baz) (echo $1 EQAL parn foo ${v:=\(bar')'} baz) (echo $1 QSTN parn foo ${v:?\(bar')'} baz) 2>/dev/null || \ echo "$1 QSTN parn -> error" } tl_brace() { v=$2 test x"$v" = x"-" && unset v (echo $1 plus brac foo ${v+a$u{{{\}b} c ${v+d{}} baz) (echo $1 dash brac foo ${v-a$u{{{\}b} c ${v-d{}} baz) (echo $1 eqal brac foo ${v=a$u{{{\}b} c ${v=d{}} baz) (echo $1 qstn brac foo ${v?a$u{{{\}b} c ${v?d{}} baz) 2>/dev/null || \ echo "$1 qstn brac -> error" (echo $1 PLUS brac foo ${v:+a$u{{{\}b} c ${v:+d{}} baz) (echo $1 DASH brac foo ${v:-a$u{{{\}b} c ${v:-d{}} baz) (echo $1 EQAL brac foo ${v:=a$u{{{\}b} c ${v:=d{}} baz) (echo $1 QSTN brac foo ${v:?a$u{{{\}b} c ${v:?d{}} baz) 2>/dev/null || \ echo "$1 QSTN brac -> error" } : '}}}' '}}}' '}}}' '}}}' '}}}' '}}}' '}}}' '}}}' tl_norm 1 - tl_norm 2 '' tl_norm 3 x tl_paren 4 - tl_paren 5 '' tl_paren 6 x tl_brace 7 - tl_brace 8 '' tl_brace 9 x expected-stdout: 1 plus norm foo baz 1 dash norm foo bar baz 1 eqal norm foo bar baz 1 qstn norm -> error 1 PLUS norm foo baz 1 DASH norm foo bar baz 1 EQAL norm foo bar baz 1 QSTN norm -> error 2 plus norm foo bar baz 2 dash norm foo baz 2 eqal norm foo baz 2 qstn norm foo baz 2 PLUS norm foo baz 2 DASH norm foo bar baz 2 EQAL norm foo bar baz 2 QSTN norm -> error 3 plus norm foo bar baz 3 dash norm foo x baz 3 eqal norm foo x baz 3 qstn norm foo x baz 3 PLUS norm foo bar baz 3 DASH norm foo x baz 3 EQAL norm foo x baz 3 QSTN norm foo x baz 4 plus parn foo baz 4 dash parn foo (bar) baz 4 eqal parn foo (bar) baz 4 qstn parn -> error 4 PLUS parn foo baz 4 DASH parn foo (bar) baz 4 EQAL parn foo (bar) baz 4 QSTN parn -> error 5 plus parn foo (bar) baz 5 dash parn foo baz 5 eqal parn foo baz 5 qstn parn foo baz 5 PLUS parn foo baz 5 DASH parn foo (bar) baz 5 EQAL parn foo (bar) baz 5 QSTN parn -> error 6 plus parn foo (bar) baz 6 dash parn foo x baz 6 eqal parn foo x baz 6 qstn parn foo x baz 6 PLUS parn foo (bar) baz 6 DASH parn foo x baz 6 EQAL parn foo x baz 6 QSTN parn foo x baz 7 plus brac foo c } baz 7 dash brac foo ax{{{}b c d{} baz 7 eqal brac foo ax{{{}b c ax{{{}b} baz 7 qstn brac -> error 7 PLUS brac foo c } baz 7 DASH brac foo ax{{{}b c d{} baz 7 EQAL brac foo ax{{{}b c ax{{{}b} baz 7 QSTN brac -> error 8 plus brac foo ax{{{}b c d{} baz 8 dash brac foo c } baz 8 eqal brac foo c } baz 8 qstn brac foo c } baz 8 PLUS brac foo c } baz 8 DASH brac foo ax{{{}b c d{} baz 8 EQAL brac foo ax{{{}b c ax{{{}b} baz 8 QSTN brac -> error 9 plus brac foo ax{{{}b c d{} baz 9 dash brac foo x c x} baz 9 eqal brac foo x c x} baz 9 qstn brac foo x c x} baz 9 PLUS brac foo ax{{{}b c d{} baz 9 DASH brac foo x c x} baz 9 EQAL brac foo x c x} baz 9 QSTN brac foo x c x} baz --- name: expand-threecolons-dblq description: Check for a particular thing that used to segfault stdin: TEST=1234 echo "${TEST:1:2:3}" echo $? but still living expected-stderr-pattern: /bad substitution/ expected-exit: 1 --- name: expand-threecolons-unq description: Check for a particular thing that used to not error out stdin: TEST=1234 echo ${TEST:1:2:3} echo $? but still living expected-stderr-pattern: /bad substitution/ expected-exit: 1 --- name: expand-weird-1 description: Check corner cases of trim expansion vs. $# vs. ${#var} vs. ${var?} stdin: set 1 2 3 4 5 6 7 8 9 10 11 echo ${#} # value of $# echo ${##} # length of $# echo ${##1} # $# trimmed 1 set 1 2 3 4 5 6 7 8 9 10 11 12 echo ${##1} (exit 0) echo $? = ${#?} . (exit 111) echo $? = ${#?} . expected-stdout: 11 2 1 2 0 = 1 . 111 = 3 . --- name: expand-weird-2 description: Check more substitution and extension corner cases stdin: :& set -C; pid=$$; sub=$!; flg=$-; set -- i; exec 3>x.tmp #echo "D: !=$! #=$# \$=$$ -=$- ?=$?" echo >&3 3 = s^${!-word} , ${#-word} , p^${$-word} , f^${--word} , ${?-word} . echo >&3 4 = ${!+word} , ${#+word} , ${$+word} , ${-+word} , ${?+word} . echo >&3 5 = s^${!=word} , ${#=word} , p^${$=word} , f^${-=word} , ${?=word} . echo >&3 6 = s^${!?word} , ${#?word} , p^${$?word} , f^${-?word} , ${??word} . echo >&3 7 = sl^${#!} , ${##} , pl^${#$} , fl^${#-} , ${#?} . echo >&3 8 = sw^${%!} , ${%#} , pw^${%$} , fw^${%-} , ${%?} . echo >&3 9 = ${!!} , s^${!#} , ${!$} , s^${!-} , s^${!?} . echo >&3 10 = s^${!#pattern} , ${##pattern} , p^${$#pattern} , f^${-#pattern} , ${?#pattern} . echo >&3 11 = s^${!%pattern} , ${#%pattern} , p^${$%pattern} , f^${-%pattern} , ${?%pattern} . echo >&3 12 = $# : ${##} , ${##1} . set -- echo >&3 14 = $# : ${##} , ${##1} . set -- 1 2 3 4 5 echo >&3 16 = $# : ${##} , ${##1} . set -- 1 2 3 4 5 6 7 8 9 a b c d e echo >&3 18 = $# : ${##} , ${##1} . exec 3>&- <${a#\~}> <${b:-~}> <${b:-\~}> <${c:=~}><$c> <${a/~}> <${a/x/~}> <${a/x/\~}>" expected-stdout: <~/x> <~> <\~> <~><~> <~/x> <~//etc> <~/~> --- name: expand-bang-1 description: Check corner case of ${!?} with ! being var vs. op stdin: echo ${!?} expected-exit: 1 expected-stderr-pattern: /not set/ --- name: expand-bang-2 description: Check corner case of ${!var} vs. ${var op} with var=! stdin: echo 1 $! . echo 2 ${!#} . echo 3 ${!#[0-9]} . echo 4 ${!-foo} . # get an at least three-digit bg pid while :; do :& x=$! if [[ $x != +([0-9]) ]]; then echo >&2 "cannot test, pid '$x' not numeric" echo >&2 report this with as many details as possible exit 1 fi [[ $x = [0-9][0-9][0-9]* ]] && break done y=${x#?} t=$!; [[ $t = $x ]]; echo 5 $? . t=${!#}; [[ $t = $x ]]; echo 6 $? . t=${!#[0-9]}; [[ $t = $y ]]; echo 7 $? . t=${!-foo}; [[ $t = $x ]]; echo 8 $? . t=${!?bar}; [[ $t = $x ]]; echo 9 $? . expected-stdout: 1 . 2 . 3 . 4 foo . 5 0 . 6 0 . 7 0 . 8 0 . 9 0 . --- name: expand-number-1 description: Check that positional arguments do not overflow stdin: echo "1 ${12345678901234567890} ." expected-stdout: 1 . --- name: expand-slashes-1 description: Check that side effects in substring replacement are handled correctly stdin: foo=n1n1n1n2n3 i=2 n=1 echo 1 ${foo//n$((n++))/[$((++i))]} . echo 2 $n , $i . expected-stdout: 1 [3][3][3]n2n3 . 2 2 , 3 . --- name: expand-slashes-2 description: Check that side effects in substring replacement are handled correctly stdin: foo=n1n1n1n2n3 i=2 n=1 echo 1 ${foo@/n$((n++))/[$((++i))]} . echo 2 $n , $i . expected-stdout: 1 [3]n1n1[4][5] . 2 5 , 5 . --- name: expand-slashes-3 description: Check that we can access the replaced string stdin: foo=n1n1n1n2n3 echo 1 ${foo@/n[12]/[$KSH_MATCH]} . expected-stdout: 1 [n1][n1][n1][n2]n3 . --- name: eglob-bad-1 description: Check that globbing isn't done when glob has syntax error file-setup: file 644 "abcx" file-setup: file 644 "abcz" file-setup: file 644 "bbc" stdin: echo !([*)* echo +(a|b[)* expected-stdout: !([*)* +(a|b[)* --- name: eglob-bad-2 description: Check that globbing isn't done when glob has syntax error (AT&T ksh fails this test) file-setup: file 644 "abcx" file-setup: file 644 "abcz" file-setup: file 644 "bbc" stdin: echo [a*(]*)z expected-stdout: [a*(]*)z --- name: eglob-infinite-plus description: Check that shell doesn't go into infinite loop expanding +(...) expressions. file-setup: file 644 "abc" time-limit: 3 stdin: echo +()c echo +()x echo +(*)c echo +(*)x expected-stdout: +()c +()x abc +(*)x --- name: eglob-subst-1 description: Check that eglobbing isn't done on substitution results file-setup: file 644 "abc" stdin: x='@(*)' echo $x expected-stdout: @(*) --- name: eglob-nomatch-1 description: Check that the pattern doesn't match stdin: echo 1: no-file+(a|b)stuff echo 2: no-file+(a*(c)|b)stuff echo 3: no-file+((((c)))|b)stuff expected-stdout: 1: no-file+(a|b)stuff 2: no-file+(a*(c)|b)stuff 3: no-file+((((c)))|b)stuff --- name: eglob-match-1 description: Check that the pattern matches correctly file-setup: file 644 "abd" file-setup: file 644 "acd" file-setup: file 644 "abac" stdin: echo 1: a+(b|c)d echo 2: a!(@(b|B))d echo 3: *(a(b|c)) # (...|...) can be used within X(..) echo 4: a[b*(foo|bar)]d # patterns not special inside [...] expected-stdout: 1: abd acd 2: acd 3: abac 4: abd --- name: eglob-case-1 description: Simple negation tests stdin: case foo in !(foo|bar)) echo yes;; *) echo no;; esac case bar in !(foo|bar)) echo yes;; *) echo no;; esac expected-stdout: no no --- name: eglob-case-2 description: Simple kleene tests stdin: case foo in *(a|b[)) echo yes;; *) echo no;; esac case foo in *(a|b[)|f*) echo yes;; *) echo no;; esac case '*(a|b[)' in *(a|b[)) echo yes;; *) echo no;; esac expected-stdout: no yes yes --- name: eglob-trim-1 description: Eglobbing in trim expressions... (AT&T ksh fails this - docs say # matches shortest string, ## matches longest...) stdin: x=abcdef echo 1: ${x#a|abc} echo 2: ${x##a|abc} echo 3: ${x%def|f} echo 4: ${x%%f|def} expected-stdout: 1: bcdef 2: def 3: abcde 4: abc --- name: eglob-trim-2 description: Check eglobbing works in trims... stdin: x=abcdef echo 1: ${x#*(a|b)cd} echo 2: "${x#*(a|b)cd}" echo 3: ${x#"*(a|b)cd"} echo 4: ${x#a(b|c)} expected-stdout: 1: ef 2: ef 3: abcdef 4: cdef --- name: eglob-trim-3 description: Check eglobbing works in trims, for Korn Shell Ensure eglobbing does not work for reduced-feature /bin/sh stdin: set +o sh x=foobar y=foobaz z=fooba\? echo "<${x%bar|baz},${y%bar|baz},${z%\?}>" echo "<${x%ba(r|z)},${y%ba(r|z)}>" set -o sh echo "<${x%bar|baz},${y%bar|baz},${z%\?}>" z='foo(bar' echo "<${z%(*}>" expected-stdout: --- name: eglob-substrpl-1 description: Check eglobbing works in substs... and they work at all stdin: [[ -n $BASH_VERSION ]] && shopt -s extglob x=1222321_ab/cde_b/c_1221 y=xyz echo 1: ${x/2} . ${x/} echo 2: ${x//2} echo 3: ${x/+(2)} echo 4: ${x//+(2)} echo 5: ${x/2/4} echo 6: ${x//2/4} echo 7: ${x/+(2)/4} echo 8: ${x//+(2)/4} echo 9: ${x/b/c/e/f} echo 10: ${x/b\/c/e/f} echo 11: ${x/b\/c/e\/f} echo 12: ${x/b\/c/e\\/f} echo 13: ${x/b\\/c/e\\/f} echo 14: ${x//b/c/e/f} echo 15: ${x//b\/c/e/f} echo 16: ${x//b\/c/e\/f} echo 17: ${x//b\/c/e\\/f} echo 18: ${x//b\\/c/e\\/f} echo 19: ${x/b\/*\/c/x} echo 20: ${x/\//.} echo 21: ${x//\//.} echo 22: ${x///.} echo 23: ${x/#1/9} echo 24: ${x//#1/9} echo 25: ${x/%1/9} echo 26: ${x//%1/9} echo 27: ${x//\%1/9} echo 28: ${x//\\%1/9} echo 29: ${x//\a/9} echo 30: ${x//\\a/9} echo 31: ${x/2/$y} expected-stdout: 1: 122321_ab/cde_b/c_1221 . 1222321_ab/cde_b/c_1221 2: 131_ab/cde_b/c_11 3: 1321_ab/cde_b/c_1221 4: 131_ab/cde_b/c_11 5: 1422321_ab/cde_b/c_1221 6: 1444341_ab/cde_b/c_1441 7: 14321_ab/cde_b/c_1221 8: 14341_ab/cde_b/c_141 9: 1222321_ac/e/f/cde_b/c_1221 10: 1222321_ae/fde_b/c_1221 11: 1222321_ae/fde_b/c_1221 12: 1222321_ae\/fde_b/c_1221 13: 1222321_ab/cde_b/c_1221 14: 1222321_ac/e/f/cde_c/e/f/c_1221 15: 1222321_ae/fde_e/f_1221 16: 1222321_ae/fde_e/f_1221 17: 1222321_ae\/fde_e\/f_1221 18: 1222321_ab/cde_b/c_1221 19: 1222321_ax_1221 20: 1222321_ab.cde_b/c_1221 21: 1222321_ab.cde_b.c_1221 22: 1222321_ab/cde_b/c_1221 23: 9222321_ab/cde_b/c_1221 24: 1222321_ab/cde_b/c_1221 25: 1222321_ab/cde_b/c_1229 26: 1222321_ab/cde_b/c_1221 27: 1222321_ab/cde_b/c_1221 28: 1222321_ab/cde_b/c_1221 29: 1222321_9b/cde_b/c_1221 30: 1222321_ab/cde_b/c_1221 31: 1xyz22321_ab/cde_b/c_1221 --- name: eglob-substrpl-2 description: Check anchored substring replacement works, corner cases stdin: foo=123 echo 1: ${foo/#/x} echo 2: ${foo/%/x} echo 3: ${foo/#/} echo 4: ${foo/#} echo 5: ${foo/%/} echo 6: ${foo/%} expected-stdout: 1: x123 2: 123x 3: 123 4: 123 5: 123 6: 123 --- name: eglob-substrpl-3a description: Check substring replacement works with variables and slashes, too stdin: HOME=/etc pfx=/home/user wd=/home/user/tmp echo "${wd/#$pfx/~}" echo "${wd/#\$pfx/~}" echo "${wd/#"$pfx"/~}" echo "${wd/#'$pfx'/~}" echo "${wd/#"\$pfx"/~}" echo "${wd/#'\$pfx'/~}" expected-stdout: /etc/tmp /home/user/tmp /etc/tmp /home/user/tmp /home/user/tmp /home/user/tmp --- name: eglob-substrpl-3b description: More of this, bash fails it (bash4 passes) stdin: HOME=/etc pfx=/home/user wd=/home/user/tmp echo "${wd/#$(echo /home/user)/~}" echo "${wd/#"$(echo /home/user)"/~}" echo "${wd/#'$(echo /home/user)'/~}" expected-stdout: /etc/tmp /etc/tmp /home/user/tmp --- name: eglob-substrpl-3c description: Even more weird cases stdin: HOME=/etc pfx=/home/user wd='$pfx/tmp' echo 1: ${wd/#$pfx/~} echo 2: ${wd/#\$pfx/~} echo 3: ${wd/#"$pfx"/~} echo 4: ${wd/#'$pfx'/~} echo 5: ${wd/#"\$pfx"/~} echo 6: ${wd/#'\$pfx'/~} ts='a/ba/b$tp$tp_a/b$tp_*(a/b)_*($tp)' tp=a/b tr=c/d [[ -n $BASH_VERSION ]] && shopt -s extglob echo 7: ${ts/a\/b/$tr} echo 8: ${ts/a\/b/\$tr} echo 9: ${ts/$tp/$tr} echo 10: ${ts/\$tp/$tr} echo 11: ${ts/\\$tp/$tr} echo 12: ${ts/$tp/c/d} echo 13: ${ts/$tp/c\/d} echo 14: ${ts/$tp/c\\/d} echo 15: ${ts/+(a\/b)/$tr} echo 16: ${ts/+(a\/b)/\$tr} echo 17: ${ts/+($tp)/$tr} echo 18: ${ts/+($tp)/c/d} echo 19: ${ts/+($tp)/c\/d} echo 20: ${ts//a\/b/$tr} echo 21: ${ts//a\/b/\$tr} echo 22: ${ts//$tp/$tr} echo 23: ${ts//$tp/c/d} echo 24: ${ts//$tp/c\/d} echo 25: ${ts//+(a\/b)/$tr} echo 26: ${ts//+(a\/b)/\$tr} echo 27: ${ts//+($tp)/$tr} echo 28: ${ts//+($tp)/c/d} echo 29: ${ts//+($tp)/c\/d} tp="+($tp)" echo 30: ${ts/$tp/$tr} echo 31: ${ts//$tp/$tr} expected-stdout: 1: $pfx/tmp 2: /etc/tmp 3: $pfx/tmp 4: /etc/tmp 5: /etc/tmp 6: $pfx/tmp 7: c/da/b$tp$tp_a/b$tp_*(a/b)_*($tp) 8: $tra/b$tp$tp_a/b$tp_*(a/b)_*($tp) 9: c/da/b$tp$tp_a/b$tp_*(a/b)_*($tp) 10: a/ba/bc/d$tp_a/b$tp_*(a/b)_*($tp) 11: a/ba/b$tp$tp_a/b$tp_*(a/b)_*($tp) 12: c/da/b$tp$tp_a/b$tp_*(a/b)_*($tp) 13: c/da/b$tp$tp_a/b$tp_*(a/b)_*($tp) 14: c\/da/b$tp$tp_a/b$tp_*(a/b)_*($tp) 15: c/d$tp$tp_a/b$tp_*(a/b)_*($tp) 16: $tr$tp$tp_a/b$tp_*(a/b)_*($tp) 17: c/d$tp$tp_a/b$tp_*(a/b)_*($tp) 18: c/d$tp$tp_a/b$tp_*(a/b)_*($tp) 19: c/d$tp$tp_a/b$tp_*(a/b)_*($tp) 20: c/dc/d$tp$tp_c/d$tp_*(c/d)_*($tp) 21: $tr$tr$tp$tp_$tr$tp_*($tr)_*($tp) 22: c/dc/d$tp$tp_c/d$tp_*(c/d)_*($tp) 23: c/dc/d$tp$tp_c/d$tp_*(c/d)_*($tp) 24: c/dc/d$tp$tp_c/d$tp_*(c/d)_*($tp) 25: c/d$tp$tp_c/d$tp_*(c/d)_*($tp) 26: $tr$tp$tp_$tr$tp_*($tr)_*($tp) 27: c/d$tp$tp_c/d$tp_*(c/d)_*($tp) 28: c/d$tp$tp_c/d$tp_*(c/d)_*($tp) 29: c/d$tp$tp_c/d$tp_*(c/d)_*($tp) 30: a/ba/b$tp$tp_a/b$tp_*(a/b)_*($tp) 31: a/ba/b$tp$tp_a/b$tp_*(a/b)_*($tp) # This is what GNU bash does: # 30: c/d$tp$tp_a/b$tp_*(a/b)_*($tp) # 31: c/d$tp$tp_c/d$tp_*(c/d)_*($tp) --- name: eglob-utf8-1 description: UTF-8 mode differences for eglobbing stdin: s=blöd set +U print 1: ${s%???} . print 2: ${s/b???d/x} . set -U print 3: ${s%???} . print 4: ${s/b??d/x} . x=nö print 5: ${x%?} ${x%%?} . x=äh print 6: ${x#?} ${x##?} . x= print 7: ${x%?} ${x%%?} . x=mä print 8: ${x%?} ${x%%?} . x=何 print 9: ${x%?} ${x%%?} . expected-stdout: 1: bl . 2: x . 3: b . 4: x . 5: n n . 6: h h . 7: . 8: mä mä . 9: . --- name: glob-bad-1 description: Check that globbing isn't done when glob has syntax error file-setup: dir 755 "[x" file-setup: file 644 "[x/foo" stdin: echo [* echo *[x echo [x/* expected-stdout: [* *[x [x/foo --- name: glob-bad-2 description: Check that symbolic links aren't stat()'d # breaks on Dell UNIX 4.0 R2.2 (SVR4) where unlink also fails # breaks on FreeMiNT (cannot unlink dangling symlinks) # breaks on MSYS, OS/2 (do not support symlinks) category: !os:mint,!os:msys,!os:svr4.0,!nosymlink file-setup: dir 755 "dir" file-setup: symlink 644 "dir/abc" non-existent-file stdin: echo d*/* echo d*/abc expected-stdout: dir/abc dir/abc --- name: glob-range-1 description: Test range matching file-setup: file 644 ".bc" file-setup: file 644 "abc" file-setup: file 644 "bbc" file-setup: file 644 "cbc" file-setup: file 644 "-bc" stdin: echo [ab-]* echo [-ab]* echo [!-ab]* echo [!ab]* echo []ab]* :>'./!bc' :>'./^bc' echo [^ab]* echo [!ab]* expected-stdout: -bc abc bbc -bc abc bbc cbc -bc cbc abc bbc ^bc abc bbc !bc -bc ^bc cbc --- name: glob-range-2 description: Test range matching (AT&T ksh fails this; POSIX says invalid) file-setup: file 644 "abc" stdin: echo [a--]* expected-stdout: [a--]* --- name: glob-range-3 description: Check that globbing matches the right things... # breaks on Mac OSX (HFS+ non-standard Unicode canonical decomposition) # breaks on Cygwin 1.7 (files are now UTF-16 or something) # breaks on QNX 6.4.1 (says RT) category: !os:cygwin,!os:darwin,!os:msys,!os:nto,!os:os2 need-pass: no file-setup: file 644 "ac" stdin: echo a[-]* expected-stdout: ac --- name: glob-range-4 description: Results unspecified according to POSIX file-setup: file 644 ".bc" stdin: echo [a.]* expected-stdout: [a.]* --- name: glob-range-5 description: Results unspecified according to POSIX (AT&T ksh treats this like [a-cc-e]*) file-setup: file 644 "abc" file-setup: file 644 "bbc" file-setup: file 644 "cbc" file-setup: file 644 "dbc" file-setup: file 644 "ebc" file-setup: file 644 "-bc" stdin: echo [a-c-e]* expected-stdout: -bc abc bbc cbc ebc --- name: glob-trim-1 description: Check against a regression from fixing IFS-subst-2 stdin: x='#foo' print -r "before='$x'" x=${x%%#*} print -r "after ='$x'" expected-stdout: before='#foo' after ='' --- name: heredoc-1 description: Check ordering/content of redundent here documents. stdin: cat << EOF1 << EOF2 hi EOF1 there EOF2 expected-stdout: there --- name: heredoc-2 description: Check quoted here-doc is protected. stdin: a=foo cat << 'EOF' hi\ there$a stuff EO\ F EOF expected-stdout: hi\ there$a stuff EO\ F --- name: heredoc-3 description: Check that newline isn't needed after heredoc-delimiter marker. stdin: ! cat << EOF hi there EOF expected-stdout: hi there --- name: heredoc-4a description: Check that an error occurs if the heredoc-delimiter is missing. stdin: ! cat << EOF hi there expected-exit: e > 0 expected-stderr-pattern: /.*/ --- name: heredoc-4an description: Check that an error occurs if the heredoc-delimiter is missing. arguments: !-n! stdin: ! cat << EOF hi there expected-exit: e > 0 expected-stderr-pattern: /.*/ --- name: heredoc-4b description: Check that an error occurs if the heredoc is missing. stdin: ! cat << EOF expected-exit: e > 0 expected-stderr-pattern: /.*/ --- name: heredoc-4bn description: Check that an error occurs if the heredoc is missing. arguments: !-n! stdin: ! cat << EOF expected-exit: e > 0 expected-stderr-pattern: /.*/ --- name: heredoc-5 description: Check that backslash quotes a $, ` and \ and kills a \newline stdin: a=BAD b=ok cat << EOF h\${a}i h\\${b}i th\`echo not-run\`ere th\\`echo is-run`ere fol\\ks more\\ last \ line EOF expected-stdout: h${a}i h\oki th`echo not-run`ere th\is-runere fol\ks more\ last line --- name: heredoc-6 description: Check that \newline in initial here-delim word doesn't imply a quoted here-doc. stdin: a=i cat << EO\ F h$a there EOF expected-stdout: hi there --- name: heredoc-7 description: Check that double quoted $ expressions in here delimiters are not expanded and match the delimiter. POSIX says only quote removal is applied to the delimiter. stdin: a=b cat << "E$a" hi h$a hb E$a echo done expected-stdout: hi h$a hb done --- name: heredoc-8 description: Check that double quoted escaped $ expressions in here delimiters are not expanded and match the delimiter. POSIX says only quote removal is applied to the delimiter (\ counts as a quote). stdin: a=b cat << "E\$a" hi h$a h\$a hb h\b E$a echo done expected-stdout: hi h$a h\$a hb h\b done --- name: heredoc-9a description: Check that here strings work. stdin: bar="bar baz" tr abcdefghijklmnopqrstuvwxyz nopqrstuvwxyzabcdefghijklm <</dev/null) expected-stdout: baz --- name: heredoc-9f description: Check long here strings stdin: cat <<< "$( : )aa" expected-stdout: aa --- name: heredoc-10 description: Check direct here document assignment stdin: x=u va=<" y=$(<<-EOF hi! $foo) is not a problem EOF) echo "7<$y>" expected-stdout: 3 7 --- name: heredoc-subshell-1 description: Tests for here documents in subshells, taken from Austin ML stdin: (cat <&1 echo hi echo there fc -e - expected-stdout-pattern: /X*hi\nX*there\nX*echo there\nthere\nX*/ expected-stderr-pattern: /^X*$/ --- name: history-e-minus-3 description: fc -e - fails when there is no history (ksh93 has a bug that causes this to fail) (ksh88 loops on this) need-ctty: yes arguments: !-i! env-setup: !ENV=./Env!HISTFILE=hist.file! file-setup: file 644 "Env" PS1=X stdin: fc -e - echo ok expected-stdout: ok expected-stderr-pattern: /^X*.*:.*history.*\nX*$/ --- name: history-e-minus-4 description: Check if "fc -e -" command output goes to stdout. need-ctty: yes arguments: !-i! env-setup: !ENV=./Env!HISTFILE=hist.file! file-setup: file 644 "Env" PS1=X stdin: echo abc fc -e - | (read x; echo "A $x") echo ok expected-stdout: abc A abc ok expected-stderr-pattern: /^X*echo abc\nX*/ --- name: history-e-minus-5 description: fc is replaced in history by new command. need-ctty: yes arguments: !-i! env-setup: !ENV=./Env!HISTFILE=hist.file! file-setup: file 644 "Env" PS1=X stdin: echo abc def echo ghi jkl : fc -e - echo fc -l 2 5 expected-stdout: abc def ghi jkl ghi jkl 2 echo ghi jkl 3 : 4 echo ghi jkl 5 fc -l 2 5 expected-stderr-pattern: /^X*echo ghi jkl\nX*$/ --- name: history-list-1 description: List lists correct range (ksh88 fails 'cause it lists the fc command) need-ctty: yes arguments: !-i! env-setup: !ENV=./Env!HISTFILE=hist.file! file-setup: file 644 "Env" PS1=X stdin: echo line 1 echo line 2 echo line 3 fc -l -- -2 expected-stdout: line 1 line 2 line 3 2 echo line 2 3 echo line 3 expected-stderr-pattern: /^X*$/ --- name: history-list-2 description: Lists oldest history if given pre-historic number (ksh93 has a bug that causes this to fail) (ksh88 fails 'cause it lists the fc command) need-ctty: yes arguments: !-i! env-setup: !ENV=./Env!HISTFILE=hist.file! file-setup: file 644 "Env" PS1=X stdin: echo line 1 echo line 2 echo line 3 fc -l -- -40 expected-stdout: line 1 line 2 line 3 1 echo line 1 2 echo line 2 3 echo line 3 expected-stderr-pattern: /^X*$/ --- name: history-list-3 description: Can give number 'options' to fc need-ctty: yes arguments: !-i! env-setup: !ENV=./Env!HISTFILE=hist.file! file-setup: file 644 "Env" PS1=X stdin: echo line 1 echo line 2 echo line 3 echo line 4 fc -l -3 -2 expected-stdout: line 1 line 2 line 3 line 4 2 echo line 2 3 echo line 3 expected-stderr-pattern: /^X*$/ --- name: history-list-4 description: -1 refers to previous command need-ctty: yes arguments: !-i! env-setup: !ENV=./Env!HISTFILE=hist.file! file-setup: file 644 "Env" PS1=X stdin: echo line 1 echo line 2 echo line 3 echo line 4 fc -l -1 -1 expected-stdout: line 1 line 2 line 3 line 4 4 echo line 4 expected-stderr-pattern: /^X*$/ --- name: history-list-5 description: List command stays in history need-ctty: yes arguments: !-i! env-setup: !ENV=./Env!HISTFILE=hist.file! file-setup: file 644 "Env" PS1=X stdin: echo line 1 echo line 2 echo line 3 echo line 4 fc -l -1 -1 fc -l -2 -1 expected-stdout: line 1 line 2 line 3 line 4 4 echo line 4 4 echo line 4 5 fc -l -1 -1 expected-stderr-pattern: /^X*$/ --- name: history-list-6 description: HISTSIZE limits about of history kept. (ksh88 fails 'cause it lists the fc command) need-ctty: yes arguments: !-i! env-setup: !ENV=./Env!HISTFILE=hist.file!HISTSIZE=3! file-setup: file 644 "Env" PS1=X stdin: echo line 1 echo line 2 echo line 3 echo line 4 echo line 5 fc -l expected-stdout: line 1 line 2 line 3 line 4 line 5 4 echo line 4 5 echo line 5 expected-stderr-pattern: /^X*$/ --- name: history-list-7 description: fc allows too old/new errors in range specification need-ctty: yes arguments: !-i! env-setup: !ENV=./Env!HISTFILE=hist.file!HISTSIZE=3! file-setup: file 644 "Env" PS1=X stdin: echo line 1 echo line 2 echo line 3 echo line 4 echo line 5 fc -l 1 30 expected-stdout: line 1 line 2 line 3 line 4 line 5 4 echo line 4 5 echo line 5 6 fc -l 1 30 expected-stderr-pattern: /^X*$/ --- name: history-list-r-1 description: test -r flag in history need-ctty: yes arguments: !-i! env-setup: !ENV=./Env!HISTFILE=hist.file! file-setup: file 644 "Env" PS1=X stdin: echo line 1 echo line 2 echo line 3 echo line 4 echo line 5 fc -l -r 2 4 expected-stdout: line 1 line 2 line 3 line 4 line 5 4 echo line 4 3 echo line 3 2 echo line 2 expected-stderr-pattern: /^X*$/ --- name: history-list-r-2 description: If first is newer than last, -r is implied. need-ctty: yes arguments: !-i! env-setup: !ENV=./Env!HISTFILE=hist.file! file-setup: file 644 "Env" PS1=X stdin: echo line 1 echo line 2 echo line 3 echo line 4 echo line 5 fc -l 4 2 expected-stdout: line 1 line 2 line 3 line 4 line 5 4 echo line 4 3 echo line 3 2 echo line 2 expected-stderr-pattern: /^X*$/ --- name: history-list-r-3 description: If first is newer than last, -r is cancelled. need-ctty: yes arguments: !-i! env-setup: !ENV=./Env!HISTFILE=hist.file! file-setup: file 644 "Env" PS1=X stdin: echo line 1 echo line 2 echo line 3 echo line 4 echo line 5 fc -l -r 4 2 expected-stdout: line 1 line 2 line 3 line 4 line 5 2 echo line 2 3 echo line 3 4 echo line 4 expected-stderr-pattern: /^X*$/ --- name: history-subst-1 description: Basic substitution need-ctty: yes arguments: !-i! env-setup: !ENV=./Env!HISTFILE=hist.file! file-setup: file 644 "Env" PS1=X stdin: echo abc def echo ghi jkl fc -e - abc=AB 'echo a' expected-stdout: abc def ghi jkl AB def expected-stderr-pattern: /^X*echo AB def\nX*$/ --- name: history-subst-2 description: Does subst find previous command? need-ctty: yes arguments: !-i! env-setup: !ENV=./Env!HISTFILE=hist.file! file-setup: file 644 "Env" PS1=X stdin: echo abc def echo ghi jkl fc -e - jkl=XYZQRT 'echo g' expected-stdout: abc def ghi jkl ghi XYZQRT expected-stderr-pattern: /^X*echo ghi XYZQRT\nX*$/ --- name: history-subst-3 description: Does subst find previous command when no arguments given need-ctty: yes arguments: !-i! env-setup: !ENV=./Env!HISTFILE=hist.file! file-setup: file 644 "Env" PS1=X stdin: echo abc def echo ghi jkl fc -e - jkl=XYZQRT expected-stdout: abc def ghi jkl ghi XYZQRT expected-stderr-pattern: /^X*echo ghi XYZQRT\nX*$/ --- name: history-subst-4 description: Global substitutions work (ksh88 and ksh93 do not have -g option) need-ctty: yes arguments: !-i! env-setup: !ENV=./Env!HISTFILE=hist.file! file-setup: file 644 "Env" PS1=X stdin: echo abc def asjj sadjhasdjh asdjhasd fc -e - -g a=FooBAR expected-stdout: abc def asjj sadjhasdjh asdjhasd FooBARbc def FooBARsjj sFooBARdjhFooBARsdjh FooBARsdjhFooBARsd expected-stderr-pattern: /^X*echo FooBARbc def FooBARsjj sFooBARdjhFooBARsdjh FooBARsdjhFooBARsd\nX*$/ --- name: history-subst-5 description: Make sure searches don't find current (fc) command (ksh88/ksh93 don't have the ? prefix thing so they fail this test) need-ctty: yes arguments: !-i! env-setup: !ENV=./Env!HISTFILE=hist.file! file-setup: file 644 "Env" PS1=X stdin: echo abc def echo ghi jkl fc -e - abc=AB \?abc expected-stdout: abc def ghi jkl AB def expected-stderr-pattern: /^X*echo AB def\nX*$/ --- name: history-ed-1-old description: Basic (ed) editing works (assumes you have generic ed editor that prints no prompts). This is for oldish ed(1) which write the character count to stdout. category: stdout-ed need-ctty: yes need-pass: no arguments: !-i! env-setup: !ENV=./Env!HISTFILE=hist.file! file-setup: file 644 "Env" PS1=X stdin: echo abc def fc echo s/abc/FOOBAR/ w q expected-stdout: abc def 13 16 FOOBAR def expected-stderr-pattern: /^X*echo FOOBAR def\nX*$/ --- name: history-ed-2-old description: Correct command is edited when number given category: stdout-ed need-ctty: yes need-pass: no arguments: !-i! env-setup: !ENV=./Env!HISTFILE=hist.file! file-setup: file 644 "Env" PS1=X stdin: echo line 1 echo line 2 is here echo line 3 echo line 4 fc 2 s/is here/is changed/ w q expected-stdout: line 1 line 2 is here line 3 line 4 20 23 line 2 is changed expected-stderr-pattern: /^X*echo line 2 is changed\nX*$/ --- name: history-ed-3-old description: Newly created multi line commands show up as single command in history. (ksh88 fails 'cause it lists the fc command) category: stdout-ed need-ctty: yes need-pass: no arguments: !-i! env-setup: !ENV=./Env!HISTFILE=hist.file! file-setup: file 644 "Env" PS1=X stdin: echo abc def fc echo s/abc/FOOBAR/ $a echo a new line . w q fc -l expected-stdout: abc def 13 32 FOOBAR def a new line 1 echo abc def 2 echo FOOBAR def echo a new line expected-stderr-pattern: /^X*echo FOOBAR def\necho a new line\nX*$/ --- name: history-ed-1 description: Basic (ed) editing works (assumes you have generic ed editor that prints no prompts). This is for newish ed(1) and stderr. category: !no-stderr-ed need-ctty: yes need-pass: no arguments: !-i! env-setup: !ENV=./Env!HISTFILE=hist.file! file-setup: file 644 "Env" PS1=X stdin: echo abc def fc echo s/abc/FOOBAR/ w q expected-stdout: abc def FOOBAR def expected-stderr-pattern: /^X*13\n16\necho FOOBAR def\nX*$/ --- name: history-ed-2 description: Correct command is edited when number given category: !no-stderr-ed need-ctty: yes need-pass: no arguments: !-i! env-setup: !ENV=./Env!HISTFILE=hist.file! file-setup: file 644 "Env" PS1=X stdin: echo line 1 echo line 2 is here echo line 3 echo line 4 fc 2 s/is here/is changed/ w q expected-stdout: line 1 line 2 is here line 3 line 4 line 2 is changed expected-stderr-pattern: /^X*20\n23\necho line 2 is changed\nX*$/ --- name: history-ed-3 description: Newly created multi line commands show up as single command in history. category: !no-stderr-ed need-ctty: yes need-pass: no arguments: !-i! env-setup: !ENV=./Env!HISTFILE=hist.file! file-setup: file 644 "Env" PS1=X stdin: echo abc def fc echo s/abc/FOOBAR/ $a echo a new line . w q fc -l expected-stdout: abc def FOOBAR def a new line 1 echo abc def 2 echo FOOBAR def echo a new line expected-stderr-pattern: /^X*13\n32\necho FOOBAR def\necho a new line\nX*$/ --- name: IFS-space-1 description: Simple test, default IFS stdin: showargs() { for s_arg in "$@"; do echo -n "<$s_arg> "; done; echo .; } set -- A B C showargs 1 $* showargs 2 "$*" showargs 3 $@ showargs 4 "$@" expected-stdout: <1> . <2> . <3> . <4> . --- name: IFS-colon-1 description: Simple test, IFS=: stdin: showargs() { for s_arg in "$@"; do echo -n "<$s_arg> "; done; echo .; } IFS=: set -- A B C showargs 1 $* showargs 2 "$*" showargs 3 $@ showargs 4 "$@" expected-stdout: <1> . <2> . <3> . <4> . --- name: IFS-null-1 description: Simple test, IFS="" stdin: showargs() { for s_arg in "$@"; do echo -n "<$s_arg> "; done; echo .; } IFS="" set -- A B C showargs 1 $* showargs 2 "$*" showargs 3 $@ showargs 4 "$@" expected-stdout: <1> . <2> . <3> . <4> . --- name: IFS-space-colon-1 description: Simple test, IFS=: stdin: showargs() { for s_arg in "$@"; do echo -n "<$s_arg> "; done; echo .; } IFS="$IFS:" set -- showargs 1 $* showargs 2 "$*" showargs 3 $@ showargs 4 "$@" showargs 5 : "$@" expected-stdout: <1> . <2> <> . <3> . <4> . <5> <:> . --- name: IFS-space-colon-2 description: Simple test, IFS=: AT&T ksh fails this, POSIX says the test is correct. stdin: showargs() { for s_arg in "$@"; do echo -n "<$s_arg> "; done; echo .; } IFS="$IFS:" set -- showargs :"$@" expected-stdout: <:> . --- name: IFS-space-colon-4 description: Simple test, IFS=: stdin: showargs() { for s_arg in "$@"; do echo -n "<$s_arg> "; done; echo .; } IFS="$IFS:" set -- showargs "$@$@" expected-stdout: . --- name: IFS-space-colon-5 description: Simple test, IFS=: Don't know what POSIX thinks of this. AT&T ksh does not do this. stdin: showargs() { for s_arg in "$@"; do echo -n "<$s_arg> "; done; echo .; } IFS="$IFS:" set -- showargs "${@:-}" expected-stdout: <> . --- name: IFS-subst-1 description: Simple test, IFS=: stdin: showargs() { for s_arg in "$@"; do echo -n "<$s_arg> "; done; echo .; } IFS="$IFS:" x=":b: :" echo -n '1:'; for i in $x ; do echo -n " [$i]" ; done ; echo echo -n '2:'; for i in :b:: ; do echo -n " [$i]" ; done ; echo showargs 3 $x showargs 4 :b:: x="a:b:" echo -n '5:'; for i in $x ; do echo -n " [$i]" ; done ; echo showargs 6 $x x="a::c" echo -n '7:'; for i in $x ; do echo -n " [$i]" ; done ; echo showargs 8 $x echo -n '9:'; for i in ${FOO-`echo -n h:i`th:ere} ; do echo -n " [$i]" ; done ; echo showargs 10 ${FOO-`echo -n h:i`th:ere} showargs 11 "${FOO-`echo -n h:i`th:ere}" x=" A : B::D" echo -n '12:'; for i in $x ; do echo -n " [$i]" ; done ; echo showargs 13 $x expected-stdout: 1: [] [b] [] 2: [:b::] <3> <> <> . <4> <:b::> . 5: [a] [b] <6> . 7: [a] [] [c] <8> <> . 9: [h] [ith] [ere] <10> . <11> . 12: [A] [B] [] [D] <13> <> . --- name: IFS-subst-2 description: Check leading whitespace after trim does not make a field stdin: showargs() { for s_arg in "$@"; do echo -n "<$s_arg> "; done; echo .; } x="X 1 2" showargs 1 shift ${x#X} expected-stdout: <1> <1> <2> . --- name: IFS-subst-3-arr description: Check leading IFS non-whitespace after trim does make a field but leading IFS whitespace does not, nor empty replacements stdin: showargs() { for s_arg in "$@"; do echo -n "<$s_arg> "; done; echo .; } showargs 0 ${-+} IFS=: showargs 1 ${-+:foo:bar} IFS=' ' showargs 2 ${-+ foo bar} expected-stdout: <0> . <1> <> . <2> . --- name: IFS-subst-3-ass description: Check non-field semantics stdin: showargs() { for s_arg in "$@"; do echo -n "<$s_arg> "; done; echo .; } showargs 0 x=${-+} IFS=: showargs 1 x=${-+:foo:bar} IFS=' ' showargs 2 x=${-+ foo bar} expected-stdout: <0> . <1> . <2> . --- name: IFS-subst-3-lcl description: Check non-field semantics, smaller corner case (LP#1381965) stdin: set -x local regex=${2:-} exit 1 expected-exit: e != 0 expected-stderr-pattern: /regex=/ --- name: IFS-subst-4-1 description: reported by mikeserv stdin: pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; } a='space divded argument here' IFS=\ ; set -- $a IFS= ; q="$*" ; nq=$* pfn "$*" $* "$q" "$nq" [ "$q" = "$nq" ] && echo =true || echo =false expected-stdout: =true --- name: IFS-subst-4-2 description: extended testsuite based on problem by mikeserv stdin: pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; } a='space divded argument here' IFS=\ ; set -- $a IFS= ; q="$@" ; nq=$@ pfn "$*" $* "$q" "$nq" [ "$q" = "$nq" ] && echo =true || echo =false expected-stdout: =true --- name: IFS-subst-4-3 description: extended testsuite based on problem by mikeserv stdin: pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; } a='space divded argument here' IFS=\ ; set -- $a; IFS= qs="$*" nqs=$* qk="$@" nqk=$@ print -nr -- '= qs '; pfn "$qs" print -nr -- '=nqs '; pfn "$nqs" print -nr -- '= qk '; pfn "$qk" print -nr -- '=nqk '; pfn "$nqk" print -nr -- '~ qs '; pfn "$*" print -nr -- '~nqs '; pfn $* print -nr -- '~ qk '; pfn "$@" print -nr -- '~nqk '; pfn $@ expected-stdout: = qs =nqs = qk =nqk ~ qs ~nqs ~ qk ~nqk --- name: IFS-subst-4-4 description: extended testsuite based on problem by mikeserv stdin: pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; } a='space divded argument here' IFS=\ ; set -- $a; IFS= qs="$*" print -nr -- '= qs '; pfn "$qs" print -nr -- '~ qs '; pfn "$*" nqs=$* print -nr -- '=nqs '; pfn "$nqs" print -nr -- '~nqs '; pfn $* qk="$@" print -nr -- '= qk '; pfn "$qk" print -nr -- '~ qk '; pfn "$@" nqk=$@ print -nr -- '=nqk '; pfn "$nqk" print -nr -- '~nqk '; pfn $@ expected-stdout: = qs ~ qs =nqs ~nqs = qk ~ qk =nqk ~nqk --- name: IFS-subst-4-4p description: extended testsuite based on problem by mikeserv stdin: pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; } a='space divded argument here' IFS=\ ; set -- $a; IFS= unset v qs=${v:-"$*"} print -nr -- '= qs '; pfn "$qs" print -nr -- '~ qs '; pfn ${v:-"$*"} nqs=${v:-$*} print -nr -- '=nqs '; pfn "$nqs" print -nr -- '~nqs '; pfn ${v:-$*} qk=${v:-"$@"} print -nr -- '= qk '; pfn "$qk" print -nr -- '~ qk '; pfn ${v:-"$@"} nqk=${v:-$@} print -nr -- '=nqk '; pfn "$nqk" print -nr -- '~nqk '; pfn ${v:-$@} expected-stdout: = qs ~ qs =nqs ~nqs = qk ~ qk =nqk ~nqk --- name: IFS-subst-4-5 description: extended testsuite based on problem by mikeserv stdin: pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; } a='space divded argument here' IFS=\ ; set -- $a; IFS=, qs="$*" print -nr -- '= qs '; pfn "$qs" print -nr -- '~ qs '; pfn "$*" nqs=$* print -nr -- '=nqs '; pfn "$nqs" print -nr -- '~nqs '; pfn $* qk="$@" print -nr -- '= qk '; pfn "$qk" print -nr -- '~ qk '; pfn "$@" nqk=$@ print -nr -- '=nqk '; pfn "$nqk" print -nr -- '~nqk '; pfn $@ expected-stdout: = qs ~ qs =nqs ~nqs = qk ~ qk =nqk ~nqk --- name: IFS-subst-4-5p description: extended testsuite based on problem by mikeserv stdin: pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; } a='space divded argument here' IFS=\ ; set -- $a; IFS=, unset v qs=${v:-"$*"} print -nr -- '= qs '; pfn "$qs" print -nr -- '~ qs '; pfn ${v:-"$*"} nqs=${v:-$*} print -nr -- '=nqs '; pfn "$nqs" print -nr -- '~nqs '; pfn ${v:-$*} qk=${v:-"$@"} print -nr -- '= qk '; pfn "$qk" print -nr -- '~ qk '; pfn ${v:-"$@"} nqk=${v:-$@} print -nr -- '=nqk '; pfn "$nqk" print -nr -- '~nqk '; pfn ${v:-$@} expected-stdout: = qs ~ qs =nqs ~nqs = qk ~ qk =nqk ~nqk --- name: IFS-subst-5 description: extended testsuite based on IFS-subst-3 differs slightly from ksh93: - omit trailing field in a3zna, a7ina (unquoted $@ expansion) - has extra middle fields in b5ins, b7ina (IFS_NWS unquoted expansion) differs slightly from bash: - omit leading field in a5ins, a7ina (IFS_NWS unquoted expansion) differs slightly from zsh: - differs in assignment, not expansion; probably zsh bug - has extra middle fields in b5ins, b7ina (IFS_NWS unquoted expansion) 'emulate sh' zsh has extra fields in - a5ins (IFS_NWS unquoted $*) - b5ins, matching mksh’s !!WARNING!! more to come: http://austingroupbugs.net/view.php?id=888 stdin: "$__progname" -c 'pfb() { for s_arg in "$@"; do print -r -- "[$s_arg]"; done; }; pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; }; IFS=; set -- "" 2 ""; pfb $*; x=$*; pfn "$x"' echo '=a1zns' "$__progname" -c 'pfb() { for s_arg in "$@"; do print -r -- "[$s_arg]"; done; }; pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; }; IFS=; set -- "" 2 ""; pfb "$*"; x="$*"; pfn "$x"' echo '=a2zqs' "$__progname" -c 'pfb() { for s_arg in "$@"; do print -r -- "[$s_arg]"; done; }; pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; }; IFS=; set -- "" 2 ""; pfb $@; x=$@; pfn "$x"' echo '=a3zna' "$__progname" -c 'pfb() { for s_arg in "$@"; do print -r -- "[$s_arg]"; done; }; pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; }; IFS=; set -- "" 2 ""; pfb "$@"; x="$@"; pfn "$x"' echo '=a4zqa' "$__progname" -c 'pfb() { for s_arg in "$@"; do print -r -- "[$s_arg]"; done; }; pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; }; IFS=,; set -- "" 2 ""; pfb $*; x=$*; pfn "$x"' echo '=a5ins' "$__progname" -c 'pfb() { for s_arg in "$@"; do print -r -- "[$s_arg]"; done; }; pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; }; IFS=,; set -- "" 2 ""; pfb "$*"; x="$*"; pfn "$x"' echo '=a6iqs' "$__progname" -c 'pfb() { for s_arg in "$@"; do print -r -- "[$s_arg]"; done; }; pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; }; IFS=,; set -- "" 2 ""; pfb $@; x=$@; pfn "$x"' echo '=a7ina' "$__progname" -c 'pfb() { for s_arg in "$@"; do print -r -- "[$s_arg]"; done; }; pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; }; IFS=,; set -- "" 2 ""; pfb "$@"; x="$@"; pfn "$x"' echo '=a8iqa' "$__progname" -c 'pfb() { for s_arg in "$@"; do print -r -- "[$s_arg]"; done; }; pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; }; IFS=; set -- A B "" "" C; pfb $*; x=$*; pfn "$x"' echo '=b1zns' "$__progname" -c 'pfb() { for s_arg in "$@"; do print -r -- "[$s_arg]"; done; }; pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; }; IFS=; set -- A B "" "" C; pfb "$*"; x="$*"; pfn "$x"' echo '=b2zqs' "$__progname" -c 'pfb() { for s_arg in "$@"; do print -r -- "[$s_arg]"; done; }; pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; }; IFS=; set -- A B "" "" C; pfb $@; x=$@; pfn "$x"' echo '=b3zna' "$__progname" -c 'pfb() { for s_arg in "$@"; do print -r -- "[$s_arg]"; done; }; pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; }; IFS=; set -- A B "" "" C; pfb "$@"; x="$@"; pfn "$x"' echo '=b4zqa' "$__progname" -c 'pfb() { for s_arg in "$@"; do print -r -- "[$s_arg]"; done; }; pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; }; IFS=,; set -- A B "" "" C; pfb $*; x=$*; pfn "$x"' echo '=b5ins' "$__progname" -c 'pfb() { for s_arg in "$@"; do print -r -- "[$s_arg]"; done; }; pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; }; IFS=,; set -- A B "" "" C; pfb "$*"; x="$*"; pfn "$x"' echo '=b6iqs' "$__progname" -c 'pfb() { for s_arg in "$@"; do print -r -- "[$s_arg]"; done; }; pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; }; IFS=,; set -- A B "" "" C; pfb $@; x=$@; pfn "$x"' echo '=b7ina' "$__progname" -c 'pfb() { for s_arg in "$@"; do print -r -- "[$s_arg]"; done; }; pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; }; IFS=,; set -- A B "" "" C; pfb "$@"; x="$@"; pfn "$x"' echo '=b8iqa' expected-stdout: [2] <2> =a1zns [2] <2> =a2zqs [2] < 2 > =a3zna [] [2] [] < 2 > =a4zqa [2] <,2,> =a5ins [,2,] <,2,> =a6iqs [2] < 2 > =a7ina [] [2] [] < 2 > =a8iqa [A] [B] [C] =b1zns [ABC] =b2zqs [A] [B] [C] =b3zna [A] [B] [] [] [C] =b4zqa [A] [B] [] [] [C] =b5ins [A,B,,,C] =b6iqs [A] [B] [] [] [C] =b7ina [A] [B] [] [] [C] =b8iqa --- name: IFS-subst-6 description: Regression wrt. vector expansion in trim stdin: showargs() { for s_arg in "$@"; do echo -n "<$s_arg> "; done; echo .; } IFS= x=abc set -- a b showargs ${x#$*} expected-stdout: . --- name: IFS-subst-7 description: ksh93 bug wrt. vector expansion in trim stdin: showargs() { for s_arg in "$@"; do echo -n "<$s_arg> "; done; echo .; } IFS="*" a=abcd set -- '' c showargs "$*" ${a##"$*"} expected-stdout: <*c> . --- name: IFS-subst-8 description: http://austingroupbugs.net/view.php?id=221 stdin: n() { echo "$#"; }; n "${foo-$@}" expected-stdout: 1 --- name: IFS-subst-9 description: Scalar context for $*/$@ in [[ and case stdin: "$__progname" -c 'IFS=; set a b; [[ $* = "$1$2" ]]; echo 1 $?' sh a b "$__progname" -c 'IFS=; [[ $* = ab ]]; echo 2 "$?"' sh a b "$__progname" -c 'IFS=; [[ "$*" = ab ]]; echo 3 "$?"' sh a b "$__progname" -c 'IFS=; [[ $* = a ]]; echo 4 "$?"' sh a b "$__progname" -c 'IFS=; [[ "$*" = a ]]; echo 5 "$?"' sh a b "$__progname" -c 'IFS=; [[ "$@" = a ]]; echo 6 "$?"' sh a b "$__progname" -c 'IFS=; case "$@" in a) echo 7 a;; ab) echo 7 b;; a\ b) echo 7 ok;; esac' sh a b "$__progname" -c 'IFS=; case $* in a) echo 8 a;; ab) echo 8 ok;; esac' sh a b "$__progname" -c 'pfsp() { for s_arg in "$@"; do print -nr -- "<$s_arg> "; done; print .; }; IFS=; star=$* at="$@"; pfsp 9 "$star" "$at"' sh a b expected-stdout: 1 0 2 0 3 0 4 1 5 1 6 1 7 ok 8 ok <9> . --- name: IFS-subst-10 description: Scalar context in ${var=$subst} stdin: showargs() { for s_arg in "$@"; do echo -n "<$s_arg> "; done; echo .; } set -- one "two three" four unset -v var save_IFS=$IFS IFS= set -- ${var=$*} IFS=$save_IFS echo "var=$var" showargs "$@" expected-stdout: var=onetwo threefour . --- name: IFS-arith-1 description: http://austingroupbugs.net/view.php?id=832 stdin: ${ZSH_VERSION+false} || emulate sh ${BASH_VERSION+set -o posix} showargs() { for s_arg in "$@"; do echo -n "<$s_arg> "; done; echo .; } IFS=0 showargs $((1230456)) expected-stdout: <123> <456> . --- name: integer-base-err-1 description: Can't have 0 base (causes shell to exit) expected-exit: e != 0 stdin: typeset -i i i=3 i=0#4 echo $i expected-stderr-pattern: /^.*:.*0#4.*\n$/ --- name: integer-base-err-2 description: Can't have multiple bases in a 'constant' (causes shell to exit) (ksh88 fails this test) expected-exit: e != 0 stdin: typeset -i i i=3 i=2#110#11 echo $i expected-stderr-pattern: /^.*:.*2#110#11.*\n$/ --- name: integer-base-err-3 description: Syntax errors in expressions and effects on bases (interactive so errors don't cause exits) (ksh88 fails this test - shell exits, even with -i) need-ctty: yes arguments: !-i! stdin: PS1= # minimise prompt hassles typeset -i4 a=10 typeset -i a=2+ echo $a typeset -i4 a=10 typeset -i2 a=2+ echo $a expected-stderr-pattern: /^([#\$] )?.*:.*2+.*\n.*:.*2+.*\n$/ expected-stdout: 4#22 4#22 --- name: integer-base-err-4 description: Are invalid digits (according to base) errors? (ksh93 fails this test) expected-exit: e != 0 stdin: typeset -i i; i=3#4 expected-stderr-pattern: /^([#\$] )?.*:.*3#4.*\n$/ --- name: integer-base-1 description: Missing number after base is treated as 0. stdin: typeset -i i i=3 i=2# echo $i expected-stdout: 0 --- name: integer-base-2 description: Check 'stickyness' of base in various situations stdin: typeset -i i=8 echo $i echo ---------- A typeset -i4 j=8 echo $j echo ---------- B typeset -i k=8 typeset -i4 k=8 echo $k echo ---------- C typeset -i4 l l=3#10 echo $l echo ---------- D typeset -i m m=3#10 echo $m echo ---------- E n=2#11 typeset -i n echo $n n=10 echo $n echo ---------- F typeset -i8 o=12 typeset -i4 o echo $o echo ---------- G typeset -i p let p=8#12 echo $p expected-stdout: 8 ---------- A 4#20 ---------- B 4#20 ---------- C 4#3 ---------- D 3#10 ---------- E 2#11 2#1010 ---------- F 4#30 ---------- G 8#12 --- name: integer-base-3 description: More base parsing (hmm doesn't test much..) stdin: typeset -i aa aa=1+12#10+2 echo $aa typeset -i bb bb=1+$aa echo $bb typeset -i bb bb=$aa echo $bb typeset -i cc cc=$aa echo $cc expected-stdout: 15 16 15 15 --- name: integer-base-4 description: Check that things not declared as integers are not made integers, also, check if base is not reset by -i with no arguments. (ksh93 fails - prints 10#20 - go figure) stdin: xx=20 let xx=10 typeset -i | grep '^xx=' typeset -i4 a=10 typeset -i a=20 echo $a expected-stdout: 4#110 --- name: integer-base-5 description: More base stuff stdin: typeset -i4 a=3#10 echo $a echo -- typeset -i j=3 j='~3' echo $j echo -- typeset -i k=1 x[k=k+1]=3 echo $k echo -- typeset -i l for l in 1 2+3 4; do echo $l; done expected-stdout: 4#3 -- -4 -- 2 -- 1 5 4 --- name: integer-base-6 description: Even more base stuff (ksh93 fails this test - prints 0) stdin: typeset -i7 i i= echo $i expected-stdout: 7#0 --- name: integer-base-7 description: Check that non-integer parameters don't get bases assigned stdin: echo $(( zz = 8#100 )) echo $zz expected-stdout: 64 64 --- name: integer-base-8 description: Check that base-36 works (full span) stdin: echo 1:$((36#109AZ)). typeset -i36 x=1691675 echo 2:$x. typeset -Uui36 x echo 3:$x. expected-stdout: 1:1691675. 2:36#109az. 3:36#109AZ. --- name: integer-base-check-flat description: Check behaviour does not match POSuX (except if set -o posix), because a not type-safe scripting language has *no* business interpreting the string "010" as octal number eight (dangerous). stdin: echo 1 "$("$__progname" -c 'echo :$((10))/$((010)),$((0x10)):')" . echo 2 "$("$__progname" -o posix -c 'echo :$((10))/$((010)),$((0x10)):')" . echo 3 "$("$__progname" -o sh -c 'echo :$((10))/$((010)),$((0x10)):')" . expected-stdout: 1 :10/10,16: . 2 :10/8,16: . 3 :10/10,16: . --- name: integer-base-check-numeric-from description: Check behaviour for base one to 36, and that 37 degrades to 10 stdin: echo 1:$((1#1))0. i=1 while (( ++i <= 37 )); do eval 'echo '$i':$(('$i'#10)).' done echo 37:$($__progname -c 'echo $((37#10))').$?: expected-stdout: 1:490. 2:2. 3:3. 4:4. 5:5. 6:6. 7:7. 8:8. 9:9. 10:10. 11:11. 12:12. 13:13. 14:14. 15:15. 16:16. 17:17. 18:18. 19:19. 20:20. 21:21. 22:22. 23:23. 24:24. 25:25. 26:26. 27:27. 28:28. 29:29. 30:30. 31:31. 32:32. 33:33. 34:34. 35:35. 36:36. 37:10. 37:10.0: --- name: integer-base-check-numeric-to description: Check behaviour for base one to 36, and that 37 degrades to 10 stdin: i=0 while (( ++i <= 37 )); do typeset -Uui$i x=0x40 eval "typeset -i10 y=$x" print $i:$x.$y. done expected-stdout: 1:1#@.64. 2:2#1000000.64. 3:3#2101.64. 4:4#1000.64. 5:5#224.64. 6:6#144.64. 7:7#121.64. 8:8#100.64. 9:9#71.64. 10:64.64. 11:11#59.64. 12:12#54.64. 13:13#4C.64. 14:14#48.64. 15:15#44.64. 16:16#40.64. 17:17#3D.64. 18:18#3A.64. 19:19#37.64. 20:20#34.64. 21:21#31.64. 22:22#2K.64. 23:23#2I.64. 24:24#2G.64. 25:25#2E.64. 26:26#2C.64. 27:27#2A.64. 28:28#28.64. 29:29#26.64. 30:30#24.64. 31:31#22.64. 32:32#20.64. 33:33#1V.64. 34:34#1U.64. 35:35#1T.64. 36:36#1S.64. 37:64.64. --- name: integer-arithmetic-span description: Check wraparound and size that is defined in mksh category: int:32 stdin: echo s:$((2147483647+1)).$(((2147483647*2)+1)).$(((2147483647*2)+2)). echo u:$((#2147483647+1)).$((#(2147483647*2)+1)).$((#(2147483647*2)+2)). expected-stdout: s:-2147483648.-1.0. u:2147483648.4294967295.0. --- name: integer-arithmetic-span-64 description: Check wraparound and size that is defined in mksh category: int:64 stdin: echo s:$((9223372036854775807+1)).$(((9223372036854775807*2)+1)).$(((9223372036854775807*2)+2)). echo u:$((#9223372036854775807+1)).$((#(9223372036854775807*2)+1)).$((#(9223372036854775807*2)+2)). expected-stdout: s:-9223372036854775808.-1.0. u:9223372036854775808.18446744073709551615.0. --- name: integer-size-FAIL-to-detect description: Notify the user that their ints are not 32 or 64 bit category: int:u stdin: : --- name: lineno-stdin description: See if $LINENO is updated and can be modified. stdin: echo A $LINENO echo B $LINENO LINENO=20 echo C $LINENO expected-stdout: A 1 B 2 C 20 --- name: lineno-inc description: See if $LINENO is set for .'d files. file-setup: file 644 "dotfile" echo dot A $LINENO echo dot B $LINENO LINENO=20 echo dot C $LINENO stdin: echo A $LINENO echo B $LINENO . ./dotfile expected-stdout: A 1 B 2 dot A 1 dot B 2 dot C 20 --- name: lineno-func description: See if $LINENO is set for commands in a function. stdin: echo A $LINENO echo B $LINENO bar() { echo func A $LINENO echo func B $LINENO } bar echo C $LINENO expected-stdout: A 1 B 2 func A 4 func B 5 C 8 --- name: lineno-unset description: See if unsetting LINENO makes it non-magic. file-setup: file 644 "dotfile" echo dot A $LINENO echo dot B $LINENO stdin: unset LINENO echo A $LINENO echo B $LINENO bar() { echo func A $LINENO echo func B $LINENO } bar . ./dotfile echo C $LINENO expected-stdout: A B func A func B dot A dot B C --- name: lineno-unset-use description: See if unsetting LINENO makes it non-magic even when it is re-used. file-setup: file 644 "dotfile" echo dot A $LINENO echo dot B $LINENO stdin: unset LINENO LINENO=3 echo A $LINENO echo B $LINENO bar() { echo func A $LINENO echo func B $LINENO } bar . ./dotfile echo C $LINENO expected-stdout: A 3 B 3 func A 3 func B 3 dot A 3 dot B 3 C 3 --- name: lineno-trap description: Check if LINENO is tracked in traps stdin: fail() { echo "line <$1>" exit 1 } trap 'fail $LINENO' INT ERR false expected-stdout: line <6> expected-exit: 1 --- name: unknown-trap description: Ensure unknown traps are not a syntax error stdin: ( trap "echo trap 1 executed" UNKNOWNSIGNAL || echo "foo" echo =1 trap "echo trap 2 executed" UNKNOWNSIGNAL EXIT 999999 FNORD echo = $? ) 2>&1 | sed "s^${__progname%.exe}\.*e*x*e*: \[[0-9]*]PROG" expected-stdout: PROG: trap: bad signal 'UNKNOWNSIGNAL' foo =1 PROG: trap: bad signal 'UNKNOWNSIGNAL' PROG: trap: bad signal '999999' PROG: trap: bad signal 'FNORD' = 1 trap 2 executed --- name: read-IFS-1 description: Simple test, default IFS stdin: echo "A B " > IN unset x y z read x y z < IN echo 1: "x[$x] y[$y] z[$z]" echo 1a: ${z-z not set} read x < IN echo 2: "x[$x]" expected-stdout: 1: x[A] y[B] z[] 1a: 2: x[A B] --- name: read-IFS-2 description: Complex tests, IFS either colon (IFS-NWS) or backslash (tricky) stdin: n=0 showargs() { print -nr "$1"; shift; for s_arg in "$@"; do print -nr -- " [$s_arg]"; done; print; } (IFS=\\ a=\<\\\>; showargs 3 $a) (IFS=: b=\<:\>; showargs 4 $b) print -r '<\>' | (IFS=\\ read f g; showargs 5 "$f" "$g") print -r '<\\>' | (IFS=\\ read f g; showargs 6 "$f" "$g") print '<\\\n>' | (IFS=\\ read f g; showargs 7 "$f" "$g") print -r '<\>' | (IFS=\\ read f; showargs 8 "$f") print -r '<\\>' | (IFS=\\ read f; showargs 9 "$f") print '<\\\n>' | (IFS=\\ read f; showargs 10 "$f") print -r '<\>' | (IFS=\\ read -r f g; showargs 11 "$f" "$g") print -r '<\\>' | (IFS=\\ read -r f g; showargs 12 "$f" "$g") print '<\\\n>' | (IFS=\\ read -r f g; showargs 13 "$f" "$g") print -r '<\>' | (IFS=\\ read -r f; showargs 14 "$f") print -r '<\\>' | (IFS=\\ read -r f; showargs 15 "$f") print '<\\\n>' | (IFS=\\ read -r f; showargs 16 "$f") print -r '<:>' | (IFS=: read f g; showargs 17 "$f" "$g") print -r '<::>' | (IFS=: read f g; showargs 18 "$f" "$g") print '<:\n>' | (IFS=: read f g; showargs 19 "$f" "$g") print -r '<:>' | (IFS=: read f; showargs 20 "$f") print -r '<::>' | (IFS=: read f; showargs 21 "$f") print '<:\n>' | (IFS=: read f; showargs 22 "$f") print -r '<:>' | (IFS=: read -r f g; showargs 23 "$f" "$g") print -r '<::>' | (IFS=: read -r f g; showargs 24 "$f" "$g") print '<:\n>' | (IFS=: read -r f g; showargs 25 "$f" "$g") print -r '<:>' | (IFS=: read -r f; showargs 26 "$f") print -r '<::>' | (IFS=: read -r f; showargs 27 "$f") print '<:\n>' | (IFS=: read -r f; showargs 28 "$f") expected-stdout: 3 [<] [>] 4 [<] [>] 5 [<] [>] 6 [<] [>] 7 [<>] [] 8 [<>] 9 [<\>] 10 [<>] 11 [<] [>] 12 [<] [\>] 13 [<] [] 14 [<\>] 15 [<\\>] 16 [<] 17 [<] [>] 18 [<] [:>] 19 [<] [] 20 [<:>] 21 [<::>] 22 [<] 23 [<] [>] 24 [<] [:>] 25 [<] [] 26 [<:>] 27 [<::>] 28 [<] --- name: read-ksh-1 description: If no var specified, REPLY is used stdin: echo "abc" > IN read < IN echo "[$REPLY]"; expected-stdout: [abc] --- name: read-regress-1 description: Check a regression of read file-setup: file 644 "foo" foo bar baz blah stdin: while read a b c; do read d break done <$d>" expected-stdout: --- name: read-delim-1 description: Check read with delimiters stdin: emit() { print -n 'foo bar\tbaz\nblah \0blub\tblech\nmyok meck \0' } emit | while IFS= read -d "" foo; do print -r -- "<$foo>"; done emit | while read -d "" foo; do print -r -- "<$foo>"; done emit | while read -d "eh?" foo; do print -r -- "<$foo>"; done expected-stdout: --- name: read-ext-1 description: Check read with number of bytes specified, and -A stdin: print 'foo\nbar' >x1 print -n x >x2 print 'foo\\ bar baz' >x3 x1a=u; read x1a " print -r "x1b=<$x1b>" print -r "x2a=$r2a<$x2a>" print -r "x2b=$r2b<$x2b>" print -r "x2c=$r2c<$x2c>" print -r "x3a=<${x3a[0]}|${x3a[1]}|${x3a[2]}>" expected-stdout: x1a= x1b= x2a=1 x2b=1 x2c=0 x3a= --- name: regression-1 description: Lex array code had problems with this. stdin: echo foo[ n=bar echo "hi[ $n ]=1" expected-stdout: foo[ hi[ bar ]=1 --- name: regression-2 description: When PATH is set before running a command, the new path is not used in doing the path search $ echo echo hi > /tmp/q ; chmod a+rx /tmp/q $ PATH=/tmp q q: not found $ in comexec() the two lines while (*vp != NULL) (void) typeset(*vp++, xxx, 0); need to be moved out of the switch to before findcom() is called - I don't know what this will break. stdin: : "${PWD:-`pwd 2> /dev/null`}" : "${PWD:?"PWD not set - cannot do test"}" mkdir Y cat > Y/xxxscript << EOF #!/bin/sh # Need to restore path so echo can be found (some shells don't have # it as a built-in) PATH=\$OLDPATH echo hi exit 0 EOF chmod a+rx Y/xxxscript export OLDPATH="$PATH" PATH=$PWD/Y xxxscript exit $? expected-stdout: hi --- name: regression-6 description: Parsing of $(..) expressions is non-optimal. It is impossible to have any parentheses inside the expression. I.e., $ ksh -c 'echo $(echo \( )' no closing quote $ ksh -c 'echo $(echo "(" )' no closing quote $ The solution is to hack the parsing clode in lex.c, the question is how to hack it: should any parentheses be escaped by a backslash, or should recursive parsing be done (so quotes could also be used to hide hem). The former is easier, the later better... stdin: echo $(echo \( ) echo $(echo "(" ) expected-stdout: ( ( --- name: regression-9 description: Continue in a for loop does not work right: for i in a b c ; do if [ $i = b ] ; then continue fi echo $i done Prints a forever... stdin: first=yes for i in a b c ; do if [ $i = b ] ; then if [ $first = no ] ; then echo 'continue in for loop broken' break # hope break isn't broken too :-) fi first=no continue fi done echo bye expected-stdout: bye --- name: regression-10 description: The following: set -- `false` echo $? should print 0 according to POSIX (dash, bash, ksh93, posh) but not 0 according to the getopt(1) manual page, ksh88, and Bourne sh (such as /bin/sh on Solaris). We honour POSIX except when -o sh is set. category: shell:legacy-no stdin: showf() { [[ -o posix ]]; FPOSIX=$((1-$?)) [[ -o sh ]]; FSH=$((1-$?)) echo -n "FPOSIX=$FPOSIX FSH=$FSH " } set +o posix +o sh showf set -- `false` echo rv=$? set -o sh showf set -- `false` echo rv=$? set -o posix showf set -- `false` echo rv=$? set -o posix -o sh showf set -- `false` echo rv=$? expected-stdout: FPOSIX=0 FSH=0 rv=0 FPOSIX=0 FSH=1 rv=1 FPOSIX=1 FSH=0 rv=0 FPOSIX=1 FSH=1 rv=0 --- name: regression-10-legacy description: The following: set -- `false` echo $? should print 0 according to POSIX (dash, bash, ksh93, posh) but not 0 according to the getopt(1) manual page, ksh88, and Bourne sh (such as /bin/sh on Solaris). category: shell:legacy-yes stdin: showf() { [[ -o posix ]]; FPOSIX=$((1-$?)) [[ -o sh ]]; FSH=$((1-$?)) echo -n "FPOSIX=$FPOSIX FSH=$FSH " } set +o posix +o sh showf set -- `false` echo rv=$? set -o sh showf set -- `false` echo rv=$? set -o posix showf set -- `false` echo rv=$? set -o posix -o sh showf set -- `false` echo rv=$? expected-stdout: FPOSIX=0 FSH=0 rv=1 FPOSIX=0 FSH=1 rv=1 FPOSIX=1 FSH=0 rv=0 FPOSIX=1 FSH=1 rv=0 --- name: regression-11 description: The following: x=/foo/bar/blah echo ${x##*/} should echo blah but on some machines echos /foo/bar/blah. stdin: x=/foo/bar/blah echo ${x##*/} expected-stdout: blah --- name: regression-12 description: Both of the following echos produce the same output under sh/ksh.att: #!/bin/sh x="foo bar" echo "`echo \"$x\"`" echo "`echo "$x"`" pdksh produces different output for the former (foo instead of foo\tbar) stdin: x="foo bar" echo "`echo \"$x\"`" echo "`echo "$x"`" expected-stdout: foo bar foo bar --- name: regression-13 description: The following command hangs forever: $ (: ; cat /etc/termcap) | sleep 2 This is because the shell forks a shell to run the (..) command and this shell has the pipe open. When the sleep dies, the cat doesn't get a SIGPIPE 'cause a process (ie, the second shell) still has the pipe open. NOTE: this test provokes a bizarre bug in ksh93 (shell starts reading commands from /etc/termcap..) time-limit: 10 stdin: echo A line of text that will be duplicated quite a number of times.> t1 cat t1 t1 t1 t1 t1 t1 t1 t1 t1 t1 t1 t1 t1 t1 t1 t1 > t2 cat t2 t2 t2 t2 t2 t2 t2 t2 t2 t2 t2 t2 t2 t2 t2 t2 > t1 cat t1 t1 t1 t1 > t2 (: ; cat t2 2>/dev/null) | sleep 1 --- name: regression-14 description: The command $ (foobar) 2> /dev/null generates no output under /bin/sh, but pdksh produces the error foobar: not found Also, the command $ foobar 2> /dev/null generates an error under /bin/sh and pdksh, but AT&T ksh88 produces no error (redirected to /dev/null). stdin: (you/should/not/see/this/error/1) 2> /dev/null you/should/not/see/this/error/2 2> /dev/null true --- name: regression-15 description: The command $ whence foobar generates a blank line under pdksh and sets the exit status to 0. AT&T ksh88 generates no output and sets the exit status to 1. Also, the command $ whence foobar cat generates no output under AT&T ksh88 (pdksh generates a blank line and /bin/cat). stdin: whence does/not/exist > /dev/null echo 1: $? echo 2: $(whence does/not/exist | wc -l) echo 3: $(whence does/not/exist cat | wc -l) expected-stdout: 1: 1 2: 0 3: 0 --- name: regression-16 description: ${var%%expr} seems to be broken in many places. On the mips the commands $ read line < /etc/passwd $ echo $line root:0:1:... $ echo ${line%%:*} root $ echo $line root $ change the value of line. On sun4s & pas, the echo ${line%%:*} doesn't work. Haven't checked elsewhere... script: read x y=$x echo ${x%%:*} echo $x stdin: root:asdjhasdasjhs:0:1:Root:/:/bin/sh expected-stdout: root root:asdjhasdasjhs:0:1:Root:/:/bin/sh --- name: regression-17 description: The command . /foo/bar should set the exit status to non-zero (sh and AT&T ksh88 do). XXX doting a non existent file is a fatal error for a script stdin: . does/not/exist expected-exit: e != 0 expected-stderr-pattern: /.?/ --- name: regression-19 description: Both of the following echos should produce the same thing, but don't: $ x=foo/bar $ echo ${x%/*} foo $ echo "${x%/*}" foo/bar stdin: x=foo/bar echo "${x%/*}" expected-stdout: foo --- name: regression-21 description: backslash does not work as expected in case labels: $ x='-x' $ case $x in -\?) echo hi esac hi $ x='-?' $ case $x in -\\?) echo hi esac hi $ stdin: case -x in -\?) echo fail esac --- name: regression-22 description: Quoting backquotes inside backquotes doesn't work: $ echo `echo hi \`echo there\` folks` asks for more info. sh and AT&T ksh88 both echo hi there folks stdin: echo `echo hi \`echo there\` folks` expected-stdout: hi there folks --- name: regression-23 description: )) is not treated `correctly': $ (echo hi ; (echo there ; echo folks)) missing (( $ instead of (as sh and ksh.att) $ (echo hi ; (echo there ; echo folks)) hi there folks $ stdin: ( : ; ( : ; echo hi)) expected-stdout: hi --- name: regression-25 description: Check reading stdin in a while loop. The read should only read a single line, not a whole stdio buffer; the cat should get the rest. stdin: (echo a; echo b) | while read x ; do echo $x cat > /dev/null done expected-stdout: a --- name: regression-26 description: Check reading stdin in a while loop. The read should read both lines, not just the first. script: a= while [ "$a" != xxx ] ; do last=$x read x cat /dev/null | sed 's/x/y/' a=x$a done echo $last stdin: a b expected-stdout: b --- name: regression-27 description: The command . /does/not/exist should cause a script to exit. stdin: . does/not/exist echo hi expected-exit: e != 0 expected-stderr-pattern: /does\/not\/exist/ --- name: regression-28 description: variable assignements not detected well stdin: a.x=1 echo hi expected-exit: e != 0 expected-stderr-pattern: /a\.x=1/ --- name: regression-29 description: alias expansion different from AT&T ksh88 stdin: alias a='for ' b='i in' a b hi ; do echo $i ; done expected-stdout: hi --- name: regression-30 description: strange characters allowed inside ${...} stdin: echo ${a{b}} expected-exit: e != 0 expected-stderr-pattern: /.?/ --- name: regression-31 description: Does read handle partial lines correctly script: a= ret= while [ "$a" != xxx ] ; do read x y z ret=$? a=x$a done echo "[$x]" echo $ret stdin: ! a A aA b B Bb c expected-stdout: [c] 1 --- name: regression-32 description: Does read set variables to null at eof? script: a= while [ "$a" != xxx ] ; do read x y z a=x$a done echo 1: ${x-x not set} ${y-y not set} ${z-z not set} echo 2: ${x:+x not null} ${y:+y not null} ${z:+z not null} stdin: a A Aa b B Bb expected-stdout: 1: 2: --- name: regression-33 description: Does umask print a leading 0 when umask is 3 digits? stdin: # on MiNT, the first umask call seems to fail umask 022 # now, the test proper umask 222 umask expected-stdout: 0222 --- name: regression-35 description: Tempory files used for here-docs in functions get trashed after the function is parsed (before it is executed) stdin: f1() { cat <<- EOF F1 EOF f2() { cat <<- EOF F2 EOF } } f1 f2 unset -f f1 f2 expected-stdout: F1 F2 F2 --- name: regression-36 description: Command substitution breaks reading in while loop (test from ) stdin: (echo abcdef; echo; echo 123) | while read line do # the following line breaks it c=`echo $line | wc -c` echo $c done expected-stdout: 7 1 4 --- name: regression-37 description: Machines with broken times() (reported by ) time does not report correct real time stdin: time sleep 1 expected-stderr-pattern: !/^\s*0\.0[\s\d]+real|^\s*real[\s]+0+\.0/ --- name: regression-38 description: set -e doesn't ignore exit codes for if/while/until/&&/||/!. arguments: !-e! stdin: if false; then echo hi ; fi false || true false && true while false; do echo hi; done echo ok expected-stdout: ok --- name: regression-39 description: Only posh and oksh(2013-07) say “hi” below; FreeBSD sh, GNU bash in POSIX mode, dash, ksh93, mksh don’t. All of them exit 0. The POSIX behaviour is needed by BSD make. stdin: set -e echo `false; echo hi` $(env; chmod +x env; PATH=.$PATHSEP$PATH foo=bar readonly foo foo=stuff env | grep '^foo' expected-exit: e != 0 expected-stderr-pattern: /read-only/ --- name: regression-43 description: Can subshells be prefixed by redirections (historical shells allow this) stdin: < /dev/null (sed 's/^/X/') --- name: regression-45 description: Parameter assignments with [] recognised correctly stdin: FOO=*[12] BAR=abc[ MORE=[abc] JUNK=a[bc echo "<$FOO>" echo "<$BAR>" echo "<$MORE>" echo "<$JUNK>" expected-stdout: <*[12]> <[abc]> --- name: regression-46 description: Check that alias expansion works in command substitutions and at the end of file. stdin: alias x='echo hi' FOO="`x` " echo "[$FOO]" x expected-stdout: [hi ] hi --- name: regression-47 description: Check that aliases are fully read. stdin: alias x='echo hi; echo there' x echo done expected-stdout: hi there done --- name: regression-48 description: Check that (here doc) temp files are not left behind after an exec. stdin: mkdir foo || exit 1 TMPDIR=$PWD/foo "$__progname" <<- 'EOF' x() { sed 's/^/X /' << E_O_F hi there folks E_O_F echo "done ($?)" } echo=echo; [ -x /bin/echo ] && echo=/bin/echo exec $echo subtest-1 hi EOF echo subtest-1 foo/* TMPDIR=$PWD/foo "$__progname" <<- 'EOF' echo=echo; [ -x /bin/echo ] && echo=/bin/echo sed 's/^/X /' << E_O_F; exec $echo subtest-2 hi a few lines E_O_F EOF echo subtest-2 foo/* expected-stdout: subtest-1 hi subtest-1 foo/* X a X few X lines subtest-2 hi subtest-2 foo/* --- name: regression-49 description: Check that unset params with attributes are reported by set, those sans attributes are not. stdin: unset FOO BAR echo X$FOO export BAR typeset -i BLAH set | grep FOO set | grep BAR set | grep BLAH expected-stdout: X BAR BLAH --- name: regression-50 description: Check that aliases do not use continuation prompt after trailing semi-colon. file-setup: file 644 "envf" PS1=Y PS2=X env-setup: !ENV=./envf! need-ctty: yes arguments: !-i! stdin: alias foo='echo hi ; ' foo foo echo there expected-stdout: hi hi there expected-stderr: ! YYYY --- name: regression-51 description: Check that set allows both +o and -o options on same command line. stdin: set a b c set -o noglob +o allexport echo A: $*, * expected-stdout: A: a b c, * --- name: regression-52 description: Check that globbing works in pipelined commands file-setup: file 644 "envf" PS1=P file-setup: file 644 "abc" stuff env-setup: !ENV=./envf! need-ctty: yes arguments: !-i! stdin: sed 's/^/X /' < ab* echo mark 1 sed 's/^/X /' < ab* | sed 's/^/Y /' echo mark 2 expected-stdout: X stuff mark 1 Y X stuff mark 2 expected-stderr: ! PPPPP --- name: regression-53 description: Check that getopts works in functions stdin: bfunc() { echo bfunc: enter "(args: $*; OPTIND=$OPTIND)" while getopts B oc; do case $oc in (B) echo bfunc: B option ;; (*) echo bfunc: odd option "($oc)" ;; esac done echo bfunc: leave } function kfunc { echo kfunc: enter "(args: $*; OPTIND=$OPTIND)" while getopts K oc; do case $oc in (K) echo kfunc: K option ;; (*) echo bfunc: odd option "($oc)" ;; esac done echo kfunc: leave } set -- -f -b -k -l echo "line 1: OPTIND=$OPTIND" getopts kbfl optc echo "line 2: ret=$?, optc=$optc, OPTIND=$OPTIND" bfunc -BBB blah echo "line 3: OPTIND=$OPTIND" getopts kbfl optc echo "line 4: ret=$?, optc=$optc, OPTIND=$OPTIND" kfunc -KKK blah echo "line 5: OPTIND=$OPTIND" getopts kbfl optc echo "line 6: ret=$?, optc=$optc, OPTIND=$OPTIND" echo OPTIND=1 set -- -fbkl echo "line 10: OPTIND=$OPTIND" getopts kbfl optc echo "line 20: ret=$?, optc=$optc, OPTIND=$OPTIND" bfunc -BBB blah echo "line 30: OPTIND=$OPTIND" getopts kbfl optc echo "line 40: ret=$?, optc=$optc, OPTIND=$OPTIND" kfunc -KKK blah echo "line 50: OPTIND=$OPTIND" getopts kbfl optc echo "line 60: ret=$?, optc=$optc, OPTIND=$OPTIND" expected-stdout: line 1: OPTIND=1 line 2: ret=0, optc=f, OPTIND=2 bfunc: enter (args: -BBB blah; OPTIND=2) bfunc: B option bfunc: B option bfunc: leave line 3: OPTIND=2 line 4: ret=0, optc=b, OPTIND=3 kfunc: enter (args: -KKK blah; OPTIND=1) kfunc: K option kfunc: K option kfunc: K option kfunc: leave line 5: OPTIND=3 line 6: ret=0, optc=k, OPTIND=4 line 10: OPTIND=1 line 20: ret=0, optc=f, OPTIND=2 bfunc: enter (args: -BBB blah; OPTIND=2) bfunc: B option bfunc: B option bfunc: leave line 30: OPTIND=2 line 40: ret=1, optc=?, OPTIND=2 kfunc: enter (args: -KKK blah; OPTIND=1) kfunc: K option kfunc: K option kfunc: K option kfunc: leave line 50: OPTIND=2 line 60: ret=1, optc=?, OPTIND=2 --- name: regression-54 description: Check that ; is not required before the then in if (( ... )) then ... stdin: if (( 1 )) then echo ok dparen fi if [[ -n 1 ]] then echo ok dbrackets fi expected-stdout: ok dparen ok dbrackets --- name: regression-55 description: Check ${foo:%bar} is allowed (ksh88 allows it...) stdin: x=fooXbarXblah echo 1 ${x%X*} echo 2 ${x:%X*} echo 3 ${x%%X*} echo 4 ${x:%%X*} echo 5 ${x#*X} echo 6 ${x:#*X} echo 7 ${x##*X} echo 8 ${x:##*X} expected-stdout: 1 fooXbar 2 fooXbar 3 foo 4 foo 5 barXblah 6 barXblah 7 blah 8 blah --- name: regression-57 description: Check if typeset output is correct for uninitialised array elements. stdin: typeset -i xxx[4] echo A typeset -i | grep xxx | sed 's/^/ /' echo B typeset | grep xxx | sed 's/^/ /' xxx[1]=2+5 echo M typeset -i | grep xxx | sed 's/^/ /' echo N typeset | grep xxx | sed 's/^/ /' expected-stdout: A xxx B typeset -i xxx M xxx[1]=7 N set -A xxx typeset -i xxx[1] --- name: regression-58 description: Check if trap exit is ok (exit not mistaken for signal name) stdin: trap 'echo hi' exit trap exit 1 expected-stdout: hi --- name: regression-59 description: Check if ${#array[*]} is calculated correctly. stdin: a[12]=hi a[8]=there echo ${#a[*]} expected-stdout: 2 --- name: regression-60 description: Check if default exit status is previous command stdin: (true; exit) echo A $? (false; exit) echo B $? ( (exit 103) ; exit) echo C $? expected-stdout: A 0 B 1 C 103 --- name: regression-61 description: Check if EXIT trap is executed for sub shells. stdin: trap 'echo parent exit' EXIT echo start (echo A; echo A last) echo B (echo C; trap 'echo sub exit' EXIT; echo C last) echo parent last expected-stdout: start A A last B C C last sub exit parent last parent exit --- name: regression-62 description: Check if test -nt/-ot succeeds if second(first) file is missing. stdin: :>a test a -nt b && echo nt OK || echo nt BAD test b -ot a && echo ot OK || echo ot BAD expected-stdout: nt OK ot OK --- name: regression-63 description: Check if typeset, export, and readonly work stdin: { echo FNORD-0 FNORD_A=1 FNORD_B=2 FNORD_C=3 FNORD_D=4 FNORD_E=5 FNORD_F=6 FNORD_G=7 FNORD_H=8 integer FNORD_E FNORD_F FNORD_G FNORD_H export FNORD_C FNORD_D FNORD_G FNORD_H readonly FNORD_B FNORD_D FNORD_F FNORD_H echo FNORD-1 export echo FNORD-2 export -p echo FNORD-3 readonly echo FNORD-4 readonly -p echo FNORD-5 typeset echo FNORD-6 typeset -p echo FNORD-7 typeset - echo FNORD-8 } | fgrep FNORD fnord=(42 23) typeset -p fnord echo FNORD-9 expected-stdout: FNORD-0 FNORD-1 FNORD_C FNORD_D FNORD_G FNORD_H FNORD-2 export FNORD_C=3 export FNORD_D=4 export FNORD_G=7 export FNORD_H=8 FNORD-3 FNORD_B FNORD_D FNORD_F FNORD_H FNORD-4 readonly FNORD_B=2 readonly FNORD_D=4 readonly FNORD_F=6 readonly FNORD_H=8 FNORD-5 typeset FNORD_A typeset -r FNORD_B typeset -x FNORD_C typeset -x -r FNORD_D typeset -i FNORD_E typeset -i -r FNORD_F typeset -i -x FNORD_G typeset -i -x -r FNORD_H FNORD-6 typeset FNORD_A=1 typeset -r FNORD_B=2 typeset -x FNORD_C=3 typeset -x -r FNORD_D=4 typeset -i FNORD_E=5 typeset -i -r FNORD_F=6 typeset -i -x FNORD_G=7 typeset -i -x -r FNORD_H=8 FNORD-7 FNORD_A=1 FNORD_B=2 FNORD_C=3 FNORD_D=4 FNORD_E=5 FNORD_F=6 FNORD_G=7 FNORD_H=8 FNORD-8 set -A fnord typeset fnord[0]=42 typeset fnord[1]=23 FNORD-9 --- name: regression-64 description: Check that we can redefine functions calling time builtin stdin: t() { time >/dev/null } t 2>/dev/null t() { time } --- name: regression-65 description: check for a regression with sleep builtin and signal mask category: !nojsig time-limit: 3 stdin: sleep 1 echo blub |& while read -p line; do :; done echo ok expected-stdout: ok --- name: regression-66 description: Check that quoting is sane category: !nojsig stdin: ac_space=' ' ac_newline=' ' set | grep ^ac_ |& set -A lines while IFS= read -pr line; do if [[ $line = *space* ]]; then lines[0]=$line else lines[1]=$line fi done for line in "${lines[@]}"; do print -r -- "$line" done expected-stdout: ac_space=' ' ac_newline=$'\n' --- name: regression-67 description: Check that we can both break and use source on the same line stdin: for s in s; do break; done; print -s s --- name: regression-68 description: Check that all common arithmetic operators work as expected stdin: echo 1 $(( a = 5 )) . echo 2 $(( ++a )) , $(( a++ )) , $(( a )) . echo 3 $(( --a )) , $(( a-- )) , $(( a )) . echo 4 $(( a == 5 )) , $(( a == 6 )) . echo 5 $(( a != 5 )) , $(( a != 6 )) . echo 6 $(( a *= 3 )) . echo 7 $(( a /= 5 )) . echo 8 $(( a %= 2 )) . echo 9 $(( a += 9 )) . echo 10 $(( a -= 4 )) . echo 11 $(( a <<= 1 )) . echo 12 $(( a >>= 1 )) . echo 13 $(( a &= 4 )) . echo 14 $(( a ^= a )) . echo 15 $(( a |= 5 )) . echo 16 $(( 5 << 1 )) . echo 17 $(( 5 >> 1 )) . echo 18 $(( 5 <= 6 )) , $(( 5 <= 5 )) , $(( 5 <= 4 )) . echo 19 $(( 5 >= 6 )) , $(( 5 >= 5 )) , $(( 5 >= 4 )) . echo 20 $(( 5 < 6 )) , $(( 5 < 5 )) , $(( 5 < 4 )) . echo 21 $(( 5 > 6 )) , $(( 5 > 5 )) , $(( 5 > 4 )) . echo 22 $(( 0 && 0 )) , $(( 0 && 1 )) , $(( 1 && 0 )) , $(( 1 && 1 )) . echo 23 $(( 0 || 0 )) , $(( 0 || 1 )) , $(( 1 || 0 )) , $(( 1 || 1 )) . echo 24 $(( 5 * 3 )) . echo 25 $(( 7 / 2 )) . echo 26 $(( 5 % 5 )) , $(( 5 % 4 )) , $(( 5 % 1 )) , $(( 5 % -1 )) , $(( 5 % -2 )) . echo 27 $(( 5 + 2 )) , $(( 5 + 0 )) , $(( 5 + -2 )) . echo 28 $(( 5 - 2 )) , $(( 5 - 0 )) , $(( 5 - -2 )) . echo 29 $(( 6 & 4 )) , $(( 6 & 8 )) . echo 30 $(( 4 ^ 2 )) , $(( 4 ^ 4 )) . echo 31 $(( 4 | 2 )) , $(( 4 | 4 )) , $(( 4 | 0 )) . echo 32 $(( 0 ? 1 : 2 )) , $(( 3 ? 4 : 5 )) . echo 33 $(( 5 , 2 , 3 )) . echo 34 $(( ~0 )) , $(( ~1 )) , $(( ~~1 )) , $(( ~~2 )) . echo 35 $(( !0 )) , $(( !1 )) , $(( !!1 )) , $(( !!2 )) . echo 36 $(( (5) )) . expected-stdout: 1 5 . 2 6 , 6 , 7 . 3 6 , 6 , 5 . 4 1 , 0 . 5 0 , 1 . 6 15 . 7 3 . 8 1 . 9 10 . 10 6 . 11 12 . 12 6 . 13 4 . 14 0 . 15 5 . 16 10 . 17 2 . 18 1 , 1 , 0 . 19 0 , 1 , 1 . 20 1 , 0 , 0 . 21 0 , 0 , 1 . 22 0 , 0 , 0 , 1 . 23 0 , 1 , 1 , 1 . 24 15 . 25 3 . 26 0 , 1 , 0 , 0 , 1 . 27 7 , 5 , 3 . 28 3 , 5 , 7 . 29 4 , 0 . 30 6 , 0 . 31 6 , 4 , 4 . 32 2 , 4 . 33 3 . 34 -1 , -2 , 1 , 2 . 35 1 , 0 , 1 , 1 . 36 5 . --- name: regression-69 description: Check that all non-lksh arithmetic operators work as expected category: shell:legacy-no stdin: a=5 b=0x80000005 echo 1 $(( a ^<= 1 )) , $(( b ^<= 1 )) . echo 2 $(( a ^>= 2 )) , $(( b ^>= 2 )) . echo 3 $(( 5 ^< 1 )) . echo 4 $(( 5 ^> 1 )) . expected-stdout: 1 10 , 11 . 2 -2147483646 , -1073741822 . 3 10 . 4 -2147483646 . --- name: readonly-0 description: Ensure readonly is honoured for assignments and unset stdin: "$__progname" -c 'u=x; echo $? $u .' || echo aborted, $? echo = "$__progname" -c 'readonly u; u=x; echo $? $u .' || echo aborted, $? echo = "$__progname" -c 'u=x; readonly u; unset u; echo $? $u .' || echo aborted, $? expected-stdout: 0 x . = aborted, 2 = 1 x . expected-stderr-pattern: /read-only/ --- name: readonly-1 description: http://austingroupbugs.net/view.php?id=367 for export stdin: "$__progname" -c 'readonly foo; export foo=a; echo $?' || echo aborted, $? expected-stdout: aborted, 2 expected-stderr-pattern: /read-only/ --- name: readonly-2a description: Check that getopts works as intended, for readonly-2b to be valid stdin: "$__progname" -c 'set -- -a b; getopts a c; echo $? $c .; getopts a c; echo $? $c .' || echo aborted, $? expected-stdout: 0 a . 1 ? . --- name: readonly-2b description: http://austingroupbugs.net/view.php?id=367 for getopts stdin: "$__progname" -c 'readonly c; set -- -a b; getopts a c; echo $? $c .' || echo aborted, $? expected-stdout: 2 . expected-stderr-pattern: /read-only/ --- name: readonly-3 description: http://austingroupbugs.net/view.php?id=367 for read stdin: echo x | "$__progname" -c 'read s; echo $? $s .' || echo aborted, $? echo y | "$__progname" -c 'readonly s; read s; echo $? $s .' || echo aborted, $? expected-stdout: 0 x . 2 . expected-stderr-pattern: /read-only/ --- name: readonly-4 description: Do not permit bypassing readonly for first array item stdin: set -A arr -- foo bar readonly arr arr=baz print -r -- "${arr[@]}" expected-exit: e != 0 expected-stderr-pattern: /read[ -]?only/ --- name: syntax-1 description: Check that lone ampersand is a syntax error stdin: & expected-exit: e != 0 expected-stderr-pattern: /syntax error/ --- name: xxx-quoted-newline-1 description: Check that \ works inside of ${} stdin: abc=2 echo ${ab\ c} expected-stdout: 2 --- name: xxx-quoted-newline-2 description: Check that \ works at the start of a here document stdin: cat << EO\ F hi EOF expected-stdout: hi --- name: xxx-quoted-newline-3 description: Check that \ works at the end of a here document stdin: cat << EOF hi EO\ F expected-stdout: hi --- name: xxx-multi-assignment-cmd description: Check that assignments in a command affect subsequent assignments in the same command stdin: FOO=abc FOO=123 BAR=$FOO echo $BAR expected-stdout: 123 --- name: xxx-multi-assignment-posix-cmd description: Check that the behaviour for multiple assignments with a command name matches POSIX. See: http://thread.gmane.org/gmane.comp.standards.posix.austin.general/1925 stdin: X=a Y=b; X=$Y Y=$X "$__progname" -c 'echo 1 $X $Y .'; echo 2 $X $Y . unset X Y Z X=a Y=${X=b} Z=$X "$__progname" -c 'echo 3 $Z .' unset X Y Z X=a Y=${X=b} Z=$X; echo 4 $Z . expected-stdout: 1 b a . 2 a b . 3 b . 4 a . --- name: xxx-multi-assignment-posix-nocmd description: Check that the behaviour for multiple assignments with no command name matches POSIX (Debian #334182). See: http://thread.gmane.org/gmane.comp.standards.posix.austin.general/1925 stdin: X=a Y=b; X=$Y Y=$X; echo 1 $X $Y . expected-stdout: 1 b b . --- name: xxx-multi-assignment-posix-subassign description: Check that the behaviour for multiple assignments matches POSIX: - The assignment words shall be expanded in the current execution environment. - The assignments happen in the temporary execution environment. stdin: unset X Y Z Z=a Y=${X:=b} sh -c 'echo +$X+ +$Y+ +$Z+' echo /$X/ # Now for the special case: unset X Y Z X= Y=${X:=b} sh -c 'echo +$X+ +$Y+' echo /$X/ expected-stdout: ++ +b+ +a+ /b/ ++ +b+ /b/ --- name: xxx-exec-environment-1 description: Check to see if exec sets it's environment correctly stdin: print '#!'"$__progname"'\nunset RANDOM\nexport | while IFS= read -r' \ 'RANDOM; do eval '\''print -r -- "$RANDOM=$'\''"$RANDOM"'\'\"\'\; \ done >env; chmod +x env; PATH=.$PATHSEP$PATH FOO=bar exec env expected-stdout-pattern: /(^|.*\n)FOO=bar\n/ --- name: xxx-exec-environment-2 description: Check to make sure exec doesn't change environment if a program isn't exec-ed stdin: print '#!'"$__progname"'\nunset RANDOM\nexport | while IFS= read -r' \ 'RANDOM; do eval '\''print -r -- "$RANDOM=$'\''"$RANDOM"'\'\"\'\; \ done >env; chmod +x env; PATH=.$PATHSEP$PATH env >bar1 FOO=bar exec; env >bar2 cmp -s bar1 bar2 --- name: exec-function-environment-1 description: Check assignments in function calls and whether they affect the current execution environment (ksh93, SUSv4) stdin: f() { a=2; }; g() { b=3; echo y$c-; }; a=1 f; b=2; c=1 g echo x$a-$b- z$c- expected-stdout: y1- x2-3- z1- --- name: xxx-what-do-you-call-this-1 stdin: echo "${foo:-"a"}*" expected-stdout: a* --- name: xxx-prefix-strip-1 stdin: foo='a cdef' echo ${foo#a c} expected-stdout: def --- name: xxx-prefix-strip-2 stdin: set a c x='a cdef' echo ${x#$*} expected-stdout: def --- name: xxx-variable-syntax-1 stdin: echo ${:} expected-stderr-pattern: /bad substitution/ expected-exit: 1 --- name: xxx-variable-syntax-2 stdin: set 0 echo ${*:0} expected-stderr-pattern: /bad substitution/ expected-exit: 1 --- name: xxx-variable-syntax-3 stdin: set -A foo 0 echo ${foo[*]:0} expected-stderr-pattern: /bad substitution/ expected-exit: 1 --- name: xxx-variable-syntax-4 description: Not all kinds of trims are currently impossible, check those who do stdin: foo() { echo "<$*> X${*:+ }X" } foo a b foo "" c foo "" foo "" "" IFS=: foo a b foo "" c foo "" foo "" "" IFS= foo a b foo "" c foo "" foo "" "" expected-stdout: X X < c> X X <> XX < > X X X X <:c> X X <> XX <:> X X X X X X <> XX <> XX --- name: xxx-substitution-eval-order description: Check order of evaluation of expressions stdin: i=1 x= y= set -A A abc def GHI j G k echo ${A[x=(i+=1)]#${A[y=(i+=2)]}} echo $x $y expected-stdout: HI 2 4 --- name: xxx-set-option-1 description: Check option parsing in set stdin: set -vsA foo -- A 1 3 2 echo ${foo[*]} expected-stderr: echo ${foo[*]} expected-stdout: 1 2 3 A --- name: xxx-exec-1 description: Check that exec exits for built-ins need-ctty: yes arguments: !-i! stdin: exec echo hi echo still herre expected-stdout: hi expected-stderr-pattern: /.*/ --- name: xxx-while-1 description: Check the return value of while loops XXX need to do same for for/select/until loops stdin: i=x while [ $i != xxx ] ; do i=x$i if [ $i = xxx ] ; then false continue fi done echo loop1=$? i=x while [ $i != xxx ] ; do i=x$i if [ $i = xxx ] ; then false break fi done echo loop2=$? i=x while [ $i != xxx ] ; do i=x$i false done echo loop3=$? expected-stdout: loop1=0 loop2=0 loop3=1 --- name: xxx-status-1 description: Check that blank lines don't clear $? need-ctty: yes arguments: !-i! stdin: (exit 1) echo $? (exit 1) echo $? true expected-stdout: 1 1 expected-stderr-pattern: /.*/ --- name: xxx-status-2 description: Check that $? is preserved in subshells, includes, traps. stdin: (exit 1) echo blank: $? (exit 2) (echo subshell: $?) echo 'echo include: $?' > foo (exit 3) . ./foo trap 'echo trap: $?' ERR (exit 4) echo exit: $? expected-stdout: blank: 1 subshell: 2 include: 3 trap: 4 exit: 4 --- name: xxx-clean-chars-1 description: Check MAGIC character is stuffed correctly stdin: echo `echo [` expected-stdout: [ --- name: xxx-param-subst-qmark-1 description: Check suppresion of error message with null string. According to POSIX, it shouldn't print the error as 'word' isn't ommitted. ksh88/93, Solaris /bin/sh and /usr/xpg4/bin/sh all print the error. stdin: unset foo x= echo x${foo?$x} expected-exit: 1 expected-stderr-pattern: !/not set/ --- name: xxx-param-subst-qmark-namespec description: Check special names are output correctly stdin: doit() { "$__progname" -c "$@" >o1 2>o2 rv=$? echo RETVAL: $rv sed -e "s^${__progname%.exe}\.*e*x*e*: PROG: " -e 's/^/STDOUT: /g' 'c=a' typeset c=[ab] :>'d=a' x=typeset; $x d=[ab] echo "<$c>" "<$d>" wd=$PWD cd / plus=$(print -r -- ~+) minus=$(print -r -- ~-) nix=$(print -r -- ~) [[ $plus = / ]]; echo one $? . [[ $minus = "$wd" ]]; echo two $? . [[ $nix = /sweet ]]; echo nix $? . expected-stdout: <[ab]> one 0 . two 0 . nix 0 . --- name: tilde-expand-3 description: Check mostly Austin 351 stuff stdin: showargs() { for s_arg in "$@"; do echo -n "<$s_arg> "; done; echo .; } set "1 b=2" "3 d=4" export a=$1 \c=$2 showargs 1 "$a" "$b" "$c" "$d" unset a b c d HOME=/tmp export \a=~ b=~ command export c=~ builtin export d=~ \\builtin export e=~ showargs 2 "$a" "$b" "$c" "$d" "$e" ksh unset a b c d e set -o posix export \a=~ b=~ command export c=~ builtin export d=~ \\builtin export e=~ showargs 3 "$a" "$b" "$c" "$d" "$e" posix unset a b c d e set +o posix export a=$1 showargs 4 "$a" "$b" ksh unset a b showargs 5 a=$1 ksh export \a=$1 showargs 6 "$a" "$b" ksh unset a b set -o posix export a=$1 showargs 7 "$a" "$b" posix unset a b showargs 8 a=$1 posix export \a=$1 showargs 9 "$a" "$b" posix unset a b set +o posix command echo 10 ksh a=~ command command export a=~ showargs 11 "$a" unset a set -o posix command echo 12 posix a=~ command command export a=~ showargs 13 "$a" unset a # unspecified whether /tmp or ~ var=export; command $var a=~ showargs 14 "$a" echo 'echo "<$foo>"' >bar "$__progname" bar var=foo export $var=1 "$__progname" bar export $var=~ "$__progname" bar # unspecified command -- export a=~ showargs 18 "$a" set -A bla typeset bla[1]=~:~ global gbl=~ g2=$1 local lcl=~ l2=$1 readonly ro=~ r2=$1 showargs 19 "${bla[1]}" a=~ "$gbl" "$lcl" "$ro" "$g2" "$l2" "$r2" set +o posix echo "20 some arbitrary stuff "=~ set -o posix echo "21 some arbitrary stuff "=~ expected-stdout: <1> <1 b=2> <> <3> <4> . <2> . <3> <~> <~> . <4> <1 b=2> <> . <5> . <6> <1> <2> . <7> <1 b=2> <> . <8> . <9> <1> <2> . 10 ksh a=/tmp <11> . 12 posix a=~ <13> . <14> <~> . <> <1> <~> <18> <~> . <19> <1 b=2> <1 b=2> <1 b=2> . 20 some arbitrary stuff =/tmp 21 some arbitrary stuff =~ --- name: exit-err-1 description: Check some "exit on error" conditions stdin: print '#!'"$__progname"'\nexec "$1"' >env print '#!'"$__progname"'\nexit 1' >false chmod +x env false PATH=.$PATHSEP$PATH set -ex env false && echo something echo END expected-stdout: END expected-stderr: + env false + echo END --- name: exit-err-2 description: Check some "exit on error" edge conditions (POSIXly) stdin: print '#!'"$__progname"'\nexec "$1"' >env print '#!'"$__progname"'\nexit 1' >false print '#!'"$__progname"'\nexit 0' >true chmod +x env false PATH=.$PATHSEP$PATH set -ex if env true; then env false && echo something fi echo END expected-stdout: END expected-stderr: + env true + env false + echo END --- name: exit-err-3 description: pdksh regression which AT&T ksh does right TFM says: [set] -e | errexit Exit (after executing the ERR trap) ... stdin: trap 'echo EXIT' EXIT trap 'echo ERR' ERR set -e cd /XXXXX 2>/dev/null echo DONE exit 0 expected-stdout: ERR EXIT expected-exit: e != 0 --- name: exit-err-4 description: "set -e" test suite (POSIX) stdin: set -e echo pre if true ; then false && echo foo fi echo bar expected-stdout: pre bar --- name: exit-err-5 description: "set -e" test suite (POSIX) stdin: set -e foo() { while [ "$1" ]; do for E in $x; do [ "$1" = "$E" ] && { shift ; continue 2 ; } done x="$x $1" shift done echo $x } echo pre foo a b b c echo post expected-stdout: pre a b c post --- name: exit-err-6 description: "set -e" test suite (BSD make) category: os:mirbsd stdin: mkdir zd zd/a zd/b print 'all:\n\t@echo eins\n\t@exit 42\n' >zd/a/Makefile print 'all:\n\t@echo zwei\n' >zd/b/Makefile wd=$(pwd) set -e for entry in a b; do ( set -e; if [[ -d $wd/zd/$entry.i386 ]]; then _newdir_="$entry.i386"; else _newdir_="$entry"; fi; if [[ -z $_THISDIR_ ]]; then _nextdir_="$_newdir_"; else _nextdir_="$_THISDIR_/$_newdir_"; fi; _makefile_spec_=; [[ ! -f $wd/zd/$_newdir_/Makefile.bsd-wrapper ]] || _makefile_spec_="-f Makefile.bsd-wrapper"; subskipdir=; for skipdir in ; do subentry=${skipdir#$entry}; if [[ $subentry != $skipdir ]]; then if [[ -z $subentry ]]; then echo "($_nextdir_ skipped)"; break; fi; subskipdir="$subskipdir ${subentry#/}"; fi; done; if [[ -z $skipdir || -n $subentry ]]; then echo "===> $_nextdir_"; cd $wd/zd/$_newdir_; make SKIPDIR="$subskipdir" $_makefile_spec_ _THISDIR_="$_nextdir_" all; fi; ) done 2>&1 | sed "s!$wd!WD!g" expected-stdout: ===> a eins *** Error code 42 Stop in WD/zd/a (line 2 of Makefile). --- name: exit-err-7 description: "set -e" regression (LP#1104543) stdin: set -e bla() { [ -x $PWD/nonexistant ] && $PWD/nonexistant } echo x bla echo y$? expected-stdout: x expected-exit: 1 --- name: exit-err-8 description: "set -e" regression (Debian #700526) stdin: set -e _db_cmd() { return $1; } db_input() { _db_cmd 30; } db_go() { _db_cmd 0; } db_input || : db_go exit 0 --- name: exit-err-9 description: "set -e" versus bang pipelines stdin: set -e ! false | false echo 1 ok ! false && false echo 2 wrong expected-stdout: 1 ok expected-exit: 1 --- name: exit-enoent-1 description: SUSv4 says that the shell should exit with 126/127 in some situations stdin: i=0 (echo; echo :) >x "$__progname" ./x >/dev/null 2>&1; r=$?; echo $((i++)) $r . "$__progname" -c ./x >/dev/null 2>&1; r=$?; echo $((i++)) $r . echo exit 42 >x "$__progname" ./x >/dev/null 2>&1; r=$?; echo $((i++)) $r . "$__progname" -c ./x >/dev/null 2>&1; r=$?; echo $((i++)) $r . rm -f x "$__progname" ./x >/dev/null 2>&1; r=$?; echo $((i++)) $r . "$__progname" -c ./x >/dev/null 2>&1; r=$?; echo $((i++)) $r . expected-stdout: 0 0 . 1 126 . 2 42 . 3 126 . 4 127 . 5 127 . --- name: exit-eval-1 description: Check eval vs substitution exit codes (ksh93 alike) stdin: (exit 12) eval $(false) echo A $? (exit 12) eval ' $(false)' echo B $? (exit 12) eval " $(false)" echo C $? (exit 12) eval "eval $(false)" echo D $? (exit 12) eval 'eval '"$(false)" echo E $? IFS="$IFS:" (exit 12) eval $(echo :; false) echo F $? echo -n "G " (exit 12) eval 'echo $?' echo H $? expected-stdout: A 0 B 1 C 0 D 0 E 0 F 0 G 12 H 0 --- name: exit-trap-1 description: Check that "exit" with no arguments behaves SUSv4 conformant. stdin: trap 'echo hi; exit' EXIT exit 9 expected-stdout: hi expected-exit: 9 --- name: exit-trap-2 description: Check that ERR and EXIT traps are run just like ksh93 does. GNU bash does not run ERtrap in ±e eval-undef but runs it twice (bug?) in +e eval-false, so does ksh93 (bug?), which also has a bug to continue execution (echoing "and out" and returning 0) in +e eval-undef. file-setup: file 644 "x" v=; unset v trap 'echo EXtrap' EXIT trap 'echo ERtrap' ERR set $1 echo "and run $2" eval $2 echo and out file-setup: file 644 "xt" v=; unset v trap 'echo EXtrap' EXIT trap 'echo ERtrap' ERR set $1 echo 'and run true' true echo and out file-setup: file 644 "xf" v=; unset v trap 'echo EXtrap' EXIT trap 'echo ERtrap' ERR set $1 echo 'and run false' false echo and out file-setup: file 644 "xu" v=; unset v trap 'echo EXtrap' EXIT trap 'echo ERtrap' ERR set $1 echo 'and run ${v?}' ${v?} echo and out stdin: runtest() { rm -f rc ( "$__progname" "$@" echo $? >rc ) 2>&1 | sed \ -e 's/parameter not set/parameter null or not set/' \ -e 's/[[]6]//' -e 's/: eval: line 1//' -e 's/: line 6//' \ -e "s^${__progname%.exe}\.*e*x*e*: \[[0-9]*]PROG" } xe=-e echo : $xe runtest x $xe true echo = eval-true $(' 2005/08/21 && echo ja || echo nein test 2005/08/21 \> 2005/10/08 && echo ja || echo nein expected-stdout: nein ja ja nein expected-stderr-pattern: !/unexpected op/ --- name: test-precedence-1 description: Check a weird precedence case (and POSIX echo) stdin: test \( -f = -f \) rv=$? echo $rv expected-stdout: 0 --- name: test-option-1 description: Test the test -o operator stdin: runtest() { test -o $1; echo $? [ -o $1 ]; echo $? [[ -o $1 ]]; echo $? } if_test() { test -o $1 -o -o !$1; echo $? [ -o $1 -o -o !$1 ]; echo $? [[ -o $1 || -o !$1 ]]; echo $? test -o ?$1; echo $? } echo 0y $(if_test utf8-mode) = echo 0n $(if_test utf8-hack) = echo 1= $(runtest utf8-hack) = echo 2= $(runtest !utf8-hack) = echo 3= $(runtest ?utf8-hack) = set +U echo 1+ $(runtest utf8-mode) = echo 2+ $(runtest !utf8-mode) = echo 3+ $(runtest ?utf8-mode) = set -U echo 1- $(runtest utf8-mode) = echo 2- $(runtest !utf8-mode) = echo 3- $(runtest ?utf8-mode) = echo = short flags = echo 0y $(if_test -U) = echo 0y $(if_test +U) = echo 0n $(if_test -_) = echo 0n $(if_test -U-) = echo 1= $(runtest -_) = echo 2= $(runtest !-_) = echo 3= $(runtest ?-_) = set +U echo 1+ $(runtest -U) = echo 2+ $(runtest !-U) = echo 3+ $(runtest ?-U) = echo 1+ $(runtest +U) = echo 2+ $(runtest !+U) = echo 3+ $(runtest ?+U) = set -U echo 1- $(runtest -U) = echo 2- $(runtest !-U) = echo 3- $(runtest ?-U) = echo 1- $(runtest +U) = echo 2- $(runtest !+U) = echo 3- $(runtest ?+U) = expected-stdout: 0y 0 0 0 0 = 0n 1 1 1 1 = 1= 1 1 1 = 2= 1 1 1 = 3= 1 1 1 = 1+ 1 1 1 = 2+ 0 0 0 = 3+ 0 0 0 = 1- 0 0 0 = 2- 1 1 1 = 3- 0 0 0 = = short flags = 0y 0 0 0 0 = 0y 0 0 0 0 = 0n 1 1 1 1 = 0n 1 1 1 1 = 1= 1 1 1 = 2= 1 1 1 = 3= 1 1 1 = 1+ 1 1 1 = 2+ 0 0 0 = 3+ 0 0 0 = 1+ 1 1 1 = 2+ 0 0 0 = 3+ 0 0 0 = 1- 0 0 0 = 2- 1 1 1 = 3- 0 0 0 = 1- 0 0 0 = 2- 1 1 1 = 3- 0 0 0 = --- name: test-stnze-1 description: Check that the short form [ $x ] works stdin: i=0 [ -n $x ] rv=$?; echo $((++i)) $rv [ $x ] rv=$?; echo $((++i)) $rv [ -n "$x" ] rv=$?; echo $((++i)) $rv [ "$x" ] rv=$?; echo $((++i)) $rv x=0 [ -n $x ] rv=$?; echo $((++i)) $rv [ $x ] rv=$?; echo $((++i)) $rv [ -n "$x" ] rv=$?; echo $((++i)) $rv [ "$x" ] rv=$?; echo $((++i)) $rv x='1 -a 1 = 2' [ -n $x ] rv=$?; echo $((++i)) $rv [ $x ] rv=$?; echo $((++i)) $rv [ -n "$x" ] rv=$?; echo $((++i)) $rv [ "$x" ] rv=$?; echo $((++i)) $rv expected-stdout: 1 0 2 1 3 1 4 1 5 0 6 0 7 0 8 0 9 1 10 1 11 0 12 0 --- name: test-stnze-2 description: Check that the short form [[ $x ]] works (ksh93 extension) stdin: i=0 [[ -n $x ]] rv=$?; echo $((++i)) $rv [[ $x ]] rv=$?; echo $((++i)) $rv [[ -n "$x" ]] rv=$?; echo $((++i)) $rv [[ "$x" ]] rv=$?; echo $((++i)) $rv x=0 [[ -n $x ]] rv=$?; echo $((++i)) $rv [[ $x ]] rv=$?; echo $((++i)) $rv [[ -n "$x" ]] rv=$?; echo $((++i)) $rv [[ "$x" ]] rv=$?; echo $((++i)) $rv x='1 -a 1 = 2' [[ -n $x ]] rv=$?; echo $((++i)) $rv [[ $x ]] rv=$?; echo $((++i)) $rv [[ -n "$x" ]] rv=$?; echo $((++i)) $rv [[ "$x" ]] rv=$?; echo $((++i)) $rv expected-stdout: 1 1 2 1 3 1 4 1 5 0 6 0 7 0 8 0 9 0 10 0 11 0 12 0 --- name: test-numeq description: Check numeric -eq works (R40d regression); spotted by Martijn Dekker stdin: tst() { eval "$2" case $? in (0) echo yepp 0 \#"$*" ;; (1) echo nope 1 \#"$*" ;; (2) echo terr 2 \#"$*" ;; (*) echo wtf\? $? \#"$*" ;; esac } tst 1 'test 2 -eq 2' tst 2 'test 2 -eq 2a' tst 3 'test 2 -eq 3' tst 4 'test 2 -ne 2' tst 5 'test 2 -ne 2a' tst 6 'test 2 -ne 3' tst 7 'test \! 2 -eq 2' tst 8 'test \! 2 -eq 2a' tst 9 'test \! 2 -eq 3' expected-stdout: yepp 0 #1 test 2 -eq 2 terr 2 #2 test 2 -eq 2a nope 1 #3 test 2 -eq 3 nope 1 #4 test 2 -ne 2 terr 2 #5 test 2 -ne 2a yepp 0 #6 test 2 -ne 3 nope 1 #7 test \! 2 -eq 2 terr 2 #8 test \! 2 -eq 2a yepp 0 #9 test \! 2 -eq 3 expected-stderr-pattern: /bad number/ --- name: mkshrc-1 description: Check that ~/.mkshrc works correctly. Part 1: verify user environment is not read (internal) stdin: echo x $FNORD expected-stdout: x --- name: mkshrc-2a description: Check that ~/.mkshrc works correctly. Part 2: verify mkshrc is not read (non-interactive shells) file-setup: file 644 ".mkshrc" FNORD=42 env-setup: !HOME=.!ENV=! stdin: echo x $FNORD expected-stdout: x --- name: mkshrc-2b description: Check that ~/.mkshrc works correctly. Part 2: verify mkshrc can be read (interactive shells) file-setup: file 644 ".mkshrc" FNORD=42 need-ctty: yes arguments: !-i! env-setup: !HOME=.!ENV=!PS1=! stdin: echo x $FNORD expected-stdout: x 42 expected-stderr-pattern: /(# )*/ --- name: mkshrc-3 description: Check that ~/.mkshrc works correctly. Part 3: verify mkshrc can be turned off file-setup: file 644 ".mkshrc" FNORD=42 env-setup: !HOME=.!ENV=nonexistant! stdin: echo x $FNORD expected-stdout: x --- name: sh-mode-1 description: Check that sh mode turns braceexpand off and that that works correctly stdin: set -o braceexpand set +o sh [[ $(set +o) == *@(-o sh)@(| *) ]] && echo sh || echo nosh [[ $(set +o) == *@(-o braceexpand)@(| *) ]] && echo brex || echo nobrex echo {a,b,c} set +o braceexpand echo {a,b,c} set -o braceexpand echo {a,b,c} set -o sh echo {a,b,c} [[ $(set +o) == *@(-o sh)@(| *) ]] && echo sh || echo nosh [[ $(set +o) == *@(-o braceexpand)@(| *) ]] && echo brex || echo nobrex set -o braceexpand echo {a,b,c} [[ $(set +o) == *@(-o sh)@(| *) ]] && echo sh || echo nosh [[ $(set +o) == *@(-o braceexpand)@(| *) ]] && echo brex || echo nobrex expected-stdout: nosh brex a b c {a,b,c} a b c {a,b,c} sh nobrex a b c sh brex --- name: sh-mode-2a description: Check that posix or sh mode is *not* automatically turned on category: !binsh stdin: ln -s "$__progname" ksh || cp "$__progname" ksh ln -s "$__progname" sh || cp "$__progname" sh ln -s "$__progname" ./-ksh || cp "$__progname" ./-ksh ln -s "$__progname" ./-sh || cp "$__progname" ./-sh for shell in {,-}{,k}sh; do print -- $shell $(./$shell +l -c \ '[[ $(set +o) == *"-o "@(sh|posix)@(| *) ]] && echo sh || echo nosh') done expected-stdout: sh nosh ksh nosh -sh nosh -ksh nosh --- name: sh-mode-2b description: Check that posix or sh mode *is* automatically turned on category: binsh stdin: ln -s "$__progname" ksh || cp "$__progname" ksh ln -s "$__progname" sh || cp "$__progname" sh ln -s "$__progname" ./-ksh || cp "$__progname" ./-ksh ln -s "$__progname" ./-sh || cp "$__progname" ./-sh for shell in {,-}{,k}sh; do print -- $shell $(./$shell +l -c \ '[[ $(set +o) == *"-o "@(sh|posix)@(| *) ]] && echo sh || echo nosh') done expected-stdout: sh sh ksh nosh -sh sh -ksh nosh --- name: pipeline-1 description: pdksh bug: last command of a pipeline is executed in a subshell - make sure it still is, scripts depend on it file-setup: file 644 "abcx" file-setup: file 644 "abcy" stdin: echo * echo a | while read d; do echo $d echo $d* echo * set -o noglob echo $d* echo * done echo * expected-stdout: abcx abcy a abcx abcy abcx abcy a* * abcx abcy --- name: pipeline-2 description: check that co-processes work with TCOMs, TPIPEs and TPARENs category: !nojsig stdin: "$__progname" -c 'i=100; echo hi |& while read -p line; do echo "$((i++)) $line"; done' "$__progname" -c 'i=200; echo hi | cat |& while read -p line; do echo "$((i++)) $line"; done' "$__progname" -c 'i=300; (echo hi | cat) |& while read -p line; do echo "$((i++)) $line"; done' expected-stdout: 100 hi 200 hi 300 hi --- name: pipeline-3 description: Check that PIPESTATUS does what it's supposed to stdin: echo 1 $PIPESTATUS . echo 2 ${PIPESTATUS[0]} . echo 3 ${PIPESTATUS[1]} . (echo x; exit 12) | (cat; exit 23) | (cat; exit 42) echo 5 $? , $PIPESTATUS , ${PIPESTATUS[0]} , ${PIPESTATUS[1]} , ${PIPESTATUS[2]} , ${PIPESTATUS[3]} . echo 6 ${PIPESTATUS[0]} . set | fgrep PIPESTATUS echo 8 $(set | fgrep PIPESTATUS) . expected-stdout: 1 0 . 2 0 . 3 . x 5 42 , 12 , 12 , 23 , 42 , . 6 0 . PIPESTATUS[0]=0 8 PIPESTATUS[0]=0 PIPESTATUS[1]=0 . --- name: pipeline-4 description: Check that "set -o pipefail" does what it's supposed to stdin: echo 1 "$("$__progname" -c '(exit 12) | (exit 23) | (exit 42); echo $?')" . echo 2 "$("$__progname" -c '! (exit 12) | (exit 23) | (exit 42); echo $?')" . echo 3 "$("$__progname" -o pipefail -c '(exit 12) | (exit 23) | (exit 42); echo $?')" . echo 4 "$("$__progname" -o pipefail -c '! (exit 12) | (exit 23) | (exit 42); echo $?')" . echo 5 "$("$__progname" -c '(exit 23) | (exit 42) | :; echo $?')" . echo 6 "$("$__progname" -c '! (exit 23) | (exit 42) | :; echo $?')" . echo 7 "$("$__progname" -o pipefail -c '(exit 23) | (exit 42) | :; echo $?')" . echo 8 "$("$__progname" -o pipefail -c '! (exit 23) | (exit 42) | :; echo $?')" . echo 9 "$("$__progname" -o pipefail -c 'x=$( (exit 23) | (exit 42) | :); echo $?')" . expected-stdout: 1 42 . 2 0 . 3 42 . 4 0 . 5 0 . 6 1 . 7 42 . 8 0 . 9 42 . --- name: persist-history-1 description: Check if persistent history saving works category: !no-histfile need-ctty: yes arguments: !-i! env-setup: !ENV=./Env!HISTFILE=hist.file! file-setup: file 644 "Env" PS1=X stdin: cat hist.file expected-stdout-pattern: /cat hist.file/ expected-stderr-pattern: /^X*$/ --- name: typeset-1 description: Check that global does what typeset is supposed to do stdin: set -A arrfoo 65 foo() { global -Uui16 arrfoo[*] } echo before ${arrfoo[0]} . foo echo after ${arrfoo[0]} . set -A arrbar 65 bar() { echo inside before ${arrbar[0]} . arrbar[0]=97 echo inside changed ${arrbar[0]} . global -Uui16 arrbar[*] echo inside typeset ${arrbar[0]} . arrbar[0]=48 echo inside changed ${arrbar[0]} . } echo before ${arrbar[0]} . bar echo after ${arrbar[0]} . expected-stdout: before 65 . after 16#41 . before 65 . inside before 65 . inside changed 97 . inside typeset 16#61 . inside changed 16#30 . after 16#30 . --- name: typeset-padding-1 description: Check if left/right justification works as per TFM stdin: typeset -L10 ln=0hall0 typeset -R10 rn=0hall0 typeset -ZL10 lz=0hall0 typeset -ZR10 rz=0hall0 typeset -Z10 rx=" hallo " echo "<$ln> <$rn> <$lz> <$rz> <$rx>" expected-stdout: <0hall0 > < 0hall0> <00000hall0> <0000 hallo> --- name: typeset-padding-2 description: Check if base-!10 integers are padded right stdin: typeset -Uui16 -L9 ln=16#1 typeset -Uui16 -R9 rn=16#1 typeset -Uui16 -Z9 zn=16#1 typeset -L9 ls=16#1 typeset -R9 rs=16#1 typeset -Z9 zs=16#1 echo "<$ln> <$rn> <$zn> <$ls> <$rs> <$zs>" expected-stdout: <16#1 > < 16#1> <16#000001> <16#1 > < 16#1> <0000016#1> --- name: utf8bom-1 description: Check that the UTF-8 Byte Order Mark is ignored as the first multibyte character of the shell input (with -c, from standard input, as file, or as eval argument), but nowhere else # breaks on Mac OSX (HFS+ non-standard Unicode canonical decomposition) category: !os:darwin stdin: mkdir foo print '#!/bin/sh\necho ohne' >foo/fnord print '#!/bin/sh\necho mit' >foo/fnord print 'fnord\nfnord\nfnord\nfnord' >foo/bar print eval \''fnord\nfnord\nfnord\nfnord'\' >foo/zoo set -A anzahl -- foo/* echo got ${#anzahl[*]} files chmod +x foo/* export PATH=$(pwd)/foo$PATHSEP$PATH "$__progname" -c 'fnord' echo = "$__progname" -c 'fnord; fnord; fnord; fnord' echo = "$__progname" foo/bar echo = "$__progname" t1 print '#!'"$__progname"'\nprint "2 a=$ENV{FOO}";' >t2 print '#!'"$__perlname"'\nprint "3 a=$ENV{FOO}\n";' >t3 print '#!'"$__perlname"'\nprint "4 a=$ENV{FOO}\n";' >t4 chmod +x t? ./t1 ./t2 ./t3 ./t4 expected-stdout: 1 a=/nonexistant{FOO} 2 a=/nonexistant{FOO} 3 a=BAR 4 a=BAR expected-stderr-pattern: /(Unrecognized character .... ignored at \..t4 line 1)*/ --- name: utf8opt-1a description: Check that the utf8-mode flag is not set at non-interactive startup category: !os:hpux env-setup: !PS1=!PS2=!LC_CTYPE=en_US.UTF-8! stdin: if [[ $- = *U* ]]; then echo is set else echo is not set fi expected-stdout: is not set --- name: utf8opt-1b description: Check that the utf8-mode flag is not set at non-interactive startup category: os:hpux env-setup: !PS1=!PS2=!LC_CTYPE=en_US.utf8! stdin: if [[ $- = *U* ]]; then echo is set else echo is not set fi expected-stdout: is not set --- name: utf8opt-2a description: Check that the utf8-mode flag is set at interactive startup. -DMKSH_ASSUME_UTF8=0 => expected failure, please ignore -DMKSH_ASSUME_UTF8=1 => not expected, please investigate -UMKSH_ASSUME_UTF8 => not expected, but if your OS is old, try passing HAVE_SETLOCALE_CTYPE=0 to Build.sh need-pass: no category: !os:hpux,!os:msys need-ctty: yes arguments: !-i! env-setup: !PS1=!PS2=!LC_CTYPE=en_US.UTF-8! stdin: if [[ $- = *U* ]]; then echo is set else echo is not set fi expected-stdout: is set expected-stderr-pattern: /(# )*/ --- name: utf8opt-2b description: Check that the utf8-mode flag is set at interactive startup Expected failure if -DMKSH_ASSUME_UTF8=0 category: os:hpux need-ctty: yes arguments: !-i! env-setup: !PS1=!PS2=!LC_CTYPE=en_US.utf8! stdin: if [[ $- = *U* ]]; then echo is set else echo is not set fi expected-stdout: is set expected-stderr-pattern: /(# )*/ --- name: utf8opt-3a description: Ensure ±U on the command line is honoured (these two tests may pass falsely depending on CPPFLAGS) stdin: export i=0 code='if [[ $- = *U* ]]; then echo $i on; else echo $i off; fi' let i++; "$__progname" -U -c "$code" let i++; "$__progname" +U -c "$code" echo $((++i)) done expected-stdout: 1 on 2 off 3 done --- name: utf8opt-3b description: Ensure ±U on the command line is honoured, interactive shells need-ctty: yes stdin: export i=0 code='if [[ $- = *U* ]]; then echo $i on; else echo $i off; fi' let i++; "$__progname" -U -ic "$code" let i++; "$__progname" +U -ic "$code" echo $((++i)) done expected-stdout: 1 on 2 off 3 done --- name: utf8bug-1 description: Ensure trailing combining characters are not lost stdin: set -U a=a b=$'\u0301' x=$a$b print -r -- "" x=$a x+=$b print -r -- "" b=$'\u0301'b x=$a x+=$b print -r -- "" expected-stdout: --- name: aliases-1 description: Check if built-in shell aliases are okay stdin: alias typeset -f expected-stdout: autoload='\typeset -fu' functions='\typeset -f' hash='\builtin alias -t' history='\builtin fc -l' integer='\typeset -i' local='\typeset' login='\exec login' nameref='\typeset -n' nohup='nohup ' r='\builtin fc -e -' type='\builtin whence -v' --- name: aliases-2b description: Check if “set -o sh” does not influence built-in aliases arguments: !-o!sh! stdin: alias typeset -f expected-stdout: autoload='\typeset -fu' functions='\typeset -f' hash='\builtin alias -t' history='\builtin fc -l' integer='\typeset -i' local='\typeset' login='\exec login' nameref='\typeset -n' nohup='nohup ' r='\builtin fc -e -' type='\builtin whence -v' --- name: aliases-3b description: Check if running as sh does not influence built-in aliases stdin: cp "$__progname" sh ./sh -c 'alias; typeset -f' rm -f sh expected-stdout: autoload='\typeset -fu' functions='\typeset -f' hash='\builtin alias -t' history='\builtin fc -l' integer='\typeset -i' local='\typeset' login='\exec login' nameref='\typeset -n' nohup='nohup ' r='\builtin fc -e -' type='\builtin whence -v' --- name: aliases-cmdline description: Check that aliases work from the command line (Debian #517009) Note that due to the nature of the lexing process, defining aliases in COMSUBs then immediately using them, and things like 'alias foo=bar && foo', still fail. stdin: "$__progname" -c $'alias a="echo OK"\na' expected-stdout: OK --- name: aliases-funcdef-1 description: Check if POSIX functions take precedences over aliases stdin: alias foo='echo makro' foo() { echo funktion } foo expected-stdout: makro --- name: aliases-funcdef-2 description: Check if POSIX functions take precedences over aliases stdin: alias foo='echo makro' foo () { echo funktion } foo expected-stdout: makro --- name: aliases-funcdef-3 description: Check if aliases take precedences over Korn functions stdin: alias foo='echo makro' function foo { echo funktion } foo expected-stdout: makro --- name: aliases-funcdef-4 description: Functions should only take over if actually being defined stdin: alias local :|| local() { :; } alias local expected-stdout: local='\typeset' local='\typeset' --- name: arrays-1 description: Check if Korn Shell arrays work as expected stdin: v="c d" set -A foo -- a \$v "$v" '$v' b echo "${#foo[*]}|${foo[0]}|${foo[1]}|${foo[2]}|${foo[3]}|${foo[4]}|" expected-stdout: 5|a|$v|c d|$v|b| --- name: arrays-2a description: Check if bash-style arrays work as expected stdin: v="c d" foo=(a \$v "$v" '$v' b) echo "${#foo[*]}|${foo[0]}|${foo[1]}|${foo[2]}|${foo[3]}|${foo[4]}|" expected-stdout: 5|a|$v|c d|$v|b| --- name: arrays-2b description: Check if bash-style arrays work as expected, with newlines stdin: print '#!'"$__progname"'\nfor x in "$@"; do print -nr -- "$x|"; done' >pfp chmod +x pfp test -n "$ZSH_VERSION" && setopt KSH_ARRAYS v="e f" foo=(a bc d \$v "$v" '$v' g ) ./pfp "${#foo[*]}" "${foo[0]}" "${foo[1]}" "${foo[2]}" "${foo[3]}" "${foo[4]}" "${foo[5]}" "${foo[6]}"; echo foo=(a\ bc d \$v "$v" '$v' g ) ./pfp "${#foo[*]}" "${foo[0]}" "${foo[1]}" "${foo[2]}" "${foo[3]}" "${foo[4]}" "${foo[5]}" "${foo[6]}"; echo foo=(a\ bc\\ d \$v "$v" '$v' g) ./pfp "${#foo[*]}" "${foo[0]}" "${foo[1]}" "${foo[2]}" "${foo[3]}" "${foo[4]}" "${foo[5]}" "${foo[6]}"; echo expected-stdout: 7|a|bc|d|$v|e f|$v|g| 7|a|bc|d|$v|e f|$v|g| 6|abc\|d|$v|e f|$v|g|| --- name: arrays-3 description: Check if array bounds are uint32_t stdin: set -A foo a b c foo[4097]=d foo[2147483637]=e echo ${foo[*]} foo[-1]=f echo ${foo[4294967295]} g ${foo[*]} expected-stdout: a b c d e f g a b c d e f --- name: arrays-4 description: Check if Korn Shell arrays with specified indices work as expected stdin: v="c d" set -A foo -- [1]=\$v [2]="$v" [4]='$v' [0]=a [5]=b echo "${#foo[*]}|${foo[0]}|${foo[1]}|${foo[2]}|${foo[3]}|${foo[4]}|${foo[5]}|" # we don't want this at all: # 5|a|$v|c d||$v|b| set -A arr "[5]=meh" echo "<${arr[0]}><${arr[5]}>" expected-stdout: 5|[1]=$v|[2]=c d|[4]=$v|[0]=a|[5]=b|| <[5]=meh><> --- name: arrays-5 description: Check if bash-style arrays with specified indices work as expected (taken out temporarily to fix arrays-4; see also arrays-9a comment) category: disabled stdin: v="c d" foo=([1]=\$v [2]="$v" [4]='$v' [0]=a [5]=b) echo "${#foo[*]}|${foo[0]}|${foo[1]}|${foo[2]}|${foo[3]}|${foo[4]}|${foo[5]}|" x=([128]=foo bar baz) echo k= ${!x[*]} . echo v= ${x[*]} . # Check that we do not break this by globbing :>b=blah bleh=5 typeset -a arr arr+=([bleh]=blah) echo "<${arr[0]}><${arr[5]}>" expected-stdout: 5|a|$v|c d||$v|b| k= 128 129 130 . v= foo bar baz . <> --- name: arrays-6 description: Check if we can get the array keys (indices) for indexed arrays, Korn shell style stdin: of() { i=0 for x in "$@"; do echo -n "$((i++))<$x>" done echo } foo[1]=eins set | grep '^foo' echo = foo[0]=zwei foo[4]=drei set | grep '^foo' echo = echo a $(of ${foo[*]}) = $(of ${bar[*]}) a echo b $(of "${foo[*]}") = $(of "${bar[*]}") b echo c $(of ${foo[@]}) = $(of ${bar[@]}) c echo d $(of "${foo[@]}") = $(of "${bar[@]}") d echo e $(of ${!foo[*]}) = $(of ${!bar[*]}) e echo f $(of "${!foo[*]}") = $(of "${!bar[*]}") f echo g $(of ${!foo[@]}) = $(of ${!bar[@]}) g echo h $(of "${!foo[@]}") = $(of "${!bar[@]}") h expected-stdout: foo[1]=eins = foo[0]=zwei foo[1]=eins foo[4]=drei = a 012 = a b 0 = 0<> b c 012 = c d 012 = d e 0<0>1<1>2<4> = e f 0<0 1 4> = 0<> f g 0<0>1<1>2<4> = g h 0<0>1<1>2<4> = h --- name: arrays-7 description: Check if we can get the array keys (indices) for indexed arrays, Korn shell style, in some corner cases stdin: echo !arz: ${!arz} echo !arz[0]: ${!arz[0]} echo !arz[1]: ${!arz[1]} arz=foo echo !arz: ${!arz} echo !arz[0]: ${!arz[0]} echo !arz[1]: ${!arz[1]} unset arz echo !arz: ${!arz} echo !arz[0]: ${!arz[0]} echo !arz[1]: ${!arz[1]} expected-stdout: !arz: arz !arz[0]: arz[0] !arz[1]: arz[1] !arz: arz !arz[0]: arz[0] !arz[1]: arz[1] !arz: arz !arz[0]: arz[0] !arz[1]: arz[1] --- name: arrays-8 description: Check some behavioural rules for arrays. stdin: fna() { set -A aa 9 } fnb() { typeset ab set -A ab 9 } fnc() { typeset ac set -A ac 91 unset ac set -A ac 92 } fnd() { set +A ad 9 } fne() { unset ae set +A ae 9 } fnf() { unset af[0] set +A af 9 } fng() { unset ag[*] set +A ag 9 } set -A aa 1 2 set -A ab 1 2 set -A ac 1 2 set -A ad 1 2 set -A ae 1 2 set -A af 1 2 set -A ag 1 2 set -A ah 1 2 typeset -Z3 aa ab ac ad ae af ag print 1a ${aa[*]} . print 1b ${ab[*]} . print 1c ${ac[*]} . print 1d ${ad[*]} . print 1e ${ae[*]} . print 1f ${af[*]} . print 1g ${ag[*]} . print 1h ${ah[*]} . fna fnb fnc fnd fne fnf fng typeset -Z5 ah[*] print 2a ${aa[*]} . print 2b ${ab[*]} . print 2c ${ac[*]} . print 2d ${ad[*]} . print 2e ${ae[*]} . print 2f ${af[*]} . print 2g ${ag[*]} . print 2h ${ah[*]} . expected-stdout: 1a 001 002 . 1b 001 002 . 1c 001 002 . 1d 001 002 . 1e 001 002 . 1f 001 002 . 1g 001 002 . 1h 1 2 . 2a 9 . 2b 001 002 . 2c 92 . 2d 009 002 . 2e 9 . 2f 9 002 . 2g 009 . 2h 00001 00002 . --- name: arrays-9a description: Check that we can concatenate arrays stdin: unset foo; foo=(bar); foo+=(baz); echo 1 ${!foo[*]} : ${foo[*]} . unset foo; foo=(foo bar); foo+=(baz); echo 2 ${!foo[*]} : ${foo[*]} . # unset foo; foo=([2]=foo [0]=bar); foo+=(baz [5]=quux); echo 3 ${!foo[*]} : ${foo[*]} . expected-stdout: 1 0 1 : bar baz . 2 0 1 2 : foo bar baz . # 3 0 2 3 5 : bar foo baz quux . --- name: arrays-9b description: Check that we can concatenate parameters too stdin: unset foo; foo=bar; foo+=baz; echo 1 $foo . unset foo; typeset -i16 foo=10; foo+=20; echo 2 $foo . expected-stdout: 1 barbaz . 2 16#a20 . --- name: arrassign-basic description: Check basic whitespace conserving properties of wdarrassign stdin: a=($(echo a b)) b=($(echo "a b")) c=("$(echo "a b")") d=("$(echo a b)") a+=($(echo c d)) b+=($(echo "c d")) c+=("$(echo "c d")") d+=("$(echo c d)") echo ".a:${a[0]}.${a[1]}.${a[2]}.${a[3]}:" echo ".b:${b[0]}.${b[1]}.${b[2]}.${b[3]}:" echo ".c:${c[0]}.${c[1]}.${c[2]}.${c[3]}:" echo ".d:${d[0]}.${d[1]}.${d[2]}.${d[3]}:" expected-stdout: .a:a.b.c.d: .b:a.b.c.d: .c:a b.c d..: .d:a b.c d..: --- name: arrassign-fnc-none description: Check locality of array access inside a function stdin: function fn { x+=(f) echo ".fn:${x[0]}.${x[1]}.${x[2]}.${x[3]}:" } function rfn { if [[ -n $BASH_VERSION ]]; then y=() else set -A y fi y+=(f) echo ".rfn:${y[0]}.${y[1]}.${y[2]}.${y[3]}:" } x=(m m) y=(m m) echo ".f0:${x[0]}.${x[1]}.${x[2]}.${x[3]}:" fn echo ".f1:${x[0]}.${x[1]}.${x[2]}.${x[3]}:" fn echo ".f2:${x[0]}.${x[1]}.${x[2]}.${x[3]}:" echo ".rf0:${y[0]}.${y[1]}.${y[2]}.${y[3]}:" rfn echo ".rf1:${y[0]}.${y[1]}.${y[2]}.${y[3]}:" rfn echo ".rf2:${y[0]}.${y[1]}.${y[2]}.${y[3]}:" expected-stdout: .f0:m.m..: .fn:m.m.f.: .f1:m.m.f.: .fn:m.m.f.f: .f2:m.m.f.f: .rf0:m.m..: .rfn:f...: .rf1:f...: .rfn:f...: .rf2:f...: --- name: arrassign-fnc-local description: Check locality of array access inside a function with the bash/mksh/ksh93 local/typeset keyword (note: ksh93 has no local; typeset works only in FKSH) stdin: function fn { typeset x x+=(f) echo ".fn:${x[0]}.${x[1]}.${x[2]}.${x[3]}:" } function rfn { if [[ -n $BASH_VERSION ]]; then y=() else set -A y fi typeset y y+=(f) echo ".rfn:${y[0]}.${y[1]}.${y[2]}.${y[3]}:" } function fnr { typeset z if [[ -n $BASH_VERSION ]]; then z=() else set -A z fi z+=(f) echo ".fnr:${z[0]}.${z[1]}.${z[2]}.${z[3]}:" } x=(m m) y=(m m) z=(m m) echo ".f0:${x[0]}.${x[1]}.${x[2]}.${x[3]}:" fn echo ".f1:${x[0]}.${x[1]}.${x[2]}.${x[3]}:" fn echo ".f2:${x[0]}.${x[1]}.${x[2]}.${x[3]}:" echo ".rf0:${y[0]}.${y[1]}.${y[2]}.${y[3]}:" rfn echo ".rf1:${y[0]}.${y[1]}.${y[2]}.${y[3]}:" rfn echo ".rf2:${y[0]}.${y[1]}.${y[2]}.${y[3]}:" echo ".f0r:${z[0]}.${z[1]}.${z[2]}.${z[3]}:" fnr echo ".f1r:${z[0]}.${z[1]}.${z[2]}.${z[3]}:" fnr echo ".f2r:${z[0]}.${z[1]}.${z[2]}.${z[3]}:" expected-stdout: .f0:m.m..: .fn:f...: .f1:m.m..: .fn:f...: .f2:m.m..: .rf0:m.m..: .rfn:f...: .rf1:...: .rfn:f...: .rf2:...: .f0r:m.m..: .fnr:f...: .f1r:m.m..: .fnr:f...: .f2r:m.m..: --- name: arrassign-fnc-global description: Check locality of array access inside a function with the mksh-specific global keyword stdin: function fn { global x x+=(f) echo ".fn:${x[0]}.${x[1]}.${x[2]}.${x[3]}:" } function rfn { set -A y global y y+=(f) echo ".rfn:${y[0]}.${y[1]}.${y[2]}.${y[3]}:" } function fnr { global z set -A z z+=(f) echo ".fnr:${z[0]}.${z[1]}.${z[2]}.${z[3]}:" } x=(m m) y=(m m) z=(m m) echo ".f0:${x[0]}.${x[1]}.${x[2]}.${x[3]}:" fn echo ".f1:${x[0]}.${x[1]}.${x[2]}.${x[3]}:" fn echo ".f2:${x[0]}.${x[1]}.${x[2]}.${x[3]}:" echo ".rf0:${y[0]}.${y[1]}.${y[2]}.${y[3]}:" rfn echo ".rf1:${y[0]}.${y[1]}.${y[2]}.${y[3]}:" rfn echo ".rf2:${y[0]}.${y[1]}.${y[2]}.${y[3]}:" echo ".f0r:${z[0]}.${z[1]}.${z[2]}.${z[3]}:" fnr echo ".f1r:${z[0]}.${z[1]}.${z[2]}.${z[3]}:" fnr echo ".f2r:${z[0]}.${z[1]}.${z[2]}.${z[3]}:" expected-stdout: .f0:m.m..: .fn:m.m.f.: .f1:m.m.f.: .fn:m.m.f.f: .f2:m.m.f.f: .rf0:m.m..: .rfn:f...: .rf1:f...: .rfn:f...: .rf2:f...: .f0r:m.m..: .fnr:f...: .f1r:f...: .fnr:f...: .f2r:f...: --- name: strassign-fnc-none description: Check locality of string access inside a function stdin: function fn { x+=f echo ".fn:$x:" } function rfn { y= y+=f echo ".rfn:$y:" } x=m y=m echo ".f0:$x:" fn echo ".f1:$x:" fn echo ".f2:$x:" echo ".rf0:$y:" rfn echo ".rf1:$y:" rfn echo ".rf2:$y:" expected-stdout: .f0:m: .fn:mf: .f1:mf: .fn:mff: .f2:mff: .rf0:m: .rfn:f: .rf1:f: .rfn:f: .rf2:f: --- name: strassign-fnc-local description: Check locality of string access inside a function with the bash/mksh/ksh93 local/typeset keyword (note: ksh93 has no local; typeset works only in FKSH) stdin: function fn { typeset x x+=f echo ".fn:$x:" } function rfn { y= typeset y y+=f echo ".rfn:$y:" } function fnr { typeset z z= z+=f echo ".fnr:$z:" } x=m y=m z=m echo ".f0:$x:" fn echo ".f1:$x:" fn echo ".f2:$x:" echo ".rf0:$y:" rfn echo ".rf1:$y:" rfn echo ".rf2:$y:" echo ".f0r:$z:" fnr echo ".f1r:$z:" fnr echo ".f2r:$z:" expected-stdout: .f0:m: .fn:f: .f1:m: .fn:f: .f2:m: .rf0:m: .rfn:f: .rf1:: .rfn:f: .rf2:: .f0r:m: .fnr:f: .f1r:m: .fnr:f: .f2r:m: --- name: strassign-fnc-global description: Check locality of string access inside a function with the mksh-specific global keyword stdin: function fn { global x x+=f echo ".fn:$x:" } function rfn { y= global y y+=f echo ".rfn:$y:" } function fnr { global z z= z+=f echo ".fnr:$z:" } x=m y=m z=m echo ".f0:$x:" fn echo ".f1:$x:" fn echo ".f2:$x:" echo ".rf0:$y:" rfn echo ".rf1:$y:" rfn echo ".rf2:$y:" echo ".f0r:$z:" fnr echo ".f1r:$z:" fnr echo ".f2r:$z:" expected-stdout: .f0:m: .fn:mf: .f1:mf: .fn:mff: .f2:mff: .rf0:m: .rfn:f: .rf1:f: .rfn:f: .rf2:f: .f0r:m: .fnr:f: .f1r:f: .fnr:f: .f2r:f: --- name: unset-fnc-local-ksh description: Check that “unset” removes a previous “local” (ksh93 syntax compatible version); apparently, there are shells which fail this? stdin: function f { echo f0: $x typeset x echo f1: $x x=fa echo f2: $x unset x echo f3: $x x=fb echo f4: $x } x=o echo before: $x f echo after: $x expected-stdout: before: o f0: o f1: f2: fa f3: o f4: fb after: fb --- name: unset-fnc-local-sh description: Check that “unset” removes a previous “local” (Debian Policy §10.4 sh version); apparently, there are shells which fail this? stdin: f() { echo f0: $x local x echo f1: $x x=fa echo f2: $x unset x echo f3: $x x=fb echo f4: $x } x=o echo before: $x f echo after: $x expected-stdout: before: o f0: o f1: f2: fa f3: o f4: fb after: fb --- name: varexpand-substr-1 description: Check if bash-style substring expansion works when using positive numerics stdin: x=abcdefghi typeset -i y=123456789 typeset -i 16 z=123456789 # 16#75bcd15 echo a t${x:2:2} ${y:2:3} ${z:2:3} a echo b ${x::3} ${y::3} ${z::3} b echo c ${x:2:} ${y:2:} ${z:2:} c echo d ${x:2} ${y:2} ${z:2} d echo e ${x:2:6} ${y:2:6} ${z:2:7} e echo f ${x:2:7} ${y:2:7} ${z:2:8} f echo g ${x:2:8} ${y:2:8} ${z:2:9} g expected-stdout: a tcd 345 #75 a b abc 123 16# b c c d cdefghi 3456789 #75bcd15 d e cdefgh 345678 #75bcd1 e f cdefghi 3456789 #75bcd15 f g cdefghi 3456789 #75bcd15 g --- name: varexpand-substr-2 description: Check if bash-style substring expansion works when using negative numerics or expressions stdin: x=abcdefghi typeset -i y=123456789 typeset -i 16 z=123456789 # 16#75bcd15 n=2 echo a ${x:$n:3} ${y:$n:3} ${z:$n:3} a echo b ${x:(n):3} ${y:(n):3} ${z:(n):3} b echo c ${x:(-2):1} ${y:(-2):1} ${z:(-2):1} c echo d t${x: n:2} ${y: n:3} ${z: n:3} d expected-stdout: a cde 345 #75 a b cde 345 #75 b c h 8 1 c d tcd 345 #75 d --- name: varexpand-substr-3 description: Check that some things that work in bash fail. This is by design. Oh and vice versa, nowadays. stdin: export x=abcdefghi n=2 "$__progname" -c 'echo v${x:(n)}x' "$__progname" -c 'echo w${x: n}x' "$__progname" -c 'echo x${x:n}x' "$__progname" -c 'echo y${x:}x' "$__progname" -c 'echo z${x}x' # next fails only in bash "$__progname" -c 'x=abcdef;y=123;echo ${x:${y:2:1}:2}' >/dev/null 2>&1; echo $? expected-stdout: vcdefghix wcdefghix zabcdefghix 0 expected-stderr-pattern: /x:n.*bad substitution.*\n.*bad substitution/ --- name: varexpand-substr-4 description: Check corner cases for substring expansion stdin: x=abcdefghi integer y=2 echo a ${x:(y == 1 ? 2 : 3):4} a expected-stdout: a defg a --- name: varexpand-substr-5A description: Check that substring expansions work on characters stdin: set +U x=mäh echo a ${x::1} ${x: -1} a echo b ${x::3} ${x: -3} b echo c ${x:1:2} ${x: -3:2} c echo d ${#x} d expected-stdout: a m h a b mä äh b c ä ä c d 4 d --- name: varexpand-substr-5W description: Check that substring expansions work on characters stdin: set -U x=mäh echo a ${x::1} ${x: -1} a echo b ${x::2} ${x: -2} b echo c ${x:1:1} ${x: -2:1} c echo d ${#x} d expected-stdout: a m h a b mä äh b c ä ä c d 3 d --- name: varexpand-substr-6 description: Check that string substitution works correctly stdin: foo=1 bar=2 baz=qwertyuiop echo a ${baz: foo: bar} echo b ${baz: foo: $bar} echo c ${baz: $foo: bar} echo d ${baz: $foo: $bar} expected-stdout: a we b we c we d we --- name: varexpand-special-hash description: Check special ${var@x} expansion for x=hash stdin: typeset -i8 foo=10 bar=baz unset baz print ${foo@#} ${bar@#} ${baz@#} . expected-stdout: 9B15FBFB CFBDD32B 00000000 . --- name: varexpand-special-quote description: Check special ${var@Q} expansion for quoted strings stdin: set +U i=x j=a\ b k=$'c d\xA0''e€f' print -r -- "" s="u=${i@Q} v=${j@Q} w=${k@Q}" print -r -- "s=\"$s\"" eval "$s" typeset -p u v w expected-stdout: s="u=x v='a b' w=$'c\nd\240e\u20ACf'" typeset u=x typeset v='a b' typeset w=$'c\nd\240e\u20ACf' --- name: varexpand-null-1 description: Ensure empty strings expand emptily stdin: print s ${a} . ${b} S print t ${a#?} . ${b%?} T print r ${a=} . ${b/c/d} R print q print s "${a}" . "${b}" S print t "${a#?}" . "${b%?}" T print r "${a=}" . "${b/c/d}" R expected-stdout: s . S t . T r . R q s . S t . T r . R --- name: varexpand-null-2 description: Ensure empty strings, when quoted, are expanded as empty strings stdin: print '#!'"$__progname"'\nfor x in "$@"; do print -nr -- "<$x> "; done' >pfs chmod +x pfs ./pfs 1 "${a}" 2 "${a#?}" + "${b%?}" 3 "${a=}" + "${b/c/d}" echo . expected-stdout: <1> <> <2> <> <+> <> <3> <> <+> <> . --- name: varexpand-null-3 description: Ensure concatenating behaviour matches other shells stdin: showargs() { for s_arg in "$@"; do echo -n "<$s_arg> "; done; echo .; } showargs 0 ""$@ x=; showargs 1 "$x"$@ set A; showargs 2 "${@:+}" n() { echo "$#"; } unset e set -- a b n """$@" n "$@" n "$@""" n "$e""$@" n "$@" n "$@""$e" set -- n """$@" n "$@" n "$@""" n "$e""$@" n "$@" n "$@""$e" expected-stdout: <0> <> . <1> <> . <2> <> . 2 2 2 2 2 2 1 0 1 1 0 1 --- name: varexpand-funny-chars description: Check some characters XXX \uEF80 is asymmetric, possibly buggy so we don’t check this stdin: x=$'<\x00>'; typeset -p x x=$'<\x01>'; typeset -p x x=$'<\u0000>'; typeset -p x x=$'<\u0001>'; typeset -p x expected-stdout: typeset x='<' typeset x=$'<\001>' typeset x='<' typeset x=$'<\001>' --- name: print-funny-chars description: Check print builtin's capability to output designated characters stdin: { print '<\0144\0344\xDB\u00DB\u20AC\uDB\x40>' print '<\x00>' print '<\x01>' print '<\u0000>' print '<\u0001>' } | { # integer-base-one-3Ar typeset -Uui16 -Z11 pos=0 typeset -Uui16 -Z5 hv=2147483647 dasc= if read -arN -1 line; then typeset -i1 line i=0 while (( i < ${#line[*]} )); do hv=${line[i++]} if (( (pos & 15) == 0 )); then (( pos )) && print -r -- "$dasc|" print -n "${pos#16#} " dasc=' |' fi print -n "${hv#16#} " if (( (hv < 32) || (hv > 126) )); then dasc=$dasc. else dasc=$dasc${line[i-1]#1#} fi (( (pos++ & 15) == 7 )) && print -n -- '- ' done fi while (( pos & 15 )); do print -n ' ' (( (pos++ & 15) == 7 )) && print -n -- '- ' done (( hv == 2147483647 )) || print -r -- "$dasc|" } expected-stdout: 00000000 3C 64 E4 DB C3 9B E2 82 - AC C3 9B 40 3E 0A 3C 00 |.<.| 00000010 3E 0A 3C 01 3E 0A 3C 00 - 3E 0A 3C 01 3E 0A |>.<.>.<.>.<.>.| --- name: print-bksl-c description: Check print builtin's \c escape stdin: print '\ca'; print b expected-stdout: ab --- name: print-cr description: Check that CR+LF is not collapsed into LF as some MSYS shells wrongly do stdin: echo '#!'"$__progname" >foo cat >>foo <<-'EOF' print -n -- '220-blau.mirbsd.org ESMTP ready at Thu, 25 Jul 2013 15:57:57 GMT\r\n220->> Bitte keine Werbung einwerfen! <<\r\r\n220 Who do you wanna pretend to be today' print \? EOF chmod +x foo echo "[$(./foo)]" ./foo | while IFS= read -r line; do print -r -- "{$line}" done expected-stdout: [220-blau.mirbsd.org ESMTP ready at Thu, 25 Jul 2013 15:57:57 GMT 220->> Bitte keine Werbung einwerfen! << 220 Who do you wanna pretend to be today? ] {220-blau.mirbsd.org ESMTP ready at Thu, 25 Jul 2013 15:57:57 GMT } {220->> Bitte keine Werbung einwerfen! << } {220 Who do you wanna pretend to be today? } --- name: print-crlf description: Check that CR+LF is shown and read as-is stdin: cat >foo <<-'EOF' x='bar ' # echo .${#x} # if test x"$KSH_VERSION" = x""; then # printf '<%s>' "$x" # else # print -nr -- "<$x>" # fi # EOF echo "[$("$__progname" foo)]" "$__progname" foo | while IFS= read -r line; do print -r -- "{$line}" done expected-stdout: [.5 ] {.5} {foo <<-'EOF' x='bar ' # echo .${#x} # if test x"$KSH_VERSION" = x""; then # printf '<%s>' "$x" # else # print -nr -- "<$x>" # fi # EOF echo "[$("$__progname" foo)]" "$__progname" foo | while IFS= read -r line; do print -r -- "{$line}" done expected-stdout: [.4 ] {.4} {') print $(($(print '<\0>' | wc -c))) $(($(print "$x" | wc -c))) \ ${#x} "$x" '<\0>' expected-stdout-pattern: /^4 3 2 <> <\0>$/ --- name: print-array description: Check that print -A works as expected stdin: print -An 0x20AC 0xC3 0xBC 8#101 set -U print -A 0x20AC 0xC3 0xBC 8#102 expected-stdout: üA€Ã¼B --- name: print-escapes description: Check backslash expansion by the print builtin stdin: print '\ \!\"\#\$\%\&'\\\''\(\)\*\+\,\-\.\/\0\1\2\3\4\5\6\7\8' \ '\9\:\;\<\=\>\?\@\A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T' \ '\U\V\W\X\Y\Z\[\\\]\^\_\`\a\b \d\e\f\g\h\i\j\k\l\m\n\o\p' \ '\q\r\s\t\u\v\w\x\y\z\{\|\}\~' '\u20acd' '\U20acd' '\x123' \ '\0x' '\0123' '\01234' | { # integer-base-one-3As typeset -Uui16 -Z11 pos=0 typeset -Uui16 -Z5 hv=2147483647 typeset -i1 wc=0x0A dasc= nl=${wc#1#} while IFS= read -r line; do line=$line$nl while [[ -n $line ]]; do hv=1#${line::1} if (( (pos & 15) == 0 )); then (( pos )) && print -r -- "$dasc|" print -n "${pos#16#} " dasc=' |' fi print -n "${hv#16#} " if (( (hv < 32) || (hv > 126) )); then dasc=$dasc. else dasc=$dasc${line::1} fi (( (pos++ & 15) == 7 )) && print -n -- '- ' line=${line:1} done done while (( pos & 15 )); do print -n ' ' (( (pos++ & 15) == 7 )) && print -n -- '- ' done (( hv == 2147483647 )) || print -r -- "$dasc|" } expected-stdout: 00000000 5C 20 5C 21 5C 22 5C 23 - 5C 24 5C 25 5C 26 5C 27 |\ \!\"\#\$\%\&\'| 00000010 5C 28 5C 29 5C 2A 5C 2B - 5C 2C 5C 2D 5C 2E 5C 2F |\(\)\*\+\,\-\.\/| 00000020 5C 31 5C 32 5C 33 5C 34 - 5C 35 5C 36 5C 37 5C 38 |\1\2\3\4\5\6\7\8| 00000030 20 5C 39 5C 3A 5C 3B 5C - 3C 5C 3D 5C 3E 5C 3F 5C | \9\:\;\<\=\>\?\| 00000040 40 5C 41 5C 42 5C 43 5C - 44 1B 5C 46 5C 47 5C 48 |@\A\B\C\D.\F\G\H| 00000050 5C 49 5C 4A 5C 4B 5C 4C - 5C 4D 5C 4E 5C 4F 5C 50 |\I\J\K\L\M\N\O\P| 00000060 5C 51 5C 52 5C 53 5C 54 - 20 5C 55 5C 56 5C 57 5C |\Q\R\S\T \U\V\W\| 00000070 58 5C 59 5C 5A 5C 5B 5C - 5C 5D 5C 5E 5C 5F 5C 60 |X\Y\Z\[\\]\^\_\`| 00000080 07 08 20 20 5C 64 1B 0C - 5C 67 5C 68 5C 69 5C 6A |.. \d..\g\h\i\j| 00000090 5C 6B 5C 6C 5C 6D 0A 5C - 6F 5C 70 20 5C 71 0D 5C |\k\l\m.\o\p \q.\| 000000A0 73 09 5C 75 0B 5C 77 5C - 78 5C 79 5C 7A 5C 7B 5C |s.\u.\w\x\y\z\{\| 000000B0 7C 5C 7D 5C 7E 20 E2 82 - AC 64 20 EF BF BD 20 12 ||\}\~ ...d ... .| 000000C0 33 20 78 20 53 20 53 34 - 0A |3 x S S4.| --- name: dollar-doublequoted-strings description: Check that a $ preceding "…" is ignored stdin: echo $"Localise me!" cat <<<$"Me too!" V=X aol=aol cat <<-$"aol" I do not take a $V for a V! aol expected-stdout: Localise me! Me too! I do not take a $V for a V! --- name: dollar-quoted-strings description: Check backslash expansion by $'…' strings stdin: print '#!'"$__progname"'\nfor x in "$@"; do print -r -- "$x"; done' >pfn chmod +x pfn ./pfn $'\ \!\"\#\$\%\&\'\(\)\*\+\,\-\.\/ \1\2\3\4\5\6' \ $'a\0b' $'a\01b' $'\7\8\9\:\;\<\=\>\?\@\A\B\C\D\E\F\G\H\I' \ $'\J\K\L\M\N\O\P\Q\R\S\T\U1\V\W\X\Y\Z\[\\\]\^\_\`\a\b\d\e' \ $'\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u1\v\w\x1\y\z\{\|\}\~ $x' \ $'\u20acd' $'\U20acd' $'\x123' $'fn\x0rd' $'\0234' $'\234' \ $'\2345' $'\ca' $'\c!' $'\c?' $'\c€' $'a\ b' | { # integer-base-one-3As typeset -Uui16 -Z11 pos=0 typeset -Uui16 -Z5 hv=2147483647 typeset -i1 wc=0x0A dasc= nl=${wc#1#} while IFS= read -r line; do line=$line$nl while [[ -n $line ]]; do hv=1#${line::1} if (( (pos & 15) == 0 )); then (( pos )) && print -r -- "$dasc|" print -n "${pos#16#} " dasc=' |' fi print -n "${hv#16#} " if (( (hv < 32) || (hv > 126) )); then dasc=$dasc. else dasc=$dasc${line::1} fi (( (pos++ & 15) == 7 )) && print -n -- '- ' line=${line:1} done done while (( pos & 15 )); do print -n ' ' (( (pos++ & 15) == 7 )) && print -n -- '- ' done (( hv == 2147483647 )) || print -r -- "$dasc|" } expected-stdout: 00000000 20 21 22 23 24 25 26 27 - 28 29 2A 2B 2C 2D 2E 2F | !"#$%&'()*+,-./| 00000010 20 01 02 03 04 05 06 0A - 61 0A 61 01 62 0A 07 38 | .......a.a.b..8| 00000020 39 3A 3B 3C 3D 3E 3F 40 - 41 42 43 44 1B 46 47 48 |9:;<=>?@ABCD.FGH| 00000030 49 0A 4A 4B 4C 4D 4E 4F - 50 51 52 53 54 01 56 57 |I.JKLMNOPQRST.VW| 00000040 58 59 5A 5B 5C 5D 5E 5F - 60 07 08 64 1B 0A 0C 67 |XYZ[\]^_`..d...g| 00000050 68 69 6A 6B 6C 6D 0A 6F - 70 71 0D 73 09 01 0B 77 |hijklm.opq.s...w| 00000060 01 79 7A 7B 7C 7D 7E 20 - 24 78 0A E2 82 AC 64 0A |.yz{|}~ $x....d.| 00000070 EF BF BD 0A C4 A3 0A 66 - 6E 0A 13 34 0A 9C 0A 9C |.......fn..4....| 00000080 35 0A 01 0A 01 0A 7F 0A - 02 82 AC 0A 61 0A 62 0A |5...........a.b.| --- name: dollar-quotes-in-heredocs-strings description: They are, however, not parsed in here documents, here strings (outside of string delimiters) or regular strings, but in parameter substitutions. stdin: cat <dotfile (exit 42) . ./dotfile echo 1 $? . expected-stdout: 1 0 . --- name: alias-function-no-conflict description: make aliases not conflict with function definitions stdin: # POSIX function can be defined, but alias overrides it alias foo='echo bar' foo foo() { echo baz } foo unset -f foo foo 2>/dev/null || echo rab # alias overrides ksh function alias korn='echo bar' korn function korn { echo baz } korn # alias temporarily overrides POSIX function bla() { echo bfn } bla alias bla='echo bal' bla unalias bla bla expected-stdout: bar bar bar bar bar bfn bal bfn --- name: bash-function-parens description: ensure the keyword function is ignored when preceding POSIX style function declarations (bashism) stdin: mk() { echo '#!'"$__progname" echo "$1 {" echo ' echo "bar='\''$0'\'\" echo '}' print -r -- "${2:-foo}" } mk 'function foo' >f-korn mk 'foo ()' >f-dash mk 'function foo ()' >f-bash print '#!'"$__progname"'\nprint -r -- "${0%/f-argh}"' >f-argh chmod +x f-* u=$(./f-argh) x="korn: $(./f-korn)"; echo "${x/@("$u")/.}" x="dash: $(./f-dash)"; echo "${x/@("$u")/.}" x="bash: $(./f-bash)"; echo "${x/@("$u")/.}" expected-stdout: korn: bar='foo' dash: bar='./f-dash' bash: bar='./f-bash' --- name: integer-base-one-1 description: check if the use of fake integer base 1 works stdin: set -U typeset -Uui16 i0=1# i1=1#€ typeset -i1 o0a=64 typeset -i1 o1a=0x263A typeset -Uui1 o0b=0x7E typeset -Uui1 o1b=0xFDD0 integer px=0xCAFE 'p0=1# ' p1=1#… pl=1#f echo "in <$i0> <$i1>" echo "out <${o0a#1#}|${o0b#1#}> <${o1a#1#}|${o1b#1#}>" typeset -Uui1 i0 i1 echo "pass <$px> <$p0> <$p1> <$pl> <${i0#1#}|${i1#1#}>" typeset -Uui16 tv1=1#~ tv2=1# tv3=1# tv4=1# tv5=1# tv6=1# tv7=1#  tv8=1#€ echo "specX <${tv1#16#}> <${tv2#16#}> <${tv3#16#}> <${tv4#16#}> <${tv5#16#}> <${tv6#16#}> <${tv7#16#}> <${tv8#16#}>" typeset -i1 tv1 tv2 tv3 tv4 tv5 tv6 tv7 tv8 echo "specW <${tv1#1#}> <${tv2#1#}> <${tv3#1#}> <${tv4#1#}> <${tv5#1#}> <${tv6#1#}> <${tv7#1#}> <${tv8#1#}>" typeset -i1 xs1=0xEF7F xs2=0xEF80 xs3=0xFDD0 echo "specU <${xs1#1#}> <${xs2#1#}> <${xs3#1#}>" expected-stdout: in <16#EFEF> <16#20AC> out <@|~> <☺|﷐> pass <16#cafe> <1# > <1#…> <1#f> <|€> specX <7E> <7F> <80> specW <~> <> <> <> <> <> < > <€> specU <> <> <﷐> --- name: integer-base-one-2a description: check if the use of fake integer base 1 stops at correct characters stdin: set -U integer x=1#foo echo /$x/ expected-stderr-pattern: /1#foo: unexpected 'oo'/ expected-exit: e != 0 --- name: integer-base-one-2b description: check if the use of fake integer base 1 stops at correct characters stdin: set -U integer x=1# echo /$x/ expected-stderr-pattern: /1#: unexpected ''/ expected-exit: e != 0 --- name: integer-base-one-2c1 description: check if the use of fake integer base 1 stops at correct characters stdin: set -U integer x=1#… echo /$x/ expected-stdout: /1#…/ --- name: integer-base-one-2c2 description: check if the use of fake integer base 1 stops at correct characters stdin: set +U integer x=1#… echo /$x/ expected-stderr-pattern: /1#…: unexpected ''/ expected-exit: e != 0 --- name: integer-base-one-2d1 description: check if the use of fake integer base 1 handles octets okay stdin: set -U typeset -i16 x=1# echo /$x/ # invalid utf-8 expected-stdout: /16#efff/ --- name: integer-base-one-2d2 description: check if the use of fake integer base 1 handles octets stdin: set -U typeset -i16 x=1# echo /$x/ # invalid 2-byte expected-stdout: /16#efc2/ --- name: integer-base-one-2d3 description: check if the use of fake integer base 1 handles octets stdin: set -U typeset -i16 x=1# echo /$x/ # invalid 2-byte expected-stdout: /16#efef/ --- name: integer-base-one-2d4 description: check if the use of fake integer base 1 stops at invalid input stdin: set -U typeset -i16 x=1# echo /$x/ # invalid 3-byte expected-stderr-pattern: /1#: unexpected ''/ expected-exit: e != 0 --- name: integer-base-one-2d5 description: check if the use of fake integer base 1 stops at invalid input stdin: set -U typeset -i16 x=1# echo /$x/ # non-minimalistic expected-stderr-pattern: /1#: unexpected ''/ expected-exit: e != 0 --- name: integer-base-one-2d6 description: check if the use of fake integer base 1 stops at invalid input stdin: set -U typeset -i16 x=1# echo /$x/ # non-minimalistic expected-stderr-pattern: /1#: unexpected ''/ expected-exit: e != 0 --- name: integer-base-one-3As description: some sample code for hexdumping not NUL safe; input lines must be NL terminated stdin: { print 'Hello, World!\\\nこんにちは!' typeset -Uui16 i=0x100 # change that to 0xFF once we can handle embedded # NUL characters in strings / here documents while (( i++ < 0x1FF )); do print -n "\x${i#16#1}" done print '\0z' } | { # integer-base-one-3As typeset -Uui16 -Z11 pos=0 typeset -Uui16 -Z5 hv=2147483647 typeset -i1 wc=0x0A dasc= nl=${wc#1#} while IFS= read -r line; do line=$line$nl while [[ -n $line ]]; do hv=1#${line::1} if (( (pos & 15) == 0 )); then (( pos )) && print -r -- "$dasc|" print -n "${pos#16#} " dasc=' |' fi print -n "${hv#16#} " if (( (hv < 32) || (hv > 126) )); then dasc=$dasc. else dasc=$dasc${line::1} fi (( (pos++ & 15) == 7 )) && print -n -- '- ' line=${line:1} done done while (( pos & 15 )); do print -n ' ' (( (pos++ & 15) == 7 )) && print -n -- '- ' done (( hv == 2147483647 )) || print -r -- "$dasc|" } expected-stdout: 00000000 48 65 6C 6C 6F 2C 20 57 - 6F 72 6C 64 21 5C 0A E3 |Hello, World!\..| 00000010 81 93 E3 82 93 E3 81 AB - E3 81 A1 E3 81 AF EF BC |................| 00000020 81 0A 01 02 03 04 05 06 - 07 08 09 0A 0B 0C 0D 0E |................| 00000030 0F 10 11 12 13 14 15 16 - 17 18 19 1A 1B 1C 1D 1E |................| 00000040 1F 20 21 22 23 24 25 26 - 27 28 29 2A 2B 2C 2D 2E |. !"#$%&'()*+,-.| 00000050 2F 30 31 32 33 34 35 36 - 37 38 39 3A 3B 3C 3D 3E |/0123456789:;<=>| 00000060 3F 40 41 42 43 44 45 46 - 47 48 49 4A 4B 4C 4D 4E |?@ABCDEFGHIJKLMN| 00000070 4F 50 51 52 53 54 55 56 - 57 58 59 5A 5B 5C 5D 5E |OPQRSTUVWXYZ[\]^| 00000080 5F 60 61 62 63 64 65 66 - 67 68 69 6A 6B 6C 6D 6E |_`abcdefghijklmn| 00000090 6F 70 71 72 73 74 75 76 - 77 78 79 7A 7B 7C 7D 7E |opqrstuvwxyz{|}~| 000000A0 7F 80 81 82 83 84 85 86 - 87 88 89 8A 8B 8C 8D 8E |................| 000000B0 8F 90 91 92 93 94 95 96 - 97 98 99 9A 9B 9C 9D 9E |................| 000000C0 9F A0 A1 A2 A3 A4 A5 A6 - A7 A8 A9 AA AB AC AD AE |................| 000000D0 AF B0 B1 B2 B3 B4 B5 B6 - B7 B8 B9 BA BB BC BD BE |................| 000000E0 BF C0 C1 C2 C3 C4 C5 C6 - C7 C8 C9 CA CB CC CD CE |................| 000000F0 CF D0 D1 D2 D3 D4 D5 D6 - D7 D8 D9 DA DB DC DD DE |................| 00000100 DF E0 E1 E2 E3 E4 E5 E6 - E7 E8 E9 EA EB EC ED EE |................| 00000110 EF F0 F1 F2 F3 F4 F5 F6 - F7 F8 F9 FA FB FC FD FE |................| 00000120 FF 7A 0A - |.z.| --- name: integer-base-one-3Ws description: some sample code for hexdumping Unicode not NUL safe; input lines must be NL terminated stdin: set -U { print 'Hello, World!\\\nこんにちは!' typeset -Uui16 i=0x100 # change that to 0xFF once we can handle embedded # NUL characters in strings / here documents while (( i++ < 0x1FF )); do print -n "\u${i#16#1}" done print print \\xff # invalid utf-8 print \\xc2 # invalid 2-byte print \\xef\\xbf\\xc0 # invalid 3-byte print \\xc0\\x80 # non-minimalistic print \\xe0\\x80\\x80 # non-minimalistic print '�￾￿' # end of range print '\0z' # embedded NUL } | { # integer-base-one-3Ws typeset -Uui16 -Z11 pos=0 typeset -Uui16 -Z7 hv typeset -i1 wc=0x0A typeset -i lpos dasc= nl=${wc#1#} while IFS= read -r line; do line=$line$nl lpos=0 while (( lpos < ${#line} )); do wc=1#${line:(lpos++):1} if (( (wc < 32) || \ ((wc > 126) && (wc < 160)) )); then dch=. elif (( (wc & 0xFF80) == 0xEF80 )); then dch=� else dch=${wc#1#} fi if (( (pos & 7) == 7 )); then dasc=$dasc$dch dch= elif (( (pos & 7) == 0 )); then (( pos )) && print -r -- "$dasc|" print -n "${pos#16#} " dasc=' |' fi let hv=wc print -n "${hv#16#} " (( (pos++ & 7) == 3 )) && \ print -n -- '- ' dasc=$dasc$dch done done while (( pos & 7 )); do print -n ' ' (( (pos++ & 7) == 3 )) && print -n -- '- ' done (( hv == 2147483647 )) || print -r -- "$dasc|" } expected-stdout: 00000000 0048 0065 006C 006C - 006F 002C 0020 0057 |Hello, W| 00000008 006F 0072 006C 0064 - 0021 005C 000A 3053 |orld!\.こ| 00000010 3093 306B 3061 306F - FF01 000A 0001 0002 |んにちは!...| 00000018 0003 0004 0005 0006 - 0007 0008 0009 000A |........| 00000020 000B 000C 000D 000E - 000F 0010 0011 0012 |........| 00000028 0013 0014 0015 0016 - 0017 0018 0019 001A |........| 00000030 001B 001C 001D 001E - 001F 0020 0021 0022 |..... !"| 00000038 0023 0024 0025 0026 - 0027 0028 0029 002A |#$%&'()*| 00000040 002B 002C 002D 002E - 002F 0030 0031 0032 |+,-./012| 00000048 0033 0034 0035 0036 - 0037 0038 0039 003A |3456789:| 00000050 003B 003C 003D 003E - 003F 0040 0041 0042 |;<=>?@AB| 00000058 0043 0044 0045 0046 - 0047 0048 0049 004A |CDEFGHIJ| 00000060 004B 004C 004D 004E - 004F 0050 0051 0052 |KLMNOPQR| 00000068 0053 0054 0055 0056 - 0057 0058 0059 005A |STUVWXYZ| 00000070 005B 005C 005D 005E - 005F 0060 0061 0062 |[\]^_`ab| 00000078 0063 0064 0065 0066 - 0067 0068 0069 006A |cdefghij| 00000080 006B 006C 006D 006E - 006F 0070 0071 0072 |klmnopqr| 00000088 0073 0074 0075 0076 - 0077 0078 0079 007A |stuvwxyz| 00000090 007B 007C 007D 007E - 007F 0080 0081 0082 |{|}~....| 00000098 0083 0084 0085 0086 - 0087 0088 0089 008A |........| 000000A0 008B 008C 008D 008E - 008F 0090 0091 0092 |........| 000000A8 0093 0094 0095 0096 - 0097 0098 0099 009A |........| 000000B0 009B 009C 009D 009E - 009F 00A0 00A1 00A2 |..... ¡¢| 000000B8 00A3 00A4 00A5 00A6 - 00A7 00A8 00A9 00AA |£¤¥¦§¨©ª| 000000C0 00AB 00AC 00AD 00AE - 00AF 00B0 00B1 00B2 |«¬­®¯°±²| 000000C8 00B3 00B4 00B5 00B6 - 00B7 00B8 00B9 00BA |³´µ¶·¸¹º| 000000D0 00BB 00BC 00BD 00BE - 00BF 00C0 00C1 00C2 |»¼½¾¿ÀÁÂ| 000000D8 00C3 00C4 00C5 00C6 - 00C7 00C8 00C9 00CA |ÃÄÅÆÇÈÉÊ| 000000E0 00CB 00CC 00CD 00CE - 00CF 00D0 00D1 00D2 |ËÌÍÎÏÐÑÒ| 000000E8 00D3 00D4 00D5 00D6 - 00D7 00D8 00D9 00DA |ÓÔÕÖ×ØÙÚ| 000000F0 00DB 00DC 00DD 00DE - 00DF 00E0 00E1 00E2 |ÛÜÝÞßàáâ| 000000F8 00E3 00E4 00E5 00E6 - 00E7 00E8 00E9 00EA |ãäåæçèéê| 00000100 00EB 00EC 00ED 00EE - 00EF 00F0 00F1 00F2 |ëìíîïðñò| 00000108 00F3 00F4 00F5 00F6 - 00F7 00F8 00F9 00FA |óôõö÷øùú| 00000110 00FB 00FC 00FD 00FE - 00FF 000A EFFF 000A |ûüýþÿ.�.| 00000118 EFC2 000A EFEF EFBF - EFC0 000A EFC0 EF80 |�.���.��| 00000120 000A EFE0 EF80 EF80 - 000A FFFD EFEF EFBF |.���.���| 00000128 EFBE EFEF EFBF EFBF - 000A 007A 000A |����.z.| --- name: integer-base-one-3Ar description: some sample code for hexdumping; NUL and binary safe stdin: { print 'Hello, World!\\\nこんにちは!' typeset -Uui16 i=0x100 # change that to 0xFF once we can handle embedded # NUL characters in strings / here documents while (( i++ < 0x1FF )); do print -n "\x${i#16#1}" done print '\0z' } | { # integer-base-one-3Ar typeset -Uui16 -Z11 pos=0 typeset -Uui16 -Z5 hv=2147483647 dasc= if read -arN -1 line; then typeset -i1 line i=0 while (( i < ${#line[*]} )); do hv=${line[i++]} if (( (pos & 15) == 0 )); then (( pos )) && print -r -- "$dasc|" print -n "${pos#16#} " dasc=' |' fi print -n "${hv#16#} " if (( (hv < 32) || (hv > 126) )); then dasc=$dasc. else dasc=$dasc${line[i-1]#1#} fi (( (pos++ & 15) == 7 )) && print -n -- '- ' done fi while (( pos & 15 )); do print -n ' ' (( (pos++ & 15) == 7 )) && print -n -- '- ' done (( hv == 2147483647 )) || print -r -- "$dasc|" } expected-stdout: 00000000 48 65 6C 6C 6F 2C 20 57 - 6F 72 6C 64 21 5C 0A E3 |Hello, World!\..| 00000010 81 93 E3 82 93 E3 81 AB - E3 81 A1 E3 81 AF EF BC |................| 00000020 81 0A 01 02 03 04 05 06 - 07 08 09 0A 0B 0C 0D 0E |................| 00000030 0F 10 11 12 13 14 15 16 - 17 18 19 1A 1B 1C 1D 1E |................| 00000040 1F 20 21 22 23 24 25 26 - 27 28 29 2A 2B 2C 2D 2E |. !"#$%&'()*+,-.| 00000050 2F 30 31 32 33 34 35 36 - 37 38 39 3A 3B 3C 3D 3E |/0123456789:;<=>| 00000060 3F 40 41 42 43 44 45 46 - 47 48 49 4A 4B 4C 4D 4E |?@ABCDEFGHIJKLMN| 00000070 4F 50 51 52 53 54 55 56 - 57 58 59 5A 5B 5C 5D 5E |OPQRSTUVWXYZ[\]^| 00000080 5F 60 61 62 63 64 65 66 - 67 68 69 6A 6B 6C 6D 6E |_`abcdefghijklmn| 00000090 6F 70 71 72 73 74 75 76 - 77 78 79 7A 7B 7C 7D 7E |opqrstuvwxyz{|}~| 000000A0 7F 80 81 82 83 84 85 86 - 87 88 89 8A 8B 8C 8D 8E |................| 000000B0 8F 90 91 92 93 94 95 96 - 97 98 99 9A 9B 9C 9D 9E |................| 000000C0 9F A0 A1 A2 A3 A4 A5 A6 - A7 A8 A9 AA AB AC AD AE |................| 000000D0 AF B0 B1 B2 B3 B4 B5 B6 - B7 B8 B9 BA BB BC BD BE |................| 000000E0 BF C0 C1 C2 C3 C4 C5 C6 - C7 C8 C9 CA CB CC CD CE |................| 000000F0 CF D0 D1 D2 D3 D4 D5 D6 - D7 D8 D9 DA DB DC DD DE |................| 00000100 DF E0 E1 E2 E3 E4 E5 E6 - E7 E8 E9 EA EB EC ED EE |................| 00000110 EF F0 F1 F2 F3 F4 F5 F6 - F7 F8 F9 FA FB FC FD FE |................| 00000120 FF 00 7A 0A - |..z.| --- name: integer-base-one-3Wr description: some sample code for hexdumping Unicode; NUL and binary safe stdin: set -U { print 'Hello, World!\\\nこんにちは!' typeset -Uui16 i=0x100 # change that to 0xFF once we can handle embedded # NUL characters in strings / here documents while (( i++ < 0x1FF )); do print -n "\u${i#16#1}" done print print \\xff # invalid utf-8 print \\xc2 # invalid 2-byte print \\xef\\xbf\\xc0 # invalid 3-byte print \\xc0\\x80 # non-minimalistic print \\xe0\\x80\\x80 # non-minimalistic print '�￾￿' # end of range print '\0z' # embedded NUL } | { # integer-base-one-3Wr typeset -Uui16 -Z11 pos=0 typeset -Uui16 -Z7 hv=2147483647 dasc= if read -arN -1 line; then typeset -i1 line i=0 while (( i < ${#line[*]} )); do hv=${line[i++]} if (( (hv < 32) || \ ((hv > 126) && (hv < 160)) )); then dch=. elif (( (hv & 0xFF80) == 0xEF80 )); then dch=� else dch=${line[i-1]#1#} fi if (( (pos & 7) == 7 )); then dasc=$dasc$dch dch= elif (( (pos & 7) == 0 )); then (( pos )) && print -r -- "$dasc|" print -n "${pos#16#} " dasc=' |' fi print -n "${hv#16#} " (( (pos++ & 7) == 3 )) && \ print -n -- '- ' dasc=$dasc$dch done fi while (( pos & 7 )); do print -n ' ' (( (pos++ & 7) == 3 )) && print -n -- '- ' done (( hv == 2147483647 )) || print -r -- "$dasc|" } expected-stdout: 00000000 0048 0065 006C 006C - 006F 002C 0020 0057 |Hello, W| 00000008 006F 0072 006C 0064 - 0021 005C 000A 3053 |orld!\.こ| 00000010 3093 306B 3061 306F - FF01 000A 0001 0002 |んにちは!...| 00000018 0003 0004 0005 0006 - 0007 0008 0009 000A |........| 00000020 000B 000C 000D 000E - 000F 0010 0011 0012 |........| 00000028 0013 0014 0015 0016 - 0017 0018 0019 001A |........| 00000030 001B 001C 001D 001E - 001F 0020 0021 0022 |..... !"| 00000038 0023 0024 0025 0026 - 0027 0028 0029 002A |#$%&'()*| 00000040 002B 002C 002D 002E - 002F 0030 0031 0032 |+,-./012| 00000048 0033 0034 0035 0036 - 0037 0038 0039 003A |3456789:| 00000050 003B 003C 003D 003E - 003F 0040 0041 0042 |;<=>?@AB| 00000058 0043 0044 0045 0046 - 0047 0048 0049 004A |CDEFGHIJ| 00000060 004B 004C 004D 004E - 004F 0050 0051 0052 |KLMNOPQR| 00000068 0053 0054 0055 0056 - 0057 0058 0059 005A |STUVWXYZ| 00000070 005B 005C 005D 005E - 005F 0060 0061 0062 |[\]^_`ab| 00000078 0063 0064 0065 0066 - 0067 0068 0069 006A |cdefghij| 00000080 006B 006C 006D 006E - 006F 0070 0071 0072 |klmnopqr| 00000088 0073 0074 0075 0076 - 0077 0078 0079 007A |stuvwxyz| 00000090 007B 007C 007D 007E - 007F 0080 0081 0082 |{|}~....| 00000098 0083 0084 0085 0086 - 0087 0088 0089 008A |........| 000000A0 008B 008C 008D 008E - 008F 0090 0091 0092 |........| 000000A8 0093 0094 0095 0096 - 0097 0098 0099 009A |........| 000000B0 009B 009C 009D 009E - 009F 00A0 00A1 00A2 |..... ¡¢| 000000B8 00A3 00A4 00A5 00A6 - 00A7 00A8 00A9 00AA |£¤¥¦§¨©ª| 000000C0 00AB 00AC 00AD 00AE - 00AF 00B0 00B1 00B2 |«¬­®¯°±²| 000000C8 00B3 00B4 00B5 00B6 - 00B7 00B8 00B9 00BA |³´µ¶·¸¹º| 000000D0 00BB 00BC 00BD 00BE - 00BF 00C0 00C1 00C2 |»¼½¾¿ÀÁÂ| 000000D8 00C3 00C4 00C5 00C6 - 00C7 00C8 00C9 00CA |ÃÄÅÆÇÈÉÊ| 000000E0 00CB 00CC 00CD 00CE - 00CF 00D0 00D1 00D2 |ËÌÍÎÏÐÑÒ| 000000E8 00D3 00D4 00D5 00D6 - 00D7 00D8 00D9 00DA |ÓÔÕÖ×ØÙÚ| 000000F0 00DB 00DC 00DD 00DE - 00DF 00E0 00E1 00E2 |ÛÜÝÞßàáâ| 000000F8 00E3 00E4 00E5 00E6 - 00E7 00E8 00E9 00EA |ãäåæçèéê| 00000100 00EB 00EC 00ED 00EE - 00EF 00F0 00F1 00F2 |ëìíîïðñò| 00000108 00F3 00F4 00F5 00F6 - 00F7 00F8 00F9 00FA |óôõö÷øùú| 00000110 00FB 00FC 00FD 00FE - 00FF 000A EFFF 000A |ûüýþÿ.�.| 00000118 EFC2 000A EFEF EFBF - EFC0 000A EFC0 EF80 |�.���.��| 00000120 000A EFE0 EF80 EF80 - 000A FFFD EFEF EFBF |.���.���| 00000128 EFBE EFEF EFBF EFBF - 000A 0000 007A 000A |����..z.| --- name: integer-base-one-4 description: Check if ksh93-style base-one integers work category: !smksh stdin: set -U echo 1 $(('a')) (echo 2f $(('aa'))) 2>&1 | sed "s/^[^']*'/2p '/" echo 3 $(('…')) x="'a'" echo "4 <$x>" echo 5 $(($x)) echo 6 $((x)) expected-stdout: 1 97 2p 'aa': multi-character character constant 3 8230 4 <'a'> 5 97 6 97 --- name: integer-base-one-5A description: Check to see that we’re NUL and Unicode safe stdin: set +U print 'a\0b\xfdz' >x read -a y x read -a y a 2>b echo =1= cat a echo =2= cat b echo =3= d 2>&1 >c echo =4= cat c echo =5= expected-stdout: =1= o0. =2= e0. =3= e1. =4= o1. =5= --- name: bashiop-1 description: Check if GNU bash-like I/O redirection works Part 1: this is also supported by GNU bash stdin: exec 3>&1 function threeout { echo ras echo dwa >&2 echo tri >&3 } threeout &>foo echo === cat foo expected-stdout: tri === ras dwa --- name: bashiop-2a description: Check if GNU bash-like I/O redirection works Part 2: this is *not* supported by GNU bash stdin: exec 3>&1 function threeout { echo ras echo dwa >&2 echo tri >&3 } threeout 3&>foo echo === cat foo expected-stdout: ras === dwa tri --- name: bashiop-2b description: Check if GNU bash-like I/O redirection works Part 2: this is *not* supported by GNU bash stdin: exec 3>&1 function threeout { echo ras echo dwa >&2 echo tri >&3 } threeout 3>foo &>&3 echo === cat foo expected-stdout: === ras dwa tri --- name: bashiop-2c description: Check if GNU bash-like I/O redirection works Part 2: this is supported by GNU bash 4 only stdin: echo mir >foo set -o noclobber exec 3>&1 function threeout { echo ras echo dwa >&2 echo tri >&3 } threeout &>>foo echo === cat foo expected-stdout: tri === mir ras dwa --- name: bashiop-3a description: Check if GNU bash-like I/O redirection fails correctly Part 1: this is also supported by GNU bash stdin: echo mir >foo set -o noclobber exec 3>&1 function threeout { echo ras echo dwa >&2 echo tri >&3 } threeout &>foo echo === cat foo expected-stdout: === mir expected-stderr-pattern: /.*: can't (create|overwrite) .*/ --- name: bashiop-3b description: Check if GNU bash-like I/O redirection fails correctly Part 2: this is *not* supported by GNU bash stdin: echo mir >foo set -o noclobber exec 3>&1 function threeout { echo ras echo dwa >&2 echo tri >&3 } threeout &>|foo echo === cat foo expected-stdout: tri === ras dwa --- name: bashiop-4 description: Check if GNU bash-like I/O redirection works Part 4: this is also supported by GNU bash, but failed in some mksh versions stdin: exec 3>&1 function threeout { echo ras echo dwa >&2 echo tri >&3 } function blubb { [[ -e bar ]] && threeout "$bf" &>foo } blubb echo -n >bar blubb echo === cat foo expected-stdout: tri === ras dwa --- name: bashiop-5 description: Check if GNU bash-like I/O redirection is only supported in !POSIX !sh mode as it breaks existing scripts' syntax stdin: :>x; echo 1 "$("$__progname" -c 'echo foo>/dev/null&>x echo bar')" = "$(x; echo 2 "$("$__progname" -o posix -c 'echo foo>/dev/null&>x echo bar')" = "$(x; echo 3 "$("$__progname" -o sh -c 'echo foo>/dev/null&>x echo bar')" = "$(env; chmod +x env; PATH=.$PATHSEP$PATH function k { if [ x$FOO != xbar ]; then echo 1 return 1 fi x=$(env | grep FOO) if [ "x$x" != "xFOO=bar" ]; then echo 2 return 1; fi FOO=foo return 0 } b () { if [ x$FOO != xbar ]; then echo 3 return 1 fi x=$(env | grep FOO) if [ "x$x" != "xFOO=bar" ]; then echo 4 return 1; fi FOO=foo return 0 } FOO=bar k if [ $? != 0 ]; then exit 1 fi if [ x$FOO != x ]; then exit 1 fi FOO=bar b if [ $? != 0 ]; then exit 1 fi if [ x$FOO != xfoo ]; then exit 1 fi FOO=barbar FOO=bar k if [ $? != 0 ]; then exit 1 fi if [ x$FOO != xbarbar ]; then exit 1 fi FOO=bar b if [ $? != 0 ]; then exit 1 fi if [ x$FOO != xfoo ]; then exit 1 fi --- name: fd-cloexec-1 description: Verify that file descriptors > 2 are private for Korn shells AT&T ksh93 does this still, which means we must keep it as well XXX fails on some old Perl installations need-pass: no stdin: cat >cld <<-EOF #!$__perlname open(my \$fh, ">&", 9) or die "E: open \$!"; syswrite(\$fh, "Fowl\\n", 5) or die "E: write \$!"; EOF chmod +x cld exec 9>&1 ./cld expected-exit: e != 0 expected-stderr-pattern: /E: open / --- name: fd-cloexec-2 description: Verify that file descriptors > 2 are not private for POSIX shells See Debian Bug #154540, Closes: #499139 XXX fails on some old Perl installations need-pass: no stdin: cat >cld <<-EOF #!$__perlname open(my \$fh, ">&", 9) or die "E: open \$!"; syswrite(\$fh, "Fowl\\n", 5) or die "E: write \$!"; EOF chmod +x cld test -n "$POSH_VERSION" || set -o posix exec 9>&1 ./cld expected-stdout: Fowl --- name: comsub-1a description: COMSUB are now parsed recursively, so this works see also regression-6: matching parenthesēs bug Fails on: pdksh bash2 bash3 zsh Passes on: bash4 ksh93 mksh(20110313+) stdin: echo 1 $(case 1 in (1) echo yes;; (2) echo no;; esac) . echo 2 $(case 1 in 1) echo yes;; 2) echo no;; esac) . TEST=1234; echo 3 ${TEST: $(case 1 in (1) echo 1;; (*) echo 2;; esac)} . TEST=5678; echo 4 ${TEST: $(case 1 in 1) echo 1;; *) echo 2;; esac)} . a=($(case 1 in (1) echo 1;; (*) echo 2;; esac)); echo 5 ${a[0]} . a=($(case 1 in 1) echo 1;; *) echo 2;; esac)); echo 6 ${a[0]} . expected-stdout: 1 yes . 2 yes . 3 234 . 4 678 . 5 1 . 6 1 . --- name: comsub-1b description: COMSUB are now parsed recursively, so this works Fails on: pdksh bash2 bash3 bash4 zsh Passes on: ksh93 mksh(20110313+) stdin: echo 1 $(($(case 1 in (1) echo 1;; (*) echo 2;; esac)+10)) . echo 2 $(($(case 1 in 1) echo 1;; *) echo 2;; esac)+20)) . (( a = $(case 1 in (1) echo 1;; (*) echo 2;; esac) )); echo 3 $a . (( a = $(case 1 in 1) echo 1;; *) echo 2;; esac) )); echo 4 $a . a=($(($(case 1 in (1) echo 1;; (*) echo 2;; esac)+10))); echo 5 ${a[0]} . a=($(($(case 1 in 1) echo 1;; *) echo 2;; esac)+20))); echo 6 ${a[0]} . expected-stdout: 1 11 . 2 21 . 3 1 . 4 1 . 5 11 . 6 21 . --- name: comsub-2 description: RedHat BZ#496791 – another case of missing recursion in parsing COMSUB expressions Fails on: pdksh bash2 bash3¹ bash4¹ zsh Passes on: ksh93 mksh(20110305+) ① bash[34] seem to choke on comment ending with backslash-newline stdin: # a comment with " ' \ x=$( echo yes # a comment with " ' \ ) echo $x expected-stdout: yes --- name: comsub-3 description: Extended test for COMSUB explaining why a recursive parser is a must (a non-recursive parser cannot pass all three of these test cases, especially the ‘#’ is difficult) stdin: print '#!'"$__progname"'\necho 1234' >id; chmod +x id; PATH=.$PATHSEP$PATH echo $(typeset -i10 x=16#20; echo $x) echo $(typeset -Uui16 x=16#$(id -u) ) . echo $(c=1; d=1 typeset -Uui16 a=36#foo; c=2 typeset -Uui16 b=36 #foo; d=2 echo $a $b $c $d) expected-stdout: 32 . 16#4F68 16#24 2 1 --- name: comsub-4 description: Check the tree dump functions for !MKSH_SMALL functionality category: !smksh stdin: x() { case $1 in u) echo x ;;& *) echo $1 ;; esac; } typeset -f x expected-stdout: x() { case $1 in (u) echo x ;| (*) echo $1 ;; esac } --- name: comsub-5 description: Check COMSUB works with aliases (does not expand them twice) stdin: print '#!'"$__progname"'\nfor x in "$@"; do print -r -- "$x"; done' >pfn chmod +x pfn alias echo='echo a' foo() { ./pfn "$(echo foo)" } ./pfn "$(echo b)" typeset -f foo expected-stdout: a b foo() { ./pfn "$(echo foo )" } --- name: comsub-torture description: Check the tree dump functions work correctly stdin: if [[ -z $__progname ]]; then echo >&2 call me with __progname; exit 1; fi while IFS= read -r line; do if [[ $line = '#1' ]]; then lastf=0 continue elif [[ $line = EOFN* ]]; then fbody=$fbody$'\n'$line continue elif [[ $line != '#'* ]]; then fbody=$fbody$'\n\t'$line continue fi if (( lastf )); then x="inline_${nextf}() {"$fbody$'\n}\n' print -nr -- "$x" print -r -- "${x}typeset -f inline_$nextf" | "$__progname" x="function comsub_$nextf { x=\$("$fbody$'\n); }\n' print -nr -- "$x" print -r -- "${x}typeset -f comsub_$nextf" | "$__progname" x="function reread_$nextf { x=\$(("$fbody$'\n)|tr u x); }\n' print -nr -- "$x" print -r -- "${x}typeset -f reread_$nextf" | "$__progname" fi lastf=1 fbody= nextf=${line#?} done <<'EOD' #1 #TCOM vara=1 varb='2 3' cmd arg1 $arg2 "$arg3 4" #TPAREN_TPIPE_TLIST (echo $foo | tr -dc 0-9; echo) #TAND_TOR cmd && echo ja || echo nein #TSELECT select file in *; do echo "<$file>" ; break ; done #TFOR_TTIME time for i in {1,2,3} ; do echo $i ; done #TCASE case $foo in 1) echo eins;& 2) echo zwei ;| *) echo kann net bis drei zählen;; esac #TIF_TBANG_TDBRACKET_TELIF if ! [[ 1 = 1 ]] ; then echo eins; elif [[ 1 = 2 ]]; then echo zwei ;else echo drei; fi #TWHILE i=1; while (( i < 10 )); do echo $i; let ++i; done #TUNTIL i=10; until (( !--i )) ; do echo $i; done #TCOPROC cat * |& ls #TFUNCT_TBRACE_TASYNC function korn { echo eins; echo zwei ; } bourne () { logger * & } #IOREAD_IOCAT tr x u 0>bar #IOWRITE_IOCLOB_IOHERE_noIOSKIP cat >|bar <<'EOFN' foo EOFN #IOWRITE_noIOCLOB_IOHERE_IOSKIP cat 1>bar <<-EOFI foo EOFI #IORDWR_IODUP sh 1<>/dev/console 0<&1 2>&1 #COMSUB_EXPRSUB_FUNSUB_VALSUB echo $(true) $((1+ 2)) ${ :;} ${| REPLY=x;} #QCHAR_OQUOTE_CQUOTE echo fo\ob\"a\`r\'b\$az echo "fo\ob\"a\`r\'b\$az" echo 'fo\ob\"a\`r'\''b\$az' #OSUBST_CSUBST_OPAT_SPAT_CPAT [[ ${foo#bl\(u\)b} = @(bar|baz) ]] #heredoc_closed x=$(cat <&1 <<-EOF 1,/^\$/d 0a $x . wq EOF)" = @(?) ]] && rm -f /etc/motd if [[ ! -s /etc/motd ]]; then install -c -o root -g wheel -m 664 /dev/null /etc/motd print -- "$x\n" >/etc/motd fi #wdarrassign case x in x) a+=b; c+=(d e) esac #0 EOD expected-stdout: inline_TCOM() { vara=1 varb='2 3' cmd arg1 $arg2 "$arg3 4" } inline_TCOM() { vara=1 varb="2 3" cmd arg1 $arg2 "$arg3 4" } function comsub_TCOM { x=$( vara=1 varb='2 3' cmd arg1 $arg2 "$arg3 4" ); } function comsub_TCOM { x=$(vara=1 varb="2 3" cmd arg1 $arg2 "$arg3 4" ) } function reread_TCOM { x=$(( vara=1 varb='2 3' cmd arg1 $arg2 "$arg3 4" )|tr u x); } function reread_TCOM { x=$(( vara=1 varb="2 3" cmd arg1 $arg2 "$arg3 4" ) | tr u x ) } inline_TPAREN_TPIPE_TLIST() { (echo $foo | tr -dc 0-9; echo) } inline_TPAREN_TPIPE_TLIST() { ( echo $foo | tr -dc 0-9 echo ) } function comsub_TPAREN_TPIPE_TLIST { x=$( (echo $foo | tr -dc 0-9; echo) ); } function comsub_TPAREN_TPIPE_TLIST { x=$(( echo $foo | tr -dc 0-9 ; echo ) ) } function reread_TPAREN_TPIPE_TLIST { x=$(( (echo $foo | tr -dc 0-9; echo) )|tr u x); } function reread_TPAREN_TPIPE_TLIST { x=$(( ( echo $foo | tr -dc 0-9 ; echo ) ) | tr u x ) } inline_TAND_TOR() { cmd && echo ja || echo nein } inline_TAND_TOR() { cmd && echo ja || echo nein } function comsub_TAND_TOR { x=$( cmd && echo ja || echo nein ); } function comsub_TAND_TOR { x=$(cmd && echo ja || echo nein ) } function reread_TAND_TOR { x=$(( cmd && echo ja || echo nein )|tr u x); } function reread_TAND_TOR { x=$(( cmd && echo ja || echo nein ) | tr u x ) } inline_TSELECT() { select file in *; do echo "<$file>" ; break ; done } inline_TSELECT() { select file in * do echo "<$file>" break done } function comsub_TSELECT { x=$( select file in *; do echo "<$file>" ; break ; done ); } function comsub_TSELECT { x=$(select file in * ; do echo "<$file>" ; break ; done ) } function reread_TSELECT { x=$(( select file in *; do echo "<$file>" ; break ; done )|tr u x); } function reread_TSELECT { x=$(( select file in * ; do echo "<$file>" ; break ; done ) | tr u x ) } inline_TFOR_TTIME() { time for i in {1,2,3} ; do echo $i ; done } inline_TFOR_TTIME() { time for i in {1,2,3} do echo $i done } function comsub_TFOR_TTIME { x=$( time for i in {1,2,3} ; do echo $i ; done ); } function comsub_TFOR_TTIME { x=$(time for i in {1,2,3} ; do echo $i ; done ) } function reread_TFOR_TTIME { x=$(( time for i in {1,2,3} ; do echo $i ; done )|tr u x); } function reread_TFOR_TTIME { x=$(( time for i in {1,2,3} ; do echo $i ; done ) | tr u x ) } inline_TCASE() { case $foo in 1) echo eins;& 2) echo zwei ;| *) echo kann net bis drei zählen;; esac } inline_TCASE() { case $foo in (1) echo eins ;& (2) echo zwei ;| (*) echo kann net bis drei zählen ;; esac } function comsub_TCASE { x=$( case $foo in 1) echo eins;& 2) echo zwei ;| *) echo kann net bis drei zählen;; esac ); } function comsub_TCASE { x=$(case $foo in (1) echo eins ;& (2) echo zwei ;| (*) echo kann net bis drei zählen ;; esac ) } function reread_TCASE { x=$(( case $foo in 1) echo eins;& 2) echo zwei ;| *) echo kann net bis drei zählen;; esac )|tr u x); } function reread_TCASE { x=$(( case $foo in (1) echo eins ;& (2) echo zwei ;| (*) echo kann net bis drei zählen ;; esac ) | tr u x ) } inline_TIF_TBANG_TDBRACKET_TELIF() { if ! [[ 1 = 1 ]] ; then echo eins; elif [[ 1 = 2 ]]; then echo zwei ;else echo drei; fi } inline_TIF_TBANG_TDBRACKET_TELIF() { if ! [[ 1 = 1 ]] then echo eins elif [[ 1 = 2 ]] then echo zwei else echo drei fi } function comsub_TIF_TBANG_TDBRACKET_TELIF { x=$( if ! [[ 1 = 1 ]] ; then echo eins; elif [[ 1 = 2 ]]; then echo zwei ;else echo drei; fi ); } function comsub_TIF_TBANG_TDBRACKET_TELIF { x=$(if ! [[ 1 = 1 ]] ; then echo eins ; elif [[ 1 = 2 ]] ; then echo zwei ; else echo drei ; fi ) } function reread_TIF_TBANG_TDBRACKET_TELIF { x=$(( if ! [[ 1 = 1 ]] ; then echo eins; elif [[ 1 = 2 ]]; then echo zwei ;else echo drei; fi )|tr u x); } function reread_TIF_TBANG_TDBRACKET_TELIF { x=$(( if ! [[ 1 = 1 ]] ; then echo eins ; elif [[ 1 = 2 ]] ; then echo zwei ; else echo drei ; fi ) | tr u x ) } inline_TWHILE() { i=1; while (( i < 10 )); do echo $i; let ++i; done } inline_TWHILE() { i=1 while { \let] " i < 10 " } do echo $i let ++i done } function comsub_TWHILE { x=$( i=1; while (( i < 10 )); do echo $i; let ++i; done ); } function comsub_TWHILE { x=$(i=1 ; while { \let] " i < 10 " ; } ; do echo $i ; let ++i ; done ) } function reread_TWHILE { x=$(( i=1; while (( i < 10 )); do echo $i; let ++i; done )|tr u x); } function reread_TWHILE { x=$(( i=1 ; while { \let] " i < 10 " ; } ; do echo $i ; let ++i ; done ) | tr u x ) } inline_TUNTIL() { i=10; until (( !--i )) ; do echo $i; done } inline_TUNTIL() { i=10 until { \let] " !--i " } do echo $i done } function comsub_TUNTIL { x=$( i=10; until (( !--i )) ; do echo $i; done ); } function comsub_TUNTIL { x=$(i=10 ; until { \let] " !--i " ; } ; do echo $i ; done ) } function reread_TUNTIL { x=$(( i=10; until (( !--i )) ; do echo $i; done )|tr u x); } function reread_TUNTIL { x=$(( i=10 ; until { \let] " !--i " ; } ; do echo $i ; done ) | tr u x ) } inline_TCOPROC() { cat * |& ls } inline_TCOPROC() { cat * |& ls } function comsub_TCOPROC { x=$( cat * |& ls ); } function comsub_TCOPROC { x=$(cat * |& ls ) } function reread_TCOPROC { x=$(( cat * |& ls )|tr u x); } function reread_TCOPROC { x=$(( cat * |& ls ) | tr u x ) } inline_TFUNCT_TBRACE_TASYNC() { function korn { echo eins; echo zwei ; } bourne () { logger * & } } inline_TFUNCT_TBRACE_TASYNC() { function korn { echo eins echo zwei } bourne() { logger * & } } function comsub_TFUNCT_TBRACE_TASYNC { x=$( function korn { echo eins; echo zwei ; } bourne () { logger * & } ); } function comsub_TFUNCT_TBRACE_TASYNC { x=$(function korn { echo eins ; echo zwei ; } ; bourne() { logger * & } ) } function reread_TFUNCT_TBRACE_TASYNC { x=$(( function korn { echo eins; echo zwei ; } bourne () { logger * & } )|tr u x); } function reread_TFUNCT_TBRACE_TASYNC { x=$(( function korn { echo eins ; echo zwei ; } ; bourne() { logger * & } ) | tr u x ) } inline_IOREAD_IOCAT() { tr x u 0>bar } inline_IOREAD_IOCAT() { tr x u >bar } function comsub_IOREAD_IOCAT { x=$( tr x u 0>bar ); } function comsub_IOREAD_IOCAT { x=$(tr x u >bar ) } function reread_IOREAD_IOCAT { x=$(( tr x u 0>bar )|tr u x); } function reread_IOREAD_IOCAT { x=$(( tr x u >bar ) | tr u x ) } inline_IOWRITE_IOCLOB_IOHERE_noIOSKIP() { cat >|bar <<'EOFN' foo EOFN } inline_IOWRITE_IOCLOB_IOHERE_noIOSKIP() { cat >|bar <<"EOFN" foo EOFN } function comsub_IOWRITE_IOCLOB_IOHERE_noIOSKIP { x=$( cat >|bar <<'EOFN' foo EOFN ); } function comsub_IOWRITE_IOCLOB_IOHERE_noIOSKIP { x=$(cat >|bar <<"EOFN" foo EOFN ) } function reread_IOWRITE_IOCLOB_IOHERE_noIOSKIP { x=$(( cat >|bar <<'EOFN' foo EOFN )|tr u x); } function reread_IOWRITE_IOCLOB_IOHERE_noIOSKIP { x=$(( cat >|bar <<"EOFN" foo EOFN ) | tr u x ) } inline_IOWRITE_noIOCLOB_IOHERE_IOSKIP() { cat 1>bar <<-EOFI foo EOFI } inline_IOWRITE_noIOCLOB_IOHERE_IOSKIP() { cat >bar <<-EOFI foo EOFI } function comsub_IOWRITE_noIOCLOB_IOHERE_IOSKIP { x=$( cat 1>bar <<-EOFI foo EOFI ); } function comsub_IOWRITE_noIOCLOB_IOHERE_IOSKIP { x=$(cat >bar <<-EOFI foo EOFI ) } function reread_IOWRITE_noIOCLOB_IOHERE_IOSKIP { x=$(( cat 1>bar <<-EOFI foo EOFI )|tr u x); } function reread_IOWRITE_noIOCLOB_IOHERE_IOSKIP { x=$(( cat >bar <<-EOFI foo EOFI ) | tr u x ) } inline_IORDWR_IODUP() { sh 1<>/dev/console 0<&1 2>&1 } inline_IORDWR_IODUP() { sh 1<>/dev/console <&1 2>&1 } function comsub_IORDWR_IODUP { x=$( sh 1<>/dev/console 0<&1 2>&1 ); } function comsub_IORDWR_IODUP { x=$(sh 1<>/dev/console <&1 2>&1 ) } function reread_IORDWR_IODUP { x=$(( sh 1<>/dev/console 0<&1 2>&1 )|tr u x); } function reread_IORDWR_IODUP { x=$(( sh 1<>/dev/console <&1 2>&1 ) | tr u x ) } inline_COMSUB_EXPRSUB_FUNSUB_VALSUB() { echo $(true) $((1+ 2)) ${ :;} ${| REPLY=x;} } inline_COMSUB_EXPRSUB_FUNSUB_VALSUB() { echo $(true ) $((1+ 2)) ${ : ;} ${|REPLY=x ;} } function comsub_COMSUB_EXPRSUB_FUNSUB_VALSUB { x=$( echo $(true) $((1+ 2)) ${ :;} ${| REPLY=x;} ); } function comsub_COMSUB_EXPRSUB_FUNSUB_VALSUB { x=$(echo $(true ) $((1+ 2)) ${ : ;} ${|REPLY=x ;} ) } function reread_COMSUB_EXPRSUB_FUNSUB_VALSUB { x=$(( echo $(true) $((1+ 2)) ${ :;} ${| REPLY=x;} )|tr u x); } function reread_COMSUB_EXPRSUB_FUNSUB_VALSUB { x=$(( echo $(true ) $((1+ 2)) ${ : ;} ${|REPLY=x ;} ) | tr u x ) } inline_QCHAR_OQUOTE_CQUOTE() { echo fo\ob\"a\`r\'b\$az echo "fo\ob\"a\`r\'b\$az" echo 'fo\ob\"a\`r'\''b\$az' } inline_QCHAR_OQUOTE_CQUOTE() { echo fo\ob\"a\`r\'b\$az echo "fo\ob\"a\`r\'b\$az" echo "fo\\ob\\\"a\\\`r"\'"b\\\$az" } function comsub_QCHAR_OQUOTE_CQUOTE { x=$( echo fo\ob\"a\`r\'b\$az echo "fo\ob\"a\`r\'b\$az" echo 'fo\ob\"a\`r'\''b\$az' ); } function comsub_QCHAR_OQUOTE_CQUOTE { x=$(echo fo\ob\"a\`r\'b\$az ; echo "fo\ob\"a\`r\'b\$az" ; echo "fo\\ob\\\"a\\\`r"\'"b\\\$az" ) } function reread_QCHAR_OQUOTE_CQUOTE { x=$(( echo fo\ob\"a\`r\'b\$az echo "fo\ob\"a\`r\'b\$az" echo 'fo\ob\"a\`r'\''b\$az' )|tr u x); } function reread_QCHAR_OQUOTE_CQUOTE { x=$(( echo fo\ob\"a\`r\'b\$az ; echo "fo\ob\"a\`r\'b\$az" ; echo "fo\\ob\\\"a\\\`r"\'"b\\\$az" ) | tr u x ) } inline_OSUBST_CSUBST_OPAT_SPAT_CPAT() { [[ ${foo#bl\(u\)b} = @(bar|baz) ]] } inline_OSUBST_CSUBST_OPAT_SPAT_CPAT() { [[ ${foo#bl\(u\)b} = @(bar|baz) ]] } function comsub_OSUBST_CSUBST_OPAT_SPAT_CPAT { x=$( [[ ${foo#bl\(u\)b} = @(bar|baz) ]] ); } function comsub_OSUBST_CSUBST_OPAT_SPAT_CPAT { x=$([[ ${foo#bl\(u\)b} = @(bar|baz) ]] ) } function reread_OSUBST_CSUBST_OPAT_SPAT_CPAT { x=$(( [[ ${foo#bl\(u\)b} = @(bar|baz) ]] )|tr u x); } function reread_OSUBST_CSUBST_OPAT_SPAT_CPAT { x=$(( [[ ${foo#bl\(u\)b} = @(bar|baz) ]] ) | tr u x ) } inline_heredoc_closed() { x=$(cat <&1 <<-EOF 1,/^\$/d 0a $x . wq EOF)" = @(?) ]] && rm -f /etc/motd if [[ ! -s /etc/motd ]]; then install -c -o root -g wheel -m 664 /dev/null /etc/motd print -- "$x\n" >/etc/motd fi } inline_patch_motd() { x=$(sysctl -n kern.version | sed 1q ) [[ -s /etc/motd && "$([[ "$(head -1 /etc/motd )" != $x ]] && ed -s /etc/motd 2>&1 <<-EOF 1,/^\$/d 0a $x . wq EOF )" = @(?) ]] && rm -f /etc/motd if [[ ! -s /etc/motd ]] then install -c -o root -g wheel -m 664 /dev/null /etc/motd print -- "$x\n" >/etc/motd fi } function comsub_patch_motd { x=$( x=$(sysctl -n kern.version | sed 1q) [[ -s /etc/motd && "$([[ "$(head -1 /etc/motd)" != $x ]] && \ ed -s /etc/motd 2>&1 <<-EOF 1,/^\$/d 0a $x . wq EOF)" = @(?) ]] && rm -f /etc/motd if [[ ! -s /etc/motd ]]; then install -c -o root -g wheel -m 664 /dev/null /etc/motd print -- "$x\n" >/etc/motd fi ); } function comsub_patch_motd { x=$(x=$(sysctl -n kern.version | sed 1q ) ; [[ -s /etc/motd && "$([[ "$(head -1 /etc/motd )" != $x ]] && ed -s /etc/motd 2>&1 <<-EOF 1,/^\$/d 0a $x . wq EOF )" = @(?) ]] && rm -f /etc/motd ; if [[ ! -s /etc/motd ]] ; then install -c -o root -g wheel -m 664 /dev/null /etc/motd ; print -- "$x\n" >/etc/motd ; fi ) } function reread_patch_motd { x=$(( x=$(sysctl -n kern.version | sed 1q) [[ -s /etc/motd && "$([[ "$(head -1 /etc/motd)" != $x ]] && \ ed -s /etc/motd 2>&1 <<-EOF 1,/^\$/d 0a $x . wq EOF)" = @(?) ]] && rm -f /etc/motd if [[ ! -s /etc/motd ]]; then install -c -o root -g wheel -m 664 /dev/null /etc/motd print -- "$x\n" >/etc/motd fi )|tr u x); } function reread_patch_motd { x=$(( x=$(sysctl -n kern.version | sed 1q ) ; [[ -s /etc/motd && "$([[ "$(head -1 /etc/motd )" != $x ]] && ed -s /etc/motd 2>&1 <<-EOF 1,/^\$/d 0a $x . wq EOF )" = @(?) ]] && rm -f /etc/motd ; if [[ ! -s /etc/motd ]] ; then install -c -o root -g wheel -m 664 /dev/null /etc/motd ; print -- "$x\n" >/etc/motd ; fi ) | tr u x ) } inline_wdarrassign() { case x in x) a+=b; c+=(d e) esac } inline_wdarrassign() { case x in (x) a+=b \set -A c+ -- d e ;; esac } function comsub_wdarrassign { x=$( case x in x) a+=b; c+=(d e) esac ); } function comsub_wdarrassign { x=$(case x in (x) a+=b ; \set -A c+ -- d e ;; esac ) } function reread_wdarrassign { x=$(( case x in x) a+=b; c+=(d e) esac )|tr u x); } function reread_wdarrassign { x=$(( case x in (x) a+=b ; \set -A c+ -- d e ;; esac ) | tr u x ) } --- name: comsub-torture-io description: Check the tree dump functions work correctly with I/O redirection stdin: if [[ -z $__progname ]]; then echo >&2 call me with __progname; exit 1; fi while IFS= read -r line; do if [[ $line = '#1' ]]; then lastf=0 continue elif [[ $line = EOFN* ]]; then fbody=$fbody$'\n'$line continue elif [[ $line != '#'* ]]; then fbody=$fbody$'\n\t'$line continue fi if (( lastf )); then x="inline_${nextf}() {"$fbody$'\n}\n' print -nr -- "$x" print -r -- "${x}typeset -f inline_$nextf" | "$__progname" x="function comsub_$nextf { x=\$("$fbody$'\n); }\n' print -nr -- "$x" print -r -- "${x}typeset -f comsub_$nextf" | "$__progname" x="function reread_$nextf { x=\$(("$fbody$'\n)|tr u x); }\n' print -nr -- "$x" print -r -- "${x}typeset -f reread_$nextf" | "$__progname" fi lastf=1 fbody= nextf=${line#?} done <<'EOD' #1 #TCOM vara=1 varb='2 3' cmd arg1 $arg2 "$arg3 4" >&3 #TPAREN_TPIPE_TLIST (echo $foo | tr -dc 0-9 >&3; echo >&3) >&3 #TAND_TOR cmd >&3 && >&3 echo ja || echo >&3 nein #TSELECT select file in *; do echo "<$file>" ; break >&3 ; done >&3 #TFOR_TTIME for i in {1,2,3} ; do time >&3 echo $i ; done >&3 #TCASE case $foo in 1) echo eins >&3;& 2) echo zwei >&3 ;| *) echo kann net bis drei zählen >&3;; esac >&3 #TIF_TBANG_TDBRACKET_TELIF if ! [[ 1 = 1 ]] >&3 ; then echo eins; elif [[ 1 = 2 ]] >&3; then echo zwei ;else echo drei; fi >&3 #TWHILE i=1; while (( i < 10 )) >&3; do echo $i; let ++i; done >&3 #TUNTIL i=10; until (( !--i )) >&3 ; do echo $i; done >&3 #TCOPROC cat * >&3 |& >&3 ls #TFUNCT_TBRACE_TASYNC function korn { echo eins; echo >&3 zwei ; } bourne () { logger * >&3 & } #COMSUB_EXPRSUB echo $(true >&3) $((1+ 2)) #0 EOD expected-stdout: inline_TCOM() { vara=1 varb='2 3' cmd arg1 $arg2 "$arg3 4" >&3 } inline_TCOM() { vara=1 varb="2 3" cmd arg1 $arg2 "$arg3 4" >&3 } function comsub_TCOM { x=$( vara=1 varb='2 3' cmd arg1 $arg2 "$arg3 4" >&3 ); } function comsub_TCOM { x=$(vara=1 varb="2 3" cmd arg1 $arg2 "$arg3 4" >&3 ) } function reread_TCOM { x=$(( vara=1 varb='2 3' cmd arg1 $arg2 "$arg3 4" >&3 )|tr u x); } function reread_TCOM { x=$(( vara=1 varb="2 3" cmd arg1 $arg2 "$arg3 4" >&3 ) | tr u x ) } inline_TPAREN_TPIPE_TLIST() { (echo $foo | tr -dc 0-9 >&3; echo >&3) >&3 } inline_TPAREN_TPIPE_TLIST() { ( echo $foo | tr -dc 0-9 >&3 echo >&3 ) >&3 } function comsub_TPAREN_TPIPE_TLIST { x=$( (echo $foo | tr -dc 0-9 >&3; echo >&3) >&3 ); } function comsub_TPAREN_TPIPE_TLIST { x=$(( echo $foo | tr -dc 0-9 >&3 ; echo >&3 ) >&3 ) } function reread_TPAREN_TPIPE_TLIST { x=$(( (echo $foo | tr -dc 0-9 >&3; echo >&3) >&3 )|tr u x); } function reread_TPAREN_TPIPE_TLIST { x=$(( ( echo $foo | tr -dc 0-9 >&3 ; echo >&3 ) >&3 ) | tr u x ) } inline_TAND_TOR() { cmd >&3 && >&3 echo ja || echo >&3 nein } inline_TAND_TOR() { cmd >&3 && echo ja >&3 || echo nein >&3 } function comsub_TAND_TOR { x=$( cmd >&3 && >&3 echo ja || echo >&3 nein ); } function comsub_TAND_TOR { x=$(cmd >&3 && echo ja >&3 || echo nein >&3 ) } function reread_TAND_TOR { x=$(( cmd >&3 && >&3 echo ja || echo >&3 nein )|tr u x); } function reread_TAND_TOR { x=$(( cmd >&3 && echo ja >&3 || echo nein >&3 ) | tr u x ) } inline_TSELECT() { select file in *; do echo "<$file>" ; break >&3 ; done >&3 } inline_TSELECT() { select file in * do echo "<$file>" break >&3 done >&3 } function comsub_TSELECT { x=$( select file in *; do echo "<$file>" ; break >&3 ; done >&3 ); } function comsub_TSELECT { x=$(select file in * ; do echo "<$file>" ; break >&3 ; done >&3 ) } function reread_TSELECT { x=$(( select file in *; do echo "<$file>" ; break >&3 ; done >&3 )|tr u x); } function reread_TSELECT { x=$(( select file in * ; do echo "<$file>" ; break >&3 ; done >&3 ) | tr u x ) } inline_TFOR_TTIME() { for i in {1,2,3} ; do time >&3 echo $i ; done >&3 } inline_TFOR_TTIME() { for i in {1,2,3} do time echo $i >&3 done >&3 } function comsub_TFOR_TTIME { x=$( for i in {1,2,3} ; do time >&3 echo $i ; done >&3 ); } function comsub_TFOR_TTIME { x=$(for i in {1,2,3} ; do time echo $i >&3 ; done >&3 ) } function reread_TFOR_TTIME { x=$(( for i in {1,2,3} ; do time >&3 echo $i ; done >&3 )|tr u x); } function reread_TFOR_TTIME { x=$(( for i in {1,2,3} ; do time echo $i >&3 ; done >&3 ) | tr u x ) } inline_TCASE() { case $foo in 1) echo eins >&3;& 2) echo zwei >&3 ;| *) echo kann net bis drei zählen >&3;; esac >&3 } inline_TCASE() { case $foo in (1) echo eins >&3 ;& (2) echo zwei >&3 ;| (*) echo kann net bis drei zählen >&3 ;; esac >&3 } function comsub_TCASE { x=$( case $foo in 1) echo eins >&3;& 2) echo zwei >&3 ;| *) echo kann net bis drei zählen >&3;; esac >&3 ); } function comsub_TCASE { x=$(case $foo in (1) echo eins >&3 ;& (2) echo zwei >&3 ;| (*) echo kann net bis drei zählen >&3 ;; esac >&3 ) } function reread_TCASE { x=$(( case $foo in 1) echo eins >&3;& 2) echo zwei >&3 ;| *) echo kann net bis drei zählen >&3;; esac >&3 )|tr u x); } function reread_TCASE { x=$(( case $foo in (1) echo eins >&3 ;& (2) echo zwei >&3 ;| (*) echo kann net bis drei zählen >&3 ;; esac >&3 ) | tr u x ) } inline_TIF_TBANG_TDBRACKET_TELIF() { if ! [[ 1 = 1 ]] >&3 ; then echo eins; elif [[ 1 = 2 ]] >&3; then echo zwei ;else echo drei; fi >&3 } inline_TIF_TBANG_TDBRACKET_TELIF() { if ! [[ 1 = 1 ]] >&3 then echo eins elif [[ 1 = 2 ]] >&3 then echo zwei else echo drei fi >&3 } function comsub_TIF_TBANG_TDBRACKET_TELIF { x=$( if ! [[ 1 = 1 ]] >&3 ; then echo eins; elif [[ 1 = 2 ]] >&3; then echo zwei ;else echo drei; fi >&3 ); } function comsub_TIF_TBANG_TDBRACKET_TELIF { x=$(if ! [[ 1 = 1 ]] >&3 ; then echo eins ; elif [[ 1 = 2 ]] >&3 ; then echo zwei ; else echo drei ; fi >&3 ) } function reread_TIF_TBANG_TDBRACKET_TELIF { x=$(( if ! [[ 1 = 1 ]] >&3 ; then echo eins; elif [[ 1 = 2 ]] >&3; then echo zwei ;else echo drei; fi >&3 )|tr u x); } function reread_TIF_TBANG_TDBRACKET_TELIF { x=$(( if ! [[ 1 = 1 ]] >&3 ; then echo eins ; elif [[ 1 = 2 ]] >&3 ; then echo zwei ; else echo drei ; fi >&3 ) | tr u x ) } inline_TWHILE() { i=1; while (( i < 10 )) >&3; do echo $i; let ++i; done >&3 } inline_TWHILE() { i=1 while { \let] " i < 10 " } >&3 do echo $i let ++i done >&3 } function comsub_TWHILE { x=$( i=1; while (( i < 10 )) >&3; do echo $i; let ++i; done >&3 ); } function comsub_TWHILE { x=$(i=1 ; while { \let] " i < 10 " ; } >&3 ; do echo $i ; let ++i ; done >&3 ) } function reread_TWHILE { x=$(( i=1; while (( i < 10 )) >&3; do echo $i; let ++i; done >&3 )|tr u x); } function reread_TWHILE { x=$(( i=1 ; while { \let] " i < 10 " ; } >&3 ; do echo $i ; let ++i ; done >&3 ) | tr u x ) } inline_TUNTIL() { i=10; until (( !--i )) >&3 ; do echo $i; done >&3 } inline_TUNTIL() { i=10 until { \let] " !--i " } >&3 do echo $i done >&3 } function comsub_TUNTIL { x=$( i=10; until (( !--i )) >&3 ; do echo $i; done >&3 ); } function comsub_TUNTIL { x=$(i=10 ; until { \let] " !--i " ; } >&3 ; do echo $i ; done >&3 ) } function reread_TUNTIL { x=$(( i=10; until (( !--i )) >&3 ; do echo $i; done >&3 )|tr u x); } function reread_TUNTIL { x=$(( i=10 ; until { \let] " !--i " ; } >&3 ; do echo $i ; done >&3 ) | tr u x ) } inline_TCOPROC() { cat * >&3 |& >&3 ls } inline_TCOPROC() { cat * >&3 |& ls >&3 } function comsub_TCOPROC { x=$( cat * >&3 |& >&3 ls ); } function comsub_TCOPROC { x=$(cat * >&3 |& ls >&3 ) } function reread_TCOPROC { x=$(( cat * >&3 |& >&3 ls )|tr u x); } function reread_TCOPROC { x=$(( cat * >&3 |& ls >&3 ) | tr u x ) } inline_TFUNCT_TBRACE_TASYNC() { function korn { echo eins; echo >&3 zwei ; } bourne () { logger * >&3 & } } inline_TFUNCT_TBRACE_TASYNC() { function korn { echo eins echo zwei >&3 } bourne() { logger * >&3 & } } function comsub_TFUNCT_TBRACE_TASYNC { x=$( function korn { echo eins; echo >&3 zwei ; } bourne () { logger * >&3 & } ); } function comsub_TFUNCT_TBRACE_TASYNC { x=$(function korn { echo eins ; echo zwei >&3 ; } ; bourne() { logger * >&3 & } ) } function reread_TFUNCT_TBRACE_TASYNC { x=$(( function korn { echo eins; echo >&3 zwei ; } bourne () { logger * >&3 & } )|tr u x); } function reread_TFUNCT_TBRACE_TASYNC { x=$(( function korn { echo eins ; echo zwei >&3 ; } ; bourne() { logger * >&3 & } ) | tr u x ) } inline_COMSUB_EXPRSUB() { echo $(true >&3) $((1+ 2)) } inline_COMSUB_EXPRSUB() { echo $(true >&3 ) $((1+ 2)) } function comsub_COMSUB_EXPRSUB { x=$( echo $(true >&3) $((1+ 2)) ); } function comsub_COMSUB_EXPRSUB { x=$(echo $(true >&3 ) $((1+ 2)) ) } function reread_COMSUB_EXPRSUB { x=$(( echo $(true >&3) $((1+ 2)) )|tr u x); } function reread_COMSUB_EXPRSUB { x=$(( echo $(true >&3 ) $((1+ 2)) ) | tr u x ) } --- name: funsub-1 description: Check that non-subenvironment command substitution works stdin: set -e foo=bar echo "ob $foo ." echo "${ echo "ib $foo :" foo=baz echo "ia $foo :" false }" . echo "oa $foo ." expected-stdout: ob bar . ib bar : ia baz : . oa baz . --- name: funsub-2 description: You can now reliably use local and return in funsubs (not exit though) stdin: x=q; e=1; x=${ echo a; e=2; echo x$e;}; echo 1:y$x,$e,$?. x=q; e=1; x=${ echo a; typeset e=2; echo x$e;}; echo 2:y$x,$e,$?. x=q; e=1; x=${ echo a; typeset e=2; return 3; echo x$e;}; echo 3:y$x,$e,$?. expected-stdout: 1:ya x2,2,0. 2:ya x2,1,0. 3:ya,1,3. --- name: valsub-1 description: Check that "value substitutions" work as advertised stdin: x=1 y=2 z=3 REPLY=4 echo "before: x<$x> y<$y> z<$z> R<$REPLY>" x=${| local y echo "start: x<$x> y<$y> z<$z> R<$REPLY>" x=5 y=6 z=7 REPLY=8 echo "end: x<$x> y<$y> z<$z> R<$REPLY>" } echo "after: x<$x> y<$y> z<$z> R<$REPLY>" # ensure trailing newlines are kept t=${|REPLY=$'foo\n\n';} typeset -p t echo -n this used to segfault echo ${|true;}$(true). expected-stdout: before: x<1> y<2> z<3> R<4> start: x<1> y<> z<3> R<> end: x<5> y<6> z<7> R<8> after: x<8> y<2> z<7> R<4> typeset t=$'foo\n\n' this used to segfault. --- name: event-subst-3 description: Check that '!' substitution in noninteractive mode is ignored file-setup: file 755 "falsetto" #! /bin/sh echo molto bene exit 42 file-setup: file 755 "!false" #! /bin/sh echo si stdin: export PATH=.$PATHSEP$PATH falsetto echo yeap !false echo meow ! false echo = $? if ! false; then echo foo; else echo bar; fi expected-stdout: molto bene yeap si meow = 0 foo --- name: event-subst-0 description: Check that '!' substitution in interactive mode is ignored need-ctty: yes arguments: !-i! file-setup: file 755 "falsetto" #! /bin/sh echo molto bene exit 42 file-setup: file 755 "!false" #! /bin/sh echo si stdin: export PATH=.$PATHSEP$PATH falsetto echo yeap !false echo meow ! false echo = $? if ! false; then echo foo; else echo bar; fi expected-stdout: molto bene yeap si meow = 0 foo expected-stderr-pattern: /.*/ --- name: nounset-1 description: Check that "set -u" matches (future) SUSv4 requirement stdin: (set -u try() { local v eval v=\$$1 if [[ -n $v ]]; then echo $1=nz else echo $1=zf fi } x=y (echo $x) echo =1 (echo $y) echo =2 (try x) echo =3 (try y) echo =4 (try 0) echo =5 (try 2) echo =6 (try) echo =7 (echo at=$@) echo =8 (echo asterisk=$*) echo =9 (echo $?) echo =10 (echo $!) echo =11 (echo $-) echo =12 #(echo $_) #echo =13 (echo $#) echo =14 (mypid=$$; try mypid) echo =15 ) 2>&1 | sed -e 's/^[^]]*]//' -e 's/^[^:]*: *//' exit ${PIPESTATUS[0]} expected-stdout: y =1 y: parameter not set =2 x=nz =3 y: parameter not set =4 0=nz =5 2: parameter not set =6 1: parameter not set =7 at= =8 asterisk= =9 0 =10 !: parameter not set =11 ush =12 0 =14 mypid=nz =15 --- name: nameref-1 description: Testsuite for nameref (bound variables) stdin: bar=global typeset -n ir2=bar typeset -n ind=ir2 echo !ind: ${!ind} echo ind: $ind echo !ir2: ${!ir2} echo ir2: $ir2 typeset +n ind echo !ind: ${!ind} echo ind: $ind typeset -n ir2=ind echo !ir2: ${!ir2} echo ir2: $ir2 set|grep ^ir2|sed 's/^/s1: /' typeset|grep ' ir2'|sed -e 's/^/s2: /' -e 's/nameref/typeset -n/' set -A blub -- e1 e2 e3 typeset -n ind=blub typeset -n ir2=blub[2] echo !ind[1]: ${!ind[1]} echo !ir2: $!ir2 echo ind[1]: ${ind[1]} echo ir2: $ir2 expected-stdout: !ind: bar ind: global !ir2: bar ir2: global !ind: ind ind: ir2 !ir2: ind ir2: ir2 s1: ir2=ind s2: typeset -n ir2 !ind[1]: blub[1] !ir2: ir2 ind[1]: e2 ir2: e3 --- name: nameref-2da description: Testsuite for nameref (bound variables) Functions, argument given directly, after local stdin: function foo { typeset bar=lokal baz=auch typeset -n v=bar echo entering echo !v: ${!v} echo !bar: ${!bar} echo !baz: ${!baz} echo bar: $bar echo v: $v v=123 echo bar: $bar echo v: $v echo exiting } bar=global echo bar: $bar foo bar echo bar: $bar expected-stdout: bar: global entering !v: bar !bar: bar !baz: baz bar: lokal v: lokal bar: 123 v: 123 exiting bar: global --- name: nameref-3 description: Advanced testsuite for bound variables (ksh93 fails this) stdin: typeset -n foo=bar[i] set -A bar -- b c a for i in 0 1 2 3; do print $i $foo . done expected-stdout: 0 b . 1 c . 2 a . 3 . --- name: nameref-4 description: Ensure we don't run in an infinite loop time-limit: 3 stdin: baz() { typeset -n foo=fnord fnord=foo foo[0]=bar } set -A foo bad echo sind $foo . baz echo blah $foo . expected-stdout: sind bad . blah bad . expected-stderr-pattern: /fnord: expression recurses on parameter/ --- name: better-parens-1a description: Check support for ((…)) and $((…)) vs (…) and $(…) stdin: if ( (echo fubar)|tr u x); then echo ja else echo nein fi expected-stdout: fxbar ja --- name: better-parens-1b description: Check support for ((…)) and $((…)) vs (…) and $(…) stdin: echo $( (echo fubar)|tr u x) $? expected-stdout: fxbar 0 --- name: better-parens-1c description: Check support for ((…)) and $((…)) vs (…) and $(…) stdin: x=$( (echo fubar)|tr u x); echo $x $? expected-stdout: fxbar 0 --- name: better-parens-2a description: Check support for ((…)) and $((…)) vs (…) and $(…) stdin: if ((echo fubar)|tr u x); then echo ja else echo nein fi expected-stdout: fxbar ja --- name: better-parens-2b description: Check support for ((…)) and $((…)) vs (…) and $(…) stdin: echo $((echo fubar)|tr u x) $? expected-stdout: fxbar 0 --- name: better-parens-2c description: Check support for ((…)) and $((…)) vs (…) and $(…) stdin: x=$((echo fubar)|tr u x); echo $x $? expected-stdout: fxbar 0 --- name: better-parens-3a description: Check support for ((…)) and $((…)) vs (…) and $(…) stdin: if ( (echo fubar)|(tr u x)); then echo ja else echo nein fi expected-stdout: fxbar ja --- name: better-parens-3b description: Check support for ((…)) and $((…)) vs (…) and $(…) stdin: echo $( (echo fubar)|(tr u x)) $? expected-stdout: fxbar 0 --- name: better-parens-3c description: Check support for ((…)) and $((…)) vs (…) and $(…) stdin: x=$( (echo fubar)|(tr u x)); echo $x $? expected-stdout: fxbar 0 --- name: better-parens-4a description: Check support for ((…)) and $((…)) vs (…) and $(…) stdin: if ((echo fubar)|(tr u x)); then echo ja else echo nein fi expected-stdout: fxbar ja --- name: better-parens-4b description: Check support for ((…)) and $((…)) vs (…) and $(…) stdin: echo $((echo fubar)|(tr u x)) $? expected-stdout: fxbar 0 --- name: better-parens-4c description: Check support for ((…)) and $((…)) vs (…) and $(…) stdin: x=$((echo fubar)|(tr u x)); echo $x $? expected-stdout: fxbar 0 --- name: better-parens-5 description: Another corner case stdin: ( (echo 'fo o$bar' "baz\$bla\"" m\$eh) | tr a A) ((echo 'fo o$bar' "baz\$bla\"" m\$eh) | tr a A) expected-stdout: fo o$bAr bAz$blA" m$eh fo o$bAr bAz$blA" m$eh --- name: echo-test-1 description: Test what the echo builtin does (mksh) stdin: echo -n 'foo\x40bar' echo -e '\tbaz' expected-stdout: foo@bar baz --- name: echo-test-2 description: Test what the echo builtin does (POSIX) Note: this follows Debian Policy 10.4 which mandates that -n shall be treated as an option, not XSI which mandates it shall be treated as string but escapes shall be expanded. stdin: test -n "$POSH_VERSION" || set -o posix echo -n 'foo\x40bar' echo -e '\tbaz' expected-stdout: foo\x40bar-e \tbaz --- name: echo-test-3-mnbsd description: Test what the echo builtin does, and test a compatibility flag. category: mnbsdash stdin: "$__progname" -c 'echo -n 1=\\x40$1; echo -e \\x2E' -- foo bar "$__progname" -o posix -c 'echo -n 2=\\x40$1; echo -e \\x2E' -- foo bar "$__progname" -o sh -c 'echo -n 3=\\x40$1; echo -e \\x2E' -- foo bar expected-stdout: 1=@foo. 2=\x40foo-e \x2E 3=\x40bar. --- name: echo-test-3-normal description: Test what the echo builtin does, and test a compatibility flag. category: !mnbsdash stdin: "$__progname" -c 'echo -n 1=\\x40$1; echo -e \\x2E' -- foo bar "$__progname" -o posix -c 'echo -n 2=\\x40$1; echo -e \\x2E' -- foo bar "$__progname" -o sh -c 'echo -n 3=\\x40$1; echo -e \\x2E' -- foo bar expected-stdout: 1=@foo. 2=\x40foo-e \x2E 3=\x40foo-e \x2E --- name: utilities-getopts-1 description: getopts sets OPTIND correctly for unparsed option stdin: set -- -a -a -x while getopts :a optc; do echo "OPTARG=$OPTARG, OPTIND=$OPTIND, optc=$optc." done echo done expected-stdout: OPTARG=, OPTIND=2, optc=a. OPTARG=, OPTIND=3, optc=a. OPTARG=x, OPTIND=4, optc=?. done --- name: utilities-getopts-2 description: Check OPTARG stdin: set -- -a Mary -x while getopts a: optc; do echo "OPTARG=$OPTARG, OPTIND=$OPTIND, optc=$optc." done echo done expected-stdout: OPTARG=Mary, OPTIND=3, optc=a. OPTARG=, OPTIND=4, optc=?. done expected-stderr-pattern: /.*-x.*option/ --- name: utilities-getopts-3 description: Check unsetting OPTARG stdin: set -- -x arg -y getopts x:y opt && echo "${OPTARG-unset}" getopts x:y opt && echo "${OPTARG-unset}" expected-stdout: arg unset --- name: wcswidth-1 description: Check the new wcswidth feature stdin: s=何 set +U print octets: ${#s} . print 8-bit width: ${%s} . set -U print characters: ${#s} . print columns: ${%s} . s=� set +U print octets: ${#s} . print 8-bit width: ${%s} . set -U print characters: ${#s} . print columns: ${%s} . expected-stdout: octets: 3 . 8-bit width: -1 . characters: 1 . columns: 2 . octets: 3 . 8-bit width: 3 . characters: 1 . columns: 1 . --- name: wcswidth-2 description: Check some corner cases stdin: print % $% . set -U x='a b' print c ${%x} . set +U x='a b' print d ${%x} . expected-stdout: % $% . c -1 . d -1 . --- name: wcswidth-3 description: Check some corner cases stdin: print ${%} . expected-stderr-pattern: /bad substitution/ expected-exit: 1 --- name: wcswidth-4a description: Check some corner cases stdin: print ${%*} . expected-stderr-pattern: /bad substitution/ expected-exit: 1 --- name: wcswidth-4b description: Check some corner cases stdin: print ${%@} . expected-stderr-pattern: /bad substitution/ expected-exit: 1 --- name: wcswidth-4c description: Check some corner cases stdin: : print ${%?} . expected-stdout: 1 . --- name: realpath-1 description: Check proper return values for realpath category: os:mirbsd stdin: wd=$(realpath .) mkdir dir :>file :>dir/file ln -s dir lndir ln -s file lnfile ln -s nix lnnix ln -s . lnself i=0 chk() { typeset x y x=$(realpath "$wd/$1" 2>&1); y=$? print $((++i)) "?$1" =${x##*$wd/} !$y } chk dir chk dir/ chk dir/file chk dir/nix chk file chk file/ chk file/file chk file/nix chk nix chk nix/ chk nix/file chk nix/nix chk lndir chk lndir/ chk lndir/file chk lndir/nix chk lnfile chk lnfile/ chk lnfile/file chk lnfile/nix chk lnnix chk lnnix/ chk lnnix/file chk lnnix/nix chk lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself rm lnself expected-stdout: 1 ?dir =dir !0 2 ?dir/ =dir !0 3 ?dir/file =dir/file !0 4 ?dir/nix =dir/nix !0 5 ?file =file !0 6 ?file/ =file/: Not a directory !20 7 ?file/file =file/file: Not a directory !20 8 ?file/nix =file/nix: Not a directory !20 9 ?nix =nix !0 10 ?nix/ =nix !0 11 ?nix/file =nix/file: No such file or directory !2 12 ?nix/nix =nix/nix: No such file or directory !2 13 ?lndir =dir !0 14 ?lndir/ =dir !0 15 ?lndir/file =dir/file !0 16 ?lndir/nix =dir/nix !0 17 ?lnfile =file !0 18 ?lnfile/ =lnfile/: Not a directory !20 19 ?lnfile/file =lnfile/file: Not a directory !20 20 ?lnfile/nix =lnfile/nix: Not a directory !20 21 ?lnnix =nix !0 22 ?lnnix/ =nix !0 23 ?lnnix/file =lnnix/file: No such file or directory !2 24 ?lnnix/nix =lnnix/nix: No such file or directory !2 25 ?lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself =lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself: Too many levels of symbolic links !62 --- name: realpath-2 description: Ensure that exactly two leading slashes are not collapsed POSIX guarantees this exception, e.g. for UNC paths on Cygwin category: os:mirbsd stdin: ln -s /bin t1 ln -s //bin t2 ln -s ///bin t3 realpath /bin realpath //bin realpath ///bin realpath /usr/bin realpath /usr//bin realpath /usr///bin realpath t1 realpath t2 realpath t3 rm -f t1 t2 t3 cd //usr/bin pwd cd ../lib pwd realpath //usr/include/../bin expected-stdout: /bin //bin /bin /usr/bin /usr/bin /usr/bin /bin //bin /bin //usr/bin //usr/lib //usr/bin --- name: crash-1 description: Crashed during March 2011, fixed on vernal equinōx ☺ category: os:mirbsd,os:openbsd stdin: export MALLOC_OPTIONS=FGJPRSX "$__progname" -c 'x=$(tr z r <<?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\177\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377\u00A0\u20AC\uFFFD\357\277\276\357\277\277\360\220\200\200.' --- name: stateptr-underflow description: This check overflows an Xrestpos stored in a short in R40 category: fastbox stdin: function Lb64decode { [[ -o utf8-mode ]]; local u=$? set +U local c s="$*" t= [[ -n $s ]] || { s=$(cat;print x); s=${s%x}; } local -i i=0 n=${#s} p=0 v x local -i16 o while (( i < n )); do c=${s:(i++):1} case $c { (=) break ;; ([A-Z]) (( v = 1#$c - 65 )) ;; ([a-z]) (( v = 1#$c - 71 )) ;; ([0-9]) (( v = 1#$c + 4 )) ;; (+) v=62 ;; (/) v=63 ;; (*) continue ;; } (( x = (x << 6) | v )) case $((p++)) { (0) continue ;; (1) (( o = (x >> 4) & 255 )) ;; (2) (( o = (x >> 2) & 255 )) ;; (3) (( o = x & 255 )) p=0 ;; } t=$t\\x${o#16#} done print -n $t (( u )) || set -U } i=-1 s= while (( ++i < 12120 )); do s+=a done Lb64decode $s >/dev/null --- name: xtrace-1 description: Check that "set -x" doesn't redirect too quickly stdin: print '#!'"$__progname" >bash cat >>bash <<'EOF' echo 'GNU bash, version 2.05b.0(1)-release (i386-ecce-mirbsd10) Copyright (C) 2002 Free Software Foundation, Inc.' EOF chmod +x bash "$__progname" -xc 'foo=$(./bash --version 2>&1 | sed q); echo "=$foo="' expected-stdout: =GNU bash, version 2.05b.0(1)-release (i386-ecce-mirbsd10)= expected-stderr-pattern: /.*/ --- name: xtrace-2 description: Check that "set -x" is off during PS4 expansion stdin: f() { print -n "(f1:$-)" set -x print -n "(f2:$-)" } PS4='[(p:$-)$(f)] ' print "(o0:$-)" set -x -o inherit-xtrace print "(o1:$-)" set +x print "(o2:$-)" expected-stdout: (o0:sh) (o1:shx) (o2:sh) expected-stderr: [(p:sh)(f1:sh)(f2:sh)] print '(o1:shx)' [(p:sh)(f1:sh)(f2:sh)] set +x --- name: fksh-flags description: Check that FKSH functions have their own shell flags category: shell:legacy-no stdin: [[ $KSH_VERSION = Version* ]] && set +B function foo { set +f set -e echo 2 "${-/s}" . } set -fh echo 1 "${-/s}" . foo echo 3 "${-/s}" . expected-stdout: 1 fh . 2 eh . 3 fh . --- name: fksh-flags-legacy description: Check that even FKSH functions share the shell flags category: shell:legacy-yes stdin: [[ $KSH_VERSION = Version* ]] && set +B foo() { set +f set -e echo 2 "${-/s}" . } set -fh echo 1 "${-/s}" . foo echo 3 "${-/s}" . expected-stdout: 1 fh . 2 eh . 3 eh . --- name: fsh-flags description: Check that !FKSH functions share the shell flags stdin: [[ $KSH_VERSION = Version* ]] && set +B foo() { set +f set -e echo 2 "${-/s}" . } set -fh echo 1 "${-/s}" . foo echo 3 "${-/s}" . expected-stdout: 1 fh . 2 eh . 3 eh . ---