# $MirOS: src/bin/mksh/check.t,v 1.721 2016/01/20 21:34:09 tg Exp $ # -*- mode: sh -*- #- # Copyright © 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, # 2011, 2012, 2013, 2014, 2015, 2016 # 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://openbsd.cs.toronto.edu/cgi-bin/cvsweb/src/regress/bin/ksh/?sortby=date expected-stdout: @(#)MIRBSD KSH R52 2016/01/20 description: Check version of shell. stdin: echo $KSH_VERSION name: KSH_VERSION category: shell:legacy-no --- expected-stdout: @(#)LEGACY KSH R52 2016/01/20 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-legacy description: Check some things in the LEGACY KSH category: shell:legacy-yes stdin: set +o emacs set +o vi [[ "$(set +o) -o" = *"-o emacs -o"* ]] && echo 1=emacs [[ "$(set +o) -o" = *"-o vi -o"* ]] && echo 1=vi set -o emacs set -o vi [[ "$(set +o) -o" = *"-o emacs -o"* ]] && echo 2=emacs [[ "$(set +o) -o" = *"-o vi -o"* ]] && echo 2=vi expected-stdout: 2=emacs 2=vi --- 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-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-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 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> . --- 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 case of trim expansion vs. $# 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} expected-stdout: 11 2 1 2 --- name: expand-weird-2 description: Check corner case of ${var?} vs. ${#var} stdin: (exit 0) echo $? = ${#?} . (exit 111) echo $? = ${#?} . expected-stdout: 0 = 1 . 111 = 3 . --- name: expand-weird-3 description: Check that trimming works with positional parameters (Debian #48453) stdin: A=9999-02 B=9999 echo 1=${A#$B?}. set -- $A $B echo 2=${1#$2?}. expected-stdout: 1=02. 2=02. --- name: expand-weird-4 description: Check that tilde expansion is enabled in ${x#~} and cases that are modelled after it (${x/~/~}) stdin: HOME=/etc a="~/x" echo "<${a#~}> <${a#\~}> <${b:-~}> <${b:-\~}> <${c:=~}><$c> <${a/~}> <${a/x/~}> <${a/x/\~}>" expected-stdout: <~/x> <~> <\~> <~><~> <~/x> <~//etc> <~/~> --- name: expand-number-1 description: Check that positional arguments do not overflow stdin: echo "1 ${12345678901234567890} ." expected-stdout: 1 . --- 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} 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 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-4 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-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=<&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-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 numer 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: touch 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: 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-_-1 # fails due to weirdness of execv stuff category: !os:uwin-nt description: Check c flag is set. arguments: !-c!echo "[$-]"! expected-stdout-pattern: /^\[.*c.*\]$/ --- name: tilde-expand-1 description: Check tilde expansion after equal signs env-setup: !HOME=/sweet! stdin: echo ${A=a=}~ b=~ c=d~ ~ export e=~ f=d~ command command export g=~ h=d~ echo ". $e . $f ." echo ". $g . $h ." set -o posix unset A e f g h echo ${A=a=}~ b=~ c=d~ ~ export e=~ f=d~ command command export g=~ h=d~ echo ". $e . $f ." echo ". $g . $h ." expected-stdout: a=/sweet b=/sweet c=d~ /sweet . /sweet . d~ . . /sweet . d~ . a=~ b=~ c=d~ /sweet . /sweet . d~ . . /sweet . d~ . --- name: tilde-expand-2 description: Check tilde expansion works env-setup: !HOME=/sweet! stdin: 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: one 0 . two 0 . nix 0 . --- 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-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: 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>' expected-stdout: <> <> <> <> --- 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-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 "$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 "$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 56 5C 57 5C 58 5C |\Q\R\S\T \V\W\X\| 00000070 59 5C 5A 5C 5B 5C 5C 5D - 5C 5E 5C 5F 5C 60 07 08 |Y\Z\[\]\^\_\`..| 00000080 20 20 5C 64 1B 0C 5C 67 - 5C 68 5C 69 5C 6A 5C 6B | \d..\g\h\i\j\k| 00000090 5C 6C 5C 6D 0A 5C 6F 5C - 70 20 5C 71 0D 5C 73 09 |\l\m.\o\p \q.\s.| 000000A0 0B 5C 77 5C 79 5C 7A 5C - 7B 5C 7C 5C 7D 5C 7E 20 |.\w\y\z\{\|\}\~ | 000000B0 E2 82 AC 64 20 EF BF BD - 20 12 33 20 78 20 53 20 |...d ... .3 x S | 000000C0 53 34 0A - |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 "$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 "$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 </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 "$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 "$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 "$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 "$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 "$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 "$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 "$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 "$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 category: shell:legacy-no 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 category: shell:legacy-no 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 category: shell:legacy-no 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 category: shell:legacy-no 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 category: shell:legacy-no 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 category: shell:legacy-no 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 category: shell:legacy-no 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-normal description: Check if GNU bash-like I/O redirection is only supported in !POSIX !sh mode as it breaks existing scripts' syntax category: shell:legacy-no 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')" = "$(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')" = "$(foo print -u12 bar echo baz >&12 cat foo expected-stdout: bar baz --- name: oksh-eval description: Check expansions. stdin: a= for n in ${a#*=}; do echo 1hu ${n} .; done for n in "${a#*=}"; do echo 1hq ${n} .; done for n in ${a##*=}; do echo 2hu ${n} .; done for n in "${a##*=}"; do echo 2hq ${n} .; done for n in ${a%=*}; do echo 1pu ${n} .; done for n in "${a%=*}"; do echo 1pq ${n} .; done for n in ${a%%=*}; do echo 2pu ${n} .; done for n in "${a%%=*}"; do echo 2pq ${n} .; done expected-stdout: 1hq . 2hq . 1pq . 2pq . --- name: oksh-and-list-error-1 description: Test exit status of rightmost element in 2 element && list in -e mode stdin: true && false echo "should not print" arguments: !-e! expected-exit: e != 0 --- name: oksh-and-list-error-2 description: Test exit status of rightmost element in 3 element && list in -e mode stdin: true && true && false echo "should not print" arguments: !-e! expected-exit: e != 0 --- name: oksh-or-list-error-1 description: Test exit status of || list in -e mode stdin: false || false echo "should not print" arguments: !-e! expected-exit: e != 0 --- name: oksh-longline-crash description: This used to cause a core dump stdin: ulimit -c 0 deplibs="-lz -lpng /usr/local/lib/libjpeg.la -ltiff -lm -lX11 -lXext /usr/local/lib/libiconv.la -L/usr/local/lib -L/usr/ports/devel/gettext/w-gettext-0.10.40/gettext-0.10.40/intl/.libs /usr/local/lib/libintl.la /usr/local/lib/libglib.la /usr/local/lib/libgmodule.la -lintl -lm -lX11 -lXext -L/usr/X11R6/lib -lglib -lgmodule -L/usr/local/lib /usr/local/lib/libgdk.la -lintl -lm -lX11 -lXext -L/usr/X11R6/lib -lglib -lgmodule -L/usr/local/lib /usr/local/lib/libgtk.la -ltiff -ljpeg -lz -lpng -lm -lX11 -lXext -lintl -lglib -lgmodule -lgdk -lgtk -L/usr/X11R6/lib -lglib -lgmodule -L/usr/local/lib /usr/local/lib/libgdk_pixbuf.la -lz -lpng /usr/local/lib/libiconv.la -L/usr/local/lib -L/usr/ports/devel/gettext/w-gettext-0.10.40/gettext-0.10.40/intl/.libs /usr/local/lib/libintl.la /usr/local/lib/libglib.la -lm -lm /usr/local/lib/libaudiofile.la -lm -lm -laudiofile -L/usr/local/lib /usr/local/lib/libesd.la -lm -lz -L/usr/local/lib /usr/local/lib/libgnomesupport.la -lm -lz -lm -lglib -L/usr/local/lib /usr/local/lib/libgnome.la -lX11 -lXext /usr/local/lib/libiconv.la -L/usr/local/lib -L/usr/ports/devel/gettext/w-gettext-0.10.40/gettext-0.10.40/intl/.libs /usr/local/lib/libintl.la /usr/local/lib/libgmodule.la -lintl -lm -lX11 -lXext -L/usr/X11R6/lib -lglib -lgmodule -L/usr/local/lib /usr/local/lib/libgdk.la -lintl -lm -lX11 -lXext -L/usr/X11R6/lib -lglib -lgmodule -L/usr/local/lib /usr/local/lib/libgtk.la -lICE -lSM -lz -lpng /usr/local/lib/libungif.la /usr/local/lib/libjpeg.la -ltiff -lm -lz -lpng /usr/local/lib/libungif.la -lz /usr/local/lib/libjpeg.la -ltiff -L/usr/local/lib -L/usr/X11R6/lib /usr/local/lib/libgdk_imlib.la -lm -L/usr/local/lib /usr/local/lib/libart_lgpl.la -lm -lz -lm -lX11 -lXext -lintl -lglib -lgmodule -lgdk -lgtk -lICE -lSM -lm -lX11 -lXext -lintl -lglib -lgmodule -lgdk -lgtk -L/usr/X11R6/lib -lm -lz -lpng -lungif -lz -ljpeg -ltiff -ljpeg -lgdk_imlib -lglib -lm -laudiofile -lm -laudiofile -lesd -L/usr/local/lib /usr/local/lib/libgnomeui.la -lz -lz /usr/local/lib/libxml.la -lz -lz -lz /usr/local/lib/libxml.la -lm -lX11 -lXext /usr/local/lib/libiconv.la -L/usr/ports/devel/gettext/w-gettext-0.10.40/gettext-0.10.40/intl/.libs /usr/local/lib/libintl.la /usr/local/lib/libglib.la /usr/local/lib/libgmodule.la -lintl -lglib -lgmodule /usr/local/lib/libgdk.la /usr/local/lib/libgtk.la -L/usr/X11R6/lib -L/usr/local/lib /usr/local/lib/libglade.la -lz -lz -lz /usr/local/lib/libxml.la /usr/local/lib/libglib.la -lm -lm /usr/local/lib/libaudiofile.la -lm -lm -laudiofile /usr/local/lib/libesd.la -lm -lz /usr/local/lib/libgnomesupport.la -lm -lz -lm -lglib /usr/local/lib/libgnome.la -lX11 -lXext /usr/local/lib/libiconv.la -L/usr/ports/devel/gettext/w-gettext-0.10.40/gettext-0.10.40/intl/.libs /usr/local/lib/libintl.la /usr/local/lib/libgmodule.la -lintl -lm -lX11 -lXext -lglib -lgmodule /usr/local/lib/libgdk.la -lintl -lm -lX11 -lXext -lglib -lgmodule /usr/local/lib/libgtk.la -lICE -lSM -lz -lpng /usr/local/lib/libungif.la /usr/local/lib/libjpeg.la -ltiff -lm -lz -lz /usr/local/lib/libgdk_imlib.la /usr/local/lib/libart_lgpl.la -lm -lz -lm -lX11 -lXext -lintl -lglib -lgmodule -lgdk -lgtk -lm -lX11 -lXext -lintl -lglib -lgmodule -lgdk -lgtk -lm -lz -lungif -lz -ljpeg -ljpeg -lgdk_imlib -lglib -lm -laudiofile -lm -laudiofile -lesd /usr/local/lib/libgnomeui.la -L/usr/X11R6/lib -L/usr/local/lib /usr/local/lib/libglade-gnome.la /usr/local/lib/libglib.la -lm -lm /usr/local/lib/libaudiofile.la -lm -lm -laudiofile -L/usr/local/lib /usr/local/lib/libesd.la -lm -lz -L/usr/local/lib /usr/local/lib/libgnomesupport.la -lm -lz -lm -lglib -L/usr/local/lib /usr/local/lib/libgnome.la -lX11 -lXext /usr/local/lib/libiconv.la -L/usr/local/lib -L/usr/ports/devel/gettext/w-gettext-0.10.40/gettext-0.10.40/intl/.libs /usr/local/lib/libintl.la /usr/local/lib/libgmodule.la -lintl -lm -lX11 -lXext -L/usr/X11R6/lib -lglib -lgmodule -L/usr/local/lib /usr/local/lib/libgdk.la -lintl -lm -lX11 -lXext -L/usr/X11R6/lib -lglib -lgmodule -L/usr/local/lib /usr/local/lib/libgtk.la -lICE -lSM -lz -lpng /usr/local/lib/libungif.la /usr/local/lib/libjpeg.la -ltiff -lm -lz -lpng /usr/local/lib/libungif.la -lz /usr/local/lib/libjpeg.la -ltiff -L/usr/local/lib -L/usr/X11R6/lib /usr/local/lib/libgdk_imlib.la -lm -L/usr/local/lib /usr/local/lib/libart_lgpl.la -lm -lz -lm -lX11 -lXext -lintl -lglib -lgmodule -lgdk -lgtk -lICE -lSM -lm -lX11 -lXext -lintl -lglib -lgmodule -lgdk -lgtk -L/usr/X11R6/lib -lm -lz -lpng -lungif -lz -ljpeg -ltiff -ljpeg -lgdk_imlib -lglib -lm -laudiofile -lm -laudiofile -lesd -L/usr/local/lib /usr/local/lib/libgnomeui.la -L/usr/X11R6/lib -L/usr/local/lib" specialdeplibs="-lgnomeui -lart_lgpl -lgdk_imlib -ltiff -ljpeg -lungif -lpng -lz -lSM -lICE -lgtk -lgdk -lgmodule -lintl -lXext -lX11 -lgnome -lgnomesupport -lesd -laudiofile -lm -lglib" for deplib in $deplibs; do case $deplib in -L*) new_libs="$deplib $new_libs" ;; *) case " $specialdeplibs " in *" $deplib "*) new_libs="$deplib $new_libs";; esac ;; esac done --- name: oksh-seterror-1 description: The -e flag should be ignored when executing a compound list followed by an if statement. stdin: if true; then false && false; fi true arguments: !-e! expected-exit: e == 0 --- name: oksh-seterror-2 description: The -e flag should be ignored when executing a compound list followed by an if statement. stdin: if true; then if true; then false && false; fi; fi true arguments: !-e! expected-exit: e == 0 --- name: oksh-seterror-3 description: The -e flag should be ignored when executing a compound list followed by an elif statement. stdin: if true; then :; elif true; then false && false; fi arguments: !-e! expected-exit: e == 0 --- name: oksh-seterror-4 description: The -e flag should be ignored when executing a pipeline beginning with '!' stdin: for i in 1 2 3 do false && false true || false done arguments: !-e! expected-exit: e == 0 --- name: oksh-seterror-5 description: The -e flag should be ignored when executing a pipeline beginning with '!' stdin: ! true | false true arguments: !-e! expected-exit: e == 0 --- name: oksh-seterror-6 description: When trapping ERR and EXIT, both traps should run in -e mode when an error occurs. stdin: trap 'echo EXIT' EXIT trap 'echo ERR' ERR set -e false echo DONE exit 0 arguments: !-e! expected-exit: e != 0 expected-stdout: ERR EXIT --- name: oksh-seterror-7 description: The -e flag within a command substitution should be honored stdin: echo $( set -e; false; echo foo ) arguments: !-e! expected-stdout: --- name: oksh-input-comsub description: A command substitution using input redirection should exit with failure if the input file does not exist. stdin: var=$(< non-existent) expected-exit: e != 0 expected-stderr-pattern: /non-existent/ --- name: oksh-empty-for-list description: A for list which expands to zero items should not execute the body. stdin: set foo bar baz ; for out in ; do echo $out ; done --- name: oksh-varfunction-mod1 description: (Inspired by PR 2450 on OpenBSD.) Calling FOO=bar f where f is a ksh style function, should not set FOO in the current env. If f is a Bourne style function, FOO should be set. Furthermore, the function should receive a correct value of FOO. However, differing from oksh, setting FOO in the function itself must change the value in setting FOO in the function itself should not change the value in global environment. 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 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 category: shell:legacy-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 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: fd-cloexec-3 description: Verify that file descriptors > 2 are not private for LEGACY KSH category: shell:legacy-yes 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-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 "begin: 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> begin: 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: 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 | head -1); 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 . ---