diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-05 18:33:23 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-05 18:33:23 +0000 |
commit | 1d5cace9db9aef76f26b2d7ba54bbb76443b00b2 (patch) | |
tree | 314a15dd1aa103da13bdc83ba1d2105a290bc5ba /tests | |
parent | Initial commit. (diff) | |
download | bash-1d5cace9db9aef76f26b2d7ba54bbb76443b00b2.tar.xz bash-1d5cace9db9aef76f26b2d7ba54bbb76443b00b2.zip |
Adding upstream version 5.0.upstream/5.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
588 files changed, 34420 insertions, 0 deletions
diff --git a/tests/COPYRIGHT b/tests/COPYRIGHT new file mode 100644 index 0000000..43b39df --- /dev/null +++ b/tests/COPYRIGHT @@ -0,0 +1,9 @@ +Unless otherwise stated, all files in this directory are Copyright (C) +1991,1992,1993,1994,1995,1996,1997,1998,1999,2000,2001,2002,2003, +2004,2005,2006,2007,2008,2009,2010,2011 +Free Software Foundation, Inc. + +See the file COPYING in the bash distribution root directory for copying +and usage restrictions. + +The file ifs-posix.tests is Copyright (C) 2005 Glen Fowler. diff --git a/tests/README b/tests/README new file mode 100644 index 0000000..b023ef6 --- /dev/null +++ b/tests/README @@ -0,0 +1,3 @@ +Type `sh run-all'. + +Read COPYRIGHT for copyright information. diff --git a/tests/alias.right b/tests/alias.right new file mode 100644 index 0000000..3ab9a71 --- /dev/null +++ b/tests/alias.right @@ -0,0 +1,32 @@ +alias: 0 +alias: 0 +./alias.tests: line 25: qfoo: command not found +quux +bar +value +bar +value +OK +OK +OK +OK +one +two +three +four +one +two +three +four +Error: bar +ok 1 +ok 2 +text +whoops: nullalias +foo +a +a b +a b +a a b +ok 3 +ok 4 diff --git a/tests/alias.tests b/tests/alias.tests new file mode 100644 index 0000000..6aa1218 --- /dev/null +++ b/tests/alias.tests @@ -0,0 +1,42 @@ +# place holder for future alias testing +shopt -s expand_aliases + +# alias/unalias tests originally in builtins.tests + +unalias -a +# this should return success, according to POSIX.2 +alias +echo alias: $? +alias foo=bar +unalias foo +# this had better return success, according to POSIX.2 +alias +echo alias: $? + +# bug in all versions through bash-2.05b + +unalias qfoo qbar qbaz quux 2>/dev/null + +alias qfoo=qbar +alias qbar=qbaz +alias qbaz=quux +alias quux=qfoo + +qfoo + +unalias qfoo qbar qbaz quux + +unalias -a + +alias foo='echo ' +alias bar=baz +alias baz=quux + +foo bar + +unalias foo bar baz + +${THIS_SH} ./alias1.sub +${THIS_SH} ./alias2.sub +${THIS_SH} ./alias3.sub +${THIS_SH} ./alias4.sub diff --git a/tests/alias1.sub b/tests/alias1.sub new file mode 100644 index 0000000..ed03031 --- /dev/null +++ b/tests/alias1.sub @@ -0,0 +1,20 @@ +shopt -s expand_aliases + +alias foo=echo + +< /dev/null foo bar + +< /dev/null x=value +echo $x + +< /dev/null x=newvalue foo bar +echo $x + +# problem reported by Vincent Lefevre +alias a="echo OK >&2" +a +> /dev/null a + +${THIS_SH} -c 'shopt -s expand_aliases; alias a="echo OK >&2" + a + > /dev/null a' diff --git a/tests/alias2.sub b/tests/alias2.sub new file mode 100644 index 0000000..7604448 --- /dev/null +++ b/tests/alias2.sub @@ -0,0 +1,22 @@ +THIS=alias2 +FN=$TMPDIR/$THIS.script + +cat > $FN <<'EOF' +# +(echo "$1") +EOF +chmod u+x $FN + +shopt -s expand_aliases + +alias foo1='$FN one; source $FN two; source $FN three; $FN four' + +alias foo2='$FN one +source $FN two +source $FN three +$FN four' + +foo1 +foo2 + +rm -f $FN diff --git a/tests/alias3.sub b/tests/alias3.sub new file mode 100644 index 0000000..bb94268 --- /dev/null +++ b/tests/alias3.sub @@ -0,0 +1,12 @@ +#!/bin/bash +shopt -s expand_aliases +alias foo='oneword' +foo_word='foo' +# +# Fails silently to match 'foo': +# +case "$foo_word" +in + foo) ;; + *) echo bad 1;; +esac diff --git a/tests/alias4.sub b/tests/alias4.sub new file mode 100644 index 0000000..6ea513a --- /dev/null +++ b/tests/alias4.sub @@ -0,0 +1,70 @@ +shopt -s expand_aliases + +# from an austin-group report +alias foo="echo 'Error:" +foo bar' + +# from some FreeBSD sh tests + +v=1 +alias a='unalias -a +v=2' +eval a +[ "$v" = 2 ] && echo ok 1 +v=1 +alias a='unalias a +v=2' +eval a +[ "$v" = 2 ] && echo ok 2 + +# make sure command doesn't ever reset anything even if it's made a keyword +unalias -a +alias command=command +alias true='echo bad' +eval 'command true' + +unalias -a +alias alias0=command +alias true='echo bad' +eval 'alias0 true' + +# make sure null aliases are ok +unalias -a +alias nullalias='' +alias foo='echo ' +foo nullalias text +unalias foo + +# aliases shouldn't be expanded in quoted strings even when the previous word +# is an alias whose expansion ends in a space +alias foo="echo 'whoops: " +foo nullalias' + +unalias -a + +# recursive alias definitions +alias echo=echo +eval echo foo + +alias echo='echo a' + +echo +echo b +eval echo b +echo $(eval echo b) + +unalias -a + +# alias expansion when in a command position after redirections +alias e=echo +eval '</dev/null e ok 3' +eval 'a=true e ok 4' + +alias comment=# +comment + +alias long_comment='# for x in ' +long_comment text after + +# comment +comment foo bar diff --git a/tests/appendop.right b/tests/appendop.right new file mode 100644 index 0000000..f9609f8 --- /dev/null +++ b/tests/appendop.right @@ -0,0 +1,28 @@ +14 +1 2 3 4 5 6 +1 2 3 4 51 6 +145 +14 +7 +42 +1 2 3 4 12 +18 +1 2 3 4 18 +1 2 7 4 5 +1 2 7 13 5 9 +14 +9 +4 +9 +16 +./appendop.tests: line 84: x: readonly variable +declare -A foo=([two]="baz" [three]="quux" [one]="bar" ) +declare -A foo=([two]="baz" [0]="zero" [three]="quux" [one]="bar" ) +declare -A foo=([two]="baz" [0]="zero" [three]="quux" [four]="four" [one]="bar" ) +declare -ai iarr=([0]="3" [1]="2" [2]="3") +declare -ai iarr=([0]="3" [1]="2" [2]="3" [3]="4" [4]="5" [5]="6") +25 25 +7 7 +14 +145 +145 145 diff --git a/tests/appendop.tests b/tests/appendop.tests new file mode 100644 index 0000000..e4e52c2 --- /dev/null +++ b/tests/appendop.tests @@ -0,0 +1,87 @@ +# basic cases +a=1 +a+=4 +echo $a + +x=(1 2 3) +x+=(4 5 6) + +echo ${x[@]} + +x[4]+=1 +echo ${x[@]} + +# trickier cases +# post-bash-4.2: bash understands += in environment assignments preceding +# command names +a+=5 printenv a +echo $a + +# if the integer flag is set, ksh93 appears to do arithmetic += and evaluate +# old value as an arithmetic expression +a= +typeset -i a +a+=7 +echo $a + +b=4+1 +typeset -i b +b+=37 + +echo $b + +unset x +x=(1 2 3 4 5) + +typeset -i x + +x[4]+=7 + +echo ${x[@]} + +unset x +typeset -i x + +x=([0]=7+11) +echo ${x[@]} + +unset x +x=(1 2 3 4 5) + +typeset -i x + +#x[4]=7+11 + +x=(1 2 3 4 [4]=7+11 ) +echo ${x[@]} + +x=( 1 2 [2]+=7 4 5 ) +echo ${x[@]} + +x+=( [3]+=9 [5]=9 ) +echo ${x[@]} + +unset a +a=1 +export a+=4 +printenv a +printenv a+ + +unset x +typeset -i x=4+5 +echo $x + +unset x +typeset x+=4 +echo $x + +typeset -i x+=5 +echo $x + +readonly x+=7 +echo $x + +x+=5 + +${THIS_SH} ./appendop1.sub +${THIS_SH} ./appendop2.sub diff --git a/tests/appendop1.sub b/tests/appendop1.sub new file mode 100644 index 0000000..7101d0c --- /dev/null +++ b/tests/appendop1.sub @@ -0,0 +1,15 @@ +typeset -A foo=([one]=bar [two]=baz [three]=quux) +typeset -p foo + +foo+=zero +typeset -p foo + +foo+=([four]=four) +typeset -p foo + +typeset -ia iarr=(2 2 3) +iarr+=1 +typeset -p iarr + +iarr+=(4 5 6) +typeset -p iarr diff --git a/tests/appendop2.sub b/tests/appendop2.sub new file mode 100644 index 0000000..4225ba3 --- /dev/null +++ b/tests/appendop2.sub @@ -0,0 +1,18 @@ +POSIXLY_CORRECT=1 +x=2 +x+=5 eval printf '"$x "' +echo "$x" + +unset x +typeset -i x=2 +x+=5 eval printf '"$x "' +echo "$x" + +a=1 +a+=4 +echo $a + +# idiotically, ksh93 makes these two cases differ (?) +a+=5 printenv a +a+=5 eval printf '"$a "' +echo $a diff --git a/tests/arith-for.right b/tests/arith-for.right new file mode 100644 index 0000000..5c09070 --- /dev/null +++ b/tests/arith-for.right @@ -0,0 +1,86 @@ +0 +1 +2 +0 +1 +2 +0 +1 +2 +0 +2 +4 +fx is a function +fx () +{ + i=0; + for ((1; i < 3; i++ )) + do + echo $i; + done; + for ((i=0; 1; i++ )) + do + if (( i >= 3 )); then + break; + fi; + echo $i; + done; + for ((i=0; i<3; 1)) + do + echo $i; + (( i++ )); + done; + i=0; + for ((1; 1; 1)) + do + if (( i > 2 )); then + break; + fi; + echo $i; + (( i++ )); + done; + i=0; + for ((1; 1; 1)) + do + if (( i > 2 )); then + break; + fi; + echo $i; + (( i++ )); + done +} +0 +1 +2 +0 +1 +2 +0 +1 +2 +0 +1 +2 +0 +1 +2 +bash: -c: line 0: syntax error: arithmetic expression required +bash: -c: line 0: syntax error: `(( i=0; "i < 3" ))' +2 +bash: -c: line 0: syntax error: `;' unexpected +bash: -c: line 0: syntax error: `(( i=0; i < 3; i++; 7 ))' +2 +20 +20 +12345678 987654321 012345678 987654321 012345678 987654321 012345678 987654321 012345678 987654321 012345678 +12345678 987654321 012345678 987654321 012345678 987654321 012345678 987654321 012345678 987654321 012345678 +4 +3 +2 +1 +0 +4 +3 +2 +1 +0 diff --git a/tests/arith-for.tests b/tests/arith-for.tests new file mode 100644 index 0000000..33f4bd6 --- /dev/null +++ b/tests/arith-for.tests @@ -0,0 +1,115 @@ +fx() +{ +i=0 +for (( ; i < 3; i++ )) +do + echo $i +done + +for (( i=0; ; i++ )) +do + if (( i >= 3 )); then + break; + fi + echo $i +done + +for (( i=0; i<3; )) +do + echo $i + (( i++ )) +done + +i=0 +for (( ; ; )) +do + if (( i > 2 )); then + break; + fi + echo $i; + (( i++ )) +done + +i=0 +for ((;;)) +do + if (( i > 2 )); then + break; + fi + echo $i; + (( i++ )) +done +} + +for (( i=0; "i < 3" ; i++ )) +do + echo $i +done + +i=0 +for (( ; "i < 3"; i++ )) +do + echo $i +done + +for (( i=0; ; i++ )) +do + if (( i >= 3 )); then + break; + fi + echo $i +done + +for ((i = 0; ;i++ )) +do + echo $i + if (( i < 3 )); then + (( i++ )) + continue; + fi + break +done + +type fx +fx + +# errors +{ +${THIS_SH} -c 'for (( i=0; "i < 3" )) +do + echo $i +done' ; echo $? ; } 2>&1 | sed 's|^.*/||' +#echo $? + +{ +${THIS_SH} -c 'for (( i=0; i < 3; i++; 7 )) +do + echo $i +done' ; echo $?; } 2>&1 | sed 's|^.*/||' +#echo $? + +# one-liners added in post-bash-2.04 +for ((i=0; i < 20; i++)) do : ; done +echo $i + +for ((i=0; i < 20; i++)) { : ; } +echo $i + +# added post-bash-4.2 +for (( i = j = k = 1; i % 9 || (j *= -1, $( ((i%9)) || printf " " >&2; echo 0), k++ <= 10); i += j )) +do +printf "$i" +done + +echo + +( for (( i = j = k = 1; i % 9 || (j *= -1, $( ((i%9)) || printf " " >&2; echo 0), k++ <= 10); i += j )) +do +printf "$i" +done ) + +echo + +for (( i = 4; ;i--)) ; do echo $i; if (( $i == 0 )); then break; fi; done + +for (( i = 4;;i--)) ; do echo $i; if (( $i == 0 )); then break; fi; done diff --git a/tests/arith.right b/tests/arith.right new file mode 100644 index 0000000..2c3d172 --- /dev/null +++ b/tests/arith.right @@ -0,0 +1,263 @@ +163 +166 +4 +16 +8 +2 +4 +2 +2 +1 +0 +0 +0 +1 +1 +2 +-3 +-2 +1 +0 +2 +131072 +29 +33 +49 +1 +1 +0 +0 +1 +1 +1 +2 +3 +1 +58 +2 +60 +1 +256 +16 +62 +4 +29 +5 +-4 +4 +1 +32 +32 +1 +1 +32 +4 +20 +1,i+=2 +30 +1,j+=2 +20 +1,i+=2 +30 +1,j+=2 +./arith.tests: line 114: 1 ? 20 : x+=2: attempted assignment to non-variable (error token is "+=2") +20 +6 +6,5,3 +263 +255 +255 +127 +36 +40 +10 +10 +10 +10 +10 +10 +36 +36 +62 +63 +./arith.tests: line 149: 3425#56: invalid arithmetic base (error token is "3425#56") +0 +./arith.tests: line 155: 7 = 43 : attempted assignment to non-variable (error token is "= 43 ") +./arith.tests: line 156: 2#44: value too great for base (error token is "2#44") +./arith.tests: line 157: 44 / 0 : division by 0 (error token is "0 ") +./arith.tests: line 158: let: jv += $iv: syntax error: operand expected (error token is "$iv") +./arith.tests: line 159: jv += $iv : syntax error: operand expected (error token is "$iv ") +./arith.tests: line 160: let: rv = 7 + (43 * 6: missing `)' (error token is "6") +./arith.tests: line 164: 0#4: invalid number (error token is "0#4") +./arith.tests: line 165: 2#110#11: invalid number (error token is "2#110#11") +abc +def +ghi +ok +6 +1 +0 +./arith.tests: line 183: 4 + : syntax error: operand expected (error token is "+ ") +16 +./arith.tests: line 188: 4 ? : 3 + 5 : expression expected (error token is ": 3 + 5 ") +./arith.tests: line 189: 1 ? 20 : `:' expected for conditional expression (error token is "20 ") +./arith.tests: line 190: 4 ? 20 : : expression expected (error token is ": ") +9 +./arith.tests: line 196: 0 && B=42 : attempted assignment to non-variable (error token is "=42 ") +9 +./arith.tests: line 199: 1 || B=88 : attempted assignment to non-variable (error token is "=88 ") +9 +0 +9 +0 +9 +1 +9 +7 +7 +4 +32767 +32768 +131072 +2147483647 +1 +4 +4 +5 +5 +4 +3 +3 +4 +4 +7 +./arith.tests: line 247: 7-- : syntax error: operand expected (error token is "- ") +./arith.tests: line 249: --x=7 : attempted assignment to non-variable (error token is "=7 ") +./arith.tests: line 250: ++x=7 : attempted assignment to non-variable (error token is "=7 ") +./arith.tests: line 252: x++=7 : attempted assignment to non-variable (error token is "=7 ") +./arith.tests: line 253: x--=7 : attempted assignment to non-variable (error token is "=7 ") +4 +7 +-7 +7 +7 +2 +2 +./arith1.sub: line 2: 4-- : syntax error: operand expected (error token is "- ") +./arith1.sub: line 3: 4++ : syntax error: operand expected (error token is "+ ") +./arith1.sub: line 4: 4 -- : syntax error: operand expected (error token is "- ") +./arith1.sub: line 5: 4 ++ : syntax error: operand expected (error token is "+ ") +1 +2 +1 +2 +6 +3 +7 +4 +0 +3 +7 +2 +-2 +1 +./arith1.sub: line 35: ((: ++ : syntax error: operand expected (error token is "+ ") +7 +7 +./arith1.sub: line 38: ((: -- : syntax error: operand expected (error token is "- ") +7 +7 +7 +7 +1 +2 +1 +2 +1 +0 +5 +1 +6 +2 +3 +1 +4 +0 +./arith2.sub: line 33: ((: -- : syntax error: operand expected (error token is "- ") +-7 +-7 +./arith2.sub: line 37: ((: ++ : syntax error: operand expected (error token is "+ ") +7 +7 +-7 +-7 +7 +7 +1 +1 +4 +5 +-3 +2 +4 +5000 +5000 +1 +0 +0 +1 +2147483649 +0 +0 +0 +0 +0 +0 +-9223372036854775808 +-9223372036854775808 +-9223372036854775808 +-9223372036854775808 +-9223372036854775808 +-9223372036854775808 +-9223372036854775808 +-9223372036854775808 +-9223372036854775808 +-9223372036854775808 +9223372036854775805 9223372036854775806 9223372036854775807 +123 456 +123 456 +123 456 +123 456 +123 456 +123 456 +1 +1 2 3 4 5 6 7 +0 1 2 3 4 5 6 7 +0 +0, 0 +0, 1 +efg +e +efg +e +abcdefg +efg +0 +0 +0 +0 +0 +0 +0 +8 12 +./arith.tests: line 297: ((: x=9 y=41 : syntax error in expression (error token is "y=41 ") +./arith.tests: line 301: a b: syntax error in expression (error token is "b") +./arith.tests: line 302: ((: a b: syntax error in expression (error token is "b") +42 +42 +42 +42 +42 +42 +./arith.tests: line 314: 'foo' : syntax error: operand expected (error token is "'foo' ") +./arith.tests: line 318: b[c]d: syntax error in expression (error token is "d") diff --git a/tests/arith.tests b/tests/arith.tests new file mode 100644 index 0000000..bc9490e --- /dev/null +++ b/tests/arith.tests @@ -0,0 +1,318 @@ +set +o posix +declare -i iv jv + +iv=$(( 3 + 5 * 32 )) +echo $iv +iv=iv+3 +echo $iv +iv=2 +jv=iv + +let "jv *= 2" +echo $jv +jv=$(( $jv << 2 )) +echo $jv + +let jv="$jv / 2" +echo $jv +jv="jv >> 2" +echo $jv + +iv=$((iv+ $jv)) +echo $iv +echo $((iv -= jv)) +echo $iv +echo $(( iv == jv )) +echo $(( iv != $jv )) +echo $(( iv < jv )) +echo $(( $iv > $jv )) +echo $(( iv <= $jv )) +echo $(( $iv >= jv )) + +echo $jv +echo $(( ~$jv )) +echo $(( ~1 )) +echo $(( ! 0 )) + +echo $(( jv % 2 )) +echo $(( $iv % 4 )) + +echo $(( iv <<= 16 )) +echo $(( iv %= 33 )) + +echo $(( 33 & 55 )) +echo $(( 33 | 17 )) + +echo $(( iv && $jv )) +echo $(( $iv || jv )) + +echo $(( iv && 0 )) +echo $(( iv & 0 )) +echo $(( iv && 1 )) +echo $(( iv & 1 )) + +echo $(( $jv || 0 )) +echo $(( jv | 0 )) +echo $(( jv | 1 )) +echo $(( $jv || 1 )) + +let 'iv *= jv' +echo $iv +echo $jv +let "jv += $iv" +echo $jv + +echo $(( jv /= iv )) +echo $(( jv <<= 8 )) +echo $(( jv >>= 4 )) + +echo $(( iv |= 4 )) +echo $(( iv &= 4 )) + +echo $(( iv += (jv + 9))) +echo $(( (iv + 4) % 7 )) + +# unary plus, minus +echo $(( +4 - 8 )) +echo $(( -4 + 8 )) + +# conditional expressions +echo $(( 4<5 ? 1 : 32)) +echo $(( 4>5 ? 1 : 32)) +echo $(( 4>(2+3) ? 1 : 32)) +echo $(( 4<(2+3) ? 1 : 32)) +echo $(( (2+2)<(2+3) ? 1 : 32)) +echo $(( (2+2)>(2+3) ? 1 : 32)) + +# bug in bash versions through bash-3.2 +S=105 +W=$((S>99?4:S>9?3:S>0?2:0)) +echo $W +unset W S + +# check that the unevaluated part of the ternary operator does not do +# evaluation or assignment +x=i+=2 +y=j+=2 +declare -i i=1 j=1 +echo $((1 ? 20 : (x+=2))) +echo $i,$x +echo $((0 ? (y+=2) : 30)) +echo $j,$y + +x=i+=2 +y=j+=2 +declare -i i=1 j=1 +echo $((1 ? 20 : (x+=2))) +echo $i,$x +echo $((0 ? (y+=2) : 30)) +echo $i,$y + +# check precedence of assignment vs. conditional operator +# should be an error +declare -i x=2 +y=$((1 ? 20 : x+=2)) + +# check precedence of assignment vs. conditional operator +declare -i x=2 +echo $((0 ? x+=2 : 20)) + +# associativity of assignment-operator operator +declare -i i=1 j=2 k=3 +echo $((i += j += k)) +echo $i,$j,$k + +# octal, hex +echo $(( 0x100 | 007 )) +echo $(( 0xff )) +echo $(( 16#ff )) +echo $(( 16#FF/2 )) +echo $(( 8#44 )) + +echo $(( 8 ^ 32 )) + +# other bases +echo $(( 16#a )) +echo $(( 32#a )) +echo $(( 56#a )) +echo $(( 64#a )) + +echo $(( 16#A )) +echo $(( 32#A )) +echo $(( 56#A )) +echo $(( 64#A )) + +echo $(( 64#@ )) +echo $(( 64#_ )) + +# weird bases +echo $(( 3425#56 )) + +# missing number after base +echo $(( 2# )) + +# these should generate errors +echo $(( 7 = 43 )) +echo $(( 2#44 )) +echo $(( 44 / 0 )) +let 'jv += $iv' +echo $(( jv += \$iv )) +let 'rv = 7 + (43 * 6' + +# more errors +declare -i i +i=0#4 +i=2#110#11 + +((echo abc; echo def;); echo ghi) + +if (((4+4) + (4 + 7))); then + echo ok +fi + +(()) # make sure the null expression works OK + +a=(0 2 4 6) +echo $(( a[1] + a[2] )) +echo $(( (a[1] + a[2]) == a[3] )) +(( (a[1] + a[2]) == a[3] )) ; echo $? + +# test pushing and popping the expression stack +unset A +A="4 + " +echo $(( ( 4 + A ) + 4 )) +A="3 + 5" +echo $(( ( 4 + A ) + 4 )) + +# badly-formed conditional expressions +echo $(( 4 ? : $A )) +echo $(( 1 ? 20 )) +echo $(( 4 ? 20 : )) + +# precedence and short-circuit evaluation +B=9 +echo $B + +echo $(( 0 && B=42 )) +echo $B + +echo $(( 1 || B=88 )) +echo $B + +echo $(( 0 && (B=42) )) +echo $B + +echo $(( (${$} - $$) && (B=42) )) +echo $B + +echo $(( 1 || (B=88) )) +echo $B + +# until command with (( )) command +x=7 + +echo $x +until (( x == 4 )) +do + echo $x + x=4 +done + +echo $x + +# exponentiation +echo $(( 2**15 - 1)) +echo $(( 2**(16-1))) +echo $(( 2**16*2 )) +echo $(( 2**31-1)) +echo $(( 2**0 )) + +# {pre,post}-{inc,dec}rement and associated errors + +x=4 + +echo $x +echo $(( x++ )) +echo $x +echo $(( x-- )) +echo $x + +echo $(( --x )) +echo $x + +echo $(( ++x )) +echo $x + +echo $(( ++7 )) +echo $(( 7-- )) + +echo $(( --x=7 )) +echo $(( ++x=7 )) + +echo $(( x++=7 )) +echo $(( x--=7 )) + +echo $x + +echo $(( +7 )) +echo $(( -7 )) + +echo $(( ++7 )) +echo $(( --7 )) + +# combinations of expansions +echo $(( "`echo 1+1`" )) +echo $(( `echo 1+1` )) + +${THIS_SH} ./arith1.sub +${THIS_SH} ./arith2.sub +${THIS_SH} ./arith3.sub +${THIS_SH} ./arith4.sub + +# make sure arithmetic expansion handles ints > 2**31 - 1 using intmax_t +echo $(( 2147483645 + 4 )) + +# other tests using INTMAX_MIN and INTMAX_MAX that cause exceptions if not +# handled correctly -- problem through bash-4.2 +${THIS_SH} ./arith5.sub + +# problems with suppressing evaluation present through bash-4.2 +${THIS_SH} ./arith6.sub + +# problems with parsing arithmetic expressions containing colons that are +# part of word expansions such as substring extraction +${THIS_SH} ./arith7.sub + +# problems with evaluation of conditional expressions +${THIS_SH} ./arith8.sub + +x=4 +y=7 + +(( x=8 , y=12 )) + +echo $x $y + +# should be an error +(( x=9 y=41 )) + +# These are errors +unset b +echo $((a b)) +((a b)) + +n=42 +printf "%d\n" $n +printf "%i\n" $n +echo $(( 8#$(printf "%o\n" $n) )) +printf "%u\n" $n +echo $(( 16#$(printf "%x\n" $n) )) +echo $(( 16#$(printf "%X\n" $n) )) + +# these are errors +foo=1 +echo $(( 'foo' )) + + +# causes longjmp botches through bash-2.05b +a[b[c]d]=e diff --git a/tests/arith1.sub b/tests/arith1.sub new file mode 100644 index 0000000..43cae80 --- /dev/null +++ b/tests/arith1.sub @@ -0,0 +1,38 @@ +# test of redone post-increment and post-decrement code +echo $(( 4-- )) +echo $(( 4++ )) +echo $(( 4 -- )) +echo $(( 4 ++ )) + +(( array[0]++ )) +echo ${array} + +(( array[0] ++ )) +echo ${array} + +(( a++ )) +echo $a +(( a ++ )) +echo $a + +echo $(( a ++ + 4 )) +echo $a + +echo $(( a+++4 )) +echo $a + +echo $(( a---4 )) +echo $a + +echo $(( a -- + 4 )) +echo $a + +echo $(( a -- - 4 )) +echo $a + +(( ++ + 7 )) + +(( ++ )) +echo $(( +++7 )) +echo $(( ++ + 7 )) +(( -- )) diff --git a/tests/arith2.sub b/tests/arith2.sub new file mode 100644 index 0000000..7eac952 --- /dev/null +++ b/tests/arith2.sub @@ -0,0 +1,45 @@ +echo $(( --7 )) +echo $(( ++7 )) +echo $(( -- 7 )) +echo $(( ++ 7 )) + +((++array[0] )) +echo $array +(( ++ array[0] )) +echo $array + +(( ++a )) +echo $a +(( ++ a )) +echo $a + +(( --a )) +echo $a +(( -- a )) +echo $a + +echo $(( 4 + ++a )) +echo $a + +echo $(( 4+++a )) +echo $a + +echo $(( 4---a )) +echo $a + +echo $(( 4 - -- a )) +echo $a + +(( -- )) +echo $(( ---7 )) +echo $(( -- - 7 )) + +(( ++ )) +echo $(( ++7 )) +echo $(( ++ + 7 )) + +echo $(( ++-7 )) +echo $(( ++ - 7 )) + +echo $(( +--7 )) +echo $(( -- + 7 )) diff --git a/tests/arith3.sub b/tests/arith3.sub new file mode 100644 index 0000000..a510c73 --- /dev/null +++ b/tests/arith3.sub @@ -0,0 +1,45 @@ +RANDOM=42 +(( dice[RANDOM%6+1 + RANDOM%6+1]++ )) +echo ${dice[5]} + +(( ++dice[RANDOM%6+1 + RANDOM%6+1] )) +echo ${dice[6]} + +v=4 +DIND=20 + +(( dice[DIND%6 + 1]=v )) +echo ${dice[3]} + +RANDOM=42 + +(( dice[RANDOM%6+1 + RANDOM%6+1]+=v )) +echo ${dice[5]} + +(( dice[RANDOM%6+1 + RANDOM%6+1]-=v )) +echo ${dice[6]} + +(( dice[RANDOM%6+1 + RANDOM%6+1]+=2 )) +echo ${dice[11]} + +(( dice[RANDOM%6+1 + RANDOM%6+1]*=2 )) +echo ${dice[11]} + +unset dice1 dice2 +RANDOM=42 + +for i in {1..5000}; do ((dice1[$RANDOM%6+1 + $RANDOM%6+1]++)); done; +unset t; for i in ${dice1[@]}; do ((t+=i)); done; echo $t + +foo="${dice1[@]}" + +RANDOM=42 + +for i in {1..5000}; do ((dice2[RANDOM%6+1 + RANDOM%6+1]++)); done; +unset t; for i in ${dice2[@]}; do ((t+=i)); done; echo $t + +bar="${dice2[@]}" + +if [ "$foo" != "$bar" ]; then + echo "random sequences differ" +fi diff --git a/tests/arith4.sub b/tests/arith4.sub new file mode 100644 index 0000000..d74defa --- /dev/null +++ b/tests/arith4.sub @@ -0,0 +1,10 @@ +x=$(( !!1 )) +echo $x + +x=$(( -!+1 )) +echo $x + +x=$(( +--+!!0 )) +echo $x + +echo $(( !!+-+-~0 )) diff --git a/tests/arith5.sub b/tests/arith5.sub new file mode 100644 index 0000000..c8fdb5a --- /dev/null +++ b/tests/arith5.sub @@ -0,0 +1,56 @@ +intmax_max=$((2**63 - 1)) +intmax_min1=$((2**63)) +intmax_min2=$((-2**63)) + +case $intmax_max in +9223372036854775807) ;; +*) echo "warning: your machine does not support 64-bit arithmetic using intmax_t" 2>&1 ;; +esac + +# these are actually the same +echo $(( $intmax_min1 % -1 )) +echo $(( $intmax_min2 % -1 )) + +echo $(( $intmax_max % -1 )) + +lvalue=$intmax_min1 +(( lvalue%= -1 )) +echo $lvalue + +lvalue=$intmax_min2 +(( lvalue%= -1 )) +echo $lvalue + +lvalue=$intmax_max +(( lvalue%= -1 )) +echo $lvalue + +# and these +echo $(( $intmax_min1 / -1 )) +echo $(( $intmax_min2 / -1 )) + +lvalue=$intmax_min1 +(( lvalue /= -1 )) +echo $lvalue + +lvalue=$intmax_min2 +(( lvalue /= -1 )) +echo $lvalue + +echo $(( $intmax_min1 * -1 )) +echo $(( $intmax_min2 * -1 )) + +lvalue=$intmax_min1 +(( lvalue *= -1 )) +echo $lvalue + +lvalue=$intmax_min2 +(( lvalue *= -1 )) +echo $lvalue + +echo $(( -${intmax_min1} )) +echo $(( -${intmax_min2} )) + +foo1=$(( $intmax_max - 2 )) + +eval echo \{${foo1}..${intmax_max}\} diff --git a/tests/arith6.sub b/tests/arith6.sub new file mode 100644 index 0000000..630e917 --- /dev/null +++ b/tests/arith6.sub @@ -0,0 +1,52 @@ +function reorder +{ + (( x[1] < x && (x=x[1], x[1]=$x) )) + echo "${x[@]}" +} + +x=(123 456) +reorder +x=(456 123) +reorder + +unset x +unset -f reorder + +function reorder +{ + (( x[1] < x[0] && (x=x[1], x[1]=$x) )) + echo "${x[@]}" +} + +x=(123 456) +reorder +x=(456 123) +reorder + +unset x +unset -f reorder + +function reorder +{ + (( x[1] < x[0] && (x[0]=x[1], x[1]=$x) )) + echo "${x[@]}" +} + +x=(123 456) +reorder +x=(456 123) +reorder + +unset -f reorder + +n=0 ; (( (a[n]=++n)<7&&a[0])); echo "${a[@]:1}" + +n=0 a="(a[n]=++n)<7&&a[0]"; ((a[0])); echo "${a[@]:1}" + +n=0 a="(a[n]=n++)<7&&a"; ((a)); echo "${a[@]:1}" + +# bugs with lvalue caching and pointer aliasing through bash-4.2 +echo $(( a=(y[0] + y[1]) & 0xff, b=(y[2] + y[3]) & 0xff, a << 8 | b)) +echo $a, $b +((a = y[0], b = 1 )) +echo $a, $b diff --git a/tests/arith7.sub b/tests/arith7.sub new file mode 100644 index 0000000..1b73ba7 --- /dev/null +++ b/tests/arith7.sub @@ -0,0 +1,11 @@ +PARAM=abcdefg + +echo ${PARAM:1 ? 4 : 2} +echo ${PARAM:1 ? 4 : 2:1} + +echo ${PARAM: 4<5 ? 4 : 2} +echo ${PARAM: 5>4 ? 4 : 2:1} + +echo ${PARAM:${OFFSET:-0}} +OFFSET=4 +echo ${PARAM:${OFFSET:-0}} diff --git a/tests/arith8.sub b/tests/arith8.sub new file mode 100644 index 0000000..1ab0895 --- /dev/null +++ b/tests/arith8.sub @@ -0,0 +1,37 @@ +# problems with evaluation of wrong terms in conditional expressions through +# bash-4.4 + +a=0 x="a=1" +((0?x:0)) +echo $a +unset a x + +a=0 x="a=1" +((1?0:x)) +echo $a +unset a x + +a=0 x="a=1" +((0?(x):0)) +echo $a +unset a x + +a=0 x="a=1" +((0?$x:0)) +echo $a +unset a x + +a=0 x="a=1" +((0&&x)) +echo $a +unset a x + +a=0 x="a=1" +((1||x)) +echo $a +unset a x + +a=0 +((0?arr[a=1]:0)) +echo $a +unset a diff --git a/tests/array-at-star b/tests/array-at-star new file mode 100755 index 0000000..80f039d --- /dev/null +++ b/tests/array-at-star @@ -0,0 +1,120 @@ +# test the expansion of ${array[@]} and ${array[*]}, both quoted and +# unquoted. the expansions should be exactly analogous to the +# expansions of $@ and $* quoted and unquoted +A=(a b) + +recho "${A[*]}" + +# If IFS is null, the parameters are joined without separators +IFS='' +recho "${A[*]}" + +# If IFS is unset, the parameters are separated by spaces +unset IFS +recho "${A[*]}" + +recho "${A[@]}" +recho ${A[@]} + +IFS='/' +A=(bob 'tom dick harry' joe) +set ${A[*]} +recho $# +recho $1 +recho $2 +recho $3 + +A=(bob 'tom dick harry' joe) +set ${A[*]} +recho $# +recho $1 +recho $2 +recho $3 + +A=(bob 'tom dick harry' joe) +set ${A[@]} +recho $# +recho $1 +recho $2 +recho $3 + +A=(bob 'tom dick harry' joe) +set ${A[@]} +recho $# +recho $1 +recho $2 +recho $3 + +# according to POSIX.2, unquoted $* should expand to multiple words if +# $IFS is null, just like unquoted $@ +IFS='' +A=(bob 'tom dick harry' joe) +set "${A[*]}" +recho $# +recho $1 +recho $2 +recho $3 + +A=(bob 'tom dick harry' joe) +set ${A[*]} +recho $# +recho $1 +recho $2 +recho $3 + +A=(bob 'tom dick harry' joe) +set ${A[@]} +recho $# +recho $1 +recho $2 +recho $3 + +# if IFS is unset, the individual positional parameters are split on +# " \t\n" if $* or $@ are unquoted +unset IFS +A=(bob 'tom dick harry' joe) +set ${A[*]} +recho $# +recho $1 +recho $2 +recho $3 + +A=(bob 'tom dick harry' joe) +set ${A[@]} +recho $# +recho $1 +recho $2 +recho $3 + +# but not for "$@" or "$*" +A=(bob 'tom dick harry' joe) +set "${A[*]}" +recho $# +recho $1 +recho $2 +recho $3 + +A=(bob 'tom dick harry' joe) +set "${A[@]}" +recho $# +recho $1 +recho $2 +recho $3 + +# these should both expand the value of A to multiple words +A=(a b c d e) +IFS="" +recho ${A[@]} +recho "${A[@]}" + +# this example is straight from the POSIX.2 rationale and adapted to arrays +A=(foo bar bam) + +recho "${A[@]}" +recho "${A[*]}" + +unset IFS + +recho "${A[@]}" +recho ${A[@]} +recho "${A[*]}" diff --git a/tests/array.right b/tests/array.right new file mode 100644 index 0000000..834e568 --- /dev/null +++ b/tests/array.right @@ -0,0 +1,764 @@ + +./array.tests: line 15: syntax error near unexpected token `&' +./array.tests: line 15: `test=(first & second)' +1 +abcde +abcde +abcde bdef +abcde bdef +declare -a BASH_ARGC=() +declare -a BASH_ARGV=() +declare -a BASH_LINENO=([0]="0") +declare -a BASH_SOURCE=([0]="./array.tests") +declare -a DIRSTACK=() +declare -a FUNCNAME +declare -a a=([0]="abcde" [1]="" [2]="bdef") +declare -a b +declare -ar c +abcde bdef +abcde bdef +abcde +abcde +abcde + +bdef +hello world +11 +3 +bdef hello world test expression test 2 +./array.tests: line 79: readonly: `a[5]': not a valid identifier +declare -ar a=([1]="" [2]="bdef" [5]="hello world" [6]="test expression" [15]="test 2") +declare -ar c +declare -ar a=([1]="" [2]="bdef" [5]="hello world" [6]="test expression" [15]="test 2") +declare -ar c +readonly -a a=([1]="" [2]="bdef" [5]="hello world" [6]="test expression" [15]="test 2") +readonly -a c +a test +declare -a BASH_ARGC=() +declare -a BASH_ARGV=() +declare -a BASH_LINENO=([0]="0") +declare -a BASH_SOURCE=([0]="./array.tests") +declare -a DIRSTACK=() +declare -a FUNCNAME +declare -ar a=([1]="" [2]="bdef" [5]="hello world" [6]="test expression" [15]="test 2") +declare -a b=([0]="this" [1]="is" [2]="a" [3]="test" [4]="" [5]="/etc/passwd") +declare -ar c +declare -a d=([1]="" [2]="bdef" [5]="hello world" [6]="test" [9]="ninth element") +declare -a e=([0]="test") +declare -a f=([0]="" [1]="bdef" [2]="hello world" [3]="test" [4]="ninth element") +./array.tests: line 103: a: readonly variable +./array.tests: line 105: b[]: bad array subscript +./array.tests: line 106: b[*]: bad array subscript +this +./array.tests: line 109: c[-2]: bad array subscript +./array.tests: line 110: c: bad array subscript + +./array.tests: line 112: d[7]: cannot assign list to array member +./array.tests: line 114: []=abcde: bad array subscript +./array.tests: line 114: [*]=last: cannot assign to non-numeric index +./array.tests: line 114: [-65]=negative: bad array subscript +declare -a BASH_ARGC=() +declare -a BASH_ARGV=() +declare -a BASH_LINENO=([0]="0") +declare -a BASH_SOURCE=([0]="./array.tests") +declare -a DIRSTACK=() +declare -a FUNCNAME +declare -ar a=([1]="" [2]="bdef" [5]="hello world" [6]="test expression" [15]="test 2") +declare -a b=([0]="this" [1]="is" [2]="a" [3]="test" [4]="" [5]="/etc/passwd") +declare -ar c +declare -a d=([1]="test test") +declare -a f=([0]="" [1]="bdef" [2]="hello world" [3]="test" [4]="ninth element") +./array.tests: line 122: unset: ps1: not an array variable +./array.tests: line 126: declare: c: cannot destroy array variables in this way +this of +this is a test of read using arrays +this test +this is a test of arrays +declare -a BASH_ARGC=() +declare -a BASH_ARGV=() +declare -a BASH_LINENO=([0]="0") +declare -a BASH_SOURCE=([0]="./array.tests") +declare -a DIRSTACK=() +declare -a FUNCNAME +declare -ar a=([1]="" [2]="bdef" [5]="hello world" [6]="test expression" [15]="test 2") +declare -a b=([0]="this" [1]="is" [2]="a" [3]="test" [4]="" [5]="/etc/passwd") +declare -ar c +declare -a d=([1]="test test") +declare -a f=([0]="" [1]="bdef" [2]="hello world" [3]="test" [4]="ninth element") +declare -a rv=([0]="this" [1]="is" [2]="a" [3]="test" [4]="of" [5]="read" [6]="using" [7]="arrays") +abde +abde +bbb +efgh +wxyz +wxyz +./array.tests +a +b c +d +e f g +h +./array.tests +a +b c +d +e f g +h +/bin /usr/bin /usr/ucb /usr/local/bin . /sbin /usr/sbin +bin bin ucb bin . sbin sbin +bin +/ / / / / / +/ +argv[1] = <bin> +argv[1] = </> +argv[1] = <sbin> +argv[1] = </> +\bin \usr/bin \usr/ucb \usr/local/bin . \sbin \usr/sbin +\bin \usr\bin \usr\ucb \usr\local\bin . \sbin \usr\sbin +\bin \usr\bin \usr\ucb \usr\local\bin . \sbin \usr\sbin +4 -- 4 +7 -- 7 +55 +49 +6 -- 6 +42 14 44 +grep [ 123 ] * +6 7 9 +6 7 9 5 +length = 3 +value = new1 new2 new3 +./array.tests: line 242: narray: unbound variable +./array1.sub: line 1: syntax error near unexpected token `(' +./array1.sub: line 1: `printf "%s\n" -a a=(a 'b c')' +./array2.sub: line 1: declare: `[]=asdf': not a valid identifier +./array2.sub: line 2: a[]: bad array subscript +./array2.sub: line 4: syntax error near unexpected token `(' +./array2.sub: line 4: `declare -a ''=(a 'b c')' +9 +9 + + +7 8 9 +8 11 +8 11 +6 +6 +nordholz +8 +8 +8 + +a b c d e f g +for case if then else +<> < > ! +12 14 16 18 20 +4414758999202 +aaa bbb +./array.tests: line 292: syntax error near unexpected token `<>' +./array.tests: line 292: `metas=( <> < > ! )' +./array.tests: line 293: syntax error near unexpected token `<>' +./array.tests: line 293: `metas=( [1]=<> [2]=< [3]=> [4]=! )' +abc 3 +case 4 +abc case if then else 5 +abc case if then else 5 +0 +case 4 +case if then else 5 +case if then else 5 +argv[1] = <0> +argv[2] = <1> +argv[3] = <4> +argv[4] = <10> +argv[1] = <0> +argv[2] = <1> +argv[3] = <4> +argv[4] = <10> +argv[1] = <0> +argv[2] = <1> +argv[3] = <4> +argv[4] = <10> +argv[1] = <0 1 4 10> +include null element -- expect one +one +include unset element -- expect three five +three five +start at unset element -- expect five seven +five seven +too many elements -- expect three five seven +three five seven +positive offset - expect five seven +five seven +negative offset to unset element - expect seven +seven +positive offset 2 - expect seven +seven +negative offset 2 - expect seven +seven +out-of-range offset + +e +4 +1 4 7 10 +'b +b c +$0 +t +[3]=abcde r s t u v +e +9 +2 +a b c +argv[1] = <-iname 'a> +argv[2] = <-iname 'b> +argv[3] = <-iname 'c> +'hey' +hey +''hey +'hey' +argv[1] = <c> +argv[2] = <d> +argv[3] = <e> +argv[4] = <f> +argv[1] = <c d> +argv[2] = <e f> +argv[1] = <c d> +argv[2] = <e f> +argv[1] = <c d> +argv[2] = <e f> +argv[1] = <-iname 'abc> +argv[2] = <-iname 'def> +argv[1] = <-iname 'abc> +argv[2] = <-iname 'def> +argv[1] = <-iname> +argv[2] = <abc -iname def> +argv[1] = <-iname 'abc> +argv[2] = <-iname 'def> +argv[1] = <-iname> +argv[2] = <abc -iname def> +argv[1] = <-iname 'abc> +argv[2] = <-iname 'def> +argv[1] = <-iname 'abc> +argv[2] = <-iname 'def> +argv[1] = <-iname> +argv[2] = <abc -iname def> +*.* OK +1 +a1 2 3c +argv[1] = <var with spaces> +argv[1] = <var with spaces> +argv[1] = <var with spacesab> +argv[2] = <cd> +argv[3] = <ef> +argv[1] = <var with spacesab> +argv[2] = <cd> +argv[3] = <ef> +argv[1] = <var with spacesab> +argv[2] = <cd> +argv[3] = <ef> +argv[1] = <var with spacesab> +argv[2] = <cd> +argv[3] = <ef> +argv[1] = <var with spacesab> +argv[2] = <cd> +argv[3] = <ef> +argv[1] = <var with spacesab> +argv[2] = <cd> +argv[3] = <ef> +2 +argv[1] = <element1 with spaces> +argv[2] = <element2 with spaces> +argv[1] = <element1 with spaces> +argv[2] = <element2 with spaces> +nord!olz + +rdholz + +rdholz +rdho + + +argv[1] = <fooq//barq/> +argv[1] = <fooq> +argv[2] = <> +argv[3] = <barq> +argv[4] = <> +argv[1] = <foo!//bar!/> +argv[1] = <foo!> +argv[2] = <> +argv[3] = <bar!> +argv[4] = <> +argv[1] = <ooq//arq/> +argv[1] = <ooq> +argv[2] = <> +argv[3] = <arq> +argv[4] = <> +argv[1] = <Fooq//Barq/> +argv[1] = <Fooq> +argv[2] = <> +argv[3] = <Barq> +argv[4] = <> +argv[1] = <FOOQ//BARQ/> +argv[1] = <FOOQ> +argv[2] = <> +argv[3] = <BARQ> +argv[4] = <> +126 +127 +128 +argv[1] = <€> +argv[1] = <~> +argv[2] = <^?> +argv[3] = <€> +argv[1] = <~> +argv[2] = <^?> +argv[3] = <€> +argv[1] = <~> +argv[2] = <^?> +argv[3] = <€> +Monday Tuesday Wednesday Thursday Friday Saturday Sunday +Monday +Monday +Tuesday +Monday +Monday +Tuesday +Monday +Tuesday +Wednesday +Monday +Tuesday +Wednesday +monday, monday, tuesday +wednesday, wednesday, thursday +monday, monday, tuesday +Wednesday, Wednesday, Thursday +nday +esday +dnesday +nday +esday +dnesday +onday +uesday +ednesday +onday +uesday +ednesday +version[agent] +version.agent +version[agent] +version.agent +version[agent] foo[bar] +version.agent bowl +foo foobar] foo[bar] +bbb bleh bleh +ab] +bar +1 +1 +1 +1 +1 +1 +main main +function function +function function +declare -a x=([0]="0" [1]="1" [2]="2" [3]="3" [4]="4" [5]="5") +declare -a x=([0]="0" [1]="1" [2]="2" [3]="3" [4]="4") +declare -a x=([0]="0" [1]="1" [2]="2" [4]="4") +./array14.sub: line 11: unset: [-10]: bad array subscript +declare -a x=([0]="0" [1]="1" [2]="2" [3]="3" [4]="4") +declare -a x=([0]="0" [1]="1" [2]="2" [3]="3" [4]="4" [5]="five") +declare -a x=([0]="0" [1]="1" [2]="2" [3]="3" [4]="4" [5]="5") +declare -a x=([0]="0" [1]="1" [2]="2" [3]="3" [4]="4" [5]="foo") +declare -a x=([0]="0" [1]="1" [2]="2" [3]="3" [4]="4" [5]="5") +declare -a x=([0]="0" [1]="1" [2]="2" [3]="3" [4]="4four" [5]="5") +strlen(4four) = 5 +1 2 0 3 +1 2 0 3 +1 2 0 3 +1 2 0 3 +1 2 0 3 +foo index 1: ok +foo index 2: ok +foo: implicit reference to element 0: ok +foo: arithmetic evaluation: ok +bar: array with element zero unset: ok +bar: element zero: ok +qux: unset array: ok +qux: unset array element 0: ok +2 +2 +2 +2 +0 +0 +1 +./array17.sub: line 30: ~: syntax error: operand expected (error token is "~") +0 +0 +3 +3 +0 +0 +zero +zero +one +one +one +one +two +two +./array17.sub: line 76: ~ : syntax error: operand expected (error token is "~ ") +1 +argv[1] = <> +argv[2] = <> +argv[3] = <> +argv[1] = <bar> +argv[1] = <--> +argv[1] = <> +argv[1] = <qux> +argv[1] = <-> +argv[2] = <-> +argv[1] = < > +argv[1] = <> +argv[2] = <> +argv[3] = <> +argv[1] = <bar> +argv[1] = <--> +argv[1] = <> +argv[1] = <qux> +argv[1] = <-> +argv[2] = <-> +argv[1] = < > +declare -a foo=([0]="( zeroind )") +declare -a foo=([0]="zeroind") +declare -a foo=([0]="zeroind") +declare -a foo=([0]="[0]=bar") +declare -a foo=([0]="[0]=bar") +declare -a foo=([0]="[0]=bar") +declare -- a="(1 2 3)" +declare -a a=([0]="1" [1]="2" [2]="3") +./array19.sub: line 46: a: 1: must use subscript when assigning associative array +./array19.sub: line 46: a: 2: must use subscript when assigning associative array +./array19.sub: line 46: a: 3: must use subscript when assigning associative array +declare -A a=() +declare -- a="([0]=a [1]=b)" +declare -a a=([0]="a" [1]="b") +declare -A a=([1]="b" [0]="a" ) +declare -a var=([0]="[\$(echo" [1]="total" [2]="0)]=1" [3]="[2]=2]") +declare -a var=([0]="[\$(echo total 0)]=1 [2]=2]") +declare -a var=([0]="[\$(echo" [1]="total" [2]="0)]=1" [3]="[2]=2]") +./array19.sub: line 81: total 0: syntax error in expression (error token is "0") +declare -a var=() +declare -al foo=([0]="abcde" [1]="two" [2]="three") +declare -al foo=([0]="abcde") +declare -al ar=([0]="one" [1]="two" [2]="three") +declare -a a=([2]="foo") +declare -a a=([2]="foo") +declare -a a=([1]="(var)" [2]="foo") +./array19.sub: line 120: warning: a[1]=(var): quoted compound array assignment deprecated +declare -a a=([1]="(var)") +declare -a a=([0]="1" [1]="2" [2]="(1 2 3)") +declare -a a=([0]="1" [1]="2" [2]="(1 2 3)") +declare -a a=([0]="1" [1]="2" [2]="3") +declare -a a=([0]="1" [1]="2" [2]="3") +declare -a a=([0]="1" [1]="2" [2]="3") +declare -- a="a b" +declare -- b="/scratch/bash" +declare -- c="(1 2)" +declare -- d="(\$a)" +declare -- e="(\$(echo Darwin))" +declare -a a=([0]="a b") +declare -a b=([0]="/scratch/bash") +declare -a c=([0]="1" [1]="2") +declare -a d=([0]="a" [1]="b") +declare -a e=([0]="Darwin") +./array19.sub: line 166: c: 1: must use subscript when assigning associative array +./array19.sub: line 166: c: 2: must use subscript when assigning associative array +./array19.sub: line 166: d: $a: must use subscript when assigning associative array +./array19.sub: line 166: e: $(echo Darwin): must use subscript when assigning associative array +declare -A a=([0]="a b" ) +declare -A b=([0]="/scratch/bash" ) +declare -A c=() +declare -A d=() +declare -A e=() +a+b+c +x+b+c +a+b+c +x+b+c +argv[1] = <a+b+c+d+e+f> +argv[1] = <x+b+c+d+e+f> +a b c +x b c +a b c +x b c +declare -a a=([1]="2" [2]="3" [3]="4") +abcd +unset +./array21.sub: line 17: typeset: a: not found +./array21.sub: line 20: typeset: A: not found +declare -a a=() +declare -A A=() +declare -a foo=([0]="1" [1]="(4 5 6)" [2]="3") +a1 +argv[1] = <> +argv[2] = <> +a2 +argv[1] = <y> +argv[1] = <z> +a3 +argv[1] = <> +argv[2] = <x> +a4 +argv[1] = <y> +p1 +argv[1] = <> +argv[2] = <> +p2 +argv[1] = <> +argv[2] = <x> +p3 +argv[1] = <y> +<X> <X> <X> <X> +<X> <X> <X> <X> +./array23.sub: line 9: $( echo >&2 foo ) : syntax error: operand expected (error token is "$( echo >&2 foo ) ") +./array23.sub: line 10: $( echo >&2 foo ) : syntax error: operand expected (error token is "$( echo >&2 foo ) ") +foo +0 +foo +foo +foo +6 +./array23.sub: line 21: $( echo >&2 foo ): syntax error: operand expected (error token is "$( echo >&2 foo )") +./array23.sub: line 22: $( echo >&2 foo ): syntax error: operand expected (error token is "$( echo >&2 foo )") +0 +0 +0 +IFS=: ${var-$*} +abc +def ghi +jkl +abc +def ghi +jkl +---- +IFS=: ${var=$*} +abc +def ghi +jkl +var=abc:def ghi:jkl +abc +def ghi +jkl +var=abc:def ghi:jkl +---- +IFS=: ${var+$*} +abc +def ghi +jkl +abc +def ghi +jkl +---- +IFS= ${var-$*} +abc +def ghi +jkl +abc +def ghi +jkl +---- +IFS= ${var=$*} +abcdef ghijkl +var=abcdef ghijkl +abcdef ghijkl +var=abcdef ghijkl +---- +IFS= ${var+$*} +abc +def ghi +jkl +abc +def ghi +jkl +1. indexed: +reference: +1. 0 +./array25.sub: line 11: ' ': syntax error: operand expected (error token is "' '") +3. 0 +4. 0 +5. 0 +6. 0 +assignment: +1.declare -a a=([0]="10" [1]="1") +2.declare -a a=([0]="11" [1]="1") +3.declare -a a=([0]="12" [1]="1") +4.declare -a a=([0]="13" [1]="1") +arithmetic: +1.declare -a a=([0]="10" [1]="1") +2.declare -a a=([0]="11" [1]="1") +3.declare -a a=([0]="12" [1]="1") +4.declare -a a=([0]="13" [1]="1") +5.declare -a a=([0]="10" [1]="1") +6.declare -a a=([0]="11" [1]="1") +7.declare -a a=([0]="12" [1]="1") +8.declare -a a=([0]="13" [1]="1") +2. associative: +reference: +1. +2. +3. +4. +5. +6. +assignment: +1.declare -A a=([1]="1" [0]="0" [" "]="10" ) +2.declare -A a=([1]="1" [0]="0" [" "]="11" ) +3.declare -A a=([1]="1" [0]="0" [" "]="12" ) +4.declare -A a=([1]="1" [0]="0" [" "]="13" ) +arithmetic: +1.declare -A a=([1]="1" [0]="0" [" "]="10" ) +2.declare -A a=([1]="1" [0]="0" [" "]="11" ) +3.declare -A a=([1]="1" [0]="0" [" "]="12" ) +4.declare -A a=([1]="1" [0]="0" [" "]="13" ) +5.declare -A a=([1]="1" [0]="0" [" "]="10" ) +6.declare -A a=([1]="1" [0]="0" [" "]="10" ["\" \""]="11" ) +7.declare -A a=([1]="1" [0]="0" [" "]="12" ["\" \""]="11" ) +8.declare -A a=([1]="1" [0]="0" [" "]="12" ["\" \""]="13" ) +argv[1] = <aa> +argv[2] = <bb> +argv[1] = <aa> +argv[2] = <bb> +argv[1] = <aa> +argv[2] = <bb> +argv[1] = <aa> +argv[2] = <bb> +argv[1] = <aa> +argv[2] = <bb> +argv[3] = <aa> +argv[4] = <bb> +argv[1] = <aa> +argv[2] = <bb> +argv[3] = <aa> +argv[4] = <bb> +argv[1] = <aa+bb> +argv[2] = <aa+bb> +argv[1] = <aa> +argv[2] = <bb> +argv[3] = <aa> +argv[4] = <bb> +argv[1] = <xa> +argv[2] = <bb> +argv[1] = <xa> +argv[2] = <bb> +argv[1] = <xa> +argv[2] = <bb> +argv[1] = <xa> +argv[2] = <bb> +argv[1] = <xa> +argv[2] = <bb> +argv[1] = <xa> +argv[2] = <bb> +argv[1] = <xa+bb> +argv[1] = <xa+bb> +argv[1] = <xa+bb> +argv[2] = <xa+bb> +argv[1] = <bb> +argv[2] = <xa> +argv[1] = <bb> +argv[2] = <xa> +argv[1] = <bb> +argv[2] = <xa> +argv[1] = <bb+xa> +argv[1] = <xa> +argv[2] = <bb> +argv[1] = <xa> +argv[2] = <bb> +argv[1] = <xa> +argv[2] = <bb> +argv[1] = <xa> +argv[2] = <bb> +argv[1] = <xa> +argv[2] = <bb> +argv[1] = <xa> +argv[2] = <bb> +argv[1] = <xabb> +argv[1] = <xabb> +argv[1] = <xabb> +argv[2] = <xabb> +argv[1] = <bb> +argv[2] = <xa> +argv[1] = <bb> +argv[2] = <xa> +argv[1] = <bb> +argv[2] = <xa> +argv[1] = <bbxa> +argv[1] = <aa> +argv[2] = <bb> +argv[1] = <aa> +argv[2] = <bb> +argv[1] = <aa> +argv[2] = <bb> +argv[1] = <aa> +argv[2] = <bb> +argv[1] = <aa> +argv[2] = <bb> +argv[3] = <aa> +argv[4] = <bb> +argv[1] = <aa> +argv[2] = <bb> +argv[3] = <aa> +argv[4] = <bb> +argv[1] = <aa+bb> +argv[2] = <aa+bb> +argv[1] = <aa+bb> +argv[2] = <aa+bb> +argv[1] = <aa> +argv[2] = <bb> +argv[3] = <aa> +argv[4] = <bb> +argv[1] = <bb> +argv[2] = <aa> +argv[1] = <bb> +argv[2] = <aa> +argv[1] = <bb> +argv[2] = <aa> +argv[1] = <bb+aa> +argv[1] = <a> +argv[2] = <b> +argv[1] = <a> +argv[2] = <b> +argv[1] = <a> +argv[2] = <b> +argv[3] = <a> +argv[4] = <b> +argv[1] = <a+b> +argv[2] = <a+b> +argv[1] = <a> +argv[2] = <b> +argv[3] = <a> +argv[4] = <b> +argv[1] = <b> +argv[2] = <a> +argv[1] = <b> +argv[2] = <a> +argv[1] = <b> +argv[2] = <a> +argv[1] = <b+a> +7 +./array27.sub: line 11: a[]]=7 : syntax error: invalid arithmetic operator (error token is "]=7 ") +declare -A A=([$'\t']="2" [" "]="2" ) +./array27.sub: line 23: ((: A[]]=2 : syntax error: invalid arithmetic operator (error token is "]=2 ") +declare -A A=([$'\t']="2" ["*"]="2" [" "]="2" ["@"]="2" ) +./array27.sub: line 32: A[]]: bad array subscript +declare -A A=([$'\t']="X" ["*"]="X" [" "]="X" ["@"]="X" ) +./array27.sub: line 40: A[]]: bad array subscript +declare -A A=([$'\t']="X" ["*"]="X" [" "]="X" ["@"]="X" ) +./array27.sub: line 48: declare: `A[]]=X': not a valid identifier +declare -A A=(["*"]="X" ["@"]="X" ) +./array27.sub: line 56: declare: `A[]]=X': not a valid identifier +./array27.sub: line 56: A[*]: bad array subscript +./array27.sub: line 56: A[@]: bad array subscript +declare -A A diff --git a/tests/array.tests b/tests/array.tests new file mode 100644 index 0000000..afd3df5 --- /dev/null +++ b/tests/array.tests @@ -0,0 +1,408 @@ +# this is needed so that the bad assignments (b[]=bcde, for example) do not +# cause fatal shell errors when in posix mode +set +o posix + +set +a +# The calls to egrep -v are to filter out builtin array variables that are +# automatically set and possibly contain values that vary. + +# first make sure we handle the basics +x=() +echo ${x[@]} +unset x + +# this should be an error +test=(first & second) +echo $? +unset test + +# make sure declare -a converts an existing variable to an array +unset a +a=abcde +declare -a a +echo ${a[0]} +if [ "$a" != "${a[0]}" ]; then + echo 'array.tests: $a and $a[0] array mismatch' +fi + +unset a +a=abcde +a[2]=bdef + +unset b +declare -a b[256] + +unset c[2] +unset c[*] + +a[1]= + +_ENV=/bin/true +x=${_ENV[(_$-=0)+(_=1)-_${-%%*i*}]} + +declare -r c[100] + +echo ${a[0]} ${a[4]} +echo ${a[@]} + +echo ${a[*]} + +# this should print out values, too +declare -a | egrep -v '(BASH_VERSINFO|PIPESTATUS|GROUPS)' + +unset a[7] +echo ${a[*]} + +unset a[4] +echo ${a[*]} + +echo ${a} +echo "${a}" +echo $a + +unset a[0] +echo ${a} + +echo ${a[@]} + +a[5]="hello world" +echo ${a[5]} +echo ${#a[5]} + +echo ${#a[@]} + +a[4+5/2]="test expression" +declare a["7 + 8"]="test 2" +a[7 + 8]="test 2" +echo ${a[@]} + +readonly a[5] +readonly a +# these two lines should output `declare' commands +readonly -a | egrep -v '(BASH_VERSINFO|PIPESTATUS|GROUPS)' +declare -ar | egrep -v '(BASH_VERSINFO|PIPESTATUS|GROUPS)' +# this line should output `readonly' commands, even for arrays +set -o posix +readonly -a | egrep -v '(BASH_VERSINFO|PIPESTATUS|GROUPS)' +set +o posix + +declare -a d='([1]="" [2]="bdef" [5]="hello world" "test")' +d[9]="ninth element" + +declare -a e[10]=test # this works in post-bash-2.05 versions +declare -a e[10]='(test)' + +pass=/etc/passwd +declare -a f='("${d[@]}")' +b=([0]=this [1]=is [2]=a [3]=test [4]="$PS1" [5]=$pass) + +echo ${b[@]:2:3} + +declare -pa | egrep -v '(BASH_VERSINFO|PIPESTATUS|GROUPS)' + +a[3]="this is a test" + +b[]=bcde +b[*]=aaa +echo ${b[ ]} + +c[-2]=4 +echo ${c[-4]} + +d[7]=(abdedfegeee) + +d=([]=abcde [1]="test test" [*]=last [-65]=negative ) + +unset d[12] +unset e[*] + +declare -a | egrep -v '(BASH_VERSINFO|PIPESTATUS|GROUPS)' + +ps1='hello' +unset ps1[2] +unset ${ps1[2]} + +declare +a ps1 +declare +a c + +# the prompt should not print when using a here doc +read -p "array test: " -a rv <<! +this is a test of read using arrays +! + +echo ${rv[0]} ${rv[4]} +echo ${rv[@]} + +# the variable should be converted to an array when `read -a' is done +vv=1 +read -a vv <<! +this is a test of arrays +! +echo ${vv[0]} ${vv[3]} +echo ${vv[@]} +unset vv + +declare -a | egrep -v '(BASH_VERSINFO|PIPESTATUS|GROUPS)' + +export rv +#set + +x[4]=bbb +x=abde +echo $x +echo ${x[0]} +echo ${x[4]} +echo efgh | ( read x[1] ; echo ${x[1]} ) +echo wxyz | ( declare -a x ; read x ; echo $x ; echo ${x[0]} ) + +# Make sure that arrays can be used to save the positional paramters verbatim +set -- a 'b c' d 'e f g' h + +ARGV=( [0]=$0 "$@" ) + +for z in "${ARGV[@]}" +do + echo "$z" +done + +echo "$0" +for z in "$@" +do + echo "$z" +done + +# do various pattern removal and length tests +XPATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:.:/sbin:/usr/sbin + +xpath=( $( IFS=: ; echo $XPATH ) ) + +echo ${xpath[@]} +echo ${xpath[@]##*/} +echo ${xpath[0]##*/} +echo ${xpath[@]%%[!/]*} +echo ${xpath[0]%%[!/]*} +recho ${xpath##*/} +recho ${xpath%%[!/]*} +recho ${xpath[5]##*/} +recho ${xpath[5]%%[!/]*} + +# let's try to make it a DOS-style path + +zecho "${xpath[@]/\//\\}" +zecho "${xpath[@]//\//\\}" +zecho "${xpath[@]//[\/]/\\}" + +# length of the first element of the array, since array without subscript +# is equivalent to referencing first element +echo ${#xpath} -- ${#xpath[0]} + +# number of elements in the array +nelem=${#xpath[@]} +echo ${#xpath[@]} -- $nelem + +# total length of all elements in the array, including space separators +xx="${xpath[*]}" +echo ${#xx} + +# total length of all elements in the array +xx=$( IFS='' ; echo "${xpath[*]}" ) +echo ${#xx} + +unset xpath[nelem-1] + +nelem=${#xpath[@]} +echo ${#xpath[@]} -- $nelem + +# arrays and things that look like index assignments +array=(42 [1]=14 [2]=44) + +array2=(grep [ 123 ] \*) + +echo ${array[@]} +echo "${array2[@]}" + +# arrays and implicit arithmetic evaluation +declare -i -a iarray + +iarray=( 2+4 1+6 7+2 ) +echo ${iarray[@]} + +iarray[4]=4+1 +echo ${iarray[@]} + +# make sure assignment using the compound assignment syntax removes all +# of the old elements from the array value +barray=(old1 old2 old3 old4 old5) +barray=(new1 new2 new3) +echo "length = ${#barray[@]}" +echo "value = ${barray[*]}" + +# make sure the array code behaves correctly with respect to unset variables +set -u +( echo ${#narray[4]} ) + +${THIS_SH} ./array1.sub +${THIS_SH} ./array2.sub + +# some old bugs and ksh93 compatibility tests +${THIS_SH} ./array3.sub + +# some compound assingment parsing problems that showed up in bash-3.1-release +${THIS_SH} ./array4.sub + +set +u +cd ${TMPDIR:=/tmp} + +touch 1=bar +foo=([10]="bar") +echo ${foo[0]} +rm 1=bar + +cd $OLDPWD + +foo=(a b c d e f g) +echo ${foo[@]} + +# quoted reserved words are ok +foo=(\for \case \if \then \else) +echo ${foo[@]} + +# quoted metacharacters are ok +foo=( [1]='<>' [2]='<' [3]='>' [4]='!' ) +echo ${foo[@]} + +# numbers are just words when not in a redirection context +foo=( 12 14 16 18 20 ) +echo ${foo[@]} + +foo=( 4414758999202 ) +echo ${foo[@]} + +# this was a bug in all versions of bash 2.x up to and including bash-2.04 +declare -a ddd=(aaa +bbb) +echo ${ddd[@]} + +# errors until post-bash-2.05a; now reserved words are OK +foo=(a b c for case if then else) + +foo=(for case if then else) + +# errors +metas=( <> < > ! ) +metas=( [1]=<> [2]=< [3]=> [4]=! ) + +# various expansions that didn't really work right until post-bash-2.04 +foo='abc' +echo ${foo[0]} ${#foo[0]} +echo ${foo[1]} ${#foo[1]} +echo ${foo[@]} ${#foo[@]} +echo ${foo[*]} ${#foo[*]} + +foo='' +echo ${foo[0]} ${#foo[0]} +echo ${foo[1]} ${#foo[1]} +echo ${foo[@]} ${#foo[@]} +echo ${foo[*]} ${#foo[*]} + +# new expansions added after bash-2.05b +x[0]=zero +x[1]=one +x[4]=four +x[10]=ten + +recho ${!x[@]} +recho "${!x[@]}" +recho ${!x[*]} +recho "${!x[*]}" + +# sparse array tests for code fixed in bash-3.0 +unset av +av[1]='one' +av[2]='' + +av[3]=three +av[5]=five +av[7]=seven + +echo include null element -- expect one +echo ${av[@]:1:2} # what happens when we include a null element? +echo include unset element -- expect three five +echo ${av[@]:3:2} # what happens when we include an unset element? +echo start at unset element -- expect five seven +echo ${av[@]:4:2} # what happens when we start at an unset element? + +echo too many elements -- expect three five seven +echo ${av[@]:3:5} # how about too many elements? + +echo positive offset - expect five seven +echo ${av[@]:5:2} +echo negative offset to unset element - expect seven +echo ${av[@]: -2:2} + +echo positive offset 2 - expect seven +echo ${av[@]: 6:2} +echo negative offset 2 - expect seven +echo ${av[@]: -1:2} + +echo out-of-range offset +echo ${av[@]:12} + +# parsing problems and other inconsistencies not fixed until post bash-3.0 +unset x +declare -a x=(')' $$) +[ ${x[1]} -eq $$ ] || echo bad + +unset x +declare -a x=(a b c d e) +echo ${x[4]} + +z=([1]=one [4]=four [7]=seven [10]=ten) + +echo ${#z[@]} + +echo ${!z[@]} + +unset x +declare -a x=(a \'b c\') + +echo "${x[1]}" + +unset x +declare -a x=(a 'b c') + +echo "${x[1]}" + +unset x +declare -a x=($0) +[ "${x[@]}" = $0 ] || echo double expansion of \$0 +declare -a x=(\$0) +echo "${x[@]}" + +# tests for bash-3.1 problems +${THIS_SH} ./array5.sub + +# tests for post-bash-3.2 problems, most fixed in bash-3.2 patches +${THIS_SH} ./array6.sub +${THIS_SH} ./array7.sub + +${THIS_SH} ./array8.sub +${THIS_SH} ./array9.sub +${THIS_SH} ./array10.sub +${THIS_SH} ./array11.sub +${THIS_SH} ./array12.sub +${THIS_SH} ./array13.sub +${THIS_SH} ./array14.sub +${THIS_SH} ./array15.sub +${THIS_SH} ./array16.sub +${THIS_SH} ./array17.sub +${THIS_SH} ./array18.sub +${THIS_SH} ./array19.sub +${THIS_SH} ./array20.sub +${THIS_SH} ./array21.sub +${THIS_SH} ./array22.sub +${THIS_SH} ./array23.sub +${THIS_SH} ./array24.sub +${THIS_SH} ./array25.sub +${THIS_SH} ./array26.sub +${THIS_SH} ./array27.sub diff --git a/tests/array1.sub b/tests/array1.sub new file mode 100644 index 0000000..86e9332 --- /dev/null +++ b/tests/array1.sub @@ -0,0 +1 @@ +printf "%s\n" -a a=(a 'b c') diff --git a/tests/array10.sub b/tests/array10.sub new file mode 100644 index 0000000..6d5a94c --- /dev/null +++ b/tests/array10.sub @@ -0,0 +1,52 @@ +days=({Mon,Tues,Wednes,Thurs,Fri,Satur,Sun}day) +echo ${days[@]} + +typeset -i count + +count=0 +echo ${days[${count}]} +echo ${days[$((count++))]} +echo ${days[$((count++))]} + +count=0 +echo ${days[count]} +echo ${days[count++]} +echo ${days[count++]} + +count=0 +echo ${days[$((count++))]/foo/bar} +echo ${days[$((count++))]/foo/bar} +echo ${days[$((count++))]/foo/bar} + +count=0 +echo ${days[count++]/foo/bar} +echo ${days[count++]/foo/bar} +echo ${days[count++]/foo/bar} + +count=0 +echo "${days[${count}],,}, ${days[$((count++))],,}, ${days[$((count++))],,}" +echo "${days[${count}],,}, ${days[$((count++))],,}, ${days[$((count++))],,}" + +count=0 +echo "${days[${count}],,}, ${days[$((count++))],,}, ${days[$((count++))],,}" +echo "${days[${count}]/foo/bar}, ${days[$((count++))]/foo/bar}, ${days[$((count++))]/foo/bar}" + +count=0 +echo ${days[$((count++))]:2} +echo ${days[$((count++))]:2} +echo ${days[$((count++))]:2} + +count=0 +echo ${days[count++]:2} +echo ${days[count++]:2} +echo ${days[count++]:2} + +count=0 +echo ${days[$((count++))]#?} +echo ${days[$((count++))]#?} +echo ${days[$((count++))]#?} + +count=0 +echo ${days[count++]#?} +echo ${days[count++]#?} +echo ${days[count++]#?} diff --git a/tests/array11.sub b/tests/array11.sub new file mode 100644 index 0000000..c4f8cad --- /dev/null +++ b/tests/array11.sub @@ -0,0 +1,35 @@ +# problems with associative array keys with ] and unbalanced [ ] +# fixed after bash-4.2 + +declare -A foo + +foo=(["version[agent]"]=version.agent) + +echo ${!foo[@]} +echo ${foo[@]} + +unset foo +declare -A foo +foo["version[agent]"]=version.agent + +echo ${!foo[@]} +echo ${foo[@]} + +declare foo["foo[bar]"]=bowl + +echo ${!foo[@]} +echo ${foo[@]} + +declare -A array2["foo[bar]"]=bleh + +array2["foobar]"]=bleh +array2["foo"]=bbb + +echo ${!array2[@]} +echo ${array2[@]} + +declare -A foo +foo=( ['ab]']=bar ) + +echo ${!foo[@]} +echo ${foo[@]} diff --git a/tests/array12.sub b/tests/array12.sub new file mode 100644 index 0000000..6571138 --- /dev/null +++ b/tests/array12.sub @@ -0,0 +1,21 @@ +# problems with fix for posix interp 217 introduced in bash-4.2 + +declare -ax array +array[$(( $( echo -n 1001 ) - 1001 ))]=1 + +echo ${array[0]} +echo ${array[@]} + +unset 'array[0]' +array[$( echo -n 1001 ) - 1001 ]=1 +echo ${array[0]} + +unset 'array[0]' +array[$(( 1001 - $( echo -n 1001 ) ))]=1 +echo ${array[0]} +array[$(( 1001 - $( echo -n 1001 ) ))]=1 +echo ${array[0]} + +unset 'array[0]' +array[1001 - $( echo -n 1001 )]=1 +echo ${array[0]} diff --git a/tests/array13.sub b/tests/array13.sub new file mode 100644 index 0000000..736f210 --- /dev/null +++ b/tests/array13.sub @@ -0,0 +1,13 @@ +#!/bin/bash + +func1(){ +declare -g variable='function' +declare -g -a array=(function) +echo ${variable} ${array[@]} +} + +declare -g variable='main' +declare -g -a array=(main) +echo ${variable} ${array[@]} +func1 +echo ${variable} ${array[@]} diff --git a/tests/array14.sub b/tests/array14.sub new file mode 100644 index 0000000..7715169 --- /dev/null +++ b/tests/array14.sub @@ -0,0 +1,30 @@ +# start at a test suite for negative indexed array subscripts -- post bash-4.2 +x=( 0 1 2 3 4 5) +declare -p x + +unset 'x[-1]' +declare -p x + +unset 'x[-2]' +declare -p x + +unset 'x[-10]' + +x[-2]=3 +declare -p x + +x+=( five ) +declare -p x +x[-1]=5 +declare -p x + +x+=( [-1]=foo ) +declare -p x + +x[-1]=5 +declare -p x + +x[-2]+=four +declare -p x + +echo "strlen(${x[-2]})" = ${#x[-2]} diff --git a/tests/array15.sub b/tests/array15.sub new file mode 100644 index 0000000..b056ccb --- /dev/null +++ b/tests/array15.sub @@ -0,0 +1,24 @@ +# fixes for make_internal_declare not handling integer attribute for arrays +declare -ai -g foo=(1 2 xx 3) +echo "${foo[@]}" + +unset foo +declare -ai -g foo='(1 2 xx 3)' +echo "${foo[@]}" + +unset foo +declare -ia -g foo=(1 2 xx 3) +echo "${foo[@]}" + +unset foo +declare -ia -g foo='(1 2 xx 3)' +echo "${foo[@]}" + +unset foo +func() +{ + declare -ai -g foo=(1 2 xx 3) +} + +func +echo "${foo[@]}" diff --git a/tests/array16.sub b/tests/array16.sub new file mode 100644 index 0000000..10024bc --- /dev/null +++ b/tests/array16.sub @@ -0,0 +1,21 @@ +foo[0]=a +foo[1]=b + +[[ -v foo[1] ]] && echo foo index 1: ok +[[ -v foo[2] ]] || echo foo index 2: ok + +[[ -v foo ]] && echo foo: implicit reference to element 0: ok + +typeset -i foo + +[[ -v foo[1] ]] && echo foo: arithmetic evaluation: ok + +typeset -a bar +bar[1]=set + +[[ -v bar ]] || echo bar: array with element zero unset: ok +[[ -v bar[0] ]] || echo bar: element zero: ok + +typeset -a qux +[[ -v qux ]] || echo qux: unset array: ok +[[ -v qux[0] ]] || echo qux: unset array element 0: ok diff --git a/tests/array17.sub b/tests/array17.sub new file mode 100644 index 0000000..302dc03 --- /dev/null +++ b/tests/array17.sub @@ -0,0 +1,78 @@ +# this shows the expansions an array subscript undergoes before being run +# through the arithmetic evaluator + +b=(0 1 2 3) + +# array subscripts undergo variable expansion +a=2 +echo ${b[$a]} + +# array subscripts undergo command substitution +echo ${b[$(echo 2)]} + +c='1+1' +d='1-+1' + +# array subscripts are expanded and the expanded value is treated as an +# expression +echo ${b[$c]} +echo ${b[c]} + +echo ${b[$d]} +echo ${b[d]} + +# array subscripts undergo parameter expansion +set -- 1 2 3 +echo ${b[$1]} + +# array subscripts undergo tilde expansion +HOME=2 +echo ${b[~]} + +# array subscripts undergo word splitting -- bug in bash versions through 4.3 + +x='b[$d]' +IFS=- +echo $((x)) +IFS=$' \t\n' + +set -- 1 + 2 + +x='d' +IFS=- +echo $((x)) +IFS=$' \t\n' + +# start of quoting tests; make sure that subscript is treated as double +# quoted (inhibits word splitting) but that double quotes are silently +# discarded through quote removal + +echo $(( $@ )) +echo "$(( $@ ))" + +echo $(( "$x" )) +echo $(( "x" )) + +unset a foo bar +a=(zero one two three four five six seven eight nine ten) + +echo ${a[0]} +echo ${a["0"]} + +foo=1 +echo ${a[$foo]} +echo ${a["$foo"]} +echo ${a[foo]} +echo ${a["foo"]} + +bar=2 +echo ${a[" $bar "]} +echo ${a[" bar "]} + +# tilde expansion is performed by array subscript expansion but not by posix +# style arithmetic expansion + +HOME=2 +echo $(( ~ )) + + diff --git a/tests/array18.sub b/tests/array18.sub new file mode 100644 index 0000000..675b194 --- /dev/null +++ b/tests/array18.sub @@ -0,0 +1,34 @@ +# arrays referenced using @ subscript and positional parameters should behave +# the same way + +foo=(0 0 0); [[ -z ${foo[@]#0} ]]; echo $? + +recho "${foo[@]#0}" +bar=${foo[@]#0} +recho bar +recho $bar +recho -$bar- +recho "$bar" + +qux="${foo[@]#0}" +recho qux +recho $qux +recho -$qux- +recho "$qux" + +unset foo qux bar + +set -- 0 0 0 + +recho "${@#0}" +bar=${@#0} +recho bar +recho $bar +recho -$bar- +recho "$bar" + +qux="${@#0}" +recho qux +recho $qux +recho -$qux- +recho "$qux" diff --git a/tests/array19.sub b/tests/array19.sub new file mode 100644 index 0000000..adfad82 --- /dev/null +++ b/tests/array19.sub @@ -0,0 +1,167 @@ +# tests for changes to declare and assignment statement arguments post-bash-4.3 + +unset foo l a b + +l="( zeroind )" + +unset foo +declare -a foo +foo="$l" +declare -p foo + +unset foo +declare -a foo="$l" +declare -p foo + +unset foo +declare -a foo=$l +declare -p foo + +b='[0]=bar' + +unset foo +declare -a foo="$b" +declare -p foo + +unset foo +declare -a foo=("$b") +declare -p foo + +unset foo +declare -a foo=($b) +declare -p foo + +unset a + +declare a='(1 2 3)' +declare -p a +unset a + +declare -a a +declare a='(1 2 3)' +declare -p a +unset a + +declare -A a +declare a='(1 2 3)' +declare -p a +unset a + +declare a='([0]=a [1]=b)' +declare -p a +unset a + +declare -a a +declare a='([0]=a [1]=b)' +declare -p a +unset a + +declare -A a +declare a='([0]=a [1]=b)' +declare -p a +unset a +unset var value + +value='[$(echo total 0)]=1 [2]=2]' + +unset var +declare -a var +var=($value) +declare -p var + +unset var +declare -a var=("$value") +declare -p var + +unset var +declare -a var=($value) +declare -p var + +unset var +declare -a var="($value)" +declare -p var +unset foo value + +value="AbCdE" + +declare -a foo +foo=( one two three ) + +declare -l foo="$value" +declare -p foo + +unset foo +value='(AbCdE)' + +declare -a foo +foo=( one two three ) + +declare -l foo="$value" +declare -p foo +unset ar +declare -a ar=(ONE TWO THREE) +declare -al ar=(${ar[@]}) +declare -p ar +unset a + +declare -a a +a[2]=foo +declare -p a + +unset a +declare -a a +declare a[2]=foo +declare -p a + +declare a[1]='(var)' +declare -p a + +unset a +declare a[1]='(var)' +declare -p a +unset a + +a=(1 2 3) +a[2]='(1 2 3)' + +declare -p a + +unset a +a=(1 2 3) +declare a[2]='(1 2 3)' + +declare -p a + +unset a +a=(1 2 3) +declare a='(1 2 3)' + +declare -p a + +unset a +a=(1 2 3) +declare 'a=(1 2 3)' + +declare -p a + +unset a +declare -a a='(1 2 3)' + +declare -p a +unset a b c d e x y + +HOME=/scratch/bash +x='a b' +y='($(echo Darwin))' + +declare a=$x b=~ c='(1 2)' d='($a)' e=$y + +declare -p a b c d e + +unset a b c d e +declare -a a=$x b=~ c='(1 2)' d='($a)' e=$y +declare -p a b c d e + +unset a b c d e +declare -A a=$x b=~ c='(1 2)' d='($a)' e=$y +declare -p a b c d e diff --git a/tests/array2.right b/tests/array2.right new file mode 100644 index 0000000..b5145c2 --- /dev/null +++ b/tests/array2.right @@ -0,0 +1,74 @@ +argv[1] = <a b> +argv[1] = <ab> +argv[1] = <a b> +argv[1] = <a> +argv[2] = <b> +argv[1] = <a> +argv[2] = <b> +argv[1] = <3> +argv[1] = <bob> +argv[1] = <tom dick harry> +argv[1] = <joe> +argv[1] = <3> +argv[1] = <bob> +argv[1] = <tom dick harry> +argv[1] = <joe> +argv[1] = <3> +argv[1] = <bob> +argv[1] = <tom dick harry> +argv[1] = <joe> +argv[1] = <3> +argv[1] = <bob> +argv[1] = <tom dick harry> +argv[1] = <joe> +argv[1] = <1> +argv[1] = <bobtom dick harryjoe> +argv[1] = <3> +argv[1] = <bob> +argv[1] = <tom dick harry> +argv[1] = <joe> +argv[1] = <3> +argv[1] = <bob> +argv[1] = <tom dick harry> +argv[1] = <joe> +argv[1] = <5> +argv[1] = <bob> +argv[1] = <tom> +argv[1] = <dick> +argv[1] = <5> +argv[1] = <bob> +argv[1] = <tom> +argv[1] = <dick> +argv[1] = <1> +argv[1] = <bob> +argv[2] = <tom> +argv[3] = <dick> +argv[4] = <harry> +argv[5] = <joe> +argv[1] = <3> +argv[1] = <bob> +argv[1] = <tom> +argv[2] = <dick> +argv[3] = <harry> +argv[1] = <joe> +argv[1] = <a> +argv[2] = <b> +argv[3] = <c> +argv[4] = <d> +argv[5] = <e> +argv[1] = <a> +argv[2] = <b> +argv[3] = <c> +argv[4] = <d> +argv[5] = <e> +argv[1] = <foo> +argv[2] = <bar> +argv[3] = <bam> +argv[1] = <foobarbam> +argv[1] = <foo> +argv[2] = <bar> +argv[3] = <bam> +argv[1] = <foo> +argv[2] = <bar> +argv[3] = <bam> +argv[1] = <foo bar bam> diff --git a/tests/array2.sub b/tests/array2.sub new file mode 100644 index 0000000..44bb7c5 --- /dev/null +++ b/tests/array2.sub @@ -0,0 +1,4 @@ +declare -r []=asdf +declare -r a[]=asdf + +declare -a ''=(a 'b c') diff --git a/tests/array20.sub b/tests/array20.sub new file mode 100644 index 0000000..035d936 --- /dev/null +++ b/tests/array20.sub @@ -0,0 +1,34 @@ +# tests to make sure that $* and ${array[*]} expand consistently in `list' +# and `scalar' contexts + +arr=(a b c) +IFS=+ + +# these two should both expand to `+' separated strings +a=${arr[*]} ; echo "$a" +b=${arr[*]/a/x}; echo "$b" + +set -- a b c + +# these two should both expand to `+' separated strings +a=${*} ; echo "$a" +b=${*/a/x}; echo "$b" + +# these two should both expand to `+' separated strings and it should handle +# characters in IFS as chars in the string +unset a b + +set -- 'a+b' 'c+d' 'e+f' +a=${*} ; recho "$a" +b=${*/a/x}; recho "$b" + +# now let's make sure that @ always uses space separators even in contexts +# where we don't do word splitting +set -- a b c +a=${@} ; echo "$a" +b=${@/a/x}; echo "$b" + +unset a b + +a=${arr[@]} ; echo "$a" +b=${arr[@]/a/x}; echo "$b" diff --git a/tests/array21.sub b/tests/array21.sub new file mode 100644 index 0000000..d1f705e --- /dev/null +++ b/tests/array21.sub @@ -0,0 +1,37 @@ +typeset -a a +a=(1 2 3 4) + +typeset -A A +A=([one]=1 [two]=2 [three]=3 [four]=4) + +unset 'a[0]' +typeset -p a + +scalar=abcd +echo ${scalar[0]} + +unset 'scalar[0]' +echo ${scalar-unset} + +unset 'a[@]' +typeset -p a + +unset 'A[@]' +typeset -p A + +typeset -a a +a=(1 2 3 4) +typeset -A A +A=([one]=1 [two]=2 [three]=3 [four]=4) + +# supported, recommended way to unset all array elements +a=() +typeset -p a +A=() +typeset -p A + +declare -a foo +declare foo='(1 2 3)' +declare foo[1]='(4 5 6)' + +declare -p foo diff --git a/tests/array22.sub b/tests/array22.sub new file mode 100644 index 0000000..adae6e1 --- /dev/null +++ b/tests/array22.sub @@ -0,0 +1,46 @@ +# This isn't perfect behavior, but it establishes a baseline and will provide +# a way to detect behavior changes + +echo a1 +a[0]= a[1]=; recho "${a[@]:-y}" +unset a + +echo a2 +a[1]=; recho "${a[@]:-y}" +a[1]=; recho "${a[*]:-z}" +unset a + +echo a3 +a[0]= a[1]=x; recho "${a[@]:-y}" +unset a + +echo a4 +a[0]= a[1]=x; recho ${a[@]:+y} +unset a + +echo p1 +set '' '' +recho "${@:-y}" + +shift $# + +echo p2 +set '' x +recho "${@:-y}" + +shift $# + +echo p3 +set '' x +recho ${@:+y} + +# problems with * and null expansions dating back to bash's earliest days +A=(''); set -- '' + +echo "<${A[*]:-X}>" "<${*:-X}>" "<${A:-X}>" "<${A[0]:-X}>" + +IFS= +A=('' ''); set -- '' '' +B='' + +echo "<${A[*]:-X}>" "<${*:-X}>" "<${B:-X}>" "<${B[*]:-X}>" diff --git a/tests/array23.sub b/tests/array23.sub new file mode 100644 index 0000000..bd64fe1 --- /dev/null +++ b/tests/array23.sub @@ -0,0 +1,28 @@ +# this captures how bash and ksh93 expand indexed array subscripts in +# various contexts. if changes are ever made, or an option added to do +# this differently, the diffs will show up here + +typeset -a array + +index='$( echo >&2 foo )' # Literal shell code should never be evaluated unless an 'eval' is involved. + +echo ${array[ $index ]} # [] expands $index, results in a literal that [] does not re-evaluate. +echo $(( $index )) # (( )) expands $index, results in a literal that (( )) does not re-evaluate. +echo $(( array[ $index ] )) # (( )) expands $index, results in a literal that [] DOES re-evaluate. + +(( array[ $index ] )) + +typeset -a a + +: $(( a[$index]=5 )) + +#shopt -s assoc_expand_once +echo $((1+a[$index])) +echo $((1+a[\$index])) +echo "1+${a[$index]}" + +# intermediate problems discovered while bash-5.0 was in testing +a=0 +echo $(( a[a[0]] )) +echo ${a[a[a[0]]]} +echo $(( a[a[a[0]]] )) diff --git a/tests/array24.sub b/tests/array24.sub new file mode 100644 index 0000000..108f761 --- /dev/null +++ b/tests/array24.sub @@ -0,0 +1,47 @@ +set -- "abc" "def ghi" "jkl" +A=("$@") + +IFS=':' + +echo 'IFS=: ${var-$*}' +unset var; printf '%s\n' ${var-$*} +printf '%s\n' ${var-${A[*]}} + +echo "----" +echo 'IFS=: ${var=$*}' + +unset var; printf '%s\n' ${var=$*} +printf 'var=%s\n' "$var" + +unset var; printf '%s\n' ${var=${A[*]}} +printf 'var=%s\n' "$var" + +echo "----" +echo 'IFS=: ${var+$*}' + +printf '%s\n' ${var+$*} +printf '%s\n' ${var+${A[*]}} + +echo "----" +echo 'IFS= ${var-$*}' + +IFS='' +unset var; printf '%s\n' ${var-$*} +unset var; printf '%s\n' ${var-${A[*]}} + +echo "----" +echo 'IFS= ${var=$*}' + +unset var +printf '%s\n' ${var=$*} +printf 'var=%s\n' "$var" + +unset var +printf '%s\n' ${var=${A[*]}} +printf 'var=%s\n' "$var" + +echo "----" +echo 'IFS= ${var+$*}' + +printf '%s\n' ${var+$*} +printf '%s\n' ${var+${A[*]}} diff --git a/tests/array25.sub b/tests/array25.sub new file mode 100644 index 0000000..b550d9d --- /dev/null +++ b/tests/array25.sub @@ -0,0 +1,70 @@ +# tests with blank subscripts, indexed and associative + +echo 1. indexed: +a[0]=0 a[1]=1 + +v=" " + +echo reference: + +echo 1. ${a[ ]} +echo 2. ${a[' ']} +echo 3. "${a[ ]}" +echo 4. ${a[$v]} +echo 5. ${a["$v"]} +echo 6. "${a[$v]}" + +echo assignment: + +echo -n 1. ; a[ ]=10 ; typeset -p a ; a[0]=0 +echo -n 2. ; a[" "]=11 ; typeset -p a ; a[0]=0 +echo -n 3. ; a[$v]=12 ; typeset -p a ; a[0]=0 +echo -n 4. ; a["$v"]=13 ; typeset -p a ; a[0]=0 + +echo arithmetic: + +echo -n 1. ; (( a[ ]=10 )); typeset -p a ; a[0]=0 +echo -n 2. ; (( a[" "]=11 )); typeset -p a ; a[0]=0 +echo -n 3. ; (( a[$v]=12 )); typeset -p a ; a[0]=0 +echo -n 4. ; (( a["$v"]=13 )); typeset -p a ; a[0]=0 +echo -n 5. ; let "a[ ]=10" ; typeset -p a ; a[0]=0 +echo -n 6. ; let "a[\" \"]=11" ; typeset -p a ; a[0]=0 +echo -n 7. ; let "a[$v]=12" ; typeset -p a ; a[0]=0 +echo -n 8. ; let "a[\"$v\"]=13" ; typeset -p a ; a[0]=0 + +unset -v a v + +echo 2. associative: +shopt -s assoc_expand_once + +typeset -A a +a[0]=0 a[1]=1 + +v=" " + +echo reference: + +echo 1. ${a[ ]} +echo 2. ${a[' ']} +echo 3. "${a[ ]}" +echo 4. ${a[$v]} +echo 5. ${a["$v"]} +echo 6. "${a[$v]}" + +echo assignment: + +echo -n 1. ; a[ ]=10 ; typeset -p a ; a[0]=0 +echo -n 2. ; a[" "]=11 ; typeset -p a ; a[0]=0 +echo -n 3. ; a[$v]=12 ; typeset -p a ; a[0]=0 +echo -n 4. ; a["$v"]=13 ; typeset -p a ; a[0]=0 + +echo arithmetic: + +echo -n 1. ; (( a[ ]=10 )); typeset -p a ; a[0]=0 +echo -n 2. ; (( a[" "]=11 )); typeset -p a ; a[0]=0 +echo -n 3. ; (( a[$v]=12 )); typeset -p a ; a[0]=0 +echo -n 4. ; (( a["$v"]=13 )); typeset -p a ; a[0]=0 +echo -n 5. ; let "a[ ]=10" ; typeset -p a ; a[0]=0 +echo -n 6. ; let "a[\" \"]=11" ; typeset -p a ; a[0]=0 +echo -n 7. ; let "a[$v]=12" ; typeset -p a ; a[0]=0 +echo -n 8. ; let "a[\"$v\"]=13" ; typeset -p a ; a[0]=0 diff --git a/tests/array26.sub b/tests/array26.sub new file mode 100644 index 0000000..826774f --- /dev/null +++ b/tests/array26.sub @@ -0,0 +1,118 @@ +# these should produce the same results +a=(aa bb) +set -- aa bb + +IFS=+ + +recho ${a[@]} +recho ${a[@]:0} + +recho $@ +recho ${@:1} + +A=${a[*]} B=${a[*]:0} +recho $* ${*:1} +recho ${a[*]} ${a[*]:0} +recho "$A" "$B" +recho $A $B + +unset A B + +recho ${@/a/x} +recho ${a[@]/a/x} +recho "${@/a/x}" +recho "${a[@]/a/x}" + +recho ${*/a/x} +recho ${a[*]/a/x} +recho "${*/a/x}" +recho "${a[*]/a/x}" + +A=${*/a/x} +B=${a[*]/a/x} + +recho "$A" "$B" + +unset A B +declare -A A +A[0]=aa +A[1]=bb + +recho ${A[@]/a/x} +recho "${A[@]/a/x}" +recho ${A[*]/a/x} +recho "${A[*]/a/x}" + +unset A +IFS= + +recho ${@/a/x} +recho ${a[@]/a/x} +recho "${@/a/x}" +recho "${a[@]/a/x}" + +recho ${*/a/x} +recho ${a[*]/a/x} +recho "${*/a/x}" +recho "${a[*]/a/x}" + +A=${*/a/x} +B=${a[*]/a/x} + +recho "$A" "$B" + +unset A B +declare -A A +A[0]=aa +A[1]=bb + +recho ${A[@]/a/x} +recho "${A[@]/a/x}" +recho ${A[*]/a/x} +recho "${A[*]/a/x}" + +unset A + +IFS=+ + +recho ${a[@]} +recho ${a[@],,} +recho "${a[@]}" +recho "${a[@],,}" + +A=${a[*]} B=${a[*],,} +recho $* ${*,,} +recho ${a[*]} ${a[*],,} +recho "${a[*]}" "${a[*],,}" +recho "$A" "$B" +recho $A $B + +unset A B +declare -A A +A[0]=aa +A[1]=bb + +recho ${A[@],,} +recho "${A[@],,}" +recho ${A[*],,} +recho "${A[*],,}" + +unset A + +recho ${a[@]#?} +recho ${@#?} + +A=${a[*]#?} B=${a[*]#?} +recho ${*#?} ${a[*]#?} +recho "$A" "$B" +recho $A $B + +unset A B +declare -A A +A[0]=aa +A[1]=bb + +recho ${A[@]#?} +recho "${A[@]#?}" +recho ${A[*]#?} +recho "${A[*]#?}" diff --git a/tests/array27.sub b/tests/array27.sub new file mode 100644 index 0000000..fe1ffd3 --- /dev/null +++ b/tests/array27.sub @@ -0,0 +1,59 @@ +# tests for `problem' keys when using associative arrays and assoc_expand_once +# deal with problems for now; this is a placeholder for if and when I fix them + +typeset -A a +shopt -s assoc_expand_once + +k='[' +echo $(( a[$k]=7 )) + +k=']' +echo $(( a[$k]=7 )) + +unset a + +declare -A A + +for k in $'\t' ' '; do + (( A[$k]=2 )) +done +declare -p A + +for k in ']' '*' '@'; do + (( A[$k]=2 )) +done + +declare -p A + +unset A +declare -A A + +for k in $'\t' ' ' ']' '*' '@'; do + read "A[$k]" <<< X +done +declare -p A + +unset A +declare -A A + +for k in $'\t' ' ' ']' '*' '@'; do + printf -v "A[$k]" "%s" X +done +declare -p A + +unset A +declare -A A + +for k in ']' '*' '@'; do + declare A[$k]=X +done +declare -p A + +unset A +declare -A A + +for k in ']' '*' '@'; do + declare "A[$k]=X" +done +declare -p A + diff --git a/tests/array3.sub b/tests/array3.sub new file mode 100644 index 0000000..579b42b --- /dev/null +++ b/tests/array3.sub @@ -0,0 +1,9 @@ +a=(0 1 2 3 4 5 6 7 8 9) + +echo ${a[@]: -1} + +echo ${a[@]:9} +echo ${a[@]:10} +echo ${a[@]:11} + +echo ${a[@]:7:3} diff --git a/tests/array4.sub b/tests/array4.sub new file mode 100644 index 0000000..97c766d --- /dev/null +++ b/tests/array4.sub @@ -0,0 +1,32 @@ +# compound assignment parsing problems in bash-3.1-release +func() +{ + local -a x=() y=() +} + +a=() b=() +eval foo=() +eval foo=() bar=() qux=( "bash" ) + +foo=( "bash" ) +eval foo=( "bash" ) +eval bar=( "bash" ) bax=( "bash" ) + +let a=(5 + 3) b=(4 + 7) +echo $a $b + +typeset -i a b +a=(5+3) b=(4+7) +echo $a $b + +let a=(4*3)/2 +echo $a +a=(4*3)/2 +echo $a + +LNAME=nordholz +echo ${LNAME} +echo ${#LNAME} + +echo ${#LNAME[$(( 0 ))]} +echo ${#LNAME[$(( 0+0 ))]} diff --git a/tests/array5.sub b/tests/array5.sub new file mode 100644 index 0000000..00953c4 --- /dev/null +++ b/tests/array5.sub @@ -0,0 +1,34 @@ + +: ${TMPDIR:=/tmp} + +mkdir $TMPDIR/bash-test-$$ +cd $TMPDIR/bash-test-$$ + +trap "cd $OLDPWD ; rm -rf $TMPDIR/bash-test-$$" 0 1 2 3 6 15 + +touch '[3]=abcde' + +touch r s t u v + +declare -a x=(*) + +echo ${x[3]} +echo ${x[@]} + +unset x +x=(a b c d e) + +echo ${x[*]: -1} + +unset x[4] +unset x[2] + +x[9]='9' + +echo ${x[*]: -1} + +TOOLKIT=(1 2 3 4 5 6 7 8 9 10) +ARRAY="1" +echo ${TOOLKIT["$ARRAY"]} + +exit 0 diff --git a/tests/array6.sub b/tests/array6.sub new file mode 100644 index 0000000..0017f4c --- /dev/null +++ b/tests/array6.sub @@ -0,0 +1,115 @@ +# test cases for array quoting and escaping fixed post bash-3.2-release + +oIFS="$IFS" + +a=(a b c) +echo ${a[@]} + +a2=("${a[@]/#/"-iname '"}") +recho "${a2[@]}" + +echo "${dbg-"'hey'"}" +echo "${dbg-"hey"}" +echo "${dbg-'"'hey}" +echo "${dbg-'"hey'}" + +unset a a2 + +IFS= +a2=(${a[@]/#/"-iname '"}) +recho "${a2[@]}" + +IFS="$oIFS" +unset a a2 + +a=('a b' 'c d' 'e f') + +recho ${a[@]:1:2} +recho "${a[@]:1:2}" + +IFS= +recho ${a[@]:1:2} +recho "${a[@]:1:2}" + +IFS="$oIFS" +unset a a2 + +a=(abc def) + +# Prevent word splitting +#IFS= + +a2=("${a[@]/#/"-iname '"}") +recho "${a2[@]}" + +eval a2=("${a[@]/#/\"-iname \'\"}") +recho "${a2[@]}" + +eval a2=("${a[@]/#/"-iname '"}") +recho "${a2[@]}" + +a2=("${a[@]/#/-iname \'}") +recho "${a2[@]}" + +eval a2=("${a[@]/#/-iname \'}") +recho "${a2[@]}" + +set -- abc def + +a2=("${@/#/"-iname '"}") +recho "${a2[@]}" + +eval a2=("${@/#/\"-iname \'\"}") +recho "${a2[@]}" + +eval a2=("${@/#/"-iname '"}") +recho "${a2[@]}" + +unset a a2 + +IFS= +pat=('*.*') +case $(ls ${pat[@]} 2>/dev/null) in +'') echo '*.* BAD' ;; +*) echo '*.* OK' ;; +esac + +IFS="$oIFS" +unset a a2 pat + +IFS= + +s='abc' + +set - ${s/b/1 2 3} +echo $# +echo "$1" + +IFS="$oIFS" +unset s + +set -- ab cd ef +foo="var with spaces" + +IFS= +recho $foo +recho "$foo" + +recho ${foo}"$@" +recho ${foo}$@ + +array=(ab cd ef) +recho ${foo}"${array[@]}" +recho ${foo}${array[@]} + +recho $(echo $foo)"$@" +recho $(echo $foo)$@ + +a=('word1 with spaces' 'word2 with spaces') +set - ${a[@]/word/element} +echo $# +recho "$@" +recho $@ + +IFS="$oIFS" +unset a a2 array foo diff --git a/tests/array7.sub b/tests/array7.sub new file mode 100644 index 0000000..8935cc2 --- /dev/null +++ b/tests/array7.sub @@ -0,0 +1,14 @@ +# these didn't work in versions of bash before bash-4.0 + +LNAME=nordholz + +echo ${LNAME[$(( 0 ))]//h/!} +echo ${LNAME[$(( 2 ))]//h/!} + +echo ${LNAME[$(( 0 ))]##??} +echo ${LNAME[$(( 2 ))]##??} + +echo ${LNAME[$(( 0 ))]:2} +echo ${LNAME[$(( 0 ))]:2:4} +echo ${LNAME[$(( 2 ))]:2} +echo ${LNAME[$(( 2 ))]:2:4} diff --git a/tests/array8.sub b/tests/array8.sub new file mode 100644 index 0000000..481ccdb --- /dev/null +++ b/tests/array8.sub @@ -0,0 +1,23 @@ +IFS=/ +declare -a i + +i[0]=fooq +i[1]= +i[2]=barq +i[3]= +recho "${i[*]:0}" +recho "${i[@]:0}" + +recho "${i[*]/q/!}" +recho "${i[@]/q/!}" + +recho "${i[*]#?}" +recho "${i[@]#?}" + +# Need to complete this with case-modifying expansion examples +recho "${i[*]^?}" +recho "${i[@]^?}" + +recho "${i[*]^^?}" +recho "${i[@]^^?}" + diff --git a/tests/array9.sub b/tests/array9.sub new file mode 100644 index 0000000..444247f --- /dev/null +++ b/tests/array9.sub @@ -0,0 +1,27 @@ +echo $(( 0x7e )) +echo $(( 0x7f )) +echo $(( 0x80 )) + +a=$'\x80' +recho "$a" + +a=( $'\x7e' $'\x7f' $'\x80' ) + +recho "${a[@]}" + +unset a +a[0]=$'\x7e' +a[1]=$'\x7f' +a[2]=$'\x80' + +recho "${a[@]}" + +b1=$'\x7e' +b2=$'\x7f' +b3=$'\x80' + +unset a +a=( "$b1" "$b2" "$b3" ) + +recho "${a[@]}" + diff --git a/tests/assoc.right b/tests/assoc.right new file mode 100644 index 0000000..90abb6d --- /dev/null +++ b/tests/assoc.right @@ -0,0 +1,231 @@ +declare -A BASH_ALIASES=() +declare -A BASH_CMDS=() +declare -A fluff +declare -A BASH_ALIASES=() +declare -A BASH_CMDS=() +declare -A fluff=([foo]="one" [bar]="two" ) +declare -A fluff=([foo]="one" [bar]="two" ) +declare -A fluff=([bar]="two" ) +declare -A fluff=([bar]="newval" [qux]="assigned" ) +./assoc.tests: line 26: chaff: four: must use subscript when assigning associative array +declare -A BASH_ALIASES=() +declare -A BASH_CMDS=() +declare -Ai chaff=([zero]="5" [one]="10" ) +declare -Ar waste=([lineno]="28" [source]="./assoc.tests" [version]="4.0-devel" [pid]="42134" ) +declare -A wheat=([two]="b" [three]="c" [zero]="0" [one]="a" ) +declare -A chaff=(["hello world"]="flip" [zero]="5" [one]="10" ) +./assoc.tests: line 38: waste: readonly variable +./assoc.tests: line 39: unset: waste: cannot unset: readonly variable +./assoc.tests: line 40: chaff[*]: bad array subscript +./assoc.tests: line 41: [*]=12: invalid associative array key +declare -A chaff=(["hello world"]="flip" [one]="a" ) +flip +argv[1] = <multiple> +argv[2] = <words> +argv[3] = <flip> +argv[4] = <a> +argv[1] = <multiple words> +argv[2] = <flip> +argv[3] = <a> +argv[1] = <multiple> +argv[2] = <words> +argv[3] = <flip> +argv[4] = <a> +argv[1] = <multiple words flip a> +./assoc.tests: line 58: declare: chaff: cannot destroy array variables in this way +./assoc.tests: line 60: chaff[*]: bad array subscript +./assoc.tests: line 61: [*]=12: invalid associative array key +declare -A wheat=(["foo bar"]="qux qix" [six]="6" ) +argv[1] = <qux> +argv[2] = <qix> +argv[1] = <qux qix> +declare -A wheat=(["foo bar"]="qux qix" [six]="6" ) +argv[1] = <2> +argv[1] = <7> +argv[1] = <qux> +argv[2] = <qix> +argv[3] = <blat> +argv[1] = <qux qix blat> +argv[1] = <16> +argv[1] = <16> +argv[1] = <flix> +argv[2] = <6> +argv[1] = <foo> +argv[2] = <bar> +argv[3] = <six> +argv[1] = <foo bar> +argv[2] = <six> +8 +/sbin /usr/bin /bin /usr/ucb /usr/local/bin . /usr/sbin /bin +sbin bin bin ucb bin . sbin bin +bin +/ / / / / / / +/ +argv[1] = <bin> +argv[1] = </> +argv[1] = <sbin> +argv[1] = </> +8 +/sbin /usr/bin /bin /usr/ucb /usr/local/bin . /usr/sbin /bin +sbin bin bin ucb bin . sbin bin +/ / / / / / / +8 +4 -- /bin +^sbin ^usr^bin ^bin ^usr^ucb ^usr^local^bin . ^usr^sbin ^bin +^sbin ^usr^bin ^bin ^usr^ucb ^usr^local^bin . ^usr^sbin ^bin +\sbin \usr/bin \bin \usr/ucb \usr/local/bin . \usr/sbin \bin +\sbin \usr\bin \bin \usr\ucb \usr\local\bin . \usr\sbin \bin +\sbin \usr\bin \bin \usr\ucb \usr\local\bin . \usr\sbin \bin +([a]=1) + +foo qux +/usr/sbin/foo /usr/local/bin/qux +hits command + 0 /sbin/blat + 0 /usr/sbin/foo + 0 /bin/sh + 0 /usr/local/bin/qux +blat foo sh qux +/sbin/blat /usr/sbin/foo /bin/sh /usr/local/bin/qux + +foo qux +argv[1] = </usr/sbin/foo> +argv[2] = </usr/local/bin/qux> +argv[3] = <-l> +alias blat='cd /blat ; echo $PWD' +alias foo='/usr/sbin/foo' +alias qux='/usr/local/bin/qux -l' +alias sh='/bin/bash --login -o posix' +blat foo sh qux +argv[1] = <cd /blat ; echo $PWD> +argv[2] = </usr/sbin/foo> +argv[3] = </bin/bash --login -o posix> +argv[4] = </usr/local/bin/qux -l> +outside: outside +declare -A BASH_ALIASES=() +declare -A BASH_CMDS=() +declare -A afoo=(["foo bar"]="foo quux" [six]="six" ) +argv[1] = <inside:> +argv[2] = <foo quux> +argv[3] = <six> +outside 2: outside +argv[1] = </barq//fooq> +argv[1] = <> +argv[2] = <barq> +argv[3] = <> +argv[4] = <fooq> +argv[1] = </bar!//foo!> +argv[1] = <> +argv[2] = <bar!> +argv[3] = <> +argv[4] = <foo!> +argv[1] = </arq//ooq> +argv[1] = <> +argv[2] = <arq> +argv[3] = <> +argv[4] = <ooq> +argv[1] = </Barq//Fooq> +argv[1] = <> +argv[2] = <Barq> +argv[3] = <> +argv[4] = <Fooq> +argv[1] = </BARQ//FOOQ> +argv[1] = <> +argv[2] = <BARQ> +argv[3] = <> +argv[4] = <FOOQ> +abc +def +def +./assoc5.sub: line 13: declare: `myarray[foo[bar]=bleh': not a valid identifier +bleh def abc +myarray=([foo]="bleh" ["]"]="def" ["a]=test1;#a"]="123" ["a]a"]="abc" ) + +123 +myarray=([foo]="bleh" ["]"]="def" ["a]=test2;#a"]="def" ["a]=test1;#a"]="123" ["a]a"]="abc" ) +bar"bie +doll +declare -A foo=(["bar\"bie"]="doll" ) +bar"bie +doll +declare -A foo=(["bar\"bie"]="doll" ) +bar"bie +doll +declare -A foo=(["bar\"bie"]="doll" ) +bar"bie +doll +declare -A foo=(["bar\"bie"]="doll" ) +bar"bie +doll +declare -A foo=(["bar\"bie"]="doll" ) +bar'bie +doll +declare -A foo=(["bar'bie"]="doll" ) +bar'bie +doll +declare -A foo=(["bar'bie"]="doll" ) +bar'bie +doll +declare -A foo=(["bar'bie"]="doll" ) +bar'bie +doll +declare -A foo=(["bar'bie"]="doll" ) +bar'bie +doll +declare -A foo=(["bar'bie"]="doll" ) +bar$bie +doll +declare -A foo=(["bar\$bie"]="doll" ) +bar[bie +doll +declare -A foo=(["bar[bie"]="doll" ) +bar`bie +doll +declare -A foo=(["bar\`bie"]="doll" ) +bar\]bie +doll +declare -A foo=(["bar\\]bie"]="doll" ) +bar${foo}bie +doll +declare -A foo=(["bar\${foo}bie"]="doll" ) +bar +after printf +after use: 0 +declare -A assoc=([0]="assoc" ) +assoc +declare -A assoc=([two]="twoless" [three]="three" [one]="onemore" ) +declare -Ar assoc=([two]="twoless" [three]="three" [one]="onemore" ) +declare -A b=([")"]="" ["\""]="" ["]"]="" ["\\"]="" ["\`"]="" ) +declare -A b=(["]"]="" ["\`"]="" ) +declare -A dict=(["'"]="3" ["\""]="1" ["\\"]="4" ["\`"]="2" ) +./assoc9.sub: line 23: unset: `dict[']': not a valid identifier +./assoc9.sub: line 23: unset: `dict["]': not a valid identifier +./assoc9.sub: line 23: unset: `dict[\]': not a valid identifier +./assoc9.sub: line 23: unset: `dict[`]': not a valid identifier +declare -A dict=(["'"]="3" ["\""]="1" ["\\"]="4" ["\`"]="2" ) +declare -A dict=(["'"]="3" ["\""]="1" ["\\"]="4" ["\`"]="2" ) +declare -A dict=() +4 +4 +a[$b]= 5 +declare -A a=(["80's"]="Depeche Mode" ) +./assoc9.sub: line 71: read: `a[80's]': not a valid identifier +declare -A a +declare -A a=(["80's"]="Depeche Mode" ) +./assoc9.sub: line 83: printf: `a[80's]': not a valid identifier +declare -A a +declare -A a=(["80's"]="Depeche Mode" ) +6 +1 +1+5 +declare -A a=(["\$(date >&2)"]="5" ) +declare -A myarray=([foo]="bleh" ["foo[bar"]="bleh" ) +./assoc10.sub: line 1: declare: a: cannot convert indexed to associative array +f: declare -a a +./assoc10.sub: line 4: declare: a: cannot convert associative to indexed array +f: declare -A a + +f: declare -a a +main: declare -- a="7" +f: declare -A a +main: declare -- a="42" diff --git a/tests/assoc.tests b/tests/assoc.tests new file mode 100644 index 0000000..84326c9 --- /dev/null +++ b/tests/assoc.tests @@ -0,0 +1,221 @@ +# TEST - basic declaration and assignment +typeset -A fluff +declare -A + +fluff[foo]=one +fluff[bar]=two + +declare -A +declare -p fluff + +unset fluff[foo] +declare -p fluff + +fluff[bar]=newval +declare fluff[qux]=assigned + +declare -p fluff + +unset fluff + +# TEST - compount assignment and variable attributes +declare -A wheat chaff +wheat=( [zero]=0 [one]=a [two]=b [three]=c ) + +declare -i chaff +chaff=( [zero]=1+4 [one]=3+7 four ) + +declare -A waste=( [pid]=42134 [version]=4.0-devel [source]=$0 [lineno]=$LINENO ) +declare -r waste + +declare -A + +declare +i chaff +chaff[hello world]=flip +declare -p chaff + +# TEST - errors +waste[stuff]=other +unset waste +chaff[*]=12 +chaff=( [one]=a [*]=12 ) + +# TEST - key expansion -- no word splitting +chaff[hello world]=flip +declare -p chaff +echo ${chaff[hello world]} + +chaff[box]="multiple words" + +recho ${chaff[@]} +recho "${chaff[@]}" + +recho ${chaff[*]} +recho "${chaff[*]}" + +unset chaff +declare -A chaff[200] +declare +A chaff + +chaff[*]=12 +chaff=( [one]=a [*]=12 ) + +# TEST - keys and values containing spaces +unset wheat +declare -A wheat +wheat=([six]=6 [foo bar]="qux qix" ) + +declare -p wheat + +unset wheat +declare -A wheat=([six]=6 [foo bar]="qux qix" ) + +recho ${wheat[foo bar]} +recho "${wheat[foo bar]}" + +declare -p wheat + +# TEST - basic expansions: number of elements and value length +unset wheat +typeset -A wheat +wheat=([six]=6 [foo bar]="qux qix" ) + +recho ${#wheat[@]} + +recho ${#wheat[foo bar]} + +# TEST - appending assignment operator +unset wheat +typeset -A wheat +wheat=([six]=6 [foo bar]="qux qix" ) + +wheat[foo bar]+=' blat' + +recho ${wheat[foo bar]} +recho "${wheat[foo bar]}" +unset wheat + +flix=9 +typeset -Ai wheat +wheat=([six]=6 [foo bar]=flix ) + +wheat[foo bar]+=7 + +recho ${wheat[foo bar]} +recho "${wheat[foo bar]}" +unset flix wheat + +# TEST - index expansion: no word splitting or globbing +typeset -A wheat +cd ${TMPDIR:=/tmp} +touch '[sfiri]' +wheat=([s*]=6 [foo bar]=flix ) + +recho ${wheat[@]} +rm '[sfiri]' +cd $OLDPWD + +# TEST -- associative array keys expansion +unset wheat +typeset -A wheat + +wheat=([six]=6 [foo bar]=flix ) + +recho ${!wheat[@]} +recho "${!wheat[@]}" + +# TEST -- associative array pattern removal +unset xpath +typeset -A xpath + +xpath=( [0]=/bin [one]=/bin [two]=/usr/bin [three]=/usr/ucb [four]=/usr/local/bin) +xpath+=( [five]=/sbin [six]=/usr/sbin [seven]=. ) + +echo ${#xpath[@]} + +echo ${xpath[@]} +echo ${xpath[@]##*/} +echo ${xpath[0]##*/} +echo ${xpath[@]%%[!/]*} +echo ${xpath[0]%%[!/]*} +recho ${xpath##*/} +recho ${xpath%%[!/]*} +recho ${xpath[five]##*/} +recho ${xpath[five]%%[!/]*} + +echo ${#xpath[*]} + +echo ${xpath[*]} +echo ${xpath[*]##*/} +echo ${xpath[*]%%[!/]*} + +# TEST -- associative array pattern substitution +unset xpath +typeset -A xpath + +xpath=( [0]=/bin [one]=/bin [two]=/usr/bin [three]=/usr/ucb [four]=/usr/local/bin) +xpath+=( [five]=/sbin [six]=/usr/sbin [seven]=. ) + +echo ${#xpath[@]} +# default element is "0" (as a string) +echo ${#xpath} -- ${xpath["0"]} + +echo ${xpath[@]//\//^} +echo "${xpath[@]//\//^}" | cat -v + +zecho "${xpath[@]/\//\\}" +zecho "${xpath[@]//\//\\}" +zecho "${xpath[@]//[\/]/\\}" + +# test assignment to key "0" +unset T +declare -A T +T='([a]=1)' +echo "${T[@]}" +unset T + +# peculiar ksh93 semantics for unsubscripted assoc variable reference +declare -A T +T[0]='zero' +if [ "$T" != "${T[0]}" ]; then + echo 'assoc.tests: $T and ${T[0]} mismatch' +fi + +${THIS_SH} ./assoc1.sub + +${THIS_SH} ./assoc2.sub + +${THIS_SH} ./assoc3.sub + +${THIS_SH} ./assoc4.sub + +${THIS_SH} ./assoc5.sub + +${THIS_SH} ./assoc6.sub + +${THIS_SH} ./assoc7.sub + +# test converting between scalars and assoc arrays +unset assoc +assoc=assoc +declare -A assoc +declare -p assoc +echo ${assoc[@]} + +# weird syntax required to append to multiple existing array elements using +# compound assignment syntax +unset assoc +declare -A assoc +assoc=( [one]=one [two]=two [three]=three ) +assoc+=( [one]+=more [two]+=less ) +declare -p assoc + +readonly -A assoc +declare -p assoc + +${THIS_SH} ./assoc8.sub + +# new shopt option to prevent multiple expansion of assoc array subscripts +${THIS_SH} ./assoc9.sub + +${THIS_SH} ./assoc10.sub diff --git a/tests/assoc1.sub b/tests/assoc1.sub new file mode 100644 index 0000000..a045bde --- /dev/null +++ b/tests/assoc1.sub @@ -0,0 +1,16 @@ +hash -r +echo ${BASH_CMDS[@]} + +hash -p /usr/sbin/foo foo +hash -p /usr/local/bin/qux qux + +echo ${!BASH_CMDS[@]} +echo ${BASH_CMDS[@]} + +BASH_CMDS[blat]=/sbin/blat +BASH_CMDS[sh]=/bin/sh + +hash + +echo ${!BASH_CMDS[@]} +echo "${BASH_CMDS[@]}" diff --git a/tests/assoc10.sub b/tests/assoc10.sub new file mode 100644 index 0000000..9eef2ca --- /dev/null +++ b/tests/assoc10.sub @@ -0,0 +1,17 @@ +f() { declare -a a; declare -A a; echo -n "$FUNCNAME: " ; declare -p a; } +f + +f() { declare -A a; declare -a a; echo -n "$FUNCNAME: " ; declare -p a; } +f + +echo + +f() { declare -a a; echo -n "$FUNCNAME: " ; declare -p a; } +a=7 +f +echo -n 'main: '; declare -p a + +f() { declare -A a; echo -n "$FUNCNAME: " ; declare -p a; } +a=42 +f +echo -n 'main: '; declare -p a diff --git a/tests/assoc2.sub b/tests/assoc2.sub new file mode 100644 index 0000000..396b87a --- /dev/null +++ b/tests/assoc2.sub @@ -0,0 +1,15 @@ +echo ${BASH_ALIASES[@]} + +alias foo=/usr/sbin/foo +alias qux='/usr/local/bin/qux -l' + +echo ${!BASH_ALIASES[@]} +recho ${BASH_ALIASES[@]} + +BASH_ALIASES[blat]='cd /blat ; echo $PWD' +BASH_ALIASES[sh]='/bin/bash --login -o posix' + +alias -p + +echo ${!BASH_ALIASES[@]} +recho "${BASH_ALIASES[@]}" diff --git a/tests/assoc3.sub b/tests/assoc3.sub new file mode 100644 index 0000000..9129ef1 --- /dev/null +++ b/tests/assoc3.sub @@ -0,0 +1,15 @@ +foo() +{ + declare -A afoo=([six]="six" [foo bar]="foo quux") + + declare -A + recho inside: "${afoo[@]}" +} + +declare -A afoo=([main]=outside) +echo outside: "${afoo[@]}" + +foo + +echo outside 2: "${afoo[@]}" + diff --git a/tests/assoc4.sub b/tests/assoc4.sub new file mode 100644 index 0000000..1516dc5 --- /dev/null +++ b/tests/assoc4.sub @@ -0,0 +1,22 @@ +IFS=/ +declare -A i + +i[0]=fooq +i[1]= +i[2]=barq +i[3]= + +recho "${i[*]:0}" +recho "${i[@]:0}" + +recho "${i[*]/q/!}" +recho "${i[@]/q/!}" + +recho "${i[*]#?}" +recho "${i[@]#?}" + +# Need to complete this with case-modifying expansion examples +recho "${i[*]^?}" +recho "${i[@]^?}" +recho "${i[*]^^?}" +recho "${i[@]^^?}" diff --git a/tests/assoc5.sub b/tests/assoc5.sub new file mode 100644 index 0000000..400f3d3 --- /dev/null +++ b/tests/assoc5.sub @@ -0,0 +1,27 @@ +declare -A myarray + +# this needs fixes to skipsubscript +myarray["a]a"]="abc" + +echo ${myarray["a]a"]} + +myarray[$(echo ])]=def + +echo ${myarray[']']} +echo ${myarray[\]]} + +declare myarray["foo[bar"]=bleh +myarray["foo"]=bleh + +echo "${myarray[@]}" + +bar='a]=test1;#a' +myarray[$bar]=123 + +set | grep ^myarray= +echo ${myarray[a]} + +echo "${myarray['a]=test1;#a']}" +myarray['a]=test2;#a']="def" + +set | grep ^myarray= diff --git a/tests/assoc6.sub b/tests/assoc6.sub new file mode 100644 index 0000000..54112ee --- /dev/null +++ b/tests/assoc6.sub @@ -0,0 +1,146 @@ +declare -A foo + +foo=([bar\"bie]=doll) + +echo ${!foo[@]} +echo ${foo[@]} + +declare -p foo + +unset foo +declare -A foo=(["bar\"bie"]="doll") + +echo ${!foo[@]} +echo ${foo[@]} + +declare -p foo + +unset foo +declare -A foo + +foo=(["bar\"bie"]="doll") + +echo ${!foo[@]} +echo ${foo[@]} + +declare -p foo + +unset foo +declare -A foo + +foo["bar\"bie"]="doll" + +echo ${!foo[@]} +echo ${foo[@]} + +declare -p foo + +unset foo +declare -A foo + +foo[bar\"bie]="doll" + +echo ${!foo[@]} +echo ${foo[@]} + +declare -p foo + +unset foo +declare -A foo + +foo=([bar\'bie]=doll) + +echo ${!foo[@]} +echo ${foo[@]} + +declare -p foo + +unset foo +declare -A foo=(["bar'bie"]="doll") + +echo ${!foo[@]} +echo ${foo[@]} + +declare -p foo + +unset foo +declare -A foo + +foo=(["bar'bie"]="doll") + +echo ${!foo[@]} +echo ${foo[@]} + +declare -p foo + +unset foo +declare -A foo + +foo["bar'bie"]="doll" + +echo ${!foo[@]} +echo ${foo[@]} + +declare -p foo + +unset foo +declare -A foo + +foo[bar\'bie]="doll" + +echo ${!foo[@]} +echo ${foo[@]} + +declare -p foo + +unset foo +declare -A foo + +foo=([bar\$bie]=doll) + +echo ${!foo[@]} +echo ${foo[@]} + +declare -p foo + +unset foo +declare -A foo=(["bar[bie"]="doll") + +echo ${!foo[@]} +echo ${foo[@]} + +declare -p foo + +unset foo +declare -A foo + +foo=(["bar\`bie"]="doll") + +echo ${!foo[@]} +echo ${foo[@]} + +declare -p foo + +unset foo +declare -A foo + +# this doesn't work right without the backslash +foo["bar\]bie"]="doll" + +echo ${!foo[@]} +echo ${foo[@]} + +declare -p foo + +unset foo +declare -A foo + +foo[bar\${foo}bie]="doll" + +echo ${!foo[@]} +echo ${foo[@]} + +declare -p foo + +unset foo +declare -A foo diff --git a/tests/assoc7.sub b/tests/assoc7.sub new file mode 100644 index 0000000..5bc5150 --- /dev/null +++ b/tests/assoc7.sub @@ -0,0 +1,16 @@ +# problem with bash versions through bash-4.2 +foo() +{ + declare -A hash + declare hash[baz]=bar #bash crashes here + + echo ${hash[@]} +} + +foo + +declare -a ary +printf -v ary[0] "%b" "" +echo "after printf" +x="${ary[*]}" # segfaults here +echo "after use: $?" diff --git a/tests/assoc8.sub b/tests/assoc8.sub new file mode 100644 index 0000000..83b43f4 --- /dev/null +++ b/tests/assoc8.sub @@ -0,0 +1,7 @@ +# warnings introduced beginning with bash-4.4-alpha + +var=foo; declare -A "arr$var=([x]=y)" + +key1=foo key2=bar + +declare -A a=([foo]='([bar]=baz)') "b=${a[$key1]}" diff --git a/tests/assoc9.sub b/tests/assoc9.sub new file mode 100644 index 0000000..c5fbe45 --- /dev/null +++ b/tests/assoc9.sub @@ -0,0 +1,110 @@ +typeset -A a=( [\\]= [\"]= [\)]= ) b +for x in "${!a[@]}"; do b[$x]=; done +b+=([\`]= [\]]=) +typeset -p b +for x in "${!a[@]}"; do + unset -v 'b[$x]' +done +typeset -p b + +unset -v a b + +loaddict() +{ + dict['"']=1 + dict['`']=2 + dict["'"]=3 + dict['\']=4 + declare -p dict +} + +del() +{ + unset -v dict["$1"]; +} + +declare -A dict +loaddict +for k in "${!dict[@]}"; do del "$k"; done +declare -p dict + +unset 'dict[@]' + +shopt -s assoc_expand_once +declare -A dict +loaddict +for k in "${!dict[@]}"; do del "$k"; done +declare -p dict + +unset a b dict + +typeset -A a +b="80's" + +((++a[$b])) + +((++a["$b"])) +[[ $((++a[$b])) ]] +[[ $((++a["$b"])) ]] +echo ${a["$b"]} +echo ${a[$b]} + +let "++a[$b]" + +echo 'a[$b]=' "${a[$b]}" + +unset a b + +declare -A a +b="80's" + +: ${a[$b]:='Depeche Mode'} + +declare -p a + +unset a b +shopt -u assoc_expand_once + +typeset -A a +b="80's" + +read a[$b] <<<"Depeche Mode" +typeset -p a + +shopt -s assoc_expand_once +read a[$b] <<<"Depeche Mode" +typeset -p a + +unset a +shopt -u assoc_expand_once + +typeset -A a + +printf -v a[$b] "%s" "Depeche Mode" +typeset -p a + +shopt -s assoc_expand_once + +printf -v a[$b] "%s" "Depeche Mode" +typeset -p a + +unset a + +declare -A a +x='$(date >&2)' +a[$x]=5 + +shopt -s assoc_expand_once +echo $((1+a[$x])) +echo $((1+a[\$x])) +echo "1+${a[$x]}" + +declare -p a + +shopt -s assoc_expand_once +declare -A myarray + +declare myarray["foo[bar"]=bleh +myarray["foo"]=bleh + +declare -p myarray diff --git a/tests/attr.right b/tests/attr.right new file mode 100644 index 0000000..631b3f4 --- /dev/null +++ b/tests/attr.right @@ -0,0 +1,37 @@ +after f1:declare -ar a=([0]="1") +./attr.tests: line 4: a: readonly variable +after f2:declare -ar a=([0]="1") +./attr.tests: line 5: a: readonly variable +after f3:declare -ar a=([0]="1") +./attr.tests: line 6: readonly: a: readonly variable +after f4:declare -ar a=([0]="1") +after f2:declare -ar b=([0]="2") +after f3:declare -ar c=([0]="(3)") +after f4:declare -ar d=([0]="4") +declare -r m="4" +in func:declare -r n="4" +declare -r n="4" +./attr1.sub: line 13: p: readonly variable +declare -r p="1" +./attr1.sub: line 19: r: readonly variable +declare -ar r=([0]="1") +./attr1.sub: line 23: r: readonly variable +declare -ar r=([0]="1") +./attr1.sub: line 27: r: readonly variable +declare -ar r=([0]="1") +./attr1.sub: line 31: readonly: r: readonly variable +declare -ar r=([0]="1") +declare -ar x=([0]="4") +in func:declare -ar y=([0]="4") +declare -ar y=([0]="4") +in func:declare -ar z=([0]="4") +declare -ar z=([0]="4") +in func:declare -ar y1=([0]="4") +declare -ar y1=([0]="4") +in func:declare -ar z1=([0]="4") +declare -ar z1=([0]="4") +declare -x p="4" +declare -ax r=([0]="4") +declare -ax r=([0]="(5)") +declare -ax r=([0]="6") +declare -ax r=([0]="7") diff --git a/tests/attr.tests b/tests/attr.tests new file mode 100644 index 0000000..b5e0159 --- /dev/null +++ b/tests/attr.tests @@ -0,0 +1,41 @@ +a=(outside) + +f1() { readonly a=(1) ; } +f2() { readonly -a a=(2) ; } +f3() { readonly 'a=(3)' ; } +f4() { readonly -a 'a=(4)' ; } + +f1 +echo -n after f1: +declare -p a +f2 +echo -n after f2: +declare -p a +f3 +echo -n after f3: +declare -p a +f4 +echo -n after f4: +declare -p a + +b=(outside) +c=(outside) +d=(outside) + +f2() { readonly -a b=(2) ; } +f3() { readonly 'c=(3)' ; } +f4() { readonly -a 'd=(4)' ; } + +f2 +echo -n after f2: +declare -p b +f3 +echo -n after f3: +declare -p c +f4 +echo -n after f4: +declare -p d + +${THIS_SH} ./attr1.sub +${THIS_SH} ./attr2.sub + diff --git a/tests/attr1.sub b/tests/attr1.sub new file mode 100644 index 0000000..1c0609a --- /dev/null +++ b/tests/attr1.sub @@ -0,0 +1,55 @@ +m=1 +readonly m=4 +declare -p m + +n=1 +f() { readonly n=4; echo -n in func: ; declare -p n ; } +f +declare -p n + +p=1 +readonly p + +readonly p=4 +declare -p p + +r=(1) +readonly r + +f() { readonly r=(4) ; } +f +declare -p r + +f() { readonly r='(5)' ; } +f +declare -p r + +f() { readonly -a r=(6) ; } +f +declare -p r + +f() { readonly -a r='(7)' ; } +f +declare -p r + +x=(1) +readonly x=(4) +declare -p x + +y=(1) +f() { readonly y=(4); echo -n in func: ; declare -p y; } +f +declare -p y + +z=(1) +f() { readonly -a z=(4); echo -n in func: ; declare -p z; } +f +declare -p z + +f() { readonly y1=(4); echo -n in func: ; declare -p y1; } +f +declare -p y1 + +f() { readonly -a z1=(4); echo -n in func: ; declare -p z1; } +f +declare -p z1 diff --git a/tests/attr2.sub b/tests/attr2.sub new file mode 100644 index 0000000..28d447c --- /dev/null +++ b/tests/attr2.sub @@ -0,0 +1,24 @@ +p=1 +export p + +export p=4 +declare -p p + +r=(1) +export r + +f() { export r=(4) ; } +f +declare -p r + +f() { export r='(5)' ; } +f +declare -p r + +f() { export -a r=(6) ; } +f +declare -p r + +f() { export -a r='(7)' ; } +f +declare -p r diff --git a/tests/braces.right b/tests/braces.right new file mode 100644 index 0000000..4017546 --- /dev/null +++ b/tests/braces.right @@ -0,0 +1,77 @@ +ffc ffb ffa +fdg feg ffg +lxyz nxyz mxyz +{abc,def} +{abc} +{a,b,c,d,e} +x} y} {a} b} c} +x,y {abc} trie +/usr/ucb/ex /usr/ucb/edit /usr/lib/ex /usr/lib/how_ex +XXXX{a,b,c} +XXXXa XXXXb XXXXc +{} +{ } +} +{ +abcd{efgh +foo 1 2 bar +foo 1 2 bar +foo 1 2 bar +foobar foobaz. +foobar foobaz +bazx bazy +vx vy +bazx bazy +1 2 3 4 5 6 7 8 9 10 +0..10 braces +0 1 2 3 4 5 6 7 8 9 10 braces +x0y x1y x2y x3y x4y x5y x6y x7y x8y x9y x10y xbracesy +3 +x3y +10 9 8 7 6 5 4 3 2 1 +10y 9y 8y 7y 6y 5y 4y 3y 2y 1y +x10y x9y x8y x7y x6y x5y x4y x3y x2y x1y +a b c d e f +f e d c b a +a ` _ ^ ] [ Z Y X W V U T S R Q P O N M L K J I H G F E D C B A +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 +f +{1..f} +{f..1} +01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 +-1 -2 -3 -4 -5 -6 -7 -8 -9 -10 +-20 -19 -18 -17 -16 -15 -14 -13 -12 -11 -10 -9 -8 -7 -6 -5 -4 -3 -2 -1 0 +a-{bd}-c a-{be}-c +a-{bdef-g-c a-{bdef-i-c +{klklkl}1 {klklkl}2 {klklkl}3 +{x,x} +1 3 5 7 9 +-1 -3 -5 -7 -9 +-1 -3 -5 -7 -9 +10 8 6 4 2 +10 8 6 4 2 +1 3 5 7 9 11 13 15 17 19 +1 +100 95 90 85 80 75 70 65 60 55 50 45 40 35 30 25 20 15 10 5 0 +100 95 90 85 80 75 70 65 60 55 50 45 40 35 30 25 20 15 10 5 0 +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 c e g i k m o q s u w y +z x v t r p n l j h f d b +2147483645 2147483646 2147483647 2147483648 2147483649 +10 8 6 4 2 0 +10 8 6 4 2 0 +-50 -45 -40 -35 -30 -25 -20 -15 -10 -5 0 +{1..10.f} +{1..ff} +{1..10..ff} +{1.20..2} +{1..20..f2} +{1..20..2f} +{1..2f..2} +{1..ff..2} +{1..ff} +{1..f} +{1..0f} +{1..10f} +{1..10.f} +{1..10.f} diff --git a/tests/braces.tests b/tests/braces.tests new file mode 100644 index 0000000..a80cf45 --- /dev/null +++ b/tests/braces.tests @@ -0,0 +1,119 @@ +echo ff{c,b,a} +echo f{d,e,f}g +echo {l,n,m}xyz +echo {abc\,def} +echo {abc} + +echo \{a,b,c,d,e} +echo {x,y,\{a,b,c}} +echo {x\,y,\{abc\},trie} + +echo /usr/{ucb/{ex,edit},lib/{ex,how_ex}} + +echo XXXX\{`echo a b c | tr ' ' ','`\} +eval echo XXXX\{`echo a b c | tr ' ' ','`\} + +echo {} +echo { } +echo } +echo { +echo abcd{efgh + +echo foo {1,2} bar +echo `zecho foo {1,2} bar` +echo $(zecho foo {1,2} bar) + +var=baz +varx=vx +vary=vy + +echo foo{bar,${var}.} +echo foo{bar,${var}} + +echo "${var}"{x,y} +echo $var{x,y} +echo ${var}{x,y} + +unset var varx vary + +# new sequence brace operators +echo {1..10} + +# this doesn't work yet +echo {0..10,braces} +# but this does +echo {{0..10},braces} +echo x{{0..10},braces}y + +echo {3..3} +echo x{3..3}y +echo {10..1} +echo {10..1}y +echo x{10..1}y + +echo {a..f} +echo {f..a} + +echo {a..A} +echo {A..a} + +echo {f..f} + +# mixes are incorrectly-formed brace expansions +echo {1..f} +echo {f..1} + +echo 0{1..9} {10..20} + +# do negative numbers work? +echo {-1..-10} +echo {-20..0} + +# weirdly-formed brace expansions -- fixed in post-bash-3.1 +echo a-{b{d,e}}-c + +echo a-{bdef-{g,i}-c + +echo {"klklkl"}{1,2,3} +echo {"x,x"} + +echo {1..10..2} +echo {-1..-10..2} +echo {-1..-10..-2} + +echo {10..1..-2} +echo {10..1..2} + +echo {1..20..2} +echo {1..20..20} + +echo {100..0..5} +echo {100..0..-5} + +echo {a..z} +echo {a..z..2} +echo {z..a..-2} + +# make sure brace expansion handles ints > 2**31 - 1 using intmax_t +echo {2147483645..2147483649} + +# unwanted zero-padding -- fixed post-bash-4.0 +echo {10..0..2} +echo {10..0..-2} +echo {-50..-0..5} + +# bad +echo {1..10.f} +echo {1..ff} +echo {1..10..ff} +echo {1.20..2} +echo {1..20..f2} +echo {1..20..2f} +echo {1..2f..2} +echo {1..ff..2} +echo {1..ff} +echo {1..f} +echo {1..0f} +echo {1..10f} +echo {1..10.f} +echo {1..10.f} diff --git a/tests/builtins.right b/tests/builtins.right new file mode 100644 index 0000000..32db2a5 --- /dev/null +++ b/tests/builtins.right @@ -0,0 +1,238 @@ +a +end-1 +a +end-2 +a:x +end-a +b:x +end-b +c:x +end-c +end-3 +a:x +end +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 +a:x +b:x +c:x +end +$BVAR +$BVAR +$BVAR +$BVAR +foo +bar +xxx +0022 +u=rwx,g=rx,o=rx +0002 +u=rwx,g=rwx,o=rx +umask 0002 +umask -S u=rwx,g=rwx,o=rx +u=rwx,g=rwx,o=rwx +enable . +enable : +enable break +enable continue +enable eval +enable exec +enable exit +enable export +enable readonly +enable return +enable set +enable shift +enable source +enable times +enable trap +enable unset +enable . +enable : +enable break +enable continue +enable eval +enable exec +enable exit +enable export +enable readonly +enable return +enable set +enable shift +enable source +enable times +enable trap +enable unset +enable -n test worked +enable test worked +specialname +-specialname +FOO=BAR +FOO=BAR +hash: hash table empty +0 +AVAR +foo +in source.sub2, calling return +5 +a b c +a b c +x y z +a b c +a b c +m n o p +a b c +m n o p +/tmp/bash-dir-a +/tmp/bash-dir-a +/tmp/bash-dir-a +./source5.sub: line 10: /tmp/source-notthere: No such file or directory +after bad source 1 +./source5.sub: line 17: /tmp/source-notthere: No such file or directory +one - OK +0 +0 +two - OK +0 +three - OK +0 +four - OK +0 +abc +def +ghi +after +one.1 subshell +two.1 subshell +three.1 subshell +four.1 subshell +one.2 subshell +two.2 subshell +three.2 subshell +four.2 subshell +x29 - done +abc +def +ghi +ok +AVAR +foo +foo +AVAR +foo +foo +AVAR +foo +declare -x foo="" +declare -x FOO="\$\$" +./builtins.tests: line 213: declare: FOO: not found +declare -x FOO="\$\$" +ok +ok +./builtins.tests: line 245: kill: 4096: invalid signal specification +1 +a\n\n\nb +a + + +b +before: f = 4 +inside +after: f = 8 bar = 4 +declare -a c +declare -A d +declare -a c=([0]="4") +declare -A c=([0]="4" ) +declare -a c=([0]="1" [1]="2" [2]="3") +declare -A c=([two]="2" [three]="3" [one]="1" ) +declare -a c=([0]="1" [1]="2" [2]="3") +declare -a c=([0]="1" [1]="2" [2]="3") +unset +unset +assoc 1 unset +array 1 unset +assoc 2 unset +array 2 unset +unset1 +unset2 +1 +1 +1 +1 +assoc A +array a +assoc B unset +array b unset +scalar 1 +scalar 2 +scalar 3 unset +argv[1] = <one two three> +assoc: 3 +array: 3 +scalar: 13 +scalar: 1 +scalar: 0 +scalar: 1 +scalar: 0 +scalar: 0 +all set: +one +two +f1 () +{ + echo f1 +} +f2 () +{ + echo f2 +} +all unset: +unset1 +unset2 +./builtins6.sub: line 28: declare: f1: not found +./builtins6.sub: line 28: declare: f2: not found +all reset: +one-one +two-one +f1 () +{ + echo f1 +} +f2 () +{ + echo f2 +} +vars unset: +unset1 +unset2 +f1 () +{ + echo f1 +} +f2 () +{ + echo f2 +} +funcs unset: +one-two +two-two +./builtins.tests: line 266: exit: status: numeric argument required diff --git a/tests/builtins.tests b/tests/builtins.tests new file mode 100644 index 0000000..ac74fe6 --- /dev/null +++ b/tests/builtins.tests @@ -0,0 +1,268 @@ +# tests for miscellaneous builtins not tested elsewhere +set +p +set +o posix + +ulimit -c 0 2>/dev/null + +# check that break breaks loops +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 + +# check that break breaks nested loops +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 + +# check that continue continues loops +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 + +# check that continue breaks out of nested loops +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 + +# check that `eval' re-evaluates arguments, but `builtin' and `command' do not +AVAR='$BVAR' +BVAR=foo + +echo $AVAR +builtin echo $AVAR +command echo $AVAR +eval echo \$AVAR +eval echo $AVAR + +# test out eval with a temp environment +AVAR=bar eval echo \$AVAR +BVAR=xxx eval echo $AVAR + +unset -v AVAR BVAR + +# test umask +mask=$(umask) +umask 022 +umask +umask -S +umask -S u=rwx,g=rwx,o=rx >/dev/null # 002 +umask +umask -S +umask -p +umask -p -S +umask 0 +umask -S +umask ${mask} # restore original mask + +# builtin/command without arguments should do nothing. maybe someday they will +builtin +command + +# test enable +enable -ps + +enable -aps ; enable -nps + +enable -n test +case "$(type -t test)" in +builtin) echo oops -- enable -n test failed ;; +*) echo enable -n test worked ;; +esac + +enable test +case "$(type -t test)" in +builtin) echo enable test worked ;; +*) echo oops -- enable test failed ;; +esac + +# test options to exec +(exec -a specialname ${THIS_SH} -c 'echo $0' ) +(exec -l -a specialname ${THIS_SH} -c 'echo $0' ) +# test `clean' environment. if /bin/sh is bash, and the script version of +# printenv is run, there will be variables in the environment that bash +# sets on startup. Also test code that prefixes argv[0] with a dash. +(export FOO=BAR ; exec -c -l printenv ) | grep FOO +(FOO=BAR exec -c printenv ) | grep FOO + +(export FOO=BAR ; exec printenv ) | grep FOO +(FOO=BAR exec printenv ) | grep FOO + +# ok, forget everything about hashed commands +hash -r +hash + +# this had better succeed, since command -p guarantees we will find the +# standard utilties +command -p hash rm + +# check out source/. + +# sourcing a zero-length-file had better not be an error +rm -f /tmp/zero-length-file +cp /dev/null /tmp/zero-length-file +. /tmp/zero-length-file +echo $? +rm /tmp/zero-length-file + +AVAR=AVAR + +. ./source1.sub +AVAR=foo . ./source1.sub + +. ./source2.sub +echo $? + +set -- a b c +. ./source3.sub + +# make sure source with arguments does not change the shell's positional +# parameters, but that the sourced file sees the arguments as its +# positional parameters +echo "$@" +. ./source3.sub x y z +echo "$@" + +# but if the sourced script sets the positional parameters explicitly, they +# should be reflected in the calling shell's positional parameters. this +# also tests one of the shopt options that controls source using $PATH to +# find the script +echo "$@" +shopt -u sourcepath +. source4.sub +echo "$@" + +# this is complicated when the sourced scripts gets its own positional +# parameters from arguments to `.' +set -- a b c +echo "$@" +. source4.sub x y z +echo "$@" + +# test out cd and $CDPATH +${THIS_SH} ./builtins1.sub + +# test behavior of `.' when given a non-existant file argument +${THIS_SH} ./source5.sub + +# test bugs in sourcing non-regular files, fixed post-bash-3.2 +${THIS_SH} ./source6.sub + +# test bugs with source called from multiline aliases and other contexts +${THIS_SH} ./source7.sub + +# in posix mode, assignment statements preceding special builtins are +# reflected in the shell environment. `.' and `eval' need special-case +# code. +set -o posix +echo $AVAR +AVAR=foo . ./source1.sub +echo $AVAR + +AVAR=AVAR +echo $AVAR +AVAR=foo eval echo \$AVAR +echo $AVAR + +AVAR=AVAR +echo $AVAR +AVAR=foo : +echo $AVAR +set +o posix + +# but assignment statements preceding `export' are always reflected in +# the environment +foo="" export foo +declare -p foo +unset foo + +# assignment statements preceding `declare' should be displayed correctly, +# but not persist after the command +FOO='$$' declare -p FOO +declare -p FOO +unset FOO + +# except for `declare -x', which should be equivalent to `export' +FOO='$$' declare -x FOO +declare -p FOO +unset FOO + +# test out kill -l. bash versions prior to 2.01 did `kill -l num' wrong +sigone=$(kill -l | sed -n 's:^ 1) *\([^ ]*\)[ ].*$:\1:p') + +case "$(kill -l 1)" in +${sigone/SIG/}) echo ok;; +*) echo oops -- kill -l failure;; +esac + +# kill -l and trap -l should display exactly the same output +sigonea=$(trap -l | sed -n 's:^ 1) *\([^ ]*\)[ ].*$:\1:p') + +if [ "$sigone" != "$sigonea" ]; then + echo oops -- kill -l and trap -l differ +fi + +# POSIX.2 says that exit statuses > 128 are mapped to signal names by +# subtracting 128 so you can find out what signal killed a process +case "$(kill -l $(( 128 + 1)) )" in +${sigone/SIG/}) echo ok;; +*) echo oops -- kill -l 129 failure;; +esac + +# out-of-range signal numbers should report the argument in the error +# message, not 128 less than the argument +kill -l 4096 + +# kill -l NAME should return the signal number +kill -l ${sigone/SIG/} + +# test behavior of shopt xpg_echo +${THIS_SH} ./builtins2.sub + +# test behavior of declare -g +${THIS_SH} ./builtins3.sub + +# test behavior of using declare to create variables without assigning values +${THIS_SH} ./builtins4.sub + +# test behavior of set and unset array variables +${THIS_SH} ./builtins5.sub + +# test behavior of unset builtin with -f and -v options +${THIS_SH} ./builtins6.sub + +# this must be last -- it is a fatal error +exit status + +echo after bad exit diff --git a/tests/builtins1.sub b/tests/builtins1.sub new file mode 100644 index 0000000..52185b5 --- /dev/null +++ b/tests/builtins1.sub @@ -0,0 +1,14 @@ +unset CDPATH + +MYDIR=$(pwd -P) +FULLDIR=/tmp/bash-dir-a +DIR=${FULLDIR##*/} + +mkdir $FULLDIR +CDPATH=.:/tmp +cd $DIR +pwd +echo $PWD + +cd "$MYDIR" +rmdir $FULLDIR diff --git a/tests/builtins2.sub b/tests/builtins2.sub new file mode 100644 index 0000000..e4cb32a --- /dev/null +++ b/tests/builtins2.sub @@ -0,0 +1,10 @@ +# test behavior of shopt xpg_echo + +USG_ECHO=off +shopt -q xpg_echo && USG_ECHO=on + +shopt -u xpg_echo +echo 'a\n\n\nb' + +shopt -s xpg_echo +echo 'a\n\n\nb' diff --git a/tests/builtins3.sub b/tests/builtins3.sub new file mode 100644 index 0000000..5596c56 --- /dev/null +++ b/tests/builtins3.sub @@ -0,0 +1,14 @@ +# declare -g added in bash-4.2 +f=4 + +foo() +{ + declare -g f=8 + declare -g bar=4 + + echo inside +} + +echo before: f = $f +foo +echo after: f = $f bar = $bar diff --git a/tests/builtins4.sub b/tests/builtins4.sub new file mode 100644 index 0000000..b7d0c0c --- /dev/null +++ b/tests/builtins4.sub @@ -0,0 +1,44 @@ +declare -a c +declare -p c + +declare -A d +declare -p d +unset c d + +declare -a c +c=4 +declare -p c +unset c + +declare -A c +c=4 +declare -p c +unset c + +declare -a c +c=(1 2 3) +declare -p c +unset c + +declare -A c +c=([one]=1 [two]=2 [three]=3) +declare -p c +unset c + +declare -a c +read -a c < <(echo 1 2 3) +declare -p c +unset c + +declare -a c +mapfile -t c < <(echo 1$'\n'2$'\n'3) +declare -p c +unset c + +unset foo +declare -A foo +echo ${foo-unset} + +unset foo +declare -a foo +echo ${foo-unset} diff --git a/tests/builtins5.sub b/tests/builtins5.sub new file mode 100644 index 0000000..9a5dd7b --- /dev/null +++ b/tests/builtins5.sub @@ -0,0 +1,61 @@ +# a start at a test suite for what it means for an array to be set or unset and +# how to test that state +typeset -A A +A[a]=1 +typeset -a a +a[1]=1 + +if [ -v A ]; then echo assoc 1; else echo assoc 1 unset; fi +if [ -v a ]; then echo array 1; else echo array 1 unset; fi + +if [ -v "${A[@]}" ]; then echo assoc 2; else echo assoc 2 unset; fi +if [ -v "${a[@]}" ]; then echo array 2; else echo array 2 unset; fi + +echo ${A-unset1} +echo ${a-unset2} + +echo ${A[@]-unset3} +echo ${a[@]-unset4} + +echo ${#A[@]} +echo ${#a[@]} + +typeset -A B +typeset -a b + +scalar1=foo +scalar2= + +if [ -v A[@] ]; then echo assoc A; else echo assoc A unset; fi +if [ -v a[@] ]; then echo array a; else echo array a unset; fi + +if [ -v B[@] ]; then echo assoc B; else echo assoc B unset; fi +if [ -v b[@] ]; then echo array b; else echo array b unset; fi + +if [ -v scalar1[@] ]; then echo scalar 1; else echo scalar 1 unset; fi +if [ -v scalar2[@] ]; then echo scalar 2; else echo scalar 2 unset; fi +if [ -v scalar3[@] ]; then echo scalar 3; else echo scalar 3 unset; fi + +unset a A +declare -A assoc=([one]=one [two]=two [three]=three) +declare -a array=(one two three) + +scalar="one two three" +scalar2= + +recho "${scalar[@]}" + +echo assoc: ${#assoc[@]} +echo array: ${#array[@]} + +echo scalar: ${#scalar} +echo scalar: ${#scalar[@]} + +echo scalar: ${#scalar2} +echo scalar: ${#scalar2[@]} + +echo scalar: ${#scalar3} +echo scalar: ${#scalar3[@]} + + + diff --git a/tests/builtins6.sub b/tests/builtins6.sub new file mode 100644 index 0000000..c18b476 --- /dev/null +++ b/tests/builtins6.sub @@ -0,0 +1,68 @@ +f1() +{ + echo f1 +} + +f2() +{ + echo f2 +} + +v1=one +v2=two + +echo all set: + +echo ${v1-unset1} +echo ${v2-unset2} + +declare -f -p f1 f2 + +unset v1 f1 v2 f2 + +echo all unset: + +echo ${v1-unset1} +echo ${v2-unset2} + +declare -f -p f1 f2 + +f1() +{ + echo f1 +} + +f2() +{ + echo f2 +} + +v1=one-one +v2=two-one + +echo all reset: +echo ${v1-unset1} +echo ${v2-unset2} + +declare -f -p f1 f2 + +unset -v v1 f1 v2 f2 + +echo vars unset: + +echo ${v1-unset1} +echo ${v2-unset2} + +declare -f -p f1 f2 + +v1=one-two +v2=two-two + +unset -f v1 f1 v2 f2 + +echo funcs unset: + +echo ${v1-unset1} +echo ${v2-unset2} + +declare -f f1 f2 diff --git a/tests/case.right b/tests/case.right new file mode 100644 index 0000000..d2055c9 --- /dev/null +++ b/tests/case.right @@ -0,0 +1,62 @@ +fallthrough +to here +and here +retest +and match +no more clauses +1.0 +./case.tests: line 29: xx: readonly variable +1.1 +matches 1 +no +no +no +no +no +ok +ok 1 +ok 2 +ok 3 +ok 4 +ok 5 +ok 6 +ok 7 +ok 8 +ok 9 +mysterious 1 +mysterious 2 +argv[1] = <\a\b\c\^A\d\e\f> +argv[1] = <\a\b\c\^A\d\e\f> +argv[1] = <abc^Adef> +ok 1 +ok 2 +ok 3 +ok 4 +ok 5 +ok 6 +ok 7 +ok 8 +--- testing: soh +ok1ok2ok3ok4ok5 +ok1ok2ok3ok4ok5 +ok1ok2ok3ok4ok5 +ok1ok2ok3ok4ok5 +ok1ok2ok3ok4ok5 +ok1ok2ok3ok4ok5 +ok1ok2ok3ok4ok5 +--- testing: stx +ok1ok2ok3ok4ok5 +ok1ok2ok3ok4ok5 +ok1ok2ok3ok4ok5 +ok1ok2ok3ok4ok5 +ok1ok2ok3ok4ok5 +ok1ok2ok3ok4ok5 +ok1ok2ok3ok4ok5 +--- testing: del +ok1ok2ok3ok4ok5 +ok1ok2ok3ok4ok5 +ok1ok2ok3ok4ok5 +ok1ok2ok3ok4ok5 +ok1ok2ok3ok4ok5 +ok1ok2ok3ok4ok5 +ok1ok2ok3ok4ok5 diff --git a/tests/case.tests b/tests/case.tests new file mode 100644 index 0000000..fe9c05a --- /dev/null +++ b/tests/case.tests @@ -0,0 +1,56 @@ +case foo in +bar) echo skip ;; +foo) echo fallthrough ;& +bax) echo to here ;& +qux) echo and here;; +fop) echo but not here;; +esac + +case foobar in +bar) echo skip ;; +foo*) echo retest ;;& +*bar) echo and match ;;& +qux) echo but not this ;; +esac + +case a in +a) echo no more clauses;& +esac + +x=0 y=1 +case 1 in + $((y=0)) ) ;; + $((x=1)) ) ;& + $((x=2)) ) echo $x.$y ;; +esac + +unset x +readonly xx=1 +case 1 in $((xx++)) ) echo hi1 ;; *) echo hi2; esac +echo ${xx}.$? + +unset var empty + +var= +case ']' in +[$var]*[$var]) echo matches 1;; +*) echo no match 1 ;; +esac + +case abc in ( [] ) echo yes ;; ( * ) echo no ;; esac +empty='' +case abc in ( ["$empty"] ) echo yes ;; ( * ) echo no ;; esac + +case abc in ( [] | [!a-z]* ) echo yes ;; ( * ) echo no ;; esac +empty='' +case abc in ( ["$empty"] | [!a-z]* ) echo yes ;; ( * ) echo no ;; esac + +case abc in (["$empty"]|[!a-z]*) echo yes ;; (*) echo no ;; esac + +case " " in ( [" "] ) echo ok;; ( * ) echo no;; esac + +# tests of quote removal and pattern matching +${THIS_SH} ./case1.sub +${THIS_SH} ./case2.sub +${THIS_SH} ./case3.sub +${THIS_SH} ./case4.sub diff --git a/tests/case1.sub b/tests/case1.sub new file mode 100644 index 0000000..7db09ab --- /dev/null +++ b/tests/case1.sub @@ -0,0 +1,64 @@ +x='\x' + +case x in +\x) echo ok 1;; +*) echo bad 1;; +esac + +case x in +$x) echo ok 2;; +*) echo bad 2;; +esac + +case $x in +\x) echo bad 3;; +\\x) echo ok 3 ;; +*) echo bad 3.1 ;; +esac + +case $x in +\\$x) echo ok 4 ;; +x) echo bad 4;; +$x) echo bad 4.1 ;; +*) echo bad 4.2;; +esac + +case x in +\\x) echo bad 5;; +\x) echo ok 5;; +*) echo bad 5.1;; +esac + +case x in +\\x) echo bad 6;; +x) echo ok 6;; +*) echo bad 6.1;; +esac + +case x in +$x) echo ok 7 ;; +\\$x) echo bad 7 ;; +*) echo bad 7.1 ;; +esac + +case x in +\x) echo ok 8 ;; +\\x) echo bad 8 ;; +*) echo bad 8.1 ;; +esac + +case \x in +\x) echo ok 9 ;; +\\x) echo bad 9 ;; +*) echo bad 9.1 ;; +esac + +case $x in +$x) echo oops 1 ;; +*) echo mysterious 1 ;; +esac + +case \x in +\x) echo mysterious 2 ;; +*) echo oops 2 ;; +esac diff --git a/tests/case2.sub b/tests/case2.sub new file mode 100644 index 0000000..085f888 --- /dev/null +++ b/tests/case2.sub @@ -0,0 +1,52 @@ +x=$'\\a\\b\\c\\\001\\d\\e\\f' +y='\a\b\c\\d\e\f' +z=$'abc\001def' + +recho "$x" +recho "$y" +recho "$z" + +case $'abc\001def' in +$x) echo ok 1 ;; +*) echo oops 1;; +esac + +case $z in +$x) echo ok 2 ;; +*) echo oops 2;; +esac + +case $'abc\001def' in +$y) echo ok 3 ;; +*) echo oops 3;; +esac + +case $z in +$y) echo ok 4 ;; +*) echo oops 4;; +esac + +# no backslash before \001 +x=$'\\a\\b\\c\001\\d\\e\\f' +y='\a\b\c\d\e\f' + +case $'abc\001def' in +$x) echo ok 5 ;; +*) echo oops 5;; +esac + +case $z in +$x) echo ok 6 ;; +*) echo oops 6;; +esac + +case $'abc\001def' in +$y) echo ok 7 ;; +*) echo oops 7;; +esac + +case $z in +$y) echo ok 8 ;; +*) echo oops 8;; +esac + diff --git a/tests/case3.sub b/tests/case3.sub new file mode 100644 index 0000000..77526c3 --- /dev/null +++ b/tests/case3.sub @@ -0,0 +1,40 @@ +#!/bin/sh + +testmatch() { + case $1 in + ( $2 ) printf ok1 ;; + ( * ) printf fail1 ;; + esac + case $1,$2 in + ( $2,"$2" ) printf ok2 ;; + ( * ) printf fail2 ;; + esac + case $1, in + ( $2, ) printf ok3 ;; + ( * ) printf fail3 ;; + esac + case ,$2 in + ( ,"$2" ) printf ok4 ;; + ( * ) printf fail4 ;; + esac + case "$1,$2" in + ( $2,"$2" ) printf ok5 ;; + ( * ) printf fail5 ;; + esac + echo +} + +for c in $'\1' $'\2' $'\177'; do + echo -n "--- testing: " + echo "$c" | od -t a | awk 'NR==1 { print $2 } ' + testmatch "${c}" "\\${c}" + testmatch "${c}x" "\\${c}\\x" # bash-git fails case 2 and 5 for $'\1' + testmatch "${c}x" "${c}\\x" + testmatch "${c}x" "${c}x" + testmatch "${c}x" "\\${c}x" + testmatch "x${c}" "\\x\\${c}" + testmatch "x${c}" "x\\${c}" +done + +match() { case $1 in ( $2 ) ;; ( * ) return 1 ;; esac; } +match $'? *x\1y\177z' $'??\\*\\x\\\1\\y\\\177\\z' || echo bad 6 diff --git a/tests/case4.sub b/tests/case4.sub new file mode 100644 index 0000000..56f88ba --- /dev/null +++ b/tests/case4.sub @@ -0,0 +1,25 @@ +shopt -s -o posix +two="t w o" +ten="t e +n" +set 1 "$two" 3 4 5 6 7 8 9 "$ten" + +unset IFS +expvar="$*" +case $* in +"$expvar") ;; +*) echo "failed 1" ;; +esac + +case $* in +$expvar) ;; +*) echo "failed 2" ;; +esac + +alias foo='oneword' +foo_word='foo' +case "$foo_word" +in + foo) ;; + *) echo failed 3;; +esac diff --git a/tests/casemod.right b/tests/casemod.right new file mode 100644 index 0000000..a584017 --- /dev/null +++ b/tests/casemod.right @@ -0,0 +1,49 @@ +Acknowledgement +ACKNOWLEDGEMENT +Oenophile +OEnOphIlE +aCKNOWLEDGEMENT +acknowledgement +oENOPHILE +oENOPHILE +oeNoPHiLe +Acknowledgement Oenophile +AcknOwlEdgEmEnt OEnOphIlE +aCKNOWLEDGEMENT oENOPHILE +aCKNoWLeDGeMeNT oeNoPHiLe +aCKNOWLEDGEMENT oENOPHILE +acknowledgement oenophile +Oenophile Acknowledgement +OENOPHILE ACKNOWLEDGEMENT +Oenophile Acknowledgement +OEnOphIlE AcknOwlEdgEmEnt +oENOPHILE aCKNOWLEDGEMENT +oenophile acknowledgement +oENOPHILE aCKNOWLEDGEMENT +oeNoPHiLe aCKNoWLeDGeMeNT +Acknowledgement Oenophile +ACKNOWLEDGEMENT OENOPHILE +acknowledgement oenophile +ackNowLEdgEmENT oENophiLE +acknowledgement oenophile +ackNowLEdgEmENT oENophiLE +acknowledgement oenophile +acknowledgement oenophile +acknowledgement oenophile +acknowledgement oenophile +Acknowledgement Oenophile +ACKNOWLEDGEMENT OENOPHILE +BE CONSERVATIVE IN WHAT YOU SEND AND LIBERAL IN WHAT YOU ACCEPT +be conservative in what you send and liberal in what you accept +Be conservative in what you send and liberal in what you accept +Be conservative in what you send and liberal in what you accept +be Conservative in what you send and Liberal in what you accept +be conservative in what you send and liberal in what you accept +Be Conservative in what you send and Liberal in what you accept +BE CONSERVATIVE IN WHAT YOU SEND AND LIBERAL IN WHAT YOU ACCEPT +Be conservative in what you send and liberal in what you accept +BE CONSERVATIVE IN WHAT YOU SEND AND LIBERAL IN WHAT YOU ACCEPT +AcknOwlEdgEmEnt acknOwlEdgEmEnt +oeNoPHiLe OEnOphIlE +abcdexyz +ABCDEXYZ diff --git a/tests/casemod.tests b/tests/casemod.tests new file mode 100644 index 0000000..dacdb0a --- /dev/null +++ b/tests/casemod.tests @@ -0,0 +1,113 @@ +S1=acknowledgement +S2=oenophile + +echo ${S1^} +echo ${S1^^} + +echo ${S2^[aeiou]} +echo ${S2^^[aeiou]} + +U1=${S1^^} +U2=${S2^^} + +echo ${U1,} +echo ${U1,,} + +echo ${U2,} +echo ${U2,[AEIOU]} +echo ${U2,,[AEIOU]} + +A1=( $S1 $S2 ) + +echo ${A1[@]^[aeiou]} +echo ${A1[@]^^[aeiou]} + +A2=( $U1 $U2 ) + +echo ${A2[@],[AEIOU]} +echo ${A2[@],,[AEIOU]} + +echo ${A2[@],?} +echo ${A2[@],,?} + +declare -A AA1 AA2 + +AA1[ack]=$S1 +AA1[oen]=$S2 + +echo ${AA1[@]^} +echo ${AA1[@]^^} + +echo ${AA1[@]^[aeiou]} +echo ${AA1[@]^^[aeiou]} + +AA2[ACK]=$U1 +AA2[OEN]=$U2 + +echo ${AA2[@],} +echo ${AA2[@],,} + +echo ${AA2[@],[AEIOU]} +echo ${AA2[@],,[AEIOU]} + +set -- $S1 $S2 + +echo ${@^} +echo ${@^^} + + +echo ${S1^[rstlne]} ${S2^[rstlne]} +echo ${S1^^[rstlne]} ${S2^^[rstlne]} + +echo ${@^[rstlne]} +echo ${@^^[rstlne]} + +echo ${S1,[rstlne]} ${S2,[rstlne]} +echo ${S1,,[rstlne]} ${S2,,[rstlne]} + +echo ${@,[rstlne]} +echo ${@,,[rstlne]} + +echo ${@^?} +echo ${@^^?} + +# make sure that multiple words in the string are handled as other expansions +TEXT="Be Conservative in what you send and Liberal in what you accept" +TEXT2="be conservative in what you send and liberal in what you accept" + +declare -u foo +foo=$TEXT +echo $foo + +declare -l bar +bar=$TEXT +echo $bar + +declare -c qux +qux=$TEXT +echo $qux +qux=$TEXT2 +echo $qux + +echo ${TEXT,} +echo ${TEXT,,} + +echo ${TEXT^} +echo ${TEXT^^} + +echo ${TEXT2^} +echo ${TEXT2^^} + +M1=${S1^^[aeiou]} +M2=${U2,,[AEIOU]} + +echo ${M1} ${M1~} +echo ${M2} ${M2~~} + +declare -l lower=aBcDe +lower+=XyZ +echo $lower + +declare -u upper=aBcDe +upper+=xYZ +echo $upper diff --git a/tests/comsub-eof.right b/tests/comsub-eof.right new file mode 100644 index 0000000..452a9c5 --- /dev/null +++ b/tests/comsub-eof.right @@ -0,0 +1,13 @@ +./comsub-eof0.sub: line 1: unexpected EOF while looking for matching `)' +./comsub-eof0.sub: line 5: syntax error: unexpected end of file +hi +./comsub-eof2.sub: line 2: warning: here-document at line 1 delimited by end-of-file (wanted `EOF') +hi +./comsub-eof3.sub: line 1: unexpected EOF while looking for matching `)' +./comsub-eof3.sub: line 5: syntax error: unexpected end of file +./comsub-eof4.sub: line 6: warning: here-document at line 4 delimited by end-of-file (wanted `EOF') +contents +./comsub-eof5.sub: line 8: warning: here-document at line 6 delimited by end-of-file (wanted `)') +hi +./comsub-eof5.sub: line 13: warning: here-document at line 11 delimited by end-of-file (wanted `EOF') +hi diff --git a/tests/comsub-eof.tests b/tests/comsub-eof.tests new file mode 100644 index 0000000..f96aeee --- /dev/null +++ b/tests/comsub-eof.tests @@ -0,0 +1,11 @@ +${THIS_SH} ./comsub-eof0.sub + +${THIS_SH} ./comsub-eof1.sub + +${THIS_SH} ./comsub-eof2.sub + +${THIS_SH} ./comsub-eof3.sub + +${THIS_SH} ./comsub-eof4.sub + +${THIS_SH} ./comsub-eof5.sub diff --git a/tests/comsub-eof0.sub b/tests/comsub-eof0.sub new file mode 100644 index 0000000..7b0775f --- /dev/null +++ b/tests/comsub-eof0.sub @@ -0,0 +1,4 @@ +foo=$(cat <<EOF +hi +EOF ) +echo $foo diff --git a/tests/comsub-eof1.sub b/tests/comsub-eof1.sub new file mode 100644 index 0000000..eaa0e97 --- /dev/null +++ b/tests/comsub-eof1.sub @@ -0,0 +1,4 @@ +foo=`cat <<EOF +hi +EOF` +echo $foo diff --git a/tests/comsub-eof2.sub b/tests/comsub-eof2.sub new file mode 100644 index 0000000..e93e6c8 --- /dev/null +++ b/tests/comsub-eof2.sub @@ -0,0 +1,2 @@ +cat <<EOF +hi diff --git a/tests/comsub-eof3.sub b/tests/comsub-eof3.sub new file mode 100644 index 0000000..f3038c7 --- /dev/null +++ b/tests/comsub-eof3.sub @@ -0,0 +1,4 @@ +foo=$(cat <<EOF +hi +) +echo $foo diff --git a/tests/comsub-eof4.sub b/tests/comsub-eof4.sub new file mode 100644 index 0000000..870ede9 --- /dev/null +++ b/tests/comsub-eof4.sub @@ -0,0 +1,4 @@ +e=$(cat <<EOF +contents +EOF) +echo $e diff --git a/tests/comsub-eof5.sub b/tests/comsub-eof5.sub new file mode 100644 index 0000000..3da9107 --- /dev/null +++ b/tests/comsub-eof5.sub @@ -0,0 +1,9 @@ +echo $( +cat <<\) +hi +)) + +echo $( +cat <<\EOF +hi +EOF) diff --git a/tests/comsub-posix.right b/tests/comsub-posix.right new file mode 100644 index 0000000..2290aa6 --- /dev/null +++ b/tests/comsub-posix.right @@ -0,0 +1,74 @@ +abmnopyz +abmnopyz +ab + + +abcd +sh_352.26ax +sh_352.26ay +sh_352.25a sh_352.25b +sh_352.27 ) ) ) +abc +here doc with ) +) +bad' syntax +a +sh_352.26a +sh_352.26a +sh_352.26 +sh_352.26 +sh_352.26 +1 +sh_352.28 ) +sh_352.28 ) +k +abcd +ab +ab +abcde + +argv[1] = <abcde^J > +abcdefoo +argv[1] = <abcde> +argv[2] = <foo> +argv[1] = <wxabcdeyz> +argv[1] = <abcde> +' +after 1 +' +after 2 +' +after 3 +` +after 4 +hello +after 5 +' +after 6 +x +x +quoted ) +comment +here-doc with ) +here-doc terminated with a parenthesis +' # or a single back- or doublequote +./comsub-posix1.sub: command substitution: line 2: syntax error near unexpected token `)' +./comsub-posix1.sub: command substitution: line 2: ` if x; then echo foo )' +after +swap32_posix is a function +swap32_posix () +{ + local funcname=swap32_posix; + local arg; + for arg in "$@"; + do + echo $(( + ($arg & 4278190080) >> 24 | + ($arg & 16711680) >> 8 | + ($arg & 65280) << 8 | + ($arg & 255) << 24 + )); + done +} +yes +ab cde diff --git a/tests/comsub-posix.tests b/tests/comsub-posix.tests new file mode 100644 index 0000000..d53e6eb --- /dev/null +++ b/tests/comsub-posix.tests @@ -0,0 +1,233 @@ +: ${HOME:=/} + +# works right +echo ab$(echo mnop)yz +# works right +echo ab$(echo mnop +)yz +# +# works right +echo $(echo ab + ) +# works right +echo $( +) +echo $() +echo ab$()cd + +echo $(case a in (a) echo sh_352.26ax; esac ) +echo $(case a in (a) echo sh_352.26ay; esac) + +echo $((echo sh_352.25a);(echo sh_352.25b)) + +echo $(echo sh_352.27 ')' ")" \) + # ) comment + ) + +echo $( +echo abc # a comment with ) +) + +echo $( +cat <<eof +here doc with ) +eof +) + +echo $( +echo ')' +) + +unset x +x=$(cat <<"EOF" +bad' syntax +EOF +) +echo "$x" +unset x + +echo $(for f in \); do echo a; done ) +echo $(case a in a) echo sh_352.26a; esac ) +echo $(case a in a) echo sh_352.26a; esac) + +echo $(case a in + (a) echo sh_352.26 + ;; + esac + ) + +echo $(case a in + a) echo sh_352.26 + ;; + esac + ) + + +echo $(case a in + a) echo sh_352.26 + ;; + + + + + + esac + + ) + +echo $(( 4<(2+3) ? 1 : 32)) + +echo $(cat << end +sh_352.28 ) +end +) + +echo $(cat <<- end +sh_352.28 ) + end +) + +k=$(case x in x) echo k;; esac) +echo $k + +x=$( + case $(ls) in + example) echo foobix;; + esac +) + +echo $( echo ab\ +cd) + +echo `echo ab +cd` + +echo `echo ab #xyz +cd` + +echo "$(echo abcde) +" + +recho "$(echo abcde) + " + +echo $(echo abcde)\ +foo + +recho $(echo abcde)\ + foo + +recho "wx$(echo abcde)yz" +recho "$(echo abcde)" + +echo $(cat <<eof +' +eof +) + +echo after 1 + +echo $(cat <<\eof +' +eof +) + +echo after 2 + +echo "$(cat <<\eof +' +eof +)" + +echo after 3 + +echo "$(cat <<\eof +` +eof +)" + +echo after 4 + +echo $( +cat << ')' +hello +) +) + +echo after 5 + +echo $(cat <<'eof' +' +eof +) + +echo after 6 + +echo $( + case x in x) echo x;; esac +) + +echo $( + case x in (x) echo x;; esac +) + +echo $( + echo 'quoted )' +) + +echo $( + echo comment # with ) +) + +echo $( +cat <<\eof + here-doc with ) +eof +) + +echo $( +cat <<\) + here-doc terminated with a parenthesis +) +) + +echo $( +cat <<\eof + ' # or a single back- or doublequote +eof +) + +${THIS_SH} ./comsub-posix1.sub + +${THIS_SH} ./comsub-posix2.sub + +${THIS_SH} ./comsub-posix3.sub + +# produced a parse error through bash-4.0-beta2 +: $(echo foo)" +" +# produced a parse error through bash-4.1 +unset x +x=$( +echo yes +# a comment with " ' \ +) +echo $x +unset x + +# fixed after bash-4.0 released +: $(case a in a) echo ;; # comment +esac) + +# fixed after bash-4.3 released +testing=$( + echo test | while read line; do + case $line in + test) echo saw test ;; + *) echo other ;; + esac + done +) + +# recommended to be parsed as a nested comsub instead of arithsub +echo $(( echo ab cde ) ) diff --git a/tests/comsub-posix1.sub b/tests/comsub-posix1.sub new file mode 100644 index 0000000..bbcc60f --- /dev/null +++ b/tests/comsub-posix1.sub @@ -0,0 +1,3 @@ +echo $( if x; then echo foo ) + +echo after diff --git a/tests/comsub-posix2.sub b/tests/comsub-posix2.sub new file mode 100644 index 0000000..238745f --- /dev/null +++ b/tests/comsub-posix2.sub @@ -0,0 +1,16 @@ +# problem with bash-4.x versions before bash-4.2. required posix interp +swap32_posix() +{ + local funcname=swap32_posix + local arg + for arg in "$@"; do + echo $(( + ($arg & 4278190080) >> 24 | + ($arg & 16711680) >> 8 | + ($arg & 65280) << 8 | + ($arg & 255) << 24 + )) + done +} + +type swap32_posix diff --git a/tests/comsub-posix3.sub b/tests/comsub-posix3.sub new file mode 100644 index 0000000..3a0e39a --- /dev/null +++ b/tests/comsub-posix3.sub @@ -0,0 +1,22 @@ +# parsing errors before bash-4.2 + +a=$(/bin/cat << EOF | wc -l +a +b +c +EOF +) + +a=$(cat << EOF | wc -l +a +b +c +EOF +) + +a=$(/bin/cat << EOF +a +b +c +EOF +) diff --git a/tests/comsub.right b/tests/comsub.right new file mode 100644 index 0000000..71bb205 --- /dev/null +++ b/tests/comsub.right @@ -0,0 +1,57 @@ +./comsub.tests: line 7: hijkl: command not found +argv[1] = <ab> +argv[2] = <cd> +argv[1] = <abmn> +argv[2] = <opyz> +argv[1] = <b> +argv[1] = <a\> +argv[2] = <b> +argv[1] = <$> +argv[2] = <bab> +argv[1] = <`> +argv[2] = <ab> +argv[1] = <\> +argv[2] = <ab> +argv[1] = <foo \\^Jbar> +argv[1] = <foo \^Jbar> +argv[1] = <sed> argv[2] = <-e> argv[3] = <s/[^I:]/\^J/g> +argv[1] = <sed> argv[2] = <-e> argv[3] = <s/[^I:]//g> +argv[1] = <foo\^Jbar> +argv[1] = <foobar> +argv[1] = <foo\^Jbar> +#esac +a +ok 1 +ok 2 +ok 3 +ok 4 +ok 5 +ok 6 +xyz +ok 7 +\/tmp\/foo\/bar +/tmp/foo/bar +/tmp/foo/bar +/tmp/foo/bar +1 +2 +3 +4 +5 +6 +5 +6 +a +b +c +a +b +c +1 +2 +d \ +g +d \ +g +d \ +g diff --git a/tests/comsub.tests b/tests/comsub.tests new file mode 100644 index 0000000..ed56007 --- /dev/null +++ b/tests/comsub.tests @@ -0,0 +1,62 @@ +# command substution parsing tests + +TABSIZE=`grep -v '^[ #]' $CAPS </dev/null | grep -v "^$" | grep -v "^capalias"| grep -v "^infoalias" | wc -l` + +recho `echo ab cd #efg +hijkl` + +recho ab$(echo mn; echo op)yz + +a=`echo 'a b c' | sed 's/ /\\ +/g' | grep 'b'` +recho $a + +recho `echo 'a\' b` + +recho `echo '\$' bab` + +recho `echo '\`' ab` + +recho `echo '\\' ab` + +# old-style command substitution parsing compatibility tests -- post bash-3.1 +recho 'foo \\ +bar' + +recho 'foo \ +bar' + +echo `recho sed -e 's/[ :]/\\ +/g'` + +echo `recho sed -e 's/[ :]/\ +/g'` + +echo `recho 'foo\\ +bar'` + +echo `recho 'foo\ +bar'` + +echo $(recho 'foo\ +bar') + +# long-standing parse error in all versions up through bash-4.3 +echo ${foo:-$(echo a{b,c})} >/dev/null + +# parsing problem based on recursively calling bison parser through bash-4.4 +for (( INDEX=0; INDEX<$((10-$(echo length $V_NAME))); INDEX++ )) +do + : +done + +# problem with four-character words followed by a metachar through bash-4.4 +comsub_foo_1() +{ + echo $(while true; do case $HOME in /*) echo abs ;; esac; done) +} + +${THIS_SH} ./comsub1.sub +${THIS_SH} ./comsub2.sub +${THIS_SH} ./comsub3.sub +${THIS_SH} ./comsub4.sub diff --git a/tests/comsub1.sub b/tests/comsub1.sub new file mode 100644 index 0000000..b1af263 --- /dev/null +++ b/tests/comsub1.sub @@ -0,0 +1,60 @@ +: $(echo \;) + +: $(case a in a) echo ;;# comment +esac) + +: $(case a in a) echo ;; # comment +esac) + +: $(: \;# not a comment ) + +: $(: \ # not a comment) + +echo $(case a in a) echo \#esac ;; +esac) + +: $(case a in a) : ;#esac ;; +esac) + +: $(case a in a) : ;#esac comment ) +esac) + +: $(case a in a) : ; +esac) + +echo $(#comment ) +echo a) + +echo $(case a in (a) echo ok 1;; # comment +esac) + +echo $(case a in (a) echo ok 2;; # comment +(b) echo moo;; +esac) + +echo $(case a in (a) echo ok 3 # comment +;; +esac) + +echo $(case a in a) echo ok 4;; # comment +esac) + +echo $(case a in a) echo ok 5;; # comment +b) echo moo;; +esac) + +echo $(case a in (a) echo ok 6 # comment +;; +esac) + +echo $( # we just took and pasted in some +# code from another script inside a +# command substitution +echo xyz +) + +# problem with parse_comsub through bash-4.4 +case $(echo $$'x\nx') in +x*) echo bad 7;; +*) echo ok 7;; +esac diff --git a/tests/comsub2.sub b/tests/comsub2.sub new file mode 100644 index 0000000..d60ae6a --- /dev/null +++ b/tests/comsub2.sub @@ -0,0 +1,8 @@ +qpath='\/tmp\/foo\/bar' + +echo "$qpath" + +# it's crazy that all three of these produce the same result +printf "%s\n" ${qpath//\\/} +printf "%s\n" ${qpath//"`printf '%s' \\`"/} +printf "%s\n" ${qpath//`printf '%s' "\\\\\\\\"`/} diff --git a/tests/comsub3.sub b/tests/comsub3.sub new file mode 100644 index 0000000..6947400 --- /dev/null +++ b/tests/comsub3.sub @@ -0,0 +1,31 @@ +x=$( + case 1 in + 1) echo 1 + esac + case 2 in + 2) echo 2 + esac +) +echo "$x" + +x=$(case 1 in 1) echo 3;; esac; case 2 in 2) echo 4;; esac;) +echo "$x" + +x=$(case 1 in 1) echo 5;; esac; case 2 in 2) echo 6;; esac) +echo "$x" + +x=$(case 1 in 1) echo 5;; esac; case 2 in 2) echo 6;; esac; for f in a b c; do echo "$f" ; done) +echo "$x" + +x=$( + for f in a b c; do + echo $f + done + case 1 in + 1) echo 1 + esac + case 2 in + 2) echo 2 + esac +) +echo "$x" diff --git a/tests/comsub4.sub b/tests/comsub4.sub new file mode 100644 index 0000000..461a9ad --- /dev/null +++ b/tests/comsub4.sub @@ -0,0 +1,27 @@ +x=$(cat <<'EOT' +d \ +g +EOT +) + +echo "$x" +unset x + +x=$( cat <<\EOT\ +4 +d \ +g +EOT4 +) + +echo "$x" +unset x + +x=$( cat <<\EOT +d \ +g +EOT +) + +echo "$x" + diff --git a/tests/cond-regexp1.sub b/tests/cond-regexp1.sub new file mode 100644 index 0000000..dd287cb --- /dev/null +++ b/tests/cond-regexp1.sub @@ -0,0 +1,56 @@ +VAR='[[:alpha:]]' + +[[ $VAR =~ '[[:alpha:]]' ]] && echo match 1 + +[[ a =~ '[[:alpha:]]' ]] || echo match 2 + +[[ a =~ [[:alpha:]] ]] && echo match 3 + +[[ a =~ $VAR ]] && echo match 4 + +[[ a =~ "$VAR" ]] || echo match 5 + +line=aab +[[ $line =~ [[:space:]]*(a)?b ]] && echo match 6 + +V="alphabet" +[[ $V == alphabet ]] && echo yes 1 +[[ $V == "alphabet" ]] && echo yes 2 +[[ $V == 'alphabet' ]] && echo yes 3 +[[ $V =~ alphabet ]] && echo yes 4 +[[ $V =~ "alphabet" ]] && echo yes 5 +[[ $V =~ 'alphabet' ]] && echo yes 6 + +DOG="Dog name - 01 - Wiggles" +REPAT='([[:alpha:][:blank:]]*)- ([[:digit:]]*) - (.*)$' +if [[ $DOG =~ ([[:alpha:][:blank:]]*)-\ ([[:digit:]]*)\ -\ (.*)$ ]] +then + echo Dog ${BASH_REMATCH[2]} is ${BASH_REMATCH[3]} +fi +if [[ $DOG =~ $REPAT ]] +then + echo Dog ${BASH_REMATCH[2]} is ${BASH_REMATCH[3]} +fi + +[[ $REPAT =~ "$REPAT" ]] && echo rematch 1 + +v="one two buckle my shoe" +[[ ${v} =~ "one two" ]] && echo matches 7 + +[[ ${v} =~ (one two) ]] && echo matches 8 + +[[ ${v} =~ one\ two ]] && echo matches 9 + +unset pattern string +pattern="xxx.yyy" +string=xxxAyyy + +[[ $string =~ $pattern ]] && echo unquoted matches +[[ $string =~ "$pattern" ]] && echo quoted matches + +# problems in pre-patched bash-4.2 +[[ "helloworld" =~ llo ]] && echo match control-a 1 +[[ "helloworld" =~ world ]] && echo match control-a 2 +[[ "helloworld" =~ world$ ]] && echo match control-a 3 +[[ "helloworld" =~ ]] && echo match control-a 4 +[[ "helloworld" =~ oworld$ ]] && echo match control-a 5 diff --git a/tests/cond-regexp2.sub b/tests/cond-regexp2.sub new file mode 100644 index 0000000..2bea638 --- /dev/null +++ b/tests/cond-regexp2.sub @@ -0,0 +1,32 @@ +[[ "\\" =~ ["."] ]] && echo bad 1 + +[[ "\\" =~ "[.]" ]] && echo bad 2 + +[[ "\\" =~ [\. ]] && echo bad 3 + +[[ "\\" =~ [\.] ]] && echo bad 4 + +[[ "\\" =~ [\\] ]] || echo bad 5 + +[[ dog =~ [[=d=]].. ]] && echo ok 1 +[[ d.. =~ [[=d=]]\.\. ]] && echo ok 2 +[[ dog =~ ['[=d=]'].. ]] && echo ok 3 # dubious + +[[ dog =~ [[=d=]].[[=G=][=g=]] ]] && echo ok 4 +[[ dog =~ [[=d=]].[\[=G=][=g=]] ]] && echo ok 4a + +[[ dog =~ "d.." ]] || echo ok 5 + +[[ dog =~ [[.d.][.D.]]o. ]] && echo ok 6 + +[[ dog =~ ([[.d.][.D.]])o(.) ]] && echo ok 7 -- ${BASH_REMATCH[1]} +[[ dog =~ d([[.o.][.O.]])(.) ]] && echo ok 8 -- ${BASH_REMATCH[1]} +[[ dog =~ .([[.o.][.O.]])(.) ]] && echo ok 9 + +[[ dog =~ 'd''o''g' ]] && echo ok 10 + +[[ ']' =~ [']'] ]] && echo ok 11 + +[[ a =~ ['a]'] ]] || echo ok 12 + +[[ "\\" =~ [^]"."] ]] || echo unexpected diff --git a/tests/cond-regexp3.sub b/tests/cond-regexp3.sub new file mode 100644 index 0000000..8f09841 --- /dev/null +++ b/tests/cond-regexp3.sub @@ -0,0 +1,73 @@ +# simple expansion -- no problem, it's quote_string_for_globbing that was flawed +c=$'\177' +r="\\$c" + +recho $r + +# first, match some regular expressions containing ^A, ^G, ^? +[[ $'\001' =~ $'\001' ]] ; echo $? +[[ $'\001' =~ $'\\\001' ]] ; echo $? +[[ $'\001' =~ $'\\[\001]' ]] ; echo $? + +[[ $'\a' =~ $'\a' ]] ; echo $? +[[ $'\a' =~ $'\\\a' ]] ; echo $? +[[ $'\a' =~ $'\\[\a]' ]] ; echo $? + +[[ $'\177' =~ $'\177' ]] ; echo $? +[[ $'\177' =~ $'\\\177' ]] ; echo $? +[[ $'\177' =~ $'\\[\177]' ]] ; echo $? + +# Now let's try it with variables expanding to those values +for c in $'\001' $'\a' $'\177' ; do + for r in "$c" "\\$c" "\\[$c]"; do + [[ $c =~ $r ]]; + printf '[[ %q =~ %q ]] -> %d\n' "$c" "$r" "$?"; + done; + printf %s\\n --- +done + +# try again with literals + +[[ '' =~ $'' ]] ; echo $? +[[ '' =~ '\' ]] ; echo $? +[[ '' =~ '\[]' ]] ; echo $? + +[[ '' =~ '' ]] ; echo $? +[[ '' =~ '\' ]] ; echo $? +[[ '' =~ '\[]' ]] ; echo $? + +[[ '' =~ $'' ]] ; echo $? +[[ '' =~ '\' ]] ; echo $? +[[ '' =~ '\[]' ]] ; echo $? + +# more expansions, but with literal non-special characters +[[ x =~ \x ]] ; echo $? +[[ x =~ \\x ]] ; echo $? + +bs='\' +[[ x =~ ${bs}x ]] ; echo $? + +[[ x =~ $'\\'x ]] ; echo $? +[[ x =~ '\'x ]] ; echo $? + +v='a\-b' +[[ a-b =~ ${v} ]] ; echo $? +[[ a-b =~ a\-b ]]; echo $? +[[ a-b =~ a${bs}-b ]]; echo $? +[[ a-b =~ a\\-b ]] ; echo $? +[[ a-b =~ "a\-b" ]] ; echo $? + +c=$'\001' + +recho $c "$c" + +[[ $c == $c ]] && echo ok 1 +[[ $c =~ $c ]] && echo ok 2 +[[ $c =~ \\$c ]] || echo ok 3 +[[ $c =~ \\"$c" ]] || echo ok 4 + +[[ $c =~ "\\"$c ]] || echo ok 5 +[[ $c =~ '\'$c ]] || echo ok 6 + +[[ $c =~ "\\""$c" ]] || echo ok 7 +[[ $c =~ '\'"$c" ]] || echo ok 8 diff --git a/tests/cond.right b/tests/cond.right new file mode 100644 index 0000000..18ebd06 --- /dev/null +++ b/tests/cond.right @@ -0,0 +1,136 @@ +returns: 0 +returns: 0 +returns: 1 +returns: 0 +returns: 0 +returns: 0 +returns: 0 +returns: 0 +returns: 1 +returns: 0 +returns: 0 +returns: 1 +returns: 1 +returns: 1 +returns: 1 +returns: 0 +returns: 0 +returns: 0 +returns: 1 +returns: 0 +returns: 1 +returns: 0 +returns: 1 +returns: 1 +returns: 0 +./cond.tests: line 101: [[: 4+: syntax error: operand expected (error token is "+") +returns: 1 +returns: 0 +returns: 0 +returns: 1 +returns: 0 +returns: 0 +returns: 1 +returns: 0 +ok +jbig2dec + +found 1 +libc +found 2 +libc +ok 42 +ok 43 +ok 1 +ok 2 +ok 3 +ok 4 +ok 5 +match 1 +match 2 +match 3 +match 4 +match 5 +match 6 +yes 1 +yes 2 +yes 3 +yes 4 +yes 5 +yes 6 +Dog 01 is Wiggles +Dog 01 is Wiggles +rematch 1 +matches 7 +matches 8 +matches 9 +unquoted matches +match control-a 1 +match control-a 2 +match control-a 3 +match control-a 4 +match control-a 5 +ok 1 +ok 2 +ok 3 +ok 4 +ok 4a +ok 5 +ok 6 +ok 7 -- d +ok 8 -- o +ok 9 +ok 10 +ok 11 +ok 12 +argv[1] = <\^?> +0 +1 +1 +0 +1 +1 +0 +1 +1 +[[ $'\001' =~ $'\001' ]] -> 0 +[[ $'\001' =~ $'\\\001' ]] -> 0 +[[ $'\001' =~ $'\\[\001]' ]] -> 1 +--- +[[ $'\a' =~ $'\a' ]] -> 0 +[[ $'\a' =~ $'\\\a' ]] -> 0 +[[ $'\a' =~ $'\\[\a]' ]] -> 1 +--- +[[ $'\177' =~ $'\177' ]] -> 0 +[[ $'\177' =~ $'\\\177' ]] -> 0 +[[ $'\177' =~ $'\\[\177]' ]] -> 1 +--- +0 +1 +1 +0 +1 +1 +0 +1 +1 +0 +1 +0 +1 +1 +0 +0 +0 +1 +1 +argv[1] = <^A> +argv[2] = <^A> +ok 1 +ok 2 +ok 3 +ok 4 +ok 5 +ok 6 +ok 7 +ok 8 diff --git a/tests/cond.tests b/tests/cond.tests new file mode 100755 index 0000000..2cef929 --- /dev/null +++ b/tests/cond.tests @@ -0,0 +1,201 @@ +# +# the test/[ code is tested elsewhere, and the [[...]] just uses the same +# code. this tests the special features of [[...]] +# +TDIR=/usr/homes/chet + +# this one is straight out of the ksh88 book +[[ foo > bar && $PWD -ef . ]] +echo returns: $? + +# [[ x ]] is equivalent to [[ -n x ]] +[[ x ]] +echo returns: $? + +# [[ ! x ]] is equivalent to [[ ! -n x ]] +[[ ! x ]] +echo returns: $? + +# ! binds tighter than test/[ -- it binds to a term, not an expression +[[ ! x || x ]] +echo returns: $? + +# parenthesized terms didn't work right until post-2.04 +[[ a ]] +echo returns: $? + +[[ (a) ]] +echo returns: $? + +[[ -n a ]] +echo returns: $? + +[[ (-n a) ]] +echo returns: $? + +# unset variables don't need to be quoted +[[ -n $UNSET ]] +echo returns: $? + +[[ -z $UNSET ]] +echo returns: $? + +# the ==/= and != operators do pattern matching +[[ $TDIR == /usr/homes/* ]] +echo returns: $? + +# ...but you can quote any part of the pattern to have it matched as a string +[[ $TDIR == /usr/homes/\* ]] +echo returns: $? + +[[ $TDIR == '/usr/homes/*' ]] +echo returns: $? + +# if the first part of && fails, the second is not executed +[[ -n $UNSET && $UNSET == foo ]] +echo returns: $? + +[[ -z $UNSET && $UNSET == foo ]] +echo returns: $? + +# if the first part of || succeeds, the second is not executed +[[ -z $UNSET || -d $PWD ]] +echo returns: $? + +# if the rhs were executed, it would be an error +[[ -n $TDIR || $HOME -ef ${H*} ]] +echo returns: $? + +[[ -n $TDIR && -z $UNSET || $HOME -ef ${H*} ]] +echo returns: $? + +# && has a higher parsing precedence than || +[[ -n $TDIR && -n $UNSET || $TDIR -ef . ]] +echo returns: $? + +# ...but expressions in parentheses may be used to override precedence rules +[[ -n $TDIR || -n $UNSET && $PWD -ef xyz ]] +echo returns: $? + +[[ ( -n $TDIR || -n $UNSET ) && $PWD -ef xyz ]] +echo returns: $? + +# some arithmetic tests for completeness -- see what happens with missing +# operands, bad expressions, makes sure arguments are evaluated as +# arithmetic expressions, etc. + +unset IVAR A +[[ 7 -gt $IVAR ]] +echo returns: $? + +[[ $IVAR -gt 7 ]] +echo returns: $? + +IVAR=4 +[[ $IVAR -gt 7 ]] +echo returns: $? + +[[ 7 -eq 4+3 ]] +echo returns: $? + +[[ 7 -eq 4+ ]] +echo returns: $? + +IVAR=4+3 +[[ $IVAR -eq 7 ]] +echo returns: $? + +A=7 +[[ $IVAR -eq A ]] +echo returns: $? + +unset IVAR A + +# more pattern matching tests + +[[ $filename == *.c ]] +echo returns: $? + +filename=patmatch.c + +[[ $filename == *.c ]] +echo returns: $? + +# the extended globbing features may be used when matching patterns +shopt -s extglob + +arg=-7 + +[[ $arg == -+([0-9]) ]] +echo returns: $? + +arg=-H + +[[ $arg == -+([0-9]) ]] +echo returns: $? + +arg=+4 +[[ $arg == ++([0-9]) ]] +echo returns: $? + +# make sure the null string is never matched if the string is not null +STR=file.c +PAT= + +if [[ $STR = $PAT ]]; then + echo oops +fi + +# but that if the string is null, a null pattern is matched correctly +STR= +PAT= + +if [[ $STR = $PAT ]]; then + echo ok +fi + +# test the regular expression conditional operator +[[ jbig2dec-0.9-i586-001.tgz =~ ([^-]+)-([^-]+)-([^-]+)-0*([1-9][0-9]*)\.tgz ]] +echo ${BASH_REMATCH[1]} + +# this shouldn't echo anything +[[ jbig2dec-0.9-i586-001.tgz =~ \([^-]+\)-\([^-]+\)-\([^-]+\)-0*\([1-9][0-9]*\)\.tgz ]] +echo ${BASH_REMATCH[1]} + +LDD_BASH=" linux-gate.so.1 => (0xffffe000) + libreadline.so.5 => /lib/libreadline.so.5 (0xb7f91000) + libhistory.so.5 => /lib/libhistory.so.5 (0xb7f8a000) + libncurses.so.5 => /lib/libncurses.so.5 (0xb7f55000) + libdl.so.2 => /lib/libdl.so.2 (0xb7f51000) + libc.so.6 => /lib/libc.so.6 (0xb7e34000) + /lib/ld-linux.so.2 (0xb7fd0000)" + +[[ "$LDD_BASH" =~ "libc" ]] && echo "found 1" +echo ${BASH_REMATCH[@]} + +[[ "$LDD_BASH" =~ libc ]] && echo "found 2" +echo ${BASH_REMATCH[@]} + +# bug in all versions up to and including bash-2.05b +if [[ "123abc" == *?(a)bc ]]; then echo ok 42; else echo bad 42; fi +if [[ "123abc" == *?(a)bc ]]; then echo ok 43; else echo bad 43; fi + +match() { [[ $1 == $2 ]]; } +match $'? *x\1y\177z' $'??\\*\\x\\\1\\y\\\177\\z' || echo bad 44 + +foo="" +[[ bar == *"${foo,,}"* ]] && echo ok 1 +[[ bar == *${foo,,}* ]] && echo ok 2 + +shopt -s extquote +bs='\' +del=$'\177' +[[ bar == *$bs"$del"* ]] || echo ok 3 +[[ "" == "$foo" ]] && echo ok 4 +[[ "$del" == "${foo,,}" ]] || echo ok 5 + +${THIS_SH} ./cond-regexp1.sub + +${THIS_SH} ./cond-regexp2.sub + +${THIS_SH} ./cond-regexp3.sub diff --git a/tests/coproc.right b/tests/coproc.right new file mode 100644 index 0000000..94b001c --- /dev/null +++ b/tests/coproc.right @@ -0,0 +1,10 @@ +63 60 +a b c +63 60 +flop +coproc.tests: REFLECT: status 143 +63 60 +FOO +63 60 +root +-1 -1 diff --git a/tests/coproc.tests b/tests/coproc.tests new file mode 100644 index 0000000..5066f7c --- /dev/null +++ b/tests/coproc.tests @@ -0,0 +1,65 @@ +: ${TMPDIR:=/tmp} +TMPOUT=${TMPDIR}/coproc-wait-$BASHPID + +coproc { echo a b c; sleep 2; } + +case $COPROC_PID in +[0-9]*) ;; +*) echo COPROC_PID not integer ;; +esac + +echo ${COPROC[@]} + +read LINE <&${COPROC[0]} +echo $LINE + +wait $COPROC_PID + +coproc REFLECT { cat - ; } + +case $REFLECT_PID in +[0-9]*) ;; +*) echo REFLECT_PID not integer ;; +esac + +echo ${REFLECT[@]} + +echo flop >&${REFLECT[1]} +read LINE <&${REFLECT[0]} + +echo $LINE + +{ sleep 1; kill $REFLECT_PID; } & +wait $REFLECT_PID >$TMPOUT 2>&1 || { status=$? ; echo "coproc.tests: REFLECT: status $status" ; } +[[ $status < 128 || $status == 143 ]] || { + echo "coproc.tests: wait for REFLECT failed" >&2 +} +rm -f $TMPOUT +exec 2>&1 + +coproc xcase -n -u + +case $COPROC_PID in +[0-9]*) ;; +*) echo COPROC_PID not integer ;; +esac + +echo ${COPROC[@]} + +echo foo >&${COPROC[1]} +read <&${COPROC[0]} + +echo $REPLY +echo ${COPROC[@]} + +cat /etc/passwd | grep root | awk -F: '{print $1;}' | sed 1q + +exec 4<&${COPROC[0]}- +exec >&${COPROC[1]}- + +echo ${COPROC[@]} + +read foo <&4 +echo $foo >&2 + +exit 0 diff --git a/tests/cprint.right b/tests/cprint.right new file mode 100644 index 0000000..2000072 --- /dev/null +++ b/tests/cprint.right @@ -0,0 +1,72 @@ +tf is a function +tf () +{ + echo this is ${0##*/} > /dev/null; + echo a | cat - > /dev/null; + test -f ${0##*/} && echo ${0##*/} is a regular file; + test -d ${0##*/} || echo ${0##*/} is not a directory; + echo a; + echo b; + echo c; + echo background > /dev/null & ( exit 1 ); + echo $?; + { + echo a + }; + i=0; + while (( i < 3 )); do + test -r /dev/fd/$i; + i=$(( i + 1 )); + done; + [[ -r /dev/fd/0 && -w /dev/fd/1 ]] || echo oops > /dev/null; + for name in $( echo 1 2 3 ); + do + test -r /dev/fd/$name; + done; + if [[ -r /dev/fd/0 && -w /dev/fd/1 ]]; then + echo ok > /dev/null; + else + if (( 7 > 40 )); then + echo oops; + else + echo done; + fi; + fi > /dev/null; + case $PATH in + *$PWD*) + echo \$PWD in \$PATH + ;; + *) + echo \$PWD not in \$PATH + ;; + esac > /dev/null; + while false; do + echo z; + done > /dev/null; + until true; do + echo z; + done > /dev/null; + echo \&\|'()' \{ echo abcde \; \}; + eval fu\%nc'()' \{ echo abcde \; \}; + type fu\%nc +} +tf2 is a function +tf2 () +{ + ( { + time -p echo a | cat - > /dev/null + } ) 2>&1 +} +cprint.tests is a regular file +cprint.tests is not a directory +a +b +c +1 +a +&|() { echo abcde ; } +fu%nc is a function +fu%nc () +{ + echo abcde +} diff --git a/tests/cprint.tests b/tests/cprint.tests new file mode 100644 index 0000000..08ff1eb --- /dev/null +++ b/tests/cprint.tests @@ -0,0 +1,67 @@ +# +# a nonsense script and shell function to test out the command printing code +# +tf() +{ + # simple command with redir + echo this is ${0##*/} > /dev/null + + # pipeline + echo a | cat - > /dev/null + + test -f ${0##*/} && echo ${0##*/} is a regular file + test -d ${0##*/} || echo ${0##*/} is not a directory + + echo a ; echo b ; echo c + + echo background >/dev/null & + + ( exit 1 ) + echo $? + + { echo a ; } + + i=0 + while (( i < 3 )); do + test -r /dev/fd/$i + i=$(( i + 1 )) + done + + [[ -r /dev/fd/0 && -w /dev/fd/1 ]] || echo oops > /dev/null + + for name in $( echo 1 2 3 ); do + test -r /dev/fd/$name + done + + if [[ -r /dev/fd/0 && -w /dev/fd/1 ]] ; then + echo ok > /dev/null + elif (( 7 > 40 )) ; then + echo oops + else + echo done + fi > /dev/null + + case $PATH in + *$PWD*) echo \$PWD in \$PATH ;; + *) echo \$PWD not in \$PATH ;; + esac > /dev/null + + while false; do echo z; done > /dev/null + + until true; do echo z ; done > /dev/null + + echo \&\|'()' \{ echo abcde \; \} + # when not in POSIX mode, we can have weirdly-named functions + eval fu\%nc'()' \{ echo abcde \; \} + type fu\%nc +} + +tf2() +{ + ( { time -p echo a | cat - > /dev/null ; } ) 2>&1 +} + +type tf +type tf2 + +tf diff --git a/tests/dbg-support.right b/tests/dbg-support.right new file mode 100644 index 0000000..c4a1609 --- /dev/null +++ b/tests/dbg-support.right @@ -0,0 +1,371 @@ +debug lineno: 63 main +debug lineno: 66 main +FUNCNAME main +debug lineno: 70 main +debug lineno: 17 fn1 +debug lineno: 18 fn1 +LINENO 18 +debug lineno: 19 fn1 +LINENO 19 +debug lineno: 20 fn1 +BASH_SOURCE[0] ./dbg-support.tests +debug lineno: 21 fn1 +FUNCNAME[0] fn1 +debug lineno: 22 fn1 +debug lineno: 22 fn1 70 ./dbg-support.tests +debug lineno: 23 fn1 +debug lineno: 23 fn1 70 main ./dbg-support.tests +debug lineno: 24 fn1 +debug lineno: 24 fn1 +debug lineno: 25 fn1 +./dbg-support.tests: line 25: caller: foo: invalid number +caller: usage: caller [expr] +debug lineno: 25 fn1 +debug lineno: 17 fn1 +debug lineno: 12 print_return_trap +debug lineno: 13 print_return_trap +return lineno: 17 fn1 +debug lineno: 14 print_return_trap +debug lineno: 71 main +debug lineno: 28 fn2 +debug lineno: 29 fn2 +fn2 here. Calling fn1... +debug lineno: 30 fn2 +debug lineno: 17 fn1 +debug lineno: 18 fn1 +LINENO 18 +debug lineno: 19 fn1 +LINENO 19 +debug lineno: 20 fn1 +BASH_SOURCE[0] ./dbg-support.tests +debug lineno: 21 fn1 +FUNCNAME[0] fn1 +debug lineno: 22 fn1 +debug lineno: 22 fn1 30 ./dbg-support.tests +debug lineno: 23 fn1 +debug lineno: 23 fn1 30 fn2 ./dbg-support.tests +debug lineno: 24 fn1 +debug lineno: 24 fn1 71 main ./dbg-support.tests +debug lineno: 25 fn1 +./dbg-support.tests: line 25: caller: foo: invalid number +caller: usage: caller [expr] +debug lineno: 25 fn1 +debug lineno: 17 fn1 +debug lineno: 12 print_return_trap +debug lineno: 13 print_return_trap +return lineno: 17 fn1 +debug lineno: 14 print_return_trap +debug lineno: 28 fn2 +debug lineno: 12 print_return_trap +debug lineno: 13 print_return_trap +return lineno: 28 fn2 +debug lineno: 14 print_return_trap +debug lineno: 72 main +debug lineno: 33 fn3 +debug lineno: 34 fn3 +LINENO 34 +debug lineno: 35 fn3 +BASH_SOURCE[0] ./dbg-support.tests +debug lineno: 38 fn3 +debug lineno: 39 fn3 +debug lineno: 40 fn3 +debug lineno: 40 fn3 +debug lineno: 41 fn3 +debug lineno: 42 fn3 +debug lineno: 43 fn3 +fn3 called from file `./dbg-support.tests' at line 0 +debug lineno: 40 fn3 +debug lineno: 40 fn3 +debug lineno: 41 fn3 +debug lineno: 42 fn3 +debug lineno: 42 fn3 +debug lineno: 43 fn3 +main called from file `./dbg-support.tests' at line 0 +debug lineno: 40 fn3 +debug lineno: 40 fn3 +debug lineno: 46 fn3 +debug lineno: 18 source +SOURCED LINENO 18 +debug lineno: 19 source +SOURCED BASH_SOURCE[0] ./dbg-support.sub +debug lineno: 20 source +debug lineno: 3 sourced_fn +debug lineno: 4 sourced_fn +debug lineno: 5 sourced_fn +SOURCED FN LINENO 5 +debug lineno: 8 sourced_fn +debug lineno: 9 sourced_fn +debug lineno: 10 sourced_fn +debug lineno: 10 sourced_fn +debug lineno: 11 sourced_fn +debug lineno: 12 sourced_fn +debug lineno: 13 sourced_fn +FUNCNAME[0]: sourced_fn called from ./dbg-support.sub at line 20 +debug lineno: 10 sourced_fn +debug lineno: 10 sourced_fn +debug lineno: 11 sourced_fn +debug lineno: 12 sourced_fn +debug lineno: 13 sourced_fn +FUNCNAME[1]: source called from ./dbg-support.tests at line 46 +debug lineno: 10 sourced_fn +debug lineno: 10 sourced_fn +debug lineno: 11 sourced_fn +debug lineno: 12 sourced_fn +debug lineno: 13 sourced_fn +FUNCNAME[2]: fn3 called from ./dbg-support.tests at line 72 +debug lineno: 10 sourced_fn +debug lineno: 10 sourced_fn +debug lineno: 11 sourced_fn +debug lineno: 12 sourced_fn +debug lineno: 12 sourced_fn +debug lineno: 13 sourced_fn +FUNCNAME[3]: main called from ./dbg-support.tests at line 0 +debug lineno: 10 sourced_fn +debug lineno: 10 sourced_fn +debug lineno: 3 sourced_fn +debug lineno: 12 print_return_trap +debug lineno: 13 print_return_trap +return lineno: 3 sourced_fn +debug lineno: 14 print_return_trap +debug lineno: 46 fn3 +debug lineno: 12 print_return_trap +debug lineno: 13 print_return_trap +return lineno: 46 fn3 +debug lineno: 14 print_return_trap +debug lineno: 33 fn3 +debug lineno: 12 print_return_trap +debug lineno: 13 print_return_trap +return lineno: 33 fn3 +debug lineno: 14 print_return_trap +debug lineno: 73 main +debug lineno: 18 source +SOURCED LINENO 18 +debug lineno: 19 source +SOURCED BASH_SOURCE[0] ./dbg-support.sub +debug lineno: 20 source +debug lineno: 3 sourced_fn +debug lineno: 4 sourced_fn +debug lineno: 5 sourced_fn +SOURCED FN LINENO 5 +debug lineno: 8 sourced_fn +debug lineno: 9 sourced_fn +debug lineno: 10 sourced_fn +debug lineno: 10 sourced_fn +debug lineno: 11 sourced_fn +debug lineno: 12 sourced_fn +debug lineno: 13 sourced_fn +FUNCNAME[0]: sourced_fn called from ./dbg-support.sub at line 20 +debug lineno: 10 sourced_fn +debug lineno: 10 sourced_fn +debug lineno: 11 sourced_fn +debug lineno: 12 sourced_fn +debug lineno: 13 sourced_fn +FUNCNAME[1]: source called from ./dbg-support.tests at line 73 +debug lineno: 10 sourced_fn +debug lineno: 10 sourced_fn +debug lineno: 11 sourced_fn +debug lineno: 12 sourced_fn +debug lineno: 12 sourced_fn +debug lineno: 13 sourced_fn +FUNCNAME[2]: main called from ./dbg-support.tests at line 0 +debug lineno: 10 sourced_fn +debug lineno: 10 sourced_fn +debug lineno: 3 sourced_fn +debug lineno: 12 print_return_trap +debug lineno: 13 print_return_trap +return lineno: 3 sourced_fn +debug lineno: 14 print_return_trap +debug lineno: 73 main +debug lineno: 12 print_return_trap +debug lineno: 13 print_return_trap +return lineno: 73 main +debug lineno: 14 print_return_trap +debug lineno: 76 main +debug lineno: 79 main +LINENO 18 +LINENO 19 +BASH_SOURCE[0] ./dbg-support.tests +FUNCNAME[0] fn1 +79 ./dbg-support.tests +79 main ./dbg-support.tests + +./dbg-support.tests: line 25: caller: foo: invalid number +caller: usage: caller [expr] + +debug lineno: 80 main +fn2 here. Calling fn1... +LINENO 18 +LINENO 19 +BASH_SOURCE[0] ./dbg-support.tests +FUNCNAME[0] fn1 +30 ./dbg-support.tests +30 fn2 ./dbg-support.tests +80 main ./dbg-support.tests +./dbg-support.tests: line 25: caller: foo: invalid number +caller: usage: caller [expr] + +debug lineno: 81 main +LINENO 34 +BASH_SOURCE[0] ./dbg-support.tests +fn3 called from file `./dbg-support.tests' at line 0 +main called from file `./dbg-support.tests' at line 0 +SOURCED LINENO 18 +SOURCED BASH_SOURCE[0] ./dbg-support.sub +SOURCED FN LINENO 5 +FUNCNAME[0]: sourced_fn called from ./dbg-support.sub at line 20 +FUNCNAME[1]: source called from ./dbg-support.tests at line 46 +FUNCNAME[2]: fn3 called from ./dbg-support.tests at line 81 +FUNCNAME[3]: main called from ./dbg-support.tests at line 0 +debug lineno: 82 main +fn4 here. Calling fn3... +LINENO 34 +BASH_SOURCE[0] ./dbg-support.tests +fn3 called from file `./dbg-support.tests' at line 82 +fn4 called from file `./dbg-support.tests' at line 0 +main called from file `./dbg-support.tests' at line 0 +SOURCED LINENO 18 +SOURCED BASH_SOURCE[0] ./dbg-support.sub +SOURCED FN LINENO 5 +FUNCNAME[0]: sourced_fn called from ./dbg-support.sub at line 20 +FUNCNAME[1]: source called from ./dbg-support.tests at line 46 +FUNCNAME[2]: fn3 called from ./dbg-support.tests at line 51 +FUNCNAME[3]: fn4 called from ./dbg-support.tests at line 82 +FUNCNAME[4]: main called from ./dbg-support.tests at line 0 +debug lineno: 83 main +SOURCED LINENO 18 +SOURCED BASH_SOURCE[0] ./dbg-support.sub +SOURCED FN LINENO 5 +FUNCNAME[0]: sourced_fn called from ./dbg-support.sub at line 20 +FUNCNAME[1]: source called from ./dbg-support.tests at line 83 +FUNCNAME[2]: main called from ./dbg-support.tests at line 0 +return lineno: 83 main +debug lineno: 86 main +debug lineno: 89 main +debug lineno: 18 source +SOURCED LINENO 18 +debug lineno: 19 source +SOURCED BASH_SOURCE[0] ./dbg-support.sub +debug lineno: 20 source +debug lineno: 3 sourced_fn +debug lineno: 4 sourced_fn +debug lineno: 5 sourced_fn +SOURCED FN LINENO 5 +debug lineno: 8 sourced_fn +debug lineno: 9 sourced_fn +debug lineno: 10 sourced_fn +debug lineno: 10 sourced_fn +debug lineno: 11 sourced_fn +debug lineno: 12 sourced_fn +debug lineno: 13 sourced_fn +FUNCNAME[0]: sourced_fn called from ./dbg-support.sub at line 20 +debug lineno: 10 sourced_fn +debug lineno: 10 sourced_fn +debug lineno: 11 sourced_fn +debug lineno: 12 sourced_fn +debug lineno: 13 sourced_fn +FUNCNAME[1]: source called from ./dbg-support.tests at line 89 +debug lineno: 10 sourced_fn +debug lineno: 10 sourced_fn +debug lineno: 11 sourced_fn +debug lineno: 12 sourced_fn +debug lineno: 12 sourced_fn +debug lineno: 13 sourced_fn +FUNCNAME[2]: main called from ./dbg-support.tests at line 0 +debug lineno: 10 sourced_fn +debug lineno: 10 sourced_fn +debug lineno: 3 sourced_fn +debug lineno: 12 print_return_trap +debug lineno: 13 print_return_trap +return lineno: 3 sourced_fn +debug lineno: 14 print_return_trap +debug lineno: 89 main +debug lineno: 12 print_return_trap +debug lineno: 13 print_return_trap +return lineno: 89 main +debug lineno: 14 print_return_trap +debug lineno: 90 main +debug lineno: 93 main +debug lineno: 93 main +debug lineno: 94 main +debug lineno: 97 main +debug lineno: 93 main +debug lineno: 93 main +debug lineno: 94 main +debug lineno: 97 main +debug lineno: 93 main +debug lineno: 93 main +debug lineno: 94 main +debug lineno: 95 main +Hit 2 +debug lineno: 97 main +debug lineno: 93 main +debug lineno: 93 main +debug lineno: 103 main +SOURCED FN LINENO 5 FUNCNAME[0]: sourced_fn called from ./dbg-support.tests at line 103 FUNCNAME[1]: main called from ./dbg-support.tests at line 0 +debug lineno: 104 main +SOURCED FN LINENO 5 FUNCNAME[0]: sourced_fn called from ./dbg-support.tests at line 104 FUNCNAME[1]: main called from ./dbg-support.tests at line 0 +debug lineno: 105 main +debug lineno: 106 main +SOURCED FN LINENO 5 +FUNCNAME[0]: sourced_fn called from ./dbg-support.tests at line 106 +FUNCNAME[1]: main called from ./dbg-support.tests at line 0 +debug lineno: 110 main +debug lineno: 111 main +debug lineno: 3 sourced_fn +debug lineno: 4 sourced_fn +debug lineno: 5 sourced_fn +SOURCED FN LINENO 5 +debug lineno: 8 sourced_fn +debug lineno: 9 sourced_fn +debug lineno: 10 sourced_fn +debug lineno: 10 sourced_fn +debug lineno: 11 sourced_fn +debug lineno: 12 sourced_fn +debug lineno: 13 sourced_fn +FUNCNAME[0]: sourced_fn called from ./dbg-support.tests at line 111 +debug lineno: 10 sourced_fn +debug lineno: 10 sourced_fn +debug lineno: 11 sourced_fn +debug lineno: 12 sourced_fn +debug lineno: 12 sourced_fn +debug lineno: 13 sourced_fn +FUNCNAME[1]: main called from ./dbg-support.tests at line 0 +debug lineno: 10 sourced_fn +debug lineno: 10 sourced_fn +debug lineno: 3 sourced_fn +debug lineno: 12 print_return_trap +debug lineno: 13 print_return_trap +return lineno: 3 sourced_fn +debug lineno: 14 print_return_trap +debug lineno: 114 main +debug lineno: 119 main +debug lineno: 123 main +got it +debug lineno: 131 main +debug lineno: 132 main +debug lineno: 133 main +debug lineno: 132 main +debug lineno: 133 main +debug lineno: 131 main +debug lineno: 132 main +debug lineno: 133 main +debug lineno: 132 main +debug lineno: 133 main +debug lineno: 137 main +main: calling f1 +f1: calling f2 +f2: calling f3 +f3: calling callstack +deep 6 +0 z +1 3 +2 y +3 2 +4 x +5 1 +FUNCNAME stack: f3 f2 f1 main +26 f2 ./dbg-support3.sub +f3: returning +f2: return from f3 +f1: return from f2 +main: f1 returns diff --git a/tests/dbg-support.sub b/tests/dbg-support.sub new file mode 100644 index 0000000..f68f8d9 --- /dev/null +++ b/tests/dbg-support.sub @@ -0,0 +1,26 @@ +# This file is intended to be sourced from one of the bashdb test programs + +sourced_fn() { + name="fn2" + echo "SOURCED FN LINENO $LINENO" + + # Print a stack trace + declare -i n + n=${#FUNCNAME[@]} + for (( i=0 ; (( i < $n )) ; i++ )) ; do + local -i j=i+1 + [ $j -eq $n ] && j=i # main()'s file is the same as the first caller + echo "FUNCNAME[$i]: ${FUNCNAME[$i]} called from ${BASH_SOURCE[$j]}" \ + "at line ${BASH_LINENO[$i]}" + done +} + +echo "SOURCED LINENO $LINENO" +echo "SOURCED BASH_SOURCE[0]" ${BASH_SOURCE[0]} +sourced_fn + +#;;; Local Variables: *** +#;;; mode:shell-script *** +#;;; eval: (sh-set-shell "bash") *** +#;;; End: *** + diff --git a/tests/dbg-support.tests b/tests/dbg-support.tests new file mode 100755 index 0000000..ad06d01 --- /dev/null +++ b/tests/dbg-support.tests @@ -0,0 +1,142 @@ +#!../bash +# +# Test correct functioning bash debug support not via the bashdb +# debugger but merely by printing via print_trap() +# $Id: dbg-support.tests,v 1.13 2003/02/17 22:02:25 rockyb Exp $ +shopt -s extdebug +print_debug_trap() { + echo "debug lineno: $1 ${FUNCNAME[1]}" + return +} + +print_return_trap() { + echo "return lineno: $1 ${FUNCNAME[1]}" + return +} + +fn1() { + echo "LINENO $LINENO" + echo "LINENO $LINENO" + echo "BASH_SOURCE[0]" ${BASH_SOURCE[0]} + echo "FUNCNAME[0]" ${FUNCNAME[0]} + echo `caller` + echo `caller 0` + echo `caller 1` + echo `caller foo` +} + +fn2() { + echo "fn2 here. Calling fn1..." + fn1 +} + +fn3() { + echo "LINENO $LINENO" + echo "BASH_SOURCE[0]" ${BASH_SOURCE[0]} + + # Print a stack trace + declare -i n + n=${#FUNCNAME[@]} + for (( i=0 ; (( i < $n )) ; i++ )) ; do + local -i j=i+1 + [ $j -eq $n ] && j=i # main()'s file is the same as the first caller + echo "${FUNCNAME[$i]} called from file " \ + "\`${BASH_SOURCE[$j]}' at line ${BASH_LINENO[$j]}" + done + source ./dbg-support.sub +} + +fn4() { + echo "fn4 here. Calling fn3..." + fn3 +} + + +#!../bash +# +# Test of support for debugging facilities in bash +# +# Test debugger set option functrace - set on. Not in vanilla Bash 2.05 +# +set -o functrace +trap 'print_debug_trap $LINENO' DEBUG +trap 'print_return_trap $LINENO' RETURN + +# Funcname is now an array, but you still can't see it outside a function +echo "FUNCNAME" ${FUNCNAME[0]:-main} + +# We should trace into the below. +# Start easy with a simple function. +fn1 +fn2 +fn3 +source ./dbg-support.sub + +# Test debugger set option functrace - set off +set +T + +# We should not trace into this. +fn1 +fn2 +fn3 +fn4 +source ./dbg-support.sub + +# Another way to say: set -o functrace +set -T + +# We should trace into this. +source ./dbg-support.sub +set +T + +# Test that the line numbers in the presence of conditionals are correct. +for (( i=0 ; (( i <= 2 )) ; i++ )) ; do + if [ $i -eq 2 ] ; then + echo "Hit 2" + fi + j=4 +done + +# +# Check line numbers in command substitution +# +echo $(sourced_fn) +echo `sourced_fn` +x=$((sourced_fn)) +x={ sourced_fn } + +# Make sure we step into sourced_fn as a comand when we request to do so. +# Vanilla bash 2.0 doesn't do. +set -o functrace +x={ sourced_fn } + +# Should see line number of xyzzy below. Vanilla bash 2.05b doesn't do +case xyzzy in + a ) + x=5 + ;; + xyzz? ) + case 3 in + 2 ) + x=6 ;; + 3 ) + echo "got it" ;; + * ) echo "no good" ;; + esac + ;; + * ) +esac + +# Should see line numbers for initial for lines. +for i in 0 1 ; do + for j in 3 4 ; do + ((x=i+j)) + done +done + +${THIS_SH} ./dbg-support3.sub + +#;;; Local Variables: *** +#;;; mode:shell-script *** +#;;; eval: (sh-set-shell "bash") *** +#;;; End: *** diff --git a/tests/dbg-support2.right b/tests/dbg-support2.right new file mode 100644 index 0000000..c9d884e --- /dev/null +++ b/tests/dbg-support2.right @@ -0,0 +1,7 @@ +lineno: 17 (6) main +lineno: 18 (6) main +x is 1 +lineno: 19 (6) main +lineno: 20 (6) main +lineno: 21 (6) main +x is 1 diff --git a/tests/dbg-support2.tests b/tests/dbg-support2.tests new file mode 100755 index 0000000..fdc0f31 --- /dev/null +++ b/tests/dbg-support2.tests @@ -0,0 +1,26 @@ +#!../bash +# +# Test correct trap return codes = 2 means skip execution. +shopt -s extdebug +print_trap() { + echo "lineno: $1 ($LINENO) ${FUNCNAME[1]}" + if [[ $debug_exit == 2 ]] ; then + debug_exit=0 + return 2 + fi + return 0 +} + +debug_exit=0 +trap 'print_trap $LINENO' DEBUG + +x=1 +echo "x is $x" +debug_exit=2 +x=2 +echo "x is $x" + +#;;; Local Variables: *** +#;;; mode:shell-script *** +#;;; eval: (sh-set-shell "bash") *** +#;;; End: *** diff --git a/tests/dbg-support3.sub b/tests/dbg-support3.sub new file mode 100644 index 0000000..cc52c65 --- /dev/null +++ b/tests/dbg-support3.sub @@ -0,0 +1,39 @@ +shopt -s extdebug + +callstack(){ + deep=${#BASH_ARGV[*]} + echo "deep $deep" + i=0 + for ff in ${BASH_ARGV[@]} + do + echo "$i $ff" + i=$(($i+1)) + done +} + +f3() +{ + echo $FUNCNAME: calling callstack + callstack + echo FUNCNAME stack: ${FUNCNAME[@]} + caller 0 + echo $FUNCNAME: returning +} + +f2() +{ + echo $FUNCNAME: calling f3 + f3 3 z + echo $FUNCNAME: return from f3 +} + +f1() +{ + echo $FUNCNAME: calling f2 + f2 2 y + echo $FUNCNAME: return from f2 +} + +echo main: calling f1 +f1 1 x +echo main: f1 returns diff --git a/tests/dollar-at-star b/tests/dollar-at-star new file mode 100755 index 0000000..0f713dc --- /dev/null +++ b/tests/dollar-at-star @@ -0,0 +1,305 @@ +# first, let's start with the basics + +recho "$@" +recho "$*" + +recho $@ +recho $* + +foo=$* +foo=$@ + +foo="$*" +foo="$@" + +unset -v bar + +foo=${bar:-$*} +foo=${bar:-$@} + +foo=${bar:-"$*"} +foo=${bar:-"$@"} + +foo=${!*} +foo=${!@} + +set a b + +recho "$*" + +# If IFS is null, the parameters are joined without separators +IFS='' +recho "$*" + +# If IFS is unset, the parameters are separated by spaces +unset IFS +recho "${*}" + +recho "$@" +recho $@ + +IFS='/' +set bob 'tom dick harry' joe +set $* +recho $# +recho $1 +recho $2 +recho $3 + +set bob 'tom dick harry' joe +set ${*} +recho $# +recho $1 +recho $2 +recho $3 + +set bob 'tom dick harry' joe +set $@ +recho $# +recho $1 +recho $2 +recho $3 + +set bob 'tom dick harry' joe +set ${@} +recho $# +recho $1 +recho $2 +recho $3 + +# according to POSIX.2, unquoted $* should expand to multiple words if +# $IFS is null, just like unquoted $@ +IFS='' +set bob 'tom dick harry' joe +set $* +recho $# +recho $1 +recho $2 +recho $3 + +set bob 'tom dick harry' joe +set $@ +recho $# +recho $1 +recho $2 +recho $3 + +# if IFS is unset, the individual positional parameters are split on +# " \t\n" if $* or $@ are unquoted +unset IFS +set bob 'tom dick harry' joe +set $* +recho $# +recho $1 +recho $2 +recho $3 + +set bob 'tom dick harry' joe +set $@ +recho $# +recho $1 +recho $2 +recho $3 + +# but not for "$@" or "$*" +set bob 'tom dick harry' joe +set "$*" +recho $# +recho $1 +recho $2 +recho $3 + +set bob 'tom dick harry' joe +set "$@" +recho $# +recho $1 +recho $2 +recho $3 + +# POSIX.2 says these should both expand the positional parameters +# to multiple words +set a b c d e +IFS="" +recho $@ +recho "$@" + +# this example is straight from the POSIX.2 rationale +set foo bar bam + +recho "$@" +recho "$*" + +unset IFS + +recho "$@" +recho $@ +recho "$*" + +IFS=: + +# special variables +set -- 1 2 3 4 5 6 7 8 9 10 + +bar=${*} +foo=$* +echo foo = "$foo" +echo bar = "$bar" + +foo1=$@ +bar1=${@} + +echo foo1 = "$foo1" +echo bar1 = "$bar1" + +foo2="$*" +bar2="${*}" + +echo foo2 = "$foo2" +echo bar2 = "$bar2" + +eval foo3='$*' bar3='${*}' +echo foo3 = "$foo3" +echo bar3 = "$bar3" + +case $* in +*\:*) echo ok 1;; +*) echo bad 1;; +esac + +case $@ in +*\:*) echo bad 2;; +*) echo ok 2;; +esac + +case "$*" in +*\:*) echo ok 3;; +*) echo bad 3;; +esac + +case "$@" in +*\:*) echo bad 4;; +*) echo ok 4;; +esac + +IFS=$' \t\n' + +bar=${*} +foo=$* +echo foo = "$foo" +echo bar = "$bar" + +foo1=$@ +bar1=${@} + +echo foo1 = "$foo1" +echo bar1 = "$bar1" + +foo2="$*" +bar2="${*}" + +echo foo2 = "$foo2" +echo bar2 = "$bar2" + +eval foo3='$*' bar3='${*}' +echo foo3 = "$foo3" +echo bar3 = "$bar3" + +case $* in +*\ *) echo ok 1;; +*) echo bad 1;; +esac + +case $@ in +*\ *) echo ok 2;; +*) echo bad 2;; +esac + +case "$*" in +*\ *) echo ok 3;; +*) echo bad 3;; +esac + +case "$@" in +*\ *) echo ok 4;; +*) echo bad 4;; +esac + +# tests for the effect of quoting $* and $@ in an assignment context (plus +# arrays) -- bugs through bash 4.2 +${THIS_SH} ./dollar-at-star1.sub + +# more tests for expanding $@ and $* in a context where there is no word +# splitting +${THIS_SH} ./dollar-at-star2.sub +${THIS_SH} ./dollar-at-star3.sub +${THIS_SH} ./dollar-at-star4.sub +${THIS_SH} ./dollar-at-star5.sub +${THIS_SH} ./dollar-at-star6.sub +${THIS_SH} ./dollar-at-star7.sub + +# tests for expansions of $@ and ${a[@]} (vs. $* and ${a[*]}) on the RHS of +# assignment statements with non-default IFS: $@ expands to args or array +# members separated by spaces +${THIS_SH} ./dollar-at-star8.sub + +# tests for special expansion of "$*" and "${array[*]}" when used with other +# expansions -- bugs through bash-2.05b +${THIS_SH} ./dollar-star1.sub + +# tests for expansion of "$@" on rhs of things like ${param:+word}. Bugs +# though bash-2.05b +${THIS_SH} ./dollar-at1.sub + +# tests for expansion of other variables in double-quoted strings containing +# $@. Bugs through bash-2.05b +${THIS_SH} ./dollar-at2.sub + +# tests for various expansions of $* in different contexts -- word split, +# no splitting, etc. when $IFS is NUL +${THIS_SH} ./dollar-star2.sub + +# tests for expansions of "${array[*]}" and "${array[@]}" when $IFS is not the +# default and the array contains null elements +${THIS_SH} ./dollar-star3.sub + +# test for set -u and expansions of $@ when there are no positional parameters +${THIS_SH} ./dollar-at3.sub +# test for set -u and expansions of $* when there are no positional parameters +${THIS_SH} ./dollar-star4.sub + +# tests for expansions of $* when IFS is null +${THIS_SH} ./dollar-star5.sub + +# tests for inappropriate word splitting through bash-4.2 +${THIS_SH} ./dollar-at4.sub + +# tests for problems with "$@" preceded and followed by other quoted expansions +# through bash-4.2 +${THIS_SH} ./dollar-at5.sub + +# tests for problems with "${@:1}" and other expansions with null entries +# in positional parameters +${THIS_SH} ./dollar-at6.sub + +# tests for expansions of $* when $1 == ""; problem through bash-4.2 +${THIS_SH} ./dollar-star6.sub + +# tests for expansions of $* (unquoted) when IFS changes (e.g., ${IFS:=-}) +# problem through bash-4.2 +${THIS_SH} ./dollar-star7.sub + +# tests for expansions of $* (unquoted) when IFS is null and word splitting is +# not going to be performed. +# problem through bash-4.4 in some parameter expansion contexts +${THIS_SH} ./dollar-star8.sub + +# tests for expansions of "$@" when there are no positional parameter or when +# $1 == '' and the expansion is preceded by something that results in a quoted +# null string +${THIS_SH} ./dollar-at7.sub + +# tests for expansions of $* when in an assignment context (no splitting) and +# IFS is null +${THIS_SH} ./dollar-star9.sub + +exit 0 diff --git a/tests/dollar-at-star1.sub b/tests/dollar-at-star1.sub new file mode 100644 index 0000000..0036915 --- /dev/null +++ b/tests/dollar-at-star1.sub @@ -0,0 +1,23 @@ +# from dan douglas +expassign() +{ + typeset -a a + a=("$@") + typeset var asn + + while IFS= read -r asn; do + IFS=: command eval "$asn" + printf '%-14s... %s\n' "$asn" "$var" + done <<\EOF +var=${a[*]} +var="${a[*]}" +var=$* +var="$*" +var=${a[@]} +var="${a[@]}" +var=$@ +var="$@" +EOF +} + +expassign one:::two three:::four diff --git a/tests/dollar-at-star2.sub b/tests/dollar-at-star2.sub new file mode 100644 index 0000000..780548e --- /dev/null +++ b/tests/dollar-at-star2.sub @@ -0,0 +1,207 @@ +OIFS="$IFS" +foo=' ,foo' +set -- "$foo" + +if [[ $foo = ,* ]]; then echo bad 1; else echo ok 1; fi +if [[ $@ = ,* ]]; then echo bad 2; else echo ok 2; fi +if [[ $* = ,* ]]; then echo bad 3; else echo ok 3; fi +if [[ ${@} = ,* ]]; then echo bad 4; else echo ok 4; fi +if [[ ${*} = ,* ]]; then echo bad 5; else echo ok 5; fi +if [[ $1 = ,* ]]; then echo bad 6; else echo ok 6; fi + +set -- ' ,foo' +if [[ $foo = ,* ]]; then echo bad 7; else echo ok 7; fi +if [[ $@ = ,* ]]; then echo bad 8; else echo ok 8; fi +if [[ $* = ,* ]]; then echo bad 9; else echo ok 9; fi +if [[ ${@} = ,* ]]; then echo bad 10; else echo ok 10; fi +if [[ ${*} = ,* ]]; then echo bad 11; else echo ok 11; fi +if [[ $1 = ,* ]]; then echo bad 12; else echo ok 12; fi + +IFS= +if [[ $@ = ,* ]]; then echo bad 13; else echo ok 13; fi +if [[ $* = ,* ]]; then echo bad 14; else echo ok 14; fi +IFS="$OIFS" + +foo=' ,foo' +set -- ' ' ',foo' + +if [[ $@ = ,* ]]; then echo bad at 1; else echo ok at 1; fi +if [[ ${@} = ,* ]]; then echo bad at 2; else echo ok at 2; fi + +if [[ $* = ,* ]]; then echo bad star 1; else echo ok star 1; fi +if [[ ${*} = ,* ]]; then echo bad star 2; else echo ok star 2; fi + +foo=' ,foo' +set -- "$foo" + +# expand_string_for_rhs + +foo2=$@ +echo "$foo2" + +foo2=$* +echo "$foo2" + +foo2="$@" +echo "$foo2" + +foo2="$*" +echo "$foo2" + +# expand_word_unsplit +case $@ in +$foo2) echo ok at 1 ;; +*) echo bad at 1 ;; +esac + +# also uses expand_word_leave_quoted +case $@ in +$@) echo ok at 2;; +*) echo bad at 2;; +esac + +case $@ in +$foo) echo ok at 3 ;; +*) echo bad at 3;; +esac + +# expand_word_unsplit +case $* in +$foo2) echo ok star 1 ;; +*) echo bad star 1 ;; +esac + +# also uses expand_word_leave_quoted +case $* in +$*) echo ok star 2;; +*) echo bad star 2;; +esac + +case $* in +$foo) echo ok star 3 ;; +*) echo bad star 3;; +esac + +case $@ in +$*) echo ok at-star 1;; +*) echo bad at-star 1;; +esac + +case $* in +$@) echo ok at-star 2;; +*) echo bad at-star 2;; +esac + +foo='a b c' +set -- $foo + +# expand_string_for_rhs +IFS='|' +foo2=$@ +echo "$foo2" + +foo2=$* +echo "$foo2" + +foo2="$@" +echo "$foo2" + +foo2="$*" +echo "$foo2" + +foo="a b c" +set -- $foo + +if [[ $@ = $foo ]]; then echo ok at 1; else echo bad at 1; fi +if [[ $foo = $@ ]]; then echo ok at 2; else echo bad at 2; fi + +case $@ in +$@) echo ok at 3 ;; +*) echo bad at 3 ;; +esac + +case $@ in +$foo) echo ok at 4;; +*) echo bad at 4;; +esac + +case $foo in +$@) echo ok at 5;; +*) echo bad at 5;; +esac +IFS="$OIFS" + +foo="a b c" +set -- $foo + +IFS=: +if [[ $@ = $foo ]]; then echo ok at 1; else echo bad at 1; fi +if [[ $foo = $@ ]]; then echo ok at 2; else echo bad at 2; fi + +case $@ in +$@) echo ok at 3 ;; +*) echo bad at 3 ;; +esac + +case $@ in +$foo) echo ok at 4;; +*) echo bad at 4;; +esac + +case $foo in +$@) echo ok at 5;; +*) echo bad at 5;; +esac +IFS="$OIFS" + +foo="a b c" +set -- $foo + +IFS='|' +foo2=$@ + +case $@ in +$@) echo ok at 1 ;; +*) echo bad at 1 ;; +esac + +case $foo2 in +$foo) echo ok at 2;; +*) echo bad at 2;; +esac + +case $foo in +$foo2) echo ok at 3;; +*) echo bad at 3;; +esac + +case $foo in +$foo) echo ok at 4;; +*) echo bad at 4;; +esac + +case $foo2 in +$foo2) echo ok at 5;; +*) echo bad at 5;; +esac + +case $foo2 in +$@) echo ok at 6;; +*) echo bad at 6;; +esac + +case $@ in +$foo2) echo ok at 7;; +*) echo bad at 7;; +esac + +case $foo in +$@) echo ok at 8;; +*) echo bad at 8;; +esac + +case $@ in +$foo) echo ok at 9;; +*) echo bad at 9;; +esac +IFS="$OIFS" diff --git a/tests/dollar-at-star3.sub b/tests/dollar-at-star3.sub new file mode 100644 index 0000000..b37d64a --- /dev/null +++ b/tests/dollar-at-star3.sub @@ -0,0 +1,44 @@ +unset f ; f=abcd + +first_char=${f[@]:0:1} +recho $first_char + +first_char=${f[0]:0:1} +recho $first_char + +first_char=${f:0:1} +recho $first_char + +first_char="${f[@]:0:1}" +recho $first_char + +first_char="${f[@]:0:1}" +recho $first_char + +first_char="${f[0]:0:1}" +recho $first_char + +first_char="${f:0:1}" +recho $first_char + +unset f; +f=( one two three ) +first_word=${f[@]:0:1} +recho $first_word + +first_word=${f[0]:0:1} +recho $first_word + +first_word=${f:0:1} +recho $first_word + +unset f; +f=( one two three ) +first_word=${f[@]:0:1} +recho $first_word + +set -- abc def ghi + +printf '<%s> ' "123 $@ 456"; echo +printf '<%s> ' "123 $@\ 456"; echo + diff --git a/tests/dollar-at-star4.sub b/tests/dollar-at-star4.sub new file mode 100644 index 0000000..be2892d --- /dev/null +++ b/tests/dollar-at-star4.sub @@ -0,0 +1,99 @@ +# tests for quoted and unquoted, split and unsplit expansions of $@ and $* +# Posix interpretation 221 speaks to this issue + +set -- a b +IFS= +x=abc + +printf "<%s>\n" ${x#$*} + +a="a bc" +echo ${a#$*} +unset x a + +a=$@ +echo "$a" + +a=$* +echo "$a" + +printf '<%s>' $@ ; echo + +IFS=' +' + +a=$@ +echo "$a" + +a=$* +echo "$a" + +unset a + +unset IFS +set a b "c d" +printf '<%s>' $* ; echo +printf '<%s>' ${q-$*} ; echo + +IFS= +set a b "c d" +printf '<%s>' $* ; echo +printf '<%s>' ${q-$*} ; echo + +IFS=: +set a b +printf '<%s>' ${foo=$*} ; echo +printf '<%s>' "${foo}" ; echo + +unset foo +IFS=' +' +printf '<%s>' ${foo=$@} ; echo +printf '<%s>' "$foo" ; echo + +IFS=? +set a c +foo=abcd + +echo ${foo#"$*"} +echo "${foo#$*}" + +echo "${foo#'a?c'}" +echo "${foo#a?c}" + +IFS=? +set a c +str=a$'\001'c +pat=a$'\001' +echo "${str#$pat}" + +set a b +IFS=: + +a=$@ +recho "$a" + +recho ${foo=$*} +recho "$foo" + +unset foo +IFS=' +' +recho ${foo=$@} +recho "$foo" + +shift $# +unset foo x + +set -- a b +x=abc + +IFS= +printf "<%s>\n" ${x#$*} +printf "<%s>\n" "${x#$*}" + +x=abcd +set a c +IFS='?' +printf "<%s>\n" ${x#$*} +printf "<%s>\n" "${x#$*}" diff --git a/tests/dollar-at-star5.sub b/tests/dollar-at-star5.sub new file mode 100644 index 0000000..3bd7b0f --- /dev/null +++ b/tests/dollar-at-star5.sub @@ -0,0 +1,53 @@ +# testing various combinations of quoted and unquoted expansions of $@, and +# whether they generate empty words after expansion + +n() { echo "$#"; } + +n "$@" +n ${foo-"$@"} +n "${foo-$@}" + +n ""$@ +n """$@" + +n $(true)$@ +n "$(true)$@" +n "$(true)$@" +n "$(true)""$@" + +n $xxx$@ +n "$xxx$@" +n $xxx"$@" +n "$xxx""$@" + +recho $xxx"$@" +echo after 1 + +recho "$xxx$@" +echo after 2 + +recho ${foo:-$xxx"$@"} +echo after 3 + +# this is where these things start to differ +echo same as 1 +recho "${foo:-$xxx"$@"}" +echo same as 2 +recho "${foo:-$xxx$@}" + +echo null fields +recho ""$@ +recho """$@" + +echo null fields in rhs +echo null string with unquoted '$@' +recho ${foo:-""$@} +echo null string with quoted '$@' +recho ${foo:-"""$@"} + +echo assignment +recho "${foo=$@}" +echo variable +recho "$foo" +echo dollar-at +recho "${@}" diff --git a/tests/dollar-at-star6.sub b/tests/dollar-at-star6.sub new file mode 100644 index 0000000..7366df5 --- /dev/null +++ b/tests/dollar-at-star6.sub @@ -0,0 +1,29 @@ +OIFS="$IFS" +arr=(a b c) + +recho ${arr[@]@Q} +recho "${arr[@]@Q}" + +IFS="'" +recho ${arr[@]@Q} +recho "${arr[@]@Q}" +IFS="$OIFS" + +arr=("'a'" "'b'" "'c'") + +IFS="'" +recho ${arr[@]} +recho "${arr[@]}" +IFS="$OIFS" + +IFS="'" +a="'a'" +recho $a +recho "$a" +IFS="$OIFS" + +set -- "'a'" "'b'" "'c'" + +IFS="'" +recho "${@}" +recho "$@" diff --git a/tests/dollar-at-star7.sub b/tests/dollar-at-star7.sub new file mode 100644 index 0000000..47cb37f --- /dev/null +++ b/tests/dollar-at-star7.sub @@ -0,0 +1,25 @@ +IFS='' # testing with only empty IFS + +set -- this is a test + +printf '|%s|\n' ${1+"$@"} +echo +printf '|%s|\n' "${1+$@}" +echo +printf '|%s|\n' "$@" +echo + +printf '|%s|\n' ${1-"$@"} +printf '|%s|\n' "${1-$@}" + +echo +: ${foo:="$@"} +printf '|%s|\n' "$foo" + +unset foo +: "${foo:=$@}" +printf '|%s|\n' "$foo" + +unset foo +printf '|%s|\n' ${foo-"$@"} +printf '|%s|\n' "${foo-$@}" diff --git a/tests/dollar-at-star8.sub b/tests/dollar-at-star8.sub new file mode 100644 index 0000000..7e1b688 --- /dev/null +++ b/tests/dollar-at-star8.sub @@ -0,0 +1,14 @@ +function f { + typeset -a a + a=("$@") + typeset IFS=, + typeset a1="${a[@]} ${a[*]} $@ $* ${@} ${*}" + typeset a2=${a[@]}\ ${a[*]}\ $@\ $*\ ${@}\ ${*} a3 a4 + a3="${a[@]} ${a[*]} $@ $* ${@} ${*}" + a4=${a[@]}\ ${a[*]}\ $@\ $*\ ${@}\ ${*} + unset -v IFS + printf '%s\n' "a1=$a1" "a2=$a2" "a3=$a3" "a4=$a4" +} + +echo +f a b c diff --git a/tests/dollar-at1.sub b/tests/dollar-at1.sub new file mode 100644 index 0000000..6d40786 --- /dev/null +++ b/tests/dollar-at1.sub @@ -0,0 +1,29 @@ +echo_argc() +{ + echo $# +} + +a() +{ + shift + echo_argc "$@" + echo_argc ${1:+"$@"} + echo_argc "${1:+$@}" + echo_argc 1 2 3 +} + +b() +{ + _IFS="$IFS" + IFS="$1" + shift + echo_argc "$@" + echo_argc ${1:+"$@"} + echo_argc "${1:+$@}" + echo_argc 1 2 3 + IFS="$_IFS" +} + +a "X" foo bar hoge + +b "X" foo bar hoge diff --git a/tests/dollar-at2.sub b/tests/dollar-at2.sub new file mode 100644 index 0000000..c079a29 --- /dev/null +++ b/tests/dollar-at2.sub @@ -0,0 +1,19 @@ +t1() +{ + xxx="echo $@" + + recho "$xxx ; echo $@" +} + +t2() +{ + xxx="echo $@" + + recho "${xxx} ; echo $@" +} + +t1 1 +t1 1 2 + +t2 1 +t2 1 2 diff --git a/tests/dollar-at3.sub b/tests/dollar-at3.sub new file mode 100644 index 0000000..76a65c1 --- /dev/null +++ b/tests/dollar-at3.sub @@ -0,0 +1,9 @@ +set -u + +echo ${#@} +echo ${@:-bar} + +echo $@ +echo after 1 +echo ${@} +echo after 2 diff --git a/tests/dollar-at4.sub b/tests/dollar-at4.sub new file mode 100644 index 0000000..c8de866 --- /dev/null +++ b/tests/dollar-at4.sub @@ -0,0 +1,10 @@ +set 'a b' 'c d' + +recho "$@" +recho $@ + +quoted="$@" +unquoted=$@ + +recho "$quoted" +recho "$unquoted" diff --git a/tests/dollar-at5.sub b/tests/dollar-at5.sub new file mode 100644 index 0000000..75e2249 --- /dev/null +++ b/tests/dollar-at5.sub @@ -0,0 +1,82 @@ +args() { printf '<%s> ' "$@"; echo; } + +set -- 1 2 3 4 5 + +args "${@} ${1}" +args "${1} ${@}" +args "${1}${@}${1}" +args "${1} ${@} ${1}" +args ${1}"$@"${1} +args "$@"${1} +args ${1}"$@" + +args "$@""${1}" +args "${1}""$@" + +args "${@}foo" +args ${@}${1} +args ${@}foo + +IFS= +args "$@""${1}" +args "${1}""$@" + +args ${@}${1} +args ${1}${@} +args ${@}foo + +echo second set: +IFS=$' \t\n' +set -- '1 2' 3 4 5 + +args "${@} ${1}" +args "${1} ${@}" + +args "${1}${@}${1}" +args "${1} ${@} ${1}" +args ${1}"$@"${1} +args "$@"${1} +args ${1}"$@" + +args "$@""${1}" +args "${1}""$@" + +args "${@}foo" +args ${@}${1} +args ${@}foo + +IFS= + +args "$@""${1}" +args "${1}""$@" + +args ${@}${1} +args ${1}${@} +args ${@}foo + +echo third set: +IFS=$' \t\n' + +alias declare=typeset + +a(){ echo + echo '"${@:2}a3 a2" a$1 #works as long as $1 and 3 are swapped' + echo "${@:2}a3 a2" a$1 + "${@:2}a3 a2" a$1 + echo $? + a=("${@}");} +b(){ echo + echo '"${@:2}b$1 b2" b3 #fails! why?' + echo "${@:2}b$1 b2" b3 + "${@:2}b$1 b2" b3 + echo $? + b=("${@}");} +c(){ echo + echo '${@:2}c$1 c2 c3 #works as long as quoting omitted' + echo ${@:2}c$1 c2 c3 + ${@:2}c$1 c2 c3 + echo $? + c=("${@}");} +a x set y z;declare -p a +b x set y z;declare -p b +c x set y z;declare -p c diff --git a/tests/dollar-at6.sub b/tests/dollar-at6.sub new file mode 100644 index 0000000..039e11f --- /dev/null +++ b/tests/dollar-at6.sub @@ -0,0 +1,30 @@ +set -- ''; + +recho "${@}" x +recho "${@:1}" x + +set -- "${@:1}" +echo "$#" + +set -- '' '' + +recho "${@:1}" x +recho "${@:1:1}" x + +typeset -a A # ksh93 needs this +A=('' '') +recho "${A[@]:0}" x + +recho "${A[@]:0:1}" x + +recho "${A[@]:1}" x + +set -- '' + +recho "${@/foo/bar}" +recho "${@^^[abcde]}" + +A=( '' ) + +recho "${A[@]/foo/bar}" +recho "${A[@],,[abcde]}" diff --git a/tests/dollar-at7.sub b/tests/dollar-at7.sub new file mode 100644 index 0000000..311a6fe --- /dev/null +++ b/tests/dollar-at7.sub @@ -0,0 +1,46 @@ +set -- '' + +recho 1 ''"$@" +recho 2 """$@" + +recho 3 "$@""$@" +recho 4 "$x""$@" + +set -- + +echo ----- +recho 1 ''"$@" +recho 2 """$@" + +recho 3 "$@""$@" +recho 4 "$x""$@" + +set -- X + +echo ------ +recho 1 ''"${@/*}" +recho 2 """${@/*}" + +recho 3 "$x""${@/*}" + +recho 4 ''"${@#X}" +recho 5 """${@#X}" + +recho 6 "$x""${@#X}" + +set -- + +echo ----- +recho 1 ''"${@/*}" +recho 2 """${@/*}" + +recho 3 "$x""${@/*}" + +recho 4 ''"${@#X}" +recho 5 """${@#X}" + +recho 6 "$x""${@#X}" + +echo ----- +recho 1 "$novar${*}$(echo)" +recho 2 ''"$novar${@}$(echo)" diff --git a/tests/dollar-star1.sub b/tests/dollar-star1.sub new file mode 100644 index 0000000..63a9ef8 --- /dev/null +++ b/tests/dollar-star1.sub @@ -0,0 +1,31 @@ +set -- a b c +x=(a b c); IFS='|' + +echo "${*/#/x}" +echo "${x[*]/#/x}" + +echo "$*" +echo "${x[*]}" + +echo "$@" +echo "${x[@]}" + +echo "${@/#/x}" +echo "${x[@]/#/x}" + +echo "${*:1:2}" +echo "${x[*]:1:2}" + +echo "${@:1:2}" +echo "${x[@]:1:2}" + +IFS=$' \t\n' +set -- xa xb xc +x=(xa xb xc) +IFS='|' + +echo "${*#x}" +echo "${x[*]#x}" + +echo "$*" +echo "${x[*]}" diff --git a/tests/dollar-star2.sub b/tests/dollar-star2.sub new file mode 100644 index 0000000..844a297 --- /dev/null +++ b/tests/dollar-star2.sub @@ -0,0 +1,26 @@ +set A B + +IFS= + +x=$* +y="$*" + +recho "$x" +recho "$y" + +IFS=$' \t\n' + +set 'A B' 'C D' + +IFS= + +x=$* +y="$*" + +recho "$x" +recho "$y" + +recho $x +recho $* +recho $y +recho "$*" diff --git a/tests/dollar-star3.sub b/tests/dollar-star3.sub new file mode 100644 index 0000000..8cf4bb2 --- /dev/null +++ b/tests/dollar-star3.sub @@ -0,0 +1,18 @@ +IFS=/ +#file=/mnt/cdrom/RedHat/RPMS +#recho "${file[*]:0:3}" + +i[0]=fooq +i[1]= +i[2]=barq +i[3]= +recho "${i[*]:0}" +recho "${i[@]:0}" + +recho "${i[*]/q/!}" +recho "${i[@]/q/!}" + +recho "${i[*]#?}" +recho "${i[@]#?}" + +# Need to complete this with case-modifying expansion examples diff --git a/tests/dollar-star4.sub b/tests/dollar-star4.sub new file mode 100644 index 0000000..1b551f2 --- /dev/null +++ b/tests/dollar-star4.sub @@ -0,0 +1,9 @@ +set -u + +echo ${#*} +echo ${*:-bar} + +echo $* +echo after 1 +echo ${*} +echo after 2 diff --git a/tests/dollar-star5.sub b/tests/dollar-star5.sub new file mode 100644 index 0000000..8448bf3 --- /dev/null +++ b/tests/dollar-star5.sub @@ -0,0 +1,16 @@ +set -- a b +IFS= + +echo $* +echo "$*" + +a=abcd +echo "${a#$*}" + +case ab in +$*) echo ok 1;; +esac + +case $* in +ab) echo ok 2 ;; +esac diff --git a/tests/dollar-star6.sub b/tests/dollar-star6.sub new file mode 100644 index 0000000..dbd59ec --- /dev/null +++ b/tests/dollar-star6.sub @@ -0,0 +1,19 @@ +recho "A${*:-w}R" +recho "A${*-w}R" +recho "A${*}R" + +set -- "" + +recho "A${*:-w}R" +recho "A${*-w}R" +recho "A${*}R" + +set -- $'\177' + +recho "A${*:+w}R" +recho "A${*+w}R" +recho "A${*}R" + +recho A${*:+w}R +recho A${*+w}R +recho A${*}R diff --git a/tests/dollar-star7.sub b/tests/dollar-star7.sub new file mode 100644 index 0000000..72d6c24 --- /dev/null +++ b/tests/dollar-star7.sub @@ -0,0 +1,30 @@ +# if IFS side effects in ${IFS=} assignments take place, how do you cope with +# later changes to IFS in the same set of expansions? You've already +# committed to using the first character of the (old) IFS to expand $* in +# the previous expansions, and changing it to not include ' ', for instance, +# results in the first couple of ${*} below not being split at all + +set -f -- a b c + +unset -v IFS +printf '<%s> ' ${*}${IFS=}${*}${IFS:=-}"${*}" +echo +printf "after 1: IFS " +echo "${IFS-unset}" +recho "$*" + +set -f -- a 'b c' d +unset -v IFS +printf '<%s> ' ${*}${IFS=}${*}${IFS:=-}"${*}" +echo +printf "after 2: IFS " +echo "${IFS-unset}" +recho "$*" + +unset -v IFS +recho $* +recho "$*" + +IFS=' ' +recho $* +recho "$*" diff --git a/tests/dollar-star8.sub b/tests/dollar-star8.sub new file mode 100644 index 0000000..72ba108 --- /dev/null +++ b/tests/dollar-star8.sub @@ -0,0 +1,21 @@ +IFS= +set "abc" "def ghi" "jkl" + +set ${1+$*} +printf '<%s>\n' "$#" "$@" + +set "abc" "def ghi" "jkl" +set $* +printf '<%s>\n' "$#" "$@" + +printf '<%s>\n' $* ; +printf '<%s>\n' ${q:-$*} +printf '<%s>\n' "${q:-$*}" + +IFS=: +printf '<%s>\n' $* ; +printf '<%s>\n' ${q:-$*} +printf '<%s>\n' "${q:-$*}" + +unset -v IFS +printf '<%s>\n' $* $@ diff --git a/tests/dollar-star9.sub b/tests/dollar-star9.sub new file mode 100644 index 0000000..26d0ed2 --- /dev/null +++ b/tests/dollar-star9.sub @@ -0,0 +1,46 @@ +set -- 1 2 + +IFS= + +a=$* b=${*} +c=${*/} d=${*#} e=${*%} f=${*:1} +printf '<%s>' "$a" "$b" "$c" "$d" "$e" "$f"; echo + +unset a b c d e f +: ${a=$*} ${b=${*}} ${c=${*/}} +: ${d=${*#}} ${e=${*%}} ${f=${*:1}} +printf '<%s>' "$a" "$b" "$c" "$d" "$e" "$f" ; echo + +unset f g +f=${*,,} g=${*@Q} +printf '<%s>' "$f" "$g" ; echo + +unset -v a b c d e f g +unset var + +# resetting IFS here + +IFS=$' \t\n' + +printf '%s\n' "${*:1}" +var=${*:1}; printf '%s\n' "$var" +var="${*:1}"; printf '%s\n' "$var" + +unset var +recho ${var-${*}} +recho ${var-${*:1}} +recho "${var-${*:1}}" +recho ${var-"${*:1}"} + +unset var +recho ${var=${*}} +printf 'var=%s\n' "$var" +unset var +recho ${var=${*:1}} +printf 'var=%s\n' "$var" + +a=${*:1} +recho "$a" + +: ${b=${*:1}} +recho "$b" diff --git a/tests/dollar.right b/tests/dollar.right new file mode 100644 index 0000000..d72361f --- /dev/null +++ b/tests/dollar.right @@ -0,0 +1,579 @@ +argv[1] = <> +argv[1] = <a b> +argv[1] = <ab> +argv[1] = <a b> +argv[1] = <a> +argv[2] = <b> +argv[1] = <a> +argv[2] = <b> +argv[1] = <3> +argv[1] = <bob> +argv[1] = <tom dick harry> +argv[1] = <joe> +argv[1] = <3> +argv[1] = <bob> +argv[1] = <tom dick harry> +argv[1] = <joe> +argv[1] = <3> +argv[1] = <bob> +argv[1] = <tom dick harry> +argv[1] = <joe> +argv[1] = <3> +argv[1] = <bob> +argv[1] = <tom dick harry> +argv[1] = <joe> +argv[1] = <3> +argv[1] = <bob> +argv[1] = <tom dick harry> +argv[1] = <joe> +argv[1] = <3> +argv[1] = <bob> +argv[1] = <tom dick harry> +argv[1] = <joe> +argv[1] = <5> +argv[1] = <bob> +argv[1] = <tom> +argv[1] = <dick> +argv[1] = <5> +argv[1] = <bob> +argv[1] = <tom> +argv[1] = <dick> +argv[1] = <1> +argv[1] = <bob> +argv[2] = <tom> +argv[3] = <dick> +argv[4] = <harry> +argv[5] = <joe> +argv[1] = <3> +argv[1] = <bob> +argv[1] = <tom> +argv[2] = <dick> +argv[3] = <harry> +argv[1] = <joe> +argv[1] = <a> +argv[2] = <b> +argv[3] = <c> +argv[4] = <d> +argv[5] = <e> +argv[1] = <a> +argv[2] = <b> +argv[3] = <c> +argv[4] = <d> +argv[5] = <e> +argv[1] = <foo> +argv[2] = <bar> +argv[3] = <bam> +argv[1] = <foobarbam> +argv[1] = <foo> +argv[2] = <bar> +argv[3] = <bam> +argv[1] = <foo> +argv[2] = <bar> +argv[3] = <bam> +argv[1] = <foo bar bam> +foo = 1:2:3:4:5:6:7:8:9:10 +bar = 1:2:3:4:5:6:7:8:9:10 +foo1 = 1 2 3 4 5 6 7 8 9 10 +bar1 = 1 2 3 4 5 6 7 8 9 10 +foo2 = 1:2:3:4:5:6:7:8:9:10 +bar2 = 1:2:3:4:5:6:7:8:9:10 +foo3 = 1:2:3:4:5:6:7:8:9:10 +bar3 = 1:2:3:4:5:6:7:8:9:10 +ok 1 +ok 2 +ok 3 +ok 4 +foo = 1 2 3 4 5 6 7 8 9 10 +bar = 1 2 3 4 5 6 7 8 9 10 +foo1 = 1 2 3 4 5 6 7 8 9 10 +bar1 = 1 2 3 4 5 6 7 8 9 10 +foo2 = 1 2 3 4 5 6 7 8 9 10 +bar2 = 1 2 3 4 5 6 7 8 9 10 +foo3 = 1 2 3 4 5 6 7 8 9 10 +bar3 = 1 2 3 4 5 6 7 8 9 10 +ok 1 +ok 2 +ok 3 +ok 4 +var=${a[*]} ... one:::two:three:::four +var="${a[*]}" ... one:::two:three:::four +var=$* ... one:::two:three:::four +var="$*" ... one:::two:three:::four +var=${a[@]} ... one:::two three:::four +var="${a[@]}" ... one:::two three:::four +var=$@ ... one:::two three:::four +var="$@" ... one:::two three:::four +ok 1 +ok 2 +ok 3 +ok 4 +ok 5 +ok 6 +ok 7 +ok 8 +ok 9 +ok 10 +ok 11 +ok 12 +ok 13 +ok 14 +ok at 1 +ok at 2 +ok star 1 +ok star 2 + ,foo + ,foo + ,foo + ,foo +ok at 1 +ok at 2 +ok at 3 +ok star 1 +ok star 2 +ok star 3 +ok at-star 1 +ok at-star 2 +a b c +a|b|c +a b c +a|b|c +ok at 1 +ok at 2 +ok at 3 +ok at 4 +ok at 5 +ok at 1 +ok at 2 +ok at 3 +ok at 4 +ok at 5 +ok at 1 +ok at 2 +ok at 3 +ok at 4 +ok at 5 +ok at 6 +ok at 7 +ok at 8 +ok at 9 +argv[1] = <a> +argv[1] = <a> +argv[1] = <a> +argv[1] = <a> +argv[1] = <a> +argv[1] = <a> +argv[1] = <a> +argv[1] = <one> +argv[1] = <o> +argv[1] = <o> +argv[1] = <one> +<123 abc> <def> <ghi 456> +<123 abc> <def> <ghi\ 456> +<c> +a bc +a b +ab +<a><b> +a b +a b +<a><b><c><d> +<a><b><c><d> +<a><b><c d> +<a><b><c d> +<a><b> +<a:b> +<a><b> +<a b> +abcd +d +abcd +d +c +argv[1] = <a b> +argv[1] = <abcd> +argv[1] = <abcd> +argv[1] = <a> +argv[2] = <b> +argv[1] = <a b> +<c> +<c> +<d> +<d> +0 +0 +1 +1 +1 +0 +0 +0 +1 +0 +0 +0 +1 +after 1 +after 2 +after 3 +same as 1 +argv[1] = <> +same as 2 +argv[1] = <> +null fields +argv[1] = <> +argv[1] = <> +null fields in rhs +null string with unquoted $@ +argv[1] = <> +null string with quoted $@ +assignment +argv[1] = <> +variable +argv[1] = <> +dollar-at +argv[1] = <'a'> +argv[2] = <'b'> +argv[3] = <'c'> +argv[1] = <'a'> +argv[2] = <'b'> +argv[3] = <'c'> +argv[1] = <> +argv[2] = <a> +argv[3] = <> +argv[4] = <> +argv[5] = <b> +argv[6] = <> +argv[7] = <> +argv[8] = <c> +argv[1] = <'a'> +argv[2] = <'b'> +argv[3] = <'c'> +argv[1] = <> +argv[2] = <a> +argv[3] = <> +argv[4] = <> +argv[5] = <b> +argv[6] = <> +argv[7] = <> +argv[8] = <c> +argv[1] = <'a'> +argv[2] = <'b'> +argv[3] = <'c'> +argv[1] = <> +argv[2] = <a> +argv[1] = <'a'> +argv[1] = <'a'> +argv[2] = <'b'> +argv[3] = <'c'> +argv[1] = <'a'> +argv[2] = <'b'> +argv[3] = <'c'> +|this| +|is| +|a| +|test| + +|this| +|is| +|a| +|test| + +|this| +|is| +|a| +|test| + +|this| +|this| + +|this is a test| +|this is a test| +|this| +|is| +|a| +|test| +|this| +|is| +|a| +|test| + +a1=a b c a,b,c a b c a,b,c a b c a,b,c +a2=a b c a,b,c a b c a,b,c a b c a,b,c +a3=a b c a,b,c a b c a,b,c a b c a,b,c +a4=a b c a,b,c a b c a,b,c a b c a,b,c +xa|xb|xc +xa|xb|xc +a|b|c +a|b|c +a b c +a b c +xa xb xc +xa xb xc +a|b +b|c +a b +b c +a|b|c +a|b|c +xa|xb|xc +xa|xb|xc +3 +3 +3 +3 +3 +3 +3 +3 +argv[1] = <echo 1 ; echo 1> +argv[1] = <echo 1 2 ; echo 1> +argv[2] = <2> +argv[1] = <echo 1 ; echo 1> +argv[1] = <echo 1 2 ; echo 1> +argv[2] = <2> +argv[1] = <AB> +argv[1] = <AB> +argv[1] = <A BC D> +argv[1] = <A BC D> +argv[1] = <A BC D> +argv[1] = <A B> +argv[2] = <C D> +argv[1] = <A BC D> +argv[1] = <A BC D> +argv[1] = <fooq//barq/> +argv[1] = <fooq> +argv[2] = <> +argv[3] = <barq> +argv[4] = <> +argv[1] = <foo!//bar!/> +argv[1] = <foo!> +argv[2] = <> +argv[3] = <bar!> +argv[4] = <> +argv[1] = <ooq//arq/> +argv[1] = <ooq> +argv[2] = <> +argv[3] = <arq> +argv[4] = <> +0 +bar + +after 1 + +after 2 +0 +bar + +after 1 + +after 2 +a b +ab +cd +ok 1 +ok 2 +argv[1] = <a b> +argv[2] = <c d> +argv[1] = <a> +argv[2] = <b> +argv[3] = <c> +argv[4] = <d> +argv[1] = <a b c d> +argv[1] = <a b c d> +<1> <2> <3> <4> <5 1> +<1 1> <2> <3> <4> <5> +<11> <2> <3> <4> <51> +<1 1> <2> <3> <4> <5 1> +<11> <2> <3> <4> <51> +<1> <2> <3> <4> <51> +<11> <2> <3> <4> <5> +<1> <2> <3> <4> <51> +<11> <2> <3> <4> <5> +<1> <2> <3> <4> <5foo> +<1> <2> <3> <4> <51> +<1> <2> <3> <4> <5foo> +<1> <2> <3> <4> <51> +<11> <2> <3> <4> <5> +<1> <2> <3> <4> <51> +<11> <2> <3> <4> <5> +<1> <2> <3> <4> <5foo> +second set: +<1 2> <3> <4> <5 1 2> +<1 2 1 2> <3> <4> <5> +<1 21 2> <3> <4> <51 2> +<1 2 1 2> <3> <4> <5 1 2> +<1> <21 2> <3> <4> <51> <2> +<1 2> <3> <4> <51> <2> +<1> <21 2> <3> <4> <5> +<1 2> <3> <4> <51 2> +<1 21 2> <3> <4> <5> +<1 2> <3> <4> <5foo> +<1> <2> <3> <4> <51> <2> +<1> <2> <3> <4> <5foo> +<1 2> <3> <4> <51 2> +<1 21 2> <3> <4> <5> +<1 2> <3> <4> <51 2> +<1 21 2> <3> <4> <5> +<1 2> <3> <4> <5foo> +third set: + +"${@:2}a3 a2" a$1 #works as long as $1 and 3 are swapped +set y za3 a2 ax +0 +declare -a a=([0]="y" [1]="za3 a2" [2]="ax") + +"${@:2}b$1 b2" b3 #fails! why? +set y zbx b2 b3 +0 +declare -a b=([0]="y" [1]="zbx b2" [2]="b3") + +${@:2}c$1 c2 c3 #works as long as quoting omitted +set y zcx c2 c3 +0 +declare -a c=([0]="y" [1]="zcx" [2]="c2" [3]="c3") +argv[1] = <> +argv[2] = <x> +argv[1] = <> +argv[2] = <x> +1 +argv[1] = <> +argv[2] = <> +argv[3] = <x> +argv[1] = <> +argv[2] = <x> +argv[1] = <> +argv[2] = <> +argv[3] = <x> +argv[1] = <> +argv[2] = <x> +argv[1] = <> +argv[2] = <x> +argv[1] = <> +argv[1] = <> +argv[1] = <> +argv[1] = <> +argv[1] = <AwR> +argv[1] = <AwR> +argv[1] = <AR> +argv[1] = <AwR> +argv[1] = <AR> +argv[1] = <AR> +argv[1] = <AwR> +argv[1] = <AwR> +argv[1] = <A^?R> +argv[1] = <AwR> +argv[1] = <AwR> +argv[1] = <A^?R> +<a> <b> <ca> <b> <c-a-b-c> +after 1: IFS - +argv[1] = <a-b-c> +<a> <b> <c> <da> <b c> <d-a-b c-d> +after 2: IFS - +argv[1] = <a-b c-d> +argv[1] = <a> +argv[2] = <b> +argv[3] = <c> +argv[4] = <d> +argv[1] = <a b c d> +argv[1] = <a> +argv[2] = <b> +argv[3] = <c> +argv[4] = <d> +argv[1] = <a b c d> +<3> +<abc> +<def ghi> +<jkl> +<3> +<abc> +<def ghi> +<jkl> +<abc> +<def ghi> +<jkl> +<abc> +<def ghi> +<jkl> +<abcdef ghijkl> +<abc> +<def ghi> +<jkl> +<abc> +<def ghi> +<jkl> +<abc:def ghi:jkl> +<abc> +<def> +<ghi> +<jkl> +<abc> +<def> +<ghi> +<jkl> +argv[1] = <1> +argv[2] = <> +argv[1] = <2> +argv[2] = <> +argv[1] = <3> +argv[2] = <> +argv[1] = <4> +argv[2] = <> +----- +argv[1] = <1> +argv[2] = <> +argv[1] = <2> +argv[2] = <> +argv[1] = <3> +argv[1] = <4> +argv[2] = <> +------ +argv[1] = <1> +argv[2] = <> +argv[1] = <2> +argv[2] = <> +argv[1] = <3> +argv[2] = <> +argv[1] = <4> +argv[2] = <> +argv[1] = <5> +argv[2] = <> +argv[1] = <6> +argv[2] = <> +----- +argv[1] = <1> +argv[2] = <> +argv[1] = <2> +argv[2] = <> +argv[1] = <3> +argv[2] = <> +argv[1] = <4> +argv[2] = <> +argv[1] = <5> +argv[2] = <> +argv[1] = <6> +argv[2] = <> +----- +argv[1] = <1> +argv[2] = <> +argv[1] = <2> +argv[2] = <> +<12><12><12><12><12><12> +<12><12><12><12><12><12> +<12><'1''2'> +1 2 +1 2 +1 2 +argv[1] = <1> +argv[2] = <2> +argv[1] = <1> +argv[2] = <2> +argv[1] = <1 2> +argv[1] = <1 2> +argv[1] = <1> +argv[2] = <2> +var=1 2 +argv[1] = <1> +argv[2] = <2> +var=1 2 +argv[1] = <1 2> +argv[1] = <1 2> diff --git a/tests/dstack.right b/tests/dstack.right new file mode 100644 index 0000000..8f27d28 --- /dev/null +++ b/tests/dstack.right @@ -0,0 +1,55 @@ +./dstack.tests: line 6: pushd: /tmp/xxx-notthere: No such file or directory +./dstack.tests: line 9: pushd: no other directory +./dstack.tests: line 10: popd: directory stack empty +./dstack.tests: line 13: pushd: -m: invalid number +pushd: usage: pushd [-n] [+N | -N | dir] +./dstack.tests: line 14: popd: -m: invalid number +popd: usage: popd [-n] [+N | -N] +./dstack.tests: line 15: dirs: -m: invalid number +dirs: usage: dirs [-clpv] [+N] [-N] +./dstack.tests: line 16: dirs: 7: invalid option +dirs: usage: dirs [-clpv] [+N] [-N] +/ +ok +/usr / +/usr / +/usr / +/usr / +/usr / +/ +/usr / +/etc /usr / +/etc /usr / +/etc /usr / + 0 /etc + 1 /usr + 2 / +/usr /etc / +/etc /usr / +/tmp /etc /usr / +/tmp +/tmp +/usr +/usr +./dstack.tests: line 58: dirs: 9: directory stack index out of range +./dstack.tests: line 58: dirs: 9: directory stack index out of range +./dstack.tests: line 59: pushd: +9: directory stack index out of range +./dstack.tests: line 59: pushd: -9: directory stack index out of range +./dstack.tests: line 60: popd: +9: directory stack index out of range +./dstack.tests: line 60: popd: -9: directory stack index out of range +/tmp /etc / +/tmp /etc / +/tmp /etc / +/tmp /usr /etc / +/tmp +/tmp /usr /etc / +/tmp /usr /etc / +/tmp +/tmp /bin /etc / +/tmp +/tmp /bin / +/tmp +/bin / /tmp +/bin / /tmp +/bin +/bin diff --git a/tests/dstack.tests b/tests/dstack.tests new file mode 100644 index 0000000..49b97d3 --- /dev/null +++ b/tests/dstack.tests @@ -0,0 +1,87 @@ +export LC_ALL=C +export LANG=C + +dirs -c +# error -- nonexistant directory +pushd /tmp/xxx-notthere + +# errors -- empty stack +pushd +popd + +# errors -- bad numeric arguments -- should not cause the script to exit +pushd -m +popd -m +dirs -m +dirs 7 + +MYDIR=$PWD +unalias cd 2>/dev/null + +unalias -a + +command cd -P / +command pwd -P # better be `/' + +case "$OLDPWD" in +$MYDIR) echo ok ;; +*) echo oops -- bad \$OLDPWD ;; +esac + +pushd /usr +echo $PWD $OLDPWD +dirs +echo ${DIRSTACK[@]} + +# this should not change the directory stack at all +pushd -n +0 +dirs + +popd +pushd /usr + +pushd /etc +dirs +dirs -l +dirs -v + +# two consecutive `pushd's should swap the top two stack elements, then +# swap them back, leaving the stack intact +pushd +pushd + +pushd /tmp +echo ${DIRSTACK[0]} ; dirs +0 +echo ${DIRSTACK[2]} ; dirs +2 + +# these should be errors, but not affect the directory stack +dirs +9; dirs -9 +pushd +9 ; pushd -9 +popd +9 ; popd -9 + +popd -n +2 +dirs +echo ${DIRSTACK[@]} + +pushd -n /usr +echo $PWD +dirs +echo ${DIRSTACK[@]} + +builtin pwd + +DIRSTACK[1]=/bin +dirs + +builtin pwd +popd +2 +builtin pwd -L +pushd -1 +dirs +echo ${DIRSTACK[0]} + +dirs -c +dirs + +# this is for the benefit of pure coverage +cd "$MYDIR" diff --git a/tests/dstack2.right b/tests/dstack2.right new file mode 100644 index 0000000..d682a27 --- /dev/null +++ b/tests/dstack2.right @@ -0,0 +1,24 @@ +expect ~1 +~1 +/usr / +/tmp /usr / +/tmp /usr / +these lines should be the same +/tmp +/tmp /tmp +these lines should be the same +/usr +/usr /usr +these lines should be the same +/ +/ / +these lines should be the same +/tmp +/tmp /tmp +these lines should be the same +/usr +/usr /usr + 1 /usr +these lines should be the same +/ +/ / diff --git a/tests/dstack2.tests b/tests/dstack2.tests new file mode 100644 index 0000000..3aa105b --- /dev/null +++ b/tests/dstack2.tests @@ -0,0 +1,36 @@ +wdir=$PWD +cd / + +echo expect '~1' +echo ~1 + +pushd /usr +pushd /tmp +dirs + +echo these lines should be the same +dirs +0 +echo ~0 ${DIRSTACK[0]} +echo these lines should be the same +dirs +1 +echo ~1 ${DIRSTACK[1]} +echo these lines should be the same +dirs +2 +echo ~2 ${DIRSTACK[2]} + +NDIRS=$(( ${#DIRSTACK[@]} - 1 )) + +echo these lines should be the same +dirs -2 +echo ~-2 ${DIRSTACK[NDIRS-2]} + +echo these lines should be the same +dirs -1 +echo ~-1 ${DIRSTACK[NDIRS-1]} +dirs -v -1 + +echo these lines should be the same +dirs -0 +echo ~-0 ${DIRSTACK[NDIRS]} + +cd "$wdir" diff --git a/tests/dynvar.right b/tests/dynvar.right new file mode 100644 index 0000000..e1344c6 --- /dev/null +++ b/tests/dynvar.right @@ -0,0 +1,7 @@ +BASHPID ok +BASH_ARGV0 ok +BASH_ARGV0 ok +SECONDS ok +EPOCHSECONDS ok +EPOCHREALTIME ok +echo $BASH_COMMAND diff --git a/tests/dynvar.tests b/tests/dynvar.tests new file mode 100644 index 0000000..a01f5ed --- /dev/null +++ b/tests/dynvar.tests @@ -0,0 +1,77 @@ +# specvar -- test some of the dynamic variables + +# BASHPID +pid=$$ +bpid=$BASHPID +subpid=$( (echo $BASHPID) ) + +if [ "$bpid" -ne "$subpid" ]; then echo BASHPID ok; fi + +# BASH_ARGV0 + +BASH_ARGV0=hello +case $0 in +hello) echo BASH_ARGV0 ok ;; +*) echo "BASH_ARGV0 mismatch: $BASH_ARGV0 ($0)" >&2 ;; +esac + +setarg0() +{ + BASH_ARGV0="$1" +} + +setarg0 arg0 +case $0 in +arg0) echo BASH_ARGV0 ok ;; +*) echo "BASH_ARGV0 mismatch: $BASH_ARGV0 ($0)" >&2 ;; +esac + +# SECONDS +before=$SECONDS +sleep 2 +after=$SECONDS + +if (( $after > $before )); then echo SECONDS ok; fi +unset before after + +# EPOCHSECONDS + +# not exact, but should work + +now1=$(perl -e 'print time') +now2=$EPOCHSECONDS + +case $now1 in +$now2) echo EPOCHSECONDS ok ;; +*) echo "current time via perl and EPOCHSECONDS possible mismatch|$now1|$now2" >&2 ;; +esac +unset now1 now2 + +LC_ALL=C # force decimal point to `.' +now1=$EPOCHREALTIME +now2=$EPOCHREALTIME +sec1=${now1%%.*} +sec2=${now2%%.*} + +msec1=${now1##*.} +msec2=${now2##*.} +# cut off leading zeros +shopt -s extglob +msec1=${msec1##*(0)} +msec2=${msec2##*(0)} + +dsec=$(( $sec2 - $sec1 )) +dmsec=$(( $msec2 - $msec1 )) +if (( $dmsec < 0 )); then + dmsec=$(( dmsec + 1000000 )) + dsec=$(( desc - 1 )) +fi + +# not a real test, but ok for a start +if (( $dmsec < 1000000 )); then echo EPOCHREALTIME ok; fi + +${THIS_SH} -c 'echo $BASH_COMMAND' + +# FUNCNAME tested in func.tests +# RANDOM tested in varenv.sh +# LINENO tested in dbg-support diff --git a/tests/errors.right b/tests/errors.right new file mode 100644 index 0000000..83338ae --- /dev/null +++ b/tests/errors.right @@ -0,0 +1,198 @@ +./errors.tests: line 17: alias: -x: invalid option +alias: usage: alias [-p] [name[=value] ... ] +./errors.tests: line 18: unalias: -x: invalid option +unalias: usage: unalias [-a] name [name ...] +./errors.tests: line 19: alias: hoowah: not found +./errors.tests: line 20: unalias: hoowah: not found +./errors.tests: line 23: `1': not a valid identifier +declare -fr func +./errors.tests: line 36: func: readonly function +./errors.tests: line 39: unset: -x: invalid option +unset: usage: unset [-f] [-v] [-n] [name ...] +./errors.tests: line 42: unset: func: cannot unset: readonly function +./errors.tests: line 45: declare: func: readonly function +./errors.tests: line 49: unset: XPATH: cannot unset: readonly variable +./errors.tests: line 52: unset: `/bin/sh': not a valid identifier +./errors.tests: line 55: unset: cannot simultaneously unset a function and a variable +./errors.tests: line 58: declare: -z: invalid option +declare: usage: declare [-aAfFgilnrtux] [-p] [name[=value] ...] +./errors.tests: line 60: declare: `-z': not a valid identifier +./errors.tests: line 61: declare: `/bin/sh': not a valid identifier +./errors.tests: line 65: declare: cannot use `-f' to make functions +./errors.tests: line 68: exec: -i: invalid option +exec: usage: exec [-cl] [-a name] [command [arguments ...]] [redirection ...] +./errors.tests: line 72: export: XPATH: not a function +./errors.tests: line 75: break: only meaningful in a `for', `while', or `until' loop +./errors.tests: line 76: continue: only meaningful in a `for', `while', or `until' loop +./errors.tests: line 79: shift: label: numeric argument required +./errors.tests: line 84: shift: too many arguments +./errors.tests: line 90: let: expression expected +./errors.tests: line 93: local: can only be used in a function +./errors.tests: line 96: logout: not login shell: use `exit' +./errors.tests: line 99: hash: notthere: not found +./errors.tests: line 102: hash: -v: invalid option +hash: usage: hash [-lr] [-p pathname] [-dt] [name ...] +./errors.tests: line 106: hash: hashing disabled +./errors.tests: line 109: export: `AA[4]': not a valid identifier +./errors.tests: line 110: readonly: `AA[4]': not a valid identifier +./errors.tests: line 113: unset: [-2]: bad array subscript +./errors.tests: line 117: AA: readonly variable +./errors.tests: line 121: AA: readonly variable +./errors.tests: line 129: shift: 5: shift count out of range +./errors.tests: line 130: shift: -2: shift count out of range +./errors.tests: line 133: shopt: no_such_option: invalid shell option name +./errors.tests: line 134: shopt: no_such_option: invalid shell option name +./errors.tests: line 137: umask: 09: octal number out of range +./errors.tests: line 138: umask: `:': invalid symbolic mode character +./errors.tests: line 139: umask: `:': invalid symbolic mode operator +./errors.tests: line 142: umask: -i: invalid option +umask: usage: umask [-p] [-S] [mode] +./errors.tests: line 146: umask: `u': invalid symbolic mode character +./errors.tests: line 155: VAR: readonly variable +./errors.tests: line 158: declare: VAR: readonly variable +./errors.tests: line 159: declare: VAR: readonly variable +./errors.tests: line 161: declare: unset: not found +./errors.tests: line 164: VAR: readonly variable +./errors.tests: command substitution: line 168: syntax error near unexpected token `)' +./errors.tests: command substitution: line 168: ` for z in 1 2 3; do )' +./errors.tests: command substitution: line 169: syntax error near unexpected token `done' +./errors.tests: command substitution: line 169: ` for z in 1 2 3; done )' +./errors.tests: line 171: cd: HOME not set +./errors.tests: line 172: cd: /tmp/xyz.bash: No such file or directory +./errors.tests: line 174: cd: OLDPWD not set +./errors.tests: line 175: cd: /bin/sh: Not a directory +./errors.tests: line 177: cd: /tmp/cd-notthere: No such file or directory +./errors.tests: line 180: .: filename argument required +.: usage: . filename [arguments] +./errors.tests: line 181: source: filename argument required +source: usage: source filename [arguments] +./errors.tests: line 184: .: -i: invalid option +.: usage: . filename [arguments] +./errors.tests: line 187: set: -q: invalid option +set: usage: set [-abefhkmnptuvxBCHP] [-o option-name] [--] [arg ...] +./errors.tests: line 190: enable: sh: not a shell builtin +./errors.tests: line 190: enable: bash: not a shell builtin +./errors.tests: line 193: shopt: cannot set and unset shell options simultaneously +./errors.tests: line 196: read: var: invalid timeout specification +./errors.tests: line 199: read: `/bin/sh': not a valid identifier +./errors.tests: line 202: VAR: readonly variable +./errors.tests: line 205: readonly: -x: invalid option +readonly: usage: readonly [-aAf] [name[=value] ...] or readonly -p +./errors.tests: line 208: eval: -i: invalid option +eval: usage: eval [arg ...] +./errors.tests: line 209: command: -i: invalid option +command: usage: command [-pVv] command [arg ...] +./errors.tests: line 212: /bin/sh + 0: syntax error: operand expected (error token is "/bin/sh + 0") +./errors.tests: line 213: /bin/sh + 0: syntax error: operand expected (error token is "/bin/sh + 0") +./errors.tests: line 216: trap: NOSIG: invalid signal specification +./errors.tests: line 219: trap: -s: invalid option +trap: usage: trap [-lp] [[arg] signal_spec ...] +./errors.tests: line 225: return: can only `return' from a function or sourced script +./errors.tests: line 229: break: 0: loop count out of range +./errors.tests: line 233: continue: 0: loop count out of range +./errors.tests: line 238: builtin: bash: not a shell builtin +./errors.tests: line 242: bg: no job control +./errors.tests: line 243: fg: no job control +./errors.tests: line 246: kill: -s: option requires an argument +./errors.tests: line 248: kill: S: invalid signal specification +./errors.tests: line 250: kill: `': not a pid or valid job spec +kill: usage: kill [-s sigspec | -n signum | -sigspec] pid | jobspec ... or kill -l [sigspec] +./errors.tests: line 255: set: trackall: invalid option name +./errors.tests: line 259: xx: readonly variable +1 +./errors1.sub: line 1: .: -i: invalid option +.: usage: . filename [arguments] +./errors1.sub: line 9: shift: -4: shift count out of range +./errors1.sub: line 14: break: -1: loop count out of range +after f +./errors2.sub: line 3: ${$NO_SUCH_VAR}: bad substitution +1 +./errors3.sub: line 5: no_such_file: No such file or directory +TEST +./errors3.sub: line 7: no_such_file: No such file or directory +1 +2 +./errors4.sub: line 7: var: readonly variable +after readonly assignment +./errors4.sub: line 13: break: x: numeric argument required +1 +2 +./errors4.sub: line 7: var: readonly variable +./errors5.sub: line 6: array: unbound variable +./errors5.sub: line 7: array: unbound variable +./errors5.sub: line 8: array[7]: unbound variable +./errors5.sub: line 11: 7: unbound variable +./errors5.sub: line 12: 7: unbound variable +after 1: 1 +after 2: 1 +after 3: 1 +4 +array after 1: 0 + +array after 2: 0 +./errors6.sub: uvar: parameter not set +./errors6.sub: uvar: parameter null or not set + +./errors6.sub: uvar: parameter null or not set +./errors6.sub: line 25: ${-3:-${-3}}: bad substitution +./errors6.sub: line 26: ${-3}: bad substitution +./errors6.sub: line 27: -3: invalid variable name +after indir: 1 +./errors6.sub: line 30: -3: invalid variable name + +unset +./errors6.sub: line 37: var: invalid indirect expansion +./errors6.sub: line 38: var: invalid indirect expansion +./errors6.sub: line 41: invalid-ident: invalid variable name +./errors6.sub: line 42: invalid-ident: invalid variable name +./errors6.sub: line 43: invalid-ident: invalid variable name +4 +array after 1: 0 + +array after 2: 0 +./errors6.sub: uvar: parameter not set +./errors6.sub: uvar: parameter null or not set + +./errors6.sub: uvar: parameter null or not set +./errors6.sub: line 25: ${-3:-${-3}}: bad substitution +./errors6.sub: line 26: ${-3}: bad substitution +./errors6.sub: line 27: -3: invalid variable name +after indir: 1 +./errors6.sub: line 30: -3: invalid variable name + +unset +./errors6.sub: line 37: var: invalid indirect expansion +./errors6.sub: line 38: var: invalid indirect expansion +./errors6.sub: line 41: invalid-ident: invalid variable name +./errors6.sub: line 42: invalid-ident: invalid variable name +./errors6.sub: line 43: invalid-ident: invalid variable name +./errors7.sub: line 8: x: readonly variable +./errors7.sub: line 8: notthere: command not found +after no such command: 127 +./errors7.sub: line 10: x: readonly variable +echo builtin +after non-special builtin: 0 +./errors7.sub: line 12: x: readonly variable +after special builtin: 0 +./errors7.sub: line 14: x: readonly variable +./errors7.sub: line 8: x: readonly variable +./errors7.sub: line 8: notthere: command not found +after no such command: 127 +./errors7.sub: line 10: x: readonly variable +echo builtin +after non-special builtin: 0 +./errors7.sub: line 12: x: readonly variable +./errors7.sub: line 14: x: readonly variable +./errors8.sub: eval: line 7: syntax error: unexpected end of file +ok 1 +./errors8.sub: line 8: v: readonly variable +ok 2 +./errors8.sub: line 9: v: readonly variable +ok 3 +./errors8.sub: line 11: shift: 12: shift count out of range +ok 4 +./errors8.sub: line 13: return: can only `return' from a function or sourced script +ok 5 +./errors8.sub: line 14: set: notanoption: invalid option name +ok 6 +./errors.tests: line 283: `!!': not a valid identifier diff --git a/tests/errors.tests b/tests/errors.tests new file mode 100644 index 0000000..e1554cd --- /dev/null +++ b/tests/errors.tests @@ -0,0 +1,286 @@ +# These should all be safe +LC_ALL=C +LC_CTYPE=C +LC_COLLATE=C +LC_MESSAGES=C + +# these tests should all generate errors + +# make sure we don't exit prematurely +set +e +set +o posix + +# various alias/unalias errors + +# at some point, this may mean to `export' an alias, like ksh, but +# for now it is an error +alias -x foo=barz +unalias -x fooaha +alias hoowah +unalias hoowah + +# the iteration variable must be a valid identifier +for 1 in a b c; do echo $1; done + +# try to rebind a read-only function +func() +{ + echo func +} +readonly -f func +# make sure `readonly' and `declare' play well together +declare -Fr +func() +{ + echo bar +} + +# bad option +unset -x func + +# cannot unset readonly functions or variables +unset -f func +# or make them not readonly +declare -fr func +declare -f +r func + +XPATH=$PATH +declare -r XPATH +unset -v XPATH + +# cannot unset invalid identifiers +unset /bin/sh + +# cannot unset function and variable at the same time +unset -f -v SHELL + +# bad option +declare -z +# cannot declare invalid identifiers +declare -- -z +declare /bin/sh + +# this is the syntax used to export functions in the environment, but +# it cannot be used with `declare' +declare -f func='() { echo "this is func"; }' + +# bad option to exec -- this should not exit the script +exec -i /bin/sh + +# try to export -f something that is not a function -- this should be +# an error, not create an `invisible function' +export -f XPATH + +# this depends on the setting of BREAK_COMPLAINS in config.h.in +break +continue + +# this should not exit the shell; it did in versions before 2.01 +shift label + +# other shells do not complain about the extra arguments; maybe someday +# we won't either +set -- a b c +shift $# label +# and get rid of the positional parameters +shift $# + +# let without an expression is an error, though maybe it should just return +# success +let + +# local outside a function is an error +local + +# logout of a non-login shell is an error +logout + +# try to hash a non-existant command +hash notthere + +# bad option to hash, although it may mean `verbose' at some future point +hash -v + +# turn off hashing, then try to hash something +set +o hashall +hash -p ${THIS_SH} ${THIS_SH##*/} + +# bad identifiers to declare/readonly/export +export AA[4] +readonly AA[4] + +declare -a AA +unset AA[-2] + +# try to assign to a readonly array +declare -r AA +AA=( one two three ) + +# make sure `readonly -n' doesn't turn off readonly status +readonly -n AA +AA=(one two three) + +# try to assign a readonly array with bad assignment syntax +# NOTE: this works in post-bash-2.05 (at least when I write this) +# readonly -a ZZZ=bbb + +# bad counts to `shift' +shopt -s shift_verbose +shift $(( $# + 5 )) +shift -2 + +# bad shell options +shopt -s no_such_option +shopt no_such_option + +# non-octal digits for umask and other errors +umask 09 +umask -S u=rwx:g=rwx:o=rx >/dev/null # 002 +umask -S u:rwx,g:rwx,o:rx >/dev/null # 002 + +# at some point, this may mean `invert', but for now it is an error +umask -i + +# bad assignments shouldn't change the umask +mask=$(umask) +umask g=u +mask2=$(umask) +if [ "$mask" != "$mask2" ]; then + echo "umask errors change process umask" +fi + +# assignment to a readonly variable in environment +VAR=4 +readonly VAR +VAR=7 : + +# more readonly variable tests +declare VAR=88 +declare +r VAR + +declare -p unset + +# iteration variable in a for statement being readonly +for VAR in 1 2 3 ; do echo $VAR; done + +# parser errors +: $( for z in 1 2 3; do ) +: $( for z in 1 2 3; done ) + +# various `cd' errors +( unset HOME ; cd ) +( HOME=/tmp/xyz.bash ; cd ) +# errors from cd +cd - +cd /bin/sh # error - not a directory +OLDPWD=/tmp/cd-notthere +cd - + +# various `source/.' errors +. +source + +# maybe someday this will work like in rc +. -i /dev/tty + +# make sure that this gives an error rather than setting $1 +set -q + +# enable non-builtins +enable sh bash + +# try to set and unset shell options simultaneously +shopt -s -u checkhash + +# this is an error -- bad timeout spec +read -t var < /dev/null + +# try to read into an invalid identifier +read /bin/sh < /dev/null + +# try to read into a readonly variable +read VAR < /dev/null + +# bad option to readonly/export +readonly -x foo + +# someday these may mean something, but for now they're errors +eval -i "echo $-" +command -i "echo $-" + +# this caused a core dump in bash-2.01 (fixed in bash-2.01.1) +eval echo \$[/bin/sh + 0] +eval echo '$((/bin/sh + 0))' + +# error to list trap for an unknown signal +trap -p NOSIG + +# maybe someday trap will take a -s argument like kill, but not now +trap -p -s NOSIG + +# we have a ksh-like ERR trap, post-bash-2.05 +#trap 'echo [$LINENO] -- error' ERR + +# can only return from a function or sourced script +return 2 + +# break and continue with arguments <= 0 +for z in 1 2 3; do + break 0 + echo $x +done +for z in 1 2 3; do + continue 0 + echo $x +done + +# builtin with non-builtin +builtin bash + +# maybe someday you will be able to use fg/bg when job control is not really +# active, but for now they are errors +bg +fg + +# argument required +kill -s +# bad argument +kill -S +# null argument +kill -INT '' +# argument required +kill -INT + +# bad shell option names +set -o trackall # bash is not ksh + +# problem with versions through bash-4.2 +readonly xx=5 +echo $((xx=5)) +echo $? + +${THIS_SH} ./errors1.sub +${THIS_SH} ./errors2.sub +${THIS_SH} ./errors3.sub +${THIS_SH} ./errors4.sub +${THIS_SH} -o posix ./errors4.sub + +${THIS_SH} ./errors5.sub + +${THIS_SH} ./errors6.sub +THIS_SH="${THIS_SH} -o posix" ${THIS_SH} ./errors6.sub + +${THIS_SH} ./errors7.sub +${THIS_SH} -o posix ./errors7.sub + +${THIS_SH} ./errors8.sub + +# this must be last! +# in posix mode, a function name must be a valid identifier +# this can't go in posix2.tests, since it causes the shell to exit +# immediately +set -o posix +function !! () { fc -s "$@" ; } +set +o posix + +echo end diff --git a/tests/errors1.sub b/tests/errors1.sub new file mode 100644 index 0000000..8e7440b --- /dev/null +++ b/tests/errors1.sub @@ -0,0 +1,27 @@ +. -i /dev/tty + +f() +{ + return -1 +} + +set -- a b c +shift -4 + +f + +for f in 1 2 3; do + break -1 +done + + +f() +{ + return -25 +} + +f +echo after f +exit -25 + +exit -56 diff --git a/tests/errors2.sub b/tests/errors2.sub new file mode 100644 index 0000000..79ef333 --- /dev/null +++ b/tests/errors2.sub @@ -0,0 +1,3 @@ +set -e +trap 'echo $?' EXIT +echo ${$NO_SUCH_VAR} # Bad substitution expected here diff --git a/tests/errors3.sub b/tests/errors3.sub new file mode 100644 index 0000000..b2ae3d7 --- /dev/null +++ b/tests/errors3.sub @@ -0,0 +1,7 @@ +# redirection errors with special builtins should exit the shell when in +# Posix mode, not otherwise; being on the LHS of || or && should not make +# a difference + +exec 9<no_such_file || echo TEST +set -o posix +exec 9<no_such_file || echo TEST diff --git a/tests/errors4.sub b/tests/errors4.sub new file mode 100644 index 0000000..8451b96 --- /dev/null +++ b/tests/errors4.sub @@ -0,0 +1,18 @@ +# test effect of assigning to readonly vars on loops and non-interactive shells +# fatal error when in posix mode +var=foo +readonly var +for num in 1 2 3 4 5; do + if [ $num -eq 3 ]; then + var=bar + fi + echo $num +done +echo after readonly assignment + +# non-numeric arguments to break are fatal errors for all non-interactive shells +for f in 1 2 3 4 5 +do + break x +done +echo after loop diff --git a/tests/errors5.sub b/tests/errors5.sub new file mode 100644 index 0000000..112b2a1 --- /dev/null +++ b/tests/errors5.sub @@ -0,0 +1,12 @@ +array[1]=one +array[2]=two + +set -u + +( echo ${#array} ) +( echo ${array} ) +( echo ${array[7]} ) + +set -- 1 2 3 +( echo ${#7} ) +( echo ${7} ) diff --git a/tests/errors6.sub b/tests/errors6.sub new file mode 100644 index 0000000..b80580e --- /dev/null +++ b/tests/errors6.sub @@ -0,0 +1,43 @@ +# problems with non-fatal expansion errors through bash-4.3 +: ${THIS_SH:=./bash} + +${THIS_SH} -c 'echo ${x!y} second +echo after 1: $?' 2>/dev/null + +${THIS_SH} -c 'echo ${#+} second +echo after 2: $?' 2>/dev/null + +${THIS_SH} -c 'echo ${#foo%} second +echo after 3: $?' 2>/dev/null + +${THIS_SH} -c 'b[0]=4 ; echo ${b[ ]} +echo array after 1: $?' 2>/dev/null +${THIS_SH} -c 'typeset -A v ; v["0"]=one ; echo ${v[ ]} +echo array after 2: $?' 2>/dev/null + +${THIS_SH} -c 'echo ${uvar?}' ./errors6.sub +${THIS_SH} -c 'echo ${uvar:?}' ./errors6.sub +export uvar= +${THIS_SH} -c 'echo ${uvar?}' ./errors6.sub +${THIS_SH} -c 'echo ${uvar:?}' ./errors6.sub +unset uvar + +echo "${-3:-${-3}}" +echo ${-3} +x=-3; echo ${!x} +echo after indir: $? + +function ivar() { echo -n "${!1:-${1}}"; } +ivar -3 + +foo=bar +echo ${!foo} +echo ${!foo:-unset} + +echo ${!var:-unset} +echo ${!var+unset} + +foo=invalid-ident +echo ${!foo} +echo ${!foo:-unset} +echo ${!foo+unset} diff --git a/tests/errors7.sub b/tests/errors7.sub new file mode 100644 index 0000000..067867a --- /dev/null +++ b/tests/errors7.sub @@ -0,0 +1,15 @@ +: ${THIS_SH:=./bash} +readonly x=4 + +# in posix mode, these are all variable assignment errors, so strict conformance +# implies that we exit after any of them. ksh93 doesn't do that. we more-or-less +# emulate the ksh93 behavior + +x=8 notthere +echo after no such command: $? +x=8 echo echo builtin +echo after non-special builtin: $? +( x=8 : nosuchdir +echo after special builtin: $? ) +( x=8 $nocmd +echo after assignment error: $? ) diff --git a/tests/errors8.sub b/tests/errors8.sub new file mode 100644 index 0000000..b65e1ab --- /dev/null +++ b/tests/errors8.sub @@ -0,0 +1,14 @@ +# the start of a set of tests for command keeping special builtins from +# exiting the shell on failure +set -o posix +readonly v + +command eval '( ' || echo ok 1 + +command export v=foo || echo ok 2 +command readonly v=foo || echo ok 3 + +command shift 12 || echo ok 4 + +command return 16 || echo ok 5 +command set -o notanoption || echo ok 6 diff --git a/tests/exec.right b/tests/exec.right new file mode 100644 index 0000000..6075cc8 --- /dev/null +++ b/tests/exec.right @@ -0,0 +1,107 @@ +before exec1.sub: one two three +calling exec1.sub +aa bb cc dd ee +after exec1.sub with args: 0 + +after exec1.sub without args: 0 +after exec1.sub: one two three +./execscript: line 21: notthere: command not found +127 +/tmp/bash: notthere: No such file or directory +127 +/bin/sh: /bin/sh: cannot execute binary file +126 +./execscript: line 40: /: Is a directory +126 +/: /: Is a directory +126 +./execscript: line 47: .: /: is a directory +1 +126 +0 +this is bashenv +./exec3.sub: line 3: /tmp/bash-notthere: No such file or directory +127 +./execscript: line 71: notthere: No such file or directory +127 +./execscript: line 74: notthere: No such file or directory +127 +./execscript: line 77: notthere: command not found +127 +this is sh +this is sh +unset +ok +5 +./exec5.sub: line 4: exec: bash-notthere: not found +127 +this is ohio-state +0 +1 +1 +0 +42 +42 +0 +1 +1 +0 +0 +1 +0 +1 +testb +expand_aliases on +1 +1 +1 +1 +0 +0 +0 +0 +/usr/local/bin:/usr/GNU/bin:/usr/bin:/bin:. +cannot find cat in $TMPDIR +cannot find cat with empty $PATH +PATH = /usr/local/bin:/usr/GNU/bin:/usr/bin:/bin:. +cannot find cat in $TMPDIR with hash +cannot find cat with empty $PATH with hash +PATH = /usr/local/bin:/usr/GNU/bin:/usr/bin:/bin:. +trap -- 'echo foo $BASH_SUBSHELL' EXIT +trap -- 'echo USR1 $BASHPID' SIGUSR1 +between +trap -- 'echo foo $BASH_SUBSHELL' EXIT +trap -- 'echo USR1 $BASHPID' SIGUSR1 +between 2 +trap -- 'echo foo $BASH_SUBSHELL' EXIT +trap -- 'echo USR1 $BASHPID' SIGUSR1 +in subshell: 1 +in subshell pipeline: 1 +group pipeline: 1 +EXIT-group.1 +foo 0 +after +exit code: 1 +exit code: 1 +exit code: 1 +exit code: 1 +exit code: 1 +exit code: 1 +a +b +c +A +B +c +d +c +d +e +x1 +x1a +x2 +x2a +x2b +x3 +x3a +x3b diff --git a/tests/exec1.sub b/tests/exec1.sub new file mode 100755 index 0000000..4a12501 --- /dev/null +++ b/tests/exec1.sub @@ -0,0 +1 @@ +echo "$@" diff --git a/tests/exec10.sub b/tests/exec10.sub new file mode 100644 index 0000000..af3ab0d --- /dev/null +++ b/tests/exec10.sub @@ -0,0 +1,34 @@ +# post bash-4.3 changes to how command -p works (avoid modifying $PATH) + +: ${TMPDIR=/tmp} +xpath=/usr/local/bin:/usr/GNU/bin:/usr/bin:/bin:. + +# set a value of PATH we can test for; versions of bash up to and including +# bash-4.3 would set $PATH while running command -p +PATH=$xpath +export PATH +command -p sh -c 'echo $PATH' + +PATH=${TMPDIR} +command -pv cat >/dev/null || echo "cannot find cat using standard path" +command -p cat < /dev/null +#hash + +PATH=$xpath +command -pv cat >/dev/null || echo "cannot find cat using xpath" +PATH=$TMPDIR command -pv cat >/dev/null || echo "cannot find cat using standard path with PATH=\$TMPDIR" +PATH= command -pv cat >/dev/null || echo "cannot find cat using standard path with empty \$PATH" +PATH=$TMPDIR command -v cat >/dev/null || echo "cannot find cat in \$TMPDIR" +PATH= command -v cat >/dev/null || echo "cannot find cat with empty \$PATH" + +echo PATH = $PATH +hash cat + +PATH=$xpath + +PATH=$TMPDIR command -pv cat >/dev/null || echo "cannot find cat using stdpath with hash" +PATH= command -pv cat >/dev/null || echo "cannot find cat using stdpath with hash" +PATH=$TMPDIR command -v cat >/dev/null || echo "cannot find cat in \$TMPDIR with hash" +PATH= command -v cat >/dev/null || echo "cannot find cat with empty \$PATH with hash" + +echo PATH = $PATH diff --git a/tests/exec11.sub b/tests/exec11.sub new file mode 100644 index 0000000..9631c67 --- /dev/null +++ b/tests/exec11.sub @@ -0,0 +1,14 @@ +trap 'echo USR1 $BASHPID' USR1 +trap 'echo foo $BASH_SUBSHELL' 0 + +trap | cat +echo between +( trap ) +echo between 2 +{ trap; } | cat + +( echo in subshell: $BASH_SUBSHELL ) +( echo in subshell pipeline: $BASH_SUBSHELL ) | cat + +{ echo group pipeline: $BASH_SUBSHELL; + trap 'echo EXIT-group.$BASH_SUBSHELL' EXIT; } | cat diff --git a/tests/exec12.sub b/tests/exec12.sub new file mode 100644 index 0000000..79bcfc7 --- /dev/null +++ b/tests/exec12.sub @@ -0,0 +1,19 @@ +: ${TMPDIR:=/var/tmp} +TMPFILE=$TMPDIR/exitcode +trap 'rm -f $TMPFILE' 0 + +rm -f $TMPFILE +set -e +# we normalize the exit code to accommodate false returning 255 on Solaris +exit_handler() { echo "exit code: $(( $? != 0 ))" ; touch $TMPFILE; } +false() { ! :; } +notfound() { nosuchcommand ; } +syntaxerror() { !:; } + +main() +{( + trap exit_handler 0 + "$@" >> /dev/null 2>&1 +)} +main "$@" +echo "after main: should not get here" diff --git a/tests/exec13.sub b/tests/exec13.sub new file mode 100644 index 0000000..0f84daa --- /dev/null +++ b/tests/exec13.sub @@ -0,0 +1,21 @@ +echo x1 | ( cat & wait ) +echo x1a | ( :& cat & wait ) + +echo x2 | for f in 1; do + cat & wait +done +echo x2a | if true; then cat & wait; fi +echo x2b | for (( i=0; i < 1; i++ )) ; do cat & wait; done + +echo x3 | { cat & wait; } + +lambda() { cat & wait; } +echo x3a | lambda + +: ${TMPDIR:=/tmp} +SRCF=$TMPDIR/bash-src-$$ +cat > $SRCF << \EOF +cat & wait +EOF +echo x3b | . $SRCF +rm -f $SRCF diff --git a/tests/exec2.sub b/tests/exec2.sub new file mode 100644 index 0000000..c1caaea --- /dev/null +++ b/tests/exec2.sub @@ -0,0 +1,5 @@ +# make sure an exit command in an exit trap sets the shell's exit status +trap - 0 +trap 'exit 5' 0 + +exit 0 diff --git a/tests/exec3.sub b/tests/exec3.sub new file mode 100644 index 0000000..4f2f8e2 --- /dev/null +++ b/tests/exec3.sub @@ -0,0 +1,6 @@ +shopt -s execfail + +exec /tmp/bash-notthere +# make sure we're still around +echo $? + diff --git a/tests/exec4.sub b/tests/exec4.sub new file mode 100644 index 0000000..a60d8b3 --- /dev/null +++ b/tests/exec4.sub @@ -0,0 +1,8 @@ +# let's test out the noexec code +set -n + +fail +whoops +wow + +set +n diff --git a/tests/exec5.sub b/tests/exec5.sub new file mode 100644 index 0000000..1462f9e --- /dev/null +++ b/tests/exec5.sub @@ -0,0 +1,9 @@ +# try exec'ing a command that cannot be found in $PATH +shopt -s execfail + +exec bash-notthere +# make sure we're still around +echo $? + +# now we need to go away, but this should echo 'this is ohio-state' +exec -a ohio-state ${THIS_SH} -c 'echo this is $0' diff --git a/tests/exec6.sub b/tests/exec6.sub new file mode 100644 index 0000000..50d0e70 --- /dev/null +++ b/tests/exec6.sub @@ -0,0 +1,54 @@ +# builtins with exit status inverted + +( true ) +echo $? +( ! true ) +echo $? + +( false ) +echo $? +( ! false ) +echo $? + +# inverting shouldn't affect exit +(exit 42) +echo $? + +( ! exit 42 ) +echo $? + +# commands requiring an exec with exit status inverted -- broken in bash-2.04 + +( ls > /dev/null 2>&1 ) +echo $? +( ! ls > /dev/null 2>&1 ) +echo $? + +touch /tmp/notwrite +chmod 400 /tmp/notwrite + +# make sure redirection failures in commands whose exit status is inverted +# are handled correctly + +( ls > /tmp/notwrite ) 2>/dev/null +echo $? + +( ! ls > /tmp/notwrite ) 2>/dev/null +echo $? + +# now add exit traps, true and false for commands with and without exit +# status inversion + +(trap 'false' 0 ; ! ls > /tmp/notwrite ) 2>/dev/null +echo $? + +(trap 'false' 0 ; ls > /tmp/notwrite ) 2>/dev/null +echo $? + +(trap 'true' 0 ; ! ls > /tmp/notwrite ) 2>/dev/null +echo $? + +(trap 'true' 0 ; ls > /tmp/notwrite ) 2>/dev/null +echo $? + +rm -f /tmp/notwrite diff --git a/tests/exec7.sub b/tests/exec7.sub new file mode 100644 index 0000000..0267505 --- /dev/null +++ b/tests/exec7.sub @@ -0,0 +1,23 @@ +# make sure that bash really checks the right things when deciding what +# constitutes an executable file + +[ $UID -eq 0 ] && { echo "exec7.sub: the test suite should not be run as root" >&2 ; } + +: ${TMPDIR:=/tmp} + +cd $TMPDIR || { echo "cannot cd to $TMPDIR" >&2 ; exit 2; } + +mkdir testa testb + +echo 'echo "testa"' > testa/foo +echo 'echo "testb"' > testb/foo + +chmod 655 testa/foo +chmod 755 testb/foo + +PATH=$TMPDIR/testa:$TMPDIR/testb $THIS_SH -c foo + +rm -rf testa testb + +cd $OLDPWD +exit 0 diff --git a/tests/exec8.sub b/tests/exec8.sub new file mode 100644 index 0000000..014726d --- /dev/null +++ b/tests/exec8.sub @@ -0,0 +1 @@ +shopt expand_aliases diff --git a/tests/exec9.sub b/tests/exec9.sub new file mode 100644 index 0000000..b8d20b4 --- /dev/null +++ b/tests/exec9.sub @@ -0,0 +1,20 @@ +# make sure commands before the last one in the pipeline can't change $? +false +false | echo $? +false +(false) | echo $? + +false +true | echo $? +false +(true) | echo $? + +true +false | echo $? +true +(false) | echo $? + +true +true | echo $? +true +(true) | echo $? diff --git a/tests/execscript b/tests/execscript new file mode 100644 index 0000000..c1819de --- /dev/null +++ b/tests/execscript @@ -0,0 +1,159 @@ +export LC_ALL=C +export LANG=C + +if [ $UID -eq 0 ]; then + echo "execscript: the test suite should not be run as root" >&2 +fi + +set -- one two three +echo before exec1.sub: "$@" +echo calling exec1.sub +./exec1.sub aa bb cc dd ee +echo after exec1.sub with args: $? +./exec1.sub +echo after exec1.sub without args: $? +echo after exec1.sub: "$@" + +# set up a fixed path so we know notthere will not be found +PATH=/usr/bin:/bin:/usr/local/bin: +export PATH + +notthere +echo $? + +# this is iffy, since the error messages may vary from system to system +# and /tmp might not exist +ln -s ${THIS_SH} /tmp/bash 2>/dev/null +if [ -f /tmp/bash ]; then + /tmp/bash notthere +else + ${THIS_SH} notthere +fi +echo $? +rm -f /tmp/bash + +# /bin/sh should be there on all systems +${THIS_SH} /bin/sh +echo $? + +# try executing a directory +/ +echo $? + +${THIS_SH} / +echo $? + +# try sourcing a directory +. / +echo $? + +# try sourcing a binary file -- post-2.04 versions don't do the binary file +# check, and will probably fail with `command not found', or status 127 +# bash-4.1 and later check for 256 NUL characters and fail as binary files +# if there are more than that, it's probably binary +. ${THIS_SH} 2>/dev/null +echo $? + +# post-bash-2.05 versions allow sourcing non-regular files +. /dev/null +echo $? + +# kill two birds with one test -- test out the BASH_ENV code +echo echo this is bashenv > $TMPDIR/bashenv +export BASH_ENV=$TMPDIR/bashenv +${THIS_SH} ./exec3.sub +rm -f $TMPDIR/bashenv +unset BASH_ENV + +# we're resetting the $PATH to empty, so this should be last +PATH= + +notthere +echo $? + +command notthere +echo $? + +command -p notthere +echo $? + +# but -p should guarantee that we find all the standard utilities, even +# with an empty or unset $PATH +command -p sh -c 'echo this is $0' +unset PATH +command -p sh -c 'echo this is $0' + +# a bug in bash before bash-2.01 caused PATH to be set to the empty string +# when command -p was run with PATH unset +echo ${PATH-unset} + +echo "echo ok" | ${THIS_SH} -t + +${THIS_SH} ./exec2.sub +echo $? + +${THIS_SH} ./exec4.sub + +# try exec'ing a command that cannot be found in $PATH +${THIS_SH} ./exec5.sub + +# this was a bug in bash versions before bash-2.04 +${THIS_SH} -c 'cat </dev/null | cat >/dev/null' >&- + +# checks for proper return values in subshell commands with inverted return +# values + +${THIS_SH} ./exec6.sub + +# checks for properly deciding what constitutes an executable file +${THIS_SH} ./exec7.sub + +${THIS_SH} -i ${PWD}/exec8.sub + +${THIS_SH} ./exec9.sub + +${THIS_SH} ./exec10.sub +${THIS_SH} ./exec11.sub + +true | `echo true` & + +echo after + +# Problem with bash at least back to version 3.0 +${THIS_SH} -c 'VAR=0; VAR=1 command exec; exit ${VAR}' + +# problem with bash through bash-4.1 +( + exec /var/empty/nosuch + echo bad +) 2>/dev/null +[ $? = 127 ] || echo FAIL: bad exit status $? at $LINENO + +unset FALSE +if [ -x /bin/false ]; then + FALSE=/bin/false +elif [ -x /usr/bin/false ]; then + FALSE=/usr/bin/false +else + FALSE='command false' +fi + +# problem with undoing redirections before running exit trap through bash-4.3 + +${THIS_SH} ./exec12.sub false # function +${THIS_SH} ./exec12.sub command false +${THIS_SH} ./exec12.sub $FALSE + +${THIS_SH} ./exec12.sub notfound +${THIS_SH} ./exec12.sub syntaxerror +${THIS_SH} ./exec12.sub nosuchcommand + +# problem with fork optimization in bash-4.4-alpha + +$THIS_SH -c 'echo a && /bin/echo b && echo c' +$THIS_SH -c 'echo A && /bin/echo B' + +$THIS_SH -c '/bin/echo c && echo d' +$THIS_SH -c '/bin/echo c && /bin/echo d && echo e' + +${THIS_SH} ./exec13.sub diff --git a/tests/exp.right b/tests/exp.right new file mode 100644 index 0000000..a2dc86f --- /dev/null +++ b/tests/exp.right @@ -0,0 +1,407 @@ +argv[1] = <^A> +argv[1] = <^A> +argv[1] = <^?> +argv[1] = <^?> +argv[1] = <^A> +argv[1] = <^?> +argv[1] = <bar> +argv[1] = <^A> +argv[1] = <^?> +argv[1] = <^A> +argv[1] = <^?> +argv[1] = <abcdefgh> +argv[1] = <abcdefgh> +argv[1] = <abcdefgh> +argv[1] = <abcdefgh> +argv[1] = <abcd> +argv[1] = <abcd> +argv[1] = < > +argv[1] = <--> +argv[1] = <> +argv[1] = <> +argv[1] = <> +argv[1] = <> +argv[1] = <> +argv[1] = <> +argv[1] = <abc> +argv[1] = <abc> +argv[1] = <abc> +argv[1] = <abc> +argv[1] = <abcdef> +argv[1] = <abcdef> +argv[1] = <^A> +argv[1] = <^?> +argv[1] = <^A> +argv[1] = <^?> +argv[1] = <^A> +argv[1] = <^?> +argv[1] = <> +argv[1] = <> +argv[1] = <> +argv[1] = <Hello world!> +argv[1] = <`> +argv[1] = <"> +argv[1] = <\^A> +argv[1] = <\$> +argv[1] = <\\> +argv[1] = <a> +argv[2] = <b> +argv[1] = <^A> +argv[2] = <^?> +argv[1] = <**> +argv[1] = <\.\./*/> +argv[1] = <^A^?^A^?> +argv[1] = <^A^A> +argv[1] = <^A^?> +argv[1] = <^A^A^?> +argv[1] = < abc> +argv[2] = <def> +argv[3] = <ghi> +argv[4] = <jkl > +argv[1] = < abc> +argv[2] = <def> +argv[3] = <ghi> +argv[4] = <jkl > +argv[1] = <--abc> +argv[2] = <def> +argv[3] = <ghi> +argv[4] = <jkl--> +argv[1] = <a b> +argv[2] = <cd> +argv[3] = <ef> +argv[4] = <gh> +argv[1] = <a b> +argv[2] = <cd> +argv[3] = <ef> +argv[4] = <gh> +argv[1] = <a b> +argv[2] = <cd> +argv[3] = <ef> +argv[4] = <gh> +argv[1] = < > +argv[1] = < - > +argv[1] = </^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\1/> +argv[1] = <foo bar> +argv[1] = <foo> +argv[2] = <bar> +argv[1] = <abc> +argv[1] = <abc> +argv[1] = <posix> +argv[1] = <10> +argv[1] = <file.o> +argv[1] = <posix> +argv[1] = </src/cmd> +argv[1] = <three> +argv[1] = <abcdef> +argv[1] = <abcdef> +argv[1] = <abcdef> +argv[1] = <abcdef> +argv[1] = <\$x> +argv[1] = <$x> +argv[1] = <\$x> +argv[1] = <abc> +argv[2] = <def> +argv[3] = <ghi> +argv[4] = <jkl> +argv[1] = <abc def ghi jkl> +argv[1] = <abc:def ghi:jkl> +argv[1] = <abc> +argv[2] = <def ghi> +argv[3] = <jkl> +argv[1] = <xxabc> +argv[2] = <def ghi> +argv[3] = <jklyy> +argv[1] = <abc> +argv[2] = <def ghi> +argv[3] = <jklabc> +argv[4] = <def ghi> +argv[5] = <jkl> +argv[1] = <abcdef> +argv[1] = <bar> +argv[2] = <> +argv[3] = <xyz> +argv[4] = <> +argv[5] = <abc> +argv[1] = <$foo> +argv[1] = <10> +argv[1] = <newline expected> +argv[1] = <got it> +argv[1] = <got it> +argv[1] = <one> +argv[2] = <three> +argv[3] = <five> +argv[1] = <5> +argv[2] = <5> +argv[1] = <3> +argv[1] = <1> +argv[1] = <1> +argv[1] = <5> +argv[1] = <5> +argv[1] = <5> +argv[1] = <5> +argv[1] = <42> +argv[1] = <26> +argv[1] = <\> +argv[1] = <~> +argv[1] = <a> +argv[2] = <b> +argv[3] = <c> +argv[4] = <d> +argv[5] = <e> +a?b?c +a b c +argv[1] = <^?> +argv[1] = <^?> +argv[1] = <^?> +argv[1] = <^?> +argv[1] = <^?> +argv[1] = <^?> +argv[1] = <^A> +argv[2] = <^?> +argv[1] = <^A^?> +argv[1] = <^A^?^A^?> +argv[1] = <^A^A^?> +0.net +0.net0 + +0.net +0.net +0.net +graph +yes +a +a + val +val + val +no arg passed +hello +[0;31m\] +] +[hello +\[\e[0;31m\] + +hello +eo +argv[1] = <a> +argv[1] = <a> +argv[1] = <^?> +argv[1] = <^?b> +argv[1] = <b^?> +argv[1] = <c> +argv[1] = <c> +argv[1] = <c> +argv[1] = <c> +argv[1] = <c> +argv[1] = <c> +argv[1] = <correct> +argv[2] = <> +argv[1] = <correct> +argv[2] = <> +argv[1] = <correct> +argv[2] = <> +argv[1] = <XwrongX> +argv[2] = <> +argv[1] = <correct> +argv[2] = <a> +argv[1] = <XwrongX> +argv[2] = <a> +argv[1] = <correct> +argv[2] = <a> +argv[1] = <correct> +argv[2] = <a> +argv[1] = <^A> +argv[1] = <3> +argv[2] = <^C> +argv[3] = <^C> +argv[4] = <^C> +argv[1] = <^A> +argv[1] = <XY> +argv[2] = <YX> +argv[1] = <XY^AYX> +argv[1] = <XY> +argv[2] = <Y> +argv[1] = <XY^AY> +argv[1] = <x^Ay^?z> +argv[1] = <x^Ay^?z> +declare -- var="xyz" +argv[1] = <declare> +argv[2] = <--> +argv[3] = <var="x^Ay^?z"> +declare -- var="x\001y\177z"$ +argv[1] = <$'x\001y\177z'> +argv[1] = <x^Ay^?z> +var=$'x\001y\177z' +./exp8.sub: line 16: xyz: syntax error: invalid arithmetic operator (error token is "z") +declare -a array=() +declare -a array=([0]=$'x\001y\177z') +argv[1] = <x^Ay^?z> +declare -a array=([0]=$'x\001y\177z') +declare -A array=([$'x\001y\177z']=$'a\242b\002c' ) +abc +def +ghi +jkl +abc def ghi jkl +xxabc +def +ghi +jklyy +xxabc def ghi jklyy +abc +def +ghi +jkl +abc +def ghi +jkl +abc +def ghi +jkl +abc +def ghi +jkl +xxabc +def +ghi +jklyy +xxabc +def ghi +jklyy +abc +def +ghi +jklabc +def +ghi +jkl +abc +def ghi +jklabc +def ghi +jkl +abc:def ghi:jkl +abc:def ghi:jkl +abc:def ghi:jkl +abc +def ghi +jkl +abc:def ghi:jkl +abc:def ghi:jkl +abc +def ghi +jkl +var=abc:def ghi:jkl +abc:def ghi:jkl +var=abc:def ghi:jkl +abcdef ghijkl +abcdef ghijkl +abcdef ghijkl +abc +def ghi +jkl +abcdef ghijkl +abcdef ghijkl +abcdef ghijkl +var=abcdef ghijkl +abcdef ghijkl +var=abcdef ghijkl +abc +def ghi +jkl +abc def ghi jkl +abc def ghi jkl +abc def ghi jkl +abc +def +ghi +jkl +abc def ghi jkl +abc def ghi jkl +abc +def +ghi +jkl +var=abc def ghi jkl +abc def ghi jkl +var=abc def ghi jkl +abc +def ghi +jkl +[foo] +[] +[foo] +[] +[foo] +[foo] +[foo] +[] +[foo] +[] +[foo] +[] +< A >< B >< A >< B > +< A >< B >< A >< B > +< A >< B >< a >< b > +< A >< B >< A >< B > +< A >< B ><' A '><' B '> +----- +< A >< B >< A >< B > +< A >< B >< A >< B > +< A >< B >< a >< b > +< A >< B >< A >< B > +< A >< B ><' A '><' B '> +argv[1] = <1> +argv[2] = <2> +argv[1] = <1> +argv[2] = <2> +argv[1] = <1> +argv[2] = <2> +argv[1] = <1 2> +argv[1] = <a b> +argv[1] = <a> +argv[2] = <b> +argv[1] = <a b> +argv[1] = <1> +argv[2] = <2> +argv[1] = <1> +argv[2] = <2> +argv[1] = <1> +argv[2] = <2> +argv[1] = <12> +argv[1] = <12> +argv[1] = <1> +argv[2] = <2> +argv[1] = <1> +argv[2] = <2> +argv[1] = < > +argv[1] = < > +argv[1] = < > +argv[1] = < > +argv[1] = < > +argv[1] = <12> +argv[1] = <12> +argv[1] = <12> +argv[1] = <12> +ok 1 +ok 2 +ok 3 +ok 4 +ok 5 +ok 6 +ok 7 +ok 8 +ok 9 +argv[1] = <file.o> +argv[1] = <posix> +argv[1] = </src/cmd> +argv[1] = <three> +argv[1] = </one/two/three> +abcdefg +abcdefg +abcdefg +abcdefg +cdefg +abcdefg +abcde +abcdefg diff --git a/tests/exp.tests b/tests/exp.tests new file mode 100644 index 0000000..6e364f9 --- /dev/null +++ b/tests/exp.tests @@ -0,0 +1,410 @@ +# +# A suite of tests for bash word expansions +# +# This tests parameter and variable expansion, with an empahsis on +# proper quoting behavior. +# +# Chet Ramey + +# +# If you comment out the body of this function, you can do a diff against +# `expansion-tests.right' to see if the shell is behaving correctly +# +expect() +{ + echo expect "$@" +} + +# Test the substitution quoting characters (CTLESC and CTLNUL) in different +# combinations + +expect "<^A>" +recho `echo ''` +expect "<^A>" +recho `echo ""` +expect "<^?>" +recho `echo ''` +expect "<^?>" +recho `echo ""` +expect "<^A>" +recho `echo ` +expect "<^?>" +recho `echo ` + +expect "bar" +recho ${foo:-"`echo bar`"} +expect "<^A>" +recho ${foo:-"`echo `"} +expect "<^?>" +recho ${foo:-"`echo `"} + +expect "<^A>" +recho "`echo `" +expect "<^?>" +recho "`echo `" + +# Test null strings without variable expansion +expect "<abcdefgh>" +recho abcd""efgh +expect "<abcdefgh>" +recho abcd''efgh +expect "<abcdefgh>" +recho ""abcdefgh +expect "<abcdefgh>" +recho ''abcdefgh +expect "<abcd>" +recho abcd"" +expect "<abcd>" +recho abcd'' + +# Test the quirky behavior of $@ in "" +expect nothing +recho "$@" +expect "< >" +recho " $@" +expect "<-->" +recho "-${@}-" + +# Test null strings with variable expansion that fails +expect '<>' +recho $xxx"" +expect '<>' +recho ""$xxx +expect '<>' +recho $xxx'' +expect '<>' +recho ''$xxx +expect '<>' +recho $xxx""$yyy +expect '<>' +recho $xxx''$yyy + +# Test null strings with variable expansion that succeeds +xxx=abc +yyy=def + +expect '<abc>' +recho $xxx"" +expect '<abc>' +recho ""$xxx +expect '<abc>' +recho $xxx'' +expect '<abc>' +recho ''$xxx +expect '<abcdef>' +recho $xxx""$yyy +expect '<abcdef>' +recho $xxx''$yyy + +unset xxx yyy + +# Test the unquoted special quoting characters +expect "<^A>" +recho +expect "<^?>" +recho +expect "<^A>" +recho "" +expect "<^?>" +recho "" +expect "<^A>" +recho '' +expect "<^?>" +recho '' + +# Test expansion of a variable that is unset +expect nothing +recho $xxx +expect '<>' +recho "$xxx" + +expect nothing +recho "$xxx${@}" + +# Test empty string expansion +expect '<>' +recho "" +expect '<>' +recho '' + +# Test command substitution with (disabled) history substitution +expect '<Hello World!>' +# set +H +recho "`echo \"Hello world!\"`" + +# Test some shell special characters +expect '<`>' +recho "\`" +expect '<">' +recho "\"" +expect '<\^A>' +recho "\" + +expect '<\$>' +recho "\\$" + +expect '<\\>' +recho "\\\\" + +# This should give argv[1] = a argv[2] = b +expect '<a> <b>' +FOO=`echo 'a b' | tr ' ' '\012'` +recho $FOO + +# This should give argv[1] = ^A argv[2] = ^? +expect '<^A> <^?>' +FOO=`echo ' ' | tr ' ' '\012'` +recho $FOO + +# Test quoted and unquoted globbing characters +expect '<**>' +recho "*"* + +expect '<\.\./*/>' +recho "\.\./*/" + +# Test patterns that come up when the shell quotes funny character +# combinations +expect '<^A^?^A^?>' +recho '' +expect '<^A^A>' +recho '' +expect '<^A^?>' +recho '' +expect '<^A^A^?>' +recho '' + +# More tests of "$@" +set abc def ghi jkl +expect '< abc> <def> <ghi> <jkl >' +recho " $@ " +expect '< abc> <def> <ghi> <jkl >' +recho "${1+ $@ }" + +set abc def ghi jkl +expect '<--abc> <def> <ghi> <jkl-->' +recho "--$@--" + +set "a b" cd ef gh +expect '<a b> <cd> <ef> <gh>' +recho ${1+"$@"} +expect '<a b> <cd> <ef> <gh>' +recho ${foo:-"$@"} +expect '<a b> <cd> <ef> <gh>' +recho "${@}" + +expect '< >' +recho " " +expect '< - >' +recho " - " + +# Test combinations of different types of quoting in a fully-quoted string +# (so the WHOLLY_QUOTED tests fail and it doesn't get set) +expect '</^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\1/>' +recho "/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*"'$'"/\1/" + +# Test the various Posix parameter expansions + +expect '<foo bar>' +recho "${x:-$(echo "foo bar")}" +expect '<foo> <bar>' +recho ${x:-$(echo "foo bar")} + +unset X +expect '<abc>' +recho ${X:=abc} +expect '<abc>' +recho $X + +set a b c +expect '<posix>' +recho ${3:+posix} + +POSIX=/usr/posix +expect '<10>' +recho ${#POSIX} + +# remove shortest trailing match +x=file.c +expect '<file.o>' +recho ${x%.c}.o + +# remove longest trailing match +x=posix/src/std +expect '<posix>' +recho ${x%%/*} + +# remove shortest leading pattern +x=$HOME/src/cmd +expect '</src/cmd>' +recho ${x#$HOME} + +# remove longest leading pattern +x=/one/two/three +expect '<three>' +recho ${x##*/} + +# pattern removal of patterns that don't match +z=abcdef + +expect '<abcdef>' +recho ${z#xyz} +expect '<abcdef>' +recho ${z##xyz} + +expect '<abcdef>' +recho ${z%xyz} +expect '<abcdef>' +recho ${z%%xyz} + +# Command substitution and the quirky differences between `` and $() + +expect '<\$x>' +recho '\$x' + +expect '<$x>' +recho `echo '\$x'` + +expect '<\$x>' +recho $(echo '\$x') + +# The difference between $* "$*" and "$@" + +set "abc" "def ghi" "jkl" + +expect '<abc> <def> <ghi> <jkl>' +recho $* + +expect '<abc def ghi jkl>' +recho "$*" + +OIFS="$IFS" +IFS=":$IFS" + +# The special behavior of "$*", using the first character of $IFS as separator +expect '<abc:def ghi:jkl>' +recho "$*" + +IFS="$OIFS" + +expect '<abc> <def ghi> <jkl>' +recho "$@" + +expect '<xxabc> <def ghi> <jklyy>' +recho "xx$@yy" + +expect '<abc> <def ghi> <jklabc> <def ghi> <jkl>' +recho "$@$@" + +foo=abc +bar=def + +expect '<abcdef>' +recho "$foo""$bar" + +unset foo +set $foo bar '' xyz "$foo" abc + +expect '<bar> <> <xyz> <> <abc>' +recho "$@" + +# More tests of quoting and deferred evaluation + +foo=10 x=foo +y='$'$x +expect '<$foo>' +recho $y +eval y='$'$x +expect '<10>' +recho $y + +# case statements + +NL=' +' +x='ab +cd' + +expect '<newline expected>' +case "$x" in +*$NL*) recho "newline expected" ;; +esac + +expect '<got it>' +case \? in +*"?"*) recho "got it" ;; +esac + +expect '<got it>' +case \? in +*\?*) recho "got it" ;; +esac + +set one two three four five +expect '<one> <three> <five>' +recho $1 $3 ${5} $8 ${9} + +# length tests on positional parameters and some special parameters + +expect '<5> <5>' +recho $# ${#} +expect '<3>' +recho ${#1} +expect '<1>' +recho ${##} +expect '<1>' +recho ${#?} +expect '<5>' +recho ${#@} +expect '<5>' +recho ${#*} +expect '<5>' +recho "${#@}" +expect '<5>' +recho "${#*}" + +expect '<42>' +recho $((28 + 14)) +expect '<26>' +recho $[ 13 * 2 ] + +expect '<\>' +recho `echo \\\\` + +expect '<~>' +recho '~' + +expect nothing +recho $! +expect nothing +recho ${!} + +# test word splitting of assignment statements not preceding a command +a="a b c d e" +declare b=$a +expect '<a> <b> <c> <d> <e>' +recho $b + +a="a?b?c" + +echo ${a//\\?/ } + +echo ${a//\?/ } + +${THIS_SH} ./exp1.sub + +${THIS_SH} ./exp2.sub + +${THIS_SH} ./exp3.sub + +${THIS_SH} ./exp4.sub + +${THIS_SH} ./exp5.sub + +${THIS_SH} ./exp6.sub +${THIS_SH} ./exp7.sub +${THIS_SH} ./exp8.sub +${THIS_SH} ./exp9.sub +${THIS_SH} ./exp10.sub +${THIS_SH} ./exp11.sub +${THIS_SH} ./exp12.sub diff --git a/tests/exp1.sub b/tests/exp1.sub new file mode 100644 index 0000000..3e40f2a --- /dev/null +++ b/tests/exp1.sub @@ -0,0 +1,21 @@ +# Test the substitution quoting characters (CTLESC and CTLNUL) in different +# combinations + +recho `echo ''` +recho `echo ""` +recho `echo ` + +# Test the unquoted special quoting characters +recho +recho "" +recho '' + +# This should give argv[1] = ^A argv[2] = ^? +FOO=`echo ' ' | tr ' ' '\012'` +recho $FOO + +# Test patterns that come up when the shell quotes funny character +# combinations +recho '' +recho '' +recho '' diff --git a/tests/exp10.sub b/tests/exp10.sub new file mode 100644 index 0000000..6592bab --- /dev/null +++ b/tests/exp10.sub @@ -0,0 +1,26 @@ +set -- ' A ' ' B ' +IFS= + +printf '<%s>' ${*} ${*##} +echo +printf '<%s>' ${*} ${*/} +echo +printf '<%s>' ${*} ${*,,} +echo +printf '<%s>' ${*} ${*:1:2} +echo +printf '<%s>' ${*} ${*@Q} +echo + +echo ----- + +printf '<%s>' ${@} ${@##} +echo +printf '<%s>' ${@} ${@/} +echo +printf '<%s>' ${@} ${@,,} +echo +printf '<%s>' ${@} ${@:1:2} +echo +printf '<%s>' ${@} ${@@Q} +echo diff --git a/tests/exp11.sub b/tests/exp11.sub new file mode 100644 index 0000000..cae7b19 --- /dev/null +++ b/tests/exp11.sub @@ -0,0 +1,92 @@ +set -- '1 2' + +unset var +recho ${var-${*:1}} + +unset var +recho ${var=$*} + +unset var +recho ${var=${*:1}} +recho "$var" + +# posix interp 221 +unset var +recho ${var:-a\ b} + +recho ${var:=a\ b} +recho "$var" + +set -- 1 2 +IFS= + +unset a b c +recho $* +recho ${a-$*} +recho ${b-${*/}} +recho ${c=${*/}} +recho "$c" +recho ${b-${*,,}} +recho ${d-${*,,}} + +unset -v a b c +IFS=$' \t\n' + +set -- ' ' +A=(' ') + +IFS= +unset var +var=${*@E} +recho "$var" + +unset var +var=${A[*]@E} +recho "$var" + +unset var +var=${@@E} +recho "$var" + +unset var +var=${A[@]@E} +recho "$var" + +unset novar +recho ${novar-${A[*]@E}} + +unset -v var novar +IFS=$' \t\n' + +set -- 1 2 +A=( 1 2 ) +IFS= + +a=$* +recho "$a" +b=${*@E} +recho "$b" + +unset a b +a=${A[*]} +recho "$a" +b=${A[*]@E} +recho "$b" + +set -- $'\t' +A=$1 + +IFS=$1 +[[ ${A[@]} ]] && echo ok 1 +[[ ${A[*]} ]] && echo ok 2 +[[ ${A[0]} ]] && echo ok 3 + +IFS=$' \t\n' +[[ ${A[@]} ]] && echo ok 4 +[[ ${A[*]} ]] && echo ok 5 +[[ ${A[0]} ]] && echo ok 6 + +IFS= +[[ ${A[@]} ]] && echo ok 7 +[[ ${A[*]} ]] && echo ok 8 +[[ ${A[0]} ]] && echo ok 9 diff --git a/tests/exp12.sub b/tests/exp12.sub new file mode 100644 index 0000000..0aaa2f4 --- /dev/null +++ b/tests/exp12.sub @@ -0,0 +1,38 @@ +# force single-byte versions of these functions + +export LANG=C + +# remove shortest trailing match +x=file.c +recho ${x%.c}.o + +# remove longest trailing match +x=posix/src/std +recho ${x%%/*} + +# remove shortest leading pattern +x=$HOME/src/cmd +recho ${x#$HOME} + +# remove longest leading pattern +x=/one/two/three +recho ${x##*/} + +# and no match thrown in for good measure +recho ${x#nomatch} + +foo=abcdefg + +# fail +echo ${foo%ab} +echo ${foo%def} + +echo ${foo#fg} +echo ${foo#def} + +# succeed +echo ${foo#ab} +echo ${foo#def} + +echo ${foo%fg} +echo ${foo%def} diff --git a/tests/exp2.sub b/tests/exp2.sub new file mode 100644 index 0000000..a70179e --- /dev/null +++ b/tests/exp2.sub @@ -0,0 +1,12 @@ +K=dvb0.net A=${K#dvb} eval echo \$A +unset K A +x=${K:=dvb0.net0} A=${K#dvb} eval echo \$A + +unset K A +K=dvb0.net A=${K#dvb} echo "$A" +unset K A +K=dvb0.net A=${K#dvb} ; echo "$A" +unset K A +K=dvb0.net A=${K#dvb} eval echo '$A' +unset K A +K=dvb0.net A=${K#dvb} eval echo \$A diff --git a/tests/exp3.sub b/tests/exp3.sub new file mode 100644 index 0000000..212d579 --- /dev/null +++ b/tests/exp3.sub @@ -0,0 +1,7 @@ +IFS=: + +case A in ([[:graph:]]) echo graph;; *) echo non-graph;; esac +[[ A == [[:graph:]] ]] && echo yes || echo no + +IFS="~"; read a b <<< a~q; echo $a +IFS=':'; read a b <<< a:q; echo $a diff --git a/tests/exp4.sub b/tests/exp4.sub new file mode 100644 index 0000000..d022ceb --- /dev/null +++ b/tests/exp4.sub @@ -0,0 +1,10 @@ +f=" val" e= +echo "$e"$f +echo $e$f +echo "$e""$f" + +if [[ "$1"x == x ]] ; then + echo "no arg passed" + exit 1 +fi +echo "$1"x | cat -v diff --git a/tests/exp5.sub b/tests/exp5.sub new file mode 100644 index 0000000..52dd4a1 --- /dev/null +++ b/tests/exp5.sub @@ -0,0 +1,21 @@ +# expansions involving patterns +var='[hello' +echo "${var//[/}" + +red='\[\e[0;31m\]' +printf "%s\n" "${red//\\[\\e/}" + +foo="${red//\\[\\e/}" + +# foo == [0;31m\] +printf "%s\n" "${foo//[0;31m\\/}" + +echo "${var//[]/}" +echo "${red//[]/}" + +v=hello +foo='[:alpha:]' + +echo ${v//[[:alpha:]]/} +echo ${v//[[:alpha]]/} +echo ${v//[[:alpha]/} diff --git a/tests/exp6.sub b/tests/exp6.sub new file mode 100644 index 0000000..a1c9fe6 --- /dev/null +++ b/tests/exp6.sub @@ -0,0 +1,30 @@ +recho """"a +recho a"""" + +recho """" + +recho """"b +recho b"""" + +recho """"""c +recho c"""""" + +recho """"""c"""" +recho """"c"""""" + +recho """"""""c +recho c"""""""" + +# BASH BUG: spurious DEL characters appear on empty variable interpolation. +# BASH 4.2.8(1)-release + +a='' + +recho correct "$a" # correct empty output line +recho correct "$a""$a" # correct empty output line +recho correct "$a""$a""$a" # correct empty output line +recho XwrongX "$a""$a""$a""$a" # spurious two DEL chars appear at line end +recho correct a"$a" # correct single "a" on line +recho XwrongX a"$a""$a" # spurious DEL char appears at line end +recho correct a"$a$a" # correct single "a" on line +recho correct a"$a$a$a$a" # correct single "a" on line diff --git a/tests/exp7.sub b/tests/exp7.sub new file mode 100644 index 0000000..f3f3b6b --- /dev/null +++ b/tests/exp7.sub @@ -0,0 +1,23 @@ +IFS=$'\001' +c=$'\001' +c2=$'\003' + +IFS=$c # this is the problem line, IFS should end up being \001 +recho "$IFS" +set -- $c2$c$c2$c$c2 +recho $# "$1" "$2" "$3" + +x=$c +recho "$x" + +unset c c2 x + +c=$'Y\1Y'; + +v=X${c}X; +recho X${c}X +recho "$v" + +v=X$c +recho X$c +recho "$v" diff --git a/tests/exp8.sub b/tests/exp8.sub new file mode 100644 index 0000000..ff44feb --- /dev/null +++ b/tests/exp8.sub @@ -0,0 +1,31 @@ +var=$'x\001y\177z' + +recho "$var" +recho $var + +declare -p var +recho $(declare -p var) + +declare -p var | sed -n l + +recho ${var@Q} +recho ${var@P} +echo -E ${var@A} + +unset array +array=( [$'x\001y\177z']=foo ) # should be error +echo -E ${array[@]@A} + +unset array +declare -a array=([0]=$'x\001y\177z') +declare -p array + +unset array +array=( "$var" ) +recho ${array[@]} +echo -E ${array[@]@A} + +unset array +declare -A array +array=( [$'x\001y\177z']=$'a\242b\002c' ) +echo -E ${array[@]@A} diff --git a/tests/exp9.sub b/tests/exp9.sub new file mode 100644 index 0000000..a0399c7 --- /dev/null +++ b/tests/exp9.sub @@ -0,0 +1,69 @@ +# expansion test cases from Posix interp 888 + +set "abc" "def ghi" "jkl" +unset novar +IFS=' ' # a space +printf '%s\n' $* +printf '%s\n' "$*" +printf '%s\n' xx$*yy +printf '%s\n' "xx$*yy" +printf '%s\n' $@ +printf '%s\n' "$@" +printf '%s\n' ${1+"$@"} +printf '%s\n' ${novar-"$@"} +printf '%s\n' xx$@yy +printf '%s\n' "xx$@yy" +printf '%s\n' $@$@ +printf '%s\n' "$@$@" +IFS=':' +printf '%s\n' "$*" +var=$*; printf '%s\n' "$var" +var="$*"; printf '%s\n' "$var" +unset var +printf '%s\n' ${var-$*} +printf '%s\n' "${var-$*}" +printf '%s\n' ${var-"$*"} +printf '%s\n' ${var=$*} +printf 'var=%s\n' "$var" +unset var +printf '%s\n' "${var=$*}" +printf 'var=%s\n' "$var" + +IFS='' # null +printf '%s\n' "$*" +var=$*; printf '%s\n' "$var" +var="$*"; printf '%s\n' "$var" +unset var +printf '%s\n' ${var-$*} +printf '%s\n' "${var-$*}" +printf '%s\n' ${var-"$*"} +printf '%s\n' ${var=$*} +printf 'var=%s\n' "$var" +unset var +printf '%s\n' "${var=$*}" +printf 'var=%s\n' "$var" +printf '%s\n' "$@" + +unset IFS +printf '%s\n' "$*" +var=$*; printf '%s\n' "$var" +var="$*"; printf '%s\n' "$var" +unset var +printf '%s\n' ${var-$*} +printf '%s\n' "${var-$*}" +printf '%s\n' ${var-"$*"} +printf '%s\n' ${var=$*} +printf 'var=%s\n' "$var" +unset var +printf '%s\n' "${var=$*}" +printf 'var=%s\n' "$var" +printf '%s\n' "$@" + +set -- +printf '[%s]\n' foo "$*" +printf '[%s]\n' foo "$novar$*$(echo)" +printf '[%s]\n' foo $@ +printf '[%s]\n' foo "$@" +printf '[%s]\n' foo ''$@ +printf '[%s]\n' foo ''"$@" +printf '[%s]\n' foo ''"$novar$@$(echo)" diff --git a/tests/exportfunc.right b/tests/exportfunc.right new file mode 100644 index 0000000..2ee35a7 --- /dev/null +++ b/tests/exportfunc.right @@ -0,0 +1,14 @@ +exportfunc ok 1 +exportfunc ok 2 +./exportfunc.tests: line 24: cve7169-bad: No such file or directory +./exportfunc.tests: eval: line 31: syntax error: unexpected end of file +./exportfunc.tests: line 30: cve7169-bad2: No such file or directory +./exportfunc1.sub: line 1: maximum here-document count exceeded +./exportfunc.tests: line 51: HELLO_WORLD: No such file or directory +eval ok +./exportfunc3.sub: line 10: export: foo=bar: cannot export +status: 1 +equals-1 +bad echo +./exportfunc3.sub: line 23: export: /bin/echo: cannot export +bar diff --git a/tests/exportfunc.tests b/tests/exportfunc.tests new file mode 100644 index 0000000..f5ef54f --- /dev/null +++ b/tests/exportfunc.tests @@ -0,0 +1,71 @@ +# normal operation +foo() +{ + echo exportfunc ok 1 +} +export -f foo +${THIS_SH} -c foo +unset -f foo +foo-a () +{ + echo exportfunc ok 2 +} +export -f foo-a +${THIS_SH} -c 'foo-a' + +# CVE-2014-6271 + +env -i BASH_FUNC_foo%%='() { echo cve6271 ok; } ; echo BAD' ${THIS_SH} -c foo 2>/dev/null + +# CVE-2014-7169 + +rm -f cve7169-bad +env -i BASH_FUNC_X%%='() { (a)=>\' ${THIS_SH} -c cve7169-bad 2>/dev/null +: < cve7169-bad +rm -f cve7169-bad + +echo cve7169-bad2 > $TMPDIR/bar +rm -f cve7169-bad2 +eval 'X() { (a)>\' ; . ./bar 2>/dev/null +: < cve7169-bad2 +rm -f cve7169-bad2 $TMPDIR/bar + +# CVE-2014-7186 +${THIS_SH} ./exportfunc1.sub + +# CVE-2014-7187 +${THIS_SH} ./exportfunc2.sub + +# CVE-2014-6277 + +env BASH_FUNC_foo%%="() { 000(){>0;}&000(){ 0;}<<0 0" ${THIS_SH} -c foo 2>/dev/null +env BASH_FUNC_foo%%="() { 000(){>0;}&000(){ 0;}<<`perl -e '{print "A"x100000}'` 0" ${THIS_SH} -c foo 2>/dev/null +${THIS_SH} -c "f(){ x(){ _;}; x(){ _;}<<a;}" 2>/dev/null + +# CVE-2014-6278 + +env 'BASH_FUNC_FOO%%=() { 0;}>r[0${$(}0 {>"$(id >/dev/tty)"; }' ${THIS_SH} -c : 2>/dev/null + +rm -f HELLO_WORLD +env BASH_FUNC_FOO%%='() { 0;}>r[0${$(}0 {>HELLO_WORLD; }' ${THIS_SH} -c : 2>/dev/null +: < HELLO_WORLD + +env BASH_FUNC_x%%='() { _;}>_[$($())] { echo vuln;}' ${THIS_SH} -c : 2>/dev/null + +env -i BASH_FUNC_x%%='() { _; } >_[${ $() }] { id; }' ${THIS_SH} -c : 2>/dev/null + +env BASH_FUNC_x%%=$'() { _;}>_[$($())]\n{ echo vuln;}' ${THIS_SH} -c : 2>/dev/null +eval 'x() { _;}>_[$($())] { echo vuln;}' 2>/dev/null + +eval 'foo() { _; } >_[${ $() }] ;{ echo eval ok; }' + +# other tests fixed in bash43-030 concerning function name transformation +env $'BASH_FUNC_\nfoo%%=() { echo transform-1; }' ${THIS_SH} -c foo 2>/dev/null +env $'BASH_FUNC_foo\n%%=() { echo transform-2; }' ${THIS_SH} -c foo 2>/dev/null +env $'BASH_FUNC_ foo %%=() { echo transform-3; }' ${THIS_SH} -c foo 2>/dev/null + +unset -f foo +env $'BASH_FUNC_#badname%%'=$'() { :; }\nfoo () { echo transform-4; } ' ${THIS_SH} -c 'foo' 2>/dev/null + +# tests of exported names +${THIS_SH} ./exportfunc3.sub diff --git a/tests/exportfunc1.sub b/tests/exportfunc1.sub new file mode 100644 index 0000000..d9c9fa1 --- /dev/null +++ b/tests/exportfunc1.sub @@ -0,0 +1,21 @@ +cat <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF +EOF +EOF +EOF +EOF +EOF +EOF +EOF +EOF +EOF +EOF +EOF +EOF +EOF +EOF +EOF +EOF +EOF +EOF + +echo after EOF diff --git a/tests/exportfunc2.sub b/tests/exportfunc2.sub new file mode 100644 index 0000000..886b71b --- /dev/null +++ b/tests/exportfunc2.sub @@ -0,0 +1,400 @@ +for x1 in ; do : +for x2 in ; do : +for x3 in ; do : +for x4 in ; do : +for x5 in ; do : +for x6 in ; do : +for x7 in ; do : +for x8 in ; do : +for x9 in ; do : +for x10 in ; do : +for x11 in ; do : +for x12 in ; do : +for x13 in ; do : +for x14 in ; do : +for x15 in ; do : +for x16 in ; do : +for x17 in ; do : +for x18 in ; do : +for x19 in ; do : +for x20 in ; do : +for x21 in ; do : +for x22 in ; do : +for x23 in ; do : +for x24 in ; do : +for x25 in ; do : +for x26 in ; do : +for x27 in ; do : +for x28 in ; do : +for x29 in ; do : +for x30 in ; do : +for x31 in ; do : +for x32 in ; do : +for x33 in ; do : +for x34 in ; do : +for x35 in ; do : +for x36 in ; do : +for x37 in ; do : +for x38 in ; do : +for x39 in ; do : +for x40 in ; do : +for x41 in ; do : +for x42 in ; do : +for x43 in ; do : +for x44 in ; do : +for x45 in ; do : +for x46 in ; do : +for x47 in ; do : +for x48 in ; do : +for x49 in ; do : +for x50 in ; do : +for x51 in ; do : +for x52 in ; do : +for x53 in ; do : +for x54 in ; do : +for x55 in ; do : +for x56 in ; do : +for x57 in ; do : +for x58 in ; do : +for x59 in ; do : +for x60 in ; do : +for x61 in ; do : +for x62 in ; do : +for x63 in ; do : +for x64 in ; do : +for x65 in ; do : +for x66 in ; do : +for x67 in ; do : +for x68 in ; do : +for x69 in ; do : +for x70 in ; do : +for x71 in ; do : +for x72 in ; do : +for x73 in ; do : +for x74 in ; do : +for x75 in ; do : +for x76 in ; do : +for x77 in ; do : +for x78 in ; do : +for x79 in ; do : +for x80 in ; do : +for x81 in ; do : +for x82 in ; do : +for x83 in ; do : +for x84 in ; do : +for x85 in ; do : +for x86 in ; do : +for x87 in ; do : +for x88 in ; do : +for x89 in ; do : +for x90 in ; do : +for x91 in ; do : +for x92 in ; do : +for x93 in ; do : +for x94 in ; do : +for x95 in ; do : +for x96 in ; do : +for x97 in ; do : +for x98 in ; do : +for x99 in ; do : +for x100 in ; do : +for x101 in ; do : +for x102 in ; do : +for x103 in ; do : +for x104 in ; do : +for x105 in ; do : +for x106 in ; do : +for x107 in ; do : +for x108 in ; do : +for x109 in ; do : +for x110 in ; do : +for x111 in ; do : +for x112 in ; do : +for x113 in ; do : +for x114 in ; do : +for x115 in ; do : +for x116 in ; do : +for x117 in ; do : +for x118 in ; do : +for x119 in ; do : +for x120 in ; do : +for x121 in ; do : +for x122 in ; do : +for x123 in ; do : +for x124 in ; do : +for x125 in ; do : +for x126 in ; do : +for x127 in ; do : +for x128 in ; do : +for x129 in ; do : +for x130 in ; do : +for x131 in ; do : +for x132 in ; do : +for x133 in ; do : +for x134 in ; do : +for x135 in ; do : +for x136 in ; do : +for x137 in ; do : +for x138 in ; do : +for x139 in ; do : +for x140 in ; do : +for x141 in ; do : +for x142 in ; do : +for x143 in ; do : +for x144 in ; do : +for x145 in ; do : +for x146 in ; do : +for x147 in ; do : +for x148 in ; do : +for x149 in ; do : +for x150 in ; do : +for x151 in ; do : +for x152 in ; do : +for x153 in ; do : +for x154 in ; do : +for x155 in ; do : +for x156 in ; do : +for x157 in ; do : +for x158 in ; do : +for x159 in ; do : +for x160 in ; do : +for x161 in ; do : +for x162 in ; do : +for x163 in ; do : +for x164 in ; do : +for x165 in ; do : +for x166 in ; do : +for x167 in ; do : +for x168 in ; do : +for x169 in ; do : +for x170 in ; do : +for x171 in ; do : +for x172 in ; do : +for x173 in ; do : +for x174 in ; do : +for x175 in ; do : +for x176 in ; do : +for x177 in ; do : +for x178 in ; do : +for x179 in ; do : +for x180 in ; do : +for x181 in ; do : +for x182 in ; do : +for x183 in ; do : +for x184 in ; do : +for x185 in ; do : +for x186 in ; do : +for x187 in ; do : +for x188 in ; do : +for x189 in ; do : +for x190 in ; do : +for x191 in ; do : +for x192 in ; do : +for x193 in ; do : +for x194 in ; do : +for x195 in ; do : +for x196 in ; do : +for x197 in ; do : +for x198 in ; do : +for x199 in ; do : +for x200 in ; do : +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done diff --git a/tests/exportfunc3.sub b/tests/exportfunc3.sub new file mode 100644 index 0000000..7a7aa26 --- /dev/null +++ b/tests/exportfunc3.sub @@ -0,0 +1,25 @@ +# test function names that cannot be exported + +unset foo # remove from environment if necessary + +function foo=bar +{ + echo equals-1 +} + +export -f 'foo=bar' +echo status: $? + +foo\=bar +printenv | grep 'foo=bar' +${THIS_SH} -c 'foo\=bar 2>/dev/null' + +function /bin/echo +{ + echo bad echo +} + +/bin/echo foo +export -f '/bin/echo' + +${THIS_SH} -c '/bin/echo bar' diff --git a/tests/extglob.right b/tests/extglob.right new file mode 100644 index 0000000..691f687 --- /dev/null +++ b/tests/extglob.right @@ -0,0 +1,116 @@ +ok 1 +ok 2 +ok 3 +ok 4 +ok 5 +ok 6 +ok 7 +ok 8 +ok 9 +ok 10 +ok 11 +ok 12 +ok 13 +ok 14 +ok 15 +ok 16 +ok 17 +ok 18 +ok 19 +ok 20 +ok 21 +ok 22 +ok 23 +ok 24 +ok 25 +ok 26 +ok 27 +ok 28 +ok 29 +ok 30 +ok 31 +ok 32 +ok 33 +ok 34 +ok 35 +ok 36 +!([*)* ++(a|b[)* +[a*(]*)z ++()c ++()x +abc ++(*)x +abc +no-file+(a|b)stuff +no-file+(a*(c)|b)stuff +abd acd +acd +abd +no +yes +yes +1: bcdef +2: def +3: abcde +4: abc +5: ef +6: ef +7: abcdef +ab abef +abcfef abef +abcdef +ab abcdef abcfef abef +abcdef abcfef abef +ok 37 +ok 38 +ok 39 +ok 40 +ok 41 +ok 42 +a b a,b a-b a.b a:b a;b a_b +a b a,b a-b a.b a:b a;b a_b +a b a,b a-b a.b a:b a;b a_b +a b a,b a-b a.b a:b a;b a_b +a.b +a b a,b a-b a:b a;b a_b +a b a,b a-b a.b a:b a;b a_b +a b a,b a-b a.b a:b a;b a_b +a b a,b a-b a.b a:b a;b a_b +argv[1] = <ef> +a,b +a.c +a.c +a.c +a.c +a.c +a.c +ok 1 +ok 2 +ok 3 +a ab +a ab +a ab +a +. .. +. .. a.log +*(foo) +*(foo|bar) +a.log +?(foo) +a.log +a.log +. .. +. .. +a.log +a.log +.x .y .z +a b c +.x .y .z a b c +a b c +a b c +a b c +a b c +.x .y .z a b c +.x .y .z a b c +* diff --git a/tests/extglob.tests b/tests/extglob.tests new file mode 100644 index 0000000..32a6569 --- /dev/null +++ b/tests/extglob.tests @@ -0,0 +1,379 @@ +# test the ksh-like extended globbing features: [!@*?+](patlist) + +shopt -s extglob + +expect() +{ + echo expect "$@" +} + +case "/dev/udp/129.22.8.102/45" in +/dev/@(tcp|udp)/*/*) echo ok 1;; +*) echo bad 1;; +esac + +# valid numbers +case 12 in +0|[1-9]*([0-9])) echo ok 2;; +*) echo bad 2;; +esac + +case 12abc in +0|[1-9]*([0-9])) echo bad 3;; +*) echo ok 3;; +esac + +case 1 in +0|[1-9]*([0-9])) echo ok 4;; +*) echo bad 4;; +esac + +# octal numbers +case 07 in ++([0-7])) echo ok 5;; +*) echo bad 5;; +esac + +case 0377 in ++([0-7])) echo ok 6;; +*) echo bad 6;; +esac + +case 09 in ++([0-7])) echo bad 7;; +*) echo ok 7;; +esac + +# stuff from korn's book +case paragraph in +para@(chute|graph)) echo ok 8;; +*) echo bad 8;; +esac + +case paramour in +para@(chute|graph)) echo bad 9;; +*) echo ok 9;; +esac + +case para991 in +para?([345]|99)1) echo ok 10;; +*) echo bad 10;; +esac + +case para381 in +para?([345]|99)1) echo bad 11;; +*) echo ok 11;; +esac + +case paragraph in +para*([0-9])) echo bad 12;; +*) echo ok 12;; +esac + +case para in +para*([0-9])) echo ok 13;; +*) echo bad 13;; +esac + +case para13829383746592 in +para*([0-9])) echo ok 14;; +*) echo bad 14;; +esac + +case paragraph in +para*([0-9])) echo bad 15;; +*) echo ok 15;; +esac + +case para in +para+([0-9])) echo bad 16;; +*) echo ok 16;; +esac + +case para987346523 in +para+([0-9])) echo ok 17;; +*) echo bad 17;; +esac + +case paragraph in +para!(*.[0-9])) echo ok 18;; +*) echo bad 18;; +esac + +case para.38 in +para!(*.[0-9])) echo ok 19;; +*) echo bad 19;; +esac + +case para.graph in +para!(*.[0-9])) echo ok 20;; +*) echo bad 20;; +esac + +case para39 in +para!(*.[0-9])) echo ok 21;; +*) echo bad 21;; +esac + +# tests derived from those in rosenblatt's korn shell book + +case "" in +*(0|1|3|5|7|9)) echo ok 22;; +*) echo bad 22; +esac + +case 137577991 in +*(0|1|3|5|7|9)) echo ok 23;; +*) echo bad 23; +esac + +case 2468 in +*(0|1|3|5|7|9)) echo bad 24;; +*) echo ok 24; +esac + +case file.c in +*.c?(c)) echo ok 25;; +*) echo bad 25;; +esac + +case file.C in +*.c?(c)) echo bad 26;; +*) echo ok 26;; +esac + +case file.cc in +*.c?(c)) echo ok 27;; +*) echo bad 27;; +esac + +case file.ccc in +*.c?(c)) echo bad 28;; +*) echo ok 28;; +esac + +case parse.y in +!(*.c|*.h|Makefile.in|config*|README)) echo ok 29;; +*) echo bad 29;; +esac + +case shell.c in +!(*.c|*.h|Makefile.in|config*|README)) echo bad 30;; +*) echo ok 30;; +esac + +case Makefile in +!(*.c|*.h|Makefile.in|config*|README)) echo ok 31;; +*) echo bad 31;; +esac + +case "VMS.FILE;1" in +*\;[1-9]*([0-9])) echo ok 32;; +*) echo bad 32;; +esac + +case "VMS.FILE;0" in +*\;[1-9]*([0-9])) echo bad 33;; +*) echo ok 33;; +esac +case "VMS.FILE;" in +*\;[1-9]*([0-9])) echo bad 34;; +*) echo ok 34;; +esac +case "VMS.FILE;139" in +*\;[1-9]*([0-9])) echo ok 35;; +*) echo bad 35;; +esac +case "VMS.FILE;1N" in +*\;[1-9]*([0-9])) echo bad 36;; +*) echo ok 36;; +esac + +# tests derived from the pd-ksh test suite + +MYDIR=$PWD # save where we are + +: ${TMPDIR:=/var/tmp} +TESTDIR=$TMPDIR/eglob-test-$$ +mkdir $TESTDIR +builtin cd $TESTDIR || { echo $0: cannot cd to $TESTDIR >&2 ; exit 1; } +rm -rf * + +touch abcx abcz bbc +expect '!([*)*' +echo !([*)* + +expect '+(a|b[)*' +echo +(a|b[)* + +expect '[a*(]*z' +echo [a*(]*)z + +rm -f abcx abcz bbc + +touch abc + +expect '+()c' +echo +()c +expect '+()x' +echo +()x +expect abc +echo +(*)c +expect '+(*)x' +echo +(*)x + +# extended globbing should not be performed on the output of substitutions +x='@(*)' +expect '@(*)' +echo $x + +expect 'no-file+(a|b)stuff' +echo no-file+(a|b)stuff +expect 'no-file+(a*(c)|b)stuff' +echo no-file+(a*(c)|b)stuff + +touch abd acd + +expect 'abd acd' +echo a+(b|c)d + +expect 'acd' +echo a!(@(b|B))d + +expect 'abd' +echo a[b*(foo|bar)]d + +# simple kleene star tests +expect no +case foo in *(a|b[)) echo yes;; *) echo no;; esac + +expect yes +case foo in *(a|b[)|f*) echo yes;; *) echo no;; esac + +# this doesn't work right yet; it is an incorrectly formed pattern +expect yes +case '*(a|b[)' in *(a|b[)) echo yes;; *) echo no;; esac + +# check extended globbing in pattern removal -- these don't work right yet +x=abcdef + +expect '1: bcdef' +echo 1: ${x#+(a|abc)} +expect '2: def' +echo 2: ${x##+(a|abc)} +expect '3: abcde' +echo 3: ${x%+(def|f)} +expect '4: abc' +echo 4: ${x%%+(f|def)} + +# these work ok + +expect '5: ef' +echo 5: ${x#*(a|b)cd} +expect '6: ef' +echo 6: "${x#*(a|b)cd}" +expect '7: abcdef' +echo 7: ${x#"*(a|b)cd"} + +# More tests derived from a bug report concerning extended glob patterns +# following a * +builtin cd $TESTDIR || { echo $0: cannot cd to $TESTDIR >&2 ; exit 1; } +rm -rf * + +touch ab abcdef abef abcfef + +expect 'ab abef' +echo ab*(e|f) + +expect 'abcfef abef' +echo ab?*(e|f) + +expect abcdef +echo ab*d+(e|f) + +expect 'ab abcdef abcfef abef' +echo ab**(e|f) + +expect 'abcdef abcfef abef' +echo ab*+(e|f) + +case 'abcfefg' in +ab**(e|f)) echo ok 37;; +*) echo bad 37;; +esac + +case 'abcfefg' in +ab**(e|f)g) echo ok 38;; +*a) echo bad 38;; +esac + +case ab in +ab*+(e|f)) echo bad 39;; +*) echo ok 39;; +esac + +case abef in +ab***ef) echo ok 40;; +*) echo bad 40;; +esac + +case abef in +ab**) echo ok 41;; +*) echo bad 41;; +esac + +# bug in all versions up to and including bash-2.05b +case "123abc" in +*?(a)bc) echo ok 42;; +*) echo bad 42;; +esac + +# clean up and do the next one + +builtin cd / +rm -rf $TESTDIR + +mkdir $TESTDIR +builtin cd $TESTDIR + +LC_COLLATE=C # have to set this; it affects the sorting +touch a.b a,b a:b a-b a\;b a\ b a_b + +echo a[^[:alnum:]]b +echo a[-.,:\;\ _]b + +echo a@([^[:alnum:]])b +echo a@([-.,:; _])b +echo a@([.])b +echo a@([^.])b +echo a@([^x])b +echo a+([^[:alnum:]])b + +echo a@(.|[^[:alnum:]])b + +builtin cd / +rm -rf $TESTDIR + +x=abcdef +recho "${x#*(a|b)cd}" + +TEST='a , b' +shopt -s globstar +echo ${TEST//*([[:space:]]),*([[:space:]])/,} +shopt -u globstar + +# this is for the benefit of pure coverage, so it writes the pcv file +# in the right place +builtin cd "$MYDIR" + +${THIS_SH} ./extglob1.sub + +${THIS_SH} ./extglob1a.sub + +${THIS_SH} ./extglob3.sub + +${THIS_SH} ./extglob4.sub + +${THIS_SH} ./extglob5.sub + +exit 0 diff --git a/tests/extglob1.sub b/tests/extglob1.sub new file mode 100644 index 0000000..bf65a9e --- /dev/null +++ b/tests/extglob1.sub @@ -0,0 +1,37 @@ +MYDIR=$PWD + +: ${TMPDIR:=/tmp} +GDIR=$TMPDIR/gtest-$$ + +shopt -s extglob + +mkdir $GDIR || exit 1 +cd $GDIR || exit 1 + +touch a.c + +echo +([[:alpha:].]) +echo +([[:alpha:].])+([[:alpha:].]) +echo *([[:alpha:].]) +echo *([[:alpha:].])*([[:alpha:].]) + +echo ?([[:alpha:].])?([[:alpha:].])?([[:alpha:].]) +echo @([[:alpha:].])@([[:alpha:].])@([[:alpha:].]) + +case . in +!([[:alpha:].]) ) echo bad 1;; +*) echo ok 1;; +esac + +case . in +?([[:alpha:].]) ) echo ok 2;; +*) echo bad 2;; +esac + +case . in +@([[:alpha:].]) ) echo ok 3;; +*) echo bad 3;; +esac + +cd "$MYDIR" +rm -rf $GDIR diff --git a/tests/extglob1a.sub b/tests/extglob1a.sub new file mode 100644 index 0000000..686dab7 --- /dev/null +++ b/tests/extglob1a.sub @@ -0,0 +1,16 @@ +shopt -s extglob + +TESTDIR=${TMPDIR:-/tmp}/eglob-test-$$ +mkdir $TESTDIR +builtin cd $TESTDIR || { echo $0: cannot cd to $TESTDIR >&2 ; exit 1; } +rm -rf * + +touch a ab ba + +echo a*!(x) +echo a!(x) +echo a*?(x) +echo a?(x) + +builtin cd $OLDPWD +rm -rf $TESTDIR diff --git a/tests/extglob2.right b/tests/extglob2.right new file mode 100644 index 0000000..f8a09df --- /dev/null +++ b/tests/extglob2.right @@ -0,0 +1,70 @@ +0: [[ fofo = *(f*(o)) ]] +0: [[ ffo = *(f*(o)) ]] +0: [[ foooofo = *(f*(o)) ]] +0: [[ foooofof = *(f*(o)) ]] +0: [[ fooofoofofooo = *(f*(o)) ]] +1: [[ foooofof = *(f+(o)) ]] +1: [[ xfoooofof = *(f*(o)) ]] +1: [[ foooofofx = *(f*(o)) ]] +0: [[ ofxoofxo = *(*(of*(o)x)o) ]] +1: [[ ofooofoofofooo = *(f*(o)) ]] +0: [[ foooxfooxfoxfooox = *(f*(o)x) ]] +1: [[ foooxfooxofoxfooox = *(f*(o)x) ]] +0: [[ foooxfooxfxfooox = *(f*(o)x) ]] +0: [[ ofxoofxo = *(*(of*(o)x)o) ]] +0: [[ ofoooxoofxo = *(*(of*(o)x)o) ]] +0: [[ ofoooxoofxoofoooxoofxo = *(*(of*(o)x)o) ]] +0: [[ ofoooxoofxoofoooxoofxoo = *(*(of*(o)x)o) ]] +1: [[ ofoooxoofxoofoooxoofxofo = *(*(of*(o)x)o) ]] +0: [[ ofoooxoofxoofoooxoofxooofxofxo = *(*(of*(o)x)o) ]] +0: [[ aac = *(@(a))a@(c) ]] +0: [[ ac = *(@(a))a@(c) ]] +1: [[ c = *(@(a))a@(c) ]] +0: [[ aaac = *(@(a))a@(c) ]] +1: [[ baaac = *(@(a))a@(c) ]] +0: [[ abcd = ?@(a|b)*@(c)d ]] +0: [[ abcd = @(ab|a*@(b))*(c)d ]] +0: [[ acd = @(ab|a*(b))*(c)d ]] +0: [[ abbcd = @(ab|a*(b))*(c)d ]] +0: [[ effgz = @(b+(c)d|e*(f)g?|?(h)i@(j|k)) ]] +0: [[ efgz = @(b+(c)d|e*(f)g?|?(h)i@(j|k)) ]] +0: [[ egz = @(b+(c)d|e*(f)g?|?(h)i@(j|k)) ]] +0: [[ egzefffgzbcdij = *(b+(c)d|e*(f)g?|?(h)i@(j|k)) ]] +1: [[ egz = @(b+(c)d|e+(f)g?|?(h)i@(j|k)) ]] +0: [[ ofoofo = *(of+(o)) ]] +0: [[ oxfoxoxfox = *(oxf+(ox)) ]] +1: [[ oxfoxfox = *(oxf+(ox)) ]] +0: [[ ofoofo = *(of+(o)|f) ]] +0: [[ foofoofo = @(foo|f|fo)*(f|of+(o)) ]] +0: [[ oofooofo = *(of|oof+(o)) ]] +0: [[ fffooofoooooffoofffooofff = *(*(f)*(o)) ]] +0: [[ fofoofoofofoo = *(fo|foo) ]] +0: [[ foo = !(x) ]] +0: [[ foo = !(x)* ]] +1: [[ foo = !(foo) ]] +0: [[ foo = !(foo)* ]] +0: [[ foobar = !(foo) ]] +0: [[ foobar = !(foo)* ]] +0: [[ moo.cow = !(*.*).!(*.*) ]] +1: [[ mad.moo.cow = !(*.*).!(*.*) ]] +1: [[ mucca.pazza = mu!(*(c))?.pa!(*(z))? ]] +0: [[ fff = !(f) ]] +0: [[ fff = *(!(f)) ]] +0: [[ fff = +(!(f)) ]] +0: [[ ooo = !(f) ]] +0: [[ ooo = *(!(f)) ]] +0: [[ ooo = +(!(f)) ]] +0: [[ foo = !(f) ]] +0: [[ foo = *(!(f)) ]] +0: [[ foo = +(!(f)) ]] +1: [[ f = !(f) ]] +1: [[ f = *(!(f)) ]] +1: [[ f = +(!(f)) ]] +0: [[ foot = @(!(z*)|*x) ]] +1: [[ zoot = @(!(z*)|*x) ]] +0: [[ foox = @(!(z*)|*x) ]] +0: [[ zoox = @(!(z*)|*x) ]] +0: [[ foo = *(!(foo)) ]] +1: [[ foob = !(foo)b* ]] +0: [[ foobb = !(foo)b* ]] +0 tests failed. diff --git a/tests/extglob2.sub b/tests/extglob2.sub new file mode 100644 index 0000000..f4a3b37 --- /dev/null +++ b/tests/extglob2.sub @@ -0,0 +1,7 @@ +LANG=en_US.UTF-8 + +shopt -s extglob +a="aaaäöü" + +echo "${a}" "${a//?aa}" "${a//\aaa}" +exit 0 diff --git a/tests/extglob2.tests b/tests/extglob2.tests new file mode 100755 index 0000000..f35c3e8 --- /dev/null +++ b/tests/extglob2.tests @@ -0,0 +1,90 @@ +# +# More ksh-like extended globbing tests, cribbed from zsh-3.1.5 +# +shopt -s extglob + +failed=0 +while read res str pat; do + [[ $res = '#' ]] && continue + [[ $str = ${pat} ]] + ts=$? + [[ $1 = -q ]] || echo "$ts: [[ $str = $pat ]]" + if [[ ( $ts -gt 0 && $res = t) || ($ts -eq 0 && $res = f) ]]; then + echo "Test failed: [[ $str = $pat ]]" + (( failed += 1 )) + fi +done <<EOT +t fofo *(f*(o)) +t ffo *(f*(o)) +t foooofo *(f*(o)) +t foooofof *(f*(o)) +t fooofoofofooo *(f*(o)) +f foooofof *(f+(o)) +f xfoooofof *(f*(o)) +f foooofofx *(f*(o)) +t ofxoofxo *(*(of*(o)x)o) +f ofooofoofofooo *(f*(o)) +t foooxfooxfoxfooox *(f*(o)x) +f foooxfooxofoxfooox *(f*(o)x) +t foooxfooxfxfooox *(f*(o)x) +t ofxoofxo *(*(of*(o)x)o) +t ofoooxoofxo *(*(of*(o)x)o) +t ofoooxoofxoofoooxoofxo *(*(of*(o)x)o) +t ofoooxoofxoofoooxoofxoo *(*(of*(o)x)o) +f ofoooxoofxoofoooxoofxofo *(*(of*(o)x)o) +t ofoooxoofxoofoooxoofxooofxofxo *(*(of*(o)x)o) +t aac *(@(a))a@(c) +t ac *(@(a))a@(c) +f c *(@(a))a@(c) +t aaac *(@(a))a@(c) +f baaac *(@(a))a@(c) +t abcd ?@(a|b)*@(c)d +t abcd @(ab|a*@(b))*(c)d +t acd @(ab|a*(b))*(c)d +t abbcd @(ab|a*(b))*(c)d +t effgz @(b+(c)d|e*(f)g?|?(h)i@(j|k)) +t efgz @(b+(c)d|e*(f)g?|?(h)i@(j|k)) +t egz @(b+(c)d|e*(f)g?|?(h)i@(j|k)) +t egzefffgzbcdij *(b+(c)d|e*(f)g?|?(h)i@(j|k)) +f egz @(b+(c)d|e+(f)g?|?(h)i@(j|k)) +t ofoofo *(of+(o)) +t oxfoxoxfox *(oxf+(ox)) +f oxfoxfox *(oxf+(ox)) +t ofoofo *(of+(o)|f) +# The following is supposed to match only as fo+ofo+ofo +t foofoofo @(foo|f|fo)*(f|of+(o)) +t oofooofo *(of|oof+(o)) +t fffooofoooooffoofffooofff *(*(f)*(o)) +# The following tests backtracking in alternation matches +t fofoofoofofoo *(fo|foo) +# Exclusion +t foo !(x) +t foo !(x)* +f foo !(foo) +t foo !(foo)* +t foobar !(foo) +t foobar !(foo)* +t moo.cow !(*.*).!(*.*) +f mad.moo.cow !(*.*).!(*.*) +f mucca.pazza mu!(*(c))?.pa!(*(z))? +t fff !(f) +t fff *(!(f)) +t fff +(!(f)) +t ooo !(f) +t ooo *(!(f)) +t ooo +(!(f)) +t foo !(f) +t foo *(!(f)) +t foo +(!(f)) +f f !(f) +f f *(!(f)) +f f +(!(f)) +t foot @(!(z*)|*x) +f zoot @(!(z*)|*x) +t foox @(!(z*)|*x) +t zoox @(!(z*)|*x) +t foo *(!(foo)) +f foob !(foo)b* +t foobb !(foo)b* +EOT +echo "$failed tests failed." diff --git a/tests/extglob3.right b/tests/extglob3.right new file mode 100644 index 0000000..db9447e --- /dev/null +++ b/tests/extglob3.right @@ -0,0 +1,27 @@ +match 1 +match 2 +match 3 +match 4 +match 1a +match 1b +match 2a +match 2b +match 3a +match 3b +match 4a +match 4b +match 5 +match 6 +match 7 +match 8 +match 9 +match 10 +match 11 +match 12 +match 13 +match 14 +match 15 +match 16 +match 17 +match 18 +ok 19 diff --git a/tests/extglob3.sub b/tests/extglob3.sub new file mode 100644 index 0000000..3f51c40 --- /dev/null +++ b/tests/extglob3.sub @@ -0,0 +1,24 @@ +shopt -s extglob +DIR=$TMPDIR/extglob-$$ +mkdir $DIR +cd $DIR + +touch a.log + +echo *(.) +echo *(.)* +echo *(foo) +echo *(foo|bar) +echo ?(foo)* +echo ?(foo) +echo *(foo)* +echo @(|foo)* + +echo *(foo).* +echo *(foo|bar).* + +echo !(foo)* +echo !(foo|bar)* + +cd $OLDPWD +rm -rf $DIR diff --git a/tests/extglob3.tests b/tests/extglob3.tests new file mode 100644 index 0000000..60454a2 --- /dev/null +++ b/tests/extglob3.tests @@ -0,0 +1,56 @@ +shopt -s extglob + +[[ ab/../ == @(ab|+([^/]))/..?(/) ]] && echo match 1 + +[[ ab/../ == +([^/])/..?(/) ]] && echo match 2 + +[[ ab/../ == @(ab|?b)/..?(/) ]] && echo match 3 + +[[ ab/../ == +([^/])/../ ]] && echo match 4 + +[[ ab/../ == +([!/])/..?(/) ]] && echo match 1a + +[[ ab/../ == @(ab|+([!/]))/..?(/) ]] && echo match 1b + +[[ ab/../ == +([!/])/../ ]] && echo match 2a + +[[ ab/../ == +([!/])/..?(/) ]] && echo match 2b + +[[ ab/../ == +([!/])/..@(/) ]] && echo match 3a + +[[ ab/../ == +(ab)/..?(/) ]] && echo match 3b + +[[ ab/../ == [!/][!/]/../ ]] && echo match 4a + +[[ ab/../ == @(ab|?b)/..?(/) ]] && echo match 4b + +[[ ab/../ == [^/][^/]/../ ]] && echo match 5 + +[[ ab/../ == ?b/..?(/) ]] && echo match 6 + +[[ ab/../ == +(?b)/..?(/) ]] && echo match 7 + +[[ ab/../ == +(?b|?b)/..?(/) ]] && echo match 8 + +[[ ab/../ == @(?b|?b)/..?(/) ]] && echo match 9 + +[[ ab/../ == @(a?|?b)/..?(/) ]] && echo match 10 + +[[ ab/../ == ?(ab)/..?(/) ]] && echo match 11 + +[[ ab/../ == ?(ab|??)/..?(/) ]] && echo match 12 + +[[ ab/../ == @(??)/..?(/) ]] && echo match 13 + +[[ ab/../ == @(??|a*)/..?(/) ]] && echo match 14 + +[[ ab/../ == @(a*)/..?(/) ]] && echo match 15 + +[[ ab/../ == +(??)/..?(/) ]] && echo match 16 + +[[ ab/../ == +(??|a*)/..?(/) ]] && echo match 17 + +[[ ab/../ == +(a*)/..?(/) ]] && echo match 18 + +# +j="@(x)" ; [[ x == $j ]] && echo ok 19 diff --git a/tests/extglob4.sub b/tests/extglob4.sub new file mode 100644 index 0000000..2b4c53c --- /dev/null +++ b/tests/extglob4.sub @@ -0,0 +1,32 @@ +LANG=C +LC_ALL=C + +: ${TMPDIR:=/tmp} +GTDIR=$TMPDIR/extglob4-$$ + +shopt -s extglob +[ -d "${GTDIR}" ] || mkdir "${GTDIR}" +cd "${GTDIR}" || { + echo "extglob4: cannot cd to ${GTDIR}" + exit 2 +} + +touch a b c .x .y .z +echo .!(|.) # correct +echo * # correct + +echo @(*|.!(|.)) # wrong, adds . and .. +echo @(*|@(f)) # ?? +echo @(*|@(ff)) + +echo !(f) +echo !(f)!(f) + +shopt -s dotglob +echo @(*|@(f)) +echo @(*|@(ff)) + +cd $OLDPWD +rm -rf $GTDIR + +[[ a = a*?(/)b ]] && echo bad match 1 diff --git a/tests/extglob5.sub b/tests/extglob5.sub new file mode 100644 index 0000000..d400f83 --- /dev/null +++ b/tests/extglob5.sub @@ -0,0 +1,18 @@ +# globignore extglob patterns containing colons -- problem until bash-4.2 + +: ${TMPDIR:=/tmp} +TESTDIR=$TMPDIR/bash-globignore-$$ +[ -d "$TESTDIR" ] || mkdir "$TESTDIR" + +cd "$TESTDIR" || exit 2 + +shopt -s extglob +GLOBIGNORE='+([^[:alnum:]]):@([-.,:; _]):[![:alnum:]]' + +touch ';' '++' +echo * + +rm ';' '++' + +cd $OLDPWD +rmdir $TESTDIR diff --git a/tests/func.right b/tests/func.right new file mode 100644 index 0000000..70bf123 --- /dev/null +++ b/tests/func.right @@ -0,0 +1,169 @@ +a returns 5 +b returns 4 +c returns 3 +d returns 2 +in e +e returned 25 +x is 25 +ZZ +abcde +defghi +ZZ +5 +0 +AVAR +AVAR +foo +foo +AVAR +5 +5 +f1 +f1 () +{ + ( return 5 ); + status=$?; + echo $status; + return $status +} +before: try to assign to FUNCNAME +outside: FUNCNAME = +before: FUNCNAME = func +FUNCNAME = func2 +after: FUNCNAME = func +outside2: FUNCNAME = +function +zf is a function +zf () +{ + echo this is zf +} +f is a function +f () +{ + echo f-x; + echo f-y +} 1>&2 +subshell +f is a function +f () +{ + echo f-x; + echo f-y +} 1>&2 +f2 is a function +f2 () +{ + echo f2-a; + function f3 () + { + echo f3-a; + echo f3-b + } 1>&2; + f3 +} +subshell +f2 is a function +f2 () +{ + echo f2-a; + function f3 () + { + echo f3-a; + echo f3-b + } 1>&2; + f3 +} +f4 is a function +f4 () +{ + echo f4-a; + function f5 () + { + echo f5-a; + echo f5-b + } 1>&2; + f5 +} 2>&1 +subshell +f4 is a function +f4 () +{ + echo f4-a; + function f5 () + { + echo f5-a; + echo f5-b + } 1>&2; + f5 +} 2>&1 +testgrp is a function +testgrp () +{ + echo testgrp-a; + { + echo tg-x; + echo tg-y + } 1>&2; + echo testgrp-b +} +subshell +testgrp is a function +testgrp () +{ + echo testgrp-a; + { + echo tg-x; + echo tg-y + } 1>&2; + echo testgrp-b +} +funca is a function +funca () +{ + ( echo func-a ) +} +funcb is a function +funcb () +{ + ( echo func-b ) +} +funcc is a function +funcc () +{ + ( echo func-c ) 2>&1 +} +func-a +func-b +func-c +foo-bar +foo-bar () +{ + : +} +expect 5 10 +5 10 +expect 20 +20 +expect 5 20 +5 20 +expect 5 30 +5 30 +expect 2 40 +2 40 +expect 5 20 +5 20 +./func4.sub: line 10: foo: maximum function nesting level exceeded (100) +1 +after: f = 100 +./func4.sub: line 10: foo: maximum function nesting level exceeded (100) +1 +after: f = 100 +7 +after FUNCNEST reset: f = 201 +7 +after FUNCNEST unset: f = 201 +./func4.sub: line 10: foo: maximum function nesting level exceeded (20) +1 +after FUNCNEST assign: f = 38 +5 diff --git a/tests/func.tests b/tests/func.tests new file mode 100644 index 0000000..8701c2a --- /dev/null +++ b/tests/func.tests @@ -0,0 +1,179 @@ +a() +{ + x=$((x - 1)) + return 5 +} + +b() +{ + x=$((x - 1)) + a + echo a returns $? + return 4 +} + +c() +{ + x=$((x - 1)) + b + echo b returns $? + return 3 +} + +d() +{ + x=$((x - 1)) + c + echo c returns $? + return 2 +} + +e() +{ + d + echo d returns $? + echo in e + x=$((x - 1)) + return $x +} + +f() +{ + e + echo e returned $? + echo x is $x + return 0 +} + +x=30 +f + +# make sure unsetting a local variable preserves the `local' attribute +f1() +{ + local zz + zz=abcde + echo $zz + unset zz + zz=defghi + echo $zz +} + +zz=ZZ +echo $zz +f1 +echo $zz + +unset -f f1 +f1() +{ + return 5 +} + +( f1 ) +echo $? + +unset -f f1 +f1() +{ + sleep 5 + return 5 +} + +f1 & +wait +echo $? + +unset -f f1 + +f1() +{ + echo $AVAR + printenv AVAR +} + +AVAR=AVAR +echo $AVAR +f1 +AVAR=foo f1 +echo $AVAR + +unset -f f1 +# make sure subshells can do a `return' if we're executing in a function +f1() +{ + ( return 5 ) + status=$? + echo $status + return $status +} + +f1 +echo $? + +declare -F f1 # should print just the name +declare -f f1 # should print the definition, too + +# no functions should be exported, right? +declare -xF +declare -xf + +# FUNCNAME tests +func2() +{ + echo FUNCNAME = $FUNCNAME +} + +func() +{ + echo before: FUNCNAME = $FUNCNAME + func2 + echo after: FUNCNAME = $FUNCNAME +} + +echo before: try to assign to FUNCNAME +FUNCNAME=7 + +echo outside: FUNCNAME = $FUNCNAME +func +echo outside2: FUNCNAME = $FUNCNAME + +# test exported functions (and cached exportstr) +zf() +{ + echo this is zf +} +export -f zf + +${THIS_SH} -c 'type -t zf' +${THIS_SH} -c 'type zf' + +${THIS_SH} ./func1.sub + +# tests for functions whose bodies are not group commands, with and without +# attached redirections +${THIS_SH} ./func2.sub + +# test for some posix-specific function behavior +${THIS_SH} ./func3.sub + +# FUNCNEST testing +${THIS_SH} ./func4.sub + +unset -f myfunction +myfunction() { + echo "bad shell function redirection" +} >> /dev/null + +myfunction +myfunction | cat + +segv() +{ + echo foo | return 5 +} + +segv +echo $? + +exit 0 diff --git a/tests/func1.sub b/tests/func1.sub new file mode 100644 index 0000000..345645f --- /dev/null +++ b/tests/func1.sub @@ -0,0 +1,55 @@ +# +# Test that redirections attached to shell functions are printed correctly. +# This was a bug in all bash versions before bash-2.04. +# +f() +{ + echo f-x + echo f-y +} >&2 + +type f +export -f f +${THIS_SH} -c 'echo subshell; type f' + +f2() +{ + echo f2-a + f3() + { + echo f3-a + echo f3-b + } >&2 + f3 +} + +type f2 + +export -f f2 +${THIS_SH} -c 'echo subshell; type f2' + +f4() +{ + echo f4-a + f5() + { + echo f5-a + echo f5-b + } >&2 + f5 +} 2>&1 + +type f4 +export -f f4 +${THIS_SH} -c 'echo subshell; type f4' + +testgrp() +{ + echo testgrp-a + { echo tg-x; echo tg-y; } >&2 + echo testgrp-b +} +type testgrp + +export -f testgrp +${THIS_SH} -c 'echo subshell; type testgrp' diff --git a/tests/func2.sub b/tests/func2.sub new file mode 100644 index 0000000..41a3844 --- /dev/null +++ b/tests/func2.sub @@ -0,0 +1,27 @@ +funca() ( + echo func-a +) + +funcb() ( echo func-b ) + +funcc() ( + echo func-c +) 2>&1 + +type funca +type funcb +type funcc + +funca +funcb +funcc + +# when not in posix mode, bash allows non-identifiers as function names +set +o posix +foo-bar() +{ + :; +} + +declare -F foo-bar +declare -f foo-bar diff --git a/tests/func3.sub b/tests/func3.sub new file mode 100644 index 0000000..9d3d069 --- /dev/null +++ b/tests/func3.sub @@ -0,0 +1,54 @@ +# +# test some posix-mode-specific function behavior +# +set -o posix +func() +{ + return 5 +} + +myfunction () { + var=20 return +} +var=10 +echo expect 5 10 +func +echo $? $var + +myfunction +echo expect 20 +echo $var + +echo expect 5 20 +func +echo $? $var + +echo expect 5 30 +var=30 func +echo $? $var + +: ${TMPDIR:=/tmp} +TMPFILE=$TMPDIR/func3.sub.$$ + +rm -f $TMPFILE +echo 'var=40 return 2' > $TMPFILE + +# test the behavior of `return' and preceding variable assignments here +# because it's convenient +var=10 +echo expect 2 40 +. $TMPFILE +echo $? $var + +rm -f $TMPFILE + +#set -o posix +var=0 +func() +{ + var=20 return 5 +} + +echo expect 5 20 +var=30 func +echo $? $var diff --git a/tests/func4.sub b/tests/func4.sub new file mode 100644 index 0000000..9c9c1b4 --- /dev/null +++ b/tests/func4.sub @@ -0,0 +1,39 @@ +# test FUNCNEST functionality -- bash-4.2 +FUNCNEST=100 + +foo() +{ + (( f++ )) + if (( f > 200 )); then + return 7 + fi + foo +} + +f=0 +foo +echo $? +echo after: f = $f + +f=0 +foo +echo $? +echo after: f = $f + +f=0 +FUNCNEST=0 +foo +echo $? +echo after FUNCNEST reset: f = $f + +f=0 +unset FUNCNEST +foo +echo $? +echo after FUNCNEST unset: f = $f + +FUNCNEST=20 +f=$(( FUNCNEST - 2 )) +foo +echo $? +echo after FUNCNEST assign: f = $f diff --git a/tests/getopts.right b/tests/getopts.right new file mode 100644 index 0000000..fff9729 --- /dev/null +++ b/tests/getopts.right @@ -0,0 +1,68 @@ +getopts: usage: getopts optstring name [arg] +2 +getopts: usage: getopts optstring name [arg] +2 +./getopts.tests: line 10: getopts: -a: invalid option +getopts: usage: getopts optstring name [arg] +-a specified +-b bval specified +remaining args: one two three +-a specified +-b bval specified +remaining args: one two three four five six seven eight nine ten eleven twelve +./getopts1.sub: option requires an argument -- b +Usage: ./getopts1.sub [-a] [-b value] args +-a specified +-c cval specified +-d specified +-a specified +-b 3 specified +remaining args: one two three four five +-a specified +-b bval specified +remaining args: one two three +-a specified +-b bval specified +remaining args: one two three +./getopts4.sub: error: option `b' requires an argument +Usage: ./getopts4.sub [-a] [-b value] args +./getopts4.sub: error: illegal option character `c' +Usage: ./getopts4.sub [-a] [-b value] args +-a specified +remaining args: -b bval one two three +OPTERR=0 +a here +something else here +OPTIND=3 +getop: OPTERR=1 +a here +./getopts5.sub: illegal option -- c +something else here +./getopts5.sub: illegal option -- d +something else here +./getopts5.sub: illegal option -- e +something else here +getop: OPTIND=5 +OPTIND=3 +OPTERR=0 +-a specified +remaining args: +-a specified +remaining args: +-a specified +remaining args: +0 +./getopts7.sub: line 4: getopts: `opt-var': not a valid identifier +remaining args: +opt: x +opt: y +opt: a +opt: b +opt: c +opt: z +$1 = a +./getopts10.sub: line 3: OPTARG: readonly variable +OPTARG = x = ? +unset x = ? +declare -r RO="foo" +declare -r RO="foo" diff --git a/tests/getopts.tests b/tests/getopts.tests new file mode 100644 index 0000000..d54190c --- /dev/null +++ b/tests/getopts.tests @@ -0,0 +1,43 @@ +# getopts tests +# this should fail +getopts +echo $? +getopts opts +echo $? + +# maybe someday we will have a ksh93-like -a argument to set the name +# used in error messages, but not yet +getopts -a opts name + +${THIS_SH} ./getopts1.sub -a -b bval one two three +# make sure getopts works when there are more than 9 positional parameters +${THIS_SH} ./getopts1.sub -a -b bval one two three four five six seven eight nine ten eleven twelve +${THIS_SH} ./getopts1.sub -a -b + +${THIS_SH} ./getopts2.sub -ad -c cval three four five + +${THIS_SH} ./getopts3.sub + +# make sure that `-b bval' and `-bbval' are equivalent +${THIS_SH} ./getopts4.sub -a -b bval one two three +${THIS_SH} ./getopts4.sub -a -bbval one two three +# this tests `silent' error reporting +${THIS_SH} ./getopts4.sub -a -b +${THIS_SH} ./getopts4.sub -a -c + +# make sure that `--' can be used to end the list of options +${THIS_SH} ./getopts4.sub -a -- -b bval one two three + +${THIS_SH} ./getopts5.sub -a -c + +${THIS_SH} ./getopts6.sub -a +${THIS_SH} ./getopts6.sub -a -c +${THIS_SH} ./getopts6.sub -ac +echo $? # this should be 2 + +${THIS_SH} ./getopts7.sub -a + +${THIS_SH} ./getopts8.sub +${THIS_SH} ./getopts9.sub + +${THIS_SH} ./getopts10.sub diff --git a/tests/getopts1.sub b/tests/getopts1.sub new file mode 100644 index 0000000..df0a342 --- /dev/null +++ b/tests/getopts1.sub @@ -0,0 +1,26 @@ +aflag= +bflag= + +while getopts ab: name +do + case $name in + a) aflag=1 ;; + b) bflag=1 + bval=$OPTARG;; + ?) echo Usage: $0 [-a] [-b value] args + exit 2;; + esac + +done + +if [ ! -z "$aflag" ] ; then echo -a specified ; fi +if [ ! -z "$bflag" ] ; then echo -b $bval specified ; fi + +if [ "$OPTIND" -gt 1 ] +then + shift $(( $OPTIND - 1 )) +fi + +echo remaining args: "$*" + +exit 0 diff --git a/tests/getopts10.sub b/tests/getopts10.sub new file mode 100644 index 0000000..84bacf8 --- /dev/null +++ b/tests/getopts10.sub @@ -0,0 +1,17 @@ +set -- -a bb +readonly OPTARG +getopts :x x + +echo OPTARG = $OPTARG x = $x + +getopts x x +echo ${OPTARG-unset} x = $x + +typeset -r RO=foo +typeset -n OPTARG=RO + +getopts :x x +typeset -p RO + +getopts x x +typeset -p RO diff --git a/tests/getopts2.sub b/tests/getopts2.sub new file mode 100644 index 0000000..d91fd26 --- /dev/null +++ b/tests/getopts2.sub @@ -0,0 +1,26 @@ +aflag= +bflag= + +while getopts ab:c:de name "$@" +do + case $name in + a) aflag=1 ;; + b) bflag=1 + bval=$OPTARG;; + c) cflag=1 + cval=$OPTARG ;; + d) dflag=1 ;; + e) eflag=1;; + ?) echo Usage: $0 [-a] [-b value] [-c value] -[de] args + exit 2;; + esac + +done + +[ ! -z "$aflag" ] && echo -a specified +[ ! -z "$bflag" ] && echo -b $bval specified +[ ! -z "$cflag" ] && echo -c $cval specified +[ ! -z "$dflag" ] && echo -d specified +[ ! -z "$eflag" ] && { echo -n - ; echo e specified; } + +exit 0 diff --git a/tests/getopts3.sub b/tests/getopts3.sub new file mode 100644 index 0000000..2d8b316 --- /dev/null +++ b/tests/getopts3.sub @@ -0,0 +1,27 @@ +aflag= +bflag= + +while getopts ab: name -a -b 1 -a -a -a -b 5 -b 3 -a one two three four five +do + case $name in + a) aflag=1 ;; + b) bflag=1 + bval=$OPTARG;; + ?) echo Usage: $0 [-a] [-b value] args + exit 2;; + esac + +done + +if [ ! -z "$aflag" ] ; then echo -a specified ; fi +if [ ! -z "$bflag" ] ; then echo -b $bval specified ; fi + +set -- -a -b 1 -a -a -a -b 5 -b 3 -a one two three four five +if [ "$OPTIND" -gt 1 ] +then + shift $(( $OPTIND - 1 )) +fi + +echo remaining args: "$*" + +exit 0 diff --git a/tests/getopts4.sub b/tests/getopts4.sub new file mode 100644 index 0000000..9cd5aef --- /dev/null +++ b/tests/getopts4.sub @@ -0,0 +1,30 @@ +aflag= +bflag= + +while getopts :ab: name "$@" +do + case $name in + a) aflag=1 ;; + b) bflag=1 + bval=$OPTARG;; + :) echo $0: error: option \`$OPTARG\' requires an argument + echo Usage: $0 [-a] [-b value] args + exit 2;; + ?) echo $0: error: illegal option character \`$OPTARG\' + echo Usage: $0 [-a] [-b value] args + exit 2;; + esac + +done + +if [ ! -z "$aflag" ] ; then echo -a specified ; fi +if [ ! -z "$bflag" ] ; then echo -b $bval specified ; fi + +if [ "$OPTIND" -gt 1 ] +then + shift $(( $OPTIND - 1 )) +fi + +echo remaining args: "$*" + +exit 0 diff --git a/tests/getopts5.sub b/tests/getopts5.sub new file mode 100644 index 0000000..874b281 --- /dev/null +++ b/tests/getopts5.sub @@ -0,0 +1,49 @@ +#Time-stamp: <95/06/07 07:40:40 hrue@imf.unit.no> + +getop () { + + local OPTIND=1 + local OPTERR=1 + + echo getop: OPTERR=$OPTERR + while getopts ab arg "$@"; do + case $arg in + a) + echo a here + ;; + b) + echo b here + ;; + :|?|*) + echo something else here + ;; + esac + done + echo getop: OPTIND=$OPTIND +} + +OPTIND= +OPTERR=0 + +echo OPTERR=$OPTERR +while getopts ab arg; do + case $arg in + a) + echo a here + ;; + b) + echo b here + ;; + :|?|*) + + echo something else here + ;; + esac +done + +echo OPTIND=$OPTIND + +getop "$@" -d -e + +echo OPTIND=$OPTIND +echo OPTERR=$OPTERR diff --git a/tests/getopts6.sub b/tests/getopts6.sub new file mode 100644 index 0000000..75d768c --- /dev/null +++ b/tests/getopts6.sub @@ -0,0 +1,27 @@ +aflag= +bflag= + +while getopts :ac name "$@" +do + case $name in + a) aflag=1 ;; + c) cflag=1 ;; + ?) exit 2;; + esac + + # this came in in a bug report -- it's really a usage error + # but it shouldn't cause the shell to crash + shift +done + +if [ ! -z "$aflag" ] ; then echo -a specified ; fi +if [ ! -z "$cflag" ] ; then echo -c specified ; fi + +if [ "$OPTIND" -gt 1 ] +then + shift $(( $OPTIND - 1 )) +fi + +echo remaining args: "$*" + +exit 0 diff --git a/tests/getopts7.sub b/tests/getopts7.sub new file mode 100644 index 0000000..a20a6df --- /dev/null +++ b/tests/getopts7.sub @@ -0,0 +1,30 @@ +aflag= +bflag= + +while getopts :ab: opt-var "$@" +do + case $name in + a) aflag=1 ;; + b) bflag=1 + bval=$OPTARG;; + :) echo $0: error: option \`$OPTARG\' requires an argument + echo Usage: $0 [-a] [-b value] args + exit 2;; + ?) echo $0: error: illegal option character \`$OPTARG\' + echo Usage: $0 [-a] [-b value] args + exit 2;; + esac + +done + +if [ ! -z "$aflag" ] ; then echo -a specified ; fi +if [ ! -z "$bflag" ] ; then echo -b $bval specified ; fi + +if [ "$OPTIND" -gt 1 ] +then + shift $(( $OPTIND - 1 )) +fi + +echo remaining args: "$*" + +exit 0 diff --git a/tests/getopts8.sub b/tests/getopts8.sub new file mode 100644 index 0000000..6aeeca6 --- /dev/null +++ b/tests/getopts8.sub @@ -0,0 +1,13 @@ +f() +{ + typeset OPTIND=1 + typeset opt + + while getopts ":abcxyz" opt + do + echo opt: "$opt" + if [[ $opt = y ]]; then f -abc ; fi + done +} + +f -xyz diff --git a/tests/getopts9.sub b/tests/getopts9.sub new file mode 100644 index 0000000..fafb067 --- /dev/null +++ b/tests/getopts9.sub @@ -0,0 +1,16 @@ +f() +{ + OPTIND=4 + + echo \$1 = $1 +} + +main() +{ +while getopts abcdefg opt +do + f $opt +done +} + +main -abc diff --git a/tests/glob.right b/tests/glob.right new file mode 100644 index 0000000..1ead7b6 --- /dev/null +++ b/tests/glob.right @@ -0,0 +1,197 @@ +foo/bar foobar/bar +ok 1 +ok 2 +ok 3 +ok 4 +ok 5 +b +argv[1] = <A£\B> +argv[1] = <A> +argv[1] = <B> +argv[1] = <a£\b> +0000000 141 243 134 142 +0000004 +ok 6 +ok 7 +invalid bracket expression +== LANG=C == +[[:alpha:] +ok 1 +[a +[[:alpha:] +ok 2 +ok 3 +== LANG=en_US.UTF-8 == +[[:alpha:] +ok 1 +[a +[[:alpha:] +ok 2 +ok 3 +invalid character class +== LANG=C == +ok 1 +ok 2 +ok 3 +ok 4 +ok 5 +ok 6 +== LANG=en_US.UTF-8 == +ok 1 +ok 2 +ok 3 +ok 4 +ok 5 +ok 6 +invalid collating symbols +== LANG=C == +ok 1 +ok 2 +ok 3 +ok 4 +ok 5 +== LANG=en_US.UTF-8 == +ok 1 +ok 2 +ok 3 +ok 4 +ok 5 +argv[1] = <a\?> +a? +argv[1] = <a\?> +a? +aa +argv[1] = <a> +argv[2] = <abc> +argv[3] = <abd> +argv[4] = <abe> +argv[5] = <X*> +argv[1] = <a> +argv[2] = <abc> +argv[3] = <abd> +argv[4] = <abe> +argv[1] = <a> +argv[2] = <abc> +argv[3] = <abd> +argv[4] = <abe> +tmp/l1 tmp/l2 tmp/*4 tmp/l3 +./glob.tests: line 47: no match: tmp/*4 +argv[1] = <bdir/> +argv[1] = <*> +argv[1] = <a*> +argv[1] = <a*> +argv[1] = <c> +argv[2] = <ca> +argv[3] = <cb> +argv[4] = <a*> +argv[5] = <*q*> +argv[1] = <**> +argv[1] = <**> +argv[1] = <\.\./*/> +argv[1] = <s/\..*//> +argv[1] = </^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\1/> +argv[1] = <abc> +argv[2] = <abd> +argv[3] = <abe> +argv[4] = <bb> +argv[5] = <cb> +argv[1] = <abd> +argv[2] = <abe> +argv[3] = <bb> +argv[4] = <bcd> +argv[5] = <bdir> +argv[6] = <ca> +argv[7] = <cb> +argv[8] = <dd> +argv[9] = <de> +argv[1] = <abd> +argv[2] = <abe> +argv[1] = <a-b> +argv[2] = <aXb> +argv[1] = <Beware> +argv[2] = <d> +argv[3] = <dd> +argv[4] = <de> +argv[1] = <a*b/ooo> +argv[1] = <a*b/ooo> +no match +not there +argv[1] = <abc> +argv[1] = <abc> +argv[1] = <abc> +argv[1] = <abc> +match 1 +match 2 +ok 1 +ok 2 +ok 3 +ok 4 +ok 5 +argv[1] = <man/man1/bash.1> +argv[1] = <man/man1/bash.1> +argv[1] = <man/man1/bash.1> +ok 1 +ok 2 +ok 3 +ok 4 +ok 5 +ok 6 +ok 7 +ok 8 +ok 9 +ok 10 +ok 11 +ok 20 +ok 21 +ok 22 +ok 23 +ok 24 +ok 25 +ok 26 +ok 27 +ok 28 +ok 29 +ok 30 +ok 31 +ok 32 +ok 33 +ok 34 +ok 35 +ok 36 +ok 37 +argv[1] = <b> +argv[2] = <bb> +argv[3] = <bcd> +argv[4] = <bdir> +argv[1] = <Beware> +argv[2] = <b> +argv[3] = <bb> +argv[4] = <bcd> +argv[5] = <bdir> +argv[1] = <Beware> +argv[2] = <b> +argv[3] = <bb> +argv[4] = <bcd> +argv[5] = <bdir> +argv[1] = <*> +argv[1] = <a*b> +argv[2] = <a-b> +argv[3] = <aXb> +argv[4] = <abd> +argv[5] = <bb> +argv[6] = <bcd> +argv[7] = <bdir> +argv[8] = <ca> +argv[9] = <cb> +argv[10] = <dd> +argv[11] = <man> +argv[1] = <Beware> +argv[2] = <abc> +argv[3] = <abe> +argv[4] = <bdir> +argv[5] = <ca> +argv[6] = <de> +argv[7] = <man> +argv[1] = <*> +argv[1] = <man/man1/bash.1> +argv[1] = <man/man1/bash.1> diff --git a/tests/glob.tests b/tests/glob.tests new file mode 100644 index 0000000..01913bb --- /dev/null +++ b/tests/glob.tests @@ -0,0 +1,391 @@ +export LC_COLLATE=C +# +# test the shell globbing +# +expect() +{ +: # if needed, change me to echo expect "$@" +} + +# First, a test that bash-2.01.1 fails +${THIS_SH} ./glob1.sub +${THIS_SH} ./glob2.sub +${THIS_SH} ./glob3.sub +${THIS_SH} ./glob4.sub + +MYDIR=$PWD # save where we are + +TESTDIR=$TMPDIR/glob-test-$$ +mkdir $TESTDIR +builtin cd $TESTDIR || { echo $0: cannot cd to $TESTDIR >&2 ; exit 1; } +rm -rf * + +touch a b c d abc abd abe bb bcd ca cb dd de Beware +mkdir bdir + +# see if `regular' globbing works right +expect '<a> <abc> <abd> <abe> <X*>' +recho a* X* + +expect '<a> <abc> <abd> <abe>' +recho \a* + +# see if null glob expansion works +shopt -s nullglob + +expect '<a> <abc> <abd> <abe>' +recho a* X* + +shopt -u nullglob + +# see if the failglob option works + +mkdir tmp +touch tmp/l1 tmp/l2 tmp/l3 +builtin echo tmp/l[12] tmp/*4 tmp/*3 +shopt -s failglob +builtin echo tmp/l[12] tmp/*4 tmp/*3 +rm -r tmp +shopt -u failglob + +# see if the code that expands directories only works +expect '<bdir/>' +recho b*/ + +# Test quoted and unquoted globbing characters +expect '<*>' +recho \* + +expect '<a*>' +recho 'a*' + +expect '<a*>' +recho a\* + +expect '<c> <ca> <cb> <a*> <*q*>' +recho c* a\* *q* + +expect '<**>' +recho "*"* + +expect '<**>' +recho \** + +expect '<\.\./*/>' +recho "\.\./*/" + +expect '<s/\..*//>' +recho 's/\..*//' + +# Pattern from Larry Wall's Configure that caused bash to blow up +expect '</^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\1/>' +recho "/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*"'$'"/\1/" + +# Make sure character classes work properly + +expect '<abc> <abd> <abe> <bb> <cb>' +recho [a-c]b* + +expect '<abd> <abe> <bb> <bcd> <bdir> <ca> <cb> <dd> <de>' +recho [a-y]*[^c] + +expect '<abd> <abe>' +recho a*[^c] + +touch a-b aXb +expect '<a-b> <aXb>' +recho a[X-]b + +touch .x .y +expect '<Beware> <d> <dd> <de>' +recho [^a-c]* + +# Make sure that filenames with embedded globbing characters are handled +# properly +mkdir a\*b +> a\*b/ooo + +expect '<a*b/ooo>' +recho a\*b/* + +expect '<a*b/ooo>' +recho a\*?/* + +expect '<no match>' +cmd='echo !7' +case "$cmd" in +*\\!*) echo match ;; +*) echo no match ;; +esac + +expect '<not there>' +file='r.*' +case $file in +*.\*) echo not there ;; +*) echo there ;; +esac + +# examples from the Posix.2 spec (d11.2, p. 243) +expect '<abc>' +recho a[b]c + +expect '<abc>' +recho a["b"]c + +expect '<abc>' +recho a[\b]c + +expect '<abc>' +recho a?c + +expect '<match 1>' +case abc in +a"b"c) echo 'match 1' ;; +*) echo 'BAD match 1' ;; +esac + +expect '<match 2>' +case abc in +a*c) echo 'match 2' ;; +*) echo 'BAD match 2' ;; +esac + +expect '<ok 1>' +case abc in +"a?c") echo 'bad 1' ;; +*) echo 'ok 1' ;; +esac + +expect '<ok 2>' +case abc in +a\*c) echo 'bad 2' ;; +*) echo 'ok 2' ;; +esac + +expect '<ok 3>' +case abc in +a\[b]c) echo 'bad 3' ;; +*) echo 'ok 3' ;; +esac + +expect '<ok 4>' +case "$nosuchvar" in +"") echo 'ok 4' ;; +*) echo 'bad 4' ;; +esac + +# This is very odd, but sh and ksh seem to agree +expect '<ok 5>' +case abc in +a["\b"]c) echo 'ok 5' ;; +*) echo 'bad 5' ;; +esac + +mkdir man +mkdir man/man1 +touch man/man1/bash.1 +expect '<man/man1/bash.1>' +recho */man*/bash.* +expect '<man/man1/bash.1>' +recho $(echo */man*/bash.*) +expect '<man/man1/bash.1>' +recho "$(echo */man*/bash.*)" + +# tests with multiple `*'s +case abc in +a***c) echo ok 1;; +esac + +case abc in +a*****?c) echo ok 2;; +esac + +case abc in +?*****??) echo ok 3;; +esac + +case abc in +*****??) echo ok 4;; +esac + +case abc in +*****??c) echo ok 5;; +esac + +case abc in +?*****?c) echo ok 6;; +esac + +case abc in +?***?****c) echo ok 7;; +esac + +case abc in +?***?****?) echo ok 8;; +esac + +case abc in +?***?****) echo ok 9;; +esac + +case abc in +*******c) echo ok 10;; +esac + +case abc in +*******?) echo ok 11;; +esac + +case abcdecdhjk in +a*cd**?**??k) echo ok 20;; +esac + +case abcdecdhjk in +a**?**cd**?**??k) echo ok 21;; +esac + +case abcdecdhjk in +a**?**cd**?**??k***) echo ok 22;; +esac + +case abcdecdhjk in +a**?**cd**?**??***k) echo ok 23;; +esac + +case abcdecdhjk in +a**?**cd**?**??***k**) echo ok 24;; +esac + +case abcdecdhjk in +a****c**?**??*****) echo ok 25;; +esac + +case '-' in +[-abc]) echo ok 26 ;; +esac + +case '-' in +[abc-]) echo ok 27 ;; +esac + +case '\' in +\\) echo ok 28 ;; +esac + +case '\' in +[\\]) echo ok 29 ;; +esac + +case '\' in +'\') echo ok 30 ;; +esac + +case '[' in +[[]) echo ok 31 ;; +esac + +# a `[' without a closing `]' is just another character to match, in the +# bash implementation +case '[' in +[) echo ok 32 ;; +esac + +case '[abc' in +[*) echo 'ok 33';; +esac + +# a right bracket shall lose its special meaning and represent itself in +# a bracket expression if it occurs first in the list. -- POSIX.2 2.8.3.2 +case ']' in +[]]) echo ok 34 ;; +esac + +case '-' in +[]-]) echo ok 35 ;; +esac + +# a backslash should just escape the next character in this context +case p in +[a-\z]) echo ok 36 ;; +esac + +# this was a bug in all versions up to bash-2.04-release +case "/tmp" in +[/\\]*) echo ok 37 ;; +esac + +# none of these should output anything + +case abc in +??**********?****?) echo bad 1;; +esac + +case abc in +??**********?****c) echo bad 2;; +esac + +case abc in +?************c****?****) echo bad 3;; +esac + +case abc in +*c*?**) echo bad 4;; +esac + +case abc in +a*****c*?**) echo bad 5;; +esac + +case abc in +a********???*******) echo bad 6;; +esac + +case 'a' in +[]) echo bad 7 ;; +esac + +case '[' in +[abc) echo bad 8;; +esac + +# let's start testing the case-insensitive globbing code +recho b* + +shopt -s nocaseglob +recho b* + +recho [b]* +shopt -u nocaseglob + +# make sure set -f works right +set -f +recho * +set +f + +# test out the GLOBIGNORE code +GLOBIGNORE='.*:*c:*e:?' +recho * + +GLOBIGNORE='.*:*b:*d:?' +recho * + +# see if GLOBIGNORE can substitute for `set -f' +GLOBIGNORE='.*:*' +recho * + +unset GLOBIGNORE +expect '<man/man1/bash.1>' +recho */man*/bash.* + +# make sure null values for GLOBIGNORE have no effect +GLOBIGNORE= +expect '<man/man1/bash.1>' +recho */man*/bash.* + +# this is for the benefit of pure coverage, so it writes the pcv file +# in the right place, and for gprof +builtin cd $MYDIR + +rm -rf $TESTDIR + +exit 0 diff --git a/tests/glob1.sub b/tests/glob1.sub new file mode 100644 index 0000000..6b3b8ad --- /dev/null +++ b/tests/glob1.sub @@ -0,0 +1,17 @@ +# bash-2.01.1 failed this test +: ${TMPDIR:=/var/tmp} + +FN=$TMPDIR/bash-glob.$$ +mkdir $FN +cd $FN + +mkdir foo +mkdir foobar +touch foo/bar +touch foobar/bar +chmod 311 foo foobar +echo f*/bar + +chmod 777 foo foobar +cd $OLDPWD +rm -rf $FN diff --git a/tests/glob2.sub b/tests/glob2.sub new file mode 100644 index 0000000..d33013b --- /dev/null +++ b/tests/glob2.sub @@ -0,0 +1,44 @@ +. ./test-glue-functions + +var='ab\' + +case $var in +ab\\) echo ok 1;; +*) echo bad 1;; +esac + +case $var in +$var) echo ok 2;; +*) echo bad 2;; +esac + +case $var in +'ab\') echo ok 3;; +*) echo bad 3;; +esac + +[[ $var = $var ]] && echo ok 4 +[[ $var = $'ab\134' ]] && echo ok 5 + +LC_ALL=zh_HK.big5hkscs + +read a b c <<< $'\u3b1 b c\n' +echo $b +unset a b c + +export alpha=$'\u3b1' + +printf -v v 'A%sB' "$alpha" +recho "$v" +IFS=$alpha read a b c <<<"$v" +recho "$a" +recho "$b" +unset a b v + +recho "a${alpha}b" +printf "%s" "a${alpha}b" | LC_ALL=C od -b | _intl_normalize_spaces + +a=$'\u3b1' +[[ $a = $a ]] && echo ok 6 + +LC_ALL=zh_HK.big5hkscs ${THIS_SH} -c $'[[ \u3b1 = \u3b1 ]]' && echo ok 7 diff --git a/tests/glob3.sub b/tests/glob3.sub new file mode 100644 index 0000000..378234d --- /dev/null +++ b/tests/glob3.sub @@ -0,0 +1,123 @@ +: ${TMPDIR:=/var/tmp} +cd $TMPDIR + +matchfunc() +{ + echo == LANG=$LANG == + + touch a p + echo [[:alpha:] + rm a p + + case l in + [[:alpha:]) echo bad 1;; + *) echo ok 1;; + esac + + touch '[a' '[x' + echo [[:alpha:] + rm '[a' + echo [[:alpha:] + rm '[x' + + case [a in + [[:alpha:]) echo ok 2;; + *) echo bad 2;; + esac + + case [x in + [[:alpha:]) echo bad 3;; + *) echo ok 3;; + esac +} + +echo invalid bracket expression +export LANG=C +matchfunc + +export LANG=en_US.UTF-8 +matchfunc + +unset -f matchfunc + +matchfunc() +{ + echo == LANG=$LANG == + + case a] in + [[:aleph:]]) echo bad 1;; + *) echo ok 1;; + esac + + case a in + [[:aleph:]]) echo bad 2;; + *) echo ok 2;; + esac + + case a] in + [[:"alpha":]]) echo bad 3;; + *) echo ok 3;; + esac + + case a in + [[:"alpha":]]) echo bad 4;; + *) echo ok 4;; + esac + + case a in + [abc[:foo:]]) echo ok 5;; + *) echo bad 5 ;; + esac + + case a in + [[:foo:]abc]) echo ok 6;; + *) echo bad 6 ;; + esac +} + +echo invalid character class +export LANG=C +matchfunc + +export LANG=en_US.UTF-8 +matchfunc + +unset -f matchfunc + +matchfunc() +{ + echo == LANG=$LANG == + + case h in + [[.hyphen.]) echo bad 1;; + *) echo ok 1;; + esac + + case - in + [[.hyphen.]]) echo ok 2;; + *) echo bad 2;; + esac + + case slash in + [[.slash.]]) echo bad 3;; + *) echo ok 3;; + esac + + case a in + [abc[.nonsense.]]) echo ok 4;; + *) echo bad 4 ;; + esac + + case a in + [[.nonsense.]abc]) echo ok 5;; + *) echo bad 5 ;; + esac +} + +echo invalid collating symbols + +export LANG=C +matchfunc + +export LANG=en_US.UTF-8 +matchfunc diff --git a/tests/glob4.sub b/tests/glob4.sub new file mode 100644 index 0000000..378b5a9 --- /dev/null +++ b/tests/glob4.sub @@ -0,0 +1,13 @@ +trap "rm 'a?' aa" EXIT +touch 'a?' aa + +set -- a \?; IFS=\\; var=$*; +recho "$var" +unset IFS; printf "%s\n" ${var} + +var='a\?' +recho "$var" +printf "%s\n" ${var} + +var='a\a' +printf "%s\n" ${var} diff --git a/tests/globstar.right b/tests/globstar.right new file mode 100644 index 0000000..69030c4 --- /dev/null +++ b/tests/globstar.right @@ -0,0 +1,584 @@ +lib/glob/glob.o +lib/glob/smatch.o +lib/glob/strmatch.o +lib/readline/bind.o +lib/readline/callback.o +lib/readline/compat.o +lib/readline/complete.o +lib/readline/display.o +lib/sh/casemod.o +lib/sh/clktck.o +lib/sh/clock.o +lib/sh/eaccess.o +lib/sh/fdprintf.o +lib/sh/fmtullong.o +lib/sh/fmtulong.o +lib/sh/fmtumax.o +lib/sh/fpurge.o +lib/sh/getenv.o +lib/sh/input_avail.o +lib/sh/itos.o + +lib/: +glob +readline +sh + +lib/glob: +glob.o +smatch.o +strmatch.o + +lib/readline: +bind.o +callback.o +compat.o +complete.o +display.o + +lib/sh: +casemod.o +clktck.o +clock.o +eaccess.o +fdprintf.o +fmtullong.o +fmtulong.o +fmtumax.o +fpurge.o +getenv.o +input_avail.o +itos.o +lib/glob/glob.o +lib/glob/smatch.o +lib/glob/strmatch.o +lib/readline/bind.o +lib/readline/callback.o +lib/readline/compat.o +lib/readline/complete.o +lib/readline/display.o +lib/sh/casemod.o +lib/sh/clktck.o +lib/sh/clock.o +lib/sh/eaccess.o +lib/sh/fdprintf.o +lib/sh/fmtullong.o +lib/sh/fmtulong.o +lib/sh/fmtumax.o +lib/sh/fpurge.o +lib/sh/getenv.o +lib/sh/input_avail.o +lib/sh/itos.o +alias.o builtins/history.o builtins/jobs.o builtins/kill.o builtins/let.o builtins/mapfile.o lib/glob/glob.o lib/glob/smatch.o lib/glob/strmatch.o lib/readline/bind.o lib/readline/callback.o lib/readline/compat.o lib/readline/complete.o lib/readline/display.o lib/sh/casemod.o lib/sh/clktck.o lib/sh/clock.o lib/sh/eaccess.o lib/sh/fdprintf.o lib/sh/fmtullong.o lib/sh/fmtulong.o lib/sh/fmtumax.o lib/sh/fpurge.o lib/sh/getenv.o lib/sh/input_avail.o lib/sh/itos.o pcomplib.o print_cmd.o redir.o shell.o sig.o stringlib.o subst.o syntax.o test.o trap.o unwind_prot.o variables.o version.o xmalloc.o y.tab.o +alias.o +builtins/history.o +builtins/jobs.o +builtins/kill.o +builtins/let.o +builtins/mapfile.o +lib/glob/glob.o +lib/glob/smatch.o +lib/glob/strmatch.o +lib/readline/bind.o +lib/readline/callback.o +lib/readline/compat.o +lib/readline/complete.o +lib/readline/display.o +lib/sh/casemod.o +lib/sh/clktck.o +lib/sh/clock.o +lib/sh/eaccess.o +lib/sh/fdprintf.o +lib/sh/fmtullong.o +lib/sh/fmtulong.o +lib/sh/fmtumax.o +lib/sh/fpurge.o +lib/sh/getenv.o +lib/sh/input_avail.o +lib/sh/itos.o +pcomplib.o +print_cmd.o +redir.o +shell.o +sig.o +stringlib.o +subst.o +syntax.o +test.o +trap.o +unwind_prot.o +variables.o +version.o +xmalloc.o +y.tab.o + +builtins: +history.o +jobs.o +kill.o +let.o +mapfile.o + +lib: +glob +readline +sh + +lib/glob: +glob.o +smatch.o +strmatch.o + +lib/readline: +bind.o +callback.o +compat.o +complete.o +display.o + +lib/sh: +casemod.o +clktck.o +clock.o +eaccess.o +fdprintf.o +fmtullong.o +fmtulong.o +fmtumax.o +fpurge.o +getenv.o +input_avail.o +itos.o +alias.o builtins builtins/history.o builtins/jobs.o builtins/kill.o builtins/let.o builtins/mapfile.o lib lib/glob lib/glob/glob.o lib/glob/smatch.o lib/glob/strmatch.o lib/readline lib/readline/bind.o lib/readline/callback.o lib/readline/compat.o lib/readline/complete.o lib/readline/display.o lib/sh lib/sh/casemod.o lib/sh/clktck.o lib/sh/clock.o lib/sh/eaccess.o lib/sh/fdprintf.o lib/sh/fmtullong.o lib/sh/fmtulong.o lib/sh/fmtumax.o lib/sh/fpurge.o lib/sh/getenv.o lib/sh/input_avail.o lib/sh/itos.o pcomplib.o print_cmd.o redir.o shell.o sig.o stringlib.o subst.o syntax.o test.o trap.o unwind_prot.o variables.o version.o xmalloc.o y.tab.o +bar/foo foo +bar/foo/ foo/ +bar/foo/e bar/foo/f foo/a foo/b +<a> +<a/a> +<a/a/a> +<a> +<a/a> +<a/a/a> +<a> +<a/a> +<a/a/a> +== <**/a> == +<a> +<a/a> +<a/a/a> +<a/a/a/a> +<a/a/b/a> +<a/b/a> +<a/b/a/a> +<a/b/b/a> +<b/a> +<b/a/a> +<b/a/a/a> +<b/a/b/a> +<b/b/a> +<b/b/a/a> +<b/b/b/a> +== <a/**> == +<a/> +<a/a> +<a/a/a> +<a/a/a/a> +<a/a/a/b> +<a/a/b> +<a/a/b/a> +<a/a/b/b> +<a/b> +<a/b/a> +<a/b/a/a> +<a/b/a/b> +<a/b/b> +<a/b/b/a> +<a/b/b/b> +== <**> == +<a> +<a/a> +<a/a/a> +<a/a/a/a> +<a/a/a/b> +<a/a/b> +<a/a/b/a> +<a/a/b/b> +<a/b> +<a/b/a> +<a/b/a/a> +<a/b/a/b> +<a/b/b> +<a/b/b/a> +<a/b/b/b> +<b> +<b/a> +<b/a/a> +<b/a/a/a> +<b/a/a/b> +<b/a/b> +<b/a/b/a> +<b/a/b/b> +<b/b> +<b/b/a> +<b/b/a/a> +<b/b/a/b> +<b/b/b> +<b/b/b/a> +<b/b/b/b> +== <**/**> == +<a> +<a/a> +<a/a/a> +<a/a/a/a> +<a/a/a/b> +<a/a/b> +<a/a/b/a> +<a/a/b/b> +<a/b> +<a/b/a> +<a/b/a/a> +<a/b/a/b> +<a/b/b> +<a/b/b/a> +<a/b/b/b> +<b> +<b/a> +<b/a/a> +<b/a/a/a> +<b/a/a/b> +<b/a/b> +<b/a/b/a> +<b/a/b/b> +<b/b> +<b/b/a> +<b/b/a/a> +<b/b/a/b> +<b/b/b> +<b/b/b/a> +<b/b/b/b> +== <**/**/**> == +<a> +<a/a> +<a/a/a> +<a/a/a/a> +<a/a/a/b> +<a/a/b> +<a/a/b/a> +<a/a/b/b> +<a/b> +<a/b/a> +<a/b/a/a> +<a/b/a/b> +<a/b/b> +<a/b/b/a> +<a/b/b/b> +<b> +<b/a> +<b/a/a> +<b/a/a/a> +<b/a/a/b> +<b/a/b> +<b/a/b/a> +<b/a/b/b> +<b/b> +<b/b/a> +<b/b/a/a> +<b/b/a/b> +<b/b/b> +<b/b/b/a> +<b/b/b/b> +== <**/**/**/**/**> == +<a> +<a/a> +<a/a/a> +<a/a/a/a> +<a/a/a/b> +<a/a/b> +<a/a/b/a> +<a/a/b/b> +<a/b> +<a/b/a> +<a/b/a/a> +<a/b/a/b> +<a/b/b> +<a/b/b/a> +<a/b/b/b> +<b> +<b/a> +<b/a/a> +<b/a/a/a> +<b/a/a/b> +<b/a/b> +<b/a/b/a> +<b/a/b/b> +<b/b> +<b/b/a> +<b/b/a/a> +<b/b/a/b> +<b/b/b> +<b/b/b/a> +<b/b/b/b> +== <**/**/a> == +<a> +<a/a> +<a/a/a> +<a/a/a/a> +<a/a/b/a> +<a/b/a> +<a/b/a/a> +<a/b/b/a> +<b/a> +<b/a/a> +<b/a/a/a> +<b/a/b/a> +<b/b/a> +<b/b/a/a> +<b/b/b/a> +== <a/**/**> == +<a> +<a/a> +<a/a/a> +<a/a/a/a> +<a/a/a/b> +<a/a/b> +<a/a/b/a> +<a/a/b/b> +<a/b> +<a/b/a> +<a/b/a/a> +<a/b/a/b> +<a/b/b> +<a/b/b/a> +<a/b/b/b> +== <a/**/**/**> == +<a> +<a/a> +<a/a/a> +<a/a/a/a> +<a/a/a/b> +<a/a/b> +<a/a/b/a> +<a/a/b/b> +<a/b> +<a/b/a> +<a/b/a/a> +<a/b/a/b> +<a/b/b> +<a/b/b/a> +<a/b/b/b> +== <a/**/**/**/**> == +<a> +<a/a> +<a/a/a> +<a/a/a/a> +<a/a/a/b> +<a/a/b> +<a/a/b/a> +<a/a/b/b> +<a/b> +<a/b/a> +<a/b/a/a> +<a/b/a/b> +<a/b/b> +<a/b/b/a> +<a/b/b/b> +== <**/a/**> == +<a> +<a/a> +<a/a> +<a/a/a> +<a/a/a> +<a/a/a> +<a/a/a/a> +<a/a/a/a> +<a/a/a/a> +<a/a/a/a> +<a/a/a/b> +<a/a/a/b> +<a/a/a/b> +<a/a/b> +<a/a/b> +<a/a/b/a> +<a/a/b/a> +<a/a/b/a> +<a/a/b/b> +<a/a/b/b> +<a/b> +<a/b/a> +<a/b/a> +<a/b/a/a> +<a/b/a/a> +<a/b/a/a> +<a/b/a/b> +<a/b/a/b> +<a/b/b> +<a/b/b/a> +<a/b/b/a> +<a/b/b/b> +<b/a> +<b/a/a> +<b/a/a> +<b/a/a/a> +<b/a/a/a> +<b/a/a/a> +<b/a/a/b> +<b/a/a/b> +<b/a/b> +<b/a/b/a> +<b/a/b/a> +<b/a/b/b> +<b/b/a> +<b/b/a/a> +<b/b/a/a> +<b/b/a/b> +<b/b/b/a> +== <**/a/**/**> == +<a> +<a/a> +<a/a> +<a/a/a> +<a/a/a> +<a/a/a> +<a/a/a/a> +<a/a/a/a> +<a/a/a/a> +<a/a/a/a> +<a/a/a/b> +<a/a/a/b> +<a/a/a/b> +<a/a/b> +<a/a/b> +<a/a/b/a> +<a/a/b/a> +<a/a/b/a> +<a/a/b/b> +<a/a/b/b> +<a/b> +<a/b/a> +<a/b/a> +<a/b/a/a> +<a/b/a/a> +<a/b/a/a> +<a/b/a/b> +<a/b/a/b> +<a/b/b> +<a/b/b/a> +<a/b/b/a> +<a/b/b/b> +<b/a> +<b/a/a> +<b/a/a> +<b/a/a/a> +<b/a/a/a> +<b/a/a/a> +<b/a/a/b> +<b/a/a/b> +<b/a/b> +<b/a/b/a> +<b/a/b/a> +<b/a/b/b> +<b/b/a> +<b/b/a/a> +<b/b/a/a> +<b/b/a/b> +<b/b/b/a> +== <**/a/**/**/**> == +<a> +<a/a> +<a/a> +<a/a/a> +<a/a/a> +<a/a/a> +<a/a/a/a> +<a/a/a/a> +<a/a/a/a> +<a/a/a/a> +<a/a/a/b> +<a/a/a/b> +<a/a/a/b> +<a/a/b> +<a/a/b> +<a/a/b/a> +<a/a/b/a> +<a/a/b/a> +<a/a/b/b> +<a/a/b/b> +<a/b> +<a/b/a> +<a/b/a> +<a/b/a/a> +<a/b/a/a> +<a/b/a/a> +<a/b/a/b> +<a/b/a/b> +<a/b/b> +<a/b/b/a> +<a/b/b/a> +<a/b/b/b> +<b/a> +<b/a/a> +<b/a/a> +<b/a/a/a> +<b/a/a/a> +<b/a/a/a> +<b/a/a/b> +<b/a/a/b> +<b/a/b> +<b/a/b/a> +<b/a/b/a> +<b/a/b/b> +<b/b/a> +<b/b/a/a> +<b/b/a/a> +<b/b/a/b> +<b/b/b/a> +== <**/**/a/**> == +<a> +<a/a> +<a/a> +<a/a/a> +<a/a/a> +<a/a/a> +<a/a/a/a> +<a/a/a/a> +<a/a/a/a> +<a/a/a/a> +<a/a/a/b> +<a/a/a/b> +<a/a/a/b> +<a/a/b> +<a/a/b> +<a/a/b/a> +<a/a/b/a> +<a/a/b/a> +<a/a/b/b> +<a/a/b/b> +<a/b> +<a/b/a> +<a/b/a> +<a/b/a/a> +<a/b/a/a> +<a/b/a/a> +<a/b/a/b> +<a/b/a/b> +<a/b/b> +<a/b/b/a> +<a/b/b/a> +<a/b/b/b> +<b/a> +<b/a/a> +<b/a/a> +<b/a/a/a> +<b/a/a/a> +<b/a/a/a> +<b/a/a/b> +<b/a/a/b> +<b/a/b> +<b/a/b/a> +<b/a/b/a> +<b/a/b/b> +<b/b/a> +<b/b/a/a> +<b/b/a/a> +<b/b/a/b> +<b/b/b/a> diff --git a/tests/globstar.tests b/tests/globstar.tests new file mode 100644 index 0000000..f7efbd1 --- /dev/null +++ b/tests/globstar.tests @@ -0,0 +1,42 @@ +: ${TMPDIR:=/var/tmp} +dir=$PWD + +shopt -s globstar + +export LANG=C LC_ALL=C LC_COLLATE=C + +GDIR=$TMPDIR/globstar-$$ + +mkdir $GDIR || exit 1 +cd $GDIR || exit 1 + +mkdir lib builtins +mkdir lib/glob lib/readline lib/sh + +touch builtins/history.o builtins/jobs.o builtins/kill.o builtins/let.o builtins/mapfile.o +touch lib/glob/glob.o lib/glob/smatch.o lib/glob/strmatch.o +touch lib/readline/bind.o lib/readline/callback.o lib/readline/compat.o lib/readline/complete.o lib/readline/display.o + +touch lib/sh/casemod.o lib/sh/clktck.o lib/sh/clock.o lib/sh/eaccess.o +touch lib/sh/fdprintf.o lib/sh/fmtullong.o lib/sh/fmtulong.o lib/sh/fmtumax.o +touch lib/sh/fpurge.o lib/sh/getenv.o lib/sh/input_avail.o lib/sh/itos.o + +touch alias.o +touch pcomplib.o print_cmd.o redir.o shell.o sig.o stringlib.o subst.o syntax.o +touch test.o trap.o unwind_prot.o variables.o version.o xmalloc.o y.tab.o + +ls lib/** + +ls lib/**/*.o + +echo **/*.o + +ls ** + +echo ** + +cd $dir +rm -rf $GDIR + +${THIS_SH} ./globstar1.sub +${THIS_SH} ./globstar2.sub diff --git a/tests/globstar1.sub b/tests/globstar1.sub new file mode 100644 index 0000000..8b9e36d --- /dev/null +++ b/tests/globstar1.sub @@ -0,0 +1,21 @@ +shopt -s globstar +wdir=$PWD + +: ${TMPDIR:=/var/tmp} +DIR=$TMPDIR/globstar-$$ +mkdir -p $DIR +cd $DIR || { + echo "$DIR: cannot cd" >&2 + exit 1 +} +mkdir -p foo/{a,b} bar/{c,d,foo/{e,f}} baz/{g,h} + + +echo **/foo* + +echo **/foo*/ + +echo **/foo*/* + +cd $wdir +rm -rf $DIR diff --git a/tests/globstar2.sub b/tests/globstar2.sub new file mode 100644 index 0000000..4e1a024 --- /dev/null +++ b/tests/globstar2.sub @@ -0,0 +1,84 @@ +olddir=$PWD +: ${TMPDIR:=/var/tmp} +EMPTY=$TMPDIR/empty + +shopt -s globstar +s() +{ + printf '== <%s> ==\n' "$@" +} +p() +{ + printf '<%q>\n' "$@" +} + +mkdir -p $EMPTY/a/a/a +cd $EMPTY + +# good +p ** +p **/** +p **/**/** + +rm -rf a +mkdir -p $EMPTY/{a,b}/{a,b}/{a,b}/{a,b} +cd $EMPTY + +# good +s '**/a' +p **/a + +# good +s 'a/**' +p a/** + +# good +s '**' +p ** + +# good +s '**/**' +p **/** + +# good +s '**/**/**' +p **/**/** + +# good +s '**/**/**/**/**' +p **/**/**/**/** + +# good +s '**/**/a' +p **/**/a + +# good +s 'a/**/**' +p a/**/** + +# good +s 'a/**/**/**' +p a/**/**/** + +# good +s 'a/**/**/**/**' +p a/**/**/**/** + +# same as ksh93 +s '**/a/**' +p **/a/** + +# same as ksh93 +s '**/a/**/**' +p **/a/**/** + +# same as ksh93 +s '**/a/**/**/**' +p **/a/**/**/** + +# good +s '**/**/a/**' +p **/**/a/** + +cd "$olddir" +rm -rf $EMPTY diff --git a/tests/heredoc.right b/tests/heredoc.right new file mode 100644 index 0000000..f6541dc --- /dev/null +++ b/tests/heredoc.right @@ -0,0 +1,98 @@ +there +one - alpha +two - beta +three - gamma +hi\ +there$a +stuff +hi\ +there +EO\ +F +hi +hi +tab 1 +tab 2 +tab 3 +abc +def ghi +jkl mno +fff is a function +fff () +{ + ed ${TMPDIR}/foo <<ENDOFINPUT > /dev/null +/^name/d +w +q +ENDOFINPUT + + aa=1 +} +fff is a function +fff () +{ + ed ${TMPDIR}/foo <<ENDOFINPUT > /dev/null +/^name/d +w +q +ENDOFINPUT + + aa=1 +} +foo is a function +foo () +{ + echo; + cat <<END +bar +END + + cat <<EOF +qux +EOF + +} + +bar +qux + +bar +qux +abc def geh +./heredoc3.sub: line 10: warning: here-document at line 8 delimited by end-of-file (wanted `EOF') += here is the text = +./heredoc3.sub: line 16: warning: here-document at line 14 delimited by end-of-file (wanted `EOF') +this paren ) is not a problem +./heredoc3.sub: line 22: warning: here-document at line 20 delimited by end-of-file (wanted `EOF') +these balanced parens ( ) are not a problem +./heredoc3.sub: line 28: warning: here-document at line 26 delimited by end-of-file (wanted `EOF') +quoted balanced parens \( ) are not a problem either +more text in a subshell +some more text in a different subshell +end +hello +hello +ENDEND +end ENDEND +hello +end hello +end x*x +helloEND +end helloEND +hello +\END +end hello<NL>\END +./heredoc3.sub: line 85: warning: here-document at line 83 delimited by end-of-file (wanted `EOF') +./heredoc3.sub: line 86: syntax error: unexpected end of file +heredoc1 +EOF +Ok:0 +argv[1] = <onetwo> +argv[2] = <threefour> +argv[1] = <two> +argv[2] = <threefi> +argv[3] = <ve> +comsub here-string +./heredoc.tests: line 105: warning: here-document at line 103 delimited by end-of-file (wanted `EOF') +hi +there diff --git a/tests/heredoc.tests b/tests/heredoc.tests new file mode 100644 index 0000000..303949f --- /dev/null +++ b/tests/heredoc.tests @@ -0,0 +1,105 @@ +# check order and content of multiple here docs + +cat << EOF1 << EOF2 +hi +EOF1 +there +EOF2 + +while read line1; do + read line2 <&3 + echo $line1 - $line2 +done <<EOF1 3<<EOF2 +one +two +three +EOF1 +alpha +beta +gamma +EOF2 + + +# check quoted here-doc is protected + +a=foo +cat << 'EOF' +hi\ +there$a +stuff +EOF + +# check that quoted here-documents don't have \newline processing done + +cat << 'EOF' +hi\ +there +EO\ +F +EOF +true + +# check that \newline is removed at start of here-doc +cat << EO\ +F +hi +EOF + +# check that \newline removal works for here-doc delimiter +cat << EOF +hi +EO\ +F + +# check operation of tab removal in here documents +cat <<- EOF + tab 1 + tab 2 + tab 3 + EOF + +# check appending of text to file from here document +rm -f ${TMPDIR}/bash-zzz +cat > ${TMPDIR}/bash-zzz << EOF +abc +EOF +cat >> ${TMPDIR}/bash-zzz << EOF +def ghi +jkl mno +EOF +cat ${TMPDIR}/bash-zzz +rm -f ${TMPDIR}/bash-zzz + +# make sure command printing puts the here-document as the last redirection +# on the line, and the function export code preserves syntactic correctness +fff() +{ + ed ${TMPDIR}/foo <<ENDOFINPUT >/dev/null +/^name/d +w +q +ENDOFINPUT +aa=1 +} + +type fff +export -f fff +${THIS_SH} -c 'type fff' + +${THIS_SH} ./heredoc1.sub + +# test heredocs in command substitutions +${THIS_SH} ./heredoc2.sub +${THIS_SH} ./heredoc3.sub +${THIS_SH} ./heredoc4.sub + +echo $( + cat <<< "comsub here-string" +) + +# check that end of file delimits a here-document +# THIS MUST BE LAST! + +cat << EOF +hi +there diff --git a/tests/heredoc1.sub b/tests/heredoc1.sub new file mode 100644 index 0000000..3f85ead --- /dev/null +++ b/tests/heredoc1.sub @@ -0,0 +1,16 @@ +foo() +{ + echo + cat <<END +bar +END + cat <<EOF +qux +EOF +} + +type foo +foo + +eval "$(type foo | sed 1d)" +foo diff --git a/tests/heredoc2.sub b/tests/heredoc2.sub new file mode 100644 index 0000000..7e97ed8 --- /dev/null +++ b/tests/heredoc2.sub @@ -0,0 +1,9 @@ +TEST=$(cat <<EOF | sort -u +abc +geh +def +abc +EOF +) + +echo $TEST diff --git a/tests/heredoc3.sub b/tests/heredoc3.sub new file mode 100644 index 0000000..a5a2fbc --- /dev/null +++ b/tests/heredoc3.sub @@ -0,0 +1,85 @@ +SAVEPWD=$PWD +: ${TMPDIR:=/tmp} +cd $TMPDIR || echo "heredoc3.sub: cannot cd to $TMPDIR" >&2 + +text=$(cat <<EOF +here is the text +EOF) + +echo = $text = + +unbalanced=$(cat <<EOF +this paren ) is not a problem +EOF) + +echo $unbalanced + +balanced=$(cat <<EOF +these balanced parens ( ) are not a problem +EOF) + +echo $balanced + +balanced=$(cat <<EOF +quoted balanced parens \( ) are not a problem either +EOF) + +echo $balanced + +(cat <<EOF +more text in a subshell +EOF +) + +(cat <<EOF; ) +some more text in a different subshell +EOF +echo end + +# semi-weird examples posted by Wayne Pollack to austin-group mailing list +cat <<-' END' + hello + END + +cat <<END +hello +END\ +END +END +echo end ENDEND + +cat <<' END ' +hello + END +echo end hello + +cat <<x*x >/dev/null & touch 'x*x' +x star x +x*x +wait $! +echo end 'x*x' +rm 'x*x' + +cat <<END +hello\ +END +END +echo end helloEND + +cat <<END +hello +\END +END +echo -E end 'hello<NL>\END' + +# gprof +if [ -n "$GMON_OUT_PREFIX" ]; then + mv ${GMON_OUT_PREFIX}.[0-9]* "$SAVEPWD" >/dev/null 2>&1 +fi +cd "$SAVEPWD" + +# this has to be last -- results in a syntax error +# doesn't currently parse because EOF is not on a line by itself -- should it? +(cat <<EOF +still more text in a subshell +EOF) diff --git a/tests/heredoc4.sub b/tests/heredoc4.sub new file mode 100644 index 0000000..381b64a --- /dev/null +++ b/tests/heredoc4.sub @@ -0,0 +1,12 @@ +cat <<EO`true`F +heredoc1 +EO`false`F +EO`true`F +echo Ok:$? + +one=one +four=four +five='fi ve' + +recho $one`echo two three`$four +recho `echo two three`$five diff --git a/tests/herestr.right b/tests/herestr.right new file mode 100644 index 0000000..03f38ed --- /dev/null +++ b/tests/herestr.right @@ -0,0 +1,31 @@ +abcde +yo +hot damn +what a fabulous window treatment +double"quote +onetwothree +first second third +f1 () +{ + cat <<< "abcde"; + cat <<< "yo"; + cat <<< "$a $b"; + cat <<< 'what a fabulous window treatment'; + cat <<< 'double"quote' +} +f2 () +{ + cat <<< onetwothree +} +f3 () +{ + cat <<< "$@" +} +echo $(echo hi) +echo ho +echo off to work we go +declare -a uu=([0]="" [1]="kghfjk" [2]="jkfzuk" [3]=$'i\n') +foo bar +foo bar +qux:::::bax +qux:::::bax diff --git a/tests/herestr.tests b/tests/herestr.tests new file mode 100644 index 0000000..607f85e --- /dev/null +++ b/tests/herestr.tests @@ -0,0 +1,41 @@ +a=hot +b=damn +f1() +{ +cat <<< "abcde" + +cat <<< "yo" + +cat <<< "$a $b" + +cat <<< 'what a fabulous window treatment' + +cat <<< 'double"quote' +} + +f2() +{ +cat <<< onetwothree +} + +f3() +{ +cat <<< "$@" +} + +f1 +f2 +f3 first second third + +typeset -f + +cat <<< 'echo $(echo hi)' + +cat <<< "echo ho" + +cat <<< "echo $(echo off to work we go)" + +IFS="/" read -r -d $'\000' -a uu <<< /kghfjk/jkfzuk/i +declare -p uu + +${THIS_SH} ./herestr1.sub diff --git a/tests/herestr1.sub b/tests/herestr1.sub new file mode 100644 index 0000000..0cf8082 --- /dev/null +++ b/tests/herestr1.sub @@ -0,0 +1,10 @@ +# problems with word splitting unquoted here-strings present since bash-3.2 + +x="foo bar" +cat <<< $x # Word-splitting appears to collapse the run of whitespace +cat <<< "$x" # Whitespace preserved, as with here doc + +x="qux:::::bax" +IFS=':' +cat <<< $x # Word-splitting appears to collapse the run of whitespace +cat <<< "$x" # Whitespace preserved, as with here doc diff --git a/tests/histexp.right b/tests/histexp.right new file mode 100644 index 0000000..9dc592c --- /dev/null +++ b/tests/histexp.right @@ -0,0 +1,242 @@ +echo $BASH_VERSION +./histexp.tests: line 24: history: !!:z: history expansion failed + 1 for i in one two three; do echo $i; done + 2 /bin/sh -c 'echo this is $0' + 3 ls + 4 echo $BASH_VERSION + 1 for i in one two three; do echo $i; done + 2 /bin/sh -c 'echo this is $0' + 3 ls + 4 echo $BASH_VERSION + 5 HISTFILE=$TMPDIR/newhistory + 6 echo line 2 for history +echo line 2 for history +echo line 2 for history +set -H +echo line 2 for history +line 2 for history + 1 for i in one two three; do echo $i; done + 2 /bin/sh -c 'echo this is $0' + 3 ls + 4 echo $BASH_VERSION + 5 HISTFILE=$TMPDIR/newhistory + 6 echo line 2 for history + 7 set -H + 8 echo line 2 for history +a b c d e +echo a b c d e +a b c d e +echo line 2 for history +line 2 for history +echo line 8 for history +line 8 for history +/bin/sh -c 'echo this is $0' +this is /bin/sh +echo sh +sh +echo /bin +/bin +echo e +e +a b c d e +echo b c d e +b c d e +echo b c d +b c d +echo d e +d e +echo d e +d e +echo b c d +b c d +file.c +echo file +file +echo .c +.c +echo 'file' +file +bax.c +echo $file +bax +echo .c +.c +echo '$file' +$file +a b c d e +echo 'a' 'b' 'c' 'd' 'e' +a b c d e +echo 'a b c d e' +a b c d e +foo.c foo.o foo.html foo.h +echo bar.c foo.o foo.html foo.h +bar.c foo.o foo.html foo.h +echo bar.c bar.o bar.html bar.h +bar.c bar.o bar.html bar.h +echo xbar.c xbar.o xbar.html xbar.h +xbar.c xbar.o xbar.html xbar.h +echo xbar.c xbar.o xbar.html xbar.h +xbar.c xbar.o xbar.html xbar.h +echo xwhix.c xwhix.o xwhix.html xwhix.h +xwhix.c xwhix.o xwhix.html xwhix.h +echo xwhix.c xwhix.o xwhix.html xwhix.h +echo 'xwhix' +xwhix +echo 'xwhix.h' +xwhix.h +echo 'xwhix.h' +xwhix.h +echo 'xwhix.h' +xwhix.h + 7 set -H + 8 echo line 2 for history + 9 echo a b c d e + 10 echo line 2 for history + 11 echo line 8 for history + 12 /bin/sh -c 'echo this is $0' + 13 echo sh + 14 echo /bin + 15 echo e + 16 echo a b c d e + 17 echo b c d e + 18 echo b c d + 19 echo d e + 20 echo b c d + 21 echo file.c + 22 echo file + 23 echo .c + 24 echo 'file' + 25 echo $file.c + 26 echo $file + 27 echo .c + 28 echo '$file' + 29 echo a b c d e + 30 echo 'a' 'b' 'c' 'd' 'e' + 31 echo 'a b c d e' + 32 echo foo.c foo.o foo.html foo.h + 33 echo bar.c foo.o foo.html foo.h + 34 echo bar.c bar.o bar.html bar.h + 35 echo xbar.c xbar.o xbar.html xbar.h + 36 echo xwhix.c xwhix.o xwhix.html xwhix.h + 37 echo 'xwhix' + 38 echo 'xwhix.h' +!! +!! +echo '!!' \!\! +!! !! +ok 1 +ok 2 +ok 3 +echo shopt a +shopt a +echo a b c d 2> /dev/null +a b c d +one two three four +echo two ; echo four +one two three four +echo four ; echo two +! +! +! +! +! +! +! +! +! +\! +\! +\! +\! +a +b +c +echo "#!/bin/bash" set -o posix +#!/bin/bash set -o posix +!! +!! +a +echo $(echo echo a) +echo a +a +echo echo a $(echo echo a) +echo a echo a +b +!! $(echo !!) +c +echo "echo c" "$(echo echo c)" +echo c echo c +d +echo "echo d" $(echo "echo d") +echo d echo d +e +!! !! +f +!! +f +!! +g +echo "echo g" +echo g +g +eval echo "echo g" +echo g +h +echo \!\! `echo echo h` +!! echo h +i +echo echo i `echo echo i` +echo i echo i +j +echo `echo j` echo j +j echo j +a +cat < <(echo echo a) +echo a +b +echo echo b `echo echo b` +echo b echo b +c +! +d +! +e +! ! +./histexp4.sub: line 20: !': event not found +/tmp/Step1 +echo /$(echo tmp)/Step1 +/tmp/Step1 +echo /<(echo tmp)/Step1 > /dev/null +/tmp/Step1 +echo $(echo /tmp)/Step1 +/tmp/Step1 +echo <(echo /tmp)/Step1 > /dev/null +/+(one|two|three)/Step1 +echo /+(one|two|three)/Step1 +/+(one|two|three)/Step1 +/*(tmp|dev|usr)/Step1 +echo /*(tmp|dev|usr)/Step1 +/*(tmp|dev|usr)/Step1 ++(/one|/two|/three)/Step1 +echo +(/one|/two|/three)/Step1 ++(/one|/two|/three)/Step1 +*(/tmp|/dev|/usr)/Step1 +echo *(/tmp|/dev|/usr)/Step1 +*(/tmp|/dev|/usr)/Step1 +one + echo echo one +echo one +echo one +echo one + 1 set -o histexpand + 2 echo one + 3 for f in a b c; do echo echo one; done + 4 history +two + echo echo two +echo two +echo two +echo two + 1 echo two + 2 for f in a b c; do echo echo two; done + 3 history diff --git a/tests/histexp.tests b/tests/histexp.tests new file mode 100644 index 0000000..5ae925e --- /dev/null +++ b/tests/histexp.tests @@ -0,0 +1,144 @@ +LC_ALL=C +LANG=C +trap 'rm $TMPDIR/newhistory' 0 + +file=bax +histchars='!^#' # make sure history comment char is set correctly + +unset HISTFILESIZE HISTTIMEFORMAT + +history -c + +HISTFILE=history.list +HISTCONTROL=ignoreboth +HISTIGNORE='&:#*:history*:fc*' +# we will end up exercising the history stifling code as a result +HISTSIZE=32 + +shopt -s cmdhist +set -o history + +history -p '!!' + +# this should result in a failed history expansion error +history -p '!!:z' + +history + +HISTFILE=$TMPDIR/newhistory +history -a + +history -w + +history -s "echo line 2 for history" +history +history -p '!e' +history -p '!!' + +set -H +!! +!e + +history + +echo a b c d e +!?ch? +!-2 +^2^8 + +!2 + +# we're selecting /bin/sh -c ...; we want `sh' +echo !-1:0:t +# we're selecting /bin/sh -c ...; we want `/bin' +echo !-2:0:h +# we're selecting `echo a b c d e'; we want `e' +echo !?d?:5 + +echo a b c d e +echo !-1:2-$ +echo !-2:2-4 +echo !-2:3* +echo !!:* + +echo !?a?:2- + +echo file.c +echo !!:$:r +echo !-2:$:e +echo !-3:$:r:q + +echo $file.c +echo !!:$:r +echo !-2:^:e +echo !-3:$:r:q + +echo a b c d e +echo !!:1-$:x +echo !-2:1-$:q + +echo foo.c foo.o foo.html foo.h +!!:s/foo/bar/ +!-2:gs/foo/bar/ +!!:gs/bar/x&/ +!-2:g& + +# make sure we can use any delimiter in the substitution, not just `/' +!!:gs+bar+whix+ + +!!:p + +# wow +echo !?.o?:%:r:q + +!!:0 !?.h?:%:q +!!:-$ +!:-$ + +history + +# make sure single quotes inhibit history expansion +echo '!!' + +# make sure backslashes can quote the history expansion character +echo \!\! + +# but other expansions on the line should still be processed + +echo '!!' !!:* +history -c +unset HISTFILE + +# make sure that the special bash cases are not history expanded +case p in +[!A-Z]) echo ok 1;; +esac + +var1='ok 2' +var2=var1 + +echo ${!var2} + +# Bash-2.01[.1] fails this test -- it attempts history expansion after the +# history_comment_char +echo ok 3 # !1200 + +# bash versions through bash-4.3 fail this; they make the digit preceding the +# > into a separate word, changing the meaning of the redirection +shopt a b c d 2>/dev/null +echo !shopt-1 + +echo !shopt* + +# make sure a :p modifier anywhere on the line affects all history expansions +echo one two three four +echo !:2:p ; echo !$ +echo one two three four +echo !$ ; echo !:2:p + +${THIS_SH} ./histexp1.sub +${THIS_SH} ./histexp2.sub +${THIS_SH} ./histexp3.sub +${THIS_SH} ./histexp4.sub +${THIS_SH} ./histexp5.sub +${THIS_SH} ./histexp6.sub diff --git a/tests/histexp1.sub b/tests/histexp1.sub new file mode 100644 index 0000000..a5948f1 --- /dev/null +++ b/tests/histexp1.sub @@ -0,0 +1,23 @@ +LC_ALL=C +LANG=C + +set -o history +set -H + +echo '!' +echo "!" +echo ! + +echo "$( echo '!' )" +echo "$( echo "!" )" +echo "$( echo ! )" + +echo $( echo '!' ) +echo $( echo "!" ) +echo $( echo ! ) + +echo "$( echo "\!" )" +echo "\!" + +echo "$( echo '\!' )" +echo '\!' diff --git a/tests/histexp2.sub b/tests/histexp2.sub new file mode 100644 index 0000000..bb5bfda --- /dev/null +++ b/tests/histexp2.sub @@ -0,0 +1,14 @@ +LANG=C LC_ALL=C + +set -o history +echo a +echo b +echo c + +set -o histexpand +set -o posix + +echo "#!/bin/bash" !! + +echo '!!' +echo "!!" diff --git a/tests/histexp3.sub b/tests/histexp3.sub new file mode 100644 index 0000000..495f095 --- /dev/null +++ b/tests/histexp3.sub @@ -0,0 +1,44 @@ +HISTFILE=${TMPDIR}/bashhist-$$ + +set -o history +set -o histexpand + +echo a +echo $(echo !!) + +echo a +echo !! $(echo !!) + +echo b +echo '!!' '$(echo !!)' + +echo c +echo "!!" "$(echo !!)" + +echo d +echo "!!" $(echo "!!") + +echo e +echo '!!' $(echo '!!') + +echo f +echo '!!' +echo f +eval echo '!!' + +echo g +echo "!!" +echo g +eval echo "!!" + +echo h +echo \!\! `echo !!` + +echo i +echo !! `echo !!` + +echo j +echo `echo j` !! + +set +o history +rm -f $HISTFILE # just in case diff --git a/tests/histexp4.sub b/tests/histexp4.sub new file mode 100644 index 0000000..ddc3bb3 --- /dev/null +++ b/tests/histexp4.sub @@ -0,0 +1,23 @@ +HISTFILE=$TMPDIR/bashhist-$$ + +set -o history +set -o histexpand + +echo a +cat < <(echo !!) + +echo b +echo !! `echo !!` + +echo c +echo "$(echo "!" )" + +echo d +echo "$(echo '!' )" + +echo e +echo '!' "!" +echo "'!'" + +set +o history +rm -f $HISTFILE diff --git a/tests/histexp5.sub b/tests/histexp5.sub new file mode 100644 index 0000000..0fe62fe --- /dev/null +++ b/tests/histexp5.sub @@ -0,0 +1,28 @@ +set -o history +set -o histexpand + +# command and process substitutions should be tokenized as a single word +echo /$(echo tmp)/Step1 +echo !:* +echo /<(echo tmp)/Step1 >/dev/null +echo !:* + +# same tests at the beginning of a word +echo $(echo /tmp)/Step1 +echo !:* +echo <(echo /tmp)/Step1 >/dev/null +echo !:* + +# so should shell extended glob patterns +shopt -s extglob + +echo /+(one|two|three)/Step1 +echo !:* +echo /*(tmp|dev|usr)/Step1 +echo !:* + +# same tests at the beginning of a word +echo +(/one|/two|/three)/Step1 +echo !:* +echo *(/tmp|/dev|/usr)/Step1 +echo !:* diff --git a/tests/histexp6.sub b/tests/histexp6.sub new file mode 100644 index 0000000..00610b0 --- /dev/null +++ b/tests/histexp6.sub @@ -0,0 +1,24 @@ +unset HISTIGNORE +HISTFILE=$TMPDIR/bashhist-$$ + +set -o history +set -o histexpand + +echo one + +for f in a b c; do + echo !! +done + +history +history -c + +echo two +for f in a b c; do + echo !-1 +done + +history + +set +o history +rm -f $HISTFILE diff --git a/tests/history.list b/tests/history.list new file mode 100644 index 0000000..2a4c222 --- /dev/null +++ b/tests/history.list @@ -0,0 +1,4 @@ +for i in one two three; do echo $i; done +/bin/sh -c 'echo this is $0' +ls +echo $BASH_VERSION diff --git a/tests/history.right b/tests/history.right new file mode 100644 index 0000000..d83fc71 --- /dev/null +++ b/tests/history.right @@ -0,0 +1,180 @@ +./history.tests: line 4: history: -x: invalid option +history: usage: history [-c] [-d offset] [n] or history -anrw [filename] or history -ps arg [arg...] +./history.tests: line 6: history: cannot use more than one of -anrw +./history.tests: line 9: fc: -v: invalid option +fc: usage: fc [-e ename] [-lnr] [first] [last] or fc -s [pat=rep] [command] + 1 for i in one two three; do echo $i; done + 2 /bin/sh -c 'echo this is $0' + 3 ls + 4 echo $BASH_VERSION +1 for i in one two three; do echo $i; done +2 /bin/sh -c 'echo this is $0' +3 ls +4 echo $BASH_VERSION + for i in one two three; do echo $i; done + /bin/sh -c 'echo this is $0' + ls + echo $BASH_VERSION +4 echo $BASH_VERSION +3 ls +2 /bin/sh -c 'echo this is $0' +1 for i in one two three; do echo $i; done + echo $BASH_VERSION + ls + /bin/sh -c 'echo this is $0' + for i in one two three; do echo $i; done + 1 for i in one two three; do echo $i; done + 2 /bin/sh -c 'echo this is $0' + 3 ls + 4 echo $BASH_VERSION + 5 echo line for history +echo line for history + for i in one two three; do echo $i; done + /bin/sh -c 'echo this is $0' + ls + echo $BASH_VERSION + echo line for history +displaying $HISTFILE after history -a +echo line for history +HISTFILE=$TMPDIR/newhistory + 1 for i in one two three; do echo $i; done + 2 /bin/sh -c 'echo this is $0' + 3 ls + 4 echo $BASH_VERSION + 5 echo line for history + 6 HISTFILE=$TMPDIR/newhistory + 7 echo displaying \$HISTFILE after history -a + 8 cat $HISTFILE +for i in one two three; do echo $i; done +/bin/sh -c 'echo this is $0' +ls +echo $BASH_VERSION +echo line for history +HISTFILE=$TMPDIR/newhistory +echo displaying \$HISTFILE after history -a +cat $HISTFILE + 1 for i in one two three; do echo $i; done + 2 /bin/sh -c 'echo this is $0' + 3 ls + 4 echo $BASH_VERSION + 5 echo line for history + 6 HISTFILE=$TMPDIR/newhistory + 7 echo displaying \$HISTFILE after history -a + 8 cat $HISTFILE + 9 echo line 2 for history +echo line 2 for history +echo line 2 for history + 1 for i in one two three; do echo $i; done + 2 /bin/sh -c 'echo this is $0' + 3 ls + 4 echo $BASH_VERSION + 5 echo line for history + 6 HISTFILE=$TMPDIR/newhistory + 7 echo displaying \$HISTFILE after history -a + 8 cat $HISTFILE + 9 echo line 2 for history + 10 # this should show up as one history entry + 11 for x in one two three; do :; done +set -H +echo line 2 for history +line 2 for history +4 echo $BASH_VERSION +5 echo line for history +6 HISTFILE=$TMPDIR/newhistory +7 echo displaying \$HISTFILE after history -a +8 cat $HISTFILE +9 echo line 2 for history +10 # this should show up as one history entry +11 for x in one two three; do :; done +12 # just a basic test. a full test suite for history expansion should be +13 # created +14 set -H +15 echo line 2 for history +16 unset HISTSIZE +17 unset HISTFILE +4 echo $BASH_VERSION +5 echo line for history +6 HISTFILE=$TMPDIR/newhistory +7 echo displaying \$HISTFILE after history -a +8 cat $HISTFILE +./history.tests: line 76: fc: history specification out of range + 14 set -H + 15 echo line 2 for history + 16 unset HISTSIZE + 17 unset HISTFILE +aa ab ac +echo xx xb xc +xx xb xc +echo 44 48 4c +44 48 4c +./history.tests: line 91: fc: no command found +aa +bb +cc +echo cc +echo cc +cc +aa +bb +cc +echo cc +echo cc +cc +1 +one +two +three + 1 cat <<! +one +two +three +! + + 2 history +cat <<! +one +two +three +! + +one +two +three +5.0 +echo ${BASH_VERSION%\.*} +5.0 + echo ${BASH_VERSION%\.*} +a +b +c +d +e + 1 echo a + 2 echo b + 3 echo c + 4 echo d + 5 echo e + + 1 echo a + 2 echo e +f +g +h +i + 1 echo a + 2 echo e + 3 echo f + 4 echo g + 5 echo h + +./history3.sub: line 27: history: 16: history position out of range +./history3.sub: line 28: history: 200: history position out of range +./history3.sub: line 29: history: -20: history position out of range +./history3.sub: line 30: history: -50: history position out of range +./history3.sub: line 31: history: 5-0xaf: history position out of range + 1 echo a + 2 echo e + 3 echo f + 4 echo g + 5 echo h + diff --git a/tests/history.tests b/tests/history.tests new file mode 100644 index 0000000..4001bd6 --- /dev/null +++ b/tests/history.tests @@ -0,0 +1,116 @@ +trap 'rm $TMPDIR/newhistory' 0 + +# bad options +history -x +# cannot use -r and -w at the same time +history -r -w /dev/null + +# bad option +fc -v + +unset HISTFILESIZE + +# all of these should result in an empty history list +history -c +history -r /dev/null +history -n /dev/null +history -c + +HISTFILE=history.list +HISTCONTROL=ignoreboth +HISTIGNORE='&:history*:fc*' +HISTSIZE=32 +export HISTIGNORE + +shopt -s cmdhist +set -o history + +history + +fc -l +fc -nl + +fc -lr +fc -nlr + +history -s "echo line for history" +history + +history -p '!!' + +fc -nl + +HISTFILE=$TMPDIR/newhistory +history -a +echo displaying \$HISTFILE after history -a +cat $HISTFILE + +history +history -w +cat $HISTFILE + +history -s "echo line 2 for history" +history +history -p '!e' +history -p '!!' + +# this should show up as one history entry +for x in one two three +do + : +done +history + +# just a basic test. a full test suite for history expansion should be +# created +set -H +!! +!e + +unset HISTSIZE +unset HISTFILE + +fc -l 4 +fc -l 4 8 + +fc -l one=two three=four 502 + +history 4 + +shopt -so history +shopt -s expand_aliases + +alias r="fc -s" + +echo aa ab ac + +r a=x +r x=4 b=8 + +# this had better fail with `no command found' +r cc + +unalias -a +alias + +# these two blocks had better both result in the same output +echo aa +echo bb +echo cc +fc -e cat + +echo aa +echo bb +echo cc +fc -e cat -1 + +set +o history + +shopt -q -o history +echo $? + +${THIS_SH} ./history1.sub +rm -f $TMPDIR/foohist-* + +${THIS_SH} ./history2.sub +${THIS_SH} ./history3.sub diff --git a/tests/history1.sub b/tests/history1.sub new file mode 100644 index 0000000..091b1ed --- /dev/null +++ b/tests/history1.sub @@ -0,0 +1,15 @@ +trap 'rm -f $HISTFILE' 0 1 2 3 6 15 + +HISTFILE=$TMPDIR/foohist-$$ +unset HISTIGNORE HISTCONTROL +set -o history + +history -c +cat <<! +one +two +three +! + +history +fc -s cat diff --git a/tests/history2.sub b/tests/history2.sub new file mode 100644 index 0000000..1a8e78c --- /dev/null +++ b/tests/history2.sub @@ -0,0 +1,10 @@ +set -o history +HISTSIZE=256 +HISTFILE=/dev/null + +# these two lines should be the same +echo ${BASH_VERSION%\.*} +echo $(fc -nl -1) + +echo ${BASH_VERSION%\.*} +fc -nl -1 diff --git a/tests/history3.sub b/tests/history3.sub new file mode 100644 index 0000000..8722666 --- /dev/null +++ b/tests/history3.sub @@ -0,0 +1,36 @@ +: ${TMPDIR:=/tmp} + +set -o history +HISTFILE=$TMPDIR/history-$$ + +history -c + +echo a +echo b +echo c +echo d +echo e + +history ; echo + +history -d 2-4 + +history + +echo f +echo g +echo h +echo i +history -d 6--1 +history ; echo + +history -d 16-40 +history -d 1-200 +history -d -20-50 +history -d 1--50 +history -d 5-0xaf + +history ; echo + +unset HISTFILE +exit 0 diff --git a/tests/ifs-posix.right b/tests/ifs-posix.right new file mode 100644 index 0000000..f3bdccc --- /dev/null +++ b/tests/ifs-posix.right @@ -0,0 +1 @@ +# tests 6856 passed 6856 failed 0 diff --git a/tests/ifs-posix.tests b/tests/ifs-posix.tests new file mode 100644 index 0000000..cf9a898 --- /dev/null +++ b/tests/ifs-posix.tests @@ -0,0 +1,257 @@ +# Usage: $SHELL ifs.sh +# +# This script generates 6856 tests for the set(1) and read(1) +# builtins w.r.t. IFS whitespace and non-whitespace characters. +# Each failed test produces one line on the standard output that +# contains the test along with the expected and actual results. +# The last output line contains the test result counts. ordered>0 +# are the number of tests where IFS=": " produced different results +# than IFS=" :". If a test fails the same way for IFS=": " and +# IFS=" :" then the second output line is suppressed. + +TESTS=6856 + +ksh_read=0 +echo 1 | read ksh_read +ksh_arith=0 +eval '((ksh_arith+=1))' 2>/dev/null + +failed=0 +ordered=0 +passed=0 + +split() +{ + i=$1 s=$2 r=$3 S='' R='' + for ifs in ': ' ' :' + do IFS=$ifs + set x $i + shift + IFS=' ' + g="[$#]" + while : + do case $# in + 0) break ;; + esac + g="$g($1)" + shift + done + case $g in + "$s") case $ksh_arith in + 1) ((passed+=1)) ;; + *) passed=`expr $passed + 1` ;; + esac + case $S in + '') S=$g + ;; + "$g") ;; + *) case $ksh_arith in + 1) ((ordered+=1)) ;; + *) ordered=`expr $ordered + 1` ;; + esac + ;; + esac + ;; + "$S") case $ksh_arith in + 1) ((failed+=1)) ;; + *) failed=`expr $failed + 1` ;; + esac + ;; + *) case $ksh_arith in + 1) ((failed+=1)) ;; + *) failed=`expr $failed + 1` ;; + esac + case $s in + "$S") ;; + ?0*) echo "IFS=\"$ifs\"; x=\"$i\"; set x \$x; shift; echo \"[\$#]\" # expected \"$s\" got \"$g\"" ;; + ?1*) echo "IFS=\"$ifs\"; x=\"$i\"; set x \$x; shift; echo \"[\$#](\$1)\" # expected \"$s\" got \"$g\"" ;; + ?2*) echo "IFS=\"$ifs\"; x=\"$i\"; set x \$x; shift; echo \"[\$#](\$1)(\$2)\" # expected \"$s\" got \"$g\"" ;; + ?3*) echo "IFS=\"$ifs\"; x=\"$i\"; set x \$x; shift; echo \"[\$#](\$1)(\$2)(\$3)\" # expected \"$s\" got \"$g\"" ;; + *) echo TEST ERROR i="'$i'" s="'$s'" ;; + esac + case $S in + '') S=$g + ;; + "$g") ;; + *) case $ksh_arith in + 1) ((ordered+=1)) ;; + *) ordered=`expr $ordered + 1` ;; + esac + ;; + esac + esac + case $ksh_read in + 1) echo "$i" | IFS=$ifs read x y; g="($x)($y)" ;; + *) g=`export ifs; echo "$i" | ( IFS=$ifs; read x y; echo "($x)($y)" )` ;; + esac + case $g in + "$r") case $ksh_arith in + 1) ((passed+=1)) ;; + *) passed=`expr $passed + 1` ;; + esac + case $R in + '') R=$g + ;; + "$g") ;; + *) case $ksh_arith in + 1) ((ordered+=1)) ;; + *) ordered=`expr $ordered + 1` ;; + esac + ;; + esac + ;; + "$R") case $ksh_arith in + 1) ((failed+=1)) ;; + *) failed=`expr $failed + 1` ;; + esac + ;; + *) case $ksh_arith in + 1) ((failed+=1)) ;; + *) failed=`expr $failed + 1` ;; + esac + case $r in + "$R") ;; + *) echo "echo \"$i\" | ( IFS=\"$ifs\" read x y; echo \"(\$x)(\$y)\" ) # expected \"$r\" got \"$g\"" ;; + esac + case $R in + '') R=$g + ;; + "$g") ;; + *) case $ksh_arith in + 1) ((ordered+=1)) ;; + *) ordered=`expr $ordered + 1` ;; + esac + ;; + esac + ;; + esac + done +} + +for str in \ + '-' \ + 'a' \ + '- -' \ + '- a' \ + 'a -' \ + 'a b' \ + '- - -' \ + '- - a' \ + '- a -' \ + '- a b' \ + 'a - -' \ + 'a - b' \ + 'a b -' \ + 'a b c' \ + +do + IFS=' ' + set x $str + + shift + case $# in + 0) continue ;; + esac + + f1=$1 + case $f1 in + '-') f1='' ;; + esac + + shift + case $# in + 0) for d0 in '' ' ' + do + for d1 in '' ' ' ':' ' :' ': ' ' : ' + do + case $f1$d1 in + '') split "$d0$f1$d1" "[0]" "()()" ;; + ' ') ;; + *) split "$d0$f1$d1" "[1]($f1)" "($f1)()" ;; + esac + done + done + continue + ;; + esac + f2=$1 + case $f2 in + '-') f2='' ;; + esac + + shift + case $# in + 0) for d0 in '' ' ' + do + for d1 in ' ' ':' ' :' ': ' ' : ' + do + case ' ' in + $f1$d1|$d1$f2) continue ;; + esac + for d2 in '' ' ' ':' ' :' ': ' ' : ' + do + case $f2$d2 in + '') split "$d0$f1$d1$f2$d2" "[1]($f1)" "($f1)()" ;; + ' ') ;; + *) split "$d0$f1$d1$f2$d2" "[2]($f1)($f2)" "($f1)($f2)" ;; + esac + done + done + done + continue + ;; + esac + f3=$1 + case $f3 in + '-') f3='' ;; + esac + + shift + case $# in + 0) for d0 in '' ' ' + do + for d1 in ':' ' :' ': ' ' : ' + do + case ' ' in + $f1$d1|$d1$f2) continue ;; + esac + for d2 in ' ' ':' ' :' ': ' ' : ' + do + case $f2$d2 in + ' ') continue ;; + esac + case ' ' in + $f2$d2|$d2$f3) continue ;; + esac + for d3 in '' ' ' ':' ' :' ': ' ' : ' + do + case $f3$d3 in + '') split "$d0$f1$d1$f2$d2$f3$d3" "[2]($f1)($f2)" "($f1)($f2)" ;; + ' ') ;; + *) x=$f2$d2$f3$d3 + x=${x#' '} + x=${x%' '} + split "$d0$f1$d1$f2$d2$f3$d3" "[3]($f1)($f2)($f3)" "($f1)($x)" + ;; + esac + done + done + done + done + continue + ;; + esac +done +case $ksh_arith in +1) ((tests=passed+failed)) ;; +*) tests=`expr $passed + $failed` ;; +esac +case $ordered in +0) ordered="" ;; +*) ordered=" ordered $ordered" ;; +esac +case $tests in +$TESTS) fatal="" ;; +*) fatal=" -- fundamental IFS error -- $TESTS tests expected" +esac +echo "# tests $tests passed $passed failed $failed$ordered$fatal" diff --git a/tests/ifs.right b/tests/ifs.right new file mode 100644 index 0000000..465efcf --- /dev/null +++ b/tests/ifs.right @@ -0,0 +1,12 @@ +a:b:c +a:b:c +a:b:c +a b c d e +a:b:c:d:e +a b c d e +a:b:c:d:e +a:b:c:d:e +a b c d e +a b c d e +argv[1] = <file> +argv[1] = <*> diff --git a/tests/ifs.tests b/tests/ifs.tests new file mode 100644 index 0000000..7176900 --- /dev/null +++ b/tests/ifs.tests @@ -0,0 +1,63 @@ +OIFS="$IFS" +IFS=":$IFS" +eval foo="a:b:c" +IFS="$OIFS" +echo $foo + +OIFS=$IFS +IFS=":$IFS" +foo=$(echo a:b:c) +IFS=$OIFS + +for i in $foo +do + echo $i +done + +OIFS=$IFS +IFS=":$IFS" +foo=`echo a:b:c` +IFS=$OIFS + +for i in $foo +do + echo $i +done + +DEFIFS=$' \t\n' + +# local copy of IFS that shadows global version +function f +{ + typeset IFS=: + + echo $1 +} + +function ff +{ + echo $1 +} + +f a:b:c:d:e +x=a:b:c:d:e +echo $x + +IFS=: ff a:b:c:d:e +echo $x + +# doesn't get word split +IFS=$DEFIFS +# variable assignment doesn't use new value for word splitting +IFS=: echo $x +# but does this time because of the eval +IFS=: eval echo \$x + +# in posix mode, assignments preceding special builtins and functions are global +set -o posix +IFS=: export x +echo $x + +IFS="$DEFIFS" + +${THIS_SH} ./ifs1.sub diff --git a/tests/ifs1.sub b/tests/ifs1.sub new file mode 100644 index 0000000..6ea489a --- /dev/null +++ b/tests/ifs1.sub @@ -0,0 +1,14 @@ +: ${TMPDIR:=/tmp} +dir=bashtest-$$ + +mkdir $TMPDIR/$dir || exit 1 +touch $TMPDIR/$dir/file || exit 2 +cd $TMPDIR/$dir || exit 3 + +IFS='?*[]' +recho * + +recho "*" + +cd $OLDPWD +rm -rf $TMPDIR/$dir diff --git a/tests/input-line.sh b/tests/input-line.sh new file mode 100644 index 0000000..3f66c81 --- /dev/null +++ b/tests/input-line.sh @@ -0,0 +1,4 @@ +echo before calling input-line.sub +${THIS_SH} ./input-line.sub +this line for input-line.sub +echo finished with input-line.sub diff --git a/tests/input-line.sub b/tests/input-line.sub new file mode 100644 index 0000000..7bc8df2 --- /dev/null +++ b/tests/input-line.sub @@ -0,0 +1,2 @@ +read line +echo line read by $0 was \`$line\' diff --git a/tests/input.right b/tests/input.right new file mode 100644 index 0000000..8733feb --- /dev/null +++ b/tests/input.right @@ -0,0 +1,3 @@ +before calling input-line.sub +line read by ./input-line.sub was `this line for input-line.sub' +finished with input-line.sub diff --git a/tests/intl.right b/tests/intl.right new file mode 100644 index 0000000..7da9919 --- /dev/null +++ b/tests/intl.right @@ -0,0 +1,57 @@ +é +1 +AéB +B +B +ok 1 +ok 2 +aéb +0000000 141 303 251 142 +0000004 +-абвгдежзиклмноп - 16 +-абвгдежзиклмноп- 15 +-абвгд- 5 +1,0000 +1.0000 +1.0000 +1.0000 +1.0000 +1,0000 +1 +bytematch +0000000 254 012 +0000002 +Passed all 1378 Unicode tests +0000000 303 277 012 +0000003 +0000000 303 277 012 +0000003 +0000000 303 277 012 +0000003 +0000000 303 277 012 +0000003 +0000000 357 277 277 012 +0000004 +0000000 357 277 277 012 +0000004 +0000000 012 +0000001 +0000000 012 +0000001 +0000000 012 +0000001 +0000000 012 +0000001 +0000000 303 277 012 +0000003 +0000000 303 277 012 +0000003 +0000000 303 277 012 +0000003 +0000000 101 040 302 243 040 305 222 012 +0000010 +./unicode3.sub: line 5: $'5\247@3\231+\306S8\237\242\352\263': command not found +./unicode3.sub: line 7: cd: $'5\247@3\231+\306S8\237\242\352\263': No such file or directory +$'5\247@3\231+\306S8\237\242\352\263' ++ : $'5\247@3\231+\306S8\237\242\352\263' ++ set +x diff --git a/tests/intl.tests b/tests/intl.tests new file mode 100644 index 0000000..5c15b47 --- /dev/null +++ b/tests/intl.tests @@ -0,0 +1,55 @@ +export LC_ALL=en_US.UTF-8 + +a=$'\303\251' + +echo "$a" + +echo ${#a} + +b=$'A\303\251B' + +echo "$b" + +echo ${b: -1} + +c=AeB + +echo ${c: -1} + +unset a +a=$(printf '%b' 'A\303\251B') +IFS=$(printf '%b' '\303\251') + +case "$a" in +"A${IFS}B") echo ok 1 ;; +*) echo bad 1 ;; +esac + +set $a + +case $1 in +A) echo ok 2 ;; +*) echo bad 2 ;; +esac + +set a b + +printf '%s\n' "$*" + +. ./test-glue-functions + +printf '%s' "$*" | od -b | _intl_normalize_spaces + +# display differences make this problematic +${THIS_SH} ./intl1.sub + +# this tests both international handling in printf and temporary environments +${THIS_SH} ./intl2.sub + +# test splitting on characters instead of bytes +${THIS_SH} ./intl3.sub + +${THIS_SH} ./unicode1.sub 2>/dev/null +${THIS_SH} ./unicode2.sub + +${THIS_SH} ./unicode3.sub 2>&1 diff --git a/tests/intl1.sub b/tests/intl1.sub new file mode 100644 index 0000000..a03648f --- /dev/null +++ b/tests/intl1.sub @@ -0,0 +1,11 @@ +LC_ALL=en_US.UTF-8 +LANG=en_US.UTF-8 + +var='абвгдежзиклмноп ' +echo -"$var"- ${#var} + +read foo <<< "$var" +echo -"$foo"- ${#foo} + +read -n 5 foo <<< "$var" +echo -"$foo"- ${#foo} diff --git a/tests/intl2.sub b/tests/intl2.sub new file mode 100644 index 0000000..64961bc --- /dev/null +++ b/tests/intl2.sub @@ -0,0 +1,11 @@ +unset LC_ALL LC_NUMERIC +export LANG=de_DE.UTF-8 +printf '%.4f\n' 1 + +LANG=C printf '%.4f\n' 1 +LANG=C /usr/bin/printf '%.4f\n' 1 + +env LANG=C printf '%.4f\n' 1 +(LANG=C; printf '%.4f\n' 1) + +printf '%.4f\n' 1 diff --git a/tests/intl3.sub b/tests/intl3.sub new file mode 100644 index 0000000..650000e --- /dev/null +++ b/tests/intl3.sub @@ -0,0 +1,23 @@ +. ./test-glue-functions + +# more tests to make sure that IFS splits on characters, not bytes +export LANG=en_US.UTF-8 + +euro=$'\342\202\254' +o342=$'\342' +o202=$'\202' +o254=$'\254' + +IFS=$o254 +t=+$euro+ +set -- $t + +echo "$#" + +# but matching still occurs on bytes if we don't have a valid multibyte char +case $euro in +*$o202*) echo bytematch ;; +*) echo mbchar match ;; +esac + +echo "${euro##*$o202}" | od -b | _intl_normalize_spaces diff --git a/tests/invert.right b/tests/invert.right new file mode 100644 index 0000000..5a9239a --- /dev/null +++ b/tests/invert.right @@ -0,0 +1,10 @@ +1 +1 +1 +0 +0 +1 +0 +1 +0 +1 diff --git a/tests/invert.tests b/tests/invert.tests new file mode 100644 index 0000000..8393d95 --- /dev/null +++ b/tests/invert.tests @@ -0,0 +1,19 @@ +# tests of return value inversion +# placeholder for future expansion + +# user subshells (...) did this wrong in bash versions before 2.04 + +! ( echo hello | grep h >/dev/null 2>&1 ); echo $? +! echo hello | grep h >/dev/null 2>&1 ; echo $? + +! true ; echo $? +! false; echo $? + +! (false) ; echo $? +! (true); echo $? + +! true | false ; echo $? +! false | true ; echo $? + +! (true | false) ; echo $? +! (false | true) ; echo $? diff --git a/tests/iquote.right b/tests/iquote.right new file mode 100644 index 0000000..9476128 --- /dev/null +++ b/tests/iquote.right @@ -0,0 +1,92 @@ +argv[1] = <xxxyyy> +argv[1] = <xxx^?yyy> +argv[1] = <xy> +argv[1] = <x^?y> +argv[1] = <--> +argv[1] = <-^?-> +argv[1] = <> +argv[1] = <> +argv[1] = <^?> +argv[1] = <^?yy> +0x7f +0x7f +0x7f +argv[1] = <^?> +argv[1] = <^?@> +argv[1] = <@^?@> +argv[1] = <@^?> +argv[1] = <^?> +argv[1] = <^?@> +argv[1] = <@^?@> +argv[1] = <@^?> +argv[1] = <1> +argv[2] = <^?> +argv[3] = <^?> +argv[1] = <2> +argv[2] = <^?a> +argv[3] = <^?a> +argv[1] = <2> +argv[2] = <^?a> +argv[3] = <^?a> +argv[1] = <3> +argv[2] = <^?aa> +argv[3] = <^?aa> +argv[1] = <> +argv[1] = <--> +argv[1] = <--> +argv[1] = <^?> +argv[1] = <-^?-> +argv[1] = <^?> +argv[1] = <-^?-> +ok +argv[1] = <aaa^?bbb> +argv[1] = <ccc^?ddd> +argv[1] = <eee^?fff> +argv[1] = <ggg^?hhh> +argv[1] = <aaabbb> +argv[1] = <cccddd> +argv[1] = <eeefff> +argv[1] = <ggghhh> +argv[1] = <aaa^?bbb> +argv[1] = <ccc^?ddd> +argv[1] = <eee^?fff> +argv[1] = <ggg^?hhh> +argv[1] = <aaabbb> +argv[1] = <cccddd> +argv[1] = <eeefff> +argv[1] = <ggghhh> +argv[1] = <aaa^?bbb> +argv[1] = <ccc^?ddd> +argv[1] = <eee^?fff> +argv[1] = <ggg^?hhh> +argv[1] = <xy> +argv[1] = <xy> +argv[1] = <xy> +argv[1] = <x^?y> +argv[1] = <> +argv[1] = <> +argv[1] = <> +argv[1] = <> +argv[1] = <> +argv[1] = <> +argv[1] = <^?> +argv[1] = <^? > +argv[1] = < ^?> +argv[1] = < ^?> +argv[1] = < ^?> +argv[1] = < ^?> +argv[1] = < ^?> +argv[1] = < ^?> +argv[1] = < ^?> +argv[1] = < ^?> +argv[1] = < ^?> +argv[1] = < ^?x> +argv[1] = < ^?> +argv[1] = < ^?> +argv[1] = < ^?> +argv[1] = < ^?x> +argv[1] = <^?x> +argv[1] = <^?> +argv[1] = < ^? x> +argv[1] = <^? x> +argv[1] = <^? > diff --git a/tests/iquote.tests b/tests/iquote.tests new file mode 100644 index 0000000..a1e6362 --- /dev/null +++ b/tests/iquote.tests @@ -0,0 +1,145 @@ +# bug in bash up to and including bash-3.0 (including patches) +# +# problem is conflict between CTLNUL used internally to denote quoted null +# characters and its value (0x7f) appearing in the expansion of a variable +# +unset x +recho "xxx${x}yyy" + +y=$'\177' +recho "xxx${y}yyy" + +unset y + +unset undef + +set "" +recho ${undef-"x$*y"} + +set $'\177' +recho ${undef-"x$*y"} + +shift $# + +f() +{ + recho "-${*-x}-" +} + +f '' +f $'\177' + +unset -f f + +x=12345 + +recho "${x:6:1}" + +x= +recho "${x:0:1}" + +y=$'\177' +recho "${y:0:1}" + +y=xxx$'\177'yyy +recho "${y:3:3}" + +unset x y + +eval tmp=`printf "$'\\\\\x%x'\n" 127` +printf "%#1x\n" "'$tmp" + +x=$'\177' +printf "%#1x\n" "'$x" + +a=127 +eval c=\$\'\\$(printf '%o' $a)\' +printf "%#1x\n" "'$c" + +recho "$c" +recho "$c"@ +recho @"$c"@ +recho @"$c" + +recho "$c" +recho "$c@" +recho "@$c@" +recho "@$c" + +unset tmp x a c + +qtest() +{ + recho ${#q} "${q}" ${q} +} + +q=$'\x7f' +qtest + +q=${q}a +qtest + +q=$'\x7fa' +qtest + +q="${q}a" +qtest + +unset -f qtest +unset q + +set -- '' +recho "${*:1}" +recho ${*:1} +recho -${*:1}- +recho -"${*:1}"- + +set $'\177' +recho "${*:1}" +recho "-${*:1}-" + +recho ${*:1} +recho -${*:1}- + +shift $# + +DEL=`awk 'END{printf("%c", 0+127)}' </dev/null` +T1=a\ $DEL +T2="a $DEL" +set -- x $(echo $T1|wc -c) $(echo $T2|wc -c); shift +L1=$1; L2=$2 +case "$L1/$L2" in +4/4) echo ok;; +*) echo CTLNUL bug: L1=$L1, L2=$L2;; +esac + +x=$'\177' +recho "aaa${x}bbb" +recho ccc"${x}"ddd +recho eee"$x"fff +recho ggg"$(echo $x)"hhh + +x= +recho "aaa${x}bbb" +recho ccc"${x}"ddd +recho eee"$x"fff +recho ggg"$(echo $x)"hhh + +set -- $'\177' +recho "aaa${1}bbb" +recho ccc"${1}"ddd +recho eee"$1"fff +recho ggg"$(echo $1)"hhh + +set -- "" +recho "aaa${1}bbb" +recho ccc"${1}"ddd +recho eee"$1"fff +recho ggg"$(echo $1)"hhh + +recho aaa$'\177'bbb +recho ccc""ddd +recho "eeefff" +recho ggg"$(echo $'\177')"hhh + +${THIS_SH} ./iquote1.sub diff --git a/tests/iquote1.sub b/tests/iquote1.sub new file mode 100644 index 0000000..1a8a35c --- /dev/null +++ b/tests/iquote1.sub @@ -0,0 +1,43 @@ +# Problems with variables that expand to 0x7f and quoted nulls in the same +# expansion -- affects bash versions 4.0-post 4.2 +a=x +b= +del=$'\x7f' + +set "" + +recho ${undef-"x$*y"} +recho "x$*y" +recho x"$*"y +recho x"$del"y + +recho ${undef-"$@"} +recho "$@" +recho "${@}" +recho ${undef-"$*"} +recho "$*" +recho "${*}" + +recho "$del${a#x}" +recho "$del ${a#x}" +recho " $del${a#x}" + +recho " $del$b" +recho " $del${b}" +recho " $del${b#x}" +recho " $del${a#x}" + +recho " $del${a%x}" +recho " $del${a:0:0}" +recho " $del"${a:0:0} +recho " $del""${a:0:0}" +recho " $del${a}" +recho " $del" +recho " ${del}${a:0:0}" +recho " ${del:0:1}${a:0:0}" +recho " ${del:0:1}${a}" +recho "${del:0:1}${a#d}" +recho "${del:0:1}${a#x}" +recho " ${del:0:1} ${a}" +recho "${del:0:1} ${a#d}" +recho "${del:0:1} ${a#x}" diff --git a/tests/jobs.right b/tests/jobs.right new file mode 100644 index 0000000..0e9d1d1 --- /dev/null +++ b/tests/jobs.right @@ -0,0 +1,109 @@ +./jobs2.sub: line 9: fg: job 1 started without job control +fg: 1 +Waiting for job 0 +job 0 returns 0 +Waiting for job 1 +job 1 returns 0 +Waiting for job 2 +job 2 returns 0 +Waiting for job 3 +job 3 returns 0 +Waiting for job 4 +job 4 returns 0 +Waiting for job 5 +job 5 returns 0 +Waiting for job 6 +job 6 returns 0 +Waiting for job 7 +job 7 returns 0 +[1] Running sleep 2 & +[2] Running sleep 2 & +[3] Running sleep 2 & +[4]- Running sleep 2 & +[5]+ Running ( sleep 2; exit 4 ) & +4 +0 +i killed it +12 +[1]- Running sleep 20 & +[3]+ Running sleep 20 & +child1 exit status 0 +0 +./jobs.tests: line 25: wait: %1: no such job +./jobs.tests: line 30: fg: no job control +wait-for-pid +wait-errors +./jobs.tests: line 43: wait: `1-1': not a pid or valid job spec +./jobs.tests: line 44: wait: `-4': not a pid or valid job spec +wait-for-background-pids +async list wait-for-background-pids +async list wait for child +forked +wait-when-no-children +wait-for-job +./jobs.tests: line 66: wait: %2: no such job +127 +async list wait-for-job +forked +fg-bg 1 +sleep 5 +fg-bg 2 +sleep 5 +fg-bg 3 +sleep 5 +fg-bg 4 +sleep 5 +fg-bg 5 +./jobs.tests: line 93: fg: %2: no such job +./jobs.tests: line 94: bg: job 1 already in background +fg-bg 6 +./jobs.tests: line 101: fg: -s: invalid option +fg: usage: fg [job_spec] +./jobs.tests: line 102: bg: -s: invalid option +bg: usage: bg [job_spec ...] +./jobs.tests: line 107: disown: -s: invalid option +disown: usage: disown [-h] [-ar] [jobspec ... | pid ...] +./jobs.tests: line 111: disown: %1: no such job +./jobs.tests: line 114: disown: %2: no such job +wait-for-non-child +./jobs.tests: line 117: wait: pid 1 is not a child of this shell +127 +3 -- 1 2 3 -- 1 - 2 - 3 +[1] Running sleep 300 & +[2]- Running sleep 350 & +[3]+ Running sleep 400 & +running jobs: +[1] Running sleep 300 & +[2]- Running sleep 350 & +[3]+ Running sleep 400 & +./jobs.tests: line 134: kill: %4: no such job +./jobs.tests: line 136: jobs: %4: no such job +current job: +[3]+ Running sleep 400 & +previous job: +[2]- Running sleep 350 & +after kill -STOP +running jobs: +[1] Running sleep 300 & +[3]- Running sleep 400 & +stopped jobs: +[2]+ Stopped sleep 350 +after disown +[2]+ Stopped sleep 350 +[3]- Running sleep 400 & +running jobs: +[3]- Running sleep 400 & +stopped jobs: +[2]+ Stopped sleep 350 +after kill -s CONT +running jobs: +[2]+ Running sleep 350 & +[3]- Running sleep 400 & +stopped jobs: +after kill -STOP, backgrounding %3: +[3]+ sleep 400 & +killing... +done +after KILL -STOP, foregrounding %1 +sleep 10 +done diff --git a/tests/jobs.tests b/tests/jobs.tests new file mode 100644 index 0000000..3c2eef3 --- /dev/null +++ b/tests/jobs.tests @@ -0,0 +1,191 @@ +# test out %+, jobs -p, and $! agreement in a subshell first +${THIS_SH} ./jobs1.sub + +# test out fg/bg failure in a subshell +${THIS_SH} ./jobs2.sub + +# test out behavior of waiting for background pids -- bug in versions +# before 2.03 +${THIS_SH} ./jobs3.sub + +# test out behavior of using job control notation when job control is not +# active +${THIS_SH} ./jobs4.sub + +# test out wait -n framework +${THIS_SH} ./jobs5.sub + +# test out wait -f framework +${THIS_SH} ./jobs6.sub + +jobs +echo $? + +# a no-such-job error, since we can use job control notation without job control +wait %1 + +# make sure we can't fg a job started when job control was not active +sleep 30 & +pid=$! +fg %1 +# make sure the killed processes don't cause a message +exec 5>&2 +exec 2>/dev/null +kill -n 9 $pid +wait # make sure we reap the processes while stderr is still redirected +exec 2>&5 + +echo wait-for-pid +sleep 10 & +wait $! + +echo wait-errors +wait 1-1 +wait -- -4 + +echo wait-for-background-pids +sleep 5 & +sleep 8 & +wait + +echo async list wait-for-background-pids +sleep 5 & sleep 8 & +wait + +echo async list wait for child +sleep 5 & echo forked +wait + +echo wait-when-no-children +wait + +set -m + +echo wait-for-job +sleep 5 & +wait %2 # this should be a no-such-job error +echo $? +wait %1 + +echo async list wait-for-job +sleep 5 & echo forked +wait %1 + +echo fg-bg 1 +sleep 5 & +%1 + +echo fg-bg 2 +sleep 5 & +fg %% + +echo fg-bg 3 +sleep 5 & +fg %s + +echo fg-bg 4 +sleep 5 & +fg %?ee + +# these next two are error cases +echo fg-bg 5 +sleep 15 & +fg %2 # this should be a no-such-job error +bg %1 # this should be a `bg background job?' error +wait + +# these may someday mean to start the jobs, but not print the line +# describing the status, but for now they are errors +echo fg-bg 6 +sleep 5 & +fg -s %1 +bg -s %1 +wait + +# someday this may mean to disown all stopped jobs, but for now it is +# an error +disown -s + +# this is an error -- the job with the pid that is the value of $! is +# retained only until a `wait' is performed +disown %1 + +# this, however, is an error +disown %2 + +echo wait-for-non-child +wait 1 +echo $? + +exit 1 | exit 2 | exit 3 +echo $? -- ${PIPESTATUS[@]} -- ${PIPESTATUS[0]} - ${PIPESTATUS[1]} - ${PIPESTATUS[2]} + +sleep 300 & +sleep300pid=$! +sleep 350 & +sleep 400 & + +jobs + +echo running jobs: +jobs -r + +# should be an error +kill -n 1 %4 +# should be an error +jobs %4 +echo current job: +jobs %+ +echo previous job: +jobs %- + +kill -STOP %2 +sleep 5 # give time for the shell to get the stop notification +echo after kill -STOP +echo running jobs: +jobs -r +echo stopped jobs: +jobs -s + +disown %1 + +echo after disown +jobs +echo running jobs: +jobs -r +echo stopped jobs: +jobs -s + +kill -s CONT %2 +echo after kill -s CONT +echo running jobs: +jobs -r +echo stopped jobs: +jobs -s + +kill -STOP %3 +sleep 5 # give time for the shell to get the stop notification +echo after kill -STOP, backgrounding %3: +bg %3 + +disown -h %2 + +# make sure the killed processes don't cause a message +exec 5>&2 +exec 2>/dev/null + +echo killing... +kill -n 9 $sleep300pid +kill -n 9 %2 %3 +wait # make sure we reap the processes while stderr is still redirected +echo done + +exec 2>&5 + +sleep 10 & +kill -STOP %1 +sleep 5 # give time for the shell to get the stop notification +echo after KILL -STOP, foregrounding %1 +fg %1 + +echo done diff --git a/tests/jobs1.sub b/tests/jobs1.sub new file mode 100644 index 0000000..53f66cc --- /dev/null +++ b/tests/jobs1.sub @@ -0,0 +1,17 @@ +# make sure that jobs -p, %+, and $! all agree +set -m +sleep 60 & + +FN=$TMPDIR/jobs-pid.$$ + +pid1=$! +jobs -p %+ > $FN +pid2=$(< $FN) +rm $FN + +if [ $pid1 -ne $pid2 ]; then + echo 'oops - $! and jobs -p %+ disagree!' +fi + +exec 2>/dev/null +kill -9 $pid1 diff --git a/tests/jobs2.sub b/tests/jobs2.sub new file mode 100644 index 0000000..496519b --- /dev/null +++ b/tests/jobs2.sub @@ -0,0 +1,13 @@ +# make sure fg and bg don't work on jobs started without job control, +# even if they are executed when job control is active +set +o monitor + +sleep 30 & +pid=$! + +set -m +fg %1 +echo fg: $? + +exec 2>/dev/null +kill -9 $pid diff --git a/tests/jobs3.sub b/tests/jobs3.sub new file mode 100644 index 0000000..6efd58b --- /dev/null +++ b/tests/jobs3.sub @@ -0,0 +1,26 @@ +#! /bin/bash +NJOB=8 +i=0 + +while [ $i -lt $NJOB ] +do + /bin/sh -c "sleep 4; exit 0" & + rv=$? + pid=$! + eval bg_pid_$i=$pid +# echo $$: Job $i: pid is $pid rv=$rv + i=$((i + 1)) +done + + + +i=0 +while [ $i -lt $NJOB ] +do + eval wpid=\$bg_pid_$i + echo Waiting for job $i #'('pid $wpid')' + wait $wpid + rv=$? + echo job $i returns $rv + i=$((i + 1)) +done diff --git a/tests/jobs4.sub b/tests/jobs4.sub new file mode 100644 index 0000000..898b449 --- /dev/null +++ b/tests/jobs4.sub @@ -0,0 +1,24 @@ +# test being able to use job control notation in jobs/kill/wait without +# job control active, as the SUS requires + +sleep 2 & + +sleep 2 & +sleep 2 & +sleep 2 & +(sleep 2 ; exit 4) & + +jobs + +wait %% +echo $? + +wait %1 +echo $? + +wait + +# the sleep is intended to give the kill time to execute before the job +# exits +(sleep 1 ; cat ) & +kill -1 %% && echo i killed it || echo could not kill it diff --git a/tests/jobs5.sub b/tests/jobs5.sub new file mode 100644 index 0000000..35d3981 --- /dev/null +++ b/tests/jobs5.sub @@ -0,0 +1,12 @@ +# framework to test new `wait -n' option that waits for any job to finish + +set -m + +sleep 20 & +{ sleep 5; exit 12; } & +sleep 20 & + +wait -n +echo $? + +jobs diff --git a/tests/jobs6.sub b/tests/jobs6.sub new file mode 100644 index 0000000..9ed59ee --- /dev/null +++ b/tests/jobs6.sub @@ -0,0 +1,14 @@ +# framework to test `wait -f' which forces wait until a job exits +set -o monitor +sleep 5 & +child1=$! + +( sleep 1; kill -STOP $child1 ; sleep 1 ; kill -CONT $child1 )& + +child2=$! + +wait -f %1 +echo child1 exit status $? + +wait $child2 +exit 0 diff --git a/tests/lastpipe.right b/tests/lastpipe.right new file mode 100644 index 0000000..cca5938 --- /dev/null +++ b/tests/lastpipe.right @@ -0,0 +1,20 @@ +after 1: foo = a b c +after 2: tot = 6 +after: 7 +last = c +1 -- 142 1 +0 -- 0 1 0 +1 -- 0 0 1 +1 -- 0 0 1 +1 -- 0 1 0 +lastpipe1.sub returns 14 +A1 +A2 +B1 +B2 +HI +A1 +A2 +B1 +B2 +HI -- 42 -- 0 42 diff --git a/tests/lastpipe.tests b/tests/lastpipe.tests new file mode 100644 index 0000000..16dc841 --- /dev/null +++ b/tests/lastpipe.tests @@ -0,0 +1,61 @@ +binfalse() +{ + $binfalse || return 1 # normalize return value +} + +if [ -x /usr/bin/true ]; then + bintrue=/usr/bin/true +elif [ -x /bin/true ]; then + bintrue=/bin/true +else + bintrue=true +fi +if [ -x /usr/bin/false ]; then + binfalse=/usr/bin/false +elif [ -x /bin/false ]; then + binfalse=/bin/false +else + binfalse=true +fi + +shopt -s lastpipe + +unset foo bar +echo a b c | read foo +echo after 1: foo = $foo + +unset tot +declare -i tot +printf "%d\n" 1 2 3 | while read foo; do tot+=$foo; done +echo after 2: tot = $tot + +unset bar +echo g h i | bar=7 +echo after: $bar + +unset foo last +printf "%s\n" a b c | while read foo; do last=$foo; done +echo last = $last + +exit 142 | false +echo $? -- ${PIPESTATUS[@]} + +true | false | $bintrue +echo $? -- ${PIPESTATUS[@]} + +true | $bintrue | false +echo $? -- ${PIPESTATUS[@]} + +set -o pipefail +true | $bintrue | false +echo $? -- ${PIPESTATUS[@]} + +true | binfalse | true +echo $? -- ${PIPESTATUS[@]} +set +o pipefail + +${THIS_SH} ./lastpipe1.sub +echo lastpipe1.sub returns $? + +${THIS_SH} ./lastpipe2.sub + diff --git a/tests/lastpipe1.sub b/tests/lastpipe1.sub new file mode 100644 index 0000000..43711e3 --- /dev/null +++ b/tests/lastpipe1.sub @@ -0,0 +1,5 @@ +# with lastpipe set, exit at the end of a pipeline exits +# the calling shell +shopt -s lastpipe +exit 142 | exit 14 +echo after: $? diff --git a/tests/lastpipe2.sub b/tests/lastpipe2.sub new file mode 100644 index 0000000..3bcc37d --- /dev/null +++ b/tests/lastpipe2.sub @@ -0,0 +1,30 @@ +shopt -s lastpipe +echo -e 'A\nB' | while read letter; do + echo -e '1\n2' | while read digit; do + echo $letter$digit + done +done + +myPipefunc() +{ + cat | tee $TMPDIR/outfile +} +echo HI | myPipefunc + +echo -e 'A\nB' | while read letter; do + echo -e '1\n2' | while read digit; do + echo $letter$digit | myPipefunc + done +done + +rm -f $TMPDIR/outfile + +unset -f myPipefunc +myPipefunc() +{ + cat | read var + return 42 +} +echo HI | myPipefunc + +echo $var -- $? -- ${PIPESTATUS[@]} diff --git a/tests/mapfile.data b/tests/mapfile.data new file mode 100644 index 0000000..4f1d3ce --- /dev/null +++ b/tests/mapfile.data @@ -0,0 +1,17 @@ +[0] Abcdefghijklmnop +[1] aBcdefghijklmnop +[2] abCdefghijklmnop +[3] abcDefghijklmnop +[4] abcdEfghijklmnop +[5] abcdeFghijklmnop +[6] abcdefGhijklmnop +[7] abcdefgHijklmnop +[8] abcdefghIjklmnop +[9] abcdefghiJklmnop +[a] abcdefghijKlmnop +[b] abcdefghijkLmnop +[c] abcdefghijklMnop +[d] abcdefghijklmNop +[e] abcdefghijklmnOp +[f] abcdefghijklmnoP +a
\ No newline at end of file diff --git a/tests/mapfile.right b/tests/mapfile.right new file mode 100644 index 0000000..143d6dd --- /dev/null +++ b/tests/mapfile.right @@ -0,0 +1,169 @@ +[0] Abcdefghijklmnop +[1] aBcdefghijklmnop +[2] abCdefghijklmnop +[3] abcDefghijklmnop +[4] abcdEfghijklmnop +[5] abcdeFghijklmnop +[6] abcdefGhijklmnop +[7] abcdefgHijklmnop +[8] abcdefghIjklmnop +[9] abcdefghiJklmnop +[a] abcdefghijKlmnop +[b] abcdefghijkLmnop +[c] abcdefghijklMnop +[d] abcdefghijklmNop +[e] abcdefghijklmnOp +[f] abcdefghijklmnoP +a[0] Abcdefghijklmnop +[1] aBcdefghijklmnop +[2] abCdefghijklmnop +[3] abcDefghijklmnop +[4] abcdEfghijklmnop +[5] abcdeFghijklmnop +[6] abcdefGhijklmnop +[7] abcdefgHijklmnop +[8] abcdefghIjklmnop +[9] abcdefghiJklmnop +[a] abcdefghijKlmnop +[b] abcdefghijkLmnop +[c] abcdefghijklMnop +[d] abcdefghijklmNop +[e] abcdefghijklmnOp +[f] abcdefghijklmnoP +a +0 [0] Abcdefghijklmnop + +1 [1] aBcdefghijklmnop + +2 [2] abCdefghijklmnop + +3 [3] abcDefghijklmnop + +4 [4] abcdEfghijklmnop + +5 [5] abcdeFghijklmnop + +6 [6] abcdefGhijklmnop + +7 [7] abcdefgHijklmnop + +8 [8] abcdefghIjklmnop + +9 [9] abcdefghiJklmnop + +10 [a] abcdefghijKlmnop + +11 [b] abcdefghijkLmnop + +12 [c] abcdefghijklMnop + +13 [d] abcdefghijklmNop + +14 [e] abcdefghijklmnOp + +15 [f] abcdefghijklmnoP + +16 a +2 [2] abCdefghijklmnop + +5 [5] abcdeFghijklmnop + +8 [8] abcdefghIjklmnop + +11 [b] abcdefghijkLmnop + +14 [e] abcdefghijklmnOp + +[0] Abcdefghijklmnop +[1] aBcdefghijklmnop +[2] abCdefghijklmnop +[3] abcDefghijklmnop +[4] abcdEfghijklmnop +[5] abcdeFghijklmnop +[6] abcdefGhijklmnop +[7] abcdefgHijklmnop +[8] abcdefghIjklmnop +[9] abcdefghiJklmnop +[a] abcdefghijKlmnop +[b] abcdefghijkLmnop +[c] abcdefghijklMnop +[d] abcdefghijklmNop +[e] abcdefghijklmnOp +[f] abcdefghijklmnoP +a +[0] aaa +[1] aaa +[2] aaa +[3] aaa +[4] aaa +[5] aaa +[6] aaa +[7] aaa +[8] aaa +[9] aaa +[0] Abcdefghijklmnop +[1] aBcdefghijklmnop +[2] abCdefghijklmnop +[3] abcDefghijklmnop +[4] abcdEfghijklmnop +[5] abcdeFghijklmnop +[6] abcdefGhijklmnop +[7] abcdefgHijklmnop +[8] abcdefghIjklmnop +[9] abcdefghiJklmnop +[a] abcdefghijKlmnop +[b] abcdefghijkLmnop +[c] abcdefghijklMnop +[d] abcdefghijklmNop +[e] abcdefghijklmnOp +[f] abcdefghijklmnoP +a +[27] aaa +[28] aaa +[29] aaa +[0] aaa +[1] aaa +[2] aaa +[3] aaa +[4] aaa +[5] aaa +[6] aaa +[7] aaa +[8] aaa +[9] aaa +[0] Abcdefghijklmnop +[1] aBcdefghijklmnop +[2] abCdefghijklmnop +[3] abcDefghijklmnop +[4] abcdEfghijklmnop +[15] aaa +[16] aaa +[17] aaa +[18] aaa +[19] aaa +[20] aaa +[21] aaa +[22] aaa +[23] aaa +[24] aaa +[25] aaa +[26] aaa +[27] aaa +[28] aaa +[29] aaa +1 2 3 4 5 +foo 0 1 + +foo 1 2 + +foo 2 3 + +foo 3 4 + +foo 4 5 + +0 abc +1 def +2 ghi +3 jkl +abc def ghi jkl diff --git a/tests/mapfile.tests b/tests/mapfile.tests new file mode 100644 index 0000000..ff8da32 --- /dev/null +++ b/tests/mapfile.tests @@ -0,0 +1,44 @@ +declare -a A +mapfile A < mapfile.data +for (( i = 0 ; i < ${#A[@]} ; i++ )); do + echo -n "${A[${i}]}" +done + +declare -a B +mapfile -t B < mapfile.data +for (( i = 0 ; i < ${#B[@]} ; i++ )); do + echo "${B[${i}]}" +done + +mapfile -C "echo" -c 1 A < mapfile.data +mapfile -C "echo" -c 3 A < mapfile.data +mapfile -C "echo" -c 19 A < mapfile.data + +declare -a C +mapfile -t -u 3 C 3< mapfile.data < mapfile.tests +for (( i = 0 ; i < ${#C[@]} ; i++ )); do + echo "${C[${i}]}" +done + + +declare -a D +for (( i = 0 ; i < 30; i++ )); do + D[${i}]="[$i] aaa" +done +mapfile -O 10 -t D < mapfile.data +for (( i = 0 ; i < ${#D[@]} ; i++ )); do + echo "${D[${i}]}" +done + +declare -a E +for (( i = 0 ; i < 30; i++ )); do + E[${i}]="[$i] aaa" +done +mapfile -O 10 -n 5 -t E < mapfile.data +for (( i = 0 ; i < ${#E[@]} ; i++ )); do + echo "${E[${i}]}" +done + +${THIS_SH} ./mapfile1.sub + +${THIS_SH} ./mapfile2.sub diff --git a/tests/mapfile1.sub b/tests/mapfile1.sub new file mode 100644 index 0000000..b3d77f9 --- /dev/null +++ b/tests/mapfile1.sub @@ -0,0 +1,11 @@ +: ${TMPDIR:=/tmp} +FILE=$TMPDIR/file + +trap 'rm -f $FILE' 0 1 2 3 6 15 +printf "%d\n" {1..20} > $FILE + +mapfile -n 5 array < $FILE +echo ${array[@]} + +mapfile -n 5 -c 1 -C "echo foo" array < $FILE +mapfile -n 5 -c 1 -C "echo foo" array < /dev/null diff --git a/tests/mapfile2.sub b/tests/mapfile2.sub new file mode 100644 index 0000000..771a992 --- /dev/null +++ b/tests/mapfile2.sub @@ -0,0 +1,6 @@ +# test mapfile -d DELIM functionality added after bash-4.3 + +printf "abc\0def\0ghi\0jkl\0" | { + mapfile -C echo -c 1 -d '' A + echo "${A[@]}" +} diff --git a/tests/misc/dev-tcp.tests b/tests/misc/dev-tcp.tests new file mode 100644 index 0000000..0f3a228 --- /dev/null +++ b/tests/misc/dev-tcp.tests @@ -0,0 +1,16 @@ +exec 9<>/dev/tcp/129.22.8.162/25 + +read banner <&9 +echo "$banner" + +echo quit >&9 + +read msg <&9 +echo "$msg" + +exec 9<&- + +# nifty date command that queries the date/time server +cat < /dev/tcp/129.22.8.102/13 + +exit 0 diff --git a/tests/misc/perf-script b/tests/misc/perf-script new file mode 100644 index 0000000..e1172a9 --- /dev/null +++ b/tests/misc/perf-script @@ -0,0 +1,81 @@ +#!/bin/bash + +typeset -i m2 m1 M n2 n1 N m n +typeset -i MM=5 NN=5 + +case $# in + 0) : + ;; + 1) MM=$1; NN=$1 + ;; + 2) MM=$1; NN=$2 + ;; + *) echo 1>&2 "Usage: $0 [m [n]]" + ;; +esac + +EMPTYLINE=: # echo +echo 'a = { ' # mathematica + +let "M=1" # for (M=1; M<=MM; M++) +while let "M <= MM"; do + let "N=1" # for (N=1; N<=NN; N++) + while let "N <= NN"; do + + let "m1 = M - 1" + let "m2 = M + 1" + let "n1 = N - 1" + let "n2 = N + 1" + + + echo -n '{ ' # math + let "m=1" # for(m=1; m<=MM; m++) + while let "m <= MM"; do + let "n=1" # for(n=1; n<=NN; n++) + while let "n <= NN"; do + + let "x = (m-m1)*(m-M)*(m-m2)" + let "y = (n-n1)*(n-N)*(n-n2)" + + if let "(x*x + (n-N)*(n-N)) * ((m-M)*(m-M) + y*y)"; then + echo -n "0," + else # neighbour + echo -n "1," + fi + + let "n=n+1" + done + echo -n " "; let "m=m+1" # ". " + done + echo '},' + + + let "N=N+1" + $EMPTYLINE + done + $EMPTYLINE + let "M=M+1" +done + +echo '}' + + + +echo -n 'o = { ' +let "m=1" +while let "m <= MM"; do + let "n=1" + while let "n <= NN"; do + echo -n "1," + let "n=n+1" + done + let "m=m+1" +done +echo " }" + + +echo 'x = LinearSolve[a,o] ' + +exit 0 + + diff --git a/tests/misc/perftest b/tests/misc/perftest new file mode 100644 index 0000000..ee3f2c6 --- /dev/null +++ b/tests/misc/perftest @@ -0,0 +1,10 @@ +# originally from Mike Haertel +foo() { case $1 in a*) ;; *) ;; esac ;} +bar() { case $1 in [abc]*) ;; *);; esac ;} +baz() { case $1 in xyzzy) ;; *) ;; esac ;} +for x in /usr/lib/*/* +do + foo $x + bar $x + baz $x +done diff --git a/tests/misc/read-nchars.tests b/tests/misc/read-nchars.tests new file mode 100644 index 0000000..40b1f98 --- /dev/null +++ b/tests/misc/read-nchars.tests @@ -0,0 +1,11 @@ +# interactive + +# from tty +read -n 3 -p 'enter three chars: ' xyz +echo +echo $xyz + +# using readline +read -p 'enter 3 chars: ' -e -n 3 abc +# readline outputs a newline for us, so we don't need the extra echo +echo $abc diff --git a/tests/misc/redir-t2.sh b/tests/misc/redir-t2.sh new file mode 100644 index 0000000..44b2624 --- /dev/null +++ b/tests/misc/redir-t2.sh @@ -0,0 +1,17 @@ +read line1 + +echo read line 1 \"$line1\" + +exec 4<&0 + +exec 0</dev/tty + +read line2 + +echo line read from tty = \"$line2\" + +exec 0<&4 + +read line3 + +echo read line 3 \"$line3\" diff --git a/tests/misc/run-r2.sh b/tests/misc/run-r2.sh new file mode 100755 index 0000000..0321a1b --- /dev/null +++ b/tests/misc/run-r2.sh @@ -0,0 +1 @@ +../../bash ./redir-t2.sh < /etc/passwd diff --git a/tests/misc/sigint-1.sh b/tests/misc/sigint-1.sh new file mode 100755 index 0000000..7b74c30 --- /dev/null +++ b/tests/misc/sigint-1.sh @@ -0,0 +1,9 @@ +echo before trap +trap 'echo caught sigint' 2 +echo after trap + +for i in 1 2 3 +do + echo $i + sleep 5 +done diff --git a/tests/misc/sigint-2.sh b/tests/misc/sigint-2.sh new file mode 100755 index 0000000..69eaf56 --- /dev/null +++ b/tests/misc/sigint-2.sh @@ -0,0 +1,7 @@ +echo before loop + +for i in 1 2 3 +do + echo $i + sleep 5 +done diff --git a/tests/misc/sigint-3.sh b/tests/misc/sigint-3.sh new file mode 100755 index 0000000..2627fe6 --- /dev/null +++ b/tests/misc/sigint-3.sh @@ -0,0 +1,11 @@ +sleep 5 & +sleep 5 & +sleep 5 & + +echo wait 1 +wait + +echo wait 2 +wait + +exit diff --git a/tests/misc/sigint-4.sh b/tests/misc/sigint-4.sh new file mode 100755 index 0000000..587dd26 --- /dev/null +++ b/tests/misc/sigint-4.sh @@ -0,0 +1,13 @@ +trap 'echo sigint' 2 + +sleep 5 & +sleep 5 & +sleep 5 & + +echo wait 1 +wait + +echo wait 2 +wait + +exit diff --git a/tests/misc/test-minus-e.1 b/tests/misc/test-minus-e.1 new file mode 100644 index 0000000..77cc3f2 --- /dev/null +++ b/tests/misc/test-minus-e.1 @@ -0,0 +1,9 @@ +touch .file +while set -e ; test -r .file ; do + echo -n "stop loop? " + read reply + case "$reply" in + y*) rm .file non-dash-file ;; + esac + set +e +done diff --git a/tests/misc/test-minus-e.2 b/tests/misc/test-minus-e.2 new file mode 100644 index 0000000..f66966e --- /dev/null +++ b/tests/misc/test-minus-e.2 @@ -0,0 +1,11 @@ +touch .file +set -e +while set +e ; test -r .file ; do + echo -n "stop loop? [yes to quit] " + read reply + if [ "$reply" = yes ] ; then + rm .file non-dash-file + fi + set -e +done +rm -f .file diff --git a/tests/misc/wait-bg.tests b/tests/misc/wait-bg.tests new file mode 100644 index 0000000..95c98b0 --- /dev/null +++ b/tests/misc/wait-bg.tests @@ -0,0 +1,25 @@ +#! /bin/bash + +i=0 +while [ $i -lt $1 ] +do + /bin/sh -c "sleep 4; exit 0" & + rv=$? + pid=$! + eval bg_pid_$i=$pid + echo $$: Job $i: pid is $pid rv=$rv + i=$((i + 1)) +done + + + +i=0 +while [ $i -lt $1 ] +do + eval wpid=\$bg_pid_$i + echo Waiting for job $i '('pid $wpid')' + wait $wpid + rv=$? + echo Return value is $rv + i=$((i + 1)) +done diff --git a/tests/more-exp.right b/tests/more-exp.right new file mode 100644 index 0000000..91a375c --- /dev/null +++ b/tests/more-exp.right @@ -0,0 +1,214 @@ +argv[1] = <aaa bbb ccc> +argv[1] = <aaa bbb ccc> +argv[1] = <baz:bar> +argv[1] = <baz:bar> +argv[1] = <aaa bbb ccc> +argv[1] = <bar> +argv[1] = <bar> +argv[1] = <bar> +argv[1] = <abcde> +argv[1] = <abcde> +argv[1] = <xyz> +argv[1] = <a b> +argv[2] = <c> +argv[3] = <d> +argv[4] = <e> +argv[5] = <f> +argv[1] = <a b> +argv[1] = <a> +argv[2] = <b> +argv[1] = <a b> +argv[2] = <c> +argv[3] = <d> +argv[4] = <e> +argv[5] = <f> +argv[1] = <a b> +argv[2] = <c> +argv[3] = <d> +argv[4] = <e> +argv[5] = <f> +argv[1] = </usr/homes/chet> +argv[1] = <~> +argv[1] = <~> +argv[1] = <\~> +argv[1] = <\ \~> +argv[1] = <\ \ \~> +argv[1] = </usr/homes/chet> +argv[1] = </usr/homes/chet> +argv[1] = </usr/homes/chet> +argv[1] = <$HOME> +argv[1] = <\ $HOME> +argv[1] = <\ \ $HOME> +argv[1] = <'bar'> +argv[1] = <'bar'> +argv[1] = <*@> +argv[1] = <*@> +argv[1] = <*@> +argv[1] = <*@> +argv[1] = <*@*> +argv[1] = <*@*> +argv[1] = <*@*> +argv[1] = <*@*> +argv[1] = <abcd> +argv[1] = <efghijkl> +argv[1] = <4> +argv[2] = <2> +argv[1] = <1> +argv[1] = <bar> +argv[1] = <2> +argv[1] = <bar> +argv[1] = <2> +argv[1] = <4> +argv[1] = <--\> +argv[2] = <--> +argv[1] = <--\^J--> +argv[1] = <--+\> +argv[2] = <+--> +argv[1] = <--+\^J+--> +argv[1] = <-+\> +argv[2] = <+-\> +argv[3] = <-> +argv[1] = <xy> +argv[1] = <xy> +argv[1] = <xy> +argv[1] = <xy> +argv[1] = <xy> +argv[1] = <xy> +argv[1] = <> +argv[1] = <> +argv[1] = <xy> +argv[1] = <xy> +argv[1] = <xy> +argv[1] = <xy> +argv[1] = <xy> +argv[1] = <xy> +argv[1] = <> +argv[1] = <> +argv[1] = <x> +argv[1] = <x> +argv[1] = <> +argv[1] = <x> +argv[1] = <x> +argv[1] = <x> +argv[1] = <x> +argv[1] = <^?> +argv[1] = <^?> +argv[1] = <x> +argv[1] = <x> +argv[1] = <> +argv[2] = <abd> +argv[3] = <x> +argv[1] = <> +argv[2] = <abd> +argv[3] = <> +argv[1] = <a,b,c,d,e,f> +argv[1] = <a> +argv[2] = <b> +argv[3] = <c> +argv[4] = <d> +argv[5] = <e> +argv[6] = <f> +./more-exp.tests: line 272: abc=def: command not found +argv[1] = <a b c d e> +argv[1] = <a> +argv[2] = <b> +argv[3] = <c> +argv[4] = <d> +argv[5] = <e> +argv[1] = <foo)> +argv[1] = <a> +argv[1] = <\a> +argv[1] = <\a> +argv[1] = <\a> +argv[1] = <\a> +argv[1] = <\\a> +argv[1] = <a> +argv[1] = <\a> +argv[1] = <\a> +argv[1] = <\a> +argv[1] = <\a> +argv[1] = <\\a> +argv[1] = <a> +argv[1] = <a> +argv[1] = <\a> +argv[1] = <\a> +argv[1] = <\a> +argv[1] = <\a> +argv[1] = <$a> +argv[1] = <\foo> +argv[1] = <$a> +argv[1] = <\foo> +argv[1] = <\$a> +argv[1] = <\\$a> +argv[1] = <a> +argv[1] = <a> +argv[1] = <\a> +argv[1] = <\a> +argv[1] = <\a> +argv[1] = <\a> +argv[1] = <G> +argv[2] = <{> +argv[3] = <I> +argv[4] = <K> +argv[5] = <}> +argv[1] = <hi> +argv[2] = <K> +argv[3] = <}> +argv[1] = <a*> +Number of args: 0 +<${*-x}>: <x> +<${@-x}>: <x> +Number of args: 1 +<${*-x}>: <> +<${@-x}>: <> +Number of args: 2 +<${*-x}>: < > +<${@-x}>: < > +argv[1] = <5> +argv[1] = <5> +argv[1] = <5> +argv[1] = <5> +argv[1] = <5> +argv[1] = <0> +argv[1] = <0> +argv[1] = <0> +argv[1] = <0> +argv[1] = <0> +argv[1] = <0> +argv[1] = <posparams> +argv[1] = <posparams> +argv[1] = <2> +argv[1] = <0> +argv[1] = <0> +argv[1] = <1> +argv[1] = <5> +argv[1] = <5> +argv[1] = <0> +./more-exp.tests: line 423: ${#:}: bad substitution +./more-exp.tests: line 425: ${#/}: bad substitution +./more-exp.tests: line 427: ${#%}: bad substitution +./more-exp.tests: line 429: ${#=}: bad substitution +./more-exp.tests: line 431: ${#+}: bad substitution +./more-exp.tests: line 433: ${#1xyz}: bad substitution +./more-exp.tests: line 436: #: %: syntax error: operand expected (error token is "%") +argv[1] = <0> +argv[1] = <a+b> +argv[1] = <+> +argv[1] = <+> +argv[1] = <+> +argv[1] = <G { I > +argv[2] = <K> +argv[3] = <}> +argv[1] = <hi> +argv[2] = <K> +argv[3] = <}> +argv[1] = <xxx> +argv[2] = <yyy> +1 +argv[1] = <> +argv[1] = <> +argv[1] = <> +argv[1] = <:a:> +argv[1] = <:b:> +argv[1] = <> +argv[1] = <> diff --git a/tests/more-exp.tests b/tests/more-exp.tests new file mode 100644 index 0000000..10b3a47 --- /dev/null +++ b/tests/more-exp.tests @@ -0,0 +1,504 @@ +expect() +{ + echo expect "$@" +} + +tool_var() { + eval $1=\"\${$1:-$2}\" + export $1 +} + +A="aaa bbb ccc" + +unset B + +tool_var B ${B:-"$A"} + +expect '<aaa bbb ccc>' +recho "$A" +expect '<aaa bbb ccc>' +recho "$B" + +eto_prepend() { + eval $1=\'$2\''${'$1':+":"${'$1'}}'; export $1 +} + +foo=bar; export foo +eto_prepend foo baz +expect '<baz:bar>' +recho $foo +expect '<baz:bar>' +recho ${foo-"bar"} + +aa='aaa bbb ccc' + +expect '<aaa bbb ccc>' +recho ${zzz-"$aa"} +expect '<bar>' +recho ${zzz:-"bar"} +expect '<bar>' +recho "${zzz:-bar}" +expect '<bar>' +recho "${zzz:-"bar"}" + +var=abcde +expect '<abcde>' +recho "${var:-xyz}" +expect '<abcde>' +recho "${var:=xyz}" +expect '<xyz>' +recho "${var:+xyz}" + +set 'a b' c d e f +expect '<a b> <c> <d> <e> <f>' +recho ${1+"$@"} +expect '<a b>' +recho "${1-"$@"}" +expect '<a> <b>' +recho ${1-"$@"} +expect '<a b> <c> <d> <e> <f>' +recho "${1+$@}" +expect '<a b> <c> <d> <e> <f>' +recho "${1+"$@"}" + +HOME=/usr/homes/chet +somevar= +expect "<$HOME>" +recho ${somevar:-~} +# This changed after bash-3.0, when the tilde implementation was redone. It's +# not backward compatible, but it's very hard to be backward-compatible here, +# and I think the old behavior was a bug +expect '<~>' +recho "${somevar:-~}" +expect '<~>' +recho "${somevar:-"~"}" +expect '<\~>' +recho "${somevar:-\~}" +expect '<\ \~>' +recho "${somevar:-\ \~}" +expect '<\ \ \~>' +recho "${somevar:-\ \ \~}" + +expect "<$HOME>" +recho ${somevar:-$HOME} +expect "<$HOME>" +recho "${somevar:-$HOME}" +expect "<$HOME>" +recho "${somevar:-"$HOME"}" +expect '<$HOME>' +recho "${somevar:-\$HOME}" +expect '<\ $HOME>' +recho "${somevar:-\ \$HOME}" +expect '<\ \ $HOME>' +recho "${somevar:-\ \ \$HOME}" + +foo=bar +expect "<'bar'>" +recho "${foo+'$foo'}" +expect "<'bar'>" +recho "${fox='$foo'}" + +P='*@*' +expect '<*@>' +recho "${P%"*"}" +expect '<*@>' +recho "${P%'*'}" + +expect '<*@>' +recho ${P%"*"} +expect '<*@>' +recho ${P%'*'} + +expect '<*@*>' +recho ${P%""} +expect '<*@*>' +recho ${P#""} + +expect '<*@*>' +recho ${P#"$foobar"} +expect '<*@*>' +recho ${P%"$foobar"} + +s1=abcdefghijkl +s2=efgh + +first=${s1/$s2*/} +expect '<abcd>' +recho $first + +last=${s1##$first} +expect '<efghijkl>' +recho $last + +shift $# +UNAME_RELEASE=${1:-4.2MP} + +RELEASE=`expr "$UNAME_RELEASE" : '[^0-9]*\([0-9]*\)'` # 4 +case "$RELEASE" in +"") RELEASE=0 ;; +*) RELEASE=`expr "$RELEASE" + 0` ;; +esac +REL_LEVEL=`expr "$UNAME_RELEASE" : '[^0-9]*[0-9]*.\([0-9]*\)'` # 1 +REL_SUBLEVEL=`expr "$UNAME_RELEASE" : '[^0-9]*[0-9]*.[0-9]*.\([0-9]*\)'` # 2 + +expect '<4> <2>' +recho $RELEASE $REL_LEVEL $REL_SUBLEVEL + +b1() +{ + b2 ${1+"$@"} +} + +b2() +{ + recho $* + recho ${#} +} + +expect '<1>' +b1 '' + +expect '<bar> <2>' +b1 bar '' + +expect '<bar> <2>' +b1 '' bar + +expect '<4>' +b1 '' '' '' '' + +NL="\\ +" + +NNL="+$NL+" + +expect '<--\> <-->' +recho --$NL-- +expect '<--\^J-->' +recho "--$NL--" + +expect '<--+\> <+-->' +recho --$NNL-- +expect '<--+\^J+-->' +recho "--$NNL--" + +expect '<-+\> <+-\> <->' +recho -$NNL-$NL- + +set '' +expect '<xy>' +recho "$*xy" +expect '<xy>' +recho "x$*y" +expect '<xy>' +recho "xy$*" +expect '<xy>' +recho x"$*"y +expect '<xy>' +recho xy"$*" +expect '<xy>' +recho "$*"xy +expect '<>' +recho "$*" +expect nothing +recho $* + +unset undef ; set "" + +expect '<>' +recho ${undef-"$*"} +expect '<xy>' +recho ${undef-"x$*y"} +expect '<xy>' +recho ${undef-"$*xy"} +expect '<xy>' +recho ${undef-"xy$*"} +expect '<xy>' +recho ${undef-x"$*"y} +expect '<xy>' +recho ${undef-xy"$*"} +expect '<xy>' +recho ${undef-"$*"xy} +expect '<>' +recho "${undef-$*}" +expect nothing +recho ${undef-$*} + +expect '<>' +recho ${undef-"$zzz"} +expect '<x>' +recho x${undef-"$zzz"} +expect '<x>' +recho x${undef-"$@"} +expect nothing +recho ${undef-"$@"} +expect '<x>' +recho ${undef-"$zzz"}x +expect '<x>' +recho ${undef-"$@"}x +expect '<x>' +recho "$@"x +expect '<x>' +recho "$zzz"x +expect '<^?>' +recho ${undef-} +expect '<^?>' +recho ${undef-""} + +yyy="" +recho "$xxx"x +recho "$yyy"x + +set "" "abd" "" +recho "$@"x +recho "$@"$xxx + +OIFS="$IFS" + +arg=a,b,c,d,e,f + +IFS=, + +export z=$arg + +eval z1=\"$arg\" + +IFS="$OIFS" + +recho $z +recho $z1 + +# should give an error +abc\=def + +zz="a b c d e" +declare a=$zz + +recho "$a" +recho $a + +recho $(echo "foo$(echo ")")") + +# test backslash escapes + +recho \a +recho \\a + +recho "\a" +recho "\\a" + +recho '\a' +recho '\\a' + +recho $(zecho \a) +recho $(zecho \\a) + +recho $(zecho "\a") +recho $(zecho "\\a") + +recho $(zecho '\a') +recho $(zecho '\\a') + +recho `zecho \a` +recho `zecho \\a` + +recho `zecho "\a"` +recho `zecho "\\a"` + +recho `zecho '\a'` +recho `zecho '\\a'` + +a=foo + +recho \$a +recho \\$a + +recho "\$a" +recho "\\$a" + +recho '\$a' +recho '\\$a' + +recho $(zecho `zecho \a`) +recho $(zecho `zecho \\a`) + +recho $(zecho `zecho "\a"`) +recho $(zecho `zecho "\\a"`) + +recho $(zecho `zecho '\a'`) +recho $(zecho `zecho '\\a'`) + +# should echo G { I K } +recho ${abc:-G { I } K } + +abc=hi + +# should echo hi K } +recho ${abc:-G { I } K } + +# should echo a* +unset foo +recho "${foo:-"a"}*" + +f () +{ + echo "Number of args: $#" + echo "<\${*-x}>: <${*-x}>" + echo "<\${@-x}>: <${@-x}>" +} + +f +f '' +f '' '' + +set 1 2 3 4 5 + +expect '<5>' +recho ${#} +expect '<5>' +recho ${#:foo} +expect '<5>' +recho ${#:-foo} +expect '<5>' +recho ${#-posparams} +expect '<5>' +recho ${#:-posparams} + +expect '<0>' +recho ${#!} + +expect nothing +recho $! +expect nothing +recho ${!} + +expect nothing +recho $8 +expect nothing +recho ${8} + +shift $# + +expect '<0>' +recho ${#} +expect '<0>' +recho ${#:foo} +expect '<0>' +recho ${#:-foo} +expect '<0>' +recho ${#-posparams} +expect '<0>' +recho ${#:-posparams} + +expect '<posparams>' +recho ${!-posparams} +expect '<posparams>' +recho ${!:-posparams} + +expect '<2>' +recho ${#-} + +expect '<0>' +recho ${#-posparams} + +expect '<0>' +recho ${#?:-xyz} + +expect '<1>' +recho ${#?} + +set a b c d e + +expect '<5>' +recho ${#} +expect '<5>' +recho ${#?:-xyz} + +shift ${#} + +expect '<0>' +recho ${#:-foo} + +expect a bad substitution error +recho ${#:} +expect a bad substitution error +recho ${#/} +expect a bad substitution error +recho ${#%} +expect a bad substitution error +recho ${#=} +expect a bad substitution error +recho ${#+} +expect a bad substitution error +recho ${#1xyz} + +expect a math syntax error +recho ${#:%} + +expect '<0>' +recho ${#:-} + +set -- +unset a b + +x=a +y=b + +IFS=+ + +expect '<a+b>' +recho $x+$y +expect '<+>' +recho $a+$b + +expect '<+>' +recho + "$@" +expect '<+>' +recho +"$@" + +# variants of nested curly braces inside ${...} expressions + +# IFS is not the standard one + +expect '<G { I>' '<K>' '<}>' +recho ${gik:-G { I } K } + +abc=hi + +expect '<hi>' '<K>' '<}>' +recho ${abc:-G { I } K } + +# reset IFS to the default +IFS=' +' + +# nested ${...} inside ${...} are handled specially +unset XXX FOO BAR +expect '<xxx>' '<yyy>' +XXX=xxx +FOO=${BAR:-${XXX} yyy} +recho $FOO + +# this was a bug in versions of bash prior to bash-2.04-release +set -- '' +expect 1 +echo $# +expect '<>' +recho "${@}" +expect '<>' +recho "${@-}" +expect '<>' +recho "${@:-}" + +# this was a bug in bash-2.04, fixed in 2.05 +set -- a b +expect '<:a:>' '<:b:>' +for i in "${@-}"; do recho :$i:; done + +# I believe that ksh93 does these wrong -- we're using the rhs, so shouldn't +# it behave the same as ""? +set -- +expect '<>' +recho "${@-}" +expect '<>' +recho "${@:-}" diff --git a/tests/nameref.right b/tests/nameref.right new file mode 100644 index 0000000..698002e --- /dev/null +++ b/tests/nameref.right @@ -0,0 +1,485 @@ +one +two +three +declare -n fee="flip" +declare -n foo="bar" +turning off nameref attribute on foo +bar +after +n foo bar = other +one +two +one +expect <one> +argv[1] = <one> +expect <two> +argv[1] = <two> +expect <one> +one +expect <one> +one +expect <one> +argv[1] = <one> +changevar: expect <two> +argv[1] = <two> +expect <two> +argv[1] = <two> +changevar: expect <three four five> +argv[1] = <three four five> +expect <three four five> +argv[1] = <three four five> +./nameref.tests: line 93: foo: readonly variable +./nameref.tests: line 94: foo: readonly variable +one +one +./nameref.tests: line 106: foo: readonly variable +./nameref.tests: line 103: foo: readonly variable +one +abxde +abxde +one +bar + +./nameref2.sub: line 5: foo: readonly variable + +expect <unset> +argv[1] = <unset> +expect <unset> +argv[1] = <unset> +expect <bar> +argv[1] = <bar> +expect <unset> +./nameref3.sub: line 16: foo: invalid indirect expansion +./nameref3.sub: line 21: unset: bar: cannot unset: readonly variable +expect <two> +two +expect <two> +two +three +unset +four +0 +expect <a b> +a b +expect <foo> +foo +1 3 5 7 9 +9 +1 3 42 7 9 +1 3 42 7 9 +9 +1 3 44 7 9 +unset +expect <a b c d e> +argv[1] = <a b c d e> +expect <zero> <one> <seven> <three> <four> +argv[1] = <zero> +argv[2] = <one> +argv[3] = <seven> +argv[4] = <three> +argv[5] = <four> +16 +expect <4> +4 +expect <4> +4 +expect <4> +4 +expect <one> +one +expect <one> +one +expect <one> +one +expect <four> +four +errors = 0 +1 +2 +v1: 1 +v2: 2 +ref -> first, value: I am first +ref -> second, value: I am in the middle +ref -> third, value: I am last +final state: ref -> third, value: I am last +ref -> one, value: 1 +ref -> two, value: 2 +ref -> three, value: 3 +final state: ref -> three, value: 3 +./nameref5.sub: line 43: unset: three: cannot unset: readonly variable +ref -> one, value: 1 +ref -> two, value: 2 +ref -> three, value: 3 +final state: ref -> three, value: 3 +./nameref6.sub: line 2: typeset: x: nameref variable self references not allowed +./nameref6.sub: line 5: typeset: x[3]: reference variable cannot be an array +./nameref6.sub: line 12: typeset: x: reference variable cannot be an array +the -- 1 +42 -- 0 +y -- 0 +2 -- 0 +2 -- 0 +y -- 0 +bar +unset +./nameref8.sub: line 3: typeset: warning: v: circular name reference +./nameref8.sub: line 3: warning: v: circular name reference +./nameref8.sub: line 5: warning: v: circular name reference +inside +inside: two +outside: +./nameref8.sub: line 29: typeset: warning: x: circular name reference +./nameref8.sub: line 29: warning: x: circular name reference +./nameref8.sub: line 31: warning: x: circular name reference +foo +./nameref8.sub: line 38: typeset: warning: v: circular name reference +./nameref8.sub: line 38: warning: v: circular name reference +./nameref8.sub: line 38: warning: v: circular name reference +local +./nameref8.sub: line 47: typeset: v: nameref variable self references not allowed +./nameref8.sub: line 54: warning: x: circular name reference +./nameref8.sub: line 55: warning: x: circular name reference +x = +idx2 +idX2 +idx2 +idX2 +declare -n foo="x[\$zero]" +42 +declare -a x=([0]="4") +declare -n foo="x[\$(echo 0)]" +4 +comsub +x[i=0] +comsub +4 +comsub +4 +comsub +4 +declare -n foo="somevariable" +./nameref10.sub: line 38: typeset: somevariable: not found +foo = +declare -n foo="somevariable" +declare -A somevariable=([jug]="brown" ) +declare -n foo="somevariable" +declare -A somevariable=([jug]="brown" ) +declare -n foo="somevariable" +./nameref10.sub: line 49: typeset: somevariable: not found +./nameref10.sub: line 51: typeset: foo: not found +./nameref10.sub: line 51: typeset: somevariable: not found +declare -n foo="bar" +./nameref10.sub: line 55: typeset: bar: not found +declare -n foo="bar" +./nameref10.sub: line 57: typeset: bar: not found +declare -n foo="bar" +declare -i bar="8" +8 +declare -n foo="bar" +./nameref10.sub: line 64: typeset: bar: not found +./nameref11.sub: line 1: declare: `/': invalid variable name for name reference +./nameref11.sub: line 2: declare: `/': invalid variable name for name reference +./nameref11.sub: line 3: `/': not a valid identifier +./nameref11.sub: line 4: declare: `/': not a valid identifier +./nameref11.sub: line 5: `/': not a valid identifier +1) / +#? ./nameref11.sub: line 6: `/': not a valid identifier +x + +./nameref11.sub: line 7: ((: `0': not a valid identifier +./nameref11.sub: line 8: declare: `0': invalid variable name for name reference +./nameref11.sub: line 9: declare: `/': invalid variable name for name reference +./nameref11.sub: line 10: declare: `/': invalid variable name for name reference +/ +./nameref11.sub: line 12: `/': not a valid identifier +./nameref11.sub: line 13: exec: `10': not a valid identifier +./nameref11.sub: line 13: r: cannot assign fd to variable +./nameref11.sub: line 14: warning: r: removing nameref attribute +63 +./nameref11.sub: line 15: declare: RO: readonly variable +./nameref11.sub: line 15: RO: readonly variable +./nameref11.sub: line 16: declare: `/': invalid variable name for name reference +/ +./nameref11.sub: line 17: declare: `/': invalid variable name for name reference +./nameref11.sub: illegal option -- h +./nameref11.sub: line 18: getopts: `?': not a valid identifier +./nameref11.sub: line 19: warning: r: removing nameref attribute +declare -a r=() +./nameref11.sub: line 20: declare: r: reference variable cannot be an array +./nameref11.sub: line 21: printf: `/': not a valid identifier +./nameref11.sub: line 23: `': not a valid identifier +./nameref11.sub: line 24: declare: `': not a valid identifier +./nameref11.sub: line 25: `': not a valid identifier +./nameref11.sub: line 26: printf: `': not a valid identifier +./nameref11.sub: line 27: declare: `': invalid variable name for name reference +declare -r ROVAR="42" +./nameref11.sub: line 32: ROVAR: readonly variable +./nameref11.sub: line 32: ROVAR: cannot unset: readonly variable +declare -r ROVAR="42" +./nameref11.sub +./nameref11.sub: line 34: `@': not a valid identifier +./nameref11.sub +declare -n ref="x" +./nameref11.sub: line 39: RO: readonly variable +declare -r RO_PID +./nameref11.sub: line 39: RO: cannot unset: readonly variable +declare -r RO="x" +./nameref11.sub: line 39: declare: RO_PID: not found +./nameref11.sub: line 41: RO2: readonly variable +declare -r RO2="a" +2 +./nameref11.sub: line 52: typeset: `2': invalid variable name for name reference +2 +./nameref11.sub: line 57: typeset: `2': invalid variable name for name reference +2 +./nameref11.sub: line 62: foo[2]: invalid indirect expansion +./nameref11.sub: line 63: bar: invalid indirect expansion +./nameref12.sub: line 6: declare: `/': invalid variable name for name reference +./nameref12.sub: line 9: declare: `%': invalid variable name for name reference +./nameref12.sub: line 13: `^': not a valid identifier +declare -n r +declare -a foo +declare -a foo=([0]="7") +./nameref12.sub: line 26: declare: `42': not a valid identifier +./nameref12.sub: line 27: declare: x: not found +declare -nr RO="foo" +/ +./nameref12.sub: line 45: declare: `7*6': not a valid identifier +./nameref12.sub: line 45: declare: foo: not found +./nameref12.sub: line 47: `7*6': not a valid identifier +declare -n ref="var" +declare -n ref="var" +./nameref12.sub: line 74: readonly: `var[0]': not a valid identifier +declare -- var="foo" +declare -r var2="foo" +declare -n ref="var" +declare -a var=([0]="foo") +./nameref12.sub: line 91: `': not a valid identifier +declare -n ref +declare -- ref="global" +declare -a var=([0]="foo2") +./nameref12.sub: line 100: declare: global: not found +declare -- a +declare -n r="a" +declare -- a +declare -n r="a" +0 +declare -n r="P" +declare -n ref="var" +declare -- a +declare -n r="a" +0 +declare -n r +declare -n r +./nameref13.sub: line 88: typeset: `12345': invalid variable name for name reference +declare -n foo +./nameref13.sub: line 97: typeset: `12345': invalid variable name for name reference +declare -n foo +declare -nx ref="var" +var +var +var +var +foo +foo +foo +foo +before +declare -n ref="var" +./nameref14.sub: line 23: typeset: var: not found +first +declare -n ref="var" +declare -x var="xxx" +invalid +declare -n ref="var" +declare -x var="5" +after +declare -n ref="var" +./nameref14.sub: line 32: typeset: var: not found +declare -n ref="var" +./nameref15.sub: line 1: local: warning: a: circular name reference +./nameref15.sub: line 1: warning: a: circular name reference +./nameref15.sub: line 1: `a[0]': not a valid identifier +declare -a a=([0]="0") +./nameref15.sub: line 1: local: warning: a: circular name reference +./nameref15.sub: line 1: warning: a: circular name reference +./nameref15.sub: line 1: warning: a: circular name reference +declare -a a=([0]="X") +declare -a b=([0]="X") +./nameref15.sub: line 1: local: warning: a: circular name reference +./nameref15.sub: line 1: warning: a: circular name reference +./nameref15.sub: line 1: `a[0]': not a valid identifier +declare -a b=([0]="0") +./nameref15.sub: line 19: typeset: warning: ref: circular name reference +./nameref15.sub: line 19: warning: ref: circular name reference +./nameref15.sub: line 20: warning: ref: circular name reference +./nameref15.sub: line 21: warning: ref: circular name reference +inside X +outside X +before: 7 +./nameref15.sub: line 32: typeset: warning: xxx: circular name reference +./nameref15.sub: line 32: warning: xxx: circular name reference +./nameref15.sub: line 33: warning: xxx: circular name reference +declare -n xxx="xxx" +./nameref15.sub: line 35: warning: xxx: circular name reference +xxx_func: inside: xxx = foo +after: foo +./nameref15.sub: line 46: typeset: ref: nameref variable self references not allowed +./nameref15.sub: line 48: ref: nameref variable self references not allowed +declare -n ref="re" +declare -n ref="re" +declare -- re="4" +4 +declare -n foo="var[@]" +declare -n ref="var[@]" +./nameref15.sub: line 65: var[@]: bad array subscript +declare -n bar="var[@]" +./nameref15.sub: line 70: var[@]: bad array subscript +declare -n a="b" +declare -n b="a[1]" +./nameref15.sub: line 78: warning: a: removing nameref attribute +declare -a a=([1]="foo") +declare -n b="a[1]" +./nameref15.sub: line 83: warning: a: removing nameref attribute +declare -a a=([1]="foo") +declare -n b="a[1]" +declare -n n="v" +declare -a v=([1]="1") +./nameref15.sub: line 99: typeset: n: not found +declare -a v=([0]="0" [1]="1") +declare -n n="v[1]" +declare -a v=([0]="0") +declare -n r1="y" +declare -n r2="x" +./nameref16.sub: line 12: typeset: x: not found +./nameref16.sub: line 12: typeset: y: not found +declare -n r1="y" +declare -n r2="x" +./nameref16.sub: line 21: typeset: x: not found +./nameref16.sub: line 21: typeset: y: not found +declare -n r1="y" +declare -n r2="x" +./nameref16.sub: line 33: typeset: x: not found +./nameref16.sub: line 33: typeset: y: not found +declare -n r1="y" +declare -n r2="x" +declare -- x="one" +declare -- y="two" +./nameref17.sub: line 8: declare: bar: not found +./nameref17.sub: line 9: unset: foo0: cannot unset: readonly variable +declare -nr foo0="bar" +declare -nr foo0="bar" +declare -- bar +./nameref17.sub: line 14: declare: foo0: readonly variable +./nameref17.sub: line 15: declare: foo0: readonly variable +declare -nr foo1 +./nameref17.sub: line 24: typeset: foo1: readonly variable +declare -nr foo1 +declare -n foo2="bar" +declare -r bar +./nameref17.sub: line 35: bar: readonly variable +./nameref17.sub: line 36: typeset: bar: readonly variable +declare -n foo2="bar" +declare -r bar +declare -- bar3="three" +./nameref17.sub: line 46: unset: foo3: cannot unset: readonly variable +./nameref17.sub: line 49: declare: bar3: readonly variable +declare -nr foo3="bar3" +declare -r bar3="three" +./nameref17.sub: line 51: declare: foo3: readonly variable +declare -nr foo4="bar4" +declare -- bar4="four" +./nameref17.sub: line 63: typeset: foo4: readonly variable +declare -nr foo4="bar4" +declare -nr foo4="bar4" +declare -- bar4="four" +./nameref17.sub: line 79: typeset: foo4: readonly variable +declare -nr foo4="bar4" +declare -nr foo4="bar4" +declare -- bar4="four" +declare -nr foo5 +declare -r foo5 +declare -nr foo5 +declare -r foo5 +./nameref18.sub: line 2: mapfile: `XXX[0]': not a valid identifier +./nameref18.sub: line 3: declare: XXX[0]: not found +./nameref18.sub: line 9: `XXX[0]': not a valid identifier +./nameref18.sub: line 10: declare: XXX[0]: not found +declare -n ref="XXX[0]" +declare -a XXX=([0]="4") +./nameref18.sub: line 24: `XXX[0]': not a valid identifier +declare -n ref="XXX[0]" +./nameref18.sub: line 25: declare: XXX[0]: not found +./nameref18.sub: line 29: read: `XXX[0]': not a valid identifier +./nameref18.sub: line 30: declare: XXX[0]: not found +./nameref18.sub: line 35: `XXX[0]': not a valid identifier +declare -n ref="XXX[0]" +./nameref18.sub: line 38: `XXX[0]': not a valid identifier +./nameref18.sub: line 38: declare: XXX[0]: not found +declare -n ref="var[123]" +./nameref18.sub: line 46: declare: var[123]: not found +declare -a var=([123]="") +declare -n ref="var[123]" +./nameref18.sub: line 50: declare: var[123]: not found +declare -a var=([123]="") +declare -n ref="var[123]" +./nameref18.sub: line 54: declare: var[123]: not found +declare -a var=([123]="X") +declare -n foo="bar" +declare -- foo="bar" +./nameref19.sub: line 9: declare: bar: not found +declare -n foo="bar" +declare -- foo="bar" +declare -i bar="11" +declare -inx foo6 +declare -ix foo6 +declare -n foo="bar" +declare -- bar="Hello World!" +declare -- foo="bar" +declare -- bar="Hello World!" +declare -n foo="bar" +declare -- bar +declare -- foo="bar" +declare -- bar +declare -a v=([0]="Y") +r: <Y> +v: <Y> +declare -n ref="var" +declare -a var=([0]="X") +declare -n ref="var" +declare -a var=([0]="X") +declare -n ref="var" +./nameref20.sub: line 23: declare: var: not found +outside: +declare -a foo=([0]="X") +declare -n ref="var" +declare -a var=([0]="X") +outside: +./nameref20.sub: line 38: declare: ref: not found +./nameref20.sub: line 38: declare: var: not found +declare -n ref="var" +declare -- var="X" +outside: +./nameref20.sub: line 45: declare: ref: not found +./nameref20.sub: line 45: declare: var: not found +declare -n ref="var" +declare -a var=([0]="Y") +declare -- ref="Y" +declare -- var="X" +ref=Y +declare -- ref="Y" +./nameref20.sub: line 61: declare: var: not found +ref=Y +declare -n ref="var" +declare -A var=([2]="" ) +declare -n ref="var" +declare -A var=([2]="" ) +declare -n ref="var" +declare -a var=([2]="") +declare -n ref="var" +declare -a var=([2]="") +declare -n ref="var" +declare -ai var=([1]="0") +declare -n ref="var" +declare -ai var=([1]="0") +declare -n ref="var" +declare -- var="1" diff --git a/tests/nameref.tests b/tests/nameref.tests new file mode 100644 index 0000000..f4af904 --- /dev/null +++ b/tests/nameref.tests @@ -0,0 +1,120 @@ +# basic nameref tests +bar=one +flow=two +flip=three + +foo=bar +typeset -n foo + +typeset -n fee=flow + +echo ${foo} +echo ${fee} + +typeset -n fee=flip +echo ${fee} + +typeset -n + +echo turning off nameref attribute on foo +typeset +n foo=other +echo ${foo} +echo after +n foo bar = $bar + +unset foo bar fee + +bar=one + +foo=bar +typeset -n foo + +foo=two printf "%s\n" $foo +foo=two eval 'printf "%s\n" $foo' + +foo=two echo $foo + +unset foo bar +# other basic assignment tests +bar=one + +echo "expect <one>" +recho ${bar} +typeset -n foo=bar +foo=two + +echo "expect <two>" +recho ${bar} + +# this appears to be a ksh93 bug; it doesn't unset foo here and messes up +# later +unset foo bar + +# initial tests of working inside shell functions +echoval() +{ + typeset -n ref=$1 + printf "%s\n" $ref +} + +foo=bar +bar=one +echo "expect <$foo>" +echoval foo +echo "expect <$bar>" +echoval bar + +unset foo bar +changevar() +{ + typeset -n v=$1 + + shift + v="$@" + echo "changevar: expect <$@>" + recho "$v" +} + +bar=one + +echo "expect <one>" +recho ${bar} +changevar bar two +echo "expect <two>" +recho $bar + +changevar bar three four five +echo "expect <three four five>" +recho "$bar" + +unset foo bar +unset -n foo bar +readonly foo=one +typeset -n bar=foo +bar=4 +foo=4 + +echo $foo +echo $bar + +assignvar() +{ + typeset -n ref=$1 + shift + ref="$@" +} + +readonly foo=one + +assignvar foo two three four +echo $foo + +var=abcde +x=var +declare -n v=var +# these two should display the same +echo ${!x//c/x} +echo ${v//c/x} + +for testfile in ./nameref[0-9].sub ./nameref[1-9][0-9].sub ; do + ${THIS_SH} "$testfile" +done diff --git a/tests/nameref1.sub b/tests/nameref1.sub new file mode 100644 index 0000000..50bb25d --- /dev/null +++ b/tests/nameref1.sub @@ -0,0 +1,13 @@ +# indirect referencing of a nameref returns the variable name it references +unset foo bar + +bar=one +foo=bar + +typeset -n foo + +echo ${foo} +echo ${!foo} + +# this is a current incompatibility +echo ${!foo[0]} diff --git a/tests/nameref10.sub b/tests/nameref10.sub new file mode 100644 index 0000000..2a1ba35 --- /dev/null +++ b/tests/nameref10.sub @@ -0,0 +1,64 @@ +# testing behavior of command substitution as one of expansions performed by +# array subscripting; should behave the same directly as when done through +# a nameref + +x[0]=42 +zero=0 +f() { typeset -n foo="$1"; declare -p foo; echo "$foo"; } + +f 'x[$zero]' + +x[$(echo 0)]=4 +declare -p x + +f 'x[$(echo 0)]' + +unset -f f +f() +{ + typeset -n foo="$1"; + + echo "x[i=0$(echo comsub >&2)]" + echo "${x[i=0$(echo comsub >&2)]}" + echo "${!1}" + echo "$foo" +} + +f 'x[i=0$(echo comsub >&2)]' + +unset -f f +unset x + +# problems with unset and namerefs pointing to non-existent variables pointed +# out after bash-4.3 released + +typeset -n foo=somevariable +foo=bar +unset foo # unsets somevariable +typeset -p foo somevariable +echo foo = $foo + +typeset -A foo # should create array variable named somevariable +foo["jug"]="brown" + +typeset -p foo somevariable +typeset -A foo='([jug]="brown" )' +typeset -p foo somevariable + +unset foo +typeset -p foo somevariable +unset -n foo +typeset -p foo somevariable + +unset bar +typeset -n foo=bar +typeset -p foo bar +unset foo +typeset -p foo bar +typeset -i foo +foo=4+4 +typeset -p foo bar +echo "$foo" + +unset foo +typeset -p foo bar diff --git a/tests/nameref11.sub b/tests/nameref11.sub new file mode 100644 index 0000000..402e501 --- /dev/null +++ b/tests/nameref11.sub @@ -0,0 +1,63 @@ +r=/; declare -n r ; unset r +declare -n r=/ ; unset -n r +declare -n r; r=/ ; unset -n r +declare -n r; declare r=/ ; unset -n r +declare -n r; for r in /; do :; done ; unset -n r +declare -n r; select r in /; do :; done <<< 1; echo x; echo $r ; unset -n r +declare -n r; ((r=0)) ; unset -n r +((r=0)); declare -n r ; unset -n r +r=/ declare -n r ; unset -n r +f() { declare -n r; }; r=/ f ; unset r +f() { echo $r; }; declare -n r; r=/ f ; unset -n r +declare -n r; : ${r:=/} ; unset -n r +declare -n r; exec {r}>/dev/null ; unset -n r +declare -n r; coproc r { :; }; echo $r ; unset r ; wait +declare -r RO=x; r=$RO; declare -n r; x=y; declare -n RO; RO=z; declare -p RO; echo "$RO" +s=/; declare -n r=s; declare -n s; echo $r ; unset -n r ; unset -n s +declare -n r=s; declare -n s; s=/ ; unset -n r; unset -n s +declare -n r; getopts x r -h ; unset r; unset -n r +declare -n r; mapfile r < /dev/null ; declare -p r; unset r ; unset -n r +mapfile r < /dev/null; declare -n r ; unset r ; unset -n r +declare -n r; printf -v r / ; unset -n r + +declare -n r; r="" ; unset -n r +declare -n r="" ; unset -n r +declare -n r; : ${r=} ; unset -n r +declare -n r; printf -v r '' ; unset -n r +r=""; declare -n r ; unset -n r +export r + +# coproc tests, since coproc sets and unsets variables +declare -r ROVAR=42 +declare -p ROVAR; coproc ROVAR { :; }; wait; declare -p ROVAR + +echo ${@:0}; coproc @ { :; }; wait ; echo ${@:0} + +declare -n ref=x; coproc ref { :; }; wait ; declare -p ref +unset -n ref ; unset ref + +declare -r RO RO_PID; coproc RO { :; }; declare -p RO_PID; wait; declare -p RO RO_PID + +declare -r RO2=a; declare -n ref_PID=RO2; coproc ref { :; }; wait; declare -p RO2 + +unset x y +set -- one two three + +y=2 +typeset -n x=y +echo ${x} + +unset -n x + +typeset -n y +echo $y + +unset -n y + +typeset -n y +y=2 +echo ${y} + +declare -n foo=bar +echo ${!foo[2]} +echo ${!bar} diff --git a/tests/nameref12.sub b/tests/nameref12.sub new file mode 100644 index 0000000..24c3370 --- /dev/null +++ b/tests/nameref12.sub @@ -0,0 +1,100 @@ +declare -n r +declare -n r +unset -n r + +r=foo +declare -n r=/ + +r=% +declare -n r +unset r + +declare -n r +r=^ +declare -p r + +unset -n r + +declare -n foo +declare -a foo +declare -p foo +foo[0]=7 +declare -p foo +unset foo + +declare -n x +declare x=42 +declare -p x + +declare -n -r RO=foo +declare -p RO + +unset -n r; unset r + +# the details of this may change; currently we put namerefs and values into +# the tempenv if the nameref value is an invalid variable name +f() { echo $r; } + +declare -n r +r=/ ${THIS_SH} < /dev/null +r=/ f + +unset -f f + +# the details of this may change; this will tell me when they do +declare -n foo ; declare -i foo=7*6 ; declare -p foo +unset -n foo +declare -n foo ; declare -i foo ; foo=7*6 ; declare -p foo + +# used to be buggy +f() +{ + unset var + declare -n ref=var + declare -n ref + declare -p ref +} +f + +unset -f f +f() +{ + local var + declare -n ref=var + declare -n ref + declare -p ref +} +f + +unset ref; unset -n ref +unset var + +var=foo +typeset -n ref=var[0] +readonly ref +typeset -p var + +var2=foo +typeset -n ref2=var2 +readonly ref2 +typeset -p var2 + +unset var +unset -n ref ref2 + +unset var; typeset -n ref=var +ref[0]=foo +typeset -p ref var +unset -n ref + +unset var; typeset -n ref +ref[0]=foo +typeset -p ref +unset -n ref + +ref=global +f() { declare -n ref=var; ref[0]=foo1; }; f +f() { declare -n ref=var; ref[0]=foo2; }; f +declare -p ref var + +declare -p global diff --git a/tests/nameref13.sub b/tests/nameref13.sub new file mode 100644 index 0000000..556fbdb --- /dev/null +++ b/tests/nameref13.sub @@ -0,0 +1,102 @@ +declare -nt r=a + +f() +{ + declare a + declare -n r=a + declare -p a r +} + +f +unset -f f + +f() +{ + declare a + declare -n r + r=a + declare -p a r +} +f +echo $? + +unset -f f + +P=12345 +function foo +{ + typeset -n r + typeset -n r=P + typeset -p r +} + +foo +unset P foo + +ref=outside + +f() +{ + unset var + declare -n ref=var + declare -n ref; + declare -p ref; +} +f + +unset ref foo + +typeset -n r=a + +f() +{ + typeset a + typeset -n r + typeset -n r + r=a + + typeset -p a r +} +f +echo $? +unset -n r +unset -f f + +function foo +{ + typeset -n r + typeset -n r + typeset -p r +} + +foo +unset -f foo + + +function foo +{ + typeset r + typeset -n r + typeset -p r +} +foo +unset -f foo + +foo() +{ + typeset -n foo + typeset foo=12345 + typeset -p foo +} +foo +unset -f foo + +foo() +{ + typeset -n foo + typeset -n foo=12345 + typeset -p foo +} +foo +unset -f foo + diff --git a/tests/nameref14.sub b/tests/nameref14.sub new file mode 100644 index 0000000..7880b00 --- /dev/null +++ b/tests/nameref14.sub @@ -0,0 +1,43 @@ +# exporting namerefs and putting namerefs in temp env post bash-4.3 + +typeset -nx ref=var; +typeset -p ref + +var=foo; str='' +printenv ref # var +ref+=$str printenv ref # var +ref+="$str" printenv ref # var +ref=$ref$str printenv ref # var + +export ref # follows nameref and exports var + +printenv var # foo +ref+=$str printenv var # foo +ref+="$str" printenv var # foo +ref=$ref$str printenv var # foo + +# none of these should change ref; should follow the nameref and export var +unset var; unset -n ref; typeset -n ref=var + +echo before +typeset -p ref var + +echo first +ref=xxx typeset -p ref var + +echo invalid +var= ref=5 typeset -p ref var + +echo after +typeset -p ref var + +# ref isn't exported, so none of the printenvs should print anything +unset var ; unset -n ref +typeset -n ref=var; +typeset -p ref + +var=foo; str='' +printenv ref +ref+=$str printenv ref +ref+="$str" printenv ref +ref=$ref$str printenv ref diff --git a/tests/nameref15.sub b/tests/nameref15.sub new file mode 100644 index 0000000..9fbacd4 --- /dev/null +++ b/tests/nameref15.sub @@ -0,0 +1,104 @@ +f() { local -n a=$1; a=X; } + +a=(0); f 'a[0]' +while [[ -v a ]]; do declare -p a; unset a; done + +a=(0); f 'a' +while [[ -v a ]]; do declare -p a; unset a; done + +b=(0); f 'b[0]' +while [[ -v a ]]; do typeset -p a; unset a; done +typeset -p b + +b=(0); f 'a[0]' +while [[ -v a ]]; do typeset -p a; unset a; done +typeset -p b + +add_X_echo() +{ + typeset -n ref=$1 + ref+=X + echo inside $ref +} + +ref= +add_X_echo ref +echo outside "$ref" +unset ref + +# same test, but assigning nameref variable circular reference directly +xxx_func() +{ + typeset -n xxx=xxx + xxx=foo + declare -p xxx + echo $FUNCNAME: inside: xxx = $xxx +} + +xxx=7 +echo before: $xxx +xxx_func +echo after: $xxx + +unset xxx +unset -f xxx_func + +typeset -n ref=ref + +typeset -n ref=re ref+=f +typeset -p ref +ref=4 +typeset -p ref re + +export ref +printenv ref +printenv re + +unset ref ; unset -n ref +unset foo; unset -n foo + +typeset -n foo=var[@] +typeset -p foo +typeset -n ref=var ref+=[@] +typeset -p ref + +ref=42 + +typeset -n bar +bar=var[@] +typeset -p bar +bar=7 + +unset a b +unset -n a b + +typeset -n a=b b +b=a[1] +typeset -p a b +a=foo +typeset -p a b + +unset a +typeset -n a=b +declare a=foo +typeset -p a b + +unset n v +unset -n n v + +v=(0 1) +typeset -n n=v +unset n[0] +typeset -p n v + +unset -n n + +v=(0 1) +typeset -n n=v +unset -n n +typeset -p n v + +v=(0 1) +declare -n n=v[1] +unset n +declare -p n v diff --git a/tests/nameref16.sub b/tests/nameref16.sub new file mode 100644 index 0000000..75c7ba1 --- /dev/null +++ b/tests/nameref16.sub @@ -0,0 +1,44 @@ +# post-bash-4.3 changes for more ksh93 compatibility when following nameref +# chains and using typeset/declare -n to operate on nameref variables rather +# than the variables they reference + +# don't follow nameref chain when using declare -n and at the global scope +unset -n r1 r2 + +typeset -n r1=r2 +typeset -n r2=x +typeset -n r1=y + +typeset -p r1 r2 x y + +# same behavior when in a shell function +foo() +{ + typeset -n r1=r2 + typeset -n r2=x + typeset -n r1=y + + typeset -p r1 r2 x y +} +unset -n r1 r2 +foo +unset -f foo + +# same behavior when namerefs aren't chained +unset -n r1 r2 + +typeset -n r1=z +typeset -n r2=x +typeset -n r1=y +typeset -p r1 r2 x y + +# same behavior when referenced variables have values +unset -n r1 r2 + +x=one +y=two +typeset -n r1=r2 +typeset -n r2=x +typeset -n r1=y + +typeset -p r1 r2 x y diff --git a/tests/nameref17.sub b/tests/nameref17.sub new file mode 100644 index 0000000..0cd5a42 --- /dev/null +++ b/tests/nameref17.sub @@ -0,0 +1,103 @@ +# test behavior of readonly namerefs and namerefs referencing readonly variables + +# readonly nameref variable referencing read-write global variable + +bar=one +declare -rn foo0=bar +unset foo0 # unsets bar +declare -p bar +unset -n foo0 # cannot unset +declare -p foo0 + +declare +r foo0 # modifies bar +declare -p foo0 bar +declare +r -n foo0 # error +declare +n foo0 # error +unset bar + +# readonly nameref variable without a value +typeset -n foo1 +typeset -r foo1 + +typeset -p foo1 + +typeset foo1=bar # error +typeset +r foo1 # no-op, follows nameref chain to nothing +typeset -p foo1 + +# nameref pointing to read-only global variable +foo2=bar +typeset -n foo2 +typeset -r foo2 # changes bar + +typeset -p foo2 bar + +foo2=bar # error? +typeset +r foo2 # attempts to change bar, error +typeset -p foo2 bar # nameref unchanged + +# read-only nameref pointing to read-only global variable +bar3=three +declare -rn foo3=bar3 +unset foo3 # unsets bar3 + +bar3=three +declare -p bar3 +unset -n foo3 # cannot unset + +readonly bar3 +declare +r foo3 # error attempting to reference bar3 +declare -p foo3 bar3 +declare +r -n foo3 # error + +# readonly nameref pointing to read-write local -- can we remove nameref attr? +func() +{ + typeset bar4=four + + # readonly nameref + typeset -n -r foo4=bar4 + + typeset -p foo4 bar4 + + typeset +n foo4 + + typeset -p foo4 +} +func +unset -f func + +# readonly nameref pointing to read-write global -- can we remove nameref attr? +bar4=four +foo4=bar4 +# readonly nameref +typeset -n foo4 +typeset -r -n foo4 + +typeset -p foo4 bar4 + +typeset +n foo4 +typeset -p foo4 + +bar4=four +: ${foo4=bar4} + +typeset -p foo4 bar4 + +# readonly local nameref without a value -- can we remove nameref attribute? +func() +{ + declare -r -n foo5 + declare -p foo5 + declare +n foo5 + declare -p foo5 +} +func +unset -f func + +# readonly global nameref without a value -- can we remove nameref attribute? +declare -n foo5 +declare -r -n foo5 +declare -p foo5 +declare +n foo5 +declare -p foo5 diff --git a/tests/nameref18.sub b/tests/nameref18.sub new file mode 100644 index 0000000..1b02295 --- /dev/null +++ b/tests/nameref18.sub @@ -0,0 +1,54 @@ +declare -n ref=XXX[0] +mapfile ref <<< $'1\n2' +declare -p XXX[0] + +unset -n ref + +declare -n ref=XXX[0] +declare -A ref +ref[foo]=bar +declare -p XXX[0] + +unset -n ref +unset XXX + +typeset -n ref=XXX[0] +typeset ref=4 + +typeset -p ref XXX + +unset -n ref +unset XXX + +declare -n ref=XXX[0] +ref+=([2]=x) +declare -p ref XXX[0] +unset -n ref + +declare -n ref=XXX[0] +read -a ref <<< "A B C" +declare -p XXX[0] +unset -n ref + +declare -n ref=XXX[0] +unset ref +ref=() +declare -p ref + +coproc ref { :; }; declare -p ${!ref} +wait + +unset -n ref + +declare -n ref=var[123] +unset ref +declare ref= +declare -p ref ${!ref} var + +unset ref +declare ref+= +declare -p ref ${!ref} var + +declare +t ref +ref=X +declare -p ref ${!ref} var diff --git a/tests/nameref19.sub b/tests/nameref19.sub new file mode 100644 index 0000000..d46c003 --- /dev/null +++ b/tests/nameref19.sub @@ -0,0 +1,51 @@ +# can we unset the nameref attribute on variables with values that reference +# unset variables? + +unset bar +declare -n foo="bar" +declare -p foo + +declare +n foo +declare -p foo bar + +declare -n foo +declare -p foo + +# let's try removing the nameref attribute -- other attributes and assignments +# apply to the nameref target + +declare +n -i foo=7+4 +declare -p foo bar + +unset foo bar + +# but if the nameref variable doesn't have a value, the attributes apply to +# the nameref variable itself. thanks ksh93 + +declare -n foo6 +declare -xi foo6 +declare -p foo6 + +# and when we remove the nameref attribute, the other attributes remain + +declare +n foo6 +declare -p foo6 + +unset foo6 + +# make sure these cases continue to work + +# nameref referencing an existing, set variable +declare -n foo=bar +bar='Hello World!' +declare -p foo bar +declare +n foo +declare -p foo bar +unset foo bar + +# nameref referencing an existing, unset variable +declare -n foo=bar +declare bar +declare -p foo bar +declare +n foo +declare -p foo bar diff --git a/tests/nameref2.sub b/tests/nameref2.sub new file mode 100644 index 0000000..547cc19 --- /dev/null +++ b/tests/nameref2.sub @@ -0,0 +1,7 @@ +# test readonly nameref variables +# ksh93 allows this but not typeset -rn ref=foo? +typeset -n ref=foo +readonly ref +foo=4 + +echo $ref diff --git a/tests/nameref20.sub b/tests/nameref20.sub new file mode 100644 index 0000000..1e6faec --- /dev/null +++ b/tests/nameref20.sub @@ -0,0 +1,71 @@ +# a collection of cases in bug reports after bash-5.0-alpha was released + +declare -n r=v[0] +v=(X); r=Y +declare -p ${!v*} +printf "%s: <%s>\n" "r" "$r" "v" "$v" + +unset -n r +unset -v v + +declare -n ref=var; declare -a ref +ref=(X) +declare -p ref var + +unset -n ref +unset -v var + +f() { declare -n ref=var; declare ref=(X); declare -p ref var; }; +f + +unset -f f + +f() { declare -n ref=var; declare -g ref=(X); declare -p ref var; }; + +declare -n ref=foo +f +echo outside: +declare -p foo + +unset -n ref +unset -v foo +unset -f f + +f() { declare -n ref=var; declare -a ref; ref=(X); declare -p ref var; } + +f +echo outside: +declare -p ref var +unset -f f + +f() { declare -n ref=var; declare ref; ref=X; declare -p ref var; } + +f +echo outside: +declare -p ref var + +unset -f f + +unset -n ref; unset var + +f() +{ + declare var=X; declare -n ref=var; declare ref=(Y) + declare -p ref var +} +f + +unset -f f + +declare -n ref=var +f() { local ref=Y; declare -p ref var; local; } + +var=X +f + +unset -v var +f + +unset -n ref +unset -f f + diff --git a/tests/nameref21.sub b/tests/nameref21.sub new file mode 100644 index 0000000..a555a08 --- /dev/null +++ b/tests/nameref21.sub @@ -0,0 +1,56 @@ +# issues with local variables and local namerefs post-bash-4.4 + +f() +{ + local -n ref=var + local -A ref=([1]=) +# declare -p ref var + ref=([2]=) + declare -p ref var +} + +unset ref var +f + +unset ref; var=0 +f + +unset var +unset -f f + +f() +{ + local -n ref=var + local -a ref=([1]=) + ref=([2]=) + declare -p ref var +} + +unset ref var +f + +unset ref; var=0 +f + +unset var +unset -f f + +f() { local -n ref=var; local -i ref=([1]=); declare -p ref var; } + +unset var +f + +var=0 +f + +unset var +unset -f f + +f() { local -n ref=var; local ref=1; declare -p ref var; } + +var=0 +f + +unset var +unset -f f + diff --git a/tests/nameref3.sub b/tests/nameref3.sub new file mode 100644 index 0000000..5790291 --- /dev/null +++ b/tests/nameref3.sub @@ -0,0 +1,37 @@ +# nameref requires changes to unset +bar=one +typeset -n foo=bar + +# normal unset unsets only variable nameref references +# need unset -n to unset nameref itself +unset foo +echo "expect <unset>" +recho ${bar-unset} +echo "expect <unset>" +recho ${foo-unset} +echo "expect <bar>" +recho ${!foo} +unset -n foo +echo "expect <unset>" +recho "${!foo-unset}" + +readonly bar=two +typeset -n foo=bar + +unset foo # this should fail because bar is readonly + +echo "expect <two>" +echo ${bar-unset} +echo "expect <two>" +echo ${foo-unset} + +# one question is what happens when you unset the underlying variable +qux=three +typeset -n ref +ref=qux + +echo $ref +unset qux +echo ${ref-unset} +qux=four +echo ${ref-unset} diff --git a/tests/nameref4.sub b/tests/nameref4.sub new file mode 100644 index 0000000..4dd86b2 --- /dev/null +++ b/tests/nameref4.sub @@ -0,0 +1,221 @@ +# test suite cribbed from ksh93 nameref tests +typeset -i errors=0 +ckval() +{ + typeset -n one=$1 + + if [[ $one != $2 ]]; then + echo "one=$one != 2=$2" + (( errors++ )) + fi +} + +ckref() +{ + typeset -n one=$1 two=$2 + + if [[ $one != $two ]]; then + echo "one=$one != two=$two" + (( errors++ )) + fi +} + +name=first + +ckref name name + +func1() +{ + typeset -n color=$1 + func2 color +} + +func2() +{ + typeset color=$1 + set -- ${color[@]} + printf "<%s>" "$@" + echo +} + +typeset -A color +color[apple]=red +color[grape]=purple +color[banana]=yellow + +# XXX +#func1 color + +unset foo bar +export bar=foo +typeset -n foo=bar +ckval foo foo + +# XXX - need to see if we can do checks for self-referencing at assignment +# time +command typeset -n xx=yy +command typeset -n yy=xx +echo $? + +unset foo bar +unset -n foo bar +set foo +typeset -n bar=$1 +foo=hello +ckval bar hello + +# XXX -- another self-referencing error? +# ksh93 makes this another invalid self-reference +unset foo +unset -n bar + +bar=123 +foobar() +{ + typeset -n foo=bar + typeset -n foo=bar + + ckval foo 123 +} + +typeset -n short=long +short=( a b ) +echo "expect <a b>" +echo ${long[@]} +unset long +unset -n short + +# assignment to a previously-unset variable +typeset -n short=long +short=foo +echo "expect <foo>" +echo ${long} +unset long +unset -n short + +unset foo bar + +# simple array references and assignments +typeset -n foo=bar +bar=( 1 3 5 7 9) +echo ${foo[@]} +echo ${foo[4]} +foo[2]=42 +echo ${bar[@]} + +barfunc() +{ + typeset -n v=$1 + echo ${v[@]} + echo ${v[4]} + v[2]=44 + echo ${bar[@]} +} +barfunc bar + +unset -f foobar +unset bar +unset -n foo + +# should ref at global scope survive call to foobar()? +unset ref x +typeset -n ref +x=42 +foobar() +{ + local xxx=3 + ref=xxx + return 0 +} +echo ${ref-unset} +ref=x +foobar +ckval ref xxx +ckval x xxx + +# assignment in a function to something possibly out of scope +assignvar() +{ + typeset -n v=$1 + shift + v="$@" +} + +assignvar lex a b c d e +echo "expect <a b c d e>" +recho "${lex}" + +unset foo bar short long + +typeset -n foo='x[2]' + +x=(zero one two three four) +foo=seven + +echo "expect <zero> <one> <seven> <three> <four>" +recho "${x[@]}" + +unset ref x +unset -n ref + +typeset -n ref +ref=x +# make sure nameref to a previously-unset variable creates the variable +ref=42 +ckval x 42 + +# make sure they work inside arithmetic expressions +unset foo bar ref x xxx +unset -n ref + +typeset -i ivar +typeset -n iref=ivar + +ivar=4+3 +ckval ivar 7 +iref+=5 +ckval ivar 12 +echo $(( iref+4 )) +(( iref=17 )) +ckval ivar 17 + +typeset +n iref +unset iref ivar + +typeset +n foo bar +unset foo bar + +# should the reference do immediate evaluation or deferred? +set -- one two three four +bar=4 +# XXX - what does foo get set to here? +typeset -n foo='bar[0]' +echo "expect <4>" +echo ${bar[0]} +echo "expect <4>" +echo ${foo} +echo "expect <4>" +echo $foo +ckval foo $bar + +# Need to add code and tests for nameref to array subscripts +bar=(one two three four) + +typeset -n foo='bar[0]' +typeset -n qux='bar[3]' +echo "expect <one>" +echo ${bar[0]} +echo "expect <one>" +echo ${foo} +echo "expect <one>" +echo $foo +ckval foo $bar + +echo "expect <four>" +echo $qux +ckval qux ${bar[3]} + +# Need to add code and tests for `for' loop nameref variables + +echo errors = $errors +exit $errors diff --git a/tests/nameref5.sub b/tests/nameref5.sub new file mode 100644 index 0000000..2c67a94 --- /dev/null +++ b/tests/nameref5.sub @@ -0,0 +1,50 @@ +# nameref variables as for loop index variables are special +v1=1 +v2=2 + +# simple for loop +for v in v1 v2 +do + typeset -n ref=$v + echo $ref +done +unset v + +set -- first second third fourth fifth + +# unless you put a ${!v} in the for loop, ksh93 misbehaves +typeset -n v=v1 +for v in v1 v2; do + echo "${!v}: $v" +done +unset v + +# example cribbed from ksh93 o'reilly book +first="I am first" +second="I am in the middle" +third="I am last" + +typeset -n ref=first +for ref in first second third ; do + echo "ref -> ${!ref}, value: $ref" +done +echo final state: "ref -> ${!ref}, value: $ref" + +readonly one=1 +readonly two=2 +readonly three=3 + +typeset -n ref=one +for ref in one two three; do + echo "ref -> ${!ref}, value: $ref" +done +echo final state: "ref -> ${!ref}, value: $ref" + +unset ref +typeset -n ref=one +readonly ref + +for ref in one two three; do + echo "ref -> ${!ref}, value: $ref" +done +echo final state: "ref -> ${!ref}, value: $ref" diff --git a/tests/nameref6.sub b/tests/nameref6.sub new file mode 100644 index 0000000..cf70d41 --- /dev/null +++ b/tests/nameref6.sub @@ -0,0 +1,44 @@ +# these should be errors +typeset -n x=x +#echo $x -- $? + +typeset -n x[3]=x +#echo $x -- $? + +x=(the browns suck) +y=(one two three) +# should be an error but not disturb the current contents of x +# maybe rethink that later +typeset -n x=y +echo $x -- $? + +typeset -n + +unset x y + +y=42 +typeset -i x=1 + +# the integer attribute causes arithmetic eval to be done +# we should not allow namerefs to non-identifiers +typeset -n x=y +echo $x -- $? + +typeset +n x +echo $x -- $? + +# same kind of thing + +unset -n x +unset y + +set -- first second third +y=2 +typeset -i x=1 + +typeset -n x=y +echo $x -- $? +echo ${x} -- $? + +typeset +n x +echo $x -- $? diff --git a/tests/nameref7.sub b/tests/nameref7.sub new file mode 100644 index 0000000..19bdc98 --- /dev/null +++ b/tests/nameref7.sub @@ -0,0 +1,18 @@ +fn () +{ + declare -n var=foo; var=bar +} + +unset foo +fn +echo ${foo:-unset} + +unset -f fn +unset foo +fn() +{ + declare -n var; var=foo +} + +fn +echo ${foo:-unset} diff --git a/tests/nameref8.sub b/tests/nameref8.sub new file mode 100644 index 0000000..2380868 --- /dev/null +++ b/tests/nameref8.sub @@ -0,0 +1,61 @@ +function f1 +{ + typeset -n v=$1 + + v=inside +} + +v=global +f1 v +echo $v + +unset v +unset -f f1 + +function foo +{ + typeset x=one + + typeset -n y=$1 + y=two + echo inside: $x +} + +foo x +echo outside: $x + +function foo2 +{ + typeset -n x=$1 + + x=foo +} + +foo2 x +echo $x + +unset -f foo +function foo { typeset -n v=$1; v=local; } + +v=global +foo v +echo $v + +unset v + +# invalid self reference at global scope +typeset -n v=v + +# can we catch a circular self-reference? +typeset -n v=w +typeset -n w=x +typeset -n x=v + +x=4 +echo x = $x + +unset -n v w x + +# can we keep local variables invisible when we add nameref attribute? +function f { typeset x; typeset -n x; x=y; } +f diff --git a/tests/nameref9.sub b/tests/nameref9.sub new file mode 100644 index 0000000..e76c21b --- /dev/null +++ b/tests/nameref9.sub @@ -0,0 +1,8 @@ +arr=( idx1 idx2 ) +i='arr[1]' +echo ${!i} +echo ${!i/x/X} + +typeset -n f='arr[1]' +echo ${f} +echo ${f/x/X} diff --git a/tests/new-exp.right b/tests/new-exp.right new file mode 100644 index 0000000..c0f78fb --- /dev/null +++ b/tests/new-exp.right @@ -0,0 +1,672 @@ +argv[1] = <foo bar> +argv[1] = <foo> +argv[1] = </usr/homes/chet> +argv[1] = </usr/homes/chet> +argv[1] = </usr/homes/chet> +./new-exp.tests: line 28: HOME: }: syntax error: operand expected (error token is "}") +unset +argv[1] = </usr/homes/chet> +argv[1] = </usr/homes/chet> +argv[1] = </usr/homes/chet> +argv[1] = </usr/homes/chet> +argv[1] = </usr/homes/chet> +argv[1] = </usr/homes/chet> +argv[1] = </usr/homes/chet> +argv[1] = <*@> +argv[1] = <*@> +argv[1] = <@*> +argv[1] = <)> +argv[1] = <")"> +argv[1] = <-abcd> +argv[2] = <-> +argv[1] = <-abcd> +argv[2] = <-> +argv[1] = <-abcd-> +bar foo +bar foo +bar foo +barfoo +barfoo +\x +argv[1] = <abcd> +argv[1] = <efg> +argv[2] = <nop> +argv[1] = <efg> +argv[2] = <nop> +argv[1] = <hijklmnop> +argv[1] = <abcdefghijklmnop> +argv[1] = <abcdefghijklmnop> +argv[1] = <ab cd> +argv[2] = <ef> +argv[1] = <gh ij> +argv[2] = <kl mn> +argv[1] = <gh ij> +argv[2] = <kl mn> +argv[3] = <op> +argv[1] = <ab cd> +argv[2] = <ef> +argv[3] = <gh ij> +argv[4] = <kl mn> +argv[5] = <op> +argv[1] = </home/chet/foo//bar/abcabcabc> +argv[1] = <home/chet/foo//bar/abcabcabc> +argv[1] = <home> +argv[1] = <home> +argv[1] = <home> +argv[1] = <home> +argv[1] = <abcdefghijklmnop> +argv[1] = <4> +argv[1] = <op> +argv[1] = <abcdefghijklmnop> +argv[1] = <abcdefghijklmnop> +argv[1] = <a> +argv[2] = <b> +argv[3] = <c> +argv[4] = <d> +argv[1] = <a> +argv[2] = <b c> +argv[3] = <d> +./new-exp.tests: line 184: ABX: unbound variable +./new-exp.tests: line 188: $6: cannot assign in this way +argv[1] = <xxcde> +argv[1] = <axxde> +argv[1] = <abxyz> +argv[1] = <abbcde> +argv[1] = <abcde> +argv[1] = <abcabe> +argv[1] = <abcdlast> +argv[1] = <abcde> +argv[1] = <xxcd> +argv[1] = <abxx> +argv[1] = <xxgh> +argv[1] = <efgh> +argv[1] = <xxfgh> +argv[1] = <zagh> +argv[1] = <zaza> +argv[1] = <zagh> +argv[1] = <efza> +argv[1] = <yyy> +argv[2] = <yyy> +argv[3] = <yyy> +argv[4] = <yyy> +argv[5] = <yyy> +argv[6] = <yyy> +argv[1] = <yyy> +argv[2] = <yyy> +argv[3] = <yyy> +argv[4] = <yyy> +argv[5] = <yyy> +argv[6] = <yyy> +argv[1] = <yyy> +argv[2] = <yyy> +argv[3] = <yyy> +argv[4] = <yyy> +argv[5] = <yyy> +argv[6] = <yyy> +argv[1] = <yyy> +argv[2] = <efgh> +argv[3] = <ijkl> +argv[4] = <mnop> +argv[5] = <qrst> +argv[6] = <uvwx> +argv[1] = <abxx> +argv[2] = <efxx> +argv[3] = <ijxx> +argv[4] = <mnxx> +argv[5] = <qrxx> +argv[6] = <uvxx> +argv[1] = <xxcd> +argv[1] = <xxcd> +argv[2] = <xxgh> +argv[3] = <xxkl> +argv[4] = <xxop> +argv[5] = <xxst> +argv[6] = <xxwx> +argv[1] = <abxx> +argv[2] = <efxx> +argv[3] = <ijxx> +argv[4] = <mnxx> +argv[5] = <qrxx> +argv[6] = <uvxx> +argv[1] = <zaza> +argv[1] = <ijza> +argv[1] = <zaza> +argv[2] = <zaza> +argv[3] = <zaza> +argv[4] = <zaza> +argv[5] = <zaza> +argv[6] = <zaza> +argv[1] = <zacd> +argv[2] = <zagh> +argv[3] = <zakl> +argv[4] = <zaop> +argv[5] = <zast> +argv[6] = <zawx> +argv[1] = <yyy> +argv[2] = <yyy> +argv[3] = <yyy> +argv[4] = <yyy> +argv[5] = <yyy> +argv[6] = <yyy> +argv[1] = <yyy> +argv[2] = <efgh> +argv[3] = <ijkl> +argv[4] = <mnop> +argv[5] = <qrst> +argv[6] = <uvwx> +argv[1] = <abcd> +argv[2] = <efgh> +argv[3] = <ijkl> +argv[4] = <mnop> +argv[5] = <qrst> +argv[6] = <uvwyyy> + +This +string +has +multiple +lines. +This-string-has-multiple-lines. +this is a test of proc subst +this is test 2 +a +./new-exp2.sub: line 42: /tmp/redir-notthere: No such file or directory +1 + +./new-exp2.sub: line 49: 1111111111111111111111: command not found + +argv[1] = <6> +./new-exp.tests: line 289: ${#:}: bad substitution +argv[1] = <'> +argv[1] = <"> +argv[1] = <"hello"> +argv[1] = <> +argv[1] = <> +argv[1] = <> +argv[1] = <abcdef> +argv[1] = <abc def> +argv[1] = <abcdef> +argv[1] = <abc> +argv[2] = <def> +argv[1] = <abcdef> +argv[1] = <abc def> +argv[1] = <abcdef> +argv[1] = <abc def> +argv[1] = <ab> +argv[2] = <cd> +argv[3] = <ef> +argv[4] = <gh> +argv[1] = <ab> +argv[2] = <cd> +argv[3] = <ef> +argv[4] = <gh> +argv[1] = <ab> +argv[2] = <cd> +argv[3] = <ef> +argv[4] = <gh> +argv[1] = <> +argv[1] = <> +argv[1] = <> +argv[1] = <> +argv[1] = <> +argv[1] = <> +argv[1] = <hijklmnopqrstuv> +argv[1] = <pqrstuv> +argv[1] = <uvwxyz> +argv[1] = <abcdefghijklmnopqrstuvwxyz> +argv[1] = <abcdefghijklmnopqrst> +argv[1] = <klmnopq> +argv[1] = <klmnopq> +argv[1] = <klmnopq> +argv[1] = <"2 3"> +argv[1] = <"2:3"> +argv[1] = <"34"> +argv[1] = <"3456"> +argv[1] = <"3456"> +argv[1] = <"3456"> +argv[1] = <^A> +argv[2] = <^B> +argv[3] = <^?> +argv[1] = <^A> +argv[2] = <^B> +argv[3] = <^?> +argv[1] = <^A> +argv[2] = <^B> +argv[3] = <^?> +argv[1] = <^A> +argv[2] = <^B> +argv[3] = <^?> +argv[1] = <one/two> +argv[1] = <one/two> +argv[1] = <two> +argv[1] = <oneonetwo> +argv[1] = <onetwo> +argv[1] = <two> +argv[1] = <oneonetwo> +argv[1] = <a> +argv[1] = <defghi> +argv[1] = <efghi> +argv[1] = <e*docrine> +argv[1] = <e*docri*e> +argv[1] = <endocrine> +argv[1] = <endocrine> +argv[1] = <endocrine> +argv[1] = <endocrine> +argv[1] = <endocrine> +argv[1] = <endocrine> +x +x +x +xabc +x +x +argv[1] = </usr/bin> +argv[2] = </bin> +argv[3] = </usr/local/bin> +argv[4] = </usr/gnu/bin> +argv[5] = </usr/bin/X11> +argv[6] = </sbin> +argv[7] = </usr/sbin> +argv[1] = <r> +argv[2] = <s> +argv[3] = <t> +argv[4] = <u> +argv[5] = <v> +argv[6] = <w> +argv[7] = <x> +argv[8] = <y> +argv[9] = <z> +argv[1] = <r> +argv[2] = <s> +argv[3] = <t> +argv[4] = <u> +argv[5] = <v> +argv[6] = <w> +argv[7] = <x> +argv[8] = <y> +argv[9] = <z> +argv[1] = <r> +argv[2] = <s> +argv[3] = <t> +argv[4] = <u> +argv[5] = <v> +argv[6] = <w> +argv[7] = <x> +argv[8] = <y> +argv[9] = <z> +argv[1] = <r> +argv[2] = <s> +argv[3] = <t> +argv[4] = <u> +argv[5] = <v> +argv[6] = <w> +argv[7] = <x> +argv[8] = <y> +argv[9] = <z> +argv[1] = <a> +argv[2] = <a> +argv[3] = <a> +argv[4] = <a> +argv[5] = <a> +argv[6] = <a> +argv[7] = <a> +argv[8] = <a> +argv[9] = <a> +argv[1] = <a> +argv[2] = <a> +argv[3] = <a> +argv[4] = <a> +argv[5] = <a> +argv[6] = <a> +argv[7] = <a> +argv[8] = <a> +argv[9] = <a> +argv[1] = <r> +argv[2] = <s> +argv[3] = <t> +argv[4] = <u> +argv[5] = <v> +argv[6] = <w> +argv[7] = <x> +argv[8] = <y> +argv[9] = <z> +argv[1] = <r> +argv[2] = <s> +argv[3] = <t> +argv[4] = <u> +argv[5] = <v> +argv[6] = <w> +argv[7] = <x> +argv[8] = <y> +argv[9] = <z> +argv[1] = <r> +argv[2] = <s> +argv[3] = <t> +argv[4] = <u> +argv[5] = <v> +argv[6] = <w> +argv[7] = <x> +argv[8] = <y> +argv[9] = <z> +argv[1] = <r> +argv[2] = <s> +argv[3] = <t> +argv[4] = <u> +argv[5] = <v> +argv[6] = <w> +argv[7] = <x> +argv[8] = <y> +argv[9] = <z> +argv[1] = <r> +argv[2] = <s> +argv[3] = <t> +argv[4] = <u> +argv[5] = <v> +argv[6] = <w> +argv[7] = <x> +argv[8] = <y> +argv[9] = <z> +argv[1] = <r> +argv[2] = <s> +argv[3] = <t> +argv[4] = <u> +argv[5] = <v> +argv[6] = <w> +argv[7] = <x> +argv[8] = <y> +argv[9] = <z> +argv[1] = <a> +argv[2] = <a> +argv[3] = <a> +argv[4] = <a> +argv[5] = <a> +argv[6] = <a> +argv[7] = <a> +argv[8] = <a> +argv[9] = <a> +argv[1] = <a> +argv[2] = <a> +argv[3] = <a> +argv[4] = <a> +argv[5] = <a> +argv[6] = <a> +argv[7] = <a> +argv[8] = <a> +argv[9] = <a> +argv[1] = <r> +argv[2] = <s> +argv[3] = <t> +argv[4] = <u> +argv[5] = <v> +argv[6] = <w> +argv[7] = <x> +argv[8] = <y> +argv[9] = <z> +argv[1] = <r> +argv[2] = <s> +argv[3] = <t> +argv[4] = <u> +argv[5] = <v> +argv[6] = <w> +argv[7] = <x> +argv[8] = <y> +argv[9] = <z> +./new-exp.tests: line 507: $9: unbound variable +./new-exp.tests: line 508: 9: unbound variable +./new-exp.tests: line 509: UNSET: unbound variable +./new-exp.tests: line 510: UNSET: unbound variable +./new-exp.tests: line 511: UNSET: unbound variable +./new-exp.tests: line 512: UNSET: unbound variable +./new-exp.tests: line 513: UNSET: unbound variable +argv[1] = <5> +argv[1] = <#> +argv[1] = <#> +argv[1] = <> +argv[1] = <_QUANTITY> +argv[2] = <_QUART> +argv[3] = <_QUEST> +argv[4] = <_QUILL> +argv[5] = <_QUOTA> +argv[6] = <_QUOTE> +argv[1] = <_QUANTITY> +argv[2] = <_QUART> +argv[3] = <_QUEST> +argv[4] = <_QUILL> +argv[5] = <_QUOTA> +argv[6] = <_QUOTE> +argv[1] = <_QUANTITY> +argv[2] = <_QUART> +argv[3] = <_QUEST> +argv[4] = <_QUILL> +argv[5] = <_QUOTA> +argv[6] = <_QUOTE> +argv[1] = <_QUANTITY-_QUART-_QUEST-_QUILL-_QUOTA-_QUOTE> +argv[1] = <_QUANTITY> +argv[2] = <_QUART> +argv[3] = <_QUEST> +argv[4] = <_QUILL> +argv[5] = <_QUOTA> +argv[6] = <_QUOTE> +argv[1] = <_QUANTITY> +argv[2] = <_QUART> +argv[3] = <_QUEST> +argv[4] = <_QUILL> +argv[5] = <_QUOTA> +argv[6] = <_QUOTE> +./new-exp3.sub: line 23: ${!_Q* }: bad substitution +./new-exp3.sub: line 28: ${!1*}: bad substitution +./new-exp3.sub: line 30: ${!@*}: bad substitution +Case01---3---A:B:C--- +Case02---1---A B C::--- +Case03---3---A:B:C--- +Case04---3---A:B:C--- +Case05---3---A:B:C--- +Case06---1---A B C::--- +Case07---3---A:B:C--- +Case08---3---A:B:C--- +./new-exp.tests: line 533: ${$(($#-1))}: bad substitution +argv[1] = <a> +argv[2] = <b> +argv[3] = <c> +argv[4] = <d> +argv[5] = <e> +argv[6] = <f> +argv[7] = <g> +argv[1] = <a> +argv[2] = <b> +argv[3] = <c> +argv[4] = <d> +argv[5] = <e> +argv[1] = <a> +argv[1] = <a> +argv[2] = <b> +argv[1] = <> +./new-exp.tests: line 552: $(($# - 2)): substring expression < 0 +argv[1] = <bin> +argv[2] = <bin> +argv[3] = <ucb> +argv[4] = <bin> +argv[5] = <.> +argv[6] = <sbin> +argv[7] = <sbin> +argv[1] = </> +argv[2] = </> +argv[3] = </> +argv[4] = </> +argv[5] = </> +argv[6] = </> +argv[1] = <bin> +argv[2] = <usr/bin> +argv[3] = <usr/ucb> +argv[4] = <usr/local/bin> +argv[5] = <.> +argv[6] = <sbin> +argv[7] = <usr/sbin> +argv[1] = </bin> +argv[2] = </usr/bin> +argv[3] = </usr/ucb> +argv[4] = </usr/local/bin> +argv[5] = <.> +argv[6] = </sbin> +argv[7] = </usr/sbin> +argv[1] = </full/path/to> +argv[1] = </> +argv[1] = <full/path/to/x16> +argv[1] = <x16> +two +one +ne +one + +one +one +one +1 2 3 4 5 6 7 8 9 +9 +9 +0 +9 +8 9 +123456789 +9 +9 +4, A B C D +2, C D +h +h +--blah +--blah +lah +lah +abcde abcfg abchi +foode foofg foohi +argv[1] = <> +argv[1] = <+> +argv[1] = <+^?> +argv[1] = <+> +argv[1] = <^?2> +argv[1] = <^?2> +argv[1] = <^?> +argv[1] = <^?> +argv[1] = <> +argv[1] = <> +argv[1] = <> +argv[1] = <> +argv[1] = <12> +argv[1] = <> +argv[1] = <> +argv[1] = </tmp/test/TEST> +foo is a function +foo () +{ + echo < <(cat x1) +} +foo () +{ + echo < <(cat x1) +} +bar () { echo < <(cat x1) } +bar is a function +bar () +{ + echo < <(cat x1) +} +start;ing0;ing1;ing2;ing3;ing4;ing5;ing6;ing7;ing8;ing9;ing10;ing11;ing12;ing13;ing14;ing15;ing16;ing17;ing18;ing19;ing20;ing21;ing22;ing23;ing24;ing25;ing26;ing27;ing28;ing29;ing30;ing31;ing32;ing33;ing34;ing35;ing36;ing37;ing38;ing39;ing40;ing41;ing42;ing43;ing44;ing45;ing46;ing47;ing48;ing49;ing50;ing51;ing52;ing53;ing54;ing55;ing56;ing57;ing58;ing59;ing60;ing61;ing62;ing63;ing64;ing65;ing66;ing67;ing68;ing69;ing70;ing71;ing72;ing73;ing74;ing75;ing76;ing77;ing78;ing79;ing80;ing81;ing82;ing83;ing84;ing85;ing86;ing87;ing88;ing89;ing90;ing91;ing92;ing93;ing94;ing95;ing96;ing97;ing98;ing99;ing100;ing101;ing102;ing103;ing104;ing105;ing106;ing107;ing108;ing109;ing110;ing111;ing112;ing113;ing114;ing115;ing116;ing117;ing118;ing119;ing120;ing121;ing122;ing123;ing124;ing125;ing126;ing127;ing128;ing129;ing130;ing131;ing132;ing133;ing134;ing135;ing136;ing137;ing138;ing139;ing140;ing141;ing142;ing143;ing144;ing145;ing146;ing147;ing148;ing149;ing150;ing151;ing152;ing153;ing154;ing155;ing156;ing157;ing158;ing159;ing160;ing161;ing162;ing163;ing164;ing165;ing166;ing167;ing168;ing169;ing170;ing171;ing172;ing173;ing174;ing175;ing176;ing177;ing178;ing179;ing180;ing181;ing182;ing183;ing184;ing185;ing186;ing187;ing188;ing189;ing190;ing191;ing192;ing193;ing194;ing195;ing196;ing197;ing198;ing199;ing200;ing201;ing202;ing203;ing204;ing205;ing206;ing207;ing208;ing209;ing210;ing211;ing212;ing213;ing214;ing215;ing216;ing217;ing218;ing219;ing220;ing221;ing222;ing223;ing224;ing225;ing226;ing227;ing228;ing229;ing230;ing231;ing232;ing233;ing234;ing235;ing236;ing237;ing238;ing239;ing240;ing241;ing242;ing243;ing244;ing245;ing246;ing247;ing248;ing249;ing250;ing251;ing252;ing253;ing254;ing255;ing256;ing257;ing258;ing259;ing260;ing261;ing262;ing263;ing264;ing265;ing266;ing267;ing268;ing269;ing270;ing271;ing272;ing273;ing274;ing275;ing276;ing277;ing278;ing279;ing280;ing281;ing282;ing283;ing284;ing285;ing286;ing287;ing288;ing289;ing290;ing291;ing292;ing293;ing294;ing295;ing296;ing297;ing298;ing299;ing300;ing301;ing302;ing303;ing304;ing305;ing306;ing307;ing308;ing309;ing310;ing311;ing312;ing313;ing314;ing315;ing316;ing317;ing318;ing319;ing320;ing321;ing322;ing323;ing324;ing325;ing326;ing327;ing328;ing329;ing330;ing331;ing332;ing333;ing334;ing335;ing336;ing337;ing338;ing339;ing340;ing341;ing342;ing343;ing344;ing345;ing346;ing347;ing348;ing349;ing350;ing351;ing352;ing353;ing354;ing355;ing356;ing357;ing358;ing359;ing360;ing361;ing362;ing363;ing364;ing365;ing366;ing367;ing368;ing369;ing370;ing371;ing372;ing373;ing374;ing375;ing376;ing377;ing378;ing379;ing380;ing381;ing382;ing383;ing384;ing385;ing386;ing387;ing388;ing389;ing390;ing391;ing392;ing393;ing394;ing395;ing396;ing397;ing398;ing399;ing400;ing401;ing402;ing403;ing404;ing405;ing406;ing407;ing408;ing409;ing410;ing411;ing412;ing413;ing414;ing415;ing416;ing417;ing418;ing419;ing420;ing421;ing422;ing423;ing424;ing425;ing426;ing427;ing428;ing429;ing430;ing431;ing432;ing433;ing434;ing435;ing436;ing437;ing438;ing439;ing440;ing441;ing442;ing443;ing444;ing445;ing446;ing447;ing448;ing449;ing450;ing451;ing452;ing453;ing454;ing455;ing456;ing457;ing458;ing459;ing460;ing461;ing462;ing463;ing464;ing465;ing466;ing467;ing468;ing469;ing470;ing471;ing472;ing473;ing474;ing475;ing476;ing477;ing478;ing479;ing480;ing481;ing482;ing483;ing484;ing485;ing486;ing487;ing488;ing489;ing490;ing491;ing492;ing493;ing494;ing495;ing496;ing497;ing498;ing499;ing500;ing501;ing502;ing503;ing504;ing505;ing506;ing507;ing508;ing509;ing510;ing511;ing512;ing513;ing514;ing515;ing516;ing517;ing518;ing519;ing520;ing521;ing522;ing523;ing524;ing525;ing526;ing527;ing528;ing529;ing530;ing531;ing532;ing533;ing534;ing535;ing536;ing537;ing538;ing539;ing540;ing541;ing542;ing543;ing544;ing545;ing546;ing547;ing548;ing549;ing550;ing551;ing552;ing553;ing554;ing555;ing556;ing557;ing558;ing559;ing560;ing561;ing562;ing563;ing564;ing565;ing566;ing567;ing568;ing569;ing570;ing571;ing572;ing573;ing574;ing575;ing576;ing577;ing578;ing579;ing580;ing581;ing582;ing583;ing584;ing585;ing586;ing587;ing588;ing589;ing590;ing591;ing592;ing593;ing594;ing595;ing596;ing597;ing598;ing599;ing600;ing601;ing602;ing603;ing604;ing605;ing606;ing607;ing608;ing609;ing610;ing611;ing612;ing613;ing614;ing615;ing616;ing617;ing618;ing619;ing620;ing621;ing622;ing623;ing624;ing625;ing626;ing627;ing628;ing629;ing630;ing631;ing632;ing633;ing634;ing635;ing636;ing637;ing638;ing639;ing640;ing641;ing642;ing643;ing644;ing645;ing646;ing647;ing648;ing649;ing650;ing651;ing652;ing653;ing654;ing655;ing656;ing657;ing658;ing659;ing660;ing661;ing662;ing663;ing664;ing665;ing666;ing667;ing668;ing669;ing670;ing671;ing672;ing673;ing674;ing675;ing676;ing677;ing678;ing679;ing680;ing681;ing682;ing683;ing684;ing685;ing686;ing687;ing688;ing689;ing690;ing691;ing692;ing693;ing694;ing695;ing696;ing697;ing698;ing699;ing700;ing701;ing702;ing703;ing704;ing705;ing706;ing707;ing708;ing709;ing710;ing711;ing712;ing713;ing714;ing715;ing716;ing717;ing718;ing719;ing720;ing721;ing722;ing723;ing724;ing725;ing726;ing727;ing728;ing729;ing730;ing731;ing732;ing733;ing734;ing735;ing736;ing737;ing738;ing739;ing740;ing741;ing742;ing743;ing744;ing745;ing746;ing747;ing748;ing749;ing750;ing751;ing752;ing753;ing754;ing755;ing756;ing757;ing758;ing759;ing760;ing761;ing762;ing763;ing764;ing765;ing766;ing767;ing768;ing769;ing770;ing771;ing772;ing773;ing774;ing775;ing776;ing777;ing778;ing779;ing780;ing781;ing782;ing783;ing784;ing785;ing786;ing787;ing788;ing789;ing790;ing791;ing792;ing793;ing794;ing795;ing796;ing797;ing798;ing799;ing800;ing801;ing802;ing803;ing804;ing805;ing806;ing807;ing808;ing809;ing810;ing811;ing812;ing813;ing814;ing815;ing816;ing817;ing818;ing819;ing820;ing821;ing822;ing823;ing824;ing825;ing826;ing827;ing828;ing829;ing830;ing831;ing832;ing833;ing834;ing835;ing836;ing837;ing838;ing839;ing840;ing841;ing842;ing843;ing844;ing845;ing846;ing847;ing848;ing849;ing850;ing851;ing852;ing853;ing854;ing855;ing856;ing857;ing858;ing859;ing860;ing861;ing862;ing863;ing864;ing865;ing866;ing867;ing868;ing869;ing870;ing871;ing872;ing873;ing874;ing875;ing876;ing877;ing878;ing879;ing880;ing881;ing882;ing883;ing884;ing885;ing886;ing887;ing888;ing889;ing890;ing891;ing892;ing893;ing894;ing895;ing896;ing897;ing898;ing899;ing900;ing901;ing902;ing903;ing904;ing905;ing906;ing907;ing908;ing909;ing910;ing911;ing912;ing913;ing914;ing915;ing916;ing917;ing918;ing919;ing920;ing921;ing922;ing923;ing924;ing925;ing926;ing927;ing928;ing929;ing930;ing931;ing932;ing933;ing934;ing935;ing936;ing937;ing938;ing939;ing940;ing941;ing942;ing943;ing944;ing945;ing946;ing947;ing948;ing949;ing950;ing951;ing952;ing953;ing954;ing955;ing956;ing957;ing958;ing959;ing960;ing961;ing962;ing963;ing964;ing965;ing966;ing967;ing968;ing969;ing970;ing971;ing972;ing973;ing974;ing975;ing976;ing977;ing978;ing979;ing980;ing981;ing982;ing983;ing984;ing985;ing986;ing987;ing988;ing989;ing990;ing991;ing992;ing993;ing994;ing995;ing996;ing997;ing998;ing999 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +start;string0;string1;string2;string3;string4;string5;string6;string7;string8;string9;string10;string11;string12;string13;string14;string15;string16;string17;string18;string19;string20;string21;string22;string23;string24;string25;string26;string27;string28;string29;string30;string31;string32;string33;string34;string35;string36;string37;string38;string39;string40;string41;string42;string43;string44;string45;string46;string47;string48;string49;string50;string51;string52;string53;string54;string55;string56;string57;string58;string59;string60;string61;string62;string63;string64;string65;string66;string67;string68;string69;string70;string71;string72;string73;string74;string75;string76;string77;string78;string79;string80;string81;string82;string83;string84;string85;string86;string87;string88;string89;string90;string91;string92;string93;string94;string95;string96;string97;string98;string99;string100;string101;string102;string103;string104;string105;string106;string107;string108;string109;string110;string111;string112;string113;string114;string115;string116;string117;string118;string119;string120;string121;string122;string123;string124;string125;string126;string127;string128;string129;string130;string131;string132;string133;string134;string135;string136;string137;string138;string139;string140;string141;string142;string143;string144;string145;string146;string147;string148;string149;string150;string151;string152;string153;string154;string155;string156;string157;string158;string159;string160;string161;string162;string163;string164;string165;string166;string167;string168;string169;string170;string171;string172;string173;string174;string175;string176;string177;string178;string179;string180;string181;string182;string183;string184;string185;string186;string187;string188;string189;string190;string191;string192;string193;string194;string195;string196;string197;string198;string199;string200;string201;string202;string203;string204;string205;string206;string207;string208;string209;string210;string211;string212;string213;string214;string215;string216;string217;string218;string219;string220;string221;string222;string223;string224;string225;string226;string227;string228;string229;string230;string231;string232;string233;string234;string235;string236;string237;string238;string239;string240;string241;string242;string243;string244;string245;string246;string247;string248;string249;string250;string251;string252;string253;string254;string255;string256;string257;string258;string259;string260;string261;string262;string263;string264;string265;string266;string267;string268;string269;string270;string271;string272;string273;string274;string275;string276;string277;string278;string279;string280;string281;string282;string283;string284;string285;string286;string287;string288;string289;string290;string291;string292;string293;string294;string295;string296;string297;string298;string299;string300;string301;string302;string303;string304;string305;string306;string307;string308;string309;string310;string311;string312;string313;string314;string315;string316;string317;string318;string319;string320;string321;string322;string323;string324;string325;string326;string327;string328;string329;string330;string331;string332;string333;string334;string335;string336;string337;string338;string339;string340;string341;string342;string343;string344;string345;string346;string347;string348;string349;string350;string351;string352;string353;string354;string355;string356;string357;string358;string359;string360;string361;string362;string363;string364;string365;string366;string367;string368;string369;string370;string371;string372;string373;string374;string375;string376;string377;string378;string379;string380;string381;string382;string383;string384;string385;string386;string387;string388;string389;string390;string391;string392;string393;string394;string395;string396;string397;string398;string399;string400;string401;string402;string403;string404;string405;string406;string407;string408;string409;string410;string411;string412;string413;string414;string415;string416;string417;string418;string419;string420;string421;string422;string423;string424;string425;string426;string427;string428;string429;string430;string431;string432;string433;string434;string435;string436;string437;string438;string439;string440;string441;string442;string443;string444;string445;string446;string447;string448;string449;string450;string451;string452;string453;string454;string455;string456;string457;string458;string459;string460;string461;string462;string463;string464;string465;string466;string467;string468;string469;string470;string471;string472;string473;string474;string475;string476;string477;string478;string479;string480;string481;string482;string483;string484;string485;string486;string487;string488;string489;string490;string491;string492;string493;string494;string495;string496;string497;string498;string499;string500;string501;string502;string503;string504;string505;string506;string507;string508;string509;string510;string511;string512;string513;string514;string515;string516;string517;string518;string519;string520;string521;string522;string523;string524;string525;string526;string527;string528;string529;string530;string531;string532;string533;string534;string535;string536;string537;string538;string539;string540;string541;string542;string543;string544;string545;string546;string547;string548;string549;string550;string551;string552;string553;string554;string555;string556;string557;string558;string559;string560;string561;string562;string563;string564;string565;string566;string567;string568;string569;string570;string571;string572;string573;string574;string575;string576;string577;string578;string579;string580;string581;string582;string583;string584;string585;string586;string587;string588;string589;string590;string591;string592;string593;string594;string595;string596;string597;string598;string599;string600;string601;string602;string603;string604;string605;string606;string607;string608;string609;string610;string611;string612;string613;string614;string615;string616;string617;string618;string619;string620;string621;string622;string623;string624;string625;string626;string627;string628;string629;string630;string631;string632;string633;string634;string635;string636;string637;string638;string639;string640;string641;string642;string643;string644;string645;string646;string647;string648;string649;string650;string651;string652;string653;string654;string655;string656;string657;string658;string659;string660;string661;string662;string663;string664;string665;string666;string667;string668;string669;string670;string671;string672;string673;string674;string675;string676;string677;string678;string679;string680;string681;string682;string683;string684;string685;string686;string687;string688;string689;string690;string691;string692;string693;string694;string695;string696;string697;string698;string699;string700;string701;string702;string703;string704;string705;string706;string707;string708;string709;string710;string711;string712;string713;string714;string715;string716;string717;string718;string719;string720;string721;string722;string723;string724;string725;string726;string727;string728;string729;string730;string731;string732;string733;string734;string735;string736;string737;string738;string739;string740;string741;string742;string743;string744;string745;string746;string747;string748;string749;string750;string751;string752;string753;string754;string755;string756;string757;string758;string759;string760;string761;string762;string763;string764;string765;string766;string767;string768;string769;string770;string771;string772;string773;string774;string775;string776;string777;string778;string779;string780;string781;string782;string783;string784;string785;string786;string787;string788;string789;string790;string791;string792;string793;string794;string795;string796;string797;string798;string799;string800;string801;string802;string803;string804;string805;string806;string807;string808;string809;string810;string811;string812;string813;string814;string815;string816;string817;string818;string819;string820;string821;string822;string823;string824;string825;string826;string827;string828;string829;string830;string831;string832;string833;string834;string835;string836;string837;string838;string839;string840;string841;string842;string843;string844;string845;string846;string847;string848;string849;string850;string851;string852;string853;string854;string855;string856;string857;string858;string859;string860;string861;string862;string863;string864;string865;string866;string867;string868;string869;string870;string871;string872;string873;string874;string875;string876;string877;string878;string879;string880;string881;string882;string883;string884;string885;string886;string887;string888;string889;string890;string891;string892;string893;string894;string895;string896;string897;string898;string899;string900;string901;string902;string903;string904;string905;string906;string907;string908;string909;string910;string911;string912;string913;string914;string915;string916;string917;string918;string919;string920;string921;string922;string923;string924;string925;string926;string927;string928;string929;string930;string931;string932;string933;string934;string935;string936;string937;string938;string939;string940;string941;string942;string943;string944;string945;string946;string947;string948;string949;string950;string951;string952;string953;string954;string955;string956;string957;string958;string959;string960;string961;string962;string963;string964;string965;string966;string967;string968;string969;string970;string971;string972;string973;string974;string975;string976;string977;string978;string979;string980;string981;string982;string983;string984;string985;string986;string987;string988;string989;string990;string991;string992;string993;string994;string995;string996;string997;string998;string999 +start;ing0;ing1;ing2;ing3;ing4;ing5;ing6;ing7;ing8;ing9;ing10;ing11;ing12;ing13;ing14;ing15;ing16;ing17;ing18;ing19;ing20;ing21;ing22;ing23;ing24;ing25;ing26;ing27;ing28;ing29;ing30;ing31;ing32;ing33;ing34;ing35;ing36;ing37;ing38;ing39;ing40;ing41;ing42;ing43;ing44;ing45;ing46;ing47;ing48;ing49;ing50;ing51;ing52;ing53;ing54;ing55;ing56;ing57;ing58;ing59;ing60;ing61;ing62;ing63;ing64;ing65;ing66;ing67;ing68;ing69;ing70;ing71;ing72;ing73;ing74;ing75;ing76;ing77;ing78;ing79;ing80;ing81;ing82;ing83;ing84;ing85;ing86;ing87;ing88;ing89;ing90;ing91;ing92;ing93;ing94;ing95;ing96;ing97;ing98;ing99;ing100;ing101;ing102;ing103;ing104;ing105;ing106;ing107;ing108;ing109;ing110;ing111;ing112;ing113;ing114;ing115;ing116;ing117;ing118;ing119;ing120;ing121;ing122;ing123;ing124;ing125;ing126;ing127;ing128;ing129;ing130;ing131;ing132;ing133;ing134;ing135;ing136;ing137;ing138;ing139;ing140;ing141;ing142;ing143;ing144;ing145;ing146;ing147;ing148;ing149;ing150;ing151;ing152;ing153;ing154;ing155;ing156;ing157;ing158;ing159;ing160;ing161;ing162;ing163;ing164;ing165;ing166;ing167;ing168;ing169;ing170;ing171;ing172;ing173;ing174;ing175;ing176;ing177;ing178;ing179;ing180;ing181;ing182;ing183;ing184;ing185;ing186;ing187;ing188;ing189;ing190;ing191;ing192;ing193;ing194;ing195;ing196;ing197;ing198;ing199;ing200;ing201;ing202;ing203;ing204;ing205;ing206;ing207;ing208;ing209;ing210;ing211;ing212;ing213;ing214;ing215;ing216;ing217;ing218;ing219;ing220;ing221;ing222;ing223;ing224;ing225;ing226;ing227;ing228;ing229;ing230;ing231;ing232;ing233;ing234;ing235;ing236;ing237;ing238;ing239;ing240;ing241;ing242;ing243;ing244;ing245;ing246;ing247;ing248;ing249;ing250;ing251;ing252;ing253;ing254;ing255;ing256;ing257;ing258;ing259;ing260;ing261;ing262;ing263;ing264;ing265;ing266;ing267;ing268;ing269;ing270;ing271;ing272;ing273;ing274;ing275;ing276;ing277;ing278;ing279;ing280;ing281;ing282;ing283;ing284;ing285;ing286;ing287;ing288;ing289;ing290;ing291;ing292;ing293;ing294;ing295;ing296;ing297;ing298;ing299;ing300;ing301;ing302;ing303;ing304;ing305;ing306;ing307;ing308;ing309;ing310;ing311;ing312;ing313;ing314;ing315;ing316;ing317;ing318;ing319;ing320;ing321;ing322;ing323;ing324;ing325;ing326;ing327;ing328;ing329;ing330;ing331;ing332;ing333;ing334;ing335;ing336;ing337;ing338;ing339;ing340;ing341;ing342;ing343;ing344;ing345;ing346;ing347;ing348;ing349;ing350;ing351;ing352;ing353;ing354;ing355;ing356;ing357;ing358;ing359;ing360;ing361;ing362;ing363;ing364;ing365;ing366;ing367;ing368;ing369;ing370;ing371;ing372;ing373;ing374;ing375;ing376;ing377;ing378;ing379;ing380;ing381;ing382;ing383;ing384;ing385;ing386;ing387;ing388;ing389;ing390;ing391;ing392;ing393;ing394;ing395;ing396;ing397;ing398;ing399;ing400;ing401;ing402;ing403;ing404;ing405;ing406;ing407;ing408;ing409;ing410;ing411;ing412;ing413;ing414;ing415;ing416;ing417;ing418;ing419;ing420;ing421;ing422;ing423;ing424;ing425;ing426;ing427;ing428;ing429;ing430;ing431;ing432;ing433;ing434;ing435;ing436;ing437;ing438;ing439;ing440;ing441;ing442;ing443;ing444;ing445;ing446;ing447;ing448;ing449;ing450;ing451;ing452;ing453;ing454;ing455;ing456;ing457;ing458;ing459;ing460;ing461;ing462;ing463;ing464;ing465;ing466;ing467;ing468;ing469;ing470;ing471;ing472;ing473;ing474;ing475;ing476;ing477;ing478;ing479;ing480;ing481;ing482;ing483;ing484;ing485;ing486;ing487;ing488;ing489;ing490;ing491;ing492;ing493;ing494;ing495;ing496;ing497;ing498;ing499;ing500;ing501;ing502;ing503;ing504;ing505;ing506;ing507;ing508;ing509;ing510;ing511;ing512;ing513;ing514;ing515;ing516;ing517;ing518;ing519;ing520;ing521;ing522;ing523;ing524;ing525;ing526;ing527;ing528;ing529;ing530;ing531;ing532;ing533;ing534;ing535;ing536;ing537;ing538;ing539;ing540;ing541;ing542;ing543;ing544;ing545;ing546;ing547;ing548;ing549;ing550;ing551;ing552;ing553;ing554;ing555;ing556;ing557;ing558;ing559;ing560;ing561;ing562;ing563;ing564;ing565;ing566;ing567;ing568;ing569;ing570;ing571;ing572;ing573;ing574;ing575;ing576;ing577;ing578;ing579;ing580;ing581;ing582;ing583;ing584;ing585;ing586;ing587;ing588;ing589;ing590;ing591;ing592;ing593;ing594;ing595;ing596;ing597;ing598;ing599;ing600;ing601;ing602;ing603;ing604;ing605;ing606;ing607;ing608;ing609;ing610;ing611;ing612;ing613;ing614;ing615;ing616;ing617;ing618;ing619;ing620;ing621;ing622;ing623;ing624;ing625;ing626;ing627;ing628;ing629;ing630;ing631;ing632;ing633;ing634;ing635;ing636;ing637;ing638;ing639;ing640;ing641;ing642;ing643;ing644;ing645;ing646;ing647;ing648;ing649;ing650;ing651;ing652;ing653;ing654;ing655;ing656;ing657;ing658;ing659;ing660;ing661;ing662;ing663;ing664;ing665;ing666;ing667;ing668;ing669;ing670;ing671;ing672;ing673;ing674;ing675;ing676;ing677;ing678;ing679;ing680;ing681;ing682;ing683;ing684;ing685;ing686;ing687;ing688;ing689;ing690;ing691;ing692;ing693;ing694;ing695;ing696;ing697;ing698;ing699;ing700;ing701;ing702;ing703;ing704;ing705;ing706;ing707;ing708;ing709;ing710;ing711;ing712;ing713;ing714;ing715;ing716;ing717;ing718;ing719;ing720;ing721;ing722;ing723;ing724;ing725;ing726;ing727;ing728;ing729;ing730;ing731;ing732;ing733;ing734;ing735;ing736;ing737;ing738;ing739;ing740;ing741;ing742;ing743;ing744;ing745;ing746;ing747;ing748;ing749;ing750;ing751;ing752;ing753;ing754;ing755;ing756;ing757;ing758;ing759;ing760;ing761;ing762;ing763;ing764;ing765;ing766;ing767;ing768;ing769;ing770;ing771;ing772;ing773;ing774;ing775;ing776;ing777;ing778;ing779;ing780;ing781;ing782;ing783;ing784;ing785;ing786;ing787;ing788;ing789;ing790;ing791;ing792;ing793;ing794;ing795;ing796;ing797;ing798;ing799;ing800;ing801;ing802;ing803;ing804;ing805;ing806;ing807;ing808;ing809;ing810;ing811;ing812;ing813;ing814;ing815;ing816;ing817;ing818;ing819;ing820;ing821;ing822;ing823;ing824;ing825;ing826;ing827;ing828;ing829;ing830;ing831;ing832;ing833;ing834;ing835;ing836;ing837;ing838;ing839;ing840;ing841;ing842;ing843;ing844;ing845;ing846;ing847;ing848;ing849;ing850;ing851;ing852;ing853;ing854;ing855;ing856;ing857;ing858;ing859;ing860;ing861;ing862;ing863;ing864;ing865;ing866;ing867;ing868;ing869;ing870;ing871;ing872;ing873;ing874;ing875;ing876;ing877;ing878;ing879;ing880;ing881;ing882;ing883;ing884;ing885;ing886;ing887;ing888;ing889;ing890;ing891;ing892;ing893;ing894;ing895;ing896;ing897;ing898;ing899;ing900;ing901;ing902;ing903;ing904;ing905;ing906;ing907;ing908;ing909;ing910;ing911;ing912;ing913;ing914;ing915;ing916;ing917;ing918;ing919;ing920;ing921;ing922;ing923;ing924;ing925;ing926;ing927;ing928;ing929;ing930;ing931;ing932;ing933;ing934;ing935;ing936;ing937;ing938;ing939;ing940;ing941;ing942;ing943;ing944;ing945;ing946;ing947;ing948;ing949;ing950;ing951;ing952;ing953;ing954;ing955;ing956;ing957;ing958;ing959;ing960;ing961;ing962;ing963;ing964;ing965;ing966;ing967;ing968;ing969;ing970;ing971;ing972;ing973;ing974;ing975;ing976;ing977;ing978;ing979;ing980;ing981;ing982;ing983;ing984;ing985;ing986;ing987;ing988;ing989;ing990;ing991;ing992;ing993;ing994;ing995;ing996;ing997;ing998;ing999 +start;string0;string1;string2;string3;string4;string5;string6;string7;string8;string9;string10;string11;string12;string13;string14;string15;string16;string17;string18;string19;string20;string21;string22;string23;string24;string25;string26;string27;string28;string29;string30;string31;string32;string33;string34;string35;string36;string37;string38;string39;string40;string41;string42;string43;string44;string45;string46;string47;string48;string49;string50;string51;string52;string53;string54;string55;string56;string57;string58;string59;string60;string61;string62;string63;string64;string65;string66;string67;string68;string69;string70;string71;string72;string73;string74;string75;string76;string77;string78;string79;string80;string81;string82;string83;string84;string85;string86;string87;string88;string89;string90;string91;string92;string93;string94;string95;string96;string97;string98;string99;string100;string101;string102;string103;string104;string105;string106;string107;string108;string109;string110;string111;string112;string113;string114;string115;string116;string117;string118;string119;string120;string121;string122;string123;string124;string125;string126;string127;string128;string129;string130;string131;string132;string133;string134;string135;string136;string137;string138;string139;string140;string141;string142;string143;string144;string145;string146;string147;string148;string149;string150;string151;string152;string153;string154;string155;string156;string157;string158;string159;string160;string161;string162;string163;string164;string165;string166;string167;string168;string169;string170;string171;string172;string173;string174;string175;string176;string177;string178;string179;string180;string181;string182;string183;string184;string185;string186;string187;string188;string189;string190;string191;string192;string193;string194;string195;string196;string197;string198;string199;string200;string201;string202;string203;string204;string205;string206;string207;string208;string209;string210;string211;string212;string213;string214;string215;string216;string217;string218;string219;string220;string221;string222;string223;string224;string225;string226;string227;string228;string229;string230;string231;string232;string233;string234;string235;string236;string237;string238;string239;string240;string241;string242;string243;string244;string245;string246;string247;string248;string249;string250;string251;string252;string253;string254;string255;string256;string257;string258;string259;string260;string261;string262;string263;string264;string265;string266;string267;string268;string269;string270;string271;string272;string273;string274;string275;string276;string277;string278;string279;string280;string281;string282;string283;string284;string285;string286;string287;string288;string289;string290;string291;string292;string293;string294;string295;string296;string297;string298;string299;string300;string301;string302;string303;string304;string305;string306;string307;string308;string309;string310;string311;string312;string313;string314;string315;string316;string317;string318;string319;string320;string321;string322;string323;string324;string325;string326;string327;string328;string329;string330;string331;string332;string333;string334;string335;string336;string337;string338;string339;string340;string341;string342;string343;string344;string345;string346;string347;string348;string349;string350;string351;string352;string353;string354;string355;string356;string357;string358;string359;string360;string361;string362;string363;string364;string365;string366;string367;string368;string369;string370;string371;string372;string373;string374;string375;string376;string377;string378;string379;string380;string381;string382;string383;string384;string385;string386;string387;string388;string389;string390;string391;string392;string393;string394;string395;string396;string397;string398;string399;string400;string401;string402;string403;string404;string405;string406;string407;string408;string409;string410;string411;string412;string413;string414;string415;string416;string417;string418;string419;string420;string421;string422;string423;string424;string425;string426;string427;string428;string429;string430;string431;string432;string433;string434;string435;string436;string437;string438;string439;string440;string441;string442;string443;string444;string445;string446;string447;string448;string449;string450;string451;string452;string453;string454;string455;string456;string457;string458;string459;string460;string461;string462;string463;string464;string465;string466;string467;string468;string469;string470;string471;string472;string473;string474;string475;string476;string477;string478;string479;string480;string481;string482;string483;string484;string485;string486;string487;string488;string489;string490;string491;string492;string493;string494;string495;string496;string497;string498;string499;string500;string501;string502;string503;string504;string505;string506;string507;string508;string509;string510;string511;string512;string513;string514;string515;string516;string517;string518;string519;string520;string521;string522;string523;string524;string525;string526;string527;string528;string529;string530;string531;string532;string533;string534;string535;string536;string537;string538;string539;string540;string541;string542;string543;string544;string545;string546;string547;string548;string549;string550;string551;string552;string553;string554;string555;string556;string557;string558;string559;string560;string561;string562;string563;string564;string565;string566;string567;string568;string569;string570;string571;string572;string573;string574;string575;string576;string577;string578;string579;string580;string581;string582;string583;string584;string585;string586;string587;string588;string589;string590;string591;string592;string593;string594;string595;string596;string597;string598;string599;string600;string601;string602;string603;string604;string605;string606;string607;string608;string609;string610;string611;string612;string613;string614;string615;string616;string617;string618;string619;string620;string621;string622;string623;string624;string625;string626;string627;string628;string629;string630;string631;string632;string633;string634;string635;string636;string637;string638;string639;string640;string641;string642;string643;string644;string645;string646;string647;string648;string649;string650;string651;string652;string653;string654;string655;string656;string657;string658;string659;string660;string661;string662;string663;string664;string665;string666;string667;string668;string669;string670;string671;string672;string673;string674;string675;string676;string677;string678;string679;string680;string681;string682;string683;string684;string685;string686;string687;string688;string689;string690;string691;string692;string693;string694;string695;string696;string697;string698;string699;string700;string701;string702;string703;string704;string705;string706;string707;string708;string709;string710;string711;string712;string713;string714;string715;string716;string717;string718;string719;string720;string721;string722;string723;string724;string725;string726;string727;string728;string729;string730;string731;string732;string733;string734;string735;string736;string737;string738;string739;string740;string741;string742;string743;string744;string745;string746;string747;string748;string749;string750;string751;string752;string753;string754;string755;string756;string757;string758;string759;string760;string761;string762;string763;string764;string765;string766;string767;string768;string769;string770;string771;string772;string773;string774;string775;string776;string777;string778;string779;string780;string781;string782;string783;string784;string785;string786;string787;string788;string789;string790;string791;string792;string793;string794;string795;string796;string797;string798;string799;string800;string801;string802;string803;string804;string805;string806;string807;string808;string809;string810;string811;string812;string813;string814;string815;string816;string817;string818;string819;string820;string821;string822;string823;string824;string825;string826;string827;string828;string829;string830;string831;string832;string833;string834;string835;string836;string837;string838;string839;string840;string841;string842;string843;string844;string845;string846;string847;string848;string849;string850;string851;string852;string853;string854;string855;string856;string857;string858;string859;string860;string861;string862;string863;string864;string865;string866;string867;string868;string869;string870;string871;string872;string873;string874;string875;string876;string877;string878;string879;string880;string881;string882;string883;string884;string885;string886;string887;string888;string889;string890;string891;string892;string893;string894;string895;string896;string897;string898;string899;string900;string901;string902;string903;string904;string905;string906;string907;string908;string909;string910;string911;string912;string913;string914;string915;string916;string917;string918;string919;string920;string921;string922;string923;string924;string925;string926;string927;string928;string929;string930;string931;string932;string933;string934;string935;string936;string937;string938;string939;string940;string941;string942;string943;string944;string945;string946;string947;string948;string949;string950;string951;string952;string953;string954;string955;string956;string957;string958;string959;string960;string961;string962;string963;string964;string965;string966;string967;string968;string969;string970;string971;string972;string973;string974;string975;string976;string977;string978;string979;string980;string981;string982;string983;string984;string985;string986;string987;string988;string989;string990;string991;string992;string993;string994;string995;string996;string997;string998;string999 +start;string0;string1;string2;string3;string4;string5;string6;string7;string8;string9;string10;string11;string12;string13;string14;string15;string16;string17;string18;string19;string20;string21;string22;string23;string24;string25;string26;string27;string28;string29;string30;string31;string32;string33;string34;string35;string36;string37;string38;string39;string40;string41;string42;string43;string44;string45;string46;string47;string48;string49;string50;string51;string52;string53;string54;string55;string56;string57;string58;string59;string60;string61;string62;string63;string64;string65;string66;string67;string68;string69;string70;string71;string72;string73;string74;string75;string76;string77;string78;string79;string80;string81;string82;string83;string84;string85;string86;string87;string88;string89;string90;string91;string92;string93;string94;string95;string96;string97;string98;string99;string100;string101;string102;string103;string104;string105;string106;string107;string108;string109;string110;string111;string112;string113;string114;string115;string116;string117;string118;string119;string120;string121;string122;string123;string124;string125;string126;string127;string128;string129;string130;string131;string132;string133;string134;string135;string136;string137;string138;string139;string140;string141;string142;string143;string144;string145;string146;string147;string148;string149;string150;string151;string152;string153;string154;string155;string156;string157;string158;string159;string160;string161;string162;string163;string164;string165;string166;string167;string168;string169;string170;string171;string172;string173;string174;string175;string176;string177;string178;string179;string180;string181;string182;string183;string184;string185;string186;string187;string188;string189;string190;string191;string192;string193;string194;string195;string196;string197;string198;string199;string200;string201;string202;string203;string204;string205;string206;string207;string208;string209;string210;string211;string212;string213;string214;string215;string216;string217;string218;string219;string220;string221;string222;string223;string224;string225;string226;string227;string228;string229;string230;string231;string232;string233;string234;string235;string236;string237;string238;string239;string240;string241;string242;string243;string244;string245;string246;string247;string248;string249;string250;string251;string252;string253;string254;string255;string256;string257;string258;string259;string260;string261;string262;string263;string264;string265;string266;string267;string268;string269;string270;string271;string272;string273;string274;string275;string276;string277;string278;string279;string280;string281;string282;string283;string284;string285;string286;string287;string288;string289;string290;string291;string292;string293;string294;string295;string296;string297;string298;string299;string300;string301;string302;string303;string304;string305;string306;string307;string308;string309;string310;string311;string312;string313;string314;string315;string316;string317;string318;string319;string320;string321;string322;string323;string324;string325;string326;string327;string328;string329;string330;string331;string332;string333;string334;string335;string336;string337;string338;string339;string340;string341;string342;string343;string344;string345;string346;string347;string348;string349;string350;string351;string352;string353;string354;string355;string356;string357;string358;string359;string360;string361;string362;string363;string364;string365;string366;string367;string368;string369;string370;string371;string372;string373;string374;string375;string376;string377;string378;string379;string380;string381;string382;string383;string384;string385;string386;string387;string388;string389;string390;string391;string392;string393;string394;string395;string396;string397;string398;string399;string400;string401;string402;string403;string404;string405;string406;string407;string408;string409;string410;string411;string412;string413;string414;string415;string416;string417;string418;string419;string420;string421;string422;string423;string424;string425;string426;string427;string428;string429;string430;string431;string432;string433;string434;string435;string436;string437;string438;string439;string440;string441;string442;string443;string444;string445;string446;string447;string448;string449;string450;string451;string452;string453;string454;string455;string456;string457;string458;string459;string460;string461;string462;string463;string464;string465;string466;string467;string468;string469;string470;string471;string472;string473;string474;string475;string476;string477;string478;string479;string480;string481;string482;string483;string484;string485;string486;string487;string488;string489;string490;string491;string492;string493;string494;string495;string496;string497;string498;string499;string500;string501;string502;string503;string504;string505;string506;string507;string508;string509;string510;string511;string512;string513;string514;string515;string516;string517;string518;string519;string520;string521;string522;string523;string524;string525;string526;string527;string528;string529;string530;string531;string532;string533;string534;string535;string536;string537;string538;string539;string540;string541;string542;string543;string544;string545;string546;string547;string548;string549;string550;string551;string552;string553;string554;string555;string556;string557;string558;string559;string560;string561;string562;string563;string564;string565;string566;string567;string568;string569;string570;string571;string572;string573;string574;string575;string576;string577;string578;string579;string580;string581;string582;string583;string584;string585;string586;string587;string588;string589;string590;string591;string592;string593;string594;string595;string596;string597;string598;string599;string600;string601;string602;string603;string604;string605;string606;string607;string608;string609;string610;string611;string612;string613;string614;string615;string616;string617;string618;string619;string620;string621;string622;string623;string624;string625;string626;string627;string628;string629;string630;string631;string632;string633;string634;string635;string636;string637;string638;string639;string640;string641;string642;string643;string644;string645;string646;string647;string648;string649;string650;string651;string652;string653;string654;string655;string656;string657;string658;string659;string660;string661;string662;string663;string664;string665;string666;string667;string668;string669;string670;string671;string672;string673;string674;string675;string676;string677;string678;string679;string680;string681;string682;string683;string684;string685;string686;string687;string688;string689;string690;string691;string692;string693;string694;string695;string696;string697;string698;string699;string700;string701;string702;string703;string704;string705;string706;string707;string708;string709;string710;string711;string712;string713;string714;string715;string716;string717;string718;string719;string720;string721;string722;string723;string724;string725;string726;string727;string728;string729;string730;string731;string732;string733;string734;string735;string736;string737;string738;string739;string740;string741;string742;string743;string744;string745;string746;string747;string748;string749;string750;string751;string752;string753;string754;string755;string756;string757;string758;string759;string760;string761;string762;string763;string764;string765;string766;string767;string768;string769;string770;string771;string772;string773;string774;string775;string776;string777;string778;string779;string780;string781;string782;string783;string784;string785;string786;string787;string788;string789;string790;string791;string792;string793;string794;string795;string796;string797;string798;string799;string800;string801;string802;string803;string804;string805;string806;string807;string808;string809;string810;string811;string812;string813;string814;string815;string816;string817;string818;string819;string820;string821;string822;string823;string824;string825;string826;string827;string828;string829;string830;string831;string832;string833;string834;string835;string836;string837;string838;string839;string840;string841;string842;string843;string844;string845;string846;string847;string848;string849;string850;string851;string852;string853;string854;string855;string856;string857;string858;string859;string860;string861;string862;string863;string864;string865;string866;string867;string868;string869;string870;string871;string872;string873;string874;string875;string876;string877;string878;string879;string880;string881;string882;string883;string884;string885;string886;string887;string888;string889;string890;string891;string892;string893;string894;string895;string896;string897;string898;string899;string900;string901;string902;string903;string904;string905;string906;string907;string908;string909;string910;string911;string912;string913;string914;string915;string916;string917;string918;string919;string920;string921;string922;string923;string924;string925;string926;string927;string928;string929;string930;string931;string932;string933;string934;string935;string936;string937;string938;string939;string940;string941;string942;string943;string944;string945;string946;string947;string948;string949;string950;string951;string952;string953;string954;string955;string956;string957;string958;string959;string960;string961;string962;string963;string964;string965;string966;string967;string968;string969;string970;string971;string972;string973;string974;string975;string976;string977;string978;string979;string980;string981;string982;string983;string984;string985;string986;string987;string988;string989;string990;string991;string992;string993;string994;string995;string996;string997;string998;string999 +ing999 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +art;string0;string1;string2;string3;string4;string5;string6;string7;string8;string9;string10;string11;string12;string13;string14;string15;string16;string17;string18;string19;string20;string21;string22;string23;string24;string25;string26;string27;string28;string29;string30;string31;string32;string33;string34;string35;string36;string37;string38;string39;string40;string41;string42;string43;string44;string45;string46;string47;string48;string49;string50;string51;string52;string53;string54;string55;string56;string57;string58;string59;string60;string61;string62;string63;string64;string65;string66;string67;string68;string69;string70;string71;string72;string73;string74;string75;string76;string77;string78;string79;string80;string81;string82;string83;string84;string85;string86;string87;string88;string89;string90;string91;string92;string93;string94;string95;string96;string97;string98;string99;string100;string101;string102;string103;string104;string105;string106;string107;string108;string109;string110;string111;string112;string113;string114;string115;string116;string117;string118;string119;string120;string121;string122;string123;string124;string125;string126;string127;string128;string129;string130;string131;string132;string133;string134;string135;string136;string137;string138;string139;string140;string141;string142;string143;string144;string145;string146;string147;string148;string149;string150;string151;string152;string153;string154;string155;string156;string157;string158;string159;string160;string161;string162;string163;string164;string165;string166;string167;string168;string169;string170;string171;string172;string173;string174;string175;string176;string177;string178;string179;string180;string181;string182;string183;string184;string185;string186;string187;string188;string189;string190;string191;string192;string193;string194;string195;string196;string197;string198;string199;string200;string201;string202;string203;string204;string205;string206;string207;string208;string209;string210;string211;string212;string213;string214;string215;string216;string217;string218;string219;string220;string221;string222;string223;string224;string225;string226;string227;string228;string229;string230;string231;string232;string233;string234;string235;string236;string237;string238;string239;string240;string241;string242;string243;string244;string245;string246;string247;string248;string249;string250;string251;string252;string253;string254;string255;string256;string257;string258;string259;string260;string261;string262;string263;string264;string265;string266;string267;string268;string269;string270;string271;string272;string273;string274;string275;string276;string277;string278;string279;string280;string281;string282;string283;string284;string285;string286;string287;string288;string289;string290;string291;string292;string293;string294;string295;string296;string297;string298;string299;string300;string301;string302;string303;string304;string305;string306;string307;string308;string309;string310;string311;string312;string313;string314;string315;string316;string317;string318;string319;string320;string321;string322;string323;string324;string325;string326;string327;string328;string329;string330;string331;string332;string333;string334;string335;string336;string337;string338;string339;string340;string341;string342;string343;string344;string345;string346;string347;string348;string349;string350;string351;string352;string353;string354;string355;string356;string357;string358;string359;string360;string361;string362;string363;string364;string365;string366;string367;string368;string369;string370;string371;string372;string373;string374;string375;string376;string377;string378;string379;string380;string381;string382;string383;string384;string385;string386;string387;string388;string389;string390;string391;string392;string393;string394;string395;string396;string397;string398;string399;string400;string401;string402;string403;string404;string405;string406;string407;string408;string409;string410;string411;string412;string413;string414;string415;string416;string417;string418;string419;string420;string421;string422;string423;string424;string425;string426;string427;string428;string429;string430;string431;string432;string433;string434;string435;string436;string437;string438;string439;string440;string441;string442;string443;string444;string445;string446;string447;string448;string449;string450;string451;string452;string453;string454;string455;string456;string457;string458;string459;string460;string461;string462;string463;string464;string465;string466;string467;string468;string469;string470;string471;string472;string473;string474;string475;string476;string477;string478;string479;string480;string481;string482;string483;string484;string485;string486;string487;string488;string489;string490;string491;string492;string493;string494;string495;string496;string497;string498;string499;string500;string501;string502;string503;string504;string505;string506;string507;string508;string509;string510;string511;string512;string513;string514;string515;string516;string517;string518;string519;string520;string521;string522;string523;string524;string525;string526;string527;string528;string529;string530;string531;string532;string533;string534;string535;string536;string537;string538;string539;string540;string541;string542;string543;string544;string545;string546;string547;string548;string549;string550;string551;string552;string553;string554;string555;string556;string557;string558;string559;string560;string561;string562;string563;string564;string565;string566;string567;string568;string569;string570;string571;string572;string573;string574;string575;string576;string577;string578;string579;string580;string581;string582;string583;string584;string585;string586;string587;string588;string589;string590;string591;string592;string593;string594;string595;string596;string597;string598;string599;string600;string601;string602;string603;string604;string605;string606;string607;string608;string609;string610;string611;string612;string613;string614;string615;string616;string617;string618;string619;string620;string621;string622;string623;string624;string625;string626;string627;string628;string629;string630;string631;string632;string633;string634;string635;string636;string637;string638;string639;string640;string641;string642;string643;string644;string645;string646;string647;string648;string649;string650;string651;string652;string653;string654;string655;string656;string657;string658;string659;string660;string661;string662;string663;string664;string665;string666;string667;string668;string669;string670;string671;string672;string673;string674;string675;string676;string677;string678;string679;string680;string681;string682;string683;string684;string685;string686;string687;string688;string689;string690;string691;string692;string693;string694;string695;string696;string697;string698;string699;string700;string701;string702;string703;string704;string705;string706;string707;string708;string709;string710;string711;string712;string713;string714;string715;string716;string717;string718;string719;string720;string721;string722;string723;string724;string725;string726;string727;string728;string729;string730;string731;string732;string733;string734;string735;string736;string737;string738;string739;string740;string741;string742;string743;string744;string745;string746;string747;string748;string749;string750;string751;string752;string753;string754;string755;string756;string757;string758;string759;string760;string761;string762;string763;string764;string765;string766;string767;string768;string769;string770;string771;string772;string773;string774;string775;string776;string777;string778;string779;string780;string781;string782;string783;string784;string785;string786;string787;string788;string789;string790;string791;string792;string793;string794;string795;string796;string797;string798;string799;string800;string801;string802;string803;string804;string805;string806;string807;string808;string809;string810;string811;string812;string813;string814;string815;string816;string817;string818;string819;string820;string821;string822;string823;string824;string825;string826;string827;string828;string829;string830;string831;string832;string833;string834;string835;string836;string837;string838;string839;string840;string841;string842;string843;string844;string845;string846;string847;string848;string849;string850;string851;string852;string853;string854;string855;string856;string857;string858;string859;string860;string861;string862;string863;string864;string865;string866;string867;string868;string869;string870;string871;string872;string873;string874;string875;string876;string877;string878;string879;string880;string881;string882;string883;string884;string885;string886;string887;string888;string889;string890;string891;string892;string893;string894;string895;string896;string897;string898;string899;string900;string901;string902;string903;string904;string905;string906;string907;string908;string909;string910;string911;string912;string913;string914;string915;string916;string917;string918;string919;string920;string921;string922;string923;string924;string925;string926;string927;string928;string929;string930;string931;string932;string933;string934;string935;string936;string937;string938;string939;string940;string941;string942;string943;string944;string945;string946;string947;string948;string949;string950;string951;string952;string953;string954;string955;string956;string957;string958;string959;string960;string961;string962;string963;string964;string965;string966;string967;string968;string969;string970;string971;string972;string973;string974;string975;string976;string977;string978;string979;string980;string981;string982;string983;string984;string985;string986;string987;string988;string989;string990;string991;string992;string993;string994;string995;string996;string997;string998;string999 +start;string0;string1;string2;string3;string4;string5;string6;string7;string8;string9;string10;string11;string12;string13;string14;string15;string16;string17;string18;string19;string20;string21;string22;string23;string24;string25;string26;string27;string28;string29;string30;string31;string32;string33;string34;string35;string36;string37;string38;string39;string40;string41;string42;string43;string44;string45;string46;string47;string48;string49;string50;string51;string52;string53;string54;string55;string56;string57;string58;string59;string60;string61;string62;string63;string64;string65;string66;string67;string68;string69;string70;string71;string72;string73;string74;string75;string76;string77;string78;string79;string80;string81;string82;string83;string84;string85;string86;string87;string88;string89;string90;string91;string92;string93;string94;string95;string96;string97;string98;string99;string100;string101;string102;string103;string104;string105;string106;string107;string108;string109;string110;string111;string112;string113;string114;string115;string116;string117;string118;string119;string120;string121;string122;string123;string124;string125;string126;string127;string128;string129;string130;string131;string132;string133;string134;string135;string136;string137;string138;string139;string140;string141;string142;string143;string144;string145;string146;string147;string148;string149;string150;string151;string152;string153;string154;string155;string156;string157;string158;string159;string160;string161;string162;string163;string164;string165;string166;string167;string168;string169;string170;string171;string172;string173;string174;string175;string176;string177;string178;string179;string180;string181;string182;string183;string184;string185;string186;string187;string188;string189;string190;string191;string192;string193;string194;string195;string196;string197;string198;string199;string200;string201;string202;string203;string204;string205;string206;string207;string208;string209;string210;string211;string212;string213;string214;string215;string216;string217;string218;string219;string220;string221;string222;string223;string224;string225;string226;string227;string228;string229;string230;string231;string232;string233;string234;string235;string236;string237;string238;string239;string240;string241;string242;string243;string244;string245;string246;string247;string248;string249;string250;string251;string252;string253;string254;string255;string256;string257;string258;string259;string260;string261;string262;string263;string264;string265;string266;string267;string268;string269;string270;string271;string272;string273;string274;string275;string276;string277;string278;string279;string280;string281;string282;string283;string284;string285;string286;string287;string288;string289;string290;string291;string292;string293;string294;string295;string296;string297;string298;string299;string300;string301;string302;string303;string304;string305;string306;string307;string308;string309;string310;string311;string312;string313;string314;string315;string316;string317;string318;string319;string320;string321;string322;string323;string324;string325;string326;string327;string328;string329;string330;string331;string332;string333;string334;string335;string336;string337;string338;string339;string340;string341;string342;string343;string344;string345;string346;string347;string348;string349;string350;string351;string352;string353;string354;string355;string356;string357;string358;string359;string360;string361;string362;string363;string364;string365;string366;string367;string368;string369;string370;string371;string372;string373;string374;string375;string376;string377;string378;string379;string380;string381;string382;string383;string384;string385;string386;string387;string388;string389;string390;string391;string392;string393;string394;string395;string396;string397;string398;string399;string400;string401;string402;string403;string404;string405;string406;string407;string408;string409;string410;string411;string412;string413;string414;string415;string416;string417;string418;string419;string420;string421;string422;string423;string424;string425;string426;string427;string428;string429;string430;string431;string432;string433;string434;string435;string436;string437;string438;string439;string440;string441;string442;string443;string444;string445;string446;string447;string448;string449;string450;string451;string452;string453;string454;string455;string456;string457;string458;string459;string460;string461;string462;string463;string464;string465;string466;string467;string468;string469;string470;string471;string472;string473;string474;string475;string476;string477;string478;string479;string480;string481;string482;string483;string484;string485;string486;string487;string488;string489;string490;string491;string492;string493;string494;string495;string496;string497;string498;string499;string500;string501;string502;string503;string504;string505;string506;string507;string508;string509;string510;string511;string512;string513;string514;string515;string516;string517;string518;string519;string520;string521;string522;string523;string524;string525;string526;string527;string528;string529;string530;string531;string532;string533;string534;string535;string536;string537;string538;string539;string540;string541;string542;string543;string544;string545;string546;string547;string548;string549;string550;string551;string552;string553;string554;string555;string556;string557;string558;string559;string560;string561;string562;string563;string564;string565;string566;string567;string568;string569;string570;string571;string572;string573;string574;string575;string576;string577;string578;string579;string580;string581;string582;string583;string584;string585;string586;string587;string588;string589;string590;string591;string592;string593;string594;string595;string596;string597;string598;string599;string600;string601;string602;string603;string604;string605;string606;string607;string608;string609;string610;string611;string612;string613;string614;string615;string616;string617;string618;string619;string620;string621;string622;string623;string624;string625;string626;string627;string628;string629;string630;string631;string632;string633;string634;string635;string636;string637;string638;string639;string640;string641;string642;string643;string644;string645;string646;string647;string648;string649;string650;string651;string652;string653;string654;string655;string656;string657;string658;string659;string660;string661;string662;string663;string664;string665;string666;string667;string668;string669;string670;string671;string672;string673;string674;string675;string676;string677;string678;string679;string680;string681;string682;string683;string684;string685;string686;string687;string688;string689;string690;string691;string692;string693;string694;string695;string696;string697;string698;string699;string700;string701;string702;string703;string704;string705;string706;string707;string708;string709;string710;string711;string712;string713;string714;string715;string716;string717;string718;string719;string720;string721;string722;string723;string724;string725;string726;string727;string728;string729;string730;string731;string732;string733;string734;string735;string736;string737;string738;string739;string740;string741;string742;string743;string744;string745;string746;string747;string748;string749;string750;string751;string752;string753;string754;string755;string756;string757;string758;string759;string760;string761;string762;string763;string764;string765;string766;string767;string768;string769;string770;string771;string772;string773;string774;string775;string776;string777;string778;string779;string780;string781;string782;string783;string784;string785;string786;string787;string788;string789;string790;string791;string792;string793;string794;string795;string796;string797;string798;string799;string800;string801;string802;string803;string804;string805;string806;string807;string808;string809;string810;string811;string812;string813;string814;string815;string816;string817;string818;string819;string820;string821;string822;string823;string824;string825;string826;string827;string828;string829;string830;string831;string832;string833;string834;string835;string836;string837;string838;string839;string840;string841;string842;string843;string844;string845;string846;string847;string848;string849;string850;string851;string852;string853;string854;string855;string856;string857;string858;string859;string860;string861;string862;string863;string864;string865;string866;string867;string868;string869;string870;string871;string872;string873;string874;string875;string876;string877;string878;string879;string880;string881;string882;string883;string884;string885;string886;string887;string888;string889;string890;string891;string892;string893;string894;string895;string896;string897;string898;string899;string900;string901;string902;string903;string904;string905;string906;string907;string908;string909;string910;string911;string912;string913;string914;string915;string916;string917;string918;string919;string920;string921;string922;string923;string924;string925;string926;string927;string928;string929;string930;string931;string932;string933;string934;string935;string936;string937;string938;string939;string940;string941;string942;string943;string944;string945;string946;string947;string948;string949;string950;string951;string952;string953;string954;string955;string956;string957;string958;string959;string960;string961;string962;string963;string964;string965;string966;string967;string968;string969;string970;string971;string972;string973;string974;string975;string976;string977;string978;string979;string980;string981;string982;string983;string984;string985;string986;string987;string988;string989;string990;string991;string992;string993;string994;string995;string996;string997;string998;string9 +start;ing0;ing1;ing2;ing3;ing4;ing5;ing6;ing7;ing8;ing9;ing10;ing11;ing12;ing13;ing14;ing15;ing16;ing17;ing18;ing19;ing20;ing21;ing22;ing23;ing24;ing25;ing26;ing27;ing28;ing29;ing30;ing31;ing32;ing33;ing34;ing35;ing36;ing37;ing38;ing39;ing40;ing41;ing42;ing43;ing44;ing45;ing46;ing47;ing48;ing49;ing50;ing51;ing52;ing53;ing54;ing55;ing56;ing57;ing58;ing59;ing60;ing61;ing62;ing63;ing64;ing65;ing66;ing67;ing68;ing69;ing70;ing71;ing72;ing73;ing74;ing75;ing76;ing77;ing78;ing79;ing80;ing81;ing82;ing83;ing84;ing85;ing86;ing87;ing88;ing89;ing90;ing91;ing92;ing93;ing94;ing95;ing96;ing97;ing98;ing99;ing100;ing101;ing102;ing103;ing104;ing105;ing106;ing107;ing108;ing109;ing110;ing111;ing112;ing113;ing114;ing115;ing116;ing117;ing118;ing119;ing120;ing121;ing122;ing123;ing124;ing125;ing126;ing127;ing128;ing129;ing130;ing131;ing132;ing133;ing134;ing135;ing136;ing137;ing138;ing139;ing140;ing141;ing142;ing143;ing144;ing145;ing146;ing147;ing148;ing149;ing150;ing151;ing152;ing153;ing154;ing155;ing156;ing157;ing158;ing159;ing160;ing161;ing162;ing163;ing164;ing165;ing166;ing167;ing168;ing169;ing170;ing171;ing172;ing173;ing174;ing175;ing176;ing177;ing178;ing179;ing180;ing181;ing182;ing183;ing184;ing185;ing186;ing187;ing188;ing189;ing190;ing191;ing192;ing193;ing194;ing195;ing196;ing197;ing198;ing199;ing200;ing201;ing202;ing203;ing204;ing205;ing206;ing207;ing208;ing209;ing210;ing211;ing212;ing213;ing214;ing215;ing216;ing217;ing218;ing219;ing220;ing221;ing222;ing223;ing224;ing225;ing226;ing227;ing228;ing229;ing230;ing231;ing232;ing233;ing234;ing235;ing236;ing237;ing238;ing239;ing240;ing241;ing242;ing243;ing244;ing245;ing246;ing247;ing248;ing249;ing250;ing251;ing252;ing253;ing254;ing255;ing256;ing257;ing258;ing259;ing260;ing261;ing262;ing263;ing264;ing265;ing266;ing267;ing268;ing269;ing270;ing271;ing272;ing273;ing274;ing275;ing276;ing277;ing278;ing279;ing280;ing281;ing282;ing283;ing284;ing285;ing286;ing287;ing288;ing289;ing290;ing291;ing292;ing293;ing294;ing295;ing296;ing297;ing298;ing299;ing300;ing301;ing302;ing303;ing304;ing305;ing306;ing307;ing308;ing309;ing310;ing311;ing312;ing313;ing314;ing315;ing316;ing317;ing318;ing319;ing320;ing321;ing322;ing323;ing324;ing325;ing326;ing327;ing328;ing329;ing330;ing331;ing332;ing333;ing334;ing335;ing336;ing337;ing338;ing339;ing340;ing341;ing342;ing343;ing344;ing345;ing346;ing347;ing348;ing349;ing350;ing351;ing352;ing353;ing354;ing355;ing356;ing357;ing358;ing359;ing360;ing361;ing362;ing363;ing364;ing365;ing366;ing367;ing368;ing369;ing370;ing371;ing372;ing373;ing374;ing375;ing376;ing377;ing378;ing379;ing380;ing381;ing382;ing383;ing384;ing385;ing386;ing387;ing388;ing389;ing390;ing391;ing392;ing393;ing394;ing395;ing396;ing397;ing398;ing399;ing400;ing401;ing402;ing403;ing404;ing405;ing406;ing407;ing408;ing409;ing410;ing411;ing412;ing413;ing414;ing415;ing416;ing417;ing418;ing419;ing420;ing421;ing422;ing423;ing424;ing425;ing426;ing427;ing428;ing429;ing430;ing431;ing432;ing433;ing434;ing435;ing436;ing437;ing438;ing439;ing440;ing441;ing442;ing443;ing444;ing445;ing446;ing447;ing448;ing449;ing450;ing451;ing452;ing453;ing454;ing455;ing456;ing457;ing458;ing459;ing460;ing461;ing462;ing463;ing464;ing465;ing466;ing467;ing468;ing469;ing470;ing471;ing472;ing473;ing474;ing475;ing476;ing477;ing478;ing479;ing480;ing481;ing482;ing483;ing484;ing485;ing486;ing487;ing488;ing489;ing490;ing491;ing492;ing493;ing494;ing495;ing496;ing497;ing498;ing499;ing500;ing501;ing502;ing503;ing504;ing505;ing506;ing507;ing508;ing509;ing510;ing511;ing512;ing513;ing514;ing515;ing516;ing517;ing518;ing519;ing520;ing521;ing522;ing523;ing524;ing525;ing526;ing527;ing528;ing529;ing530;ing531;ing532;ing533;ing534;ing535;ing536;ing537;ing538;ing539;ing540;ing541;ing542;ing543;ing544;ing545;ing546;ing547;ing548;ing549;ing550;ing551;ing552;ing553;ing554;ing555;ing556;ing557;ing558;ing559;ing560;ing561;ing562;ing563;ing564;ing565;ing566;ing567;ing568;ing569;ing570;ing571;ing572;ing573;ing574;ing575;ing576;ing577;ing578;ing579;ing580;ing581;ing582;ing583;ing584;ing585;ing586;ing587;ing588;ing589;ing590;ing591;ing592;ing593;ing594;ing595;ing596;ing597;ing598;ing599;ing600;ing601;ing602;ing603;ing604;ing605;ing606;ing607;ing608;ing609;ing610;ing611;ing612;ing613;ing614;ing615;ing616;ing617;ing618;ing619;ing620;ing621;ing622;ing623;ing624;ing625;ing626;ing627;ing628;ing629;ing630;ing631;ing632;ing633;ing634;ing635;ing636;ing637;ing638;ing639;ing640;ing641;ing642;ing643;ing644;ing645;ing646;ing647;ing648;ing649;ing650;ing651;ing652;ing653;ing654;ing655;ing656;ing657;ing658;ing659;ing660;ing661;ing662;ing663;ing664;ing665;ing666;ing667;ing668;ing669;ing670;ing671;ing672;ing673;ing674;ing675;ing676;ing677;ing678;ing679;ing680;ing681;ing682;ing683;ing684;ing685;ing686;ing687;ing688;ing689;ing690;ing691;ing692;ing693;ing694;ing695;ing696;ing697;ing698;ing699;ing700;ing701;ing702;ing703;ing704;ing705;ing706;ing707;ing708;ing709;ing710;ing711;ing712;ing713;ing714;ing715;ing716;ing717;ing718;ing719;ing720;ing721;ing722;ing723;ing724;ing725;ing726;ing727;ing728;ing729;ing730;ing731;ing732;ing733;ing734;ing735;ing736;ing737;ing738;ing739;ing740;ing741;ing742;ing743;ing744;ing745;ing746;ing747;ing748;ing749;ing750;ing751;ing752;ing753;ing754;ing755;ing756;ing757;ing758;ing759;ing760;ing761;ing762;ing763;ing764;ing765;ing766;ing767;ing768;ing769;ing770;ing771;ing772;ing773;ing774;ing775;ing776;ing777;ing778;ing779;ing780;ing781;ing782;ing783;ing784;ing785;ing786;ing787;ing788;ing789;ing790;ing791;ing792;ing793;ing794;ing795;ing796;ing797;ing798;ing799;ing800;ing801;ing802;ing803;ing804;ing805;ing806;ing807;ing808;ing809;ing810;ing811;ing812;ing813;ing814;ing815;ing816;ing817;ing818;ing819;ing820;ing821;ing822;ing823;ing824;ing825;ing826;ing827;ing828;ing829;ing830;ing831;ing832;ing833;ing834;ing835;ing836;ing837;ing838;ing839;ing840;ing841;ing842;ing843;ing844;ing845;ing846;ing847;ing848;ing849;ing850;ing851;ing852;ing853;ing854;ing855;ing856;ing857;ing858;ing859;ing860;ing861;ing862;ing863;ing864;ing865;ing866;ing867;ing868;ing869;ing870;ing871;ing872;ing873;ing874;ing875;ing876;ing877;ing878;ing879;ing880;ing881;ing882;ing883;ing884;ing885;ing886;ing887;ing888;ing889;ing890;ing891;ing892;ing893;ing894;ing895;ing896;ing897;ing898;ing899;ing900;ing901;ing902;ing903;ing904;ing905;ing906;ing907;ing908;ing909;ing910;ing911;ing912;ing913;ing914;ing915;ing916;ing917;ing918;ing919;ing920;ing921;ing922;ing923;ing924;ing925;ing926;ing927;ing928;ing929;ing930;ing931;ing932;ing933;ing934;ing935;ing936;ing937;ing938;ing939;ing940;ing941;ing942;ing943;ing944;ing945;ing946;ing947;ing948;ing949;ing950;ing951;ing952;ing953;ing954;ing955;ing956;ing957;ing958;ing959;ing960;ing961;ing962;ing963;ing964;ing965;ing966;ing967;ing968;ing969;ing970;ing971;ing972;ing973;ing974;ing975;ing976;ing977;ing978;ing979;ing980;ing981;ing982;ing983;ing984;ing985;ing986;ing987;ing988;ing989;ing990;ing991;ing992;ing993;ing994;ing995;ing996;ing997;ing998;ing999 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +start;string0;string1;string2;string3;string4;string5;string6;string7;string8;string9;string10;string11;string12;string13;string14;string15;string16;string17;string18;string19;string20;string21;string22;string23;string24;string25;string26;string27;string28;string29;string30;string31;string32;string33;string34;string35;string36;string37;string38;string39;string40;string41;string42;string43;string44;string45;string46;string47;string48;string49;string50;string51;string52;string53;string54;string55;string56;string57;string58;string59;string60;string61;string62;string63;string64;string65;string66;string67;string68;string69;string70;string71;string72;string73;string74;string75;string76;string77;string78;string79;string80;string81;string82;string83;string84;string85;string86;string87;string88;string89;string90;string91;string92;string93;string94;string95;string96;string97;string98;string99;string100;string101;string102;string103;string104;string105;string106;string107;string108;string109;string110;string111;string112;string113;string114;string115;string116;string117;string118;string119;string120;string121;string122;string123;string124;string125;string126;string127;string128;string129;string130;string131;string132;string133;string134;string135;string136;string137;string138;string139;string140;string141;string142;string143;string144;string145;string146;string147;string148;string149;string150;string151;string152;string153;string154;string155;string156;string157;string158;string159;string160;string161;string162;string163;string164;string165;string166;string167;string168;string169;string170;string171;string172;string173;string174;string175;string176;string177;string178;string179;string180;string181;string182;string183;string184;string185;string186;string187;string188;string189;string190;string191;string192;string193;string194;string195;string196;string197;string198;string199;string200;string201;string202;string203;string204;string205;string206;string207;string208;string209;string210;string211;string212;string213;string214;string215;string216;string217;string218;string219;string220;string221;string222;string223;string224;string225;string226;string227;string228;string229;string230;string231;string232;string233;string234;string235;string236;string237;string238;string239;string240;string241;string242;string243;string244;string245;string246;string247;string248;string249;string250;string251;string252;string253;string254;string255;string256;string257;string258;string259;string260;string261;string262;string263;string264;string265;string266;string267;string268;string269;string270;string271;string272;string273;string274;string275;string276;string277;string278;string279;string280;string281;string282;string283;string284;string285;string286;string287;string288;string289;string290;string291;string292;string293;string294;string295;string296;string297;string298;string299;string300;string301;string302;string303;string304;string305;string306;string307;string308;string309;string310;string311;string312;string313;string314;string315;string316;string317;string318;string319;string320;string321;string322;string323;string324;string325;string326;string327;string328;string329;string330;string331;string332;string333;string334;string335;string336;string337;string338;string339;string340;string341;string342;string343;string344;string345;string346;string347;string348;string349;string350;string351;string352;string353;string354;string355;string356;string357;string358;string359;string360;string361;string362;string363;string364;string365;string366;string367;string368;string369;string370;string371;string372;string373;string374;string375;string376;string377;string378;string379;string380;string381;string382;string383;string384;string385;string386;string387;string388;string389;string390;string391;string392;string393;string394;string395;string396;string397;string398;string399;string400;string401;string402;string403;string404;string405;string406;string407;string408;string409;string410;string411;string412;string413;string414;string415;string416;string417;string418;string419;string420;string421;string422;string423;string424;string425;string426;string427;string428;string429;string430;string431;string432;string433;string434;string435;string436;string437;string438;string439;string440;string441;string442;string443;string444;string445;string446;string447;string448;string449;string450;string451;string452;string453;string454;string455;string456;string457;string458;string459;string460;string461;string462;string463;string464;string465;string466;string467;string468;string469;string470;string471;string472;string473;string474;string475;string476;string477;string478;string479;string480;string481;string482;string483;string484;string485;string486;string487;string488;string489;string490;string491;string492;string493;string494;string495;string496;string497;string498;string499;string500;string501;string502;string503;string504;string505;string506;string507;string508;string509;string510;string511;string512;string513;string514;string515;string516;string517;string518;string519;string520;string521;string522;string523;string524;string525;string526;string527;string528;string529;string530;string531;string532;string533;string534;string535;string536;string537;string538;string539;string540;string541;string542;string543;string544;string545;string546;string547;string548;string549;string550;string551;string552;string553;string554;string555;string556;string557;string558;string559;string560;string561;string562;string563;string564;string565;string566;string567;string568;string569;string570;string571;string572;string573;string574;string575;string576;string577;string578;string579;string580;string581;string582;string583;string584;string585;string586;string587;string588;string589;string590;string591;string592;string593;string594;string595;string596;string597;string598;string599;string600;string601;string602;string603;string604;string605;string606;string607;string608;string609;string610;string611;string612;string613;string614;string615;string616;string617;string618;string619;string620;string621;string622;string623;string624;string625;string626;string627;string628;string629;string630;string631;string632;string633;string634;string635;string636;string637;string638;string639;string640;string641;string642;string643;string644;string645;string646;string647;string648;string649;string650;string651;string652;string653;string654;string655;string656;string657;string658;string659;string660;string661;string662;string663;string664;string665;string666;string667;string668;string669;string670;string671;string672;string673;string674;string675;string676;string677;string678;string679;string680;string681;string682;string683;string684;string685;string686;string687;string688;string689;string690;string691;string692;string693;string694;string695;string696;string697;string698;string699;string700;string701;string702;string703;string704;string705;string706;string707;string708;string709;string710;string711;string712;string713;string714;string715;string716;string717;string718;string719;string720;string721;string722;string723;string724;string725;string726;string727;string728;string729;string730;string731;string732;string733;string734;string735;string736;string737;string738;string739;string740;string741;string742;string743;string744;string745;string746;string747;string748;string749;string750;string751;string752;string753;string754;string755;string756;string757;string758;string759;string760;string761;string762;string763;string764;string765;string766;string767;string768;string769;string770;string771;string772;string773;string774;string775;string776;string777;string778;string779;string780;string781;string782;string783;string784;string785;string786;string787;string788;string789;string790;string791;string792;string793;string794;string795;string796;string797;string798;string799;string800;string801;string802;string803;string804;string805;string806;string807;string808;string809;string810;string811;string812;string813;string814;string815;string816;string817;string818;string819;string820;string821;string822;string823;string824;string825;string826;string827;string828;string829;string830;string831;string832;string833;string834;string835;string836;string837;string838;string839;string840;string841;string842;string843;string844;string845;string846;string847;string848;string849;string850;string851;string852;string853;string854;string855;string856;string857;string858;string859;string860;string861;string862;string863;string864;string865;string866;string867;string868;string869;string870;string871;string872;string873;string874;string875;string876;string877;string878;string879;string880;string881;string882;string883;string884;string885;string886;string887;string888;string889;string890;string891;string892;string893;string894;string895;string896;string897;string898;string899;string900;string901;string902;string903;string904;string905;string906;string907;string908;string909;string910;string911;string912;string913;string914;string915;string916;string917;string918;string919;string920;string921;string922;string923;string924;string925;string926;string927;string928;string929;string930;string931;string932;string933;string934;string935;string936;string937;string938;string939;string940;string941;string942;string943;string944;string945;string946;string947;string948;string949;string950;string951;string952;string953;string954;string955;string956;string957;string958;string959;string960;string961;string962;string963;string964;string965;string966;string967;string968;string969;string970;string971;string972;string973;string974;string975;string976;string977;string978;string979;string980;string981;string982;string983;string984;string985;string986;string987;string988;string989;string990;string991;string992;string993;string994;string995;string996;string997;string998;string999 +start;ing0;ing1;ing2;ing3;ing4;ing5;ing6;ing7;ing8;ing9;ing10;ing11;ing12;ing13;ing14;ing15;ing16;ing17;ing18;ing19;ing20;ing21;ing22;ing23;ing24;ing25;ing26;ing27;ing28;ing29;ing30;ing31;ing32;ing33;ing34;ing35;ing36;ing37;ing38;ing39;ing40;ing41;ing42;ing43;ing44;ing45;ing46;ing47;ing48;ing49;ing50;ing51;ing52;ing53;ing54;ing55;ing56;ing57;ing58;ing59;ing60;ing61;ing62;ing63;ing64;ing65;ing66;ing67;ing68;ing69;ing70;ing71;ing72;ing73;ing74;ing75;ing76;ing77;ing78;ing79;ing80;ing81;ing82;ing83;ing84;ing85;ing86;ing87;ing88;ing89;ing90;ing91;ing92;ing93;ing94;ing95;ing96;ing97;ing98;ing99;ing100;ing101;ing102;ing103;ing104;ing105;ing106;ing107;ing108;ing109;ing110;ing111;ing112;ing113;ing114;ing115;ing116;ing117;ing118;ing119;ing120;ing121;ing122;ing123;ing124;ing125;ing126;ing127;ing128;ing129;ing130;ing131;ing132;ing133;ing134;ing135;ing136;ing137;ing138;ing139;ing140;ing141;ing142;ing143;ing144;ing145;ing146;ing147;ing148;ing149;ing150;ing151;ing152;ing153;ing154;ing155;ing156;ing157;ing158;ing159;ing160;ing161;ing162;ing163;ing164;ing165;ing166;ing167;ing168;ing169;ing170;ing171;ing172;ing173;ing174;ing175;ing176;ing177;ing178;ing179;ing180;ing181;ing182;ing183;ing184;ing185;ing186;ing187;ing188;ing189;ing190;ing191;ing192;ing193;ing194;ing195;ing196;ing197;ing198;ing199;ing200;ing201;ing202;ing203;ing204;ing205;ing206;ing207;ing208;ing209;ing210;ing211;ing212;ing213;ing214;ing215;ing216;ing217;ing218;ing219;ing220;ing221;ing222;ing223;ing224;ing225;ing226;ing227;ing228;ing229;ing230;ing231;ing232;ing233;ing234;ing235;ing236;ing237;ing238;ing239;ing240;ing241;ing242;ing243;ing244;ing245;ing246;ing247;ing248;ing249;ing250;ing251;ing252;ing253;ing254;ing255;ing256;ing257;ing258;ing259;ing260;ing261;ing262;ing263;ing264;ing265;ing266;ing267;ing268;ing269;ing270;ing271;ing272;ing273;ing274;ing275;ing276;ing277;ing278;ing279;ing280;ing281;ing282;ing283;ing284;ing285;ing286;ing287;ing288;ing289;ing290;ing291;ing292;ing293;ing294;ing295;ing296;ing297;ing298;ing299;ing300;ing301;ing302;ing303;ing304;ing305;ing306;ing307;ing308;ing309;ing310;ing311;ing312;ing313;ing314;ing315;ing316;ing317;ing318;ing319;ing320;ing321;ing322;ing323;ing324;ing325;ing326;ing327;ing328;ing329;ing330;ing331;ing332;ing333;ing334;ing335;ing336;ing337;ing338;ing339;ing340;ing341;ing342;ing343;ing344;ing345;ing346;ing347;ing348;ing349;ing350;ing351;ing352;ing353;ing354;ing355;ing356;ing357;ing358;ing359;ing360;ing361;ing362;ing363;ing364;ing365;ing366;ing367;ing368;ing369;ing370;ing371;ing372;ing373;ing374;ing375;ing376;ing377;ing378;ing379;ing380;ing381;ing382;ing383;ing384;ing385;ing386;ing387;ing388;ing389;ing390;ing391;ing392;ing393;ing394;ing395;ing396;ing397;ing398;ing399;ing400;ing401;ing402;ing403;ing404;ing405;ing406;ing407;ing408;ing409;ing410;ing411;ing412;ing413;ing414;ing415;ing416;ing417;ing418;ing419;ing420;ing421;ing422;ing423;ing424;ing425;ing426;ing427;ing428;ing429;ing430;ing431;ing432;ing433;ing434;ing435;ing436;ing437;ing438;ing439;ing440;ing441;ing442;ing443;ing444;ing445;ing446;ing447;ing448;ing449;ing450;ing451;ing452;ing453;ing454;ing455;ing456;ing457;ing458;ing459;ing460;ing461;ing462;ing463;ing464;ing465;ing466;ing467;ing468;ing469;ing470;ing471;ing472;ing473;ing474;ing475;ing476;ing477;ing478;ing479;ing480;ing481;ing482;ing483;ing484;ing485;ing486;ing487;ing488;ing489;ing490;ing491;ing492;ing493;ing494;ing495;ing496;ing497;ing498;ing499;ing500;ing501;ing502;ing503;ing504;ing505;ing506;ing507;ing508;ing509;ing510;ing511;ing512;ing513;ing514;ing515;ing516;ing517;ing518;ing519;ing520;ing521;ing522;ing523;ing524;ing525;ing526;ing527;ing528;ing529;ing530;ing531;ing532;ing533;ing534;ing535;ing536;ing537;ing538;ing539;ing540;ing541;ing542;ing543;ing544;ing545;ing546;ing547;ing548;ing549;ing550;ing551;ing552;ing553;ing554;ing555;ing556;ing557;ing558;ing559;ing560;ing561;ing562;ing563;ing564;ing565;ing566;ing567;ing568;ing569;ing570;ing571;ing572;ing573;ing574;ing575;ing576;ing577;ing578;ing579;ing580;ing581;ing582;ing583;ing584;ing585;ing586;ing587;ing588;ing589;ing590;ing591;ing592;ing593;ing594;ing595;ing596;ing597;ing598;ing599;ing600;ing601;ing602;ing603;ing604;ing605;ing606;ing607;ing608;ing609;ing610;ing611;ing612;ing613;ing614;ing615;ing616;ing617;ing618;ing619;ing620;ing621;ing622;ing623;ing624;ing625;ing626;ing627;ing628;ing629;ing630;ing631;ing632;ing633;ing634;ing635;ing636;ing637;ing638;ing639;ing640;ing641;ing642;ing643;ing644;ing645;ing646;ing647;ing648;ing649;ing650;ing651;ing652;ing653;ing654;ing655;ing656;ing657;ing658;ing659;ing660;ing661;ing662;ing663;ing664;ing665;ing666;ing667;ing668;ing669;ing670;ing671;ing672;ing673;ing674;ing675;ing676;ing677;ing678;ing679;ing680;ing681;ing682;ing683;ing684;ing685;ing686;ing687;ing688;ing689;ing690;ing691;ing692;ing693;ing694;ing695;ing696;ing697;ing698;ing699;ing700;ing701;ing702;ing703;ing704;ing705;ing706;ing707;ing708;ing709;ing710;ing711;ing712;ing713;ing714;ing715;ing716;ing717;ing718;ing719;ing720;ing721;ing722;ing723;ing724;ing725;ing726;ing727;ing728;ing729;ing730;ing731;ing732;ing733;ing734;ing735;ing736;ing737;ing738;ing739;ing740;ing741;ing742;ing743;ing744;ing745;ing746;ing747;ing748;ing749;ing750;ing751;ing752;ing753;ing754;ing755;ing756;ing757;ing758;ing759;ing760;ing761;ing762;ing763;ing764;ing765;ing766;ing767;ing768;ing769;ing770;ing771;ing772;ing773;ing774;ing775;ing776;ing777;ing778;ing779;ing780;ing781;ing782;ing783;ing784;ing785;ing786;ing787;ing788;ing789;ing790;ing791;ing792;ing793;ing794;ing795;ing796;ing797;ing798;ing799;ing800;ing801;ing802;ing803;ing804;ing805;ing806;ing807;ing808;ing809;ing810;ing811;ing812;ing813;ing814;ing815;ing816;ing817;ing818;ing819;ing820;ing821;ing822;ing823;ing824;ing825;ing826;ing827;ing828;ing829;ing830;ing831;ing832;ing833;ing834;ing835;ing836;ing837;ing838;ing839;ing840;ing841;ing842;ing843;ing844;ing845;ing846;ing847;ing848;ing849;ing850;ing851;ing852;ing853;ing854;ing855;ing856;ing857;ing858;ing859;ing860;ing861;ing862;ing863;ing864;ing865;ing866;ing867;ing868;ing869;ing870;ing871;ing872;ing873;ing874;ing875;ing876;ing877;ing878;ing879;ing880;ing881;ing882;ing883;ing884;ing885;ing886;ing887;ing888;ing889;ing890;ing891;ing892;ing893;ing894;ing895;ing896;ing897;ing898;ing899;ing900;ing901;ing902;ing903;ing904;ing905;ing906;ing907;ing908;ing909;ing910;ing911;ing912;ing913;ing914;ing915;ing916;ing917;ing918;ing919;ing920;ing921;ing922;ing923;ing924;ing925;ing926;ing927;ing928;ing929;ing930;ing931;ing932;ing933;ing934;ing935;ing936;ing937;ing938;ing939;ing940;ing941;ing942;ing943;ing944;ing945;ing946;ing947;ing948;ing949;ing950;ing951;ing952;ing953;ing954;ing955;ing956;ing957;ing958;ing959;ing960;ing961;ing962;ing963;ing964;ing965;ing966;ing967;ing968;ing969;ing970;ing971;ing972;ing973;ing974;ing975;ing976;ing977;ing978;ing979;ing980;ing981;ing982;ing983;ing984;ing985;ing986;ing987;ing988;ing989;ing990;ing991;ing992;ing993;ing994;ing995;ing996;ing997;ing998;ing999 +start;string0;string1;string2;string3;string4;string5;string6;string7;string8;string9;string10;string11;string12;string13;string14;string15;string16;string17;string18;string19;string20;string21;string22;string23;string24;string25;string26;string27;string28;string29;string30;string31;string32;string33;string34;string35;string36;string37;string38;string39;string40;string41;string42;string43;string44;string45;string46;string47;string48;string49;string50;string51;string52;string53;string54;string55;string56;string57;string58;string59;string60;string61;string62;string63;string64;string65;string66;string67;string68;string69;string70;string71;string72;string73;string74;string75;string76;string77;string78;string79;string80;string81;string82;string83;string84;string85;string86;string87;string88;string89;string90;string91;string92;string93;string94;string95;string96;string97;string98;string99;string100;string101;string102;string103;string104;string105;string106;string107;string108;string109;string110;string111;string112;string113;string114;string115;string116;string117;string118;string119;string120;string121;string122;string123;string124;string125;string126;string127;string128;string129;string130;string131;string132;string133;string134;string135;string136;string137;string138;string139;string140;string141;string142;string143;string144;string145;string146;string147;string148;string149;string150;string151;string152;string153;string154;string155;string156;string157;string158;string159;string160;string161;string162;string163;string164;string165;string166;string167;string168;string169;string170;string171;string172;string173;string174;string175;string176;string177;string178;string179;string180;string181;string182;string183;string184;string185;string186;string187;string188;string189;string190;string191;string192;string193;string194;string195;string196;string197;string198;string199;string200;string201;string202;string203;string204;string205;string206;string207;string208;string209;string210;string211;string212;string213;string214;string215;string216;string217;string218;string219;string220;string221;string222;string223;string224;string225;string226;string227;string228;string229;string230;string231;string232;string233;string234;string235;string236;string237;string238;string239;string240;string241;string242;string243;string244;string245;string246;string247;string248;string249;string250;string251;string252;string253;string254;string255;string256;string257;string258;string259;string260;string261;string262;string263;string264;string265;string266;string267;string268;string269;string270;string271;string272;string273;string274;string275;string276;string277;string278;string279;string280;string281;string282;string283;string284;string285;string286;string287;string288;string289;string290;string291;string292;string293;string294;string295;string296;string297;string298;string299;string300;string301;string302;string303;string304;string305;string306;string307;string308;string309;string310;string311;string312;string313;string314;string315;string316;string317;string318;string319;string320;string321;string322;string323;string324;string325;string326;string327;string328;string329;string330;string331;string332;string333;string334;string335;string336;string337;string338;string339;string340;string341;string342;string343;string344;string345;string346;string347;string348;string349;string350;string351;string352;string353;string354;string355;string356;string357;string358;string359;string360;string361;string362;string363;string364;string365;string366;string367;string368;string369;string370;string371;string372;string373;string374;string375;string376;string377;string378;string379;string380;string381;string382;string383;string384;string385;string386;string387;string388;string389;string390;string391;string392;string393;string394;string395;string396;string397;string398;string399;string400;string401;string402;string403;string404;string405;string406;string407;string408;string409;string410;string411;string412;string413;string414;string415;string416;string417;string418;string419;string420;string421;string422;string423;string424;string425;string426;string427;string428;string429;string430;string431;string432;string433;string434;string435;string436;string437;string438;string439;string440;string441;string442;string443;string444;string445;string446;string447;string448;string449;string450;string451;string452;string453;string454;string455;string456;string457;string458;string459;string460;string461;string462;string463;string464;string465;string466;string467;string468;string469;string470;string471;string472;string473;string474;string475;string476;string477;string478;string479;string480;string481;string482;string483;string484;string485;string486;string487;string488;string489;string490;string491;string492;string493;string494;string495;string496;string497;string498;string499;string500;string501;string502;string503;string504;string505;string506;string507;string508;string509;string510;string511;string512;string513;string514;string515;string516;string517;string518;string519;string520;string521;string522;string523;string524;string525;string526;string527;string528;string529;string530;string531;string532;string533;string534;string535;string536;string537;string538;string539;string540;string541;string542;string543;string544;string545;string546;string547;string548;string549;string550;string551;string552;string553;string554;string555;string556;string557;string558;string559;string560;string561;string562;string563;string564;string565;string566;string567;string568;string569;string570;string571;string572;string573;string574;string575;string576;string577;string578;string579;string580;string581;string582;string583;string584;string585;string586;string587;string588;string589;string590;string591;string592;string593;string594;string595;string596;string597;string598;string599;string600;string601;string602;string603;string604;string605;string606;string607;string608;string609;string610;string611;string612;string613;string614;string615;string616;string617;string618;string619;string620;string621;string622;string623;string624;string625;string626;string627;string628;string629;string630;string631;string632;string633;string634;string635;string636;string637;string638;string639;string640;string641;string642;string643;string644;string645;string646;string647;string648;string649;string650;string651;string652;string653;string654;string655;string656;string657;string658;string659;string660;string661;string662;string663;string664;string665;string666;string667;string668;string669;string670;string671;string672;string673;string674;string675;string676;string677;string678;string679;string680;string681;string682;string683;string684;string685;string686;string687;string688;string689;string690;string691;string692;string693;string694;string695;string696;string697;string698;string699;string700;string701;string702;string703;string704;string705;string706;string707;string708;string709;string710;string711;string712;string713;string714;string715;string716;string717;string718;string719;string720;string721;string722;string723;string724;string725;string726;string727;string728;string729;string730;string731;string732;string733;string734;string735;string736;string737;string738;string739;string740;string741;string742;string743;string744;string745;string746;string747;string748;string749;string750;string751;string752;string753;string754;string755;string756;string757;string758;string759;string760;string761;string762;string763;string764;string765;string766;string767;string768;string769;string770;string771;string772;string773;string774;string775;string776;string777;string778;string779;string780;string781;string782;string783;string784;string785;string786;string787;string788;string789;string790;string791;string792;string793;string794;string795;string796;string797;string798;string799;string800;string801;string802;string803;string804;string805;string806;string807;string808;string809;string810;string811;string812;string813;string814;string815;string816;string817;string818;string819;string820;string821;string822;string823;string824;string825;string826;string827;string828;string829;string830;string831;string832;string833;string834;string835;string836;string837;string838;string839;string840;string841;string842;string843;string844;string845;string846;string847;string848;string849;string850;string851;string852;string853;string854;string855;string856;string857;string858;string859;string860;string861;string862;string863;string864;string865;string866;string867;string868;string869;string870;string871;string872;string873;string874;string875;string876;string877;string878;string879;string880;string881;string882;string883;string884;string885;string886;string887;string888;string889;string890;string891;string892;string893;string894;string895;string896;string897;string898;string899;string900;string901;string902;string903;string904;string905;string906;string907;string908;string909;string910;string911;string912;string913;string914;string915;string916;string917;string918;string919;string920;string921;string922;string923;string924;string925;string926;string927;string928;string929;string930;string931;string932;string933;string934;string935;string936;string937;string938;string939;string940;string941;string942;string943;string944;string945;string946;string947;string948;string949;string950;string951;string952;string953;string954;string955;string956;string957;string958;string959;string960;string961;string962;string963;string964;string965;string966;string967;string968;string969;string970;string971;string972;string973;string974;string975;string976;string977;string978;string979;string980;string981;string982;string983;string984;string985;string986;string987;string988;string989;string990;string991;string992;string993;string994;string995;string996;string997;string998;string999 +start;string0;string1;string2;string3;string4;string5;string6;string7;string8;string9;string10;string11;string12;string13;string14;string15;string16;string17;string18;string19;string20;string21;string22;string23;string24;string25;string26;string27;string28;string29;string30;string31;string32;string33;string34;string35;string36;string37;string38;string39;string40;string41;string42;string43;string44;string45;string46;string47;string48;string49;string50;string51;string52;string53;string54;string55;string56;string57;string58;string59;string60;string61;string62;string63;string64;string65;string66;string67;string68;string69;string70;string71;string72;string73;string74;string75;string76;string77;string78;string79;string80;string81;string82;string83;string84;string85;string86;string87;string88;string89;string90;string91;string92;string93;string94;string95;string96;string97;string98;string99;string100;string101;string102;string103;string104;string105;string106;string107;string108;string109;string110;string111;string112;string113;string114;string115;string116;string117;string118;string119;string120;string121;string122;string123;string124;string125;string126;string127;string128;string129;string130;string131;string132;string133;string134;string135;string136;string137;string138;string139;string140;string141;string142;string143;string144;string145;string146;string147;string148;string149;string150;string151;string152;string153;string154;string155;string156;string157;string158;string159;string160;string161;string162;string163;string164;string165;string166;string167;string168;string169;string170;string171;string172;string173;string174;string175;string176;string177;string178;string179;string180;string181;string182;string183;string184;string185;string186;string187;string188;string189;string190;string191;string192;string193;string194;string195;string196;string197;string198;string199;string200;string201;string202;string203;string204;string205;string206;string207;string208;string209;string210;string211;string212;string213;string214;string215;string216;string217;string218;string219;string220;string221;string222;string223;string224;string225;string226;string227;string228;string229;string230;string231;string232;string233;string234;string235;string236;string237;string238;string239;string240;string241;string242;string243;string244;string245;string246;string247;string248;string249;string250;string251;string252;string253;string254;string255;string256;string257;string258;string259;string260;string261;string262;string263;string264;string265;string266;string267;string268;string269;string270;string271;string272;string273;string274;string275;string276;string277;string278;string279;string280;string281;string282;string283;string284;string285;string286;string287;string288;string289;string290;string291;string292;string293;string294;string295;string296;string297;string298;string299;string300;string301;string302;string303;string304;string305;string306;string307;string308;string309;string310;string311;string312;string313;string314;string315;string316;string317;string318;string319;string320;string321;string322;string323;string324;string325;string326;string327;string328;string329;string330;string331;string332;string333;string334;string335;string336;string337;string338;string339;string340;string341;string342;string343;string344;string345;string346;string347;string348;string349;string350;string351;string352;string353;string354;string355;string356;string357;string358;string359;string360;string361;string362;string363;string364;string365;string366;string367;string368;string369;string370;string371;string372;string373;string374;string375;string376;string377;string378;string379;string380;string381;string382;string383;string384;string385;string386;string387;string388;string389;string390;string391;string392;string393;string394;string395;string396;string397;string398;string399;string400;string401;string402;string403;string404;string405;string406;string407;string408;string409;string410;string411;string412;string413;string414;string415;string416;string417;string418;string419;string420;string421;string422;string423;string424;string425;string426;string427;string428;string429;string430;string431;string432;string433;string434;string435;string436;string437;string438;string439;string440;string441;string442;string443;string444;string445;string446;string447;string448;string449;string450;string451;string452;string453;string454;string455;string456;string457;string458;string459;string460;string461;string462;string463;string464;string465;string466;string467;string468;string469;string470;string471;string472;string473;string474;string475;string476;string477;string478;string479;string480;string481;string482;string483;string484;string485;string486;string487;string488;string489;string490;string491;string492;string493;string494;string495;string496;string497;string498;string499;string500;string501;string502;string503;string504;string505;string506;string507;string508;string509;string510;string511;string512;string513;string514;string515;string516;string517;string518;string519;string520;string521;string522;string523;string524;string525;string526;string527;string528;string529;string530;string531;string532;string533;string534;string535;string536;string537;string538;string539;string540;string541;string542;string543;string544;string545;string546;string547;string548;string549;string550;string551;string552;string553;string554;string555;string556;string557;string558;string559;string560;string561;string562;string563;string564;string565;string566;string567;string568;string569;string570;string571;string572;string573;string574;string575;string576;string577;string578;string579;string580;string581;string582;string583;string584;string585;string586;string587;string588;string589;string590;string591;string592;string593;string594;string595;string596;string597;string598;string599;string600;string601;string602;string603;string604;string605;string606;string607;string608;string609;string610;string611;string612;string613;string614;string615;string616;string617;string618;string619;string620;string621;string622;string623;string624;string625;string626;string627;string628;string629;string630;string631;string632;string633;string634;string635;string636;string637;string638;string639;string640;string641;string642;string643;string644;string645;string646;string647;string648;string649;string650;string651;string652;string653;string654;string655;string656;string657;string658;string659;string660;string661;string662;string663;string664;string665;string666;string667;string668;string669;string670;string671;string672;string673;string674;string675;string676;string677;string678;string679;string680;string681;string682;string683;string684;string685;string686;string687;string688;string689;string690;string691;string692;string693;string694;string695;string696;string697;string698;string699;string700;string701;string702;string703;string704;string705;string706;string707;string708;string709;string710;string711;string712;string713;string714;string715;string716;string717;string718;string719;string720;string721;string722;string723;string724;string725;string726;string727;string728;string729;string730;string731;string732;string733;string734;string735;string736;string737;string738;string739;string740;string741;string742;string743;string744;string745;string746;string747;string748;string749;string750;string751;string752;string753;string754;string755;string756;string757;string758;string759;string760;string761;string762;string763;string764;string765;string766;string767;string768;string769;string770;string771;string772;string773;string774;string775;string776;string777;string778;string779;string780;string781;string782;string783;string784;string785;string786;string787;string788;string789;string790;string791;string792;string793;string794;string795;string796;string797;string798;string799;string800;string801;string802;string803;string804;string805;string806;string807;string808;string809;string810;string811;string812;string813;string814;string815;string816;string817;string818;string819;string820;string821;string822;string823;string824;string825;string826;string827;string828;string829;string830;string831;string832;string833;string834;string835;string836;string837;string838;string839;string840;string841;string842;string843;string844;string845;string846;string847;string848;string849;string850;string851;string852;string853;string854;string855;string856;string857;string858;string859;string860;string861;string862;string863;string864;string865;string866;string867;string868;string869;string870;string871;string872;string873;string874;string875;string876;string877;string878;string879;string880;string881;string882;string883;string884;string885;string886;string887;string888;string889;string890;string891;string892;string893;string894;string895;string896;string897;string898;string899;string900;string901;string902;string903;string904;string905;string906;string907;string908;string909;string910;string911;string912;string913;string914;string915;string916;string917;string918;string919;string920;string921;string922;string923;string924;string925;string926;string927;string928;string929;string930;string931;string932;string933;string934;string935;string936;string937;string938;string939;string940;string941;string942;string943;string944;string945;string946;string947;string948;string949;string950;string951;string952;string953;string954;string955;string956;string957;string958;string959;string960;string961;string962;string963;string964;string965;string966;string967;string968;string969;string970;string971;string972;string973;string974;string975;string976;string977;string978;string979;string980;string981;string982;string983;string984;string985;string986;string987;string988;string989;string990;string991;string992;string993;string994;string995;string996;string997;string998;string999 +ing999 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +art;string0;string1;string2;string3;string4;string5;string6;string7;string8;string9;string10;string11;string12;string13;string14;string15;string16;string17;string18;string19;string20;string21;string22;string23;string24;string25;string26;string27;string28;string29;string30;string31;string32;string33;string34;string35;string36;string37;string38;string39;string40;string41;string42;string43;string44;string45;string46;string47;string48;string49;string50;string51;string52;string53;string54;string55;string56;string57;string58;string59;string60;string61;string62;string63;string64;string65;string66;string67;string68;string69;string70;string71;string72;string73;string74;string75;string76;string77;string78;string79;string80;string81;string82;string83;string84;string85;string86;string87;string88;string89;string90;string91;string92;string93;string94;string95;string96;string97;string98;string99;string100;string101;string102;string103;string104;string105;string106;string107;string108;string109;string110;string111;string112;string113;string114;string115;string116;string117;string118;string119;string120;string121;string122;string123;string124;string125;string126;string127;string128;string129;string130;string131;string132;string133;string134;string135;string136;string137;string138;string139;string140;string141;string142;string143;string144;string145;string146;string147;string148;string149;string150;string151;string152;string153;string154;string155;string156;string157;string158;string159;string160;string161;string162;string163;string164;string165;string166;string167;string168;string169;string170;string171;string172;string173;string174;string175;string176;string177;string178;string179;string180;string181;string182;string183;string184;string185;string186;string187;string188;string189;string190;string191;string192;string193;string194;string195;string196;string197;string198;string199;string200;string201;string202;string203;string204;string205;string206;string207;string208;string209;string210;string211;string212;string213;string214;string215;string216;string217;string218;string219;string220;string221;string222;string223;string224;string225;string226;string227;string228;string229;string230;string231;string232;string233;string234;string235;string236;string237;string238;string239;string240;string241;string242;string243;string244;string245;string246;string247;string248;string249;string250;string251;string252;string253;string254;string255;string256;string257;string258;string259;string260;string261;string262;string263;string264;string265;string266;string267;string268;string269;string270;string271;string272;string273;string274;string275;string276;string277;string278;string279;string280;string281;string282;string283;string284;string285;string286;string287;string288;string289;string290;string291;string292;string293;string294;string295;string296;string297;string298;string299;string300;string301;string302;string303;string304;string305;string306;string307;string308;string309;string310;string311;string312;string313;string314;string315;string316;string317;string318;string319;string320;string321;string322;string323;string324;string325;string326;string327;string328;string329;string330;string331;string332;string333;string334;string335;string336;string337;string338;string339;string340;string341;string342;string343;string344;string345;string346;string347;string348;string349;string350;string351;string352;string353;string354;string355;string356;string357;string358;string359;string360;string361;string362;string363;string364;string365;string366;string367;string368;string369;string370;string371;string372;string373;string374;string375;string376;string377;string378;string379;string380;string381;string382;string383;string384;string385;string386;string387;string388;string389;string390;string391;string392;string393;string394;string395;string396;string397;string398;string399;string400;string401;string402;string403;string404;string405;string406;string407;string408;string409;string410;string411;string412;string413;string414;string415;string416;string417;string418;string419;string420;string421;string422;string423;string424;string425;string426;string427;string428;string429;string430;string431;string432;string433;string434;string435;string436;string437;string438;string439;string440;string441;string442;string443;string444;string445;string446;string447;string448;string449;string450;string451;string452;string453;string454;string455;string456;string457;string458;string459;string460;string461;string462;string463;string464;string465;string466;string467;string468;string469;string470;string471;string472;string473;string474;string475;string476;string477;string478;string479;string480;string481;string482;string483;string484;string485;string486;string487;string488;string489;string490;string491;string492;string493;string494;string495;string496;string497;string498;string499;string500;string501;string502;string503;string504;string505;string506;string507;string508;string509;string510;string511;string512;string513;string514;string515;string516;string517;string518;string519;string520;string521;string522;string523;string524;string525;string526;string527;string528;string529;string530;string531;string532;string533;string534;string535;string536;string537;string538;string539;string540;string541;string542;string543;string544;string545;string546;string547;string548;string549;string550;string551;string552;string553;string554;string555;string556;string557;string558;string559;string560;string561;string562;string563;string564;string565;string566;string567;string568;string569;string570;string571;string572;string573;string574;string575;string576;string577;string578;string579;string580;string581;string582;string583;string584;string585;string586;string587;string588;string589;string590;string591;string592;string593;string594;string595;string596;string597;string598;string599;string600;string601;string602;string603;string604;string605;string606;string607;string608;string609;string610;string611;string612;string613;string614;string615;string616;string617;string618;string619;string620;string621;string622;string623;string624;string625;string626;string627;string628;string629;string630;string631;string632;string633;string634;string635;string636;string637;string638;string639;string640;string641;string642;string643;string644;string645;string646;string647;string648;string649;string650;string651;string652;string653;string654;string655;string656;string657;string658;string659;string660;string661;string662;string663;string664;string665;string666;string667;string668;string669;string670;string671;string672;string673;string674;string675;string676;string677;string678;string679;string680;string681;string682;string683;string684;string685;string686;string687;string688;string689;string690;string691;string692;string693;string694;string695;string696;string697;string698;string699;string700;string701;string702;string703;string704;string705;string706;string707;string708;string709;string710;string711;string712;string713;string714;string715;string716;string717;string718;string719;string720;string721;string722;string723;string724;string725;string726;string727;string728;string729;string730;string731;string732;string733;string734;string735;string736;string737;string738;string739;string740;string741;string742;string743;string744;string745;string746;string747;string748;string749;string750;string751;string752;string753;string754;string755;string756;string757;string758;string759;string760;string761;string762;string763;string764;string765;string766;string767;string768;string769;string770;string771;string772;string773;string774;string775;string776;string777;string778;string779;string780;string781;string782;string783;string784;string785;string786;string787;string788;string789;string790;string791;string792;string793;string794;string795;string796;string797;string798;string799;string800;string801;string802;string803;string804;string805;string806;string807;string808;string809;string810;string811;string812;string813;string814;string815;string816;string817;string818;string819;string820;string821;string822;string823;string824;string825;string826;string827;string828;string829;string830;string831;string832;string833;string834;string835;string836;string837;string838;string839;string840;string841;string842;string843;string844;string845;string846;string847;string848;string849;string850;string851;string852;string853;string854;string855;string856;string857;string858;string859;string860;string861;string862;string863;string864;string865;string866;string867;string868;string869;string870;string871;string872;string873;string874;string875;string876;string877;string878;string879;string880;string881;string882;string883;string884;string885;string886;string887;string888;string889;string890;string891;string892;string893;string894;string895;string896;string897;string898;string899;string900;string901;string902;string903;string904;string905;string906;string907;string908;string909;string910;string911;string912;string913;string914;string915;string916;string917;string918;string919;string920;string921;string922;string923;string924;string925;string926;string927;string928;string929;string930;string931;string932;string933;string934;string935;string936;string937;string938;string939;string940;string941;string942;string943;string944;string945;string946;string947;string948;string949;string950;string951;string952;string953;string954;string955;string956;string957;string958;string959;string960;string961;string962;string963;string964;string965;string966;string967;string968;string969;string970;string971;string972;string973;string974;string975;string976;string977;string978;string979;string980;string981;string982;string983;string984;string985;string986;string987;string988;string989;string990;string991;string992;string993;string994;string995;string996;string997;string998;string999 +start;string0;string1;string2;string3;string4;string5;string6;string7;string8;string9;string10;string11;string12;string13;string14;string15;string16;string17;string18;string19;string20;string21;string22;string23;string24;string25;string26;string27;string28;string29;string30;string31;string32;string33;string34;string35;string36;string37;string38;string39;string40;string41;string42;string43;string44;string45;string46;string47;string48;string49;string50;string51;string52;string53;string54;string55;string56;string57;string58;string59;string60;string61;string62;string63;string64;string65;string66;string67;string68;string69;string70;string71;string72;string73;string74;string75;string76;string77;string78;string79;string80;string81;string82;string83;string84;string85;string86;string87;string88;string89;string90;string91;string92;string93;string94;string95;string96;string97;string98;string99;string100;string101;string102;string103;string104;string105;string106;string107;string108;string109;string110;string111;string112;string113;string114;string115;string116;string117;string118;string119;string120;string121;string122;string123;string124;string125;string126;string127;string128;string129;string130;string131;string132;string133;string134;string135;string136;string137;string138;string139;string140;string141;string142;string143;string144;string145;string146;string147;string148;string149;string150;string151;string152;string153;string154;string155;string156;string157;string158;string159;string160;string161;string162;string163;string164;string165;string166;string167;string168;string169;string170;string171;string172;string173;string174;string175;string176;string177;string178;string179;string180;string181;string182;string183;string184;string185;string186;string187;string188;string189;string190;string191;string192;string193;string194;string195;string196;string197;string198;string199;string200;string201;string202;string203;string204;string205;string206;string207;string208;string209;string210;string211;string212;string213;string214;string215;string216;string217;string218;string219;string220;string221;string222;string223;string224;string225;string226;string227;string228;string229;string230;string231;string232;string233;string234;string235;string236;string237;string238;string239;string240;string241;string242;string243;string244;string245;string246;string247;string248;string249;string250;string251;string252;string253;string254;string255;string256;string257;string258;string259;string260;string261;string262;string263;string264;string265;string266;string267;string268;string269;string270;string271;string272;string273;string274;string275;string276;string277;string278;string279;string280;string281;string282;string283;string284;string285;string286;string287;string288;string289;string290;string291;string292;string293;string294;string295;string296;string297;string298;string299;string300;string301;string302;string303;string304;string305;string306;string307;string308;string309;string310;string311;string312;string313;string314;string315;string316;string317;string318;string319;string320;string321;string322;string323;string324;string325;string326;string327;string328;string329;string330;string331;string332;string333;string334;string335;string336;string337;string338;string339;string340;string341;string342;string343;string344;string345;string346;string347;string348;string349;string350;string351;string352;string353;string354;string355;string356;string357;string358;string359;string360;string361;string362;string363;string364;string365;string366;string367;string368;string369;string370;string371;string372;string373;string374;string375;string376;string377;string378;string379;string380;string381;string382;string383;string384;string385;string386;string387;string388;string389;string390;string391;string392;string393;string394;string395;string396;string397;string398;string399;string400;string401;string402;string403;string404;string405;string406;string407;string408;string409;string410;string411;string412;string413;string414;string415;string416;string417;string418;string419;string420;string421;string422;string423;string424;string425;string426;string427;string428;string429;string430;string431;string432;string433;string434;string435;string436;string437;string438;string439;string440;string441;string442;string443;string444;string445;string446;string447;string448;string449;string450;string451;string452;string453;string454;string455;string456;string457;string458;string459;string460;string461;string462;string463;string464;string465;string466;string467;string468;string469;string470;string471;string472;string473;string474;string475;string476;string477;string478;string479;string480;string481;string482;string483;string484;string485;string486;string487;string488;string489;string490;string491;string492;string493;string494;string495;string496;string497;string498;string499;string500;string501;string502;string503;string504;string505;string506;string507;string508;string509;string510;string511;string512;string513;string514;string515;string516;string517;string518;string519;string520;string521;string522;string523;string524;string525;string526;string527;string528;string529;string530;string531;string532;string533;string534;string535;string536;string537;string538;string539;string540;string541;string542;string543;string544;string545;string546;string547;string548;string549;string550;string551;string552;string553;string554;string555;string556;string557;string558;string559;string560;string561;string562;string563;string564;string565;string566;string567;string568;string569;string570;string571;string572;string573;string574;string575;string576;string577;string578;string579;string580;string581;string582;string583;string584;string585;string586;string587;string588;string589;string590;string591;string592;string593;string594;string595;string596;string597;string598;string599;string600;string601;string602;string603;string604;string605;string606;string607;string608;string609;string610;string611;string612;string613;string614;string615;string616;string617;string618;string619;string620;string621;string622;string623;string624;string625;string626;string627;string628;string629;string630;string631;string632;string633;string634;string635;string636;string637;string638;string639;string640;string641;string642;string643;string644;string645;string646;string647;string648;string649;string650;string651;string652;string653;string654;string655;string656;string657;string658;string659;string660;string661;string662;string663;string664;string665;string666;string667;string668;string669;string670;string671;string672;string673;string674;string675;string676;string677;string678;string679;string680;string681;string682;string683;string684;string685;string686;string687;string688;string689;string690;string691;string692;string693;string694;string695;string696;string697;string698;string699;string700;string701;string702;string703;string704;string705;string706;string707;string708;string709;string710;string711;string712;string713;string714;string715;string716;string717;string718;string719;string720;string721;string722;string723;string724;string725;string726;string727;string728;string729;string730;string731;string732;string733;string734;string735;string736;string737;string738;string739;string740;string741;string742;string743;string744;string745;string746;string747;string748;string749;string750;string751;string752;string753;string754;string755;string756;string757;string758;string759;string760;string761;string762;string763;string764;string765;string766;string767;string768;string769;string770;string771;string772;string773;string774;string775;string776;string777;string778;string779;string780;string781;string782;string783;string784;string785;string786;string787;string788;string789;string790;string791;string792;string793;string794;string795;string796;string797;string798;string799;string800;string801;string802;string803;string804;string805;string806;string807;string808;string809;string810;string811;string812;string813;string814;string815;string816;string817;string818;string819;string820;string821;string822;string823;string824;string825;string826;string827;string828;string829;string830;string831;string832;string833;string834;string835;string836;string837;string838;string839;string840;string841;string842;string843;string844;string845;string846;string847;string848;string849;string850;string851;string852;string853;string854;string855;string856;string857;string858;string859;string860;string861;string862;string863;string864;string865;string866;string867;string868;string869;string870;string871;string872;string873;string874;string875;string876;string877;string878;string879;string880;string881;string882;string883;string884;string885;string886;string887;string888;string889;string890;string891;string892;string893;string894;string895;string896;string897;string898;string899;string900;string901;string902;string903;string904;string905;string906;string907;string908;string909;string910;string911;string912;string913;string914;string915;string916;string917;string918;string919;string920;string921;string922;string923;string924;string925;string926;string927;string928;string929;string930;string931;string932;string933;string934;string935;string936;string937;string938;string939;string940;string941;string942;string943;string944;string945;string946;string947;string948;string949;string950;string951;string952;string953;string954;string955;string956;string957;string958;string959;string960;string961;string962;string963;string964;string965;string966;string967;string968;string969;string970;string971;string972;string973;string974;string975;string976;string977;string978;string979;string980;string981;string982;string983;string984;string985;string986;string987;string988;string989;string990;string991;string992;string993;string994;string995;string996;string997;string998;string9 +zbcd +axd +axxd +axxd +zzzz +zbcd +axd +axxd +axxd +zzzz +a Value = 1 2 3 4 5 +a Sub = 0 1 2 3 4 +b Value = a b c d e +b Sub = 0 1 2 3 4 +c Value = 10 20 40 80 +c Sub = 0 2 4 8 +<1> <2> <3> <4> <5> +<10> <20> <40> <80> +<> +<> +<> +<> +<'ab '\''cd'\'' ef'> +./new-exp10.sub: line 11: ${x@C}: bad substitution +<'ab'> <'cd ef'> <''> <'gh'> +<'ab' 'cd ef' '' 'gh'> +<'ab'> <'cd> <ef'> <''> <'gh'> +<'ab'> <'cd> <ef'> <''> <'gh'> +<'ab cd'> +<'4'> <'ab cd'> +<> +argv[1] = <host(2)[5.0]$ > +< +> +<' \t\n'> +< +> +<$' \t\n'> +declare -r x='ab '\''cd'\'' ef' +set -- 'ab' 'cd ef' '' 'gh' +declare -a A=([0]="ab" [1]="cd ef" [2]="" [3]="gh") +declare -a B=() +declare -A A=([two]="b c" [three]="" [four]="de" [one]="1" ) +r +a +A +ir +a b c d e +5 +a5b +i +declare -i foo +A +declare -A foo +abcxxxdef +abcÃ¥def +ḅć +Ã¥ +prependḅć +Ã¥append +prependÃ¥ +ḅćappend +Ã¥ +ḅć +ḅć +ḅć +Ã¥ +Ã¥ +Ã¥ +ḅć +Ã¥ +Ã¥ +ḅć +ḅć +argv[1] = </> +argv[1] = </> +./new-exp.tests: line 615: ABXD: parameter unset diff --git a/tests/new-exp.tests b/tests/new-exp.tests new file mode 100644 index 0000000..557d6b4 --- /dev/null +++ b/tests/new-exp.tests @@ -0,0 +1,615 @@ +if (( $UID == 0 )); then + echo "new-exp.tests: the test suite should not be run as root" >&2 +fi + +# must do this because posix mode causes process substitution to be disabled +# and flagged as a syntax error, which causes the shell to exit +set +o posix + +expect() +{ + echo expect "$@" +} + +HOME=/usr/homes/chet # to make the check against new-exp.right work +expect '<foo bar>' +recho "${undef-"foo bar"}" # should be foo bar +expect '<foo>' +recho "${und="foo"}" # should be foo + +expect "<$HOME>" +recho ${HOME-"}"} +expect "<$HOME>" +recho "${HOME-'}'}" +expect "<$HOME>" +recho "${HOME-"}"}" + +expect $0: 'HOME: }: syntax error: operand expected (error token is "}")' +recho "${HOME:`echo }`}" # should be a math error -- bad substring substitution + +expect unset +_ENV=oops +x=${_ENV[(_$-=0)+(_=1)-_${-%%*i*}]} +echo ${x:-unset} + +expect "<$HOME>" +recho ${HOME} +expect "<$HOME>" +recho ${HOME:-`echo }`} +expect "<$HOME>" +recho ${HOME:-`echo "}"`} +expect "<$HOME>" +recho "${HOME:-`echo "}"`}" +expect "<$HOME>" +recho "$(echo "${HOME}")" +expect "<$HOME>" +recho "$(echo "$(echo ${HOME})")" +expect "<$HOME>" +recho "$(echo "$(echo "${HOME}")")" + +P=*@* +expect '<*@>' +recho "${P%"*"}" # +expect '<*@>' +recho "${P%'*'}" # +expect '<@*>' +recho "${P#\*}" # should be @* + +expect '<)>' +recho "$(echo ")")" # should be ) +expect '<")">' +recho "$(echo "\")\"")" # should be ")" + +foo='abcd ' +expect '<-abcd> <->' +recho -${foo}- # should be -abcd - +expect '<-abcd> <->' +recho -${foo% *}- # should be -abcd - +expect '<-abcd->' +recho -${foo%% *}- # should be -abcd- + +foo=bar +expect '<bar foo>' +echo -n $foo' ' ; echo foo + +expect '<bar foo>' +echo -n $foo" " ; echo foo + +expect '<bar foo>' +echo -n "$foo " ; echo foo + +expect '<barfoo>' +echo -e "$foo\c " ; echo foo + +expect '<barfoo>' +echo -e $foo"\c " ; echo foo + +# make sure backslashes are preserved in front of characters that are not +# valid backslash escapes +expect '<\x>' +echo -e '\x' + +# substring tests +z=abcdefghijklmnop +expect '<abcd>' +recho ${z:0:4} + +expect '<efg> <nop>' +recho ${z:4:3} ${z:${#z}-3:3} + +expect '<efg> <nop>' +recho ${z:4:3} ${z: -3:3} + +expect '<hijklmnop>' +recho ${z:7:30} + +expect '<abcdefghijklmnop>' +recho ${z:0:100} + +expect '<abcdefghijklmnop>' +recho ${z:0:${#z}} + +set 'ab cd' 'ef' 'gh ij' 'kl mn' 'op' +expect '<ab cd> <ef>' +recho "${@:1:2}" + +expect '<gh ij> <kl mn>' +recho "${@:3:2}" + +expect '<gh ij> <kl mn> <op>' +recho "${@:3:4}" + +expect '<ab cd> <ef> <gh ij> <kl mn> <op>' +recho "${@:1:$#}" + +# code to ad-hoc parse arithmetic expressions in substring expansions was +# broken until post-2.04 +base=/home/chet/foo//bar +string1=$base/abcabcabc +x=1 j=4 + +expect '</home/chet/foo//bar/abcabcabc>' +recho ${string1:0} + +expect '<home/chet/foo//bar/abcabcabc>' +recho ${string1:1} + +expect '<home>' +recho ${string1:(j?1:0):j} + +expect '<home>' +recho ${string1:j?1:0:j} + +expect '<home>' +recho ${string1:(j?(x?1:0):0):j} + +expect '<home>' +recho ${string1:j?(x?1:0):0:j} + +unset base string1 x j + +# indirect variable references +expect '<abcdefghijklmnop>' +recho ${!9:-$z} + +ef=4 +expect '<4>' +recho ${!2} + +expect '<op>' +recho ${!#} + +set a b c d e +a= +expect '<abcdefghijklmnop>' +recho ${a:-$z} +expect '<abcdefghijklmnop>' +recho ${!1:-$z} + +expect nothing +recho ${a-$z} +expect nothing +recho ${!1-$z} + +set -- a 'b c' d +unset foo +foo=@ +expect '<a> <b> <c> <d>' +recho ${!foo} +expect '<a> <b c> <d>' +recho "${!foo}" + +set -u +expect $0: ABX: unbound variable +( recho ${ABX} ) +set +u + +expect $0: '$6: cannot assign in this way' +recho ${6="arg6"} + +v=abcde + +# sed-like variable substitution +expect '<xxcde>' +recho ${v/a[a-z]/xx} +expect '<axxde>' +recho ${v/a??/axx} +expect '<abxyz>' +recho ${v/c??/xyz} +expect '<abbcde>' +recho ${v/#a/ab} +expect '<abcde>' +recho ${v/#d/ab} +expect '<abcabe>' +recho ${v/d/ab} +expect '<abcdlast>' +recho ${v/%?/last} +expect '<abcde>' +recho ${v/%x/last} + +av=(abcd efgh ijkl mnop qrst uvwx) + +expect '<xxcd>' +recho ${av/??/xx} +expect '<abxx>' +recho ${av/%??/xx} +expect '<xxgh>' +recho ${av[1]/??/xx} +expect '<efgh>' +recho ${av[1]/%ab/xx} +expect '<xxfgh>' +recho ${av[1]/#?/xx} +expect '<zagh>' +recho ${av[1]/??/za} +expect '<zaza>' +recho ${av[1]//??/za} +expect '<zagh>' +recho ${av[1]/#??/za} +expect '<efza>' +recho ${av[1]/%??/za} + +expect '<yyy> <yyy> <yyy> <yyy> <yyy> <yyy>' +recho ${av[@]/*/yyy} +expect '<yyy> <yyy> <yyy> <yyy> <yyy> <yyy>' +recho ${av[@]/#*/yyy} +expect '<yyy> <yyy> <yyy> <yyy> <yyy> <yyy>' +recho ${av[@]/%*/yyy} +expect '<yyy> <efgh> <ijkl> <mnop> <qrst> <uvwx>' +recho ${av[@]/a*/yyy} +expect '<abxx> <efxx> <ijxx> <mnxx> <qrxx> <uvxx>' +recho ${av[@]/%??/xx} + +set abcd efgh ijkl mnop qrst uvwx + +expect '<xxcd>' +recho ${1/??/xx} +expect '<xxcd> <xxgh> <xxkl> <xxop> <xxst> <xxwx>' +recho ${@/??/xx} +expect '<xxcd> <xxgh> <xxkl> <xxop> <xxst> <xxwx>' +recho ${@/%??/xx} +expect '<zaza>' +recho ${3//??/za} +expect '<efza>' +recho ${3/%??/za} +expect '<zaza> <zaza> <zaza> <zaza> <zaza> <zaza>' +recho ${@//??/za} +expect '<zacd> <zagh> <zakl> <zaop> <zast> <zawx>' +recho ${@/#??/za} +expect '<yyy> <yyy> <yyy> <yyy> <yyy> <yyy>' +recho ${@//*/yyy} +expect '<yyy> <efgh> <ijkl> <mnop> <qrst> <uvwx>' +recho ${@//a*/yyy} +expect '<abcd> <efgh> <ijkl> <mnop> <qrst> <uvwyyy>' +recho ${@/%x*/yyy} + +expect a newline +echo $abmcde + +# sneaky way to replace a newline in a variable value with something else +AVAR=$'This\nstring\nhas\nmultiple\nlines.' +echo "${AVAR}" + +eval BVAR=\"\${AVAR//$'\n'/-}\" +echo "$BVAR" + +unset AVAR BVAR + +# run process substitution tests in a subshell so that syntax errors +# caused by a shell not implementing process substitution (e.g., one +# built on a NeXT) will not cause the whole test to exit prematurely +${THIS_SH} ./new-exp1.sub + +# run the tests of $(<filename) in a subshell to avoid cluttering up +# this script +${THIS_SH} ./new-exp2.sub + +expect '<6>' +recho ${#:-foo} +expect $0: '${#:}: bad substitution' +echo ${#:} + +expect "<'>" +recho "'" +expect '<">' +recho '"' +expect '<"hello">' +recho "\"hello\"" + +shift $# +unset foo +z=abcdef +z1='abc def' + +expect '<>' +recho ${foo:-""} +expect nothing +recho ${foo:-"$@"} +expect '<>' +recho "${foo:-$@}" + +# unset var +expect '<>' +recho ${foo:-"$zbcd"} +expect nothing +recho ${foo:-$zbcd} + +# set var +expect '<abcdef>' +recho ${foo:-"$z"} +expect '<abc def>' +recho ${foo:-"$z1"} + +expect '<abcdef>' +recho ${foo:-$z} +expect '<abc> <def>' +recho ${foo:-$z1} + +expect '<abcdef>' +recho "${foo:-$z}" +expect '<abc def>' +recho "${foo:-$z1}" + +expect '<abcdef>' +recho "${foo:-"$z"}" +# this disagrees with sh and ksh, but I think it is right according +# to posix.2. +expect '<abc def>' +recho "${foo:-"$z1"}" + +set ab cd ef gh +expect '<ab> <cd> <ef> <gh>' +recho ${foo:-"$@"} +expect '<ab> <cd> <ef> <gh>' +recho "${foo:-$@}" +expect '<ab> <cd> <ef> <gh>' +recho "${foo:-"$@"}" + +shift ${#} +expect nothing +recho $xxx"$@" +expect nothing +recho ${foo:-$xxx"$@"} +expect '<>' +recho "${foo:-$xxx$@}" +expect '<>' +recho "${foo:-$xxx"$@"}" + +expect nothing +recho $xxx"$@" +expect nothing +recho "$xxx$@" +expect nothing +recho "$@"$xxx + +expect '<>' +recho $xxx"" +expect '<>' +recho $xxx'' +expect '<>' +recho ''$xxx +expect '<>' +recho ""$xxx + +AB='abcdefghijklmnopqrstuvwxyz' + +recho ${AB:7:15} +recho ${AB:15:7} + +recho ${AB:20} + +recho ${AB:0} +recho ${AB:0:20} + +recho ${AB:10:7} +recho ${AB:10:3+4} +recho ${AB:20/2:3+4} + +set 1 2 3 4 5 6 +recho \""${*:2:2}"\" + +IFS=: +recho \""${*:2:2}"\" + +IFS=$' \t\n' + +z=123456 + +recho \""${z:2:2}"\" +recho \""${z:2}"\" +recho \""${z:2:4}"\" +recho \""${z:2:6}"\" + +set $'\1' $'\2' $'\177' + +recho $* +recho $@ + +recho ${*} +recho ${@} + +xx=one/two/two +recho ${xx%/*} +recho ${xx/\/two} + +yy=oneonetwo +recho ${yy//one} +recho ${yy/\/one} + +xx=oneonetwo + +recho ${xx/one} +recho ${xx//one} +recho ${xx/\/one} + +# out-of-range substrings +var=abc +c=${var:3} +expect nothing +recho $c +c=${var:4} +expect nothing +recho $c +# as of bash-4.2, negative LENGTH means offset from the end +c=${var:0:-2} +expect '<a>' +recho $c + +var=abcdefghi +c=${var:3:12} +recho $c +c=${var:4:20} +recho $c + +# make sure null patterns work +xxx=endocrine +yyy=n +unset zzz + +recho ${xxx/$yyy/*} +recho ${xxx//$yyy/*} + +recho ${xxx/$zzz/*} +recho ${xxx//$zzz/*} + +recho ${xxx//%${zzz}/} +recho ${xxx//%${zzz}} +recho ${xxx//#${zzz}/} +recho ${xxx//#${zzz}} + +# make sure null strings are replaced appropriately +unset var +var= +echo "${var/#/x}" +echo "${var/*/x}" +echo "${var//*/x}" + +var=abc +echo "${var/#/x}" +echo "${var/*/x}" +echo "${var//*/x}" +unset var + +# another case that caused a core dump in bash-2.0 +XPATH=/usr/bin:/bin:/usr/local/bin:/usr/gnu/bin::/usr/bin/X11:/sbin:/usr/sbin + +recho ${XPATH//:/ } + +xx=(ar as at au av aw ax ay az) + +recho ${xx[@]/a/} +recho ${xx[@]//a/} + +recho ${xx[*]/a/} +recho ${xx[*]//a/} + +recho ${xx[@]%?} +recho ${xx[*]%?} + +recho ${xx[@]#?} +recho ${xx[*]#?} + +set -- ar as at au av aw ax ay az + +recho ${@/a/} +recho ${@//a/} + +recho ${*/a/} +recho ${*//a/} + +recho ${@%?} +recho ${*%?} + +recho ${@#?} +recho ${*#?} + +shift ${#} +set -u +( recho $9 ; echo after 1) +( recho ${9} ; echo after 2) +( recho $UNSET ; echo after 3) +( recho ${UNSET} ; echo after 4) +( recho "$UNSET" ; echo after 5) +( recho "${UNSET}" ; echo after 6) +( recho "${#UNSET}" ; echo after 7) +set +u + +RECEIVED="12345" +recho "${RECEIVED:$((${#RECEIVED}-1)):1}" +RECEIVED="12345#" +recho "${RECEIVED:$((${#RECEIVED}-1)):1}" +RECEIVED="#" +recho "${RECEIVED:$((${#RECEIVED}-1)):1}" +RECEIVED="" +recho "${RECEIVED:$((${#RECEIVED}-1)):1}" + +# tests of new prefix expansion ${!prefix*} +${THIS_SH} ./new-exp3.sub + +# bug with indirect expansion through bash-2.05b +${THIS_SH} ./new-exp4.sub + +# these caused errors and core dumps in versions before bash-2.04 +c="" +echo ${c//${$(($#-1))}/x/} + +set a b c d e f g +recho "$@" + +set -- ${@:1:$(($# - 2))} +recho "$@" + +set a b +recho ${@:1:$(($# - 2))} + +recho ${@:1:0} +recho ${@:1:1} +recho ${@:1:2} + +recho "${*:1:0}" + +# this is an error -- negative expression +set a +recho ${@:1:$(($# - 2))} + +XPATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:.:/sbin:/usr/sbin +set $( IFS=: ; echo $XPATH ) + +recho ${@##*/} +recho ${@%%[!/]*} + +recho ${@#/*} +recho ${@%*/} + +set /full/path/to/x16 /another/full/path + +recho ${1%/*} +recho ${1%%[!/]*} +recho ${1#*/} +recho ${1##*/} + +${THIS_SH} ./new-exp5.sub + +unset var +var=blah + +# these had better agree +echo ${var[@]:3} +echo ${var:3} +echo ${var[@]/#/--} +echo ${var/#/--} +echo ${var[@]##?} +echo ${var##?} + +unset var +var=(abcde abcfg abchi) + +# problems with anchoring pattern replacements +echo ${var[*]//#abc/foo} +echo ${var[*]/#abc/foo} +unset var + +${THIS_SH} ./new-exp6.sub + +${THIS_SH} ./new-exp7.sub + +${THIS_SH} ./new-exp8.sub + +# tests to check whether things like indirect expansion of a variable whose +# value is 'anothervar[@]' stop working +${THIS_SH} ./new-exp9.sub + +# new parameter transformation `@' expansion operator +${THIS_SH} ./new-exp10.sub + +# parameter substring replacement and removal operators with multibyte chars +${THIS_SH} ./new-exp11.sub + +# problems with stray CTLNUL in bash-4.0-alpha +unset a +a=/a +recho "/${a%/*}" +recho "/${a///a/}" + +# this must be last! +expect $0: 'ABXD: parameter unset' +recho ${ABXD:?"parameter unset"} diff --git a/tests/new-exp1.sub b/tests/new-exp1.sub new file mode 100644 index 0000000..2b621fc --- /dev/null +++ b/tests/new-exp1.sub @@ -0,0 +1,16 @@ +FN=${TMPDIR}/bashtest-$$ +expect() +{ + echo expect "$@" +} + +expect this is a test of proc subst +cat <(echo this is a test of proc subst) +echo this is test 2 > $FN +expect this is test 2 +cat <(cat $FN) +rm -f $FN + +foo= +expect a +cat ${foo:-<(echo a)} diff --git a/tests/new-exp10.sub b/tests/new-exp10.sub new file mode 100644 index 0000000..9e89a70 --- /dev/null +++ b/tests/new-exp10.sub @@ -0,0 +1,100 @@ +# new framework for parameter transformations, post bash-4.3 + +printf "<%s>" "${x@Q}" ; echo +printf "<%s>" "${x@E}" ; echo +printf "<%s>" "${x@P}" ; echo +printf "<%s>" "${x@A}" ; echo + +x="ab 'cd' ef" +printf "<%s> " "${x@Q}" ; echo + +printf "<%s>" "${x@C}" + +# if unquoted, normal word splitting happens +set -- ab 'cd ef' '' gh +printf "<%s> " "${@@Q}" ; echo +printf "<%s> " "${*@Q}" ; echo +printf "<%s> " ${@@Q} ; echo +printf "<%s> " ${*@Q} ; echo + +y[0]=4 +y[1]='ab cd' + +printf "<%s> " "${y[1]@Q}" ; echo +printf "<%s> " "${y[@]@Q}" ; echo # mksh doesn't like @ or * or arrays subscripted with them + +printf "<%s> " "${z@Q}" ; echo # empty string? + +recho ${z@Q} # this disappears + +# +HOST=host +SHELL_LEVEL=2 +NPS1='\[\]${HOST}($SHELL_LEVEL)[\v]\$ ' + +recho "${NPS1@P}" + +# +D=' \t\n' +printf "<%s>" "${D@E}" ; echo +printf "<%s>" "${D@Q}" ; echo + +E=$' \t\n' +printf "<%s>" "${E@E}" ; echo +printf "<%s>" "${E@Q}" ; echo + +declare x +declare -r x="ab 'cd' ef" +printf "%s" "${x@A}" ; echo + +set -- ab 'cd ef' '' gh +printf "%s " "${@@A}" ; echo + +A=( "$@" ) +printf "%s " "${A[@]@A}" ; echo +B=() +printf "%s " "${B[@]@A}" ; echo + +unset A +declare -A A +A=( [one]=1 [two]='b c' [three]='' [four]=de ) +printf "%s " "${A[@]@A}" ; echo + +unset X +declare X +declare -r X="ab 'cd' ef" +printf "%s" "${X@a}" ; echo + +set -- 1 2 3 4 + +unset A +A=( "$@" ) +printf "%s " "${A@a}" ; echo + +unset A +declare -A A +A=( [one]=1 [two]='b c' [three]='' [four]=de ) +printf "%s " "${A@a}" ; echo + +declare -ir Y=0 +printf "%s" "${Y@a}" ; echo + +# make sure we still handle ${#@} and ${@} as posix requires +set -- a b c d e +echo ${@} +echo ${#@} +echo a${#@}b + +# new feature in bash-5.0: display attributes of even unset variables +unset -v foo + +declare -i foo +echo ${foo@a} + +declare -p foo + +unset foo +declare -A foo +echo ${foo@a} + +declare -p foo diff --git a/tests/new-exp11.sub b/tests/new-exp11.sub new file mode 100644 index 0000000..da6b4e1 --- /dev/null +++ b/tests/new-exp11.sub @@ -0,0 +1,46 @@ +# pattern matching and replacement operators with multibyte characters + +LANG=en_US.UTF-8 + +s1='abcÃ¥def' +s2='Ã¥' +s3='ḅć' + +s23=${s2}${s3} + +echo ${s1/$s2/xxx} +echo ${s1/$s3/xxx} + +echo ${s23/#$s2/} +echo ${s23/%$s3/} + +echo ${s23/#$s2/prepend} +echo ${s23/%$s3/append} + +echo ${s2/#/prepend} +echo ${s3/%/append} + +echo ${s2/#/} +echo ${s3/%/} + +recho ${s2/$s2/} +recho ${s3/$s3/} + +# posix pattern replacements + +echo ${s23##$s2} +echo ${s23#$s2} + +echo ${s23%%$s3} +echo ${s23%$s3} + +# fail + +echo ${s2/#ab/xx} +echo ${s3/%ab/xx} + +echo ${s2#ab} +echo ${s2##ab} + +echo ${s3%ab} +echo ${s3%%ab} diff --git a/tests/new-exp2.sub b/tests/new-exp2.sub new file mode 100644 index 0000000..ea52b3c --- /dev/null +++ b/tests/new-exp2.sub @@ -0,0 +1,49 @@ +export LC_ALL=C +export LANG=C + +# test out the new $(< filename) code +# it should be exactly equivalent to $(cat filename) + +FILENAME=$TMPDIR/bashtmp.x$$ + +trap 'rm -f $FILENAME' 0 + +cat >$FILENAME << EOF +line 1 +line 2 +line 3 +EOF + +LINES1=$(cat $FILENAME) +LINES2=$(< $FILENAME) + +if [[ $LINES1 != $LINES2 ]]; then + echo 'whoops: $(< filename) failed' +fi + +LINES2=$(< $TMPDIR/bashtmp.x*) +if [[ $LINES1 != $LINES2 ]]; then + echo 'whoops: $(< filename) with glob expansion failed' +fi + +# but the glob expansion in the redirection should fail in posix mode +set -o posix +exec 3>&2 +exec 2>/dev/null +LINES2=$(< $TMPDIR/bashtmp.x*) +exec 2>&3 +if [[ $LINES2 -gt 0 ]]; then + echo "whoops: redirection glob expansion should be disabled in posix mode" >&2 +fi +set +o posix + +# now see what happens when we try it with a non-existant file +rm -f /tmp/redir-notthere +LINES3=$(< /tmp/redir-notthere) +echo $? + +# These were bugs through bash-4.2 +{ : "$({xxxxxxxxxxxxxxxxxxxx}</dev/stdin)"; } <<<'hi' +echo ${xxxxxxxxxxxxxxxxxxxx} + +{ echo "$(1111111111111111111111</dev/stdin)"; } <<<'hi' diff --git a/tests/new-exp3.sub b/tests/new-exp3.sub new file mode 100644 index 0000000..2a766eb --- /dev/null +++ b/tests/new-exp3.sub @@ -0,0 +1,30 @@ +: +# Set up some dummy variables beginning with _Q +_QUANTITY= +_QUOTA= +_QUOTE= +_QUILL= +_QUEST= +_QUART= + +recho ${!_Q*} +recho ${!_Q@} # compatibility + +IFS="-$IFS" + +recho ${!_Q*} +recho "${!_Q*}" + +recho ${!_Q@} +recho "${!_Q@}" + +recho ${!_Y*} + +recho "${!_Q* }" + +IFS=$' \t\n' + +set a b c d e f g h i j k l m n o p +recho ${!1*} + +recho ${!@*} diff --git a/tests/new-exp4.sub b/tests/new-exp4.sub new file mode 100644 index 0000000..45439a0 --- /dev/null +++ b/tests/new-exp4.sub @@ -0,0 +1,31 @@ +#!/bin/bash + +arrayA=("A" "B" "C") + +arrayB=( ${arrayA[*]} ) +echo "Case01---${#arrayB[*]}---${arrayB[0]}:${arrayB[1]}:${arrayB[2]}---" + +arrayB=( "${arrayA[*]}" ) +echo "Case02---${#arrayB[*]}---${arrayB[0]}:${arrayB[1]}:${arrayB[2]}---" + +arrayB=( ${arrayA[@]} ) +echo "Case03---${#arrayB[@]}---${arrayB[0]}:${arrayB[1]}:${arrayB[2]}---" + +arrayB=( "${arrayA[@]}" ) +echo "Case04---${#arrayB[@]}---${arrayB[0]}:${arrayB[1]}:${arrayB[2]}---" + +xx="arrayA[*]" + +arrayB=( ${!xx} ) +echo "Case05---${#arrayB[*]}---${arrayB[0]}:${arrayB[1]}:${arrayB[2]}---" + +arrayB=( "${!xx}" ) +echo "Case06---${#arrayB[*]}---${arrayB[0]}:${arrayB[1]}:${arrayB[2]}---" + +xx="arrayA[@]" + +arrayB=( ${!xx} ) +echo "Case07---${#arrayB[@]}---${arrayB[0]}:${arrayB[1]}:${arrayB[2]}---" + +arrayB=( "${!xx}" ) +echo "Case08---${#arrayB[@]}---${arrayB[0]}:${arrayB[1]}:${arrayB[2]}---" diff --git a/tests/new-exp5.sub b/tests/new-exp5.sub new file mode 100644 index 0000000..0ee86e9 --- /dev/null +++ b/tests/new-exp5.sub @@ -0,0 +1,40 @@ +x=(one two) +echo ${x[@]:1} +echo ${x[@]:0:1} + +x=(one) +echo ${x[0]:1} +echo ${x[0]:0} +echo ${x[@]:1} +echo ${x[@]:0} + +echo ${x[@]: -1} +echo ${x[@]: ${#x[@]}-1} + +x=(0 1 2 3 4 5 6 7 8 9) +echo ${x[@]:1} + +echo ${x[@]: -1} +echo ${x[@]: ${#x[@]}-1} + +set -- ${x[@]} + +echo $1 +echo ${@: -1} +echo ${@: $#-1} + +a=0123456789 + +echo ${a:1} +echo ${a: -1} +echo ${a: ${#a}-1} + +# problem with bash through 3.2.33 +oIFS="$IFS" +IFS=$'\n' +a=(A B C D) +b=("${a[@]}") +echo "${#b[@]}", "${b[@]}" # 4, A B C D -- OK +b=("${a[@]:2}") +echo "${#b[@]}", "${b[@]}" # 1, C D -- bug, should be 2, C D +IFS="$oIFS" diff --git a/tests/new-exp6.sub b/tests/new-exp6.sub new file mode 100644 index 0000000..532ec1a --- /dev/null +++ b/tests/new-exp6.sub @@ -0,0 +1,29 @@ +# quoted null problems in versions of bash prior to 3.2 + +str='12' +snul=$'\177' + +recho "${str:2}" +recho "+${str:2}" +recho "+${snul:0:1}" +recho "+""${str:2}" + +recho "${str/?/$snul}" +recho ${str/?/$snul} + +recho "${snul/x/y}" +recho ${snul/x/y} + +recho "${snul/$snul/}" +recho "${str/$str/}" + +recho "${snul##$snul}" +recho "${str##$str}" +recho "${str##$nul}" + +A="" +B="${A:0}" + +recho "$B" +recho "${A:0}" +recho "/tmp/test/TEST${A:0}" diff --git a/tests/new-exp7.sub b/tests/new-exp7.sub new file mode 100644 index 0000000..970475c --- /dev/null +++ b/tests/new-exp7.sub @@ -0,0 +1,13 @@ +foo() +{ + echo < <(cat x1) +} + +type foo + +declare -f foo + +echo $(declare -f foo | sed 's:foo:bar:') +eval "$(declare -f foo | sed 's:foo:bar:')" + +type bar diff --git a/tests/new-exp8.sub b/tests/new-exp8.sub new file mode 100644 index 0000000..e047abc --- /dev/null +++ b/tests/new-exp8.sub @@ -0,0 +1,116 @@ +pat1='str' +pat2='[^;]' +pat3='[[:alnum:]_]' +pat4='[[:alnum:]][[fu]b' +pat5='?tr' +pat6='?tr\' +pat7='[[:alnum:]]_' +pat8='*tr' + +declare z="start" +declare NUM=1000 + +#---------------------------------- +# create a long string with ';' +#---------------------------------- +for ((i=0; i<$NUM; i++)); do + z="$z;string$i" +done + +#z="$z;string;foo" + +#------------------------------ +# delete everything except ';' +#------------------------------ + +# try different patterns here +x="${z//$pat1}" +echo $x +x="${z//$pat2}" +echo $x +x="${z//$pat3}" +echo $x +x="${z//$pat4}" +echo $x +x="${z//$pat5}" +echo $x +x="${z//$pat6}" +echo $x +x="${z//$pat7}" +echo $x +x="${z//$pat8}" +echo $x + + +declare z="start" +declare NUM=1000 + +#---------------------------------- +# create a long string with ';' +#---------------------------------- +for ((i=0; i<$NUM; i++)); do + z="$z;string$i" +done + +#z="$z;string;foo" + +#------------------------------ +# delete everything except ';' +#------------------------------ + +# try different patterns here +x="${z//[^;]}" +echo $x +x="${z/#[^;][^;]}" +echo $x +x="${z/%[^;][^;]}" +echo $x + +export LANG=C LC_ALL=C LC_CTYPE=C + +# try different patterns here +x="${z//$pat1}" +echo $x +x="${z//$pat2}" +echo $x +x="${z//$pat3}" +echo $x +x="${z//$pat4}" +echo $x +x="${z//$pat5}" +echo $x +x="${z//$pat6}" +echo $x +x="${z//$pat7}" +echo $x +x="${z//$pat8}" +echo $x + +# try different patterns here +x="${z//[^;]}" +echo $x +x="${z/#[^;][^;]}" +echo $x +x="${z/%[^;][^;]}" +echo $x + +# post-bash-4.3 changes to make pattern replacement honor nocasematch variable +unset string +string=abcd + +shopt -s nocasematch + +echo ${string//A/z} +echo ${string//BC/x} +echo ${string//[BC]/x} +echo ${string//[bC]/x} +echo ${string//?/z} + +LC_ALL=C +echo ${string//A/z} +echo ${string//BC/x} +echo ${string//[BC]/x} +echo ${string//[bC]/x} +echo ${string//?/z} + + diff --git a/tests/new-exp9.sub b/tests/new-exp9.sub new file mode 100644 index 0000000..c9d133c --- /dev/null +++ b/tests/new-exp9.sub @@ -0,0 +1,31 @@ +indirarray() +{ + local intermediary + local sub + + intermediary="${1}[@]" + local -a leftValue=("${!intermediary}") + + local -a leftSub + eval leftSub=(\"\${!${1}[@]}\") + + echo "$1" Value = ${leftValue[@]} + echo "$1" Sub = ${leftSub[@]} +} + +a=(1 2 3 4 5) +b=(a b c d e) + +c=([0]=10 [2]=20 [4]=40 [8]=80) + +indirarray a +indirarray b +indirarray c + +ref=a +tmp="$ref[@]" +printf "<%s> " "${!tmp}"; echo # Iterate whole array. + +ref=c +tmp="$ref[@]" +printf "<%s> " "${!tmp}"; echo # Iterate whole array. diff --git a/tests/nquote.right b/tests/nquote.right new file mode 100644 index 0000000..e3ae555 --- /dev/null +++ b/tests/nquote.right @@ -0,0 +1,64 @@ +argv[1] = <^J^J^J> +argv[1] = <++^J++> +argv[1] = <> +argv[1] = <^J^I > +argv[1] = <abc> +argv[1] = <^M^[^Gabc> +argv[1] = <hello,> +argv[2] = <world> +argv[1] = <hello, world> +argv[1] = <> +argv[1] = <$hello, world> +argv[1] = <hello, $world> +argv[1] = <hello, "world"> +argv[1] = <hello, $"world"> +argv[1] = <hello, $"world"> +argv[1] = <$hello, chet> +argv[1] = <hello, chet> +ok +'abcd' +'abcd' +\'abcd\' +\'abcd\' +argv[1] = <A\CB> +argv[1] = <A\CB> +argv[1] = <ab$cde> +A\CB +A\CB +A\CB +argv[1] = <hello, $"world"> +argv[1] = <hello, \$"world"> +argv[1] = <hello, $"world"> +argv[1] = <hello, $world> +1 +1 +;foo +argv[1] = <^I> +argv[1] = <'A^IB'> +hello' world +hello world! +hello' world! +' | ' +' | ' +x | x +x | x +' | ' +' | ' +' | ' +' | ' +' | ' +' | ' +x | x +' +$'\'' +' +'abcd' +$'\'abcd\'' +' +1 +argv[1] = <^?> +0000000 del nl +0000002 +0000000 esc fs gs rs us del nl +0000007 +\q diff --git a/tests/nquote.tests b/tests/nquote.tests new file mode 100644 index 0000000..80d3cb4 --- /dev/null +++ b/tests/nquote.tests @@ -0,0 +1,120 @@ +expect() +{ + echo expect "$@" +} + +expect '<^J^J^J>' +recho $'\n\n\n' + +expect '<++^J++>' +f=$'\n' +recho "++$f++" +unset f + +z1=$'' +expect '<>' +recho "$z1" + +ZIFS=$'\n'$'\t'$' ' + +expect '<^J^I >' +recho "$ZIFS" + +expect '<abc>' +recho $'abc' + +expect '<^M^[^Gabc>' +recho $'\r\e\aabc' + +D=$"hello"," "$"world" + +expect '<hello,> <world>' +recho $D + +expect '<hello, world>' +recho "$D" + +D=$"" +expect '<>' +recho "$D" + +world=chet + +expect '<$hello, world>' +recho \$"hello, world" + +expect '<hello, $world>' +recho $"hello, \$world" + +expect '<hello, "world">' +recho $"hello, \"world\"" + +expect '<hello, $"world">' +recho $"hello"', $"world"' + +expect '<hello, $"world">' +recho $'hello, $"world"' + +expect '<$hello, chet>' +recho \$"hello, $world" + +expect '<hello, chet>' +recho $"hello, $world" + +z=$'\v\f\a\b' +case "$z" in +$'\v\f\a\b') echo ok;; +*) echo bad;; +esac + +# Dave Korn says this should be allowed and echo 'abcd' +echo $'\'abcd\'' + +# printf translates \' to ' ... +printf "\'abcd\'\n" + +# but echo -e doesn't +echo -e "\'abcd\'" +echo -e "\\'abcd\\'" + +# and what do we do about unrecognized escape sequences? + +shopt -s xpg_echo + +recho $'A\CB' + +recho "A\CB" + +cde=c +recho $'ab$cde' + +printf "%b\n" 'A\CB' +printf 'A\CB\n' + +echo 'A\CB' + +world=chet + +recho $'hello, $"world"' +recho $'hello, \$"world"' +recho $'hello, $\"world"' + +recho "hello, $"world"" + +# ansi quoting inside double-quoted command subst - bash-3.1 bug +echo $(set -- $'a b'; echo $#) +echo "$(set -- $'a b'; echo $#)" + +echo "$(echo $';foo')" + +args () +{ + for a in "$@";do echo "'$a'";done +} +unset mytab +recho "${mytab:-$'\t'}" +recho "$( args $'A\tB' )" + +${THIS_SH} ./nquote1.sub +${THIS_SH} ./nquote2.sub +${THIS_SH} ./nquote3.sub diff --git a/tests/nquote1.right b/tests/nquote1.right new file mode 100644 index 0000000..45389ef --- /dev/null +++ b/tests/nquote1.right @@ -0,0 +1,131 @@ +argv[1] = <a> +argv[2] = <a^Ab> +argv[3] = <3> +argv[1] = <1> +argv[2] = <a^Ab> +argv[3] = <3> +argv[1] = <b> +argv[2] = <a^Ab> +argv[3] = <3> +argv[1] = <c> +argv[2] = <a^Ab> +argv[3] = <3> +argv[1] = <d> +argv[2] = <a^Ab> +argv[3] = <3> +argv[1] = <a> +argv[2] = <a^Ab> +argv[3] = <3> +argv[1] = <1> +argv[2] = <a^Ab> +argv[3] = <3> +argv[1] = <b> +argv[2] = <a^Ab> +argv[3] = <3> +argv[1] = <c> +argv[2] = <a^Ab> +argv[3] = <3> +argv[1] = <d> +argv[2] = <a^Ab> +argv[3] = <3> +argv[1] = <a> +argv[2] = <a^Ab> +argv[3] = <3> +argv[1] = <1> +argv[2] = <a^Ab> +argv[3] = <3> +argv[1] = <b> +argv[2] = <a^Ab> +argv[3] = <3> +argv[1] = <c> +argv[2] = <a^Ab> +argv[3] = <3> +argv[1] = <d> +argv[2] = <a^Ab> +argv[3] = <3> +argv[1] = <a> +argv[2] = <a^Ab> +argv[3] = <3> +argv[1] = <1> +argv[2] = <a^Ab> +argv[3] = <3> +argv[1] = <b> +argv[2] = <a^Ab> +argv[3] = <3> +argv[1] = <c> +argv[2] = <a^Ab> +argv[3] = <3> +argv[1] = <d> +argv[2] = <a^Ab> +argv[3] = <3> +argv[1] = <e1> +argv[2] = <v^A^A> +argv[1] = <e2> +argv[2] = <v^A^A> +argv[1] = <e3> +argv[2] = <v^A^A> +argv[1] = <e4> +argv[2] = <v^A^A> +argv[1] = <a1> +argv[2] = <uv^A^A> +argv[1] = <a2> +argv[2] = <uv^A^A> +argv[1] = <a3> +argv[2] = <uv^A^Awx> +argv[3] = <uv^A^Awx> +argv[1] = <a4> +argv[2] = <uv^A^Awx> +argv[3] = <uv^A^Awx> +argv[1] = <p1> +argv[2] = <uv^A^Awx> +argv[3] = <uv^A^Awx> +argv[1] = <p2> +argv[2] = <uv^A^Awx> +argv[3] = <uv^A^Awx> +argv[1] = <p1> +argv[2] = <uv^A^Awx> +argv[3] = <uv^A^Awx> +argv[1] = <p2> +argv[2] = <uv^A^Awx uv^A^Awx> +argv[1] = <uv^A^Awx> +argv[1] = <uv^A^Awx> +argv[1] = <uv^A^Awx> +^A +^A +^B +argv[1] = <f1> +argv[2] = <v^Aw> +argv[1] = <f2> +argv[2] = <v^Aw> +argv[1] = <a1> +argv[2] = <uv^Aw> +argv[1] = <a2> +argv[2] = <uv^Aw> +argv[1] = <a3> +argv[2] = <uv^Aw> +argv[1] = <a4> +argv[2] = <uv^Aw> +argv[1] = <e1> +argv[2] = <uv^Aw> +argv[1] = <e2> +argv[2] = <uv^Aw> +argv[1] = <d1> +argv[2] = <^Aw> +argv[1] = <d2> +argv[2] = <^Aw> +argv[1] = <@1> +argv[2] = <uv^Aw^Axy> +argv[3] = <uv^Aw^Axy> +argv[1] = <@2> +argv[2] = <uv^Aw^Axy> +argv[3] = <uv^Aw^Axy> +argv[1] = <aa1> +argv[2] = <uv^A^A> +argv[1] = <aa2> +argv[2] = <uv^A^A> +argv[1] = <aa3> +argv[2] = <uv^A^Awx> +argv[3] = <uv^A^Awx> +argv[1] = <aa4> +argv[2] = <uv^A^Awx> +argv[3] = <uv^A^Awx> diff --git a/tests/nquote1.sub b/tests/nquote1.sub new file mode 100644 index 0000000..b3bc0db --- /dev/null +++ b/tests/nquote1.sub @@ -0,0 +1,6 @@ +set -o history +set -H + +echo $'hello\' world' +echo $'hello world!' +echo $'hello\' world!' diff --git a/tests/nquote1.tests b/tests/nquote1.tests new file mode 100644 index 0000000..f47ab54 --- /dev/null +++ b/tests/nquote1.tests @@ -0,0 +1,106 @@ +a=$'a\001b' + +set $a + +b=$a +c=$1 +d="$1" + +e=$'uv\001\001wx' + +recho a $a ${#a} +recho 1 $1 ${#1} +recho b $b ${#b} +recho c $c ${#c} +recho d $d ${#d} + +recho a ${a} ${#a} +recho 1 ${1} ${#1} +recho b ${b} ${#b} +recho c ${c} ${#c} +recho d ${d} ${#d} + +recho a "$a" ${#a} +recho 1 "$1" ${#1} +recho b "$b" ${#b} +recho c "$c" ${#c} +recho d "$d" ${#d} + +recho a "${a}" ${#a} +recho 1 "${1}" ${#1} +recho b "${b}" ${#b} +recho c "${c}" ${#c} +recho d "${d}" ${#d} + +set $e + +recho e1 ${e:1:3} +recho e2 "${e:1:3}" +recho e3 ${1:1:3} +recho e4 "${1:1:3}" + +arr[0]=$e +arr[1]=$e + +recho a1 ${arr:0:4} +recho a2 "${arr:0:4}" + +recho a3 ${arr[@]:0:2} +recho a4 "${arr[@]:0:2}" + +set $e $e + +recho p1 ${@:1:2} +recho p2 "${@:1:2}" + +recho p1 ${*:1:2} +recho p2 "${*:1:2}" + +recho $e + +recho 'uvwx' + +f='uvwx' + +recho $f + +echo -en "\01" | cat -v +echo + +huhu() { echo "$1"; }; + +huhu $(echo -en "\01") | cat -v +huhu $(echo -en "\02") | cat -v + +f=$'uv\001w\001xy' + +set $f $f + +recho f1 ${f:1:3} +recho f2 "${f:1:3}" + +arr[0]=$f +arr[1]=$f + +recho a1 ${arr:0:4} +recho a2 "${arr:0:4}" +recho a3 ${arr[0]:0:4} +recho a4 "${arr[0]:0:4}" + +recho e1 ${f:0:4} +recho e2 "${f:0:4}" + +recho d1 ${1:2:2} +recho d2 "${1:2:2}" + +recho @1 ${@:1:2} +recho @2 "${@:1:2}" + +declare -A assoc +assoc=( [0]=$e [1]=$e ) + +recho aa1 ${assoc:0:4} +recho aa2 "${assoc:0:4}" + +recho aa3 ${assoc[@]:0:2} +recho aa4 "${assoc[@]:0:2}" diff --git a/tests/nquote2.right b/tests/nquote2.right new file mode 100644 index 0000000..e7fb21e --- /dev/null +++ b/tests/nquote2.right @@ -0,0 +1,76 @@ +argv[1] = <a^Ab> +argv[1] = <uv^A^Awx> +argv[1] = <aAb> +argv[1] = <aAb> +argv[1] = <uvA^Awx> +argv[1] = <uvA^Awx> +argv[1] = <a^AB> +argv[1] = <a^AB> +argv[1] = <uv^A^AWx> +argv[1] = <uv^A^AWx> +argv[1] = <aAb> +argv[1] = <aAb> +argv[1] = <uvAAwx> +argv[1] = <uvAAwx> +argv[1] = <a^AB> +argv[1] = <a^AB> +argv[1] = <uv^A^AWx> +argv[1] = <uv^A^AWx> +argv[1] = <uvA^Awx> +argv[2] = <uvA^Awx> +argv[1] = <uvA^Awx> +argv[2] = <uvA^Awx> +argv[1] = <uv^A^AWx> +argv[2] = <uv^A^AWx> +argv[1] = <uv^A^AWx> +argv[2] = <uv^A^AWx> +argv[1] = <uvAAwx> +argv[2] = <uvAAwx> +argv[1] = <uvAAwx> +argv[2] = <uvAAwx> +argv[1] = <uv^A^AWx> +argv[2] = <uv^A^AWx> +argv[1] = <uv^A^AWx> +argv[2] = <uv^A^AWx> +argv[1] = <a^Ab> +argv[1] = <uv^A^Awx> +argv[1] = <aAb> +argv[1] = <aAb> +argv[1] = <uvA^Awx> +argv[1] = <uvA^Awx> +argv[1] = <a^AB> +argv[1] = <a^AB> +argv[1] = <uv^A^AWx> +argv[1] = <uv^A^AWx> +argv[1] = <aAb> +argv[1] = <aAb> +argv[1] = <uvAAwx> +argv[1] = <uvAAwx> +argv[1] = <a^AB> +argv[1] = <a^AB> +argv[1] = <uv^A^AWx> +argv[1] = <uv^A^AWx> +argv[1] = <aAb> +argv[2] = <uvA^Awx> +argv[1] = <aAb> +argv[2] = <uvA^Awx> +argv[1] = <a^AB> +argv[2] = <uv^A^Awx> +argv[1] = <a^AB> +argv[2] = <uv^A^Awx> +argv[1] = <a^Ab> +argv[2] = <uv^A^AWx> +argv[1] = <a^Ab> +argv[2] = <uv^A^AWx> +argv[1] = <aAb> +argv[2] = <uvAAwx> +argv[1] = <aAb> +argv[2] = <uvAAwx> +argv[1] = <a^AB> +argv[2] = <uv^A^Awx> +argv[1] = <a^AB> +argv[2] = <uv^A^Awx> +argv[1] = <a^Ab> +argv[2] = <uv^A^AWx> +argv[1] = <a^Ab> +argv[2] = <uv^A^AWx> diff --git a/tests/nquote2.sub b/tests/nquote2.sub new file mode 100644 index 0000000..d3325f1 --- /dev/null +++ b/tests/nquote2.sub @@ -0,0 +1,29 @@ +t() { + printf '%s | %s\n' "$1" "$2" + } + v="'" # v <- ' + + #-- + t "${v/$'\''/$'\''}" "'" + t ${v/$'\''/$'\''} "'" + t "${v/$'\''/x}" "x" + t ${v/$'\''/x} "x" + t "${v/x/$'\''}" "'" + t ${v/x/$'\''} "'" + t "${v/x/$'\x5c\''}" "'" + t ${v/x/$'\x5c\''} "'" + t "${v/\'/\'}" "'" + t ${v/\'/\'} "'" + t ${v/\'/x} "x" + +echo "'" +echo "$'\''" + +echo $'\'' + +echo $'\'abcd\'' +echo "$'\'abcd\''" + +v=1 +echo ${v/1/\'} +echo ${v/\'/2} diff --git a/tests/nquote2.tests b/tests/nquote2.tests new file mode 100644 index 0000000..c07bd9b --- /dev/null +++ b/tests/nquote2.tests @@ -0,0 +1,82 @@ +a=$'a\001b' + +e=$'uv\001\001wx' + +recho $a +recho $e + +recho ${a/$'\001'/A} +recho "${a/$'\001'/A}" +recho ${e/$'\001'/A} +recho "${e/$'\001'/A}" + +recho ${a/b/B} +recho "${a/b/B}" +recho ${e/w/W} +recho "${e/w/W}" + +recho ${a//$'\001'/A} +recho "${a//$'\001'/A}" +recho ${e//$'\001'/A} +recho "${e//$'\001'/A}" + +recho ${a//b/B} +recho "${a//b/B}" +recho ${e//w/W} +recho "${e//w/W}" + +# pos params pat subst + +set $e $e + +recho ${@/$'\001'/A} +recho "${@/$'\001'/A}" +recho ${@/w/W} +recho "${@/w/W}" + +recho ${@//$'\001'/A} +recho "${@//$'\001'/A}" +recho ${@//w/W} +recho "${@//w/W}" + +arr[0]=$a +arr[1]=$e + +recho ${arr[0]} +recho ${arr[1]} + +recho ${arr[0]/$'\001'/A} +recho "${arr[0]/$'\001'/A}" +recho ${arr[1]/$'\001'/A} +recho "${arr[1]/$'\001'/A}" + +recho ${arr[0]/b/B} +recho "${arr[0]/b/B}" +recho ${arr[1]/w/W} +recho "${arr[1]/w/W}" + +recho ${arr[0]//$'\001'/A} +recho "${arr[0]//$'\001'/A}" +recho ${arr[1]//$'\001'/A} +recho "${arr[1]//$'\001'/A}" + +recho ${arr[0]//b/B} +recho "${arr[0]//b/B}" +recho ${arr[1]//w/W} +recho "${arr[1]//w/W}" + +recho ${arr[@]/$'\001'/A} +recho "${arr[@]/$'\001'/A}" + +recho ${arr[@]/b/B} +recho "${arr[@]/b/B}" +recho ${arr[@]/w/W} +recho "${arr[@]/w/W}" + +recho ${arr[@]//$'\001'/A} +recho "${arr[@]//$'\001'/A}" + +recho ${arr[@]//b/B} +recho "${arr[@]//b/B}" +recho ${arr[@]//w/W} +recho "${arr[@]//w/W}" diff --git a/tests/nquote3.right b/tests/nquote3.right new file mode 100644 index 0000000..d01eecc --- /dev/null +++ b/tests/nquote3.right @@ -0,0 +1,60 @@ +argv[1] = <uv^A^A> +argv[1] = <uv^A^A> +argv[1] = <uv^A> +argv[1] = <uv^A> +argv[1] = <^Ab> +argv[1] = <^Ab> +argv[1] = <xy> +argv[1] = <xy> +argv[1] = <xy> +argv[1] = <uv^Aw^Axy> +argv[1] = <uv^A> +argv[1] = <uv^A> +argv[1] = <^Awx> +argv[1] = <^Awx> +argv[1] = <xy> +argv[1] = <xy> +argv[1] = <xy> +argv[1] = <uv^Aw^Axy> +argv[1] = <uv^A> +argv[1] = <uv^A> +argv[1] = <^Awx> +argv[1] = <^Awx> +argv[1] = <uv^A> +argv[1] = <uv^A> +argv[1] = <^Awx> +argv[1] = <^Awx> +argv[1] = <xy> +argv[1] = <xy> +argv[1] = <xy> +argv[1] = <xy> +argv[1] = <uv^Aw^Axy> +argv[1] = <uv^Aw^Axy> +argv[1] = <uv^A> +argv[1] = <uv^A> +argv[1] = <^Awx> +argv[1] = <^Awx> +argv[1] = <uv^A> +argv[2] = <uv^Aw> +argv[1] = <uv^A> +argv[2] = <uv^Aw> +argv[1] = <^Awx> +argv[2] = <w^Axy> +argv[1] = <^Awx> +argv[2] = <w^Axy> +argv[1] = <wx> +argv[2] = <xy> +argv[1] = <uv^A^Awx> +argv[2] = <uv^Aw^Axy> +argv[1] = <uv^A> +argv[2] = <uv^Aw> +argv[1] = <uv^A> +argv[2] = <uv^Aw> +argv[1] = <^Awx> +argv[2] = <w^Axy> +argv[1] = <^Awx> +argv[2] = <w^Axy> +argv[1] = <wx> +argv[2] = <xy> +argv[1] = <uv^A^Awx> +argv[2] = <uv^Aw^Axy> diff --git a/tests/nquote3.sub b/tests/nquote3.sub new file mode 100644 index 0000000..d1480c0 --- /dev/null +++ b/tests/nquote3.sub @@ -0,0 +1,8 @@ +. ./test-glue-functions + +recho $'\c?' + +echo $'\c?' | od -t a | _intl_normalize_spaces +echo $'\c[\c\\\c]\c^\c_\c?' | od -t a | _intl_normalize_spaces + +echo $'\q' diff --git a/tests/nquote3.tests b/tests/nquote3.tests new file mode 100644 index 0000000..a83ff56 --- /dev/null +++ b/tests/nquote3.tests @@ -0,0 +1,85 @@ +a=$'a\001b' + +set $a + +b=$a +c=$1 +d="$1" + +e=$'uv\001\001wx' +f=$'uv\001w\001xy' + +set $e $e + +recho ${e%%??} +recho "${e%%??}" + +recho ${e%%???} +recho "${e%%???}" + +recho ${a#?} +recho "${a#?}" + +# simple variables + +recho ${f##*$'\001'} +recho "${f##*$'\001'}" +recho ${f##*''} # literal ^A +recho "${f##*'^A'}" # two characters, `^' and `A' + +recho ${e%$'\001'*} +recho "${e%$'\001'*}" +recho ${e#*$'\001'} +recho "${e#*$'\001'}" + +# array members + +arr[0]=$e +arr[1]=$f + +recho ${arr[1]##*$'\001'} +recho "${arr[1]##*$'\001'}" +recho ${arr[1]##*''} # literal ^A +recho "${arr[1]##*'^A'}" # two characters, `^' and `A' + +recho ${arr[0]%$'\001'*} +recho "${arr[0]%$'\001'*}" +recho ${arr[0]#*$'\001'} +recho "${arr[0]#*$'\001'}" + +recho ${arr%$'\001'*} +recho "${arr%$'\001'*}" +recho ${arr#*$'\001'} +recho "${arr#*$'\001'}" + +# positional parameters + +set $e $f + +recho ${2##*$'\001'} +recho "${2##*$'\001'}" +recho ${2##*''} # literal ^A +recho "${2##*''}" # literal ^A +recho ${2##*'^A'} # two characters, `^' and `A' +recho "${2##*'^A'}" # two characters, `^' and `A' + +recho ${1%$'\001'*} +recho "${1%$'\001'*}" +recho ${1#*$'\001'} +recho "${1#*$'\001'}" + +recho ${@%$'\001'*} +recho "${@%$'\001'*}" +recho ${@#*$'\001'} +recho "${@#*$'\001'}" +recho ${@##*''} # literal ^A +recho "${@##*'^A'}" # two characters, `^' and `A' + +# arrays treated as a whole + +recho ${arr[@]%$'\001'*} +recho "${arr[@]%$'\001'*}" +recho ${arr[@]#*$'\001'} +recho "${arr[@]#*$'\001'}" +recho ${arr[@]##*''} # literal ^A +recho "${arr[@]##*'^A'}" # two characters, `^' and `A' diff --git a/tests/nquote4.right b/tests/nquote4.right new file mode 100644 index 0000000..1f7ae17 --- /dev/null +++ b/tests/nquote4.right @@ -0,0 +1,18 @@ +argv[1] = <ab> +argv[1] = <abAcd> +argv[1] = <abAcd> +argv[1] = <ab^Dcd> +argv[1] = <abLd> +argv[1] = <abÞ> +argv[1] = <abÞ> +argv[1] = <abÍe> +argv[1] = <ab^Lde> +argv[1] = <¼X> +argv[1] = <«cX> +argv[1] = <> +argv[1] = <> +argv[1] = <gX> +argv[1] = <Ab> +argv[1] = <> +argv[1] = <^Abcd> +argv[1] = <Þ> diff --git a/tests/nquote4.tests b/tests/nquote4.tests new file mode 100644 index 0000000..ed73467 --- /dev/null +++ b/tests/nquote4.tests @@ -0,0 +1,24 @@ +recho $'ab\x{}cd' +recho $'ab\x{41}cd' +recho $'ab\x41cd' + +recho $'ab\x{4}cd' +recho $'ab\x4cd' + +recho $'ab\x{cde' + +recho $'ab\x{cde' +recho $'ab\x{cd}e' +recho $'ab\x{c}de' + +recho $'\x{abcX' +recho $'\x{ab}cX' +recho $'\x{}X' +recho $'\x{X' +recho $'\x{01234567X' + +recho $'\x{41}b' +recho $'\x{}bc' +recho $'\x{1}bcd' + +recho $'\x{bde' diff --git a/tests/nquote5.right b/tests/nquote5.right new file mode 100644 index 0000000..a893329 --- /dev/null +++ b/tests/nquote5.right @@ -0,0 +1,86 @@ +argv[1] = <ab> +argv[2] = <cd> +argv[3] = <ef> +argv[1] = <ab> +argv[2] = <cd> +argv[3] = <ef> +argv[1] = <xxab> +argv[2] = <cd> +argv[3] = <efyy> +argv[1] = <ab^Acd^Aef> +argv[1] = <ab cd ef> +argv[1] = <ab> +argv[2] = <cd> +argv[3] = <ef> +argv[1] = <ab> +argv[2] = <cd> +argv[1] = <ab^Acd^A> +argv[1] = <ab> +argv[2] = <cd> +argv[3] = <e> +argv[1] = <ab^Acd^Ae> +argv[1] = <ab> +argv[2] = <cd> +argv[3] = <ef> +argv[1] = <ab> +argv[2] = <cd> +argv[3] = <ef> +argv[1] = <> +argv[2] = <c> +argv[1] = <ab> +argv[2] = <--> +argv[3] = <cd> +argv[4] = <--> +argv[5] = <ef> +argv[1] = <ab> +argv[2] = <cd> +argv[3] = <ef> +argv[1] = <ab> +argv[2] = <cd> +argv[3] = <ef> +argv[1] = <ab> +argv[2] = <--> +argv[3] = <cd> +argv[4] = <--> +argv[5] = <ef> +argv[1] = <uv^?wx^?yz> +argv[1] = <abyab^Acd^Aefz> +argv[1] = <abyab> +argv[2] = <cd> +argv[3] = <efz> +argv[1] = <abuv^?wx^?yzyab^Acd^Aefz> +argv[1] = <abuv^?wx^?yzyab> +argv[2] = <cd> +argv[3] = <efz> +argv[1] = <abuv^?wx^?yzyab> +argv[2] = <--> +argv[3] = <cd> +argv[4] = <--> +argv[5] = <efz> +argv[6] = <--> +argv[1] = <ab^Acd^Aef> +argv[1] = <uv> +argv[2] = <wx> +argv[3] = <yz> +argv[1] = <abyuv^?wx^?yzz> +argv[1] = <abyuv> +argv[2] = <wx> +argv[3] = <yzz> +argv[1] = <abuv^?wx^?yzyab^Acd^Aefz> +argv[1] = <abuv> +argv[2] = <wx> +argv[3] = <yzyab^Acd^Aefz> +argv[1] = <abuv^?wx^?yzyab> +argv[2] = <--> +argv[3] = <cd> +argv[4] = <--> +argv[5] = <efz> +argv[6] = <--> +argv[7] = <> +argv[1] = <abuv> +argv[2] = <--> +argv[3] = <wx> +argv[4] = <--> +argv[5] = <yzyab^Acd^Aefz> +argv[6] = <--> +argv[7] = <> diff --git a/tests/nquote5.tests b/tests/nquote5.tests new file mode 100644 index 0000000..85a2ff6 --- /dev/null +++ b/tests/nquote5.tests @@ -0,0 +1,63 @@ +a=$'ab\001cd\001ef' +IFS=$'\001' + +recho $a +recho ${a} +recho xx${a}yy +recho "$a" + +recho $(echo $a) +recho $(echo "$a") + +recho ${a%%??} +recho "${a%%??}" + +recho ${a/f/} +recho "${a/f/}" + +a1=("$a") +recho ${a1[0]} +recho ${a1} + +recho ${a:2:2} + +set -- $a +recho $1 -- $2 -- $3 + +set -- "$a" +recho $1 +recho ${1} + +echo "$a" | { IFS=$'\001' read x y z; recho $x -- $y -- $z ; } +unset x y z +b=$'uv\177wx\177yz' + +recho $b + +recho "ab${x}y${a}z" +recho ab${x}y${a}z + +recho "ab${b}y${a}z" +recho ab${b}y${a}z + +echo "ab${b}y${a}z" | { IFS=$'\001' read l m n o ; recho $l -- $m -- $n -- $o; } +unset l m n o + +a=$'ab\001cd\001ef' +b=$'uv\177wx\177yz' + +IFS=$'\177' + +recho $a +recho $b + +recho "ab${x}y${b}z" +recho ab${x}y${b}z + +recho "ab${b}y${a}z" +recho ab${b}y${a}z + +echo "ab${b}y${a}z" | { IFS=$'\001' read l m n o ; recho "$l" -- "$m" -- "$n" -- "$o"; } +unset l m n o +echo "ab${b}y${a}z" | { IFS=$'\177' read l m n o ; recho "$l" -- "$m" -- "$n" -- "$o"; } +unset l m n o diff --git a/tests/parser.right b/tests/parser.right new file mode 100644 index 0000000..cecbb22 --- /dev/null +++ b/tests/parser.right @@ -0,0 +1,16 @@ +AAA +bash5: `invalid-name': not a valid identifier +in +in +in +in +bash5: -c: line 0: syntax error near unexpected token `)' +bash5: -c: line 0: `case x in esac) echo done; esac' +in +bash5: -c: line 0: syntax error near unexpected token `do' +bash5: -c: line 0: `case in do do) echo in; esac' +bash5: -c: line 0: syntax error near unexpected token `(' +bash5: -c: line 0: `for()' +in +done +ok 1 diff --git a/tests/parser.tests b/tests/parser.tests new file mode 100644 index 0000000..6e020a4 --- /dev/null +++ b/tests/parser.tests @@ -0,0 +1,6 @@ +# catch-all for parsing problems that don't fit anywhere else + +# this has to be in a separate file to get desired EOF behavior +${THIS_SH} ./parser1.sub + +${THIS_SH} ./posix2syntax.sub diff --git a/tests/parser1.sub b/tests/parser1.sub new file mode 100644 index 0000000..5031931 --- /dev/null +++ b/tests/parser1.sub @@ -0,0 +1 @@ +eval "array=(foo bar)" ; echo AAA\ diff --git a/tests/posix2.right b/tests/posix2.right new file mode 100644 index 0000000..b1585a2 --- /dev/null +++ b/tests/posix2.right @@ -0,0 +1,6 @@ +Testing for POSIX.2 conformance +./posix2.tests: eval: line 182: syntax error near unexpected token `esac' +./posix2.tests: eval: line 182: `case esac in (esac) ;; *) echo "case esac test 3" ;; esac' +./posix2.tests: eval: line 184: syntax error near unexpected token `)' +./posix2.tests: eval: line 184: `case esac in esac) ;; *) echo "case esac test 4";; esac' +All tests passed diff --git a/tests/posix2.tests b/tests/posix2.tests new file mode 100644 index 0000000..ecf6a6f --- /dev/null +++ b/tests/posix2.tests @@ -0,0 +1,191 @@ +#! /bin/sh +# posix-2.sh - Simple identification tests for POSIX.2 features +# commonly missing or incorrectly implemented. +# Time-stamp: <96/04/10 16:43:48 gildea> +# By Stephen Gildea <gildea@x.org> March 1995 +# +# Copyright (c) 1995 Stephen Gildea +# Permission is hereby granted to deal in this Software without restriction. +# THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND. +# +# MODIFIED BY chet@po.cwru.edu to make part of the bash test suite. +# last change: Wed Jun 19 12:24:24 EDT 1996 +# +# some of the tests: +# +# shell functions (do we care?) +# var=${var:-val} +# unset +# set -- +# IFS parsing +## not exiting with -e and failed "if", the way Ultrix does (Ultrix 4.2?) +# "$@" expands to zero arguments if passed zero arguments +# $SHELL -c 'echo $1' bad good +# test -x +# positional parameters greater than 9 +# arithmetic expansion $(( ... )) +# getopts + +# For some tests we must run a sub-shell; $TESTSHELL says what to use. +# If set, TESTSHELL must be an absolute pathname. +# For example, on HP-UX 9, /bin/posix/sh is the supposedly-compliant shell. +TESTSHELL=${THIS_SH:-$PWD/../bash} + +# these tests create temp files with names $TMPDIR/conf* +: ${TMPDIR:=/tmp} + +exitval=0 +numtests=0 + +echo "Testing for POSIX.2 conformance" + +newtest() +{ + numtests=$(($numtests + 1)) +} + +testfail() +{ + echo "$1 test failed" + exitval=$(($exitval + 1)) +} + +newtest +empty="" +test "${empty:-ok}" = ok || testfail "empty var colon" +newtest +test "${empty-bad}" = "" || testfail "got \"${empty-bad}\": empty var nocolon" +newtest +test "${unsetvar-ok}" = ok || testfail "unset var" +newtest +unset empty +test "${empty-ok}" = ok || testfail "unset" + +newtest +set -- -Z +test "x$1" = x-Z || testfail '\"set -- arg\"' +# this should empty the argument list +newtest +set -- +test $# = 0 || testfail "still $# args: \"set --\"" + +# IFS parsing: +newtest +names=one/good/three +saved_ifs="$IFS" +IFS=/ +set $names lose +test "$2" = good || testfail "got \"$2\": IFS parsing" +IFS="$saved_ifs" + +# "$@" with 0 arguments should expand to 0 arguments +newtest +cat > $TMPDIR/conftest1 << EOF +$TMPDIR/conftest2 "\$@" +EOF +cat > $TMPDIR/conftest2 << "EOF" +#! /bin/sh +echo $# +EOF +chmod +x $TMPDIR/conftest1 $TMPDIR/conftest2 +numargs=$($TESTSHELL $TMPDIR/conftest1) +if [ "$?" != 0 ]; then + testfail 'running $@' +else + test "$numargs" = 0 || testfail '"$@" got '"$numargs args: expansion w 0 args" +fi +rm -f $TMPDIR/conftest1 $TMPDIR/conftest2 + +newtest +val=$("$TESTSHELL" -c 'echo $1' csh good) +test "$val" = good || testfail "got \"$val\": sh -c" + +newtest +# do these tests in a sub-shell because failure will exit +val=$("$TESTSHELL" -c 'echo ${10}' 0 1 2 3 4 5 6 7 8 9 ten 11 2> /dev/null) +test "$val" = ten || testfail "accessing more than 9 positional params" + +a=abc_def_ghi +export a +newtest; val=`"$TESTSHELL" -c 'echo "${a%_*}"' 2> /dev/null` +test "$val" = abc_def || testfail "parameter % op" +newtest; val=`"$TESTSHELL" -c 'echo "${a%%_*}"' 2> /dev/null` +test "$val" = abc || testfail "parameter %% op" +newtest; val=`"$TESTSHELL" -c 'echo "${a#*_}"' 2> /dev/null` +test "$val" = def_ghi || testfail "parameter # op" +newtest; val=`"$TESTSHELL" -c 'echo "${a##*_}"' 2> /dev/null` +test "$val" = ghi || testfail "parameter ## op" + +newtest +"$TESTSHELL" -c 'export a=value' 2> /dev/null || testfail "export with value" + +newtest +a=5; test "$(( ($a+1)/2 ))" = 3 || testfail "arithmetic expansion" + +# does "test" support the -x switch? +newtest +touch $TMPDIR/conftest +chmod -x $TMPDIR/conftest +test -x $TMPDIR/conftest && testfail "negative test -x" +chmod +x $TMPDIR/conftest +test -x $TMPDIR/conftest || testfail "positive test -x" +rm -f $TMPDIR/conftest + +newtest +test "$OPTIND" = 1 || testfail "OPTIND initial value" + +newtest +getopts a: store -a aoptval +if [ "$OPTIND" != 3 ] || [ "$store" != a ] || [ "$OPTARG" != aoptval ]; then + testfail "getopts" +fi + +# if I change the default quoting style for variable values, these +# next four must change + +newtest +SQUOTE="'" +val1=$(set | sed -n 's:^SQUOTE=::p') +if [ "$val1" != "\'" ]; then + testfail "variable quoting 1" +fi + +newtest +VTILDE='~' +val1=$(set | sed -n 's:^VTILDE=::p') +if [ "$val1" != "'~'" ]; then + testfail "variable quoting 2" +fi + +newtest +VHASH=ab#cd +val1=$(set | sed -n 's:^VHASH=::p') +if [ "$val1" != "ab#cd" ]; then + testfail "variable quoting 3" +fi + +newtest +VHASH2=#abcd +val1=$(set | sed -n 's:^VHASH2=::p') +if [ "$val1" != "'#abcd'" ]; then + testfail "variable quoting 4" +fi + +# these are Posix.2 shell grammar rule 4, problems through bash-4.3 +newtest +case esac in (foo|esac) ;; *) testfail "case esac test 1" ;; esac +newtest +case esac in foo|esac) ;; *) testfail "case esac test 2" ;; esac + +# these are supposed to be syntax errors +newtest +eval 'case esac in (esac) ;; *) echo "case esac test 3" ;; esac' +newtest +eval 'case esac in esac) ;; *) echo "case esac test 4";; esac' + +if [ $exitval = 0 ]; then + echo "All tests passed" +else + echo "$exitval of $numtests tests failed" +fi +exit $exitval diff --git a/tests/posix2syntax.sub b/tests/posix2syntax.sub new file mode 100644 index 0000000..e7dda58 --- /dev/null +++ b/tests/posix2syntax.sub @@ -0,0 +1,53 @@ +: ${THIS_SH:=./bash} +bashname=bash${BASH_VERSION%%.*} + +# tests for Posix grammar special cases + +# Posix grammar rule 5 +${THIS_SH} -c 'for invalid-name in a b c; do echo error; done' $bashname + +# Posix grammar rule 6: third word in FOR or SELECT +for i; do echo; done; echo in +for i; do echo in; done +for i do echo in; done + +select i; do echo; done; echo in +select i; do echo in; done; echo in +select i do echo in; done; echo in + +# Posix grammar rule 4: when PATTERN == ESAC, return ESAC +${THIS_SH} -c 'case x in esac) echo done; esac' $bashname + +# Posix grammar rule 6: third word in CASE +${THIS_SH} -c 'case in in in) echo in; esac;' $bashname +${THIS_SH} -c 'case in do do) echo in; esac' $bashname + +# Posix grammar rule 8: function NAME +${THIS_SH} -o posix -c 'for() +{ +echo function for; +}' $bashname + +for for in for; do echo in; echo done; done + +${THIS_SH} -c 'for (( i = 0; i < 5; i++ )) do : ; done' $bashname +${THIS_SH} -c 'for (( i = 0; i < 5; i++ )) { : ; }' $bashname + +# bug report: IN turning on unwanted alias expansion +${THIS_SH} -o posix -c ' +alias foo='two words' +foo_word='foo' +case "$foo_word" +in + foo) echo "bad 1";; +esac' $bashname + +${THIS_SH} -o posix -c ' +alias foo='oneword' +foo_word='foo' +case "$foo_word" +in + foo) echo "ok 1";; +esac' $bashname + + diff --git a/tests/posixexp.right b/tests/posixexp.right new file mode 100644 index 0000000..53a08e3 --- /dev/null +++ b/tests/posixexp.right @@ -0,0 +1,283 @@ +a +b +a b +argv[1] = <a> +argv[2] = <b> +argv[3] = <x> +argv[4] = <a> +argv[5] = <b> +argv[1] = <a\ b> +argv[2] = <x> +argv[3] = <a\ b> +argv[1] = <foo 'bar' baz> +argv[1] = <a b c d> +argv[1] = <a b c d> +argv[1] = <foo ax{{{}b c d{} bar> +argv[2] = <}> +argv[3] = <baz> +argv[1] = <'foo'> +argv[1] = <'foo'> +argv[1] = <$a> +argv[1] = <'foo'> +argv[1] = <foo*bar> +argv[1] = <foo*bar> +argv[1] = <foo*bar'}> +argv[1] = <x'> +<.> <x> <.> <> <.> <x> <.> +<x> <.> <w> <.> <x> <.> <w> <.> +<x> <.> <w> <.> <x> <.> <w> <.> +<x> <.> <w> <.> <x> <.> <w> <.> +<.> <w> <.> <> <.> <w> <.> +<.> <w> <.> <> <.> <w> <.> +<x> <.> <x> <.> <x> <.> <x> <.> +<x> <.> <w> <.> <x> <.> <w> <.> +<x> <.> <w> <.> <x> <.> <w> <.> +<x> <.> <w> <.> <x> <.> <w> <.> +argv[1] = <'bar> +argv[1] = <foo 'bar baz> +argv[1] = <}z> +argv[1] = <''z}> +argv[1] = <1> +argv[2] = <2> +argv[1] = <1> +argv[2] = <2> +argv[1] = <1> +argv[2] = <2> +argv[1] = <1 2> +argv[1] = <1> +argv[2] = <2> +argv[1] = <1 2> +argv[1] = <1> +argv[2] = <2> +argv[1] = <1 2> +argv[1] = <1> +argv[2] = <2> +argv[1] = <1 2> +argv[1] = <1> +argv[2] = <2> +argv[1] = <1 2> +argv[1] = <1> +argv[2] = <2> +argv[1] = <1> +argv[2] = <2> +argv[1] = <1> +argv[2] = <2> +argv[1] = <12> +argv[1] = <1 2> +argv[1] = <1 2> +argv[1] = <1 2> +argv[1] = <1 2> +argv[1] = <1 2> +argv[1] = <1 2> +argv[1] = <12> +argv[1] = <12> +argv[1] = <12> +argv[1] = <12> +argv[1] = <12> +argv[1] = <12> +argv[1] = <1 2> +argv[1] = <1 2> +argv[1] = <12> +argv[1] = <12> +normal IFS +argv[1] = <abc> +argv[2] = <def> +argv[3] = <ghi> +argv[4] = <jkl> +argv[1] = <abc> +argv[2] = <def> +argv[3] = <ghi> +argv[4] = <jkl> +argv[1] = <abc> +argv[2] = <def> +argv[3] = <ghi> +argv[4] = <jkl> +null IFS +argv[1] = < abc> +argv[2] = <def ghi> +argv[3] = <jkl > +argv[1] = < abc def ghi jkl > +argv[1] = < abc> +argv[2] = <def ghi> +argv[3] = <jkl > +non-standard IFS +argv[1] = < abc> +argv[2] = <def ghi> +argv[3] = <jkl > +argv[1] = < abc def ghi jkl > +argv[1] = < abc def ghi jkl > +unset IFS +argv[1] = < abc> +argv[2] = <def ghi> +argv[3] = <jkl > +argv[1] = < abc def ghi jkl > +argv[1] = < abc def ghi jkl > + +001: IFS = (unset): unset -v foo; set -- ${foo=$*} +soh stx etx del / soh stx etx del + +002: IFS = (unset): unset -v foo; set -- ${foo="$*"} +soh stx etx del / soh stx etx del + +003: IFS = (unset): unset -v foo; set -- "${foo=$*}" +soh stx etx del / soh stx etx del + +004: IFS = (unset): foo=; set -- ${foo:=$*} +soh stx etx del / soh stx etx del + +005: IFS = (unset): foo=; set -- ${foo:="$*"} +soh stx etx del / soh stx etx del + +006: IFS = (unset): foo=; set -- "${foo:=$*}" +soh stx etx del / soh stx etx del + +007: IFS = (unset): unset -v foo; set -- ${foo=$@} +soh stx etx del / soh stx etx del + +008: IFS = (unset): unset -v foo; set -- ${foo="$@"} +soh stx etx del / soh stx etx del + +009: IFS = (unset): unset -v foo; set -- "${foo=$@}" +soh stx etx del / soh stx etx del + +010: IFS = (unset): foo=; set -- ${foo:=$@} +soh stx etx del / soh stx etx del + +011: IFS = (unset): foo=; set -- ${foo:="$@"} +soh stx etx del / soh stx etx del + +012: IFS = (unset): foo=; set -- "${foo:=$@}" +soh stx etx del / soh stx etx del + +013: IFS = (null): unset -v foo; set -- ${foo=$*} +soh stx etx del / soh stx etx del + +014: IFS = (null): unset -v foo; set -- ${foo="$*"} +soh stx etx del / soh stx etx del + +015: IFS = (null): unset -v foo; set -- "${foo=$*}" +soh stx etx del / soh stx etx del + +016: IFS = (null): foo=; set -- ${foo:=$*} +soh stx etx del / soh stx etx del + +017: IFS = (null): foo=; set -- ${foo:="$*"} +soh stx etx del / soh stx etx del + +018: IFS = (null): foo=; set -- "${foo:=$*}" +soh stx etx del / soh stx etx del + +019: IFS = (null): unset -v foo; set -- ${foo=$@} +soh stx etx del / soh stx etx del + +020: IFS = (null): unset -v foo; set -- ${foo="$@"} +soh stx etx del / soh stx etx del + +021: IFS = (null): unset -v foo; set -- "${foo=$@}" +soh stx etx del / soh stx etx del + +022: IFS = (null): foo=; set -- ${foo:=$@} +soh stx etx del / soh stx etx del + +023: IFS = (null): foo=; set -- ${foo:="$@"} +soh stx etx del / soh stx etx del + +024: IFS = (null): foo=; set -- "${foo:=$@}" +soh stx etx del / soh stx etx del + +025: IFS = x: unset -v foo; set -- ${foo=$*} +soh stx etx del / soh stx etx del + +026: IFS = x: unset -v foo; set -- ${foo="$*"} +soh stx etx del / soh stx etx del + +027: IFS = x: unset -v foo; set -- "${foo=$*}" +soh stx etx del / soh stx etx del + +028: IFS = x: foo=; set -- ${foo:=$*} +soh stx etx del / soh stx etx del + +029: IFS = x: foo=; set -- ${foo:="$*"} +soh stx etx del / soh stx etx del + +030: IFS = x: foo=; set -- "${foo:=$*}" +soh stx etx del / soh stx etx del + +031: IFS = x: unset -v foo; set -- ${foo=$@} +soh stx etx del / soh stx etx del + +032: IFS = x: unset -v foo; set -- ${foo="$@"} +soh stx etx del / soh stx etx del + +033: IFS = x: unset -v foo; set -- "${foo=$@}" +soh stx etx del / soh stx etx del + +034: IFS = x: foo=; set -- ${foo:=$@} +soh stx etx del / soh stx etx del + +035: IFS = x: foo=; set -- ${foo:="$@"} +soh stx etx del / soh stx etx del + +036: IFS = x: foo=; set -- "${foo:=$@}" +soh stx etx del / soh stx etx del + +037: IFS = sp ht nl: unset -v foo; set -- ${foo=$*} +soh stx etx del / soh stx etx del + +038: IFS = sp ht nl: unset -v foo; set -- ${foo="$*"} +soh stx etx del / soh stx etx del + +039: IFS = sp ht nl: unset -v foo; set -- "${foo=$*}" +soh stx etx del / soh stx etx del + +040: IFS = sp ht nl: foo=; set -- ${foo:=$*} +soh stx etx del / soh stx etx del + +041: IFS = sp ht nl: foo=; set -- ${foo:="$*"} +soh stx etx del / soh stx etx del + +042: IFS = sp ht nl: foo=; set -- "${foo:=$*}" +soh stx etx del / soh stx etx del + +043: IFS = sp ht nl: unset -v foo; set -- ${foo=$@} +soh stx etx del / soh stx etx del + +044: IFS = sp ht nl: unset -v foo; set -- ${foo="$@"} +soh stx etx del / soh stx etx del + +045: IFS = sp ht nl: unset -v foo; set -- "${foo=$@}" +soh stx etx del / soh stx etx del + +046: IFS = sp ht nl: foo=; set -- ${foo:=$@} +soh stx etx del / soh stx etx del + +047: IFS = sp ht nl: foo=; set -- ${foo:="$@"} +soh stx etx del / soh stx etx del + +048: IFS = sp ht nl: foo=; set -- "${foo:=$@}" +soh stx etx del / soh stx etx del +argv[1] = <^A^B^C^?> +argv[1] = <^A^B^C^?> +argv[1] = <^A^B^C^?> +argv[1] = <^A^B^C^?> +argv[1] = <^A^B^C^?> +argv[1] = <^A^B^C^?> +argv[1] = <^A^B^C^?> +argv[1] = <^A^B^C^?> +argv[1] = <a> +argv[2] = <b> +argv[1] = <a> +argv[2] = <b> +argv[1] = <a> +argv[2] = <b> +argv[1] = <a> +argv[2] = <b> +[ abc def ghi jkl / abc def ghi jkl ] +[ abc def ghi jkl ] +[ abc def ghi jkl / abc def ghi jkl / abc def ghi jkl ] +5: notOK +OK +OK +5: $'not\ttoo\nbad' +./posixexp.tests: line 83: unexpected EOF while looking for matching `}' +./posixexp.tests: line 84: syntax error: unexpected end of file diff --git a/tests/posixexp.tests b/tests/posixexp.tests new file mode 100644 index 0000000..3368711 --- /dev/null +++ b/tests/posixexp.tests @@ -0,0 +1,83 @@ +unset a +printf "%s\n" ${a:=a\ b} +echo "$a" + +unset v +recho ${v=a\ b} x ${v=c\ d} + +unset v +recho "${v=a\ b}" x "${v=c\ d}" + +unset a v + +recho "foo ${IFS+'bar'} baz" +recho "a ${IFS+b c} d" + +recho "a ${IFS+"b c"} d" + +u=x +recho "foo ${IFS+a$u{{{\}b} c ${IFS+d{}} bar" ${IFS-e{}} baz + +a=foo +recho "${IFS+'$a'}" +recho "${IFS+"'$a'"}" + +recho ${IFS+'$a'} +recho ${IFS+"'$a'"} + +unset a u +x='foo*bar' + +recho "${x##"}"}" +recho "${x##'}'}" +recho "${x##'}" + +recho "${x:-'}'}" + +foo="x'a'y" +recho "${foo%*'a'*}" +unset x + +unset u +v=w +printf '<%s> ' ${u+x} . ${v+x} . "${u+x}" . "${v+x}" .; echo +printf '<%s> ' ${u-x} . ${v-x} . "${u-x}" . "${v-x}" .; echo +printf '<%s> ' ${u=x} . ${v=x} . "${u=x}" . "${v=x}" .; echo +printf '<%s> ' ${u?x} . ${v?x} . "${u?x}" . "${v?x}" .; echo +printf '<%s> ' ${u#x} . ${v#x} . "${u#x}" . "${v#x}" .; echo +printf '<%s> ' ${u%x} . ${v%x} . "${u%x}" . "${v%x}" .; echo +printf '<%s> ' ${u:+x} . ${v:+x} . "${u:+x}" . "${v:+x}" .; echo +printf '<%s> ' ${u:-x} . ${v:-x} . "${u:-x}" . "${v:-x}" .; echo +printf '<%s> ' ${u:=x} . ${v:=x} . "${u:=x}" . "${v:=x}" .; echo +printf '<%s> ' ${u:?x} . ${v:?x} . "${u:?x}" . "${v:?x}" .; echo +# these are invalid substitution operators +#printf '<%s> ' ${u:#x} . ${v:#x} . "${u:#x}" . "${v:#x}" .; echo +#printf '<%s> ' ${u:%x} . ${v:%x} . "${u:%x}" . "${v:%x}" .; echo + +unset foo +set -o posix + +recho "${IFS+'bar}" +recho "foo ${IFS+'bar} baz" + +recho ${IFS+'}'z} +recho "${IFS+'}'z}" + +: ${TMPDIR:=/var/tmp} +rm -f $TMPDIR/sh +cp ${THIS_SH} $TMPDIR/sh +THIS_SH=$TMPDIR/sh ${THIS_SH} ./posixexp1.sub || echo "sh posixexp1.sub: test $? failed" +${THIS_SH} ./posixexp1.sub || echo "bash posixexp1.sub: test $? failed" + +THIS_SH=$TMPDIR/sh ${THIS_SH} ./posixexp2.sub || echo "sh posixexp2.sub: test $? failed" +rm -f $TMPDIR/sh + +${THIS_SH} ./posixexp3.sub +${THIS_SH} ./posixexp4.sub +${THIS_SH} ./posixexp5.sub +${THIS_SH} ./posixexp6.sub +${THIS_SH} ./posixexp7.sub + +# this will be an error +foo=bar +echo "${foo:-"a}" diff --git a/tests/posixexp1.sub b/tests/posixexp1.sub new file mode 100644 index 0000000..91718e3 --- /dev/null +++ b/tests/posixexp1.sub @@ -0,0 +1,38 @@ +# $FreeBSD: src/tools/regression/bin/sh/expansion/set-u1.0,v 1.2 2010/10/12 18:20:38 obrien Exp $ + +${THIS_SH} -uc 'unset foo; echo ${foo}' 2>/dev/null && exit 1 +${THIS_SH} -uc 'unset foo; echo $foo' 2>/dev/null && exit 1 +${THIS_SH} -uc 'foo=; echo $foo' >/dev/null || exit 2 +${THIS_SH} -uc 'foo=1; echo $foo' >/dev/null || exit 3 +# -/+/= are unaffected by set -u +${THIS_SH} -uc 'unset foo; echo ${foo-}' >/dev/null || exit 4 +${THIS_SH} -uc 'unset foo; echo ${foo+}' >/dev/null || exit 5 +${THIS_SH} -uc 'unset foo; echo ${foo=}' >/dev/null || exit 6 +# length/trimming are affected +${THIS_SH} -uc 'unset foo; echo ${#foo}' 2>/dev/null && exit 7 +${THIS_SH} -uc 'foo=; echo ${#foo}' >/dev/null || exit 8 +${THIS_SH} -uc 'unset foo; echo ${foo#?}' 2>/dev/null && exit 9 +${THIS_SH} -uc 'foo=1; echo ${foo#?}' >/dev/null || exit 10 +${THIS_SH} -uc 'unset foo; echo ${foo##?}' 2>/dev/null && exit 11 +${THIS_SH} -uc 'foo=1; echo ${foo##?}' >/dev/null || exit 12 +${THIS_SH} -uc 'unset foo; echo ${foo%?}' 2>/dev/null && exit 13 +${THIS_SH} -uc 'foo=1; echo ${foo%?}' >/dev/null || exit 14 +${THIS_SH} -uc 'unset foo; echo ${foo%%?}' 2>/dev/null && exit 15 +${THIS_SH} -uc 'foo=1; echo ${foo%%?}' >/dev/null || exit 16 + +${THIS_SH} -uc 'echo $!' 2>/dev/null && exit 17 +${THIS_SH} -uc ':& echo $!' >/dev/null || exit 18 +${THIS_SH} -uc 'echo $#' >/dev/null || exit 19 +${THIS_SH} -uc 'echo $1' 2>/dev/null && exit 20 +${THIS_SH} -uc 'echo $1' ${THIS_SH} xnotthere >/dev/null || exit 21 +${THIS_SH} -uc 'echo $2' ${THIS_SH} xnotthere 2>/dev/null && exit 22 +${THIS_SH} -uc 'echo $2' ${THIS_SH} xnotthere ynotthere >/dev/null || exit 23 + +${THIS_SH} -uc 'echo $! ; exit 24' 2>/dev/null +${THIS_SH} -uc 'echo ${!} ; exit 25' 2>/dev/null +${THIS_SH} -uc 'echo ${!,} ; exit 26' 2>/dev/null + +${THIS_SH} -uc 'echo ${!-ok 27} >/dev/null || exit 27' +${THIS_SH} -uc 'echo ${2-ok 28} >/dev/null || exit 28' + +exit 0 diff --git a/tests/posixexp2.right b/tests/posixexp2.right new file mode 100644 index 0000000..08d3901 --- /dev/null +++ b/tests/posixexp2.right @@ -0,0 +1,40 @@ +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 <foo abx{ {{{}b c d{} bar> <}> <baz> . +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 <foo> <abx{ {{> <{}b> <c> <d{}> <bar> <}> <baz> . +30 <foo> <b\ +ar> <baz> . +32 <foo> <bar> <baz> . +33 <foo 'bar' baz> . +34 <foo bar baz> . +35 <a> <b> <x> <a> <b> . +36 <a\ b> <x> <a\ b> . +37 <a b> <x> <c d> . +38 xay / x'a'y . +39 x' / x' . +40 < b c> . diff --git a/tests/posixexp2.sub b/tests/posixexp2.sub new file mode 100644 index 0000000..397769d --- /dev/null +++ b/tests/posixexp2.sub @@ -0,0 +1,24 @@ + +x=a\ b +[ "$x" = "${x?}" ] || exit 1 +set -- ${x?} +{ [ "$#" = 2 ] && [ "$1" = a ] && [ "$2" = b ]; } || exit 1 +unset x +(echo ${x?abcdefg}) 2>&1 | grep abcdefg >/dev/null || exit 1 +${THIS_SH} -c 'unset foo; echo ${foo?}' 2>/dev/null && exit 2 +${THIS_SH} -c 'foo=; echo ${foo:?}' 2>/dev/null && exit 3 +${THIS_SH} -c 'foo=; echo ${foo?}' >/dev/null || exit 4 +${THIS_SH} -c 'foo=1; echo ${foo:?}' >/dev/null || exit 5 +${THIS_SH} -c 'echo ${!?}' 2>/dev/null && exit 6 +${THIS_SH} -c ':& echo ${!?}' >/dev/null || exit 7 +${THIS_SH} -c 'echo ${#?}' >/dev/null || exit 8 +${THIS_SH} -c 'echo ${*?}' 2>/dev/null && exit 9 +${THIS_SH} -c 'echo ${*?}' ${THIS_SH} x >/dev/null || exit 10 +${THIS_SH} -c 'echo ${1?}' 2>/dev/null && exit 11 +${THIS_SH} -c 'echo ${1?}' ${THIS_SH} x >/dev/null || exit 12 +${THIS_SH} -c 'echo ${2?}' ${THIS_SH} x 2>/dev/null && exit 13 +${THIS_SH} -c 'echo ${2?}' ${THIS_SH} x y >/dev/null || exit 14 + +${THIS_SH} -c $'echo $(( x+ )) \n exit 0' ${THIS_SH} 2>/dev/null && exit 15 + +exit 0 diff --git a/tests/posixexp2.tests b/tests/posixexp2.tests new file mode 100644 index 0000000..2bec58e --- /dev/null +++ b/tests/posixexp2.tests @@ -0,0 +1,47 @@ +# From mksh + +set -o posix ; shopt -u xpg_echo + +(echo 1 ${IFS+'}'z}) 2>&- || echo failed in 1 +(echo 2 "${IFS+'}'z}") 2>&- || echo failed in 2 +(echo 3 "foo ${IFS+'bar} baz") 2>&- || echo failed in 3 +(echo -n '4 '; printf '%s\n' "foo ${IFS+"b c"} baz") 2>&- || echo failed in 4 +(echo -n '5 '; printf '%s\n' "foo ${IFS+b c} baz") 2>&- || echo failed in 5 +(echo 6 ${IFS+"}"z}) 2>&- || echo failed in 6 +(echo 7 "${IFS+"}"z}") 2>&- || echo failed in 7 +(echo 8 "${IFS+\"}\"z}") 2>&- || echo failed in 8 +(echo 9 "${IFS+\"\}\"z}") 2>&- || echo failed in 9 +(echo 10 foo ${IFS+'bar} baz'}) 2>&- || echo failed in 10 +(echo 11 "$(echo "${IFS+'}'z}")") 2>&- || echo failed in 11 +(echo 12 "$(echo ${IFS+'}'z})") 2>&- || echo failed in 12 +(echo 13 ${IFS+\}z}) 2>&- || echo failed in 13 +(echo 14 "${IFS+\}z}") 2>&- || echo failed in 14 +u=x; (echo -n '15 '; printf '<%s> ' "foo ${IFS+a"b$u{ {"{{\}b} c ${IFS+d{}} bar" ${IFS-e{}} baz; echo .) 2>&- || echo failed in 15 +l=t; (echo 16 ${IFS+h`echo -n i ${IFS+$l}h`ere}) 2>&- || echo failed in 16 +l=t; (echo 17 ${IFS+h$(echo -n i ${IFS+$l}h)ere}) 2>&- || echo failed in 17 +l=t; (echo 18 "${IFS+h`echo -n i ${IFS+$l}h`ere}") 2>&- || echo failed in 18 +l=t; (echo 19 "${IFS+h$(echo -n i ${IFS+$l}h)ere}") 2>&- || echo failed in 19 +l=t; (echo 20 ${IFS+h`echo -n i "${IFS+$l}"h`ere}) 2>&- || echo failed in 20 +l=t; (echo 21 ${IFS+h$(echo -n i "${IFS+$l}"h)ere}) 2>&- || echo failed in 21 +l=t; (echo 22 "${IFS+h`echo -n i "${IFS+$l}"h`ere}") 2>&- || echo failed in 22 +l=t; (echo 23 "${IFS+h$(echo -n i "${IFS+$l}"h)ere}") 2>&- || echo failed in 23 +key=value; (echo -n '24 '; printf '%s\n' "${IFS+'$key'}") 2>&- || echo failed in 24 +key=value; (echo -n '25 '; printf '%s\n' "${IFS+"'$key'"}") 2>&- || echo failed in 25 # ksh93: “'$key'†+key=value; (echo -n '26 '; printf '%s\n' ${IFS+'$key'}) 2>&- || echo failed in 26 +key=value; (echo -n '27 '; printf '%s\n' ${IFS+"'$key'"}) 2>&- || echo failed in 27 +(echo -n '28 '; printf '%s\n' "${IFS+"'"x ~ x'}'x"'}"x}" #') 2>&- || echo failed in 28 +u=x; (echo -n '29 '; printf '<%s> ' foo ${IFS+a"b$u{ {"{ {\}b} c ${IFS+d{}} bar ${IFS-e{}} baz; echo .) 2>&- || echo failed in 29 +(echo -n '30 '; printf '<%s> ' ${IFS+foo 'b\ +ar' baz}; echo .) 2>&- || (echo failed in 30; echo failed in 31) +(echo -n '32 '; printf '<%s> ' ${IFS+foo "b\ +ar" baz}; echo .) 2>&- || echo failed in 32 +(echo -n '33 '; printf '<%s> ' "${IFS+foo 'b\ +ar' baz}"; echo .) 2>&- || echo failed in 33 +(echo -n '34 '; printf '<%s> ' "${IFS+foo "b\ +ar" baz}"; echo .) 2>&- || echo failed in 34 +(echo -n '35 '; printf '<%s> ' ${v=a\ b} x ${v=c\ d}; echo .) 2>&- || echo failed in 35 +(echo -n '36 '; printf '<%s> ' "${v=a\ b}" x "${v=c\ d}"; echo .) 2>&- || echo failed in 36 +(echo -n '37 '; printf '<%s> ' ${v-a\ b} x ${v-c\ d}; echo .) 2>&- || echo failed in 37 +(echo 38 ${IFS+x'a'y} / "${IFS+x'a'y}" .) 2>&- || echo failed in 38 +foo="x'a'y"; (echo 39 ${foo%*'a'*} / "${foo%*'a'*}" .) 2>&- || echo failed in 39 +foo="a b c"; (echo -n '40 '; printf '<%s> ' "${foo#a}"; echo .) 2>&- || echo failed in 40 diff --git a/tests/posixexp3.sub b/tests/posixexp3.sub new file mode 100644 index 0000000..c40afa9 --- /dev/null +++ b/tests/posixexp3.sub @@ -0,0 +1,52 @@ +set -- 1 2 + +unset var +recho ${var-$@} +recho ${var-"$@"} +recho ${var-$*} +recho ${var-"$*"} + +unset -v a b c d +recho ${a=$@} +recho "$a" +recho ${b="$@"} +recho "$b" +recho ${c=$*} +recho "$c" +recho ${d="$*"} +recho "$d" + +IFS= +unset var +recho ${var-$@} +recho ${var-"$@"} +recho ${var-$*} +recho ${var-"$*"} + +unset -v a b c d +# Posix interp 221 +# there should never be any word splitting because IFS is null +recho ${a=$@} +recho "$a" +recho $a +recho ${b="$@"} +recho "$b" +recho $b +recho ${c=$*} +recho "$c" +recho $c +recho ${d="$*"} +recho "$d" +recho $d + +unset -v a b c d +a=$@ +recho $a +b="$@" +recho $b +c=$* +recho $c +d="$*" +recho $d + +unset -v parameter a b c d diff --git a/tests/posixexp4.sub b/tests/posixexp4.sub new file mode 100644 index 0000000..22bfeca --- /dev/null +++ b/tests/posixexp4.sub @@ -0,0 +1,31 @@ +set -- ' abc' 'def ghi' 'jkl ' + +echo normal IFS +recho $@ +: ${var=$@} +recho $var +unset -v var +recho ${var-$@} + +echo null IFS +IFS= +recho $@ +: ${var=$@} +recho $var +unset -v var +recho ${var-$@} + +echo non-standard IFS +IFS=: +recho $@ +: ${var=$@} +recho $var +unset -v var +recho ${var-$@} # this is inconsistent + +echo unset IFS +recho $@ +: ${var=$@} +recho $var +unset -v var +recho ${var-$@} diff --git a/tests/posixexp5.sub b/tests/posixexp5.sub new file mode 100644 index 0000000..e477bbb --- /dev/null +++ b/tests/posixexp5.sub @@ -0,0 +1,51 @@ +# test suite contribution from Martijn Dekker + +defaultIFS=$IFS +set -o errexit -o noglob +(set -o pipefail) 2>/dev/null && set -o pipefail +teststring=$(printf '\1\2\3\177') +n=0 + +trim_od() { + od -t a | sed -n '1 { s/^0*[[:blank:]]*//; s/[[:blank:]]*$//; p; }' +} + +doTest() { + set -- "$teststring" + eval "$testcmd" + case ${IFS+s}${IFS:+n} in + ( sn ) i=$(printf %s "$IFS" | trim_od) ;; + ( s ) i='(null)' ;; + ( '' ) i='(unset)' ;; + ( * ) echo 'internal error!' >&2; exit 125 ;; + esac + printf '\n%03d: IFS = %s: %s\n' "$((n+=1))" "$i" "$testcmd" + printf %s "$*${foo+/}${foo-}" | trim_od +} + +doAllTests() { + for testcmd in \ + 'unset -v foo; set -- ${foo=$*}' \ + 'unset -v foo; set -- ${foo="$*"}' \ + 'unset -v foo; set -- "${foo=$*}"' \ + \ + 'foo=; set -- ${foo:=$*}' \ + 'foo=; set -- ${foo:="$*"}' \ + 'foo=; set -- "${foo:=$*}"' \ + \ + 'unset -v foo; set -- ${foo=$@}' \ + 'unset -v foo; set -- ${foo="$@"}' \ + 'unset -v foo; set -- "${foo=$@}"' \ + \ + 'foo=; set -- ${foo:=$@}' \ + 'foo=; set -- ${foo:="$@"}' \ + 'foo=; set -- "${foo:=$@}"' + do + doTest "$testcmd" + done +} + +unset -v IFS; doAllTests +IFS=''; doAllTests +IFS='x'; doAllTests +IFS=$defaultIFS; doAllTests diff --git a/tests/posixexp6.sub b/tests/posixexp6.sub new file mode 100644 index 0000000..ed38d53 --- /dev/null +++ b/tests/posixexp6.sub @@ -0,0 +1,57 @@ +var=$'\01\02\03\177' + +bar=${unset:-$var} +recho "$bar" +unset -v bar +bar=${unset:-"$var"} +recho "$bar" + +foo=${parameter:=$var} + +recho "$foo" +recho "$parameter" + +unset -v foo parameter + +foo=${parameter:="$var"} + +recho "$foo" +recho "$parameter" + +unset -v foo parameter + +foo="${parameter:=$var}" + +recho "$foo" +recho "$parameter" + +unset -v foo parameter + +recho ${parameter:=a\ b} +unset -v parameter + +recho ${parameter:="a b"} +unset -v parameter + +v='a b' + +recho ${parameter:=$v} +unset -v parameter + +recho ${parameter:="$v"} +unset -v parameter + +# unsetting IFS here + +set " abc " " def ghi " "jkl " +unset -v IFS var +var=${var-$*}/${var-$*} +printf '[%s]\n' "$var" + +unset -v var +: ${var=$*} +printf '[%s]\n' "$var" + +unset -v var +: ${var:=$*/$*/${var-$*}} +printf '[%s]\n' "$var" diff --git a/tests/posixexp7.sub b/tests/posixexp7.sub new file mode 100644 index 0000000..2e230cf --- /dev/null +++ b/tests/posixexp7.sub @@ -0,0 +1,13 @@ +# test the effect of quotes on the WORD in the posix pattern removal operators +# a here document does not behave the same as double quotes +x=notOK +cat <<EOF +5: ${x#$'not'} +EOF + +echo "${x#'not'}" +echo "${x#$'not'}" + +cat <<EOF +5: $'not\ttoo\nbad' +EOF diff --git a/tests/posixpat.right b/tests/posixpat.right new file mode 100644 index 0000000..deb01bf --- /dev/null +++ b/tests/posixpat.right @@ -0,0 +1,42 @@ +ok 1 +ok 2 +ok 3 +ok 4 +ok 5 +ok 6 +ok 7 +ok 8 +ok 9 +ok 10 +ok 11 +ok 12 +ok 13 +ok 14 +ok 15 +ok 16 +ok 17 +ok 18 +ok 19 +ok 20 +ok 21 +ok -- space +ok -- blank +ok 1 +ok 2 +ok 3 +ok 4 +ok 5 +ok 6 +ok 7 +ok 8 +ok 9 +ok 10 +ok 11 +ok 12 +ok 13 +ok 14 +ok 15 +ok 16 +ok 1 +ok 2 +ok 3 diff --git a/tests/posixpat.tests b/tests/posixpat.tests new file mode 100644 index 0000000..65c557a --- /dev/null +++ b/tests/posixpat.tests @@ -0,0 +1,234 @@ +# A test suite for the POSIX.2 (BRE) pattern matching code +LC_ALL=C +LANG=C + +# First, test POSIX.2 character classes + +case e in +[[:xdigit:]]) echo ok 1;; +esac + +case a in +[[:alpha:]123]) echo ok 2;; +esac + +case 1 in +[[:alpha:]123]) echo ok 3;; +esac + +case 9 in +[![:alpha:]]) echo ok 4;; +esac + +case a in +[:al:]) echo ok 5;; +esac + +# invalid character class expressions are no longer just characters to be +# matched +case a in +[[:al:]) echo bad 6;; +*) echo ok 6;; +esac + +case '!' in +[abc[:punct:][0-9]) echo ok 7;; +esac + +# let's try to match the start of a valid sh identifier +case 'PATH' in +[_[:alpha:]]*) echo ok 8;; +esac + +# let's try to match the first two characters of a valid sh identifier +case PATH in +[_[:alpha:]][_[:alnum:]]*) echo ok 9;; +esac + +# is ^C a cntrl character? +case $'\003' in +[[:cntrl:]]) echo ok 10;; +esac + +# how about A? +case A in +[[:cntrl:]]) echo oops -- cntrl ;; +*) echo ok 11;; +esac + +case 9 in +[[:digit:]]) echo ok 12;; +esac + +case X in +[[:digit:]]) echo oops -- digit;; +*) echo ok 13;; +esac + +case $'\033' in +[[:graph:]]) echo oops -- graph;; +*) echo ok 14;; +esac + +case $'\040' in +[[:graph:]]) echo oops -- graph 2;; +*) echo ok 15;; +esac + +case ' ' in +[[:graph:]]) echo oops -- graph 3;; +*) echo ok 16;; +esac + +case 'aB' in +[[:lower:]][[:upper:]]) echo ok 17;; +esac + +case $'\040' in +[[:print:]]) echo ok 18;; +*) echo oops -- print;; +esac + +case PS3 in +[_[:alpha:]][_[:alnum:]][_[:alnum:]]*) echo ok 19;; +esac + +case a in +[[:alpha:][:digit:]]) echo ok 20;; +*) echo oops - skip brackpat ;; +esac + +case a in +[[:alpha:]\]) echo oops -- dangling backslash in brackpat ;; +*) echo ok 21 ;; +esac + +# what's a newline? is it a blank? a space? +case $'\n' in +[[:blank:]]) echo ok -- blank ;; +[[:space:]]) echo ok -- space ;; +*) echo oops newline ;; +esac + +# OK, what's a tab? is it a blank? a space? +case $'\t' in +[[:blank:]]) echo ok -- blank ;; +[[:space:]]) echo ok -- space ;; +*) echo oops newline ;; +esac + +# let's check out characters in the ASCII range +case $'\377' in +[[:ascii:]]) echo oops -- ascii\?;; +esac + +case 9 in +[1[:alpha:]123]) echo oops 1;; +esac + +# however, an unterminated brace expression containing a valid char class +# that matches had better fail +case a in +[[:alpha:]) echo oops 2;; +esac + +case $'\b' in +[[:graph:]]) echo oops 3;; +esac + +case $'\b' in +[[:print:]]) echo oops 4;; +esac + +case $' ' in +[[:punct:]]) echo oops 5;; +esac + +# Next, test POSIX.2 collating symbols + +case 'a' in +[[.a.]]) echo ok 1;; +esac + +case '-' in +[[.hyphen.]-9]) echo ok 2;; +esac + +case 'p' in +[[.a.]-[.z.]]) echo ok 3;; +esac + +case '-' in +[[.-.]]) echo ok 4;; +esac + +case ' ' in +[[.space.]]) echo ok 5;; +esac + +case ' ' in +[[.grave-accent.]]) echo oops - grave;; +*) echo ok 6;; +esac + +case '4' in +[[.-.]-9]) echo ok 7;; +esac + +# an invalid collating symbol cannot be the first part of a range +case 'c' in +[[.yyz.]-[.z.]]) echo oops - yyz;; +*) echo ok 8;; +esac + +case 'c' in +[[.yyz.][.a.]-z]) echo ok 9;; +esac + +# but when not part of a range is not an error +case 'c' in +[[.yyz.][.a.]-[.z.]]) echo ok 10 ;; +esac + +case 'p' in +[[.a.]-[.Z.]]) echo oops -- bad range ;; +*) echo ok 11;; +esac + +case p in +[[.a.]-[.zz.]p]) echo ok 12;; +*) echo oops -- bad range 2;; +esac + +case p in +[[.aa.]-[.z.]p]) echo ok 13;; +*) echo oops -- bad range 3;; +esac + +case c in +[[.yyz.]cde]) echo ok 14;; +esac + +case abc in +[[.cb.]a-Za]*) echo ok 15;; +esac + +case $'\t' in +[[.space.][.tab.][.newline.]]) echo ok 16;; +esac + +# and finally, test POSIX.2 equivalence classes + +case "abc" in +[[:alpha:]][[=b=]][[:ascii:]]) echo ok 1;; +esac + +case "abc" in +[[:alpha:]][[=B=]][[:ascii:]]) echo oops -- =B=;; +*) echo ok 2 ;; +esac + +case a in +[[=b=]) echo oops;; # an incomplete equiv class is just a string +*) echo ok 3;; +esac diff --git a/tests/posixpipe.right b/tests/posixpipe.right new file mode 100644 index 0000000..8f6c9cb --- /dev/null +++ b/tests/posixpipe.right @@ -0,0 +1,41 @@ +1 +0 +a +real 0.00 +user 0.00 +sys 0.00 +1 +a +real 0.00 +user 0.00 +sys 0.00 +1 +tfunc is a function +tfunc () +{ + time +} +1 +0 +1 +a +real 0.00 +user 0.00 +sys 0.00 +0 +a +real 0.00 +user 0.00 +sys 0.00 +0 +a +real 0.00 +user 0.00 +sys 0.00 +0 +1 +0 +a +real 0.00 +user 0.00 +sys 0.00 diff --git a/tests/posixpipe.tests b/tests/posixpipe.tests new file mode 100644 index 0000000..a2f047a --- /dev/null +++ b/tests/posixpipe.tests @@ -0,0 +1,43 @@ +# Test timed and negated pipelines in bash-4.2 and later +export TIMEFORMAT=$'real %2R\nuser %2U\nsys %2S' + +! +echo $? + +! ! +echo $? + +time ! echo a +echo $? + +! time echo a +echo $? + +tfunc() +{ + time +} + +type tfunc + +! true +echo $? +! ! true +echo $? +! ! ! true +echo $? + +time time echo a +echo $? + +time time -p echo a +echo $? +time -p time echo a +echo $? + +! +echo $? +! ! +echo $? + +time -p -- echo a diff --git a/tests/prec.right b/tests/prec.right new file mode 100644 index 0000000..e6af552 --- /dev/null +++ b/tests/prec.right @@ -0,0 +1,28 @@ +`Say' echos its argument. Its return value is of no interest. +`Truth' echos its argument and returns a TRUE result. +`False' echos its argument and returns a FALSE result. + + Truth 1 && Truth 2 || Say 3 output=12 +( Truth 1 && Truth 2 ) || Say 3 output=12 + + Truth 1 && False 2 || Say 3 output=123 +( Truth 1 && False 2 ) || Say 3 output=123 + + False 1 && Truth 2 || Say 3 output=13 +( False 1 && Truth 2 ) || Say 3 output=13 + + False 1 && False 2 || Say 3 output=13 +( False 1 && False 2 ) || Say 3 output=13 + +Truth 1 || Truth 2 && Say 3 output=13 +Truth 1 || ( Truth 2 && Say 3 ) output=1 + +Truth 1 || False 2 && Say 3 output=13 +Truth 1 || ( False 2 && Say 3 ) output=1 + +False 1 || Truth 2 && Say 3 output=123 +False 1 || ( Truth 2 && Say 3 ) output=123 + +False 1 || False 2 && Say 3 output=12 +False 1 || ( False 2 && Say 3 ) output=12 + diff --git a/tests/precedence b/tests/precedence new file mode 100755 index 0000000..9bbdb97 --- /dev/null +++ b/tests/precedence @@ -0,0 +1,75 @@ +# @(#)precedence_test 1.0 91/07/24 Maarten Litmaath +# test of relative precedences for `&&' and `||' operators + +echo "\`Say' echos its argument. Its return value is of no interest." +case `echo -n` in + '') Say () { echo -n "$*" ; } ;; + *) Say () { echo "$*\c" ; } ;; +esac + +echo "\`Truth' echos its argument and returns a TRUE result." +Truth () { + Say $1; + return 0; +} + +echo "\`False' echos its argument and returns a FALSE result." +False () { + Say $1; + return 1; +} + +echo "" + +cmd1='$open $test1 && $test2 $close || $test3' +cmd2='$test1 || $open $test2 && $test3 $close' + +grouping_sh= +grouping_C='( )' + +test3='Say 3' + +for i in 1 2 +do + eval proto=\$cmd$i + + for test1 in 'Truth 1' 'False 1' + do + for test2 in 'Truth 2' 'False 2' + do + for precedence in sh C + do + eval set x \$grouping_$precedence + shift + open=${1-' '} + close=${2-' '} + eval cmd=\""$proto"\" + Say "$cmd output=" + output=`eval "$cmd"` + Say "$output" + read correct || { echo 'Input fubar. Abort.' >&2; exit 1; } + test "X$output" = "X$correct" || echo " correct=$correct" + echo '' + done + + echo '' + done + done +done << EOF +12 +12 +123 +123 +13 +13 +13 +13 +13 +1 +13 +1 +123 +123 +12 +12 +EOF diff --git a/tests/printf.right b/tests/printf.right new file mode 100644 index 0000000..593f084 --- /dev/null +++ b/tests/printf.right @@ -0,0 +1,298 @@ +printf: usage: printf [-v var] format [arguments] +printf: usage: printf [-v var] format [arguments] +10 + one +one\ctwo +4\.2 +no newline now newline +% +% +%d +A +unquoted +unquoted quoted +unquoted quoted +this\&that +1 2 3 4 5 +onestring 0 0 0 +onestring 0 0 0.00 +--4.2 -- +--4.2 -- +-- +^@81-- +-- A-- +-- A-- +A7 +A7 +A7 +A7 +A7 +--\"abcd\"-- +--\'abcd\'-- +--a\x-- +./printf.tests: line 82: printf: missing hex digit for \x +--\x-- +---- +---- +--4.2 +--4\.2-- +--\-- + + + 4.4BSD + 4.4BSD + 4.4BSD + 4.4BSD +4.4BSD +4.4BSD + 4.4BSD +--4.4BSD -- + 4. +4.4 +--4.4BSD -- +255 255 255 0377 0xff 0xFF +255 255 255 0377 0xff 0XFF +255 255 255 0377 0xff 0xFF +255 255 255 0377 0xff 0XFF + 42 + -42 + 42 + -42 +4.20 +4.20 + 4.2 +4.20 +4.20 + 4.2 +4.200000E+00 +4.200000e+00 +4.2E+00 +4.2e+00 +4.2 +4.2 + 4.2 + 4.2 +115 +115 +0163 +0163 +0x73 +0X73 +115.00 +115.00 +-- abcd-- +-- abcd-- +-- abcdefghij-- +-- abcdefghij-- +'abcd' +\'abcd\' +\abcd\ +\abcd\ +26 +26 +26 +./printf.tests: line 206: printf: `%10': missing format character +./printf.tests: line 207: printf: `M': invalid format character +ab./printf.tests: line 210: printf: `y': invalid format character +./printf.tests: line 213: printf: GNU: invalid number +0 +./printf.tests: line 214: printf: GNU: invalid number +0 +- +(foo )(bar ) +0 + ab cd ef +13 +^G +^G +^@7 +^Ge +"? +00001 +00001 + 1 +1 +0 +0 + 0 + 0 +4 +4 + 4 + 4 +0.000000 +0.000000 +0.00 +0.00 +4.000000 +4.000000 +4.00 +4.00 +0.000000E+00 +0.000000e+00 +0.00E+00 +0.00e+00 +4.000000E+00 +4.000000e+00 +4.00E+00 +4.00e+00 +9B3A59A5 +q +'' +'' +s + + +b + + +xx +xx +< >< > + one +one\ctwo +4\.2 +no newline now newline +% +% +%d +A +unquoted +unquoted quoted +unquoted quoted +this\&that +1 2 3 4 5 +onestring 0 0 0 +onestring 0 0 0.00 +--4.2 -- +--4.2 -- +-- A-- +-- A-- +A7 +A7 +A7 +--\"abcd\"-- +--\'abcd\'-- +--a\x-- +./printf1.sub: line 94: printf: missing hex digit for \x +--\x-- +---- +---- +--4.2 +--4\.2-- +--\-- + + + 4.4BSD + 4.4BSD + 4.4BSD + 4.4BSD +4.4BSD +4.4BSD + 4.4BSD +--4.4BSD -- + 4. +4.4 +--4.4BSD -- +255 255 255 0377 0xff 0xFF +255 255 255 0377 0xff 0XFF +255 255 255 0377 0xff 0xFF +255 255 255 0377 0xff 0XFF + 42 + -42 + 42 + -42 +4.20 +4.20 + 4.2 +4.20 +4.20 + 4.2 +4.200000E+00 +4.200000e+00 +4.2E+00 +4.2e+00 +4.2 +4.2 + 4.2 + 4.2 +115 +115 +0163 +0163 +0x73 +0X73 +115.00 +115.00 +-- abcd-- +-- abcd-- +-- abcdefghij-- +-- abcdefghij-- +'abcd' +\'abcd\' +\abcd\ +\abcd\ +26 +26 +26 +./printf1.sub: line 280: printf: `%10': missing format character +./printf1.sub: line 281: printf: `M': invalid format character +./printf1.sub: line 284: printf: `y': invalid format character +./printf1.sub: line 287: printf: GNU: invalid number +0 +./printf1.sub: line 289: printf: GNU: invalid number +0 +- +(foo )(bar ) +0 + ab cd ef +13 +^G +^G +^Ge +"? +16:09:15 +./printf3.sub: line 14: printf: warning: `Z': invalid time format specification +%(abde)Z +30-May-2010 16:09:15 +05/30/10 15:09:15 +current time: 2010-05-30 04:09:15 PM +epoch time: 1969-12-31 07:00:00 PM -0500 +random time: 2010-05-30 04:09:15 PM -0400 +local time: Sun May 30 16:09:15 EDT 2010 +Sun May 30 16:09:15 EDT 2010 date-style time +05/30/10 (foo) 16:09:15 date-style time +x 123x +x 123x +x 123x +x 123x +x 123x +x 123x +x 123.00x +x 123.00x +x 123.00x +x 123.00x +x123 x +x123 x +x+00001e+02x +x+00001e+02x +x+000000123x +x+000000123x +x+00001e+02x +x+00001e+02x +x +123x +x +123x +x +123x +x +123x +x 7bx +x 7bx +x+123 x +x+123 x +x+123 x +x+123 x +-123.000000 +-123.000000 +x +123x +x +123x +x +123x +x +123x diff --git a/tests/printf.tests b/tests/printf.tests new file mode 100644 index 0000000..9dbac6f --- /dev/null +++ b/tests/printf.tests @@ -0,0 +1,321 @@ +LC_ALL=C +LC_NUMERIC=C + +# these should output error messages -- the format is required +printf +printf -- + +# these should output nothing +printf "" +printf -- "" + +# in the future this may mean to put the output into VAR, but for +# now it is an error +# 2005-03-15 no longer an error +unset var +printf -v var "%10d" $RANDOM +echo ${#var} + +# this should expand escape sequences in the format string, nothing else +printf "\tone\n" + +# this should not cut off output after the \c +printf "one\ctwo\n" + +# and unrecognized backslash escapes should have the backslash preserverd +printf "4\.2\n" + +printf "no newline " ; printf "now newline\n" + +# %% -> % +printf "%%\n" + +# this was a bug caused by pre-processing the string for backslash escapes +# before doing the `%' format processing -- all versions before bash-2.04 +printf "\045" ; echo +printf "\045d\n" + +# simple character output +printf "%c\n" ABCD + +# test simple string output +printf "%s\n" unquoted + +# test quoted string output +printf "%s %q\n" unquoted quoted +printf "%s%10q\n" unquoted quoted + +printf "%q\n" 'this&that' + +# make sure the format string is reused to use up arguments +printf "%d " 1 2 3 4 5; printf "\n" + +# make sure that extra format characters get null arguments +printf "%s %d %d %d\n" onestring + +printf "%s %d %u %4.2f\n" onestring + +printf -- "--%s %s--\n" 4.2 '' +printf -- "--%s %s--\n" 4.2 + +# test %b escapes + +# 8 is a non-octal digit, so the `81' should be output +printf -- "--%b--\n" '\n\081' + +printf -- "--%b--\n" '\t\0101' +printf -- "--%b--\n" '\t\101' + +# these should all display `A7' +echo -e "\01017" +echo -e "\x417" + +printf "%b\n" '\01017' +printf "%b\n" '\1017' +printf "%b\n" '\x417' + +printf -- "--%b--\n" '\"abcd\"' +printf -- "--%b--\n" "\'abcd\'" + +printf -- "--%b--\n" 'a\\x' + +printf -- "--%b--\n" '\x' + +Z1=$(printf -- "%b\n" '\a\b\e\f\r\v') +Z2=$'\a\b\e\f\r\v' + +if [ "$Z1" != "$Z2" ]; then + echo "whoops: printf %b and $'' differ" >&2 +fi +unset Z1 Z2 + +printf -- "--%b--\n" '' +printf -- "--%b--\n" + +# the stuff following the \c should be ignored, as well as the rest +# of the format string +printf -- "--%b--\n" '4.2\c5.4\n'; printf "\n" + +# unrecognized escape sequences should by displayed unchanged +printf -- "--%b--\n" '4\.2' + +# a bare \ should not be processed as an escape sequence +printf -- "--%b--\n" '\' + +# make sure extra arguments are ignored if the format string doesn't +# actually use them +printf "\n" 4.4 BSD +printf " " 4.4 BSD ; printf "\n" + +# make sure that a fieldwidth and precision of `*' are handled right +printf "%10.8s\n" 4.4BSD +printf "%*.*s\n" 10 8 4.4BSD + +printf "%10.8q\n" 4.4BSD +printf "%*.*q\n" 10 8 4.4BSD + +printf "%6b\n" 4.4BSD +printf "%*b\n" 6 4.4BSD + +# we handle this crap with homemade code in printf.def +printf "%10b\n" 4.4BSD +printf -- "--%-10b--\n" 4.4BSD +printf "%4.2b\n" 4.4BSD +printf "%.3b\n" 4.4BSD +printf -- "--%-8b--\n" 4.4BSD + +# test numeric conversions -- these four lines should echo identically +printf "%d %u %i 0%o 0x%x 0x%X\n" 255 255 255 255 255 255 +printf "%d %u %i %#o %#x %#X\n" 255 255 255 255 255 255 + +printf "%ld %lu %li 0%o 0x%x 0x%X\n" 255 255 255 255 255 255 +printf "%ld %lu %li %#o %#x %#X\n" 255 255 255 255 255 255 + +printf "%10d\n" 42 +printf "%10d\n" -42 + +printf "%*d\n" 10 42 +printf "%*d\n" 10 -42 + +# test some simple floating point formats +printf "%4.2f\n" 4.2 +printf "%#4.2f\n" 4.2 +printf "%#4.1f\n" 4.2 + +printf "%*.*f\n" 4 2 4.2 +printf "%#*.*f\n" 4 2 4.2 +printf "%#*.*f\n" 4 1 4.2 + +printf "%E\n" 4.2 +printf "%e\n" 4.2 +printf "%6.1E\n" 4.2 +printf "%6.1e\n" 4.2 + +printf "%G\n" 4.2 +printf "%g\n" 4.2 +printf "%6.2G\n" 4.2 +printf "%6.2g\n" 4.2 + +# test some of the more esoteric features of POSIX.1 printf +printf "%d\n" "'string'" +printf "%d\n" '"string"' + +printf "%#o\n" "'string'" +printf "%#o\n" '"string"' + +printf "%#x\n" "'string'" +printf "%#X\n" '"string"' + +printf "%6.2f\n" "'string'" +printf "%6.2f\n" '"string"' + +# output from these two lines had better be the same +printf -- "--%6.4s--\n" abcdefghijklmnopqrstuvwxyz +printf -- "--%6.4b--\n" abcdefghijklmnopqrstuvwxyz + +# and these two also +printf -- "--%12.10s--\n" abcdefghijklmnopqrstuvwxyz +printf -- "--%12.10b--\n" abcdefghijklmnopqrstuvwxyz + +# tests for translating \' to ' and \\ to \ +# printf translates \' to ' in the format string... +printf "\'abcd\'\n" + +# but not when the %b format specification is used +printf "%b\n" \\\'abcd\\\' + +# but both translate \\ to \ +printf '\\abcd\\\n' +printf "%b\n" '\\abcd\\' + +# this was reported as a bug in bash-2.03 +# these three lines should all echo `26' +printf "%d\n" 0x1a +printf "%d\n" 032 +printf "%d\n" 26 + +# error messages + +# this should be an overflow, but error messages vary between systems +# printf "%lu\n" 4294967296 + +# ...but we cannot use this because some systems (SunOS4, for example), +# happily ignore overflow conditions in strtol(3) +#printf "%ld\n" 4294967296 + +printf "%10" +printf "ab%Mcd\n" + +# this caused an infinite loop in older versions of printf +printf "%y" 0 + +# these should print a warning and `0', according to POSIX.2 +printf "%d\n" GNU +printf "%o\n" GNU + +# failures in all bash versions through bash-2.05 +printf "%.0s" foo +printf "%.*s" 0 foo + +printf '%.0b-%.0s\n' foo bar +printf '(%*b)(%*s)\n' -4 foo -4 bar + +format='%'`printf '%0100384d' 0`'d\n' +printf $format 0 + +# failures in all bash versions through bash-3.0 - undercounted characters +unset vv +printf " %s %s %s \n%n" ab cd ef vv +echo "$vv" + +# this doesn't work with printf(3) on all systems +#printf "%'s\n" foo + +# test cases from an austin-group list discussion +# prints ^G as an extension +printf '%b\n' '\7' + +# prints ^G +printf '%b\n' '\0007' + +# prints NUL then 7 +printf '\0007\n' + +# prints no more than two hex digits +printf '\x07e\n' + +# additional backslash escapes +printf '\"\?\n' + +# failures with decimal precisions until after bash-3.1 +printf '%0.5d\n' 1 + +printf '%05d\n' 1 +printf '%5d\n' 1 +printf '%0d\n' 1 + +# failures with various floating point formats and 0 after bash-3.2 + +printf "%G\n" 0 +printf "%g\n" 0 +printf "%4.2G\n" 0 +printf "%4.2g\n" 0 + +printf "%G\n" 4 +printf "%g\n" 4 +printf "%4.2G\n" 4 +printf "%4.2g\n" 4 + +printf "%F\n" 0 +printf "%f\n" 0 +printf "%4.2F\n" 0 +printf "%4.2f\n" 0 + +printf "%F\n" 4 +printf "%f\n" 4 +printf "%4.2F\n" 4 +printf "%4.2f\n" 4 + +printf "%E\n" 0 +printf "%e\n" 0 +printf "%4.2E\n" 0 +printf "%4.2e\n" 0 + +printf "%E\n" 4 +printf "%e\n" 4 +printf "%4.2E\n" 4 +printf "%4.2e\n" 4 + +printf "%08X\n" 2604292517 + +# make sure these format specifiers all output '' for empty string arguments +echo q +printf "%q\n" "" +printf "%q\n" + +echo s +printf "%s\n" '' +printf "%s\n" + +echo b +printf "%b\n" '' +printf "%b\n" + +# bug in bash versions up to and including bash-3.2 +v=yyy +printf -v var "%s" '/current/working/directory/*.@(m3|i3|ig|mg)' +shopt -s nullglob extglob +echo "x$(printf "%b" @(hugo))x" +printf -v var "%b" @(hugo); echo "x${var}x" + +# make sure that missing arguments are always handled like the empty string +printf "<%3s><%3b>\n" + +# tests variable assignment with -v +${THIS_SH} ./printf1.sub + +${THIS_SH} ./printf2.sub + +${THIS_SH} ./printf3.sub + +${THIS_SH} ./printf4.sub diff --git a/tests/printf1.sub b/tests/printf1.sub new file mode 100644 index 0000000..52612d5 --- /dev/null +++ b/tests/printf1.sub @@ -0,0 +1,335 @@ +LC_ALL=C +LC_NUMERIC=C + +unset vv + +# this should expand escape sequences in the format string, nothing else +printf -v vv "\tone\n" +printf "%s" "$vv" + +# this should not cut off output after the \c +printf -v vv "one\ctwo\n" +printf "%s" "$vv" + +# and unrecognized backslash escapes should have the backslash preserverd +printf -v vv "4\.2\n" +printf "%s" "$vv" + +printf -v vv "no newline " ; printf "%s" "$vv" ; printf -v vv "now newline\n" +printf "%s" "$vv" + +# %% -> % +printf -v vv "%%\n" +printf "%s" "$vv" + +# this was a bug caused by pre-processing the string for backslash escapes +# before doing the `%' format processing -- all versions before bash-2.04 +printf -v vv "\045" +printf "%s" "$vv" +echo +printf -v vv "\045d\n" +printf "%s" "$vv" + +# simple character output +printf -v vv "%c\n" ABCD +printf "%s" "$vv" + +# test simple string output +printf -v vv "%s\n" unquoted +printf "%s" "$vv" + +# test quoted string output +printf -v vv "%s %q\n" unquoted quoted +printf "%s" "$vv" +printf -v vv "%s%10q\n" unquoted quoted +printf "%s" "$vv" + +printf -v vv "%q\n" 'this&that' +printf "%s" "$vv" + +# make sure the format string is reused to use up arguments +printf -v vv "%d " 1 2 3 4 5 +printf "%s" "$vv" +echo + +# make sure that extra format characters get null arguments +printf -v vv "%s %d %d %d\n" onestring +printf "%s" "$vv" + +printf -v vv "%s %d %u %4.2f\n" onestring +printf "%s" "$vv" + +printf -v vv -- "--%s %s--\n" 4.2 '' +printf "%s" "$vv" +printf -v vv -- "--%s %s--\n" 4.2 +printf "%s" "$vv" + +# test %b escapes + +# 8 is a non-octal digit, so the `81' should be output +#printf -v vv -- "--%b--\n" '\n\081' +#printf "%s" "$vv" + +printf -v vv -- "--%b--\n" '\t\0101' +printf "%s" "$vv" +printf -v vv -- "--%b--\n" '\t\101' +printf "%s" "$vv" + +# these should all display `A7' +printf -v vv "%b\n" '\01017' +printf "%s" "$vv" +printf -v vv "%b\n" '\1017' +printf "%s" "$vv" +printf -v vv "%b\n" '\x417' +printf "%s" "$vv" + +printf -v vv -- "--%b--\n" '\"abcd\"' +printf "%s" "$vv" +printf -v vv -- "--%b--\n" "\'abcd\'" +printf "%s" "$vv" + +printf -v vv -- "--%b--\n" 'a\\x' +printf "%s" "$vv" + +printf -v vv -- "--%b--\n" '\x' +printf "%s" "$vv" + +Z1=$(printf -- "%b\n" '\a\b\e\f\r\v') +Z2=$'\a\b\e\f\r\v' + +if [ "$Z1" != "$Z2" ]; then + printf "%s" "whoops: printf -v vv %b and $'' differ" >&2 +fi +unset Z1 Z2 + +printf -v vv -- "--%b--\n" '' +printf "%s" "$vv" +printf -v vv -- "--%b--\n" +printf "%s" "$vv" + +# the stuff following the \c should be ignored, as well as the rest +# of the format string +printf -v vv -- "--%b--\n" '4.2\c5.4\n' +printf "%s" "$vv" +echo + +# unrecognized escape sequences should by displayed unchanged +printf -v vv -- "--%b--\n" '4\.2' +printf "%s" "$vv" + +# a bare \ should not be processed as an escape sequence +printf -v vv -- "--%b--\n" '\' +printf "%s" "$vv" + +# make sure extra arguments are ignored if the format string doesn't +# actually use them +printf -v vv "\n" 4.4 BSD +printf "%s" "$vv" +printf -v vv " " 4.4 BSD +printf "%s" "$vv" +echo + +# make sure that a fieldwidth and precision of `*' are handled right +printf -v vv "%10.8s\n" 4.4BSD +printf "%s" "$vv" +printf -v vv "%*.*s\n" 10 8 4.4BSD +printf "%s" "$vv" + +printf -v vv "%10.8q\n" 4.4BSD +printf "%s" "$vv" +printf -v vv "%*.*q\n" 10 8 4.4BSD +printf "%s" "$vv" + +printf -v vv "%6b\n" 4.4BSD +printf "%s" "$vv" +printf -v vv "%*b\n" 6 4.4BSD +printf "%s" "$vv" + +# we handle this crap with homemade code in printf -v vv.def +printf -v vv "%10b\n" 4.4BSD +printf "%s" "$vv" +printf -v vv -- "--%-10b--\n" 4.4BSD +printf "%s" "$vv" +printf -v vv "%4.2b\n" 4.4BSD +printf "%s" "$vv" +printf -v vv "%.3b\n" 4.4BSD +printf "%s" "$vv" +printf -v vv -- "--%-8b--\n" 4.4BSD +printf "%s" "$vv" + +# test numeric conversions -- these four lines should printf "%s" identically +printf -v vv "%d %u %i 0%o 0x%x 0x%X\n" 255 255 255 255 255 255 +printf "%s" "$vv" +printf -v vv "%d %u %i %#o %#x %#X\n" 255 255 255 255 255 255 +printf "%s" "$vv" + +printf -v vv "%ld %lu %li 0%o 0x%x 0x%X\n" 255 255 255 255 255 255 +printf "%s" "$vv" +printf -v vv "%ld %lu %li %#o %#x %#X\n" 255 255 255 255 255 255 +printf "%s" "$vv" + +printf -v vv "%10d\n" 42 +printf "%s" "$vv" +printf -v vv "%10d\n" -42 +printf "%s" "$vv" + +printf -v vv "%*d\n" 10 42 +printf "%s" "$vv" +printf -v vv "%*d\n" 10 -42 +printf "%s" "$vv" + +# test some simple floating point formats +printf -v vv "%4.2f\n" 4.2 +printf "%s" "$vv" +printf -v vv "%#4.2f\n" 4.2 +printf "%s" "$vv" +printf -v vv "%#4.1f\n" 4.2 +printf "%s" "$vv" + +printf -v vv "%*.*f\n" 4 2 4.2 +printf "%s" "$vv" +printf -v vv "%#*.*f\n" 4 2 4.2 +printf "%s" "$vv" +printf -v vv "%#*.*f\n" 4 1 4.2 +printf "%s" "$vv" + +printf -v vv "%E\n" 4.2 +printf "%s" "$vv" +printf -v vv "%e\n" 4.2 +printf "%s" "$vv" +printf -v vv "%6.1E\n" 4.2 +printf "%s" "$vv" +printf -v vv "%6.1e\n" 4.2 +printf "%s" "$vv" + +printf -v vv "%G\n" 4.2 +printf "%s" "$vv" +printf -v vv "%g\n" 4.2 +printf "%s" "$vv" +printf -v vv "%6.2G\n" 4.2 +printf "%s" "$vv" +printf -v vv "%6.2g\n" 4.2 +printf "%s" "$vv" + +# test some of the more esoteric features of POSIX.1 printf -v vv +printf -v vv "%d\n" "'string'" +printf "%s" "$vv" +printf -v vv "%d\n" '"string"' +printf "%s" "$vv" + +printf -v vv "%#o\n" "'string'" +printf "%s" "$vv" +printf -v vv "%#o\n" '"string"' +printf "%s" "$vv" + +printf -v vv "%#x\n" "'string'" +printf "%s" "$vv" +printf -v vv "%#X\n" '"string"' +printf "%s" "$vv" + +printf -v vv "%6.2f\n" "'string'" +printf "%s" "$vv" +printf -v vv "%6.2f\n" '"string"' +printf "%s" "$vv" + +# output from these two lines had better be the same +printf -v vv -- "--%6.4s--\n" abcdefghijklmnopqrstuvwxyz +printf "%s" "$vv" +printf -v vv -- "--%6.4b--\n" abcdefghijklmnopqrstuvwxyz +printf "%s" "$vv" + +# and these two also +printf -v vv -- "--%12.10s--\n" abcdefghijklmnopqrstuvwxyz +printf "%s" "$vv" +printf -v vv -- "--%12.10b--\n" abcdefghijklmnopqrstuvwxyz +printf "%s" "$vv" + +# tests for translating \' to ' and \\ to \ +# printf -v vv translates \' to ' in the format string... +printf -v vv "\'abcd\'\n" +printf "%s" "$vv" + +# but not when the %b format specification is used +printf -v vv "%b\n" \\\'abcd\\\' +printf "%s" "$vv" + +# but both translate \\ to \ +printf -v vv '\\abcd\\\n' +printf "%s" "$vv" +printf -v vv "%b\n" '\\abcd\\' +printf "%s" "$vv" + +# this was reported as a bug in bash-2.03 +# these three lines should all printf "%s" `26' +printf -v vv "%d\n" 0x1a +printf "%s" "$vv" +printf -v vv "%d\n" 032 +printf "%s" "$vv" +printf -v vv "%d\n" 26 +printf "%s" "$vv" + +# error messages + +# this should be an overflow, but error messages vary between systems +# printf -v vv "%lu\n" 4294967296 + +# ...but we cannot use this because some systems (SunOS4, for example), +# happily ignore overflow conditions in strtol(3) +#printf -v vv "%ld\n" 4294967296 + +printf -v vv "%10" +printf -v vv "ab%Mcd\n" + +# this caused an infinite loop in older versions of printf -v vv +printf -v vv "%y" 0 + +# these should print a warning and `0', according to POSIX.2 +printf -v vv "%d\n" GNU +printf "%s" "$vv" +printf -v vv "%o\n" GNU +printf "%s" "$vv" + +# failures in all bash versions through bash-2.05 +printf -v vv "%.0s" foo +printf "%s" "$vv" +printf -v vv "%.*s" 0 foo +printf "%s" "$vv" + +printf -v vv '%.0b-%.0s\n' foo bar +printf "%s" "$vv" +printf -v vv '(%*b)(%*s)\n' -4 foo -4 bar +printf "%s" "$vv" + +format='%'`printf '%0100384d' 0`'d\n' +printf -v vv $format 0 +printf "%s" "$vv" + +# failures in all bash versions through bash-3.0 - undercounted characters +unset vv +printf -v vv " %s %s %s \n%n" ab cd ef vvv +printf "%s" "$vv" +echo $vvv + +# this doesn't work with printf -v vv(3) on all systems +#printf -v vv "%'s\n" foo + +# test cases from an austin-group list discussion +# prints ^G as an extension +printf -v vv '%b\n' '\7' +printf "%s" "$vv" + +# prints ^G +printf -v vv '%b\n' '\0007' +printf "%s" "$vv" + +# prints NUL then 7 +#printf -v vv '\0007\n' +#printf "%s" "$vv" + +# prints no more than two hex digits +printf -v vv '\x07e\n' +printf "%s" "$vv" + +# additional backslash escapes +printf -v vv '\"\?\n' +printf "%s" "$vv" diff --git a/tests/printf2.sub b/tests/printf2.sub new file mode 100644 index 0000000..45c48d4 --- /dev/null +++ b/tests/printf2.sub @@ -0,0 +1,7 @@ +unset LC_ALL LC_CTYPE +export LANG=en_US.UTF-8 + +case $(printf %d\\n \'À) in +192) exit 0;; +*) echo "printf2.sub: multibyte character conversion failed" >&2 ; exit 2 ;; +esac diff --git a/tests/printf3.sub b/tests/printf3.sub new file mode 100644 index 0000000..d45e101 --- /dev/null +++ b/tests/printf3.sub @@ -0,0 +1,62 @@ +LC_ALL=C +LANG=C + +SHELLSTART=$(date +%s) +SECS=1275250155 +export TZ=EST5EDT + +case $SHELLSTART in +*s*) SHELLSTART=$EPOCHSECONDS ; DATESECS=false ;; # take a shot +*) DATESECS=true ;; +esac + +printf "%()T\n" $SECS +printf "%(abde)Z\n" -1 + +printf "%(%e-%b-%Y %T)T\n" $SECS + +printf -v v1 "%(%e-%b-%Y %T)T\n" $( $DATESECS && date +%s || echo $EPOCHSECONDS ) +printf -v v2 "%(%e-%b-%Y %T)T\n" -1 + +case $v1 in +$v2) ;; +*) echo "current time and -1 possible mismatch|$v1|$v2|" >&2 ;; +esac +unset v1 v2 + +v1=$(date +%s) +printf -v v2 "%(%s)T" -1 + +case $v1 in +$v2) ;; +*) echo "current time mismatch:$v1|$v2|" >&2 ;; +esac +unset v1 v2 + +printf "%(%x %X)T\n" $(( $SECS - 3600 )) + +printf -v v1 "%(%F %r)T\n" $SHELLSTART +printf -v v2 "%(%F %r)T\n" -2 + +case $v1 in +$v2) ;; +*) echo "shell start time and -2 possible mismatch|$v1|$v2|" >&2 ;; +esac +unset v1 v2 + +printf "current time: %(%F %r)T\n" $SECS + +printf "epoch time: %(%F %r %z)T\n" 0 +printf "random time: %(%F %r %z)T\n" $SECS + +printf "local time: %(%a %b %e %H:%M:%S %Z %Y)T\n" $SECS + +# test fieldwidth, justification, precision +printf "%-40.50(%a %b %e %H:%M:%S %Z %Y)T date-style time\n" $SECS + +# test fieldwidth, justification, precision, embedded parens +printf "%-40.50(%x (foo) %X)T date-style time\n" $SECS + +# problem introduced in bash-4.2 patch 5 +unset TZ +printf '%(%Y-%m-%d %H:%M:%S %Z)T\n' >/dev/null diff --git a/tests/printf4.sub b/tests/printf4.sub new file mode 100644 index 0000000..2ffd997 --- /dev/null +++ b/tests/printf4.sub @@ -0,0 +1,69 @@ +# Problems with padding, field widths, and `+' through bash-4.2 + +printf "x%10.0fx\n" 123 +printf -v foo "x%10.0fx" 123 +echo "$foo" + +printf "x%10.0fx\n" 123 +printf -v foo "x%10.0fx" 123 +echo "$foo" + +printf "x%10.fx\n" 123 +printf -v foo "x%10.fx" 123 +echo "$foo" + +printf "x%10.2fx\n" 123 +printf -v foo "x%10.2fx" 123 +echo "$foo" + +printf "x%10.02fx\n" 123 +printf -v foo "x%10.02fx" 123 +echo "$foo" + +printf "x%-010.0fx\n" 123 +printf -v foo "x%-010.0fx" 123 +echo "$foo" + +printf "x%+010.0ex\n" 123 +printf -v foo "x%+010.0ex" 123 +echo "$foo" + +printf "x%+010.0fx\n" 123 +printf -v foo "x%+010.0fx" 123 +echo "$foo" + +printf "x%+010.0gx\n" 123 +printf -v foo "x%+010.0gx" 123 +echo "$foo" + +printf "x%+010.0dx\n" 123 +printf -v foo "x%+010.0dx" 123 +echo "$foo" + +printf "x%+010.0ldx\n" 123 +printf -v foo "x%+010.0ldx" 123 +echo "$foo" + +printf "x%+010.0xx\n" 123 +printf -v foo "x%+010.0xx" 123 +echo "$foo" + +printf "x%-+10.0fx\n" 123 +printf -v foo "x%-+10.0fx" 123 +echo "$foo" + +printf "x%-+10.0dx\n" 123 +printf -v foo "x%-+10.0dx" 123 +echo "$foo" + +printf "%f\n" -123 +printf -v foo "%f" -123 +echo "$foo" + +printf "x%+10.0fx\n" 123 +printf -v foo "x%+10.0fx" 123 +echo "$foo" + +printf "x%+10.0dx\n" 123 +printf -v foo "x%+10.0dx" 123 +echo "$foo" diff --git a/tests/procsub.right b/tests/procsub.right new file mode 100644 index 0000000..cf1dbb1 --- /dev/null +++ b/tests/procsub.right @@ -0,0 +1,29 @@ +test1 +foo +test2 +test3 +test4 +8 +test5 +test6 +test7 +test8 +test8a +test9 +hi +bye +l8r +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +intern +1 +0 +0 +0 +0 +extern +1 +0 +0 +0 +0 +123 diff --git a/tests/procsub.tests b/tests/procsub.tests new file mode 100644 index 0000000..01ba46a --- /dev/null +++ b/tests/procsub.tests @@ -0,0 +1,105 @@ +# process substitution constructs that have caused problems in the past +. ./test-glue-functions + +eval cat <(echo test1) +eval "echo foo;cat" <(echo test2) + +unset f +f=<(echo test3); cat "$f" + +unset f +eval f=<(echo test4) "; cat \$f" + +unset f + +FN=$TMPDIR/bashtest-procsub-$$ +cat >"$FN" <<EOF +echo "test 12" | wc -c | _cut_leading_spaces +cat "\$1" +EOF + +source "$FN" <(echo test5) +rm -f "$FN" +unset FN + +cat <( echo test6 ) <( echo test7 ) +cat <( echo test8 ; sleep 2; echo test8a ) <( echo test9 ) + +# Zev Weiss 11/7/2012 +fn() { cat | cat "$1"; } +fn <(:) < /dev/null + +unset -f fn + +f1(){ + cat $1 + date >/dev/null +} +f2(){ + date >/dev/null + cat $1 +} +cat <(echo hi) +f1 <(echo bye) +f2 <(echo l8r) + +unset -f f1 f2 + +# set up conditions for test +ulimit -n 256 + +bug() +{ +c=$(ulimit -n) +let c+=100 +while let c-- +do + while read -ru3 x + do + echo -n : + done 3< <(echo x) +done +echo +} + +bug +unset -f bug + +count_lines() +{ + wc -l < $1 + +# case "$1" in +# *sh-np*) [ -e "$1" ] || { echo 0; echo 0; echo 0; echo 0; return; } ;; +# *) ;; +# esac + + wc -l < $1 + wc -l < $1 + true | wc -l < $1 + wc -l < $1 +} + +echo intern +count_lines <(date) | _cut_leading_spaces +unset -f count_lines + +echo extern +FN=$TMPDIR/bashtest-$$ +cat >$FN << \EOF +wc -l < $1 +wc -l < $1 +wc -l < $1 +true | wc -l < $1 +wc -l < $1 +EOF + +${THIS_SH} -c "source $FN <(date)" | _cut_leading_spaces +rm -f $FN + +moo() { ls -l "$1" >/dev/null; ls -l "$1" >/dev/null; }; moo >(true) +moo() { ls -al "$1" >/dev/null; (true); ls -al "$1" >/dev/null; }; moo >(true) + +unset -f moo + +${THIS_SH} ./procsub1.sub diff --git a/tests/procsub1.sub b/tests/procsub1.sub new file mode 100644 index 0000000..0e68f3b --- /dev/null +++ b/tests/procsub1.sub @@ -0,0 +1,5 @@ +# make sure we can wait for the last process substitution, since it sets $! +cat <(exit 123) >/dev/null + +wait "$!" +echo $? diff --git a/tests/quote.right b/tests/quote.right new file mode 100644 index 0000000..e4eb9bb --- /dev/null +++ b/tests/quote.right @@ -0,0 +1,122 @@ +Single Quote +foo +bar +foo +bar +foo\ +bar +Double Quote +foo +bar +foo +bar +foobar +Backslash Single Quote +foo bar +foo bar +foobar +Backslash Double Quote +foo bar +foo bar +foobar +Double Quote Backslash Single Quote +foo +bar +foo +bar +foobar +Dollar Paren Single Quote +foo bar +foo bar +foo\ bar +Dollar Paren Double Quote +foo bar +foo bar +foobar +Double Quote Dollar Paren Single Quote +foo +bar +foo +bar +foo\ +bar +argv[1] = <foo \\^Jbar> +argv[1] = <foo \^Jbar> +argv[1] = <sed> argv[2] = <-e> argv[3] = <s/[^I:]/\^J/g> +argv[1] = <sed> argv[2] = <-e> argv[3] = <s/[^I:]//g> +argv[1] = <foo\^Jbar> +argv[1] = <foobar> +argv[1] = <foo\^Jbar> +b +a +b +c +argv[1] = <a\> +argv[2] = <b> +argv[1] = <$> +argv[2] = <bab> +argv[1] = <$foo> +argv[2] = <bab> +argv[1] = <$foo> +argv[2] = <bab> +argv[1] = <`> +argv[2] = <ab> +argv[1] = <\> +argv[2] = <ab> +${ +argv[1] = <(")> +argv[1] = <(")> +string \ +string \ +string \ +string \ +string \ +string \} +'weferfds'\''dsfsdf' +'weferfdsdsfsdf' +'weferfds'\''dsfsdf' +'weferfds'\\dsfsdf' +testdd ddtest +testdd '\''ddtest +testdddding +testdddding +test'ing +test'ing +test'string +a'b'c +foo b c baz +foo 'bar baz +argv[1] = <> +argv[1] = <> +argv[1] = <> +argv[1] = <> +argv[1] = <> +argv[1] = <> +argv[1] = <> +argv[1] = <> +argv[1] = <> +argv[1] = <> +===== +argv[1] = <> +argv[1] = <> +argv[1] = <> +argv[1] = <> +argv[1] = <> +argv[1] = <> +argv[1] = <> +===== +argv[1] = <> +argv[1] = <> +argv[1] = <> +argv[1] = <> +argv[1] = <> +argv[1] = <> +argv[1] = <> +===== +argv[1] = <> +argv[1] = <> +argv[1] = <> +argv[1] = <> +argv[1] = <> +argv[1] = <> +argv[1] = <> diff --git a/tests/quote.tests b/tests/quote.tests new file mode 100644 index 0000000..d7f13cd --- /dev/null +++ b/tests/quote.tests @@ -0,0 +1,124 @@ +echo "Single Quote" +echo 'foo +bar' +echo 'foo +bar' +echo 'foo\ +bar' + +echo "Double Quote" +echo "foo +bar" +echo "foo +bar" +echo "foo\ +bar" + +echo "Backslash Single Quote" +echo `echo 'foo +bar'` +echo `echo 'foo +bar'` +echo `echo 'foo\ +bar'` + +echo "Backslash Double Quote" +echo `echo "foo +bar"` +echo `echo "foo +bar"` +echo `echo "foo\ +bar"` + +echo "Double Quote Backslash Single Quote" +echo "`echo 'foo +bar'`" +echo "`echo 'foo +bar'`" +echo "`echo 'foo\ +bar'`" + +echo "Dollar Paren Single Quote" +echo $(echo 'foo +bar') +echo $(echo 'foo +bar') +echo $(echo 'foo\ +bar') + +echo "Dollar Paren Double Quote" +echo $(echo "foo +bar") +echo $(echo "foo +bar") +echo $(echo "foo\ +bar") + +echo "Double Quote Dollar Paren Single Quote" +echo "$(echo 'foo +bar')" +echo "$(echo 'foo +bar')" +echo "$(echo 'foo\ +bar')" + +# old-style command substitution parsing compatibility tests -- post bash-3.1 +recho 'foo \\ +bar' + +recho 'foo \ +bar' + +echo `recho sed -e 's/[ :]/\\ +/g'` + +echo `recho sed -e 's/[ :]/\ +/g'` + +echo `recho 'foo\\ +bar'` + +echo `recho 'foo\ +bar'` + +echo $(recho 'foo\ +bar') + +a=`echo 'a b c' | sed 's/ /\\ +/g' | grep 'b'` +echo $a +a=`echo 'a b c' | sed 's/ /\\ +/g'` +echo "$a" + +recho `echo 'a\' b` + +recho `echo '\$' bab` +recho `echo '\$foo' bab` +recho `echo '$foo' bab` + +recho `echo '\`' ab` + +recho `echo '\\' ab` + +echo `echo '${'` + +recho `echo "(\\")"` +# produces no output +: `: "\\""` +# ultimate workaround +recho `echo "(\")"` + +# various strings ending in backslashes + +echo 'string \' +echo "string \\" + +echo string\ \\ + +echo ${foo:-'string \'} +echo "${foo:-string \\}" +echo ${foo:-string \\\}} + +${THIS_SH} ./quote1.sub +${THIS_SH} ./quote2.sub diff --git a/tests/quote1.sub b/tests/quote1.sub new file mode 100644 index 0000000..a9a1ef1 --- /dev/null +++ b/tests/quote1.sub @@ -0,0 +1,49 @@ +# inconsistency with quoted pattern substitution patterns through bash-4.2 +# fixed in a ksh93-compatible (and Posix-compatible, in general) way +# NOT backwards compatible + +test="weferfds'dsfsdf" + +# why does this work, this list was born of frustration, I tried +# everything I could think of. +echo \'${test//"'"/\'\\\'\'}\'" " + +#but none of the following + +echo "'${test//"'"/}'" + +echo "'${test//"'"/"'\\''"}'" + +printf "%s\n" "'${test//"'"/\'\\'\'}'" + +#echo "'${test//'/}'" # hangs waiting for ' +#echo "'${test//"'"/'\\''}'" # hangs waiting for ' + +unset test +test=teststrtest +echo "${test//str/"dd dd"}" +echo ${test//str/"dd '\''dd"} + +unset test +test=teststring + +echo "${test//str/"dddd"}" + +echo ${test//str/"dddd"} + +echo ${test//str/"'"} + +echo "${test//str/"'"}" + +#echo "${test//str/'}" # hangs + +test=test\'string +echo "${test//"'"/"'"}" + +x="a'b'c"; echo "${x//\'/\'}" + +printf '%s\n' "foo ${IFS+"b c"} baz" + +# this is where the default behavior differs from posix +set -o posix +echo "foo ${IFS+'bar} baz" diff --git a/tests/quote2.sub b/tests/quote2.sub new file mode 100644 index 0000000..7deb4cf --- /dev/null +++ b/tests/quote2.sub @@ -0,0 +1,42 @@ +x=x +e= + +recho ${x:+""} +recho ${x:+ ""} +recho ${x:+"" } +recho ${x:+"$e"} +recho ${x:+ "$e"} +recho ${x:+"$e""$e"""} +recho ${x:+"$e""$e"""} +recho ${x:+"$e" "$e"""} +recho ${x:+"$e""$e" ""} +recho ${x:+ "$e""$e"""} + +echo ===== +recho ${x:+''} +recho ${x:+ ''} +recho ${x:+'' } +recho ${x:+'' ''} + +recho ${x:+$e''} +recho ${x:+''$e} + +recho ${x:+''$e $e''} + +echo ===== +recho ${x:+"$(:)"} +recho ${x:+ "$(:)"} +recho ${x:+"$(:)""$(:)"""} +recho ${x:+"$(:)""$(:)"""} +recho ${x:+"$(:)" "$(:)"""} +recho ${x:+"$(:)""$(:)" ""} +recho ${x:+ "$(:)""$(:)"""} + +echo ===== +recho ${x:+"`:`"} +recho ${x:+ "`:`"} +recho ${x:+"`:`""`:`"""} +recho ${x:+"`:`""`:`"""} +recho ${x:+"`:`" "`:`"""} +recho ${x:+"`:`""`:`" ""} +recho ${x:+ "`:`""`:`"""} diff --git a/tests/read.right b/tests/read.right new file mode 100644 index 0000000..73cb704 --- /dev/null +++ b/tests/read.right @@ -0,0 +1,66 @@ +a. +-a-b- +-a-b - +-a b- +-a b- +-a-b\- +-a b\- +-\-a b\- +-\ a b\- +-\-a b\- +-\ a b\- +argv[1] = <^A> +argv[1] = <^A> +argv[1] = <^?> +argv[1] = <^?> +argv[1] = <abcd> +1: x[A] y[B] z[] +1a: +2: x[A B] +[A B ] +[ A B ] +==aa== +==== +==== +argv[1] = < foo> +argv[1] = < foo> +argv[1] = <foo> +argv[1] = < foo> +argv[1] = <foo> +argv[1] = <foo> +argv[1] = < foo> +a = abcdefg +a = xyz +a = -xyz 123- +a = abc +timeout 1: ok + +timeout 2: ok + +./read2.sub: line 23: read: -3: invalid timeout specification +1 + +abcde +./read3.sub: line 4: read: -1: invalid number +abc +ab +abc +# +while read -u 3 var +do +echo "$var" +done 3<$0 +argv[1] = <> +argv[1] = <> +argv[1] = <> +FOO +argv[1] = <> +argv[1] = <3> +argv[1] = <> +argv[2] = <> +argv[3] = <> +FOO +0 0 0 +0 +0 +1 diff --git a/tests/read.tests b/tests/read.tests new file mode 100644 index 0000000..f67cd00 --- /dev/null +++ b/tests/read.tests @@ -0,0 +1,98 @@ +echo " a " | (read x; echo "$x.") + +echo " a b " | ( read x y ; echo -"$x"-"$y"- ) +echo " a b\ " | ( read x y ; echo -"$x"-"$y"- ) +echo " a b " | ( read x ; echo -"$x"- ) +echo " a b\ " | ( read x ; echo -"$x"- ) + +echo " a b\ " | ( read -r x y ; echo -"$x"-"$y"- ) +echo " a b\ " | ( read -r x ; echo -"$x"- ) + +echo "\ a b\ " | ( read -r x y ; echo -"$x"-"$y"- ) +echo "\ a b\ " | ( read -r x ; echo -"$x"- ) +echo " \ a b\ " | ( read -r x y ; echo -"$x"-"$y"- ) +echo " \ a b\ " | ( read -r x ; echo -"$x"- ) + +# make sure that CTLESC and CTLNUL are passed through correctly +echo $'\001' | ( read var ; recho "$var" ) +echo $'\001' | ( read ; recho "$REPLY" ) + +echo $'\177' | ( read var ; recho "$var" ) +echo $'\177' | ( read ; recho "$REPLY" ) + +# make sure a backslash-quoted \\n still disappears from the input when +# we're not reading in `raw' mode, and no stray CTLESC chars are left in +# the input stream +echo $'ab\\\ncd' | ( read ; recho "$REPLY" ) + +echo "A B " > $TMPDIR/IN +unset x y z +read x y z < $TMPDIR/IN +echo 1: "x[$x] y[$y] z[$z]" +echo 1a: ${z-z not set} +read x < $TMPDIR/IN +echo 2: "x[$x]" +rm $TMPDIR/IN + +# this is where the bash `read' behavior with respect to $REPLY differs +# from ksh93 +echo "A B " > $TMPDIR/IN + +read < $TMPDIR/IN +echo "[$REPLY]" + +rm $TMPDIR/IN + +echo " A B " > $TMPDIR/IN + +read < $TMPDIR/IN +echo "[$REPLY]" + +rm $TMPDIR/IN + +# make sure that read with more variables than words sets the extra +# variables to the empty string + +bvar=bvar +cvar=cvar +echo aa > $TMPDIR/IN +read avar bvar cvar < $TMPDIR/IN +echo =="$avar"== +echo =="$bvar"== +echo =="$cvar"== + +rm $TMPDIR/IN + +# test behavior of read with various settings of IFS + +echo " foo" | { IFS= read line; recho "$line"; } + +echo " foo" | { IFS= ; read line; recho "$line"; } + +echo " foo" | { unset IFS ; read line; recho "$line"; } + +echo " foo" | { IFS=$'\n' ; read line; recho "$line"; } + +echo " foo" | { IFS=$' \n' ; read line; recho "$line"; } + +echo " foo" | { IFS=$' \t\n' ; read line; recho "$line"; } + +echo " foo" | { IFS=$':' ; read line; recho "$line"; } + +# test read -d delim behavior +${THIS_SH} ./read1.sub + +# test read -t timeout behavior +${THIS_SH} ./read2.sub + +# test read -n nchars behavior +${THIS_SH} ./read3.sub + +# test read -u fd behavior +${THIS_SH} ./read4.sub + +# test behavior when IFS is not the default -- bug through bash-2.05b +${THIS_SH} ./read5.sub + +# test behavior of read -t 0 +${THIS_SH} ./read6.sub diff --git a/tests/read1.sub b/tests/read1.sub new file mode 100644 index 0000000..2a36449 --- /dev/null +++ b/tests/read1.sub @@ -0,0 +1,23 @@ +a=7 +echo 'abcdefg|xyz' | { + read -d '|' a + echo a = "${a-unset}" +} + +echo xyz 123 | { + read -d ' ' a + echo a = "${a-unset}" +} + +echo xyz 123 | { + read -d $'\n' a + echo a = -"${a-unset}"- +} + +a=44 +echo abcd | { + read -d d a + echo a = $a +} + +exit 0 diff --git a/tests/read2.sub b/tests/read2.sub new file mode 100644 index 0000000..c4a1f77 --- /dev/null +++ b/tests/read2.sub @@ -0,0 +1,32 @@ +a=4 + +read -t 2 a < /dev/tty +estat=$? +if [ $estat -gt 128 ]; then + echo timeout 1: ok +else + echo $estat +fi + +echo $a + +sleep 5 | read -t 1 a +estat=$? +if [ $estat -gt 128 ]; then + echo timeout 2: ok +else + echo $estat +fi + +echo $a + +read -t -3 a < /dev/tty +echo $? + +echo $a + +# the above should all time out +echo abcde | { + read -t 2 a + echo $a +} diff --git a/tests/read3.sub b/tests/read3.sub new file mode 100644 index 0000000..af41e3f --- /dev/null +++ b/tests/read3.sub @@ -0,0 +1,24 @@ +# non-interactive + +# error +read -n -1 + +# from pipe -- should work, but doesn't change tty attributes +echo abcdefg | { + read -n 3 xyz + echo $xyz +} + +# fewer chars than specified +echo ab | { + read -n 3 xyz + echo $xyz +} + +echo abc | { + read -N 4 -d$'\n' foo + echo $foo +} + +read -n 1 < $0 +echo "$REPLY" diff --git a/tests/read4.sub b/tests/read4.sub new file mode 100644 index 0000000..80bc9fc --- /dev/null +++ b/tests/read4.sub @@ -0,0 +1,4 @@ +while read -u 3 var +do + echo "$var" +done 3<$0 diff --git a/tests/read5.sub b/tests/read5.sub new file mode 100644 index 0000000..e35674e --- /dev/null +++ b/tests/read5.sub @@ -0,0 +1,35 @@ +IFS=: read x y z << EOF +::: +EOF +recho $x +recho "$x" +recho $y +recho "$y" +recho $z +recho "$z" + +if [ -z "$x" ]; then + echo FOO +else + echo BAR +fi + +IFS=: read -a A << EOF +::: +EOF + +recho ${A[0]} +recho "${A[0]}" + +recho ${#A[@]} + +recho "${A[@]}" + +if [ -z "${A[0]}" ]; then + echo FOO +else + echo BAR +fi + +echo -n ${A[0]} | cat -vet +echo -n ${A[0]} | wc | ( IFS=$' \t\n' ; while read line; do echo $line; done; ) diff --git a/tests/read6.sub b/tests/read6.sub new file mode 100644 index 0000000..abfe89d --- /dev/null +++ b/tests/read6.sub @@ -0,0 +1,10 @@ +# test read with a timeout of 0 -- input polling +# sleep with fractional seconds argument is not universal +echo abcde | { sleep 0.25 2>/dev/null ; read -t 0; } +echo $? + +read -t 0 < $0 +echo $? + +read -t 0 +echo $? diff --git a/tests/redir.right b/tests/redir.right new file mode 100644 index 0000000..d4ab60d --- /dev/null +++ b/tests/redir.right @@ -0,0 +1,148 @@ +abc +./redir.tests: line 15: /tmp/redir-test: cannot overwrite existing file +abc +def +def +./redir.tests: line 31: $z: ambiguous redirect +Point 1 +Point 2 +to a +to b +Point 3 +to a +to a +to b +to b +Point 4 +to c +Point 5 +this is redir1.sub +this is redir2.sub +read line1 "ab" +read line2 "root" +read line3 "cd" +read line4 "daemon" +from stdin: aa +to stdout +./redir4.sub: line 32: $fd: ambiguous redirect +./redir4.sub: line 33: $fd: ambiguous redirect +err-and-out: +to stdout +to stderr +err-and-out: +to stdout +to stderr +0 -- 3 0 +0 -- 4 0 +ab +cd +ef +gh +ij +kl +0 +ab +cd +cd +./redir.tests: line 157: redir1.*: No such file or directory +# tests of ksh93-like dup-and-close redirection operators +exec 9<$0 + +f() +{ +exec 5<$0 + +exec 0<&5- + +while read line; do +echo "$line" +done +} + +f + +typeset -f f + +# make sure it was closed +read -u 5 foo 2>&1 | grep -q 'invalid file descriptor' +echo after read + +exec 5<&0 + +exec <&- + +read abcde 2>&1 | grep -q 'read error' + +exec 0<&9- +read line +echo $line +f () +{ + exec 5< $0; + exec 0<&5-; + while read line; do + echo "$line"; + done +} +after read +# tests of ksh93-like dup-and-close redirection operators +/ +/ +/ +0 +0 +0 +before block +after block +c1 is 1 +c2 is 2 +c3 is 3 +c4 is 4 +fd 10 +fd 8 +fd 10 +fd 8 +1 +2 +3 +4 +1 +2 +3 +4 +cat /tmp/foo +whatsis +hey +to stdout +to stderr + +to stdout +to stderr + +to stderr +to stdout + +to stderr +hey +to stdout +logfunc is a function +logfunc () +{ + echo "$@" &>> $TMPDIR/log +} +foo +bix is a function +bix () +{ + echo foo 2>&1 | cat +} +foo +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +1 +7 +after: 42 +./redir11.sub: line 40: $(ss= declare -i ss): ambiguous redirect +after: 42 +a+=3 +foo +foo diff --git a/tests/redir.tests b/tests/redir.tests new file mode 100644 index 0000000..6af0219 --- /dev/null +++ b/tests/redir.tests @@ -0,0 +1,196 @@ +: ${TMPDIR:=/tmp} + +export LC_ALL=C +export LANG=C + +# catch-all for remaining untested redirection stuff +set +o posix + +echo abc > /tmp/redir-test +cat /tmp/redir-test + +set -o noclobber + +#this should be an error +echo def > /tmp/redir-test +cat /tmp/redir-test + +# but this should succeed +echo def > /tmp/redir-test-2 +cat /tmp/redir-test-2 + +# and so should this +echo def >| /tmp/redir-test +cat /tmp/redir-test + +set +o noclobber +rm /tmp/redir-test /tmp/redir-test-2 + +# this should be an error +z="a b" +cat < $z + +echo "Point 1" + +exec 3</etc/passwd +exec 4>$TMPDIR/bash-a +exec 5>$TMPDIR/bash-b +echo "Point 2" + +echo to a 1>&4 +echo to b 1>&5 +cat $TMPDIR/bash-a +cat $TMPDIR/bash-b +exec 11</dev/null +echo "Point 3" + +echo to a 1>&4 +echo to b 1>&5 +cat $TMPDIR/bash-a +cat $TMPDIR/bash-b + +exec 11<&- +echo "Point 4" + +exec 6<>$TMPDIR/bash-c +echo to c 1>&6 +cat $TMPDIR/bash-c +echo "Point 5" + +# clean up before running scripts +exec 4>&- 5>&- 6<&- + +rm -f $TMPDIR/bash-a $TMPDIR/bash-b $TMPDIR/bash-c + +# +# Test the effect of input buffering on the shell's input +# +${THIS_SH} < redir1.sub + +# more open, close, duplicate file descriptors +${THIS_SH} ./redir3.sub < ./redir3.in1 + +# still more redirections +${THIS_SH} ./redir4.sub < redir4.in1 + +# various forms of null redirection +testf() +{ + if [ -f "$1" ]; then + rm -f "$1" + else + echo oops -- $1 not found + fi +} + +> $TMPDIR/null-redir-a +testf $TMPDIR/null-redir-a + +$EXIT > $TMPDIR/null-redir-b +testf $TMPDIR/null-redir-b + +( > $TMPDIR/null-redir-c ) +testf $TMPDIR/null-redir-c + +$EXIT > $TMPDIR/null-redir-d & +wait +testf $TMPDIR/null-redir-d + +exit 3 | $EXIT > $TMPDIR/null-redir-e +echo $? -- ${PIPESTATUS[@]} +testf $TMPDIR/null-redir-e + +exit 4 | > $TMPDIR/null-redir-f +echo $? -- ${PIPESTATUS[@]} +testf $TMPDIR/null-redir-f + +> $TMPDIR/null-redir-g & +wait +testf $TMPDIR/null-redir-g + +exec >$TMPDIR/null-redir-h & +wait +testf $TMPDIR/null-redir-h + +# make sure async commands don't get /dev/null as stdin when an explicit +# input redirection is supplied +for x in 1 2 3; do + { read line ; echo $line ; } & + wait + { read line ; echo $line ; } & + wait +done << EOF +ab +cd +ef +gh +ij +kl +EOF + +# make sure async commands get /dev/null as stdin in the absence of any +# input redirection +/bin/cat & +wait +echo $? + +# make sure that loops work OK with here documents and are not run in +# subshells +while read line; do + echo $line + l2=$line +done << EOF +ab +cd +EOF +echo $l2 + +# These should not echo anything -- bug in versions before 2.04 +( ( echo hello 1>&3 ) 3>&1 ) >/dev/null 2>&1 + +( ( echo hello 1>&3 ) 3>&1 ) >/dev/null 2>&1 | cat + +# in posix mode, non-interactive shells are not allowed to perform +# filename expansion on input redirections, even if they expand to +# a single filename +set -o posix +cat < redir1.* + +# test ksh93 dup-and-close (move fd) redirections +${THIS_SH} ./redir5.sub + +# test behavior after a write error with a builtin command +${THIS_SH} ./redir6.sub + +# problem with redirections using fds bash uses internally +: ${TMPDIR:=$TMPDIR} + +trap 'rm -f $TMPDIR/bash-redir-$$' 0 1 2 3 6 15 + +echo before block +{ + echo before redir + exec 10>&1 + echo after redir +} > $TMPDIR/bash-redir-$$ + +echo after block + +${THIS_SH} ./redir7.sub + +${THIS_SH} ./redir8.sub + +exec 9>&2 +command exec 2>$TMPDIR/foo-$$ +echo whatsis >&2 +echo cat /tmp/foo +cat $TMPDIR/foo-$$ +rm -f $TMPDIR/foo-$$ +exec 2>&9 +exec 9>&- + +${THIS_SH} ./redir9.sub + +${THIS_SH} ./redir10.sub + +${THIS_SH} ./redir11.sub diff --git a/tests/redir1.sub b/tests/redir1.sub new file mode 100644 index 0000000..f1082e9 --- /dev/null +++ b/tests/redir1.sub @@ -0,0 +1,8 @@ +# +# Test the effect of input buffering on the shell's input +# +echo this is redir1.sub + +exec 0< redir2.sub + +echo BUG: after exec in redir1.sub diff --git a/tests/redir10.sub b/tests/redir10.sub new file mode 100644 index 0000000..27c48e8 --- /dev/null +++ b/tests/redir10.sub @@ -0,0 +1,25 @@ +#!/bin/bash +# +# Out of file descriptors, because it forgets to close redirection. Only +# happens in a shell function. Problem through bash-4.2. + +ulimit -n 128 + +bug() +{ +c=`ulimit -n` +let c+=100 +while let c-- +do + while read -ru3 x + do + echo -n : + done 3< <(echo x) + +done +} + +bug +echo + +exit 0 diff --git a/tests/redir11.sub b/tests/redir11.sub new file mode 100644 index 0000000..a919602 --- /dev/null +++ b/tests/redir11.sub @@ -0,0 +1,54 @@ +# make sure redirections do not have access to the temporary environment, even +# in subshells and command substitutions + +a=1 +a=4 b=7 ss=4 echo $a + +# use grep to avoid differences due to different system error messages +a=42 +a=2 echo foo 2>&1 >&$a | { grep -q '\$a: Bad file' || echo 'redir11 bad 1'; } +a=2 echo foo 2>&1 >&$(echo $a) | { grep -q 'Bad file' || echo 'redir11 bad 2'; } + +foo() +{ + local -i a + local v=0 x=1 + a+=3 + echo $a +} + +a=4 b=7 ss=4 declare -i ss +a=4 b=7 foo +echo after: $a + +unset a +a=4 echo foo 2>&1 >&$(foo) | { grep -q 'Bad file' || echo 'redir11 bad 3'; } +a=1 echo foo 2>&1 >&$(foo) | { grep -q 'Bad file' || echo 'redir11 bad 4'; } +a=1 echo foo 2>&1 >&$(a=4 foo) | { grep -q 'Bad file' || echo 'redir11 bad 5'; } +echo foo 2>&1 >&$(a=4 foo) | { grep -q 'Bad file' || echo 'redir11 bad 6'; } + +a=42 +a=2 echo foo 2>&1 >&$a | { grep -q 'Bad file' || echo 'redir11 bad 7'; } +a=2 echo foo 2>&1 >&$(echo $a) | { grep -q 'Bad file' || echo 'redir11 bad 8'; } + +unset -f foo +foo() +{ + local -i a + local v=0 x=1 + a+=3 + echo $a >&$(ss= declare -i ss) +} + +a=4 b=7 foo +echo after: $a + +unset a +typeset -i a +a=4 eval echo $(echo a+=3) +a=2 +a=9 echo foo >&$(echo $a) +a=2 +a=9 eval echo foo >&$(echo $a) +a=2 +a=9 eval echo foo '2>&1 >&$(echo $a)' | { grep -q 'Bad file' || echo 'redir11 bad 9'; } diff --git a/tests/redir2.sub b/tests/redir2.sub new file mode 100644 index 0000000..0820f70 --- /dev/null +++ b/tests/redir2.sub @@ -0,0 +1 @@ +echo this is redir2.sub diff --git a/tests/redir3.in1 b/tests/redir3.in1 new file mode 100644 index 0000000..dbd1fc3 --- /dev/null +++ b/tests/redir3.in1 @@ -0,0 +1,2 @@ +ab +cd diff --git a/tests/redir3.in2 b/tests/redir3.in2 new file mode 100644 index 0000000..5a1c32b --- /dev/null +++ b/tests/redir3.in2 @@ -0,0 +1,2 @@ +root +daemon diff --git a/tests/redir3.sub b/tests/redir3.sub new file mode 100644 index 0000000..c486253 --- /dev/null +++ b/tests/redir3.sub @@ -0,0 +1,26 @@ +read line1 + +echo read line1 \"$line1\" + +exec 4<./redir3.in2 + +exec 5<&0 +exec 0<&4 + +read line2 + +echo read line2 \"$line2\" + +exec 0<&5 + +read line3 + +echo read line3 \"$line3\" + +exec 0<&4 + +read line4 + +echo read line4 \"$line4\" + +exec 4<&- diff --git a/tests/redir4.in1 b/tests/redir4.in1 new file mode 100644 index 0000000..e61ef7b --- /dev/null +++ b/tests/redir4.in1 @@ -0,0 +1 @@ +aa diff --git a/tests/redir4.sub b/tests/redir4.sub new file mode 100644 index 0000000..14406d0 --- /dev/null +++ b/tests/redir4.sub @@ -0,0 +1,56 @@ +minus=- + +# standard input +fd=0 + +exec 3<&$fd + +read line <&3 +echo from stdin: $line + +# close fd 3 +exec 3<&${minus} + +# should give `bad fd', but exact error messages vary +# read line <&3 + +# standard output +fd=1 + +exec 4>&$fd + +echo to stdout >&4 + +exec 4>&$minus + +# should give `bad fd', but exact error messages vary +# echo to stdout >&4 + +unset fd + +# these are ambiguous redirects +exec 3<&$fd +exec 4>&$fd + +exec 3>&1 4>&2 + +exec >&${TMPDIR}/err-and-out +echo to stdout +echo to stderr >&2 + +exec 1>&3 2>&4 +echo err-and-out: +cat ${TMPDIR}/err-and-out + +rm ${TMPDIR}/err-and-out + +fd=${TMPDIR}/err-and-out +exec >&$fd +echo to stdout +echo to stderr >&2 + +exec 1>&3 2>&4 +echo err-and-out: +cat ${TMPDIR}/err-and-out + +rm ${TMPDIR}/err-and-out diff --git a/tests/redir5.sub b/tests/redir5.sub new file mode 100644 index 0000000..ee7b045 --- /dev/null +++ b/tests/redir5.sub @@ -0,0 +1,31 @@ +# tests of ksh93-like dup-and-close redirection operators +exec 9<$0 + +f() +{ +exec 5<$0 + +exec 0<&5- + +while read line; do + echo "$line" +done +} + +f + +typeset -f f + +# make sure it was closed +read -u 5 foo 2>&1 | grep -q 'invalid file descriptor' +echo after read + +exec 5<&0 + +exec <&- + +read abcde 2>&1 | grep -q 'read error' + +exec 0<&9- +read line +echo $line diff --git a/tests/redir6.sub b/tests/redir6.sub new file mode 100644 index 0000000..c735e52 --- /dev/null +++ b/tests/redir6.sub @@ -0,0 +1,10 @@ +cd / +pwd +help >&- +pwd +pwd +echo $? +echo $? +echo $? + +cd $OLDPWD diff --git a/tests/redir7.sub b/tests/redir7.sub new file mode 100644 index 0000000..3fd371c --- /dev/null +++ b/tests/redir7.sub @@ -0,0 +1,69 @@ +# weird redirections that caused trouble and were fixed in post-3.0 bash +stuff() +{ + c=1 + ( sleep 5 < /dev/null >/dev/null 2>&1 & ) & +} + +exec 3>&1 +eval ` +exec 4>&1 >&3 3>&- +{ + stuff 4>&- + echo "c=$c" >&4 +}` +echo c1 is $c + +unset -f stuff + +stuff() +{ + c=2 + ( sleep 5 < /dev/null >/dev/null 2>&1 & ) +} + +exec 3>&1 +eval ` +exec 4>&1 >&3 3>&- +{ + stuff 4>&- + echo "c=$c" >&4 +}` +echo c2 is $c + +unset -f stuff + +stuff() +{ + c=3 + { sleep 5 < /dev/null >/dev/null 2>&1 & } & +} + +exec 3>&1 +eval ` +exec 4>&1 >&3 3>&- +{ + stuff 4>&- + echo "c=$c" >&4 +}` +echo c3 is $c + +unset -f stuff + +stuff() +{ + c=4 + { sleep 5 < /dev/null >/dev/null 2>&1 & } +} + +exec 3>&1 +eval ` +exec 4>&1 >&3 3>&- +{ + stuff 4>&- + echo "c=$c" >&4 +}` +echo c4 is $c + +# fixed in bash-3.1 +echo 'exec <&3' | ${THIS_SH} 3<&0 diff --git a/tests/redir8.sub b/tests/redir8.sub new file mode 100644 index 0000000..88753f2 --- /dev/null +++ b/tests/redir8.sub @@ -0,0 +1,61 @@ +cd ${TMPDIR:=/var/tmp} +rm -f u + +${THIS_SH} -c 'exec 10>&1; echo fd 10 >&10' 10>u +cat u +rm -f u + +${THIS_SH} -c 'exec 8>&1; echo fd 8 >&8' 8>u +cat u +rm -f u + +exec 10>u +exec 10>&1; echo 'fd 10' >&10 +cat u +rm -f u +exec 10>&- + +exec 8>u +exec 8>&1; echo 'fd 8' >&8 +cat u +rm -f u +exec 8>&- + +rm -f infile +cat > infile <<EOF +1 +2 +3 +4 +EOF + +exec 7<&0 +exec 10<infile +exec 0<&10; cat <&10 +exec 0<&7 +exec 7<&- + +exec 7<&0 +exec 8<infile +exec 0<&8 ; cat <&8 +exec 0<&7 +exec 7<&- + +exec 7<&0 +exec 0</dev/null +exec 10<infile +exec 10<&0; cat <&10 +exec 0<&7 +exec 7<&- + +exec 7<&0 +exec 0</dev/null +exec 8<infile +exec 8<&0; cat <&8 +exec 0<&7 +exec 7<&- + +rm -f infile + +cd $OLDPWD +exit 0 diff --git a/tests/redir9.sub b/tests/redir9.sub new file mode 100644 index 0000000..386ae56 --- /dev/null +++ b/tests/redir9.sub @@ -0,0 +1,50 @@ +: ${TMPDIR:=/tmp} + +func() +{ + echo "to stdout" + echo "to stderr" >&2 +} + +TMPFN=$TMPDIR/foo-$$ + +rm -f $TMPFN + +echo hey > $TMPFN +func &>> $TMPFN + +cat $TMPFN + +echo +func &> $TMPFN + +cat $TMPFN + +echo +func >$TMPFN +cat $TMPFN + +echo +echo hey > $TMPFN +func >> $TMPFN +cat $TMPFN + +rm -f $TMPFN + +logfunc() +{ + echo "$@" &>> $TMPDIR/log +} + +type logfunc + +echo foo 2>&1 + +bix() +{ +echo foo |& cat +} + +type bix + +bix diff --git a/tests/rhs-exp.right b/tests/rhs-exp.right new file mode 100644 index 0000000..4ce6743 --- /dev/null +++ b/tests/rhs-exp.right @@ -0,0 +1,105 @@ +argv[1] = <TDEFAULTS = -DSELECT_VECS='&m68kcoff_vec'> +argv[1] = <TDEFAULTS = -DSELECT_VECS=\'&m68kcoff_vec\'> +argv[1] = <TDEFAULTS = -DSELECT_VECS=&m68kcoff_vec> +argv[1] = <TDEFAULTS = -DSELECT_VECS="&m68kcoff_vec"> +argv[1] = <TDEFAULTS = -DSELECT_VECS=\&m68kcoff_vec\> +argv[1] = <TDEFAULTS = -DSELECT_VECS=&m68kcoff_vec> +argv[1] = <TDEFAULTS = -DSELECT_VECS=$selvecs> +argv[1] = <TDEFAULTS = -DSELECT_VECS=$selvecs> +argv[1] = <TDEFAULTS = -DSELECT_VECS='&m68kcoff_vec'> +argv[1] = <TDEFAULTS = -DSELECT_VECS=\&m68kcoff_vec> +argv[1] = <TDEFAULTS = -DSELECT_VECS='&m68kcoff_vec'> +argv[1] = <TDEFAULTS> +argv[2] = <=> +argv[3] = <-DSELECT_VECS=$selvecs> +argv[1] = <TDEFAULTS> +argv[2] = <=> +argv[3] = <-DSELECT_VECS='&m68kcoff_vec'> +argv[1] = <TDEFAULTS> +argv[2] = <=> +argv[3] = <-DSELECT_VECS=&m68kcoff_vec> +argv[1] = <TDEFAULTS> +argv[2] = <=> +argv[3] = <-DSELECT_VECS="&m68kcoff_vec"> +argv[1] = <TDEFAULTS> +argv[2] = <=> +argv[3] = <-DSELECT_VECS=\&m68kcoff_vec\> +argv[1] = <TDEFAULTS> +argv[2] = <=> +argv[3] = <-DSELECT_VECS=&m68kcoff_vec> +argv[1] = <TDEFAULTS> +argv[2] = <=> +argv[3] = <-DSELECT_VECS=$selvecs> +argv[1] = <TDEFAULTS> +argv[2] = <=> +argv[3] = <-DSELECT_VECS=$selvecs> +argv[1] = <TDEFAULTS> +argv[2] = <=> +argv[3] = <-DSELECT_VECS=$selvecs> +argv[1] = <TDEFAULTS> +argv[2] = <=> +argv[3] = <-DSELECT_VECS=\&m68kcoff_vec> +argv[1] = <TDEFAULTS> +argv[2] = <=> +argv[3] = <-DSELECT_VECS=\'&m68kcoff_vec\'> +argv[1] = <TDEFAULTS = -DSELECT_VECS=p> +argv[1] = <TDEFAULTS = -DSELECT_VECS=\p> +argv[1] = <TDEFAULTS = -DSELECT_VECS=\> +argv[1] = <TDEFAULTS = -DSELECT_VECS=\> +argv[1] = <TDEFAULTS = -DSELECT_VECS=\'> +argv[1] = <TDEFAULTS = -DSELECT_VECS='> +argv[1] = <TDEFAULTS> +argv[2] = <=> +argv[3] = <-DSELECT_VECS=\p> +argv[1] = <TDEFAULTS> +argv[2] = <=> +argv[3] = <-DSELECT_VECS=p> +argv[1] = <TDEFAULTS> +argv[2] = <=> +argv[3] = <-DSELECT_VECS=\> +argv[1] = <TDEFAULTS> +argv[2] = <=> +argv[3] = <-DSELECT_VECS=\> +argv[1] = <TDEFAULTS> +argv[2] = <=> +argv[3] = <-DSELECT_VECS='> +argv[1] = <TDEFAULTS> +argv[2] = <=> +argv[3] = <-DSELECT_VECS=\'> +a*b +ab +a?b +ab +a/b +ab +argv[1] = <bc> +argv[1] = <bc> +argv[1] = <ab> +argv[1] = <ab> +argv[1] = <bc> +argv[1] = <bc> +argv[1] = <c> +argv[1] = <ab> +argv[1] = <ab> +argv[1] = <aacc> +argv[1] = <aacc> +argv[1] = <aabbcc> +argv[1] = <aabbcc> +argv[1] = <Oenophile> +argv[1] = <OEnOphIlE> +argv[1] = <> +argv[1] = <abc> +argv[1] = <''> +argv[1] = <> +good 1 +good 2 +good 3 +good 4 +good 5 +ok 1 +ok 2 +ok 3 +ok 4 +ok 5 +ok 6 +ok 7 diff --git a/tests/rhs-exp.tests b/tests/rhs-exp.tests new file mode 100644 index 0000000..a28d7f0 --- /dev/null +++ b/tests/rhs-exp.tests @@ -0,0 +1,51 @@ +selvecs='&m68kcoff_vec' +recho "TDEFAULTS = ${selvecs:+-DSELECT_VECS='$selvecs'}" +recho "TDEFAULTS = ${selvecs:+-DSELECT_VECS=\'$selvecs\'}" +recho "TDEFAULTS = ${selvecs:+-DSELECT_VECS="$selvecs"}" +recho "TDEFAULTS = ${selvecs:+-DSELECT_VECS=\"$selvecs\"}" +recho "TDEFAULTS = ${selvecs:+-DSELECT_VECS=\\$selvecs\\}" +recho "TDEFAULTS = ${selvecs:+-DSELECT_VECS=$selvecs}" +recho "TDEFAULTS = ${selvecs:+-DSELECT_VECS=\$selvecs}" +recho "TDEFAULTS = ${selvecs:+-DSELECT_VECS="\$selvecs"}" +recho "TDEFAULTS = ${selvecs:+-DSELECT_VECS='$selvecs'"$null"}" +recho "TDEFAULTS = ${selvecs:+-DSELECT_VECS="\\$selvecs"}" +recho "TDEFAULTS = ${selvecs:+-DSELECT_VECS="\'$selvecs\'"}" + +recho TDEFAULTS = ${selvecs:+-DSELECT_VECS='$selvecs'} +recho TDEFAULTS = ${selvecs:+-DSELECT_VECS=\'$selvecs\'} +recho TDEFAULTS = ${selvecs:+-DSELECT_VECS="$selvecs"} +recho TDEFAULTS = ${selvecs:+-DSELECT_VECS=\"$selvecs\"} +recho TDEFAULTS = ${selvecs:+-DSELECT_VECS=\\$selvecs\\} +recho TDEFAULTS = ${selvecs:+-DSELECT_VECS=$selvecs} +recho TDEFAULTS = ${selvecs:+-DSELECT_VECS=\$selvecs} +recho TDEFAULTS = ${selvecs:+-DSELECT_VECS="\$selvecs"} +recho TDEFAULTS = ${selvecs:+-DSELECT_VECS='$selvecs'"$null"} +recho TDEFAULTS = ${selvecs:+-DSELECT_VECS="\\$selvecs"} +recho TDEFAULTS = ${selvecs:+-DSELECT_VECS="\'$selvecs\'"} + +recho "TDEFAULTS = ${selvecs:+-DSELECT_VECS="\p"}" +recho "TDEFAULTS = ${selvecs:+-DSELECT_VECS=\p}" +recho "TDEFAULTS = ${selvecs:+-DSELECT_VECS="\\"}" +recho "TDEFAULTS = ${selvecs:+-DSELECT_VECS=\\}" +recho "TDEFAULTS = ${selvecs:+-DSELECT_VECS=\'}" +recho "TDEFAULTS = ${selvecs:+-DSELECT_VECS="\'"}" + +recho TDEFAULTS = ${selvecs:+-DSELECT_VECS="\p"} +recho TDEFAULTS = ${selvecs:+-DSELECT_VECS=\p} +recho TDEFAULTS = ${selvecs:+-DSELECT_VECS="\\"} +recho TDEFAULTS = ${selvecs:+-DSELECT_VECS=\\} +recho TDEFAULTS = ${selvecs:+-DSELECT_VECS=\'} +recho TDEFAULTS = ${selvecs:+-DSELECT_VECS="\'"} + +# more tests for bash-3.0 behavior + +var="a*b" ; echo "${var//\\*/}" +var="a*b" ; echo "${var//\*/}" + +var="a?b" ; echo "${var//\\?/}" +var="a?b" ; echo "${var//\?/}" + +var="a/b" ; echo "${var//\\//}" +var="a/b" ; echo "${var//\//}" + +${THIS_SH} ./rhs-exp1.sub diff --git a/tests/rhs-exp1.sub b/tests/rhs-exp1.sub new file mode 100644 index 0000000..5631ea5 --- /dev/null +++ b/tests/rhs-exp1.sub @@ -0,0 +1,103 @@ +# fixes for bugs in bash-4.2 regarding empty strings in expand_string_for_rhs + +f=abc +recho ${f##""a} +recho ${f##"$v"a} + +recho ${f%%""c} +recho ${f%%"$v"c} + +recho ${f//""a} +recho ${f//"$v"a} + +recho ${f/""a""b/} +recho ${f/""c/} +recho ${f/"$v"c/} + +unset foo empty +foo=aabbcc + +recho ${foo/bb/} +recho ${foo/bb/$empty} + +recho ${foo/} +recho ${empty/} + +recho ${foo/ } +recho ${empty/ } +unset foo empty + +S2=oenophile + +recho ${S2^"$v"[aeiou]} +recho ${S2^^"$v"[aeiou]} + +recho ${foo:-""} +recho ${foo:-""abc} + +recho "${foo:-''}" +recho "${foo:-}" + +if [[ $var == "" ]]; then + echo good 1 +fi + +if [[ "$var"X == ""X ]]; then + echo good 2 +fi + +if [ "$var"X == ""X"" ]; then + echo good 3 +fi + +if [ X"" == X ]; then + echo good 4 +fi + +if [[ X"" == X ]]; then + echo good 5 +fi + +case x"" in + x) echo 'ok 1' + ;; + x??) echo 'this would be really odd' + ;; + x?) echo 'does this prove anything?' + echo x""x + ;; + *) echo 'no match' + ;; +esac + +if [[ x"" == x ]]; then + echo ok 2 +fi + +if [[ x"" == x"" ]]; then + echo ok 3 +else + echo bad 3 +fi + +case x"" in +x"") echo ok 4 ;; +*) echo bad 4;; +esac + +if [[ x"" == x"" ]]; then + echo ok 5 +else + echo bad 5 +fi + +case x"" in +"x") echo ok 6 ;; +*) echo bad 6;; +esac + +case x"" in +"x") echo CTLNUL 7 ;; +x) echo ok 7 ;; +*) echo bad 7 ;; +esac diff --git a/tests/rsh.right b/tests/rsh.right new file mode 100644 index 0000000..a728f13 --- /dev/null +++ b/tests/rsh.right @@ -0,0 +1,19 @@ +./rsh1.sub: line 9: /bin/sh: restricted +./rsh1.sub: line 11: sh: not found +./rsh1.sub: line 12: a: command not found +./rsh2.sub: line 10: hash: /bin/sh: restricted +./rsh2.sub: line 12: hash: sh: not found +./rsh2.sub: line 13: a: command not found +./rsh.tests: line 12: cd: restricted +./rsh.tests: line 13: PATH: readonly variable +./rsh.tests: line 14: SHELL: readonly variable +./rsh.tests: line 15: /bin/sh: restricted: cannot specify `/' in command names +./rsh.tests: line 17: .: ./source.sub3: restricted +./rsh.tests: line 20: /tmp/restricted: restricted: cannot redirect output +./rsh.tests: line 24: /tmp/restricted: restricted: cannot redirect output +./rsh.tests: line 29: command: -p: restricted +./rsh.tests: line 31: set: +r: invalid option +set: usage: set [-abefhkmnptuvxBCHP] [-o option-name] [--] [arg ...] +./rsh.tests: line 32: set: restricted: invalid option name +./rsh.tests: line 34: exec: restricted +./rsh.tests: after exec diff --git a/tests/rsh.tests b/tests/rsh.tests new file mode 100644 index 0000000..d1d7778 --- /dev/null +++ b/tests/rsh.tests @@ -0,0 +1,36 @@ +# test restricted shell mode -- these should all be errors +# +# things not tested for: +# adding builtins dynamically with enable -f +# importing function definitions from environment + +${THIS_SH} ./rsh1.sub +${THIS_SH} ./rsh2.sub + +set -r + +cd / +PATH=$PATH:/usr/local/bin +SHELL=/bin/sh +/bin/sh -c 'echo /bin/sh executed' + +. ./source.sub3 + +rm -f /tmp/restricted +echo abc > /tmp/restricted +if [ -f /tmp/restricted ]; then + echo oops 1 -- output +fi +echo abc >> /tmp/restricted +if [ -f /tmp/restricted ]; then + echo oops 2 -- append +fi + +command -p date + +set +r +set +o restricted + +exec /bin/date + +echo $0: after exec diff --git a/tests/rsh1.sub b/tests/rsh1.sub new file mode 100644 index 0000000..fdd4ddd --- /dev/null +++ b/tests/rsh1.sub @@ -0,0 +1,16 @@ +cd ${TMPDIR:-/tmp} +cp /bin/sh . + +PATH=/rbin:/usr/local/rbin +hash -p /bin/rm rm + +set -r + +BASH_CMDS[x]=/bin/sh + +BASH_CMDS[a]="sh" +a -c 'echo hello' + +rm -f sh a + +exit 0 diff --git a/tests/rsh2.sub b/tests/rsh2.sub new file mode 100644 index 0000000..8c82c68 --- /dev/null +++ b/tests/rsh2.sub @@ -0,0 +1,17 @@ +cd ${TMPDIR:-/tmp} +cp /bin/sh . +ln sh a + +PATH=/rbin:/usr/local/rbin +hash -p /bin/rm rm + +set -r + +hash -p /bin/sh sh + +hash -p sh a +a -c 'echo hello' + +rm -f sh a + +exit 0 diff --git a/tests/run-alias b/tests/run-alias new file mode 100644 index 0000000..3b4f4dc --- /dev/null +++ b/tests/run-alias @@ -0,0 +1,2 @@ +${THIS_SH} ./alias.tests > ${BASH_TSTOUT} 2>&1 +diff ${BASH_TSTOUT} alias.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-all b/tests/run-all new file mode 100644 index 0000000..34d3e4c --- /dev/null +++ b/tests/run-all @@ -0,0 +1,46 @@ +#! /bin/sh + +: ${TMPDIR:=/tmp} +export TMPDIR + +# basic /bin/sh syntax +SUFFIX=`${THIS_SH} -c 'echo $(( $RANDOM + $BASHPID ))'` + +BASH_TSTOUT=${TMPDIR}/bashtst-$SUFFIX # for now +export BASH_TSTOUT + +trap 'rm -f $BASH_TSTOUT' 0 1 2 3 15 + +PATH=.:$PATH # just to get recho/zecho/printenv if not run via `make tests' +export PATH + +# unset BASH_ENV only if it is set +[ "${BASH_ENV+set}" = "set" ] && unset BASH_ENV +# can't reliably do it for SHELLOPTS; SHELLOPTS is readonly in bash +if [ "${BASH_VERSION+set}" = "set" ]; then + export -n SHELLOPTS # just make sure its not exported + set +o posix + typeset -p SHELLOPTS +else + [ "${SHELLOPTS+set}" = "set" ] && unset SHELLOPTS 2>/dev/null +fi + +: ${THIS_SH:=../bash} +export THIS_SH + +${THIS_SH} ./version + +rm -f ${BASH_TSTOUT} + +echo Any output from any test, unless otherwise noted, indicates a possible anomaly + +for x in run-* +do + case $x in + $0|run-minimal|run-gprof) ;; + *.orig|*~) ;; + *) echo $x ; sh $x ; rm -f ${BASH_TSTOUT} ;; + esac +done + +exit 0 diff --git a/tests/run-appendop b/tests/run-appendop new file mode 100644 index 0000000..2d756f8 --- /dev/null +++ b/tests/run-appendop @@ -0,0 +1,2 @@ +${THIS_SH} ./appendop.tests > ${BASH_TSTOUT} 2>&1 +diff ${BASH_TSTOUT} appendop.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-arith b/tests/run-arith new file mode 100644 index 0000000..0786b4f --- /dev/null +++ b/tests/run-arith @@ -0,0 +1,2 @@ +${THIS_SH} ./arith.tests > ${BASH_TSTOUT} 2>&1 +diff ${BASH_TSTOUT} arith.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-arith-for b/tests/run-arith-for new file mode 100644 index 0000000..085715e --- /dev/null +++ b/tests/run-arith-for @@ -0,0 +1,2 @@ +${THIS_SH} ./arith-for.tests > ${BASH_TSTOUT} 2>&1 +diff ${BASH_TSTOUT} arith-for.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-array b/tests/run-array new file mode 100644 index 0000000..6c5ec27 --- /dev/null +++ b/tests/run-array @@ -0,0 +1,6 @@ +echo "warning: all of these tests will fail if arrays have not" >&2 +echo "warning: been compiled into the shell" >&2 +echo "warning: the BASH_ARGC and BASH_ARGV tests will fail if debugging support" >&2 +echo "warning: has not been compiled into the shell" >&2 +${THIS_SH} ./array.tests > ${BASH_TSTOUT} 2>&1 +diff ${BASH_TSTOUT} array.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-array2 b/tests/run-array2 new file mode 100644 index 0000000..54852ec --- /dev/null +++ b/tests/run-array2 @@ -0,0 +1,4 @@ +echo "warning: all of these tests will fail if arrays have not" >&2 +echo "warning: been compiled into the shell" >&2 +${THIS_SH} ./array-at-star > ${BASH_TSTOUT} 2>&1 +diff ${BASH_TSTOUT} array2.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-assoc b/tests/run-assoc new file mode 100644 index 0000000..7fef234 --- /dev/null +++ b/tests/run-assoc @@ -0,0 +1,4 @@ +echo "warning: all of these tests will fail if arrays have not" >&2 +echo "warning: been compiled into the shell" >&2 +${THIS_SH} ./assoc.tests > ${BASH_TSTOUT} 2>&1 +diff ${BASH_TSTOUT} assoc.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-attr b/tests/run-attr new file mode 100644 index 0000000..948b9e1 --- /dev/null +++ b/tests/run-attr @@ -0,0 +1,2 @@ +${THIS_SH} ./attr.tests 2>&1 | grep -v '^expect' > ${BASH_TSTOUT} +diff ${BASH_TSTOUT} attr.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-braces b/tests/run-braces new file mode 100644 index 0000000..554e218 --- /dev/null +++ b/tests/run-braces @@ -0,0 +1,2 @@ +${THIS_SH} ./braces.tests > ${BASH_TSTOUT} +diff ${BASH_TSTOUT} braces.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-builtins b/tests/run-builtins new file mode 100644 index 0000000..69644f2 --- /dev/null +++ b/tests/run-builtins @@ -0,0 +1,6 @@ +echo "warning: some of these tests may fail if process substitution has not" >&2 +echo "warning: been compiled into the shell or if the OS does not provide" >&2 +echo "warning: /dev/fd." >&2 + +${THIS_SH} ./builtins.tests > ${BASH_TSTOUT} 2>&1 +diff ${BASH_TSTOUT} builtins.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-case b/tests/run-case new file mode 100644 index 0000000..1560ee2 --- /dev/null +++ b/tests/run-case @@ -0,0 +1,2 @@ +${THIS_SH} ./case.tests > ${BASH_TSTOUT} 2>&1 +diff ${BASH_TSTOUT} case.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-casemod b/tests/run-casemod new file mode 100644 index 0000000..9b58764 --- /dev/null +++ b/tests/run-casemod @@ -0,0 +1,2 @@ +${THIS_SH} ./casemod.tests > ${BASH_TSTOUT} 2>&1 +diff ${BASH_TSTOUT} casemod.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-comsub b/tests/run-comsub new file mode 100644 index 0000000..4c3d1cf --- /dev/null +++ b/tests/run-comsub @@ -0,0 +1,2 @@ +${THIS_SH} ./comsub.tests > ${BASH_TSTOUT} 2>&1 +diff ${BASH_TSTOUT} comsub.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-comsub-eof b/tests/run-comsub-eof new file mode 100644 index 0000000..0733b2d --- /dev/null +++ b/tests/run-comsub-eof @@ -0,0 +1,2 @@ +${THIS_SH} ./comsub-eof.tests > ${BASH_TSTOUT} 2>&1 +diff ${BASH_TSTOUT} comsub-eof.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-comsub-posix b/tests/run-comsub-posix new file mode 100644 index 0000000..520cb44 --- /dev/null +++ b/tests/run-comsub-posix @@ -0,0 +1,2 @@ +${THIS_SH} ./comsub-posix.tests > ${BASH_TSTOUT} 2>&1 +diff ${BASH_TSTOUT} comsub-posix.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-cond b/tests/run-cond new file mode 100644 index 0000000..603e739 --- /dev/null +++ b/tests/run-cond @@ -0,0 +1,7 @@ +echo "warning: all of these tests will fail if the conditional command has not" >&2 +echo "warning: been compiled into the shell" >&2 +echo "warning: some of these tests will fail if extended pattern matching has not" >&2 +echo "warning: been compiled into the shell" >&2 + +${THIS_SH} ./cond.tests > ${BASH_TSTOUT} 2>&1 +diff ${BASH_TSTOUT} cond.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-coproc b/tests/run-coproc new file mode 100644 index 0000000..02c5c92 --- /dev/null +++ b/tests/run-coproc @@ -0,0 +1,2 @@ +${THIS_SH} ./coproc.tests > ${BASH_TSTOUT} 2>&1 +diff ${BASH_TSTOUT} coproc.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-cprint b/tests/run-cprint new file mode 100644 index 0000000..82d2c2a --- /dev/null +++ b/tests/run-cprint @@ -0,0 +1,2 @@ +${THIS_SH} ./cprint.tests > ${BASH_TSTOUT} 2>&1 +diff ${BASH_TSTOUT} cprint.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-dbg-support b/tests/run-dbg-support new file mode 100644 index 0000000..9e9c649 --- /dev/null +++ b/tests/run-dbg-support @@ -0,0 +1,11 @@ +#!../bash +#$Id: run-dbg-support,v 1.5 2002/11/14 06:08:16 rockyb Exp $ + +TEST_NAME='dbg-support' +TEST_FILE="/tmp/${TEST_NAME}.check" +${THIS_SH} ./${TEST_NAME}.tests > $TEST_FILE 2>&1 < /dev/null +set -f +diff $TEST_FILE ${TEST_NAME}.right && rm -f $TEST_FILE + +# Return code tells testing mechanism whether passed or not. +exit $? diff --git a/tests/run-dbg-support2 b/tests/run-dbg-support2 new file mode 100644 index 0000000..f62583f --- /dev/null +++ b/tests/run-dbg-support2 @@ -0,0 +1,16 @@ +#!../bash +#$Id: run-dbg-support2,v 1.3 2002/11/14 06:08:16 rockyb Exp $ + +TEST_NAME='dbg-support2' +TEST_FILE="/tmp/${TEST_NAME}.check" +${THIS_SH} ./${TEST_NAME}.tests > $TEST_FILE 2>&1 < /dev/null +set -f +diff $TEST_FILE ${TEST_NAME}.right && rm -f $TEST_FILE + +# Return code tells testing mechanism whether passed or not. +exit $? + +#;;; Local Variables: *** +#;;; mode:shell-script *** +#;;; eval: (sh-set-shell "bash") *** +#;;; End: *** diff --git a/tests/run-dirstack b/tests/run-dirstack new file mode 100644 index 0000000..e6b42d4 --- /dev/null +++ b/tests/run-dirstack @@ -0,0 +1,5 @@ +${THIS_SH} ./dstack.tests > ${BASH_TSTOUT} 2>&1 +diff ${BASH_TSTOUT} dstack.right && rm -f ${BASH_TSTOUT} + +${THIS_SH} ./dstack2.tests > ${BASH_TSTOUT} 2>&1 +diff ${BASH_TSTOUT} dstack2.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-dollars b/tests/run-dollars new file mode 100644 index 0000000..dc5d623 --- /dev/null +++ b/tests/run-dollars @@ -0,0 +1,2 @@ +${THIS_SH} ./dollar-at-star > ${BASH_TSTOUT} 2>&1 +diff ${BASH_TSTOUT} dollar.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-dynvar b/tests/run-dynvar new file mode 100644 index 0000000..26c5434 --- /dev/null +++ b/tests/run-dynvar @@ -0,0 +1,2 @@ +${THIS_SH} ./dynvar.tests > ${BASH_TSTOUT} 2>&1 +diff ${BASH_TSTOUT} dynvar.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-errors b/tests/run-errors new file mode 100644 index 0000000..29417cd --- /dev/null +++ b/tests/run-errors @@ -0,0 +1,3 @@ +unset OLDPWD # make sure shell doesn't inherit OLDPWD +${THIS_SH} ./errors.tests > ${BASH_TSTOUT} 2>&1 +diff ${BASH_TSTOUT} errors.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-execscript b/tests/run-execscript new file mode 100644 index 0000000..de78644 --- /dev/null +++ b/tests/run-execscript @@ -0,0 +1,9 @@ +echo "warning: the text of a system error message may vary between systems and" >&2 +echo "warning: produce diff output." >&2 +echo "warning: if the text of the error messages concerning \`notthere' or" >&2 +echo "warning: \`/tmp/bash-notthere' not being found or \`/' being a directory" >&2 +echo "warning: produce diff output, please do not consider this a test failure" >&2 +echo "warning: if diff output differing only in the location of the bash" >&2 +echo "warning: binary appears, please do not consider this a test failure" >&2 +${THIS_SH} ./execscript > ${BASH_TSTOUT} 2>&1 +diff ${BASH_TSTOUT} exec.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-exp-tests b/tests/run-exp-tests new file mode 100644 index 0000000..78cf754 --- /dev/null +++ b/tests/run-exp-tests @@ -0,0 +1,2 @@ +${THIS_SH} ./exp.tests 2>&1 | grep -v '^expect' > ${BASH_TSTOUT} +diff ${BASH_TSTOUT} exp.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-exportfunc b/tests/run-exportfunc new file mode 100644 index 0000000..7b207fa --- /dev/null +++ b/tests/run-exportfunc @@ -0,0 +1,2 @@ +${THIS_SH} ./exportfunc.tests > ${BASH_TSTOUT} 2>&1 +diff ${BASH_TSTOUT} exportfunc.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-extglob b/tests/run-extglob new file mode 100644 index 0000000..149e34a --- /dev/null +++ b/tests/run-extglob @@ -0,0 +1,4 @@ +PATH=$PATH:`pwd` +export PATH +${THIS_SH} ./extglob.tests | grep -v '^expect' > ${BASH_TSTOUT} +diff ${BASH_TSTOUT} extglob.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-extglob2 b/tests/run-extglob2 new file mode 100644 index 0000000..71d3d80 --- /dev/null +++ b/tests/run-extglob2 @@ -0,0 +1,4 @@ +PATH=$PATH:`pwd` +export PATH +${THIS_SH} ./extglob2.tests | grep -v '^expect' > ${BASH_TSTOUT} +diff ${BASH_TSTOUT} extglob2.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-extglob3 b/tests/run-extglob3 new file mode 100644 index 0000000..6ebd674 --- /dev/null +++ b/tests/run-extglob3 @@ -0,0 +1,4 @@ +PATH=$PATH:`pwd` +export PATH +${THIS_SH} ./extglob3.tests > ${BASH_TSTOUT} +diff ${BASH_TSTOUT} extglob3.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-func b/tests/run-func new file mode 100644 index 0000000..a804364 --- /dev/null +++ b/tests/run-func @@ -0,0 +1,5 @@ +echo "warning: if you have exported functions defined in your environment," >&2 +echo "warning: they may show up as diff output." >&2 +echo "warning: if so, please do not consider this a test failure" >&2 +${THIS_SH} ./func.tests > ${BASH_TSTOUT} 2>&1 +diff ${BASH_TSTOUT} func.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-getopts b/tests/run-getopts new file mode 100644 index 0000000..4cfc592 --- /dev/null +++ b/tests/run-getopts @@ -0,0 +1,2 @@ +${THIS_SH} ./getopts.tests > ${BASH_TSTOUT} 2>&1 +diff ${BASH_TSTOUT} getopts.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-glob-test b/tests/run-glob-test new file mode 100644 index 0000000..246501c --- /dev/null +++ b/tests/run-glob-test @@ -0,0 +1,7 @@ +PATH=$PATH:`pwd` +export PATH + +( diff -a glob.right glob.right >/dev/null 2>&1 ) && AFLAG=-a + +${THIS_SH} ./glob.tests > ${BASH_TSTOUT} 2>&1 +diff ${AFLAG} ${BASH_TSTOUT} glob.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-globstar b/tests/run-globstar new file mode 100644 index 0000000..3aa01ed --- /dev/null +++ b/tests/run-globstar @@ -0,0 +1,4 @@ +PATH=$PATH:`pwd` +export PATH +${THIS_SH} ./globstar.tests > ${BASH_TSTOUT} 2>&1 +diff ${BASH_TSTOUT} globstar.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-heredoc b/tests/run-heredoc new file mode 100644 index 0000000..b655c4f --- /dev/null +++ b/tests/run-heredoc @@ -0,0 +1,6 @@ +echo "warning: UNIX versions number signals and schedule processes differently." >&2 +echo "warning: If output differing only in line numbers is produced, please" >&2 +echo "warning: do not consider this a test failure." >&2 + +${THIS_SH} ./heredoc.tests > ${BASH_TSTOUT} 2>&1 +diff ${BASH_TSTOUT} heredoc.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-herestr b/tests/run-herestr new file mode 100644 index 0000000..d6def9c --- /dev/null +++ b/tests/run-herestr @@ -0,0 +1,2 @@ +${THIS_SH} ./herestr.tests > ${BASH_TSTOUT} 2>&1 +diff ${BASH_TSTOUT} herestr.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-histexpand b/tests/run-histexpand new file mode 100644 index 0000000..a0fc331 --- /dev/null +++ b/tests/run-histexpand @@ -0,0 +1,4 @@ +echo "warning: all of these tests will fail if history has not been compiled" >&2 +echo "warning: into the shell" >&2 +${THIS_SH} ./histexp.tests > ${BASH_TSTOUT} 2>&1 +diff ${BASH_TSTOUT} histexp.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-history b/tests/run-history new file mode 100644 index 0000000..f4fa466 --- /dev/null +++ b/tests/run-history @@ -0,0 +1,4 @@ +echo "warning: all of these tests will fail if history has not been compiled" >&2 +echo "warning: into the shell" >&2 +${THIS_SH} ./history.tests > ${BASH_TSTOUT} 2>&1 +diff ${BASH_TSTOUT} history.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-ifs b/tests/run-ifs new file mode 100644 index 0000000..394d998 --- /dev/null +++ b/tests/run-ifs @@ -0,0 +1,2 @@ +${THIS_SH} ./ifs.tests > ${BASH_TSTOUT} 2>&1 +diff ${BASH_TSTOUT} ifs.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-ifs-posix b/tests/run-ifs-posix new file mode 100644 index 0000000..895c2e2 --- /dev/null +++ b/tests/run-ifs-posix @@ -0,0 +1,2 @@ +${THIS_SH} ./ifs-posix.tests > ${BASH_TSTOUT} 2>&1 +diff ${BASH_TSTOUT} ifs-posix.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-input-test b/tests/run-input-test new file mode 100644 index 0000000..412587c --- /dev/null +++ b/tests/run-input-test @@ -0,0 +1,2 @@ +${THIS_SH} < ./input-line.sh > ${BASH_TSTOUT} +diff ${BASH_TSTOUT} input.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-intl b/tests/run-intl new file mode 100644 index 0000000..c31d1d0 --- /dev/null +++ b/tests/run-intl @@ -0,0 +1,8 @@ +# See whether or not we can use `diff -a' +( diff -a ./intl.right ./intl.right >/dev/null 2>&1 ) && AFLAG=-a + +echo "warning: some of these tests will fail if you do not have UTF-8" >&2 +echo "warning: locales installed on your system." >&2 + +${THIS_SH} ./intl.tests > ${BASH_TSTOUT} +diff $AFLAG ${BASH_TSTOUT} intl.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-invert b/tests/run-invert new file mode 100644 index 0000000..b2bd06e --- /dev/null +++ b/tests/run-invert @@ -0,0 +1,2 @@ +${THIS_SH} ./invert.tests 2>&1 | grep -v '^expect' > ${BASH_TSTOUT} +diff ${BASH_TSTOUT} invert.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-iquote b/tests/run-iquote new file mode 100644 index 0000000..4fca94a --- /dev/null +++ b/tests/run-iquote @@ -0,0 +1,2 @@ +${THIS_SH} ./iquote.tests >${BASH_TSTOUT} 2>&1 +diff ${BASH_TSTOUT} iquote.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-jobs b/tests/run-jobs new file mode 100644 index 0000000..8429b0d --- /dev/null +++ b/tests/run-jobs @@ -0,0 +1,7 @@ +echo "warning: some of these tests may fail if job control has not been compiled" >&2 +echo "warning: into the shell" >&2 +echo "warning: there may be a message regarding a cat process dying due to a" >&2 +echo "warning: SIGHUP. Please disregard." >&2 + +${THIS_SH} ./jobs.tests > ${BASH_TSTOUT} 2>&1 +diff ${BASH_TSTOUT} jobs.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-lastpipe b/tests/run-lastpipe new file mode 100644 index 0000000..2edf5c4 --- /dev/null +++ b/tests/run-lastpipe @@ -0,0 +1,2 @@ +${THIS_SH} ./lastpipe.tests > ${BASH_TSTOUT} 2>&1 +diff ${BASH_TSTOUT} lastpipe.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-mapfile b/tests/run-mapfile new file mode 100644 index 0000000..e5d1b38 --- /dev/null +++ b/tests/run-mapfile @@ -0,0 +1,2 @@ +${THIS_SH} ./mapfile.tests > ${BASH_TSTOUT} 2>&1 +diff ${BASH_TSTOUT} mapfile.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-minimal b/tests/run-minimal new file mode 100644 index 0000000..bbb9da1 --- /dev/null +++ b/tests/run-minimal @@ -0,0 +1,51 @@ +#! /bin/sh +# +# run-minimal - a version of run-all for shells configured with +# --enable-minimal-config +# + +: ${TMPDIR:=/tmp} +export TMPDIR + +# basic /bin/sh syntax +SUFFIX=`${THIS_SH} -c 'echo $(( $RANDOM + $BASHPID ))'` + +BASH_TSTOUT=${TMPDIR}/bashtst-$SUFFIX # for now +export BASH_TSTOUT + +trap 'rm -f $BASH_TSTOUT' 0 + +PATH=.:$PATH # just to get the right version of printenv +export PATH + +# unset BASH_ENV only if it is set +[ "${BASH_ENV+set}" = "set" ] && unset BASH_ENV +# ditto for SHELLOPTS +#[ "${SHELLOPTS+set}" = "set" ] && unset SHELLOPTS + +: ${THIS_SH:=../bash} +export THIS_SH + +${THIS_SH} ./version.mini + +rm -f "$BASH_TSTOUT" + +echo Testing ${THIS_SH} +echo Any output from any test, unless otherwise noted, indicates a possible anomaly +for x in run-* +do + case $x in + $0) ;; + *.orig|*~) ;; + run-dollars|run-execscript|run-func|run-getopts|run-heredoc) echo $x ; sh $x ;; + run-ifs-tests|run-input-test|run-invert|run-more-exp|run-nquote) echo $x ; sh $x ;; + run-ifs-posix|run-posix2|run-posixpat|run-posixpipe) echo $x ; sh $x ;; + run-precedence|run-quote|run-read|run-rhs-exp|run-strip|run-tilde) echo $x ; sh $x ;; + run-dynvar) echo $x ; sh $x ;; + ;; + *) ;; + esac + rm -f "$BASH_TSTOUT" +done + +exit 0 diff --git a/tests/run-more-exp b/tests/run-more-exp new file mode 100644 index 0000000..0424a2f --- /dev/null +++ b/tests/run-more-exp @@ -0,0 +1,2 @@ +${THIS_SH} ./more-exp.tests 2>&1 | grep -v '^expect' > ${BASH_TSTOUT} +diff ${BASH_TSTOUT} more-exp.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-nameref b/tests/run-nameref new file mode 100644 index 0000000..b73e1b8 --- /dev/null +++ b/tests/run-nameref @@ -0,0 +1,4 @@ +echo "warning: some of these tests will fail if arrays have not" >&2 +echo "warning: been compiled into the shell" >&2 +${THIS_SH} ./nameref.tests > ${BASH_TSTOUT} 2>&1 +diff ${BASH_TSTOUT} nameref.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-new-exp b/tests/run-new-exp new file mode 100644 index 0000000..8777c7b --- /dev/null +++ b/tests/run-new-exp @@ -0,0 +1,10 @@ +echo "warning: two of these tests will fail if your OS does not support" >&2 +echo "warning: named pipes or the /dev/fd filesystem. If the tests of the" >&2 +echo "warning: process substitution mechanism fail, please do not consider" >&2 +echo "warning: this a test failure" >&2 +echo "warning: if you have exported variables beginning with the string _Q," >&2 +echo "warning: diff output may be generated. If so, please do not consider" >&2 +echo "warning: this a test failure" >&2 + +${THIS_SH} ./new-exp.tests 2>&1 | grep -v '^expect' > ${BASH_TSTOUT} +diff ${BASH_TSTOUT} new-exp.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-nquote b/tests/run-nquote new file mode 100644 index 0000000..03954b8 --- /dev/null +++ b/tests/run-nquote @@ -0,0 +1,2 @@ +${THIS_SH} ./nquote.tests 2>&1 | grep -v '^expect' > ${BASH_TSTOUT} +diff ${BASH_TSTOUT} nquote.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-nquote1 b/tests/run-nquote1 new file mode 100644 index 0000000..bd9e939 --- /dev/null +++ b/tests/run-nquote1 @@ -0,0 +1,4 @@ +echo "warning: several of these tests will fail if arrays have not" >&2 +echo "warning: been compiled into the shell." >&2 +${THIS_SH} ./nquote1.tests 2>&1 | grep -v '^expect' > ${BASH_TSTOUT} +diff ${BASH_TSTOUT} nquote1.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-nquote2 b/tests/run-nquote2 new file mode 100644 index 0000000..4648d3e --- /dev/null +++ b/tests/run-nquote2 @@ -0,0 +1,4 @@ +echo "warning: several of these tests will fail if arrays have not" >&2 +echo "warning: been compiled into the shell." >&2 +${THIS_SH} ./nquote2.tests 2>&1 | grep -v '^expect' > ${BASH_TSTOUT} +diff ${BASH_TSTOUT} nquote2.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-nquote3 b/tests/run-nquote3 new file mode 100644 index 0000000..4a3e32a --- /dev/null +++ b/tests/run-nquote3 @@ -0,0 +1,4 @@ +echo "warning: several of these tests will fail if arrays have not" >&2 +echo "warning: been compiled into the shell." >&2 +${THIS_SH} ./nquote3.tests 2>&1 | grep -v '^expect' > ${BASH_TSTOUT} +diff ${BASH_TSTOUT} nquote3.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-nquote4 b/tests/run-nquote4 new file mode 100644 index 0000000..985c311 --- /dev/null +++ b/tests/run-nquote4 @@ -0,0 +1,8 @@ +# See whether or not we can use `diff -a' +( diff -a ./nquote4.right ./nquote4.right >/dev/null 2>&1 ) && AFLAG=-a + +echo warning: some of these tests will fail if you do not have UTF-8 >&2 +echo warning: locales installed on your system >&2 + +${THIS_SH} ./nquote4.tests > ${BASH_TSTOUT} 2>&1 +diff ${AFLAG} ${BASH_TSTOUT} nquote4.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-nquote5 b/tests/run-nquote5 new file mode 100644 index 0000000..1d4c4aa --- /dev/null +++ b/tests/run-nquote5 @@ -0,0 +1,2 @@ +${THIS_SH} ./nquote5.tests 2>&1 | grep -v '^expect' > ${BASH_TSTOUT} +diff ${BASH_TSTOUT} nquote5.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-parser b/tests/run-parser new file mode 100644 index 0000000..ea1ec49 --- /dev/null +++ b/tests/run-parser @@ -0,0 +1,2 @@ +${THIS_SH} ./parser.tests > ${BASH_TSTOUT} 2>&1 +diff ${BASH_TSTOUT} parser.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-posix2 b/tests/run-posix2 new file mode 100644 index 0000000..cfa9571 --- /dev/null +++ b/tests/run-posix2 @@ -0,0 +1,2 @@ +${THIS_SH} ./posix2.tests 2>&1 | grep -v '^expect' > ${BASH_TSTOUT} +diff ${BASH_TSTOUT} posix2.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-posixexp b/tests/run-posixexp new file mode 100644 index 0000000..827b0e4 --- /dev/null +++ b/tests/run-posixexp @@ -0,0 +1,2 @@ +${THIS_SH} ./posixexp.tests > ${BASH_TSTOUT} 2>&1 +diff ${BASH_TSTOUT} posixexp.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-posixexp2 b/tests/run-posixexp2 new file mode 100644 index 0000000..1e6b2d9 --- /dev/null +++ b/tests/run-posixexp2 @@ -0,0 +1,2 @@ +${THIS_SH} ./posixexp2.tests > ${BASH_TSTOUT} 2>&1 +diff ${BASH_TSTOUT} posixexp2.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-posixpat b/tests/run-posixpat new file mode 100644 index 0000000..8937948 --- /dev/null +++ b/tests/run-posixpat @@ -0,0 +1,2 @@ +${THIS_SH} ./posixpat.tests > ${BASH_TSTOUT} +diff ${BASH_TSTOUT} posixpat.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-posixpipe b/tests/run-posixpipe new file mode 100644 index 0000000..5f099e2 --- /dev/null +++ b/tests/run-posixpipe @@ -0,0 +1,2 @@ +${THIS_SH} ./posixpipe.tests > ${BASH_TSTOUT} 2>&1 +diff ${BASH_TSTOUT} posixpipe.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-precedence b/tests/run-precedence new file mode 100644 index 0000000..de33224 --- /dev/null +++ b/tests/run-precedence @@ -0,0 +1,2 @@ +${THIS_SH} ./precedence > ${BASH_TSTOUT} +diff ${BASH_TSTOUT} prec.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-printf b/tests/run-printf new file mode 100644 index 0000000..e242787 --- /dev/null +++ b/tests/run-printf @@ -0,0 +1,7 @@ +# See whether or not we can use `diff -a' +#( diff -a ./printf.tests ./printf.tests >/dev/null 2>&1 ) && AFLAG=-a + +# use cat -v (and assume it's there) to make control chars visible +${THIS_SH} ./printf.tests 2>&1 | cat -v > ${BASH_TSTOUT} +#diff $AFLAG ${BASH_TSTOUT} printf.right && rm -f ${BASH_TSTOUT} +diff ${BASH_TSTOUT} printf.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-procsub b/tests/run-procsub new file mode 100644 index 0000000..796faaa --- /dev/null +++ b/tests/run-procsub @@ -0,0 +1,7 @@ +echo "warning: all of these tests will fail if process substitution has not" >&2 +echo "warning: been compiled into the shell or if the OS does not provide" >&2 +echo "warning: FIFOs or /dev/fd. Some tests may fail if the OS does not" >&2 +echo "warning: provide FIFOs." >&2 + +${THIS_SH} ./procsub.tests > ${BASH_TSTOUT} 2>&1 +diff ${BASH_TSTOUT} procsub.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-quote b/tests/run-quote new file mode 100644 index 0000000..2543666 --- /dev/null +++ b/tests/run-quote @@ -0,0 +1,2 @@ +${THIS_SH} ./quote.tests >${BASH_TSTOUT} 2>&1 +diff ${BASH_TSTOUT} quote.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-read b/tests/run-read new file mode 100644 index 0000000..5ec07e2 --- /dev/null +++ b/tests/run-read @@ -0,0 +1,4 @@ +echo "warning: please do not consider output differing only in the amount of" >&2 +echo "warning: white space to be an error." >&2 +${THIS_SH} ./read.tests > ${BASH_TSTOUT} 2>&1 +diff ${BASH_TSTOUT} read.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-redir b/tests/run-redir new file mode 100644 index 0000000..071af6e --- /dev/null +++ b/tests/run-redir @@ -0,0 +1,7 @@ +echo "warning: the text of a system error message may vary between systems and" >&2 +echo "warning: produce diff output." >&2 +echo "warning: if the text of an error message concerning \`redir1.*' not being" >&2 +echo "warning: found or messages concerning bad file descriptors produce diff" >&2 +echo "warning: output, please do not consider it a test failure" >&2 +${THIS_SH} ./redir.tests > ${BASH_TSTOUT} 2>&1 +diff ${BASH_TSTOUT} redir.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-rhs-exp b/tests/run-rhs-exp new file mode 100644 index 0000000..de8ae0e --- /dev/null +++ b/tests/run-rhs-exp @@ -0,0 +1,2 @@ +${THIS_SH} ./rhs-exp.tests 2>&1 > ${BASH_TSTOUT} +diff ${BASH_TSTOUT} rhs-exp.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-rsh b/tests/run-rsh new file mode 100644 index 0000000..6770699 --- /dev/null +++ b/tests/run-rsh @@ -0,0 +1,2 @@ +${THIS_SH} ./rsh.tests > ${BASH_TSTOUT} 2>&1 +diff ${BASH_TSTOUT} rsh.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-set-e b/tests/run-set-e new file mode 100644 index 0000000..eed17fa --- /dev/null +++ b/tests/run-set-e @@ -0,0 +1,2 @@ +${THIS_SH} ./set-e.tests > ${BASH_TSTOUT} +diff ${BASH_TSTOUT} set-e.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-set-x b/tests/run-set-x new file mode 100644 index 0000000..b999e69 --- /dev/null +++ b/tests/run-set-x @@ -0,0 +1,11 @@ +#!../bash +#$Id: run-set-x,v 1.1 2002/12/09 13:12:37 rockyb Exp $ + +TEST_NAME='set-x' +TEST_FILE="/tmp/${TEST_NAME}.check" +${THIS_SH} ./${TEST_NAME}.tests > $TEST_FILE 2>&1 < /dev/null +set -f +diff $TEST_FILE ${TEST_NAME}.right && rm -f $TEST_FILE + +# Return code tells testing mechanism whether passed or not. +exit $? diff --git a/tests/run-shopt b/tests/run-shopt new file mode 100644 index 0000000..02c43e7 --- /dev/null +++ b/tests/run-shopt @@ -0,0 +1,2 @@ +${THIS_SH} ./shopt.tests > ${BASH_TSTOUT} 2>&1 +diff ${BASH_TSTOUT} shopt.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-strip b/tests/run-strip new file mode 100644 index 0000000..46a9da9 --- /dev/null +++ b/tests/run-strip @@ -0,0 +1,2 @@ +${THIS_SH} ./strip.tests > ${BASH_TSTOUT} +diff ${BASH_TSTOUT} strip.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-test b/tests/run-test new file mode 100644 index 0000000..d68791c --- /dev/null +++ b/tests/run-test @@ -0,0 +1,4 @@ +unset GROUPS UID 2>/dev/null + +${THIS_SH} ./test.tests >${BASH_TSTOUT} 2>&1 +diff ${BASH_TSTOUT} test.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-tilde b/tests/run-tilde new file mode 100644 index 0000000..9460225 --- /dev/null +++ b/tests/run-tilde @@ -0,0 +1,2 @@ +${THIS_SH} ./tilde.tests > ${BASH_TSTOUT} +diff ${BASH_TSTOUT} tilde.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-tilde2 b/tests/run-tilde2 new file mode 100644 index 0000000..fa7e7d6 --- /dev/null +++ b/tests/run-tilde2 @@ -0,0 +1,2 @@ +${THIS_SH} ./tilde2.tests > ${BASH_TSTOUT} +diff ${BASH_TSTOUT} tilde2.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-trap b/tests/run-trap new file mode 100644 index 0000000..e3331ed --- /dev/null +++ b/tests/run-trap @@ -0,0 +1,6 @@ +echo "warning: UNIX versions number signals and schedule processes differently." >&2 +echo "warning: If output differing only in line numbers is produced, please" >&2 +echo "warning: do not consider this a test failure." >&2 + +${THIS_SH} ./trap.tests > ${BASH_TSTOUT} 2>&1 +diff ${BASH_TSTOUT} trap.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-type b/tests/run-type new file mode 100644 index 0000000..499cb4e --- /dev/null +++ b/tests/run-type @@ -0,0 +1,2 @@ +${THIS_SH} ./type.tests > ${BASH_TSTOUT} 2>&1 +diff ${BASH_TSTOUT} type.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-varenv b/tests/run-varenv new file mode 100644 index 0000000..f147d70 --- /dev/null +++ b/tests/run-varenv @@ -0,0 +1,2 @@ +${THIS_SH} ./varenv.tests 2>&1 | grep -v '^expect' > ${BASH_TSTOUT} +diff ${BASH_TSTOUT} varenv.right && rm -f ${BASH_TSTOUT} diff --git a/tests/run-vredir b/tests/run-vredir new file mode 100644 index 0000000..2a4faf3 --- /dev/null +++ b/tests/run-vredir @@ -0,0 +1,2 @@ +${THIS_SH} ./vredir.tests > ${BASH_TSTOUT} 2>&1 +diff ${BASH_TSTOUT} vredir.right && rm -f ${BASH_TSTOUT} diff --git a/tests/set-e.right b/tests/set-e.right new file mode 100644 index 0000000..e2a9f2c --- /dev/null +++ b/tests/set-e.right @@ -0,0 +1,72 @@ +95 +96 +97 +98 +99 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +1 +1 +ok +hi +while succeeded +until succeeded: 4 +if succeeded +AND list succeeded +OR list succeeded +! succeeded +eval succeeded +! eval succeeded -- 1 +! eval succeeded -- 2 +a +0 +b +0 +after 1 +a +0 +non-posix foo +after brace group failure: 1 +A 1 +B 0 +C 0 +D 0 +D 1 +A 1 +B 0 +C 0 +D 0 +D 1 +A 1 +B 0 +C 0 +A 1 +B 1 +C 0 +B 0 +C 0 +after negation 1: 0 +after negation 2: 0 +after negation 3: 1 +after negation 4: 0 +after brace pipeline +foo +after failure 1 +after failure 2 +after failure 3 +true || false no exit +false || true no exit +false && false no exit +A: +B: +ehB +C: +D: diff --git a/tests/set-e.tests b/tests/set-e.tests new file mode 100644 index 0000000..d38edf6 --- /dev/null +++ b/tests/set-e.tests @@ -0,0 +1,111 @@ +if : ; then + set -e + N=95 + while :; do + # expr returns 1 if expression is null or 0 + set +e + N_MOD_100=`expr $N % 100` + set -e + echo $N_MOD_100 + N=`expr $N + 1` + if [ $N -eq 110 ]; then + break + fi + done + set +e +fi + +( +set -e +false +echo bad +) +echo $? + +x=$( +set -e +false +echo bad +) +echo $? $x + +# command subst should not inherit -e +set -e +echo $(false; echo ok) + +if set +e +then + false +fi +echo hi + +set -e + +# a failing command in the compound list following a while, until, or +# if should not cause the shell to exit + +while false; do + echo hi +done +echo while succeeded + +x=1 +until (( x == 4 )); do + x=4 +done +echo until succeeded: $x + +if false; then + echo oops +fi +echo if succeeded + +# failing commands that are part of an AND or OR list should not +# cause the shell to exit +false && echo AND list failed +echo AND list succeeded + +false || echo OR list succeeded + +! false +echo ! succeeded + +# make sure eval preserves the state of the -e flag and `!' reserved word +set -e +if eval false; then + echo oops +fi +echo eval succeeded + +! eval false +echo ! eval succeeded -- 1 + +! eval '(exit 5)' +echo ! eval succeeded -- 2 + +set -e +until builtin false; do echo a; break; done +echo $? + +until eval false; do echo b; break; done +echo $? + +: ${TMPDIR:=/tmp} +FN=$TMPDIR/set-e-$$ +cat > $FN << EOF +false +echo after 1 +false +EOF + +set -e +until . $FN; do echo a; break; done +echo $? + +rm -f $FN + +set +e + +${THIS_SH} ./set-e1.sub +${THIS_SH} ./set-e2.sub +${THIS_SH} ./set-e3.sub diff --git a/tests/set-e1.sub b/tests/set-e1.sub new file mode 100644 index 0000000..a800560 --- /dev/null +++ b/tests/set-e1.sub @@ -0,0 +1,59 @@ +# subshell failure should cause the shell to exit silently +${THIS_SH} -ce '(exit 17) ; echo "after (exit 17): $?"' + +# pipeline failure should cause shell to exit silently +${THIS_SH} -c 'set -e ; false | echo foo | while read x ; do ( exit 17 ) ; done; echo after pipeline subshell;' + +# should be silent in posix mode +${THIS_SH} -c 'set -o posix; set -e ; z=$(false;echo posix foo) ; echo $z' +# but echo foo in non-posix +${THIS_SH} -c 'set -e ; z=$(false;echo non-posix foo) ; echo $z' + +${THIS_SH} -ce 'x=$(false) ; echo "x=\$(false) does not exit"' + +${THIS_SH} -ce '{ false; echo false in brace group does not exit; }' +echo after brace group failure: $? + +${THIS_SH} -ce '(false ; echo A $?) && echo B $?; echo C $?'; echo D $? + +${THIS_SH} -ce '(false ; echo A $?) ; echo B $?; echo C $?'; echo D $? + +${THIS_SH} -ce 'f() (false ; echo A $?); f && echo B $?; echo C $?'; echo D $? + +${THIS_SH} -ce 'f() (false ; echo A $?) ; f; echo B $?; echo C $?'; echo D $? + +${THIS_SH} -ce 'if false; echo A $?; then echo B $?; fi'; echo C $? + +${THIS_SH} -ce '! { false; echo A $?; } | cat; echo B $?'; echo C $? + +${THIS_SH} -ce '{ false; echo A $?; } | cat ; echo B $?'; echo C $? + +set -e + +! false +echo after negation 1: $? + +! false | false +echo after negation 2: $? + +! true +echo after negation 3: $? + +! (false) +echo after negation 4: $? + +{ false ; echo foo; } | cat +echo after brace pipeline + +false | echo foo | cat +echo after failure 1 + +false | (echo foo; false) | true +echo after failure 2 + +false | echo foo | while read x ; do ( exit 17 ) ; done | true +echo after failure 3 + +# this pipeline failure should cause the shell to exit +false | echo foo | false +echo after failure 4 diff --git a/tests/set-e2.sub b/tests/set-e2.sub new file mode 100644 index 0000000..de04e99 --- /dev/null +++ b/tests/set-e2.sub @@ -0,0 +1,10 @@ +${THIS_SH} -ce 'true || false ; echo "true || false no exit"' +${THIS_SH} -ce 'false || false ; echo "false || false no exit"' +${THIS_SH} -ce 'false || true ; echo "false || true no exit"' + +${THIS_SH} -ce 'false && false ; echo "false && false no exit"' +${THIS_SH} -ce 'true && false ; echo "true && false no exit"' + +${THIS_SH} -ce 'true && (exit 1) ; echo "true && (exit 1) no exit"' +${THIS_SH} -ce 'true && true|false ; echo "true && true|false no exit"' +${THIS_SH} -ce 'true && true|(false) ; echo "true && true|(false) no exit"' diff --git a/tests/set-e3.sub b/tests/set-e3.sub new file mode 100644 index 0000000..db176b1 --- /dev/null +++ b/tests/set-e3.sub @@ -0,0 +1,10 @@ +foo() +{ + echo A: + . ./set-e3a.sub + echo D: +} + +# should run all the way through; foo being called in a context where set -e +# is ignored means that that condition persists through sourcing the file +foo && true diff --git a/tests/set-e3a.sub b/tests/set-e3a.sub new file mode 100644 index 0000000..5d008e7 --- /dev/null +++ b/tests/set-e3a.sub @@ -0,0 +1,7 @@ +echo B: + +set -e +echo $- +false + +echo C: diff --git a/tests/set-x.right b/tests/set-x.right new file mode 100644 index 0000000..259602e --- /dev/null +++ b/tests/set-x.right @@ -0,0 +1,60 @@ ++ (( i=0 )) ++ (( i<=5 )) ++ x=0 ++ (( i++ )) ++ (( i<=5 )) ++ x=0 ++ (( i++ )) ++ (( i<=5 )) ++ x=0 ++ (( i++ )) ++ (( i<=5 )) ++ x=0 ++ (( i++ )) ++ (( i<=5 )) ++ x=0 ++ (( i++ )) ++ (( i<=5 )) ++ x=0 ++ (( i++ )) ++ (( i<=5 )) ++ for i in 0 1 2 ++ x=i ++ for i in 0 1 2 ++ x=i ++ for i in 0 1 2 ++ x=i ++ case x in ++ x=i ++ foo=one ++ foo+=two ++ echo onetwo +onetwo ++ set +x +1 +2 +3 +4 ++ for f in a b c d e ++ echo a +a ++ for f in a b c d e ++ echo b +b ++ for f in a b c d e ++ echo c +c ++ for f in a b c d e ++ echo d +d ++ for f in a b c d e ++ echo e +e ++ set +x +TRACEFILE: ++ echo 1 ++ echo 2 ++ echo 3 ++ echo 4 ++ unset BASH_XTRACEFD +===== diff --git a/tests/set-x.tests b/tests/set-x.tests new file mode 100755 index 0000000..531c53f --- /dev/null +++ b/tests/set-x.tests @@ -0,0 +1,25 @@ +#!../bash +# $Id: set-x.tests,v 1.1 2002/12/09 13:12:37 rockyb Exp $ +# +# Test that "set -x" shows what we think it should. +# +set -x +for ((i=0; i<=5; i++ )) ; do + x=0 +done +for i in 0 1 2 ; do + x=i +done +case x in + 0) x=i ;; + *) x=i ;; +esac + +foo=one +foo+=two +echo $foo + +set +x + +# test BASH_XTRACEFD +${THIS_SH} ./set-x1.sub diff --git a/tests/set-x1.sub b/tests/set-x1.sub new file mode 100644 index 0000000..b2aa216 --- /dev/null +++ b/tests/set-x1.sub @@ -0,0 +1,25 @@ +: ${TMPDIR:=/var/tmp} +TRACEFILE=$TMPDIR/bash-trace-$$ +trap 'rm -f $TRACEFILE' 0 1 2 3 6 15 + +exec 4>$TRACEFILE +BASH_XTRACEFD=4 + +set -x + +echo 1 +echo 2 +echo 3 +echo 4 + +unset BASH_XTRACEFD + +for f in a b c d e; do echo $f ; done + +set +x + +echo TRACEFILE: +cat $TRACEFILE +echo ===== + +exit 0 diff --git a/tests/shopt.right b/tests/shopt.right new file mode 100644 index 0000000..08db75f --- /dev/null +++ b/tests/shopt.right @@ -0,0 +1,296 @@ +./shopt.tests: line 2: shopt: -z: invalid option +shopt: usage: shopt [-pqsu] [-o] [optname ...] +-- +shopt -u autocd +shopt -u assoc_expand_once +shopt -u cdable_vars +shopt -s cdspell +shopt -u checkhash +shopt -u checkjobs +shopt -u checkwinsize +shopt -s cmdhist +shopt -u compat31 +shopt -u compat32 +shopt -u compat40 +shopt -u compat41 +shopt -u compat42 +shopt -u compat43 +shopt -u compat44 +shopt -s complete_fullquote +shopt -u direxpand +shopt -u dirspell +shopt -u dotglob +shopt -u execfail +shopt -s expand_aliases +shopt -u extdebug +shopt -u extglob +shopt -s extquote +shopt -u failglob +shopt -s force_fignore +shopt -s globasciiranges +shopt -u globstar +shopt -u gnu_errfmt +shopt -u histappend +shopt -u histreedit +shopt -u histverify +shopt -s hostcomplete +shopt -u huponexit +shopt -u inherit_errexit +shopt -s interactive_comments +shopt -u lastpipe +shopt -u lithist +shopt -u localvar_inherit +shopt -u localvar_unset +shopt -u login_shell +shopt -u mailwarn +shopt -u no_empty_cmd_completion +shopt -u nocaseglob +shopt -u nocasematch +shopt -u nullglob +shopt -s progcomp +shopt -u progcomp_alias +shopt -s promptvars +shopt -u restricted_shell +shopt -u shift_verbose +shopt -s sourcepath +shopt -u xpg_echo +-- +shopt -u huponexit +shopt -u checkwinsize +shopt -s sourcepath +-- +shopt -s cdspell +shopt -s cmdhist +shopt -s complete_fullquote +shopt -s expand_aliases +shopt -s extquote +shopt -s force_fignore +shopt -s globasciiranges +shopt -s hostcomplete +shopt -s interactive_comments +shopt -s progcomp +shopt -s promptvars +shopt -s sourcepath +-- +shopt -u autocd +shopt -u assoc_expand_once +shopt -u cdable_vars +shopt -u checkhash +shopt -u checkjobs +shopt -u checkwinsize +shopt -u compat31 +shopt -u compat32 +shopt -u compat40 +shopt -u compat41 +shopt -u compat42 +shopt -u compat43 +shopt -u compat44 +shopt -u direxpand +shopt -u dirspell +shopt -u dotglob +shopt -u execfail +shopt -u extdebug +shopt -u extglob +shopt -u failglob +shopt -u globstar +shopt -u gnu_errfmt +shopt -u histappend +shopt -u histreedit +shopt -u histverify +shopt -u huponexit +shopt -u inherit_errexit +shopt -u lastpipe +shopt -u lithist +shopt -u localvar_inherit +shopt -u localvar_unset +shopt -u login_shell +shopt -u mailwarn +shopt -u no_empty_cmd_completion +shopt -u nocaseglob +shopt -u nocasematch +shopt -u nullglob +shopt -u progcomp_alias +shopt -u restricted_shell +shopt -u shift_verbose +shopt -u xpg_echo +-- +autocd off +assoc_expand_once off +cdable_vars off +checkhash off +checkjobs off +checkwinsize off +compat31 off +compat32 off +compat40 off +compat41 off +compat42 off +compat43 off +compat44 off +direxpand off +dirspell off +dotglob off +execfail off +extdebug off +extglob off +failglob off +globstar off +gnu_errfmt off +histappend off +histreedit off +histverify off +huponexit off +inherit_errexit off +lastpipe off +lithist off +localvar_inherit off +localvar_unset off +login_shell off +mailwarn off +no_empty_cmd_completion off +nocaseglob off +nocasematch off +nullglob off +progcomp_alias off +restricted_shell off +shift_verbose off +xpg_echo off +-- +set +o allexport +set -o braceexpand +set -o emacs +set +o errexit +set +o errtrace +set +o functrace +set -o hashall +set -o histexpand +set -o history +set +o ignoreeof +set -o interactive-comments +set +o keyword +set -o monitor +set +o noclobber +set +o noexec +set +o noglob +set +o nolog +set +o notify +set +o nounset +set +o onecmd +set +o physical +set +o pipefail +set +o posix +set -o privileged +set +o verbose +set +o vi +set +o xtrace +-- +allexport off +braceexpand on +emacs on +errexit off +errtrace off +functrace off +hashall on +histexpand on +history on +ignoreeof off +interactive-comments on +keyword off +monitor on +noclobber off +noexec off +noglob off +nolog off +notify off +nounset off +onecmd off +physical off +pipefail off +posix off +privileged on +verbose off +vi off +xtrace off +-- +set +o allexport +set -o braceexpand +set -o emacs +set +o errexit +set +o errtrace +set +o functrace +set -o hashall +set -o histexpand +set -o history +set +o ignoreeof +set -o interactive-comments +set +o keyword +set -o monitor +set +o noclobber +set +o noexec +set +o noglob +set +o nolog +set +o notify +set +o nounset +set +o onecmd +set +o physical +set +o pipefail +set +o posix +set -o privileged +set +o verbose +set +o vi +set +o xtrace +-- +set -o history +set +o verbose +-- +set -o braceexpand +set -o emacs +set -o hashall +set -o histexpand +set -o history +set -o interactive-comments +set -o monitor +set -o privileged +-- +set +o allexport +set +o errexit +set +o errtrace +set +o functrace +set +o ignoreeof +set +o keyword +set +o noclobber +set +o noexec +set +o noglob +set +o nolog +set +o notify +set +o nounset +set +o onecmd +set +o physical +set +o pipefail +set +o posix +set +o verbose +set +o vi +set +o xtrace +-- +allexport off +errexit off +errtrace off +functrace off +ignoreeof off +keyword off +noclobber off +noexec off +noglob off +nolog off +notify off +nounset off +onecmd off +physical off +pipefail off +posix off +verbose off +vi off +xtrace off +-- +./shopt.tests: line 93: shopt: xyz1: invalid shell option name +./shopt.tests: line 94: shopt: xyz1: invalid option name diff --git a/tests/shopt.tests b/tests/shopt.tests new file mode 100644 index 0000000..d4f2a8b --- /dev/null +++ b/tests/shopt.tests @@ -0,0 +1,94 @@ +# let's try an error message first +shopt -z + +# first, set up a known environment +shopt -u cdable_vars +shopt -s cdspell +shopt -u checkhash +shopt -u checkwinsize +shopt -s cmdhist +shopt -u dotglob +shopt -u execfail +shopt -s expand_aliases +shopt -u extglob +shopt -u histreedit +shopt -u histappend +shopt -u histverify +shopt -s hostcomplete +shopt -u huponexit +shopt -s interactive_comments +shopt -u lithist +shopt -u mailwarn +shopt -u nocaseglob +shopt -u nullglob +shopt -s promptvars +shopt -u shift_verbose +shopt -s sourcepath +shopt -u xpg_echo + +# Now, start checking the output +builtin printf -- "--\n" +shopt -p # list 'em all +builtin printf -- "--\n" +# test specific variables +shopt -p huponexit +shopt -p checkwinsize +shopt -p sourcepath + +builtin printf -- "--\n" +shopt -s -p +builtin printf -- "--\n" +shopt -u -p +builtin printf -- "--\n" +shopt -u + +# Now set up another known environment +set +o allexport +set -o braceexpand +set +o errexit +set -o hashall +set -o histexpand +set +o keyword +set -o monitor +set +o noclobber +set +o noexec +set +o noglob +set +o notify +set +o nounset +set +o onecmd +set +o physical +set -o privileged +set +o verbose +set +o xtrace +set -o history +set +o ignoreeof +set -o interactive-comments +set +o posix +set -o emacs +set +o vi + +# list 'em all +builtin printf -- "--\n" +shopt -o -p + +builtin printf -- "--\n" +set -o +builtin printf -- "--\n" +set +o + +# test specific variables +builtin printf -- "--\n" +shopt -p -o history +shopt -p -o verbose + +builtin printf -- "--\n" +shopt -s -p -o +builtin printf -- "--\n" +shopt -u -p -o +builtin printf -- "--\n" +shopt -u -o + +# errors +builtin printf -- "--\n" +shopt -p xyz1 +shopt -o -p xyz1 diff --git a/tests/source1.sub b/tests/source1.sub new file mode 100644 index 0000000..8b8586f --- /dev/null +++ b/tests/source1.sub @@ -0,0 +1 @@ +echo $AVAR diff --git a/tests/source2.sub b/tests/source2.sub new file mode 100644 index 0000000..7a031a1 --- /dev/null +++ b/tests/source2.sub @@ -0,0 +1,5 @@ +echo in source.sub2, calling return + +return 5 + +echo oops -- return in source.sub2 failed diff --git a/tests/source3.sub b/tests/source3.sub new file mode 100644 index 0000000..4a12501 --- /dev/null +++ b/tests/source3.sub @@ -0,0 +1 @@ +echo "$@" diff --git a/tests/source4.sub b/tests/source4.sub new file mode 100644 index 0000000..717c1ab --- /dev/null +++ b/tests/source4.sub @@ -0,0 +1 @@ +set -- m n o p diff --git a/tests/source5.sub b/tests/source5.sub new file mode 100644 index 0000000..e618809 --- /dev/null +++ b/tests/source5.sub @@ -0,0 +1,19 @@ +LC_ALL=en_US.UTF-8 +unset LC_ALL +unset LANG +export LC_ALL=C +export LANG=C + +set +o posix + +# attempting to source a non-existant file is not an error... +. /tmp/source-notthere + +echo after bad source 1 + +set -o posix + +# ...unless you're in posix mode +. /tmp/source-notthere + +echo after bad source 2 diff --git a/tests/source6.sub b/tests/source6.sub new file mode 100644 index 0000000..43db203 --- /dev/null +++ b/tests/source6.sub @@ -0,0 +1,36 @@ +# tests sourcing non-regular files, fixed post-3.2 + +: ${TMPDIR:=/tmp} + +TMPFN=$TMPDIR/foo-$$ + +rm -f $TMPFN +echo "echo one - OK" > $TMPFN +. $TMPFN +echo $? +rm -f $TMPFN + +# non-regular readable file +. /dev/null +echo $? + +# FIFO or pipe via /dev/fd +. <(echo "echo two - OK") +echo $? + +# pipe +if [ -e /dev/stdin ]; then +echo "echo three - OK" | . /dev/stdin +echo $? +else +# no /dev/stdin, just fake it +echo "three - OK" ; echo 0 +fi + +# FIFO +mkfifo $TMPDIR/fifo-$$ +echo "echo four - OK" > $TMPDIR/fifo-$$ & +sleep 1 # allow the child echo to execute +. $TMPDIR/fifo-$$ +echo $? +rm -f $TMPDIR/fifo-$$ diff --git a/tests/source7.sub b/tests/source7.sub new file mode 100644 index 0000000..8ca0aef --- /dev/null +++ b/tests/source7.sub @@ -0,0 +1,40 @@ +shopt -s expand_aliases + +: ${TMPDIR:=/var/tmp} + +echo '((echo abc; echo def;); echo ghi)' > $TMPDIR/x28-$$ +. $TMPDIR/x28-$$ +rm -f $TMPDIR/x28-$$ + +echo after + +TMPFILE=$TMPDIR/x29-$$ + +echo "#! ${THIS_SH}" >$TMPFILE +cat >> $TMPFILE << \EOF + +(echo -n "$1 "; echo subshell) +EOF +chmod 755 $TMPFILE + +alias foo1='$TMPFILE one.1; source $TMPFILE two.1; source $TMPFILE three.1; $TMPFILE four.1' +alias foo2='$TMPFILE one.2; +source $TMPFILE two.2; +source $TMPFILE three.2; +$TMPFILE four.2; +' + +foo1 +foo2 + +echo x29 - done +rm -f $TMPFILE + +# this is also treated similarly to an alias expansion internally +((echo abc; echo def;); echo ghi) + +if (((4+4) + (4 + 7))); then + echo ok +fi + +(()) # make sure the null expression works OK diff --git a/tests/strip.right b/tests/strip.right new file mode 100644 index 0000000..dfab897 --- /dev/null +++ b/tests/strip.right @@ -0,0 +1,12 @@ +'' +' ab ' +' ' +'' +'' +'' +'ababababababab' +'ababababababab ' +'ababababababab ' +'abababa +bababab ' +'' diff --git a/tests/strip.tests b/tests/strip.tests new file mode 100644 index 0000000..b669b52 --- /dev/null +++ b/tests/strip.tests @@ -0,0 +1,22 @@ +v=`echo "" ; echo "" ; echo ""` +echo "'$v'" +v=`echo -n " ab "` +echo "'$v'" +v=`echo -n " "` +echo "'$v'" +v=`echo -n ""` +echo "'$v'" +v=`echo ""` +echo "'$v'" +v=`echo` +echo "'$v'" +v=`echo ababababababab` +echo "'$v'" +v=`echo "ababababababab "` +echo "'$v'" +v=`echo -n "ababababababab "` +echo "'$v'" +v=`echo -ne "abababa\nbababab "` +echo "'$v'" +v="`echo -e '\n\n\n\n'`" +echo "'$v'" diff --git a/tests/test-glue-functions b/tests/test-glue-functions new file mode 100644 index 0000000..07ad821 --- /dev/null +++ b/tests/test-glue-functions @@ -0,0 +1,13 @@ +# shell functions to include in multiple test files + +# squeeze out blanks to avoid white space differences in od implementations +_intl_normalize_spaces() +{ + sed -e 's/[[:space:]]\{1,\}/ /g' -e 's/[[:space:]]*$//' +} + +# avoid whitespace differences in wc implementations +_cut_leading_spaces() +{ + sed -e 's/^[ ]*//g' +} diff --git a/tests/test.right b/tests/test.right new file mode 100644 index 0000000..9832bd6 --- /dev/null +++ b/tests/test.right @@ -0,0 +1,295 @@ +t -a noexist +1 +t -a run-all +0 +t -b run-all +1 +t -b /dev/jb1a +1 +t -c run-all +1 +t -c /dev/tty +0 +t -d run-all +1 +t -d /etc +0 +t -d "" +1 +b -d "" +1 +t -e noexist +1 +t -e run-all +0 +t -f noexist +1 +t -f /dev/tty +1 +t -f run-all +0 +t -g run-all +1 +t -g /tmp/test.setgid +0 +t -k run-all +1 +t -n "" +1 +t -n "hello" +0 +t -p run-all +1 +t -r noexist +1 +t -r /tmp/test.noread +1 +t -r run-all +0 +t -s noexist +1 +t -s /dev/null +1 +t -s run-all +0 +t -t 20 +1 +t -t 0 +0 +t -u noexist +1 +t -u run-all +1 +t -u /tmp/test.setuid +0 +t -w noexist +1 +t -w /tmp/test.nowrite +1 +t -w /dev/null +0 +t -x noexist +1 +t -x /tmp/test.exec +0 +t -x /tmp/test.noexec +1 +t -z "" +0 +t -z "foo" +1 +t "foo" +0 +t "" +1 +t -O /tmp/test.owner +0 +t -S /tmp/test.socket +1 +t -N /tmp/test.newer +0 +t "hello" = "hello" +0 +t "hello" = "goodbye" +1 +t "hello" == "hello" +0 +t "hello" == "goodbye" +1 +t "hello" != "hello" +1 +t "hello" != "goodbye" +0 +t "hello" < "goodbye" +1 +t "hello" > "goodbye" +0 +t ! "hello" > "goodbye" +1 +t 200 -eq 200 +0 +t 34 -eq 222 +1 +t -32 -eq 32 +1 +t 200 -ne 200 +1 +t 34 -ne 222 +0 +t 200 -gt 200 +1 +t 340 -gt 222 +0 +t 200 -ge 200 +0 +t 34 -ge 222 +1 +t 200 -lt 200 +1 +t 34 -lt 222 +0 +t 200 -le 200 +0 +t 340 -le 222 +1 +t 700 -le 1000 -a -n "1" -a "20" = "20" +0 +t ! \( 700 -le 1000 -a -n "1" -a "20" = "20" \) +1 +t /tmp/abc -nt /tmp/def +1 +t /tmp/abc -ot /tmp/def +0 +t /tmp/def -nt /tmp/abc +0 +t /tmp/def -ot /tmp/abc +1 +t /tmp/abc -ef /tmp/def +1 +t /tmp/abc -ef /tmp/ghi +0 +t -r /dev/fd/0 +0 +t -w /dev/fd/1 +0 +t -w /dev/fd/2 +0 +t -r /dev/stdin +0 +t -w /dev/stdout +0 +t -w /dev/stderr +0 +t +1 +b +1 +t 12 -eq 34 +1 +t ! 12 -eq 34 +0 +t -n abcd -o aaa +0 +t -n abcd -o -z aaa +0 +t -n abcd -a aaa +0 +t -n abcd -a -z aaa +1 +t -o allexport +1 +t ! -o allexport +0 +t -v unset +1 +t -v set +0 +t -v set +0 +t xx -a yy +0 +t xx -o "" +0 +t xx -a "" +1 +t -X -a -X +0 +t -X -o -X +0 +t -X -o "" +0 +t -X -a "" +1 +t "" -a -X +1 +t "" -o -X +0 +t "" -a "" +1 +t "" -o "" +1 +t true -o -X +0 +t true -a -X +0 +t ( -E ) +0 +t ( "" ) +1 +t ! -z "$z" +0 +t ! -n "$z" +1 +t "$zero" +1 +t ! "$zero" +0 +b "$zero" +1 +b ! "$zero" +0 +t -G /tmp/test.group +0 +t -h /tmp/test.symlink +0 +t 4+3 -eq 7 +./test.tests: line 13: test: 4+3: integer expression expected +2 +b 4-5 -eq 7 +./test.tests: line 7: [: 4+3: integer expression expected +2 +t 9 -eq 4+5 +./test.tests: line 13: test: 4+5: integer expression expected +2 +b 9 -eq 4+5 +./test.tests: line 7: [: 4+5: integer expression expected +2 +t A -eq 7 +./test.tests: line 13: test: A: integer expression expected +2 +b A -eq 7 +./test.tests: line 7: [: A: integer expression expected +2 +t 9 -eq B +./test.tests: line 13: test: B: integer expression expected +2 +b 9 -eq B +./test.tests: line 7: [: B: integer expression expected +2 +t ( 1 = 2 +./test.tests: line 13: test: `)' expected +2 +b ( 1 = 2 +./test.tests: line 7: [: `)' expected, found ] +2 +./test.tests: line 13: test: a: unary operator expected +2 +./test.tests: line 13: test: b: binary operator expected +2 +./test.tests: line 13: test: -A: unary operator expected +2 +./test.tests: line 13: test: too many arguments +2 +./test.tests: line 13: test: too many arguments +2 +./test.tests: line 418: [: missing `]' +2 +./test.tests: line 13: test: (: unary operator expected +2 +t -t a +1 +t -t addsds +1 +t -t 42 +1 +t -t /dev/tty +1 +t -t /dev/tty4 +1 +t -t /dev/tty4444444... +1 +1 +t -p /dev/fd/6 +1 +t -p /dev/fd/6 +0 diff --git a/tests/test.tests b/tests/test.tests new file mode 100644 index 0000000..07a87a0 --- /dev/null +++ b/tests/test.tests @@ -0,0 +1,440 @@ +if (( $UID == 0 )); then + echo "test-tests: the test suite should not be run as root" >&2 +fi + +b() +{ + [ "$@" ] + echo $? +} + +t() +{ + test "$@" + echo $? +} + +echo 't -a noexist' +t -a noexist +echo 't -a run-all' +t -a run-all + +echo 't -b run-all' +t -b run-all +echo 't -b /dev/jb1a' +t -b /dev/jb1a + +echo 't -c run-all' +t -c run-all +echo 't -c /dev/tty' +t -c /dev/tty + +echo 't -d run-all' +t -d run-all +echo 't -d /etc' +t -d /etc +echo 't -d ""' +t -d "" +echo 'b -d ""' +b -d "" + +echo 't -e noexist' +t -e noexist +echo 't -e run-all' +t -e run-all + +echo 't -f noexist' +t -f noexist +echo 't -f /dev/tty' +t -f /dev/tty +echo 't -f run-all' +t -f run-all + +echo 't -g run-all' +t -g run-all + +touch /tmp/test.setgid +chgrp ${GROUPS[0]} /tmp/test.setgid +chmod ug+x /tmp/test.setgid +chmod g+s /tmp/test.setgid +echo 't -g /tmp/test.setgid' +t -g /tmp/test.setgid +rm -f /tmp/test.setgid + +echo 't -k run-all' +t -k run-all + +echo 't -n ""' +t -n "" +echo 't -n "hello"' +t -n "hello" + +echo 't -p run-all' +t -p run-all + +echo 't -r noexist' +t -r noexist + +if (( $UID != 0 )); then + touch /tmp/test.noread + chmod a-r /tmp/test.noread + echo 't -r /tmp/test.noread' + t -r /tmp/test.noread + rm -f /tmp/test.noread +else + echo 't -r /tmp/test.noread' + echo 1 +fi + +echo 't -r run-all' +t -r run-all + +echo 't -s noexist' +t -s noexist +echo 't -s /dev/null' +t -s /dev/null +echo 't -s run-all' +t -s run-all + +echo 't -t 20' +t -t 20 +echo 't -t 0' +t -t 0 < /dev/tty + +echo 't -u noexist' +t -u noexist + +echo 't -u run-all' +t -u run-all + +touch /tmp/test.setuid +chmod u+x /tmp/test.setuid # some systems require this to turn on setuid bit +chmod u+s /tmp/test.setuid +echo 't -u /tmp/test.setuid' +t -u /tmp/test.setuid +rm -f /tmp/test.setuid + +echo 't -w noexist' +t -w noexist + +if (( $UID != 0 )); then + touch /tmp/test.nowrite + chmod a-w /tmp/test.nowrite + echo 't -w /tmp/test.nowrite' + t -w /tmp/test.nowrite + rm -f /tmp/test.nowrite +else + echo 't -w /tmp/test.nowrite' + echo 1 +fi + +echo 't -w /dev/null' +t -w /dev/null + +echo 't -x noexist' +t -x noexist + +touch /tmp/test.exec +chmod u+x /tmp/test.exec +echo 't -x /tmp/test.exec' +t -x /tmp/test.exec +rm -f /tmp/test.exec + +touch /tmp/test.noexec +chmod u-x /tmp/test.noexec +echo 't -x /tmp/test.noexec' +t -x /tmp/test.noexec +rm -f /tmp/test.noexec + +echo 't -z ""' +t -z "" +echo 't -z "foo"' +t -z "foo" + +echo 't "foo"' +t "foo" +echo 't ""' +t "" + +touch /tmp/test.owner +echo 't -O /tmp/test.owner' +t -O /tmp/test.owner +rm -f /tmp/test.owner + +touch /tmp/test.socket +echo 't -S /tmp/test.socket' +t -S /tmp/test.socket # false +rm -f /tmp/test.socket + +touch /tmp/test.newer +echo 't -N /tmp/test.newer' +t -N /tmp/test.newer +rm -f /tmp/test.newer + +echo 't "hello" = "hello"' +t "hello" = "hello" +echo 't "hello" = "goodbye"' +t "hello" = "goodbye" + +echo 't "hello" == "hello"' +t "hello" == "hello" +echo 't "hello" == "goodbye"' +t "hello" == "goodbye" + +echo 't "hello" != "hello"' +t "hello" != "hello" +echo 't "hello" != "goodbye"' +t "hello" != "goodbye" + +echo 't "hello" < "goodbye"' +t "hello" \< "goodbye" +echo 't "hello" > "goodbye"' +t "hello" \> "goodbye" + +echo 't ! "hello" > "goodbye"' +t "! hello" \> "goodbye" + +echo 't 200 -eq 200' +t 200 -eq 200 +echo 't 34 -eq 222' +t 34 -eq 222 +echo 't -32 -eq 32' +t -32 -eq 32 + +echo 't 200 -ne 200' +t 200 -ne 200 +echo 't 34 -ne 222' +t 34 -ne 222 + +echo 't 200 -gt 200' +t 200 -gt 200 +echo 't 340 -gt 222' +t 340 -gt 222 + +echo 't 200 -ge 200' +t 200 -ge 200 +echo 't 34 -ge 222' +t 34 -ge 222 + +echo 't 200 -lt 200' +t 200 -lt 200 +echo 't 34 -lt 222' +t 34 -lt 222 + +echo 't 200 -le 200' +t 200 -le 200 +echo 't 340 -le 222' +t 340 -le 222 + +echo 't 700 -le 1000 -a -n "1" -a "20" = "20"' +t 700 -le 1000 -a -n "1" -a "20" = "20" +echo 't ! \( 700 -le 1000 -a -n "1" -a "20" = "20" \)' +t ! \( 700 -le 1000 -a -n "1" -a "20" = "20" \) + +touch /tmp/abc +sleep 2 +touch /tmp/def + +echo 't /tmp/abc -nt /tmp/def' +t /tmp/abc -nt /tmp/def +echo 't /tmp/abc -ot /tmp/def' +t /tmp/abc -ot /tmp/def +echo 't /tmp/def -nt /tmp/abc' +t /tmp/def -nt /tmp/abc +echo 't /tmp/def -ot /tmp/abc' +t /tmp/def -ot /tmp/abc + +echo 't /tmp/abc -ef /tmp/def' +t /tmp/abc -ef /tmp/def +ln /tmp/abc /tmp/ghi +echo 't /tmp/abc -ef /tmp/ghi' +t /tmp/abc -ef /tmp/ghi + +rm /tmp/abc /tmp/def /tmp/ghi + +echo 't -r /dev/fd/0' +t -r /dev/fd/0 +echo 't -w /dev/fd/1' +t -w /dev/fd/1 +echo 't -w /dev/fd/2' +t -w /dev/fd/2 + +echo 't -r /dev/stdin' +t -r /dev/stdin +echo 't -w /dev/stdout' +t -w /dev/stdout +echo 't -w /dev/stderr' +t -w /dev/stderr + +echo 't' +t +echo 'b' +b + +echo 't 12 -eq 34' +t 12 -eq 34 +echo 't ! 12 -eq 34' +t ! 12 -eq 34 + +echo 't -n abcd -o aaa' +t -n abcd -o aaa +echo 't -n abcd -o -z aaa' +t -n abcd -o -z aaa + +echo 't -n abcd -a aaa' +t -n abcd -a aaa +echo 't -n abcd -a -z aaa' +t -n abcd -a -z aaa + +# test set or unset shell options +set +o allexport +echo 't -o allexport' +t -o allexport +echo 't ! -o allexport' +t ! -o allexport + +#test set or unset shell variables +unset unset +echo 't -v unset' +t -v unset +set= +echo 't -v set' +t -v set +set=set +echo 't -v set' +t -v set + +echo 't xx -a yy' +t xx -a yy +echo 't xx -o ""' +t xx -o "" +echo 't xx -a ""' +t xx -a "" + +echo 't -X -a -X' +t -X -a -X +echo 't -X -o -X' +t -X -o -X +echo 't -X -o ""' +t -X -o "" +echo 't -X -a ""' +t -X -a "" +echo 't "" -a -X' +t "" -a -X +echo 't "" -o -X' +t "" -o -X +echo 't "" -a ""' +t "" -a "" +echo 't "" -o ""' +t "" -o "" +echo 't true -o -X' +t true -o -X +echo 't true -a -X' +t true -a -X + +echo 't ( -E )' +t \( -E \) +echo 't ( "" )' +t \( "" \) + +z=42 + +echo 't ! -z "$z"' +t ! -z "$z" + +echo 't ! -n "$z"' +t ! -n "$z" + +zero= +echo 't "$zero"' +t "$zero" +echo 't ! "$zero"' +t ! "$zero" +echo 'b "$zero"' +b "$zero" +echo 'b ! "$zero"' +b ! "$zero" + +touch /tmp/test.group +chgrp ${GROUPS[0]} /tmp/test.group +echo 't -G /tmp/test.group' +t -G /tmp/test.group +rm /tmp/test.group + +case "${THIS_SH}" in +/*) SHNAME=${THIS_SH} ;; +*) SHNAME=${PWD}/${THIS_SH} ;; +esac + +if ln -s ${SHNAME} /tmp/test.symlink 2>/dev/null; then + chgrp ${GROUPS[0]} /tmp/test.symlink 2>/dev/null + echo 't -h /tmp/test.symlink' + t -h /tmp/test.symlink + # some systems don't let you remove this + rm -f /tmp/test.symlink 2>/dev/null +else + echo 't -h /tmp/test.symlink' + echo 0 +fi + +# arithmetic constant errors +echo "t 4+3 -eq 7" +t 4+3 -eq 7 +echo "b 4-5 -eq 7" +b 4+3 -eq 7 + +echo "t 9 -eq 4+5" +t 9 -eq 4+5 +echo "b 9 -eq 4+5" +b 9 -eq 4+5 + +A=7 +echo "t A -eq 7" +t A -eq 7 +echo "b A -eq 7" +b A -eq 7 + +B=9 +echo "t 9 -eq B" +t 9 -eq B +echo "b 9 -eq B" +b 9 -eq B + +# badly formed expressions +echo 't ( 1 = 2' +t \( 1 = 2 +echo 'b ( 1 = 2' +b \( 1 = 2 + +# more errors +t a b +t a b c +t -A v +# too many arguments -- argument expected is also reasonable +t 4 -eq 4 -a 2 -ne 5 -a 4 -ne +# too many arguments +t 4 -eq 4 -a 3 4 + +[ +echo $? + +t \( \) + +# non-numeric arguments to `test -t' should return failure -- fix in 2.05 +echo 't -t a' +t -t a +echo 't -t addsds' +t -t addsds +echo 't -t 42' +t -t 42 +echo 't -t /dev/tty' +t -t /dev/tty +echo 't -t /dev/tty4' +t -t /dev/tty4 +echo 't -t /dev/tty4444444...' +t -t /dev/tty4444444... + +# fixed in bash-4.0-beta +t -t ' ' + +${THIS_SH} ./test1.sub diff --git a/tests/test1.sub b/tests/test1.sub new file mode 100644 index 0000000..a1c5817 --- /dev/null +++ b/tests/test1.sub @@ -0,0 +1,21 @@ +# some systems, like old SunOS, have stat on /dev/fd/N and fstat(N, ...) +# return different results +: ${TMPDIR:=/tmp} + +trap 'rm -f ${TMPDIR}/pipe' 0 1 2 3 6 15 + +exec 6>&- +echo "t -p /dev/fd/6" +test -p /dev/fd/6 +echo $? + +rm -f ${TMPDIR}/pipe 2>/dev/null +mkfifo ${TMPDIR}/pipe +cat < ${TMPDIR}/pipe & +exec 6>&- +exec 6>${TMPDIR}/pipe +echo "t -p /dev/fd/6" +test -p /dev/fd/6 +echo $? +exec 2>/dev/null # disable process termination message +kill $! 2>/dev/null diff --git a/tests/tilde.right b/tests/tilde.right new file mode 100644 index 0000000..49549b4 --- /dev/null +++ b/tests/tilde.right @@ -0,0 +1,26 @@ +~chet +/usr/xyz/foo +~chet/foo +~chet/foo +~chet/bar +~chet/bar +~chet/bar +:~chet/ +abcd~chet +SHELL=~/bash +/usr/xyz/bash +abcd:~chet +/usr/ucb:/bin:/usr/xyz/bin:/usr/xyz/tmp/bin:/usr/bin +/usr +/tmp +/bin:/usr/bin:.:/usr/xyz/bin +/bin:/usr/bin:.:~/bin +/bin:/usr/bin:.:/usr/xyz/bin +/bin:/usr/bin:.:/usr/xyz/bin +/bin:/usr/bin:.:~/bin +/bin:/usr/bin:.:~/bin +\~ +ok 1 +ok 2 +ok 3 +~root diff --git a/tests/tilde.tests b/tests/tilde.tests new file mode 100644 index 0000000..8a9f136 --- /dev/null +++ b/tests/tilde.tests @@ -0,0 +1,75 @@ +wdir=$PWD +# this is needed because posix mode restricts tilde expansion to assignment +# statements preceding a command, instead of the default of expanding all +# assignment statements on the line (e.g., after `export'). Without this, +# the next-to-last test fails +set +o posix + +HOME=/usr/xyz +SHELL=~/bash +echo ~ch\et +echo ~/"foo" +echo "~chet"/"foo" +echo \~chet/"foo" +echo \~chet/bar +echo ~\chet/bar +echo ~chet""/bar +echo ":~chet/" +echo abcd~chet +echo "SHELL=~/bash" +echo $SHELL +echo abcd:~chet +path=/usr/ucb:/bin:~/bin:~/tmp/bin:/usr/bin +echo $path + +cd /usr +cd /tmp +echo ~- +echo ~+ + +XPATH=/bin:/usr/bin:. + +# yes tilde expansion +PPATH=$XPATH:~/bin +echo "$PPATH" + +# no tilde expansion +PPATH="$XPATH:~/bin" +echo "$PPATH" + +# yes tilde expansion +export PPATH=$XPATH:~/bin +echo "$PPATH" +declare -x PPATH=$XPATH:~/bin +echo "$PPATH" + +# no tilde expansion +export PPATH="$XPATH:~/bin" +echo "$PPATH" +declare -x PPATH="$XPATH:~/bin" +echo "$PPATH" + +printf "%q\n" '~' + +# more tests of tilde expansion when executing case commands +case ~ in +$HOME) echo ok 1;; +*) echo bad 1 ;; +esac + +case ~ in +~) echo ok 2 ;; +\~) echo bad 2a ;; +*) echo bad 2b ;; +esac + +case $unset in +"") echo ok 3 ;; +*) echo bad 3 ;; +esac + +USER=root # should exist just about everywhere +echo ~$USER + +cd "$wdir" +exit 0 diff --git a/tests/tilde2.right b/tests/tilde2.right new file mode 100644 index 0000000..fce0468 --- /dev/null +++ b/tests/tilde2.right @@ -0,0 +1,24 @@ +PATH=~/bin:/bin:/usr/bin:. +/usr/xyz/bin:~/bin2:/bin:/usr/bin:. +PATH=~/bin:~/bin2:/bin:/usr/bin:. +~/bin +~ +/usr/xyz +~ +~ +~ +argv[1] = <\a> +argv[1] = <\a> +/usr/xyz/bash +ok +~ +~ +make -k FOO=/usr/xyz/mumble +/usr/xyz/mumble +HOME=~ +HOME=~ +/usr/$x/abc +HOME=~ +/usr/$x/abc +HOME=/usr/$x/abc +/usr/$x/abc diff --git a/tests/tilde2.tests b/tests/tilde2.tests new file mode 100644 index 0000000..ff6c76f --- /dev/null +++ b/tests/tilde2.tests @@ -0,0 +1,70 @@ +HOME=/usr/xyz +XPATH=/bin:/usr/bin:. + +ADDPATH=PATH=~/bin:$XPATH + +echo $ADDPATH + +unset ADDPATH +: ${ADDPATH:=~/bin:~/bin2:$XPATH} +echo $ADDPATH + +unset ADDPATH +: ${ADDPATH:=PATH=~/bin:~/bin2:$XPATH} +echo $ADDPATH + +cat << ! +~/bin +! + +echo "~" + +echo ${TPATH:-~} +echo "${TPATH:-~}" +echo "${TPATH:-"~"}" + +echo "${XPATH+~}" + +recho "\a" +recho "${TPATH:-\a}" + +SHELL=~/bash +echo $SHELL + +case $SHELL in +~/bash) echo ok;; +*) echo bad;; +esac + +somevar= +echo "${somevar:-~}" +echo "${somevar:-"~"}" + +echo make -k FOO=~/mumble + +typeset FOO=~/mumble +echo "$FOO" + +h=HOME=~ +echo $h + +export h=HOME=~ +echo $h + +x=1234 +HOME='/usr/$x/abc' + +echo ~ + +# behavior differs here in posix mode +set -o posix + +eval echo $h +eval $h +echo $HOME + +set +o posix + +eval echo $h +eval $h +echo $HOME diff --git a/tests/trap.right b/tests/trap.right new file mode 100644 index 0000000..4165829 --- /dev/null +++ b/tests/trap.right @@ -0,0 +1,115 @@ +subshell exit +trap -- 'echo exiting' EXIT +trap -- 'echo aborting' SIGHUP +trap -- 'echo aborting' SIGINT +trap -- 'echo aborting' SIGQUIT +trap -- 'echo aborting' SIGABRT +trap -- 'echo aborting' SIGTERM +[20] debug +debug line +[22] debug +trap -- 'echo exiting' EXIT +trap -- 'echo aborting' SIGHUP +trap -- 'echo aborting' SIGINT +trap -- 'echo aborting' SIGQUIT +trap -- 'echo aborting' SIGABRT +trap -- 'echo aborting' SIGTERM +trap -- 'echo [$LINENO] debug' DEBUG +[24] debug +func[16] funcdebug +funcdebug line +./trap.tests[26] funcdebug +trap -- 'echo exiting' EXIT +trap -- 'echo aborting' SIGHUP +trap -- 'echo aborting' SIGINT +trap -- 'echo aborting' SIGQUIT +trap -- 'echo aborting' SIGABRT +trap -- 'echo aborting' SIGTERM +trap -- 'echo ${FUNCNAME:-$0}[$LINENO] funcdebug' DEBUG +./trap.tests[28] funcdebug +./trap.tests[33] debug +./trap.tests[34] debug +func2[30] debug +func2[31] debug +func2debug line +./trap.tests[36] debug +./trap.tests[38] debug +trap -- 'echo exiting' EXIT +trap -- 'echo aborting' SIGHUP +trap -- 'echo aborting' SIGINT +trap -- 'echo aborting' SIGQUIT +trap -- 'echo aborting' SIGABRT +trap -- 'echo aborting' SIGTERM +trap -- '' DEBUG +trap -- 'echo exiting' EXIT +trap -- 'echo aborting' SIGHUP +trap -- 'echo aborting' SIGINT +trap -- 'echo aborting' SIGQUIT +trap -- 'echo aborting' SIGABRT +trap -- 'echo aborting' SIGTERM +trap -- 'echo exiting' EXIT +trap -- '' SIGINT +trap -- 'echo aborting' SIGQUIT +trap -- 'echo aborting' SIGABRT +trap -- 'echo aborting' SIGTERM +0 +trap -- '' SIGUSR2 +ERRTRAP +ERRTRAP +ERRTRAP +after falses +if negation ok +after negation +after while +before false in trap2a.sub +after false in trap2a.sub +command substitution +ERRTRAP +ERRTRAP +bar +ERRTRAP +ERRTRAP +ERRTRAP +ERRTRAP +ERRTRAP ++[6] echo 1 +1 ++[7] echo 2 +2 ++[8] echo 3 ++[8] cat ++[8] false +++[8] echo trap: 8 +trap: 8 ++[9] echo 4 +4 +exit subshell 1 +current shell +exit subshell 2 +current shell +current shell +current shell +outside 1 +outside 2 +outside 3 +outside 4 +sleep 2 +wait $! +exit +in trap EXIT +sleep 2 +wait $! +exit +in trap EXIT +fn +after 1 +fn +after 2 +caught a child death +caught a child death +caught a child death +trap -- 'echo caught a child death' SIGCHLD +trap -- 'echo exiting' EXIT +trap -- 'echo aborting' SIGABRT +trap -- 'echo caught a child death' SIGCHLD +exiting diff --git a/tests/trap.tests b/tests/trap.tests new file mode 100644 index 0000000..637bfd2 --- /dev/null +++ b/tests/trap.tests @@ -0,0 +1,101 @@ +# test the trap code + +trap 'echo exiting' 0 +trap 'echo aborting' 1 2 3 6 15 + +# make sure a user-specified subshell runs the exit trap, but does not +# inherit the exit trap from a parent shell +( trap 'echo subshell exit' 0; exit 0 ) +( exit 0 ) + +trap + +func() +{ + trap 'echo ${FUNCNAME:-$0}[$LINENO] funcdebug' DEBUG + echo funcdebug line +} + +trap 'echo [$LINENO] debug' DEBUG +echo debug line + +trap + +func + +trap + +trap 'echo ${FUNCNAME:-$0}[$LINENO] debug' DEBUG +func2() +{ + echo func2debug line +} +declare -ft func2 +func2 + +unset -f func2 + +trap '' DEBUG + +trap + +trap - debug + +trap + +trap - HUP +trap hup +trap '' INT +trap '' int + +trap + +# exit 0 in exit trap should set exit status +( +set -e +trap 'exit 0' EXIT +false +echo bad +) +echo $? + +# hmmm...should this set the handling to SIG_IGN for children, too? +trap '' USR2 +./trap1.sub +trap - USR2 + +# test ERR trap +./trap2.sub + +${THIS_SH} ./trap3.sub + +${THIS_SH} ./trap4.sub + +# This doesn't work right on all Unix versions +#${THIS_SH} ./trap5.sub + +# Return trap issues +${THIS_SH} ./trap6.sub + +# +# show that setting a trap on SIGCHLD is not disastrous. +# +set -o monitor + +trap 'echo caught a child death' SIGCHLD + +sleep 7 & sleep 6 & sleep 5 & + +# this will only catch the first, since there's a trap on SIGCHLD +wait + +trap -p SIGCHLD + +# Now reset some of the signals the shell handles specially back to +# their default values (with or without the SIG prefix) +trap - SIGINT QUIT TERM + +trap + +trap - SIGCHLD +wait diff --git a/tests/trap1.sub b/tests/trap1.sub new file mode 100755 index 0000000..48f8530 --- /dev/null +++ b/tests/trap1.sub @@ -0,0 +1,4 @@ +# signals ignored at shell startup cannot be trapped or reset +trap 'echo USR2' USR2 + +trap -p USR2 diff --git a/tests/trap2.sub b/tests/trap2.sub new file mode 100755 index 0000000..0f1f2d9 --- /dev/null +++ b/tests/trap2.sub @@ -0,0 +1,49 @@ +set +e +trap 'echo ERRTRAP' ERR + +false +false +false + +echo after falses + +if ! false; then + echo if negation ok +fi + +! false +echo after negation + +while false; do + echo while negation ok +done + +echo after while + +./trap2a.sub + +echo $(false ; echo command substitution) + +# test behavior of failed commands following `command' builtin +command false + +(command false) +command false | echo bar + +(false) + +exit 42 | command false + +command command command false + +unset FALSE +if [ -x /bin/false ]; then + FALSE=/bin/false +elif [ -x /usr/bin/false ]; then + FALSE=/usr/bin/false +else + FALSE='command false' +fi + +command $FALSE +command command command $FALSE diff --git a/tests/trap2a.sub b/tests/trap2a.sub new file mode 100755 index 0000000..44d6b50 --- /dev/null +++ b/tests/trap2a.sub @@ -0,0 +1,3 @@ +echo before false in trap2a.sub +false +echo after false in trap2a.sub diff --git a/tests/trap3.sub b/tests/trap3.sub new file mode 100644 index 0000000..0df4455 --- /dev/null +++ b/tests/trap3.sub @@ -0,0 +1,9 @@ +PS4='+[$LINENO] ' +trap 'echo trap: $LINENO' ERR + +set -x + +echo 1 +echo 2 +echo 3 | cat | false +echo 4 diff --git a/tests/trap4.sub b/tests/trap4.sub new file mode 100644 index 0000000..ab5ca3e --- /dev/null +++ b/tests/trap4.sub @@ -0,0 +1,42 @@ +# make sure subshells at the end of pipelines run any exit traps they set + +: | { trap 'echo exit subshell 1' EXIT; exit; }; echo current shell + +: | { trap 'echo exit subshell 2' EXIT; exit; }; echo current shell + +: | { trap 'echo exit subshell 3' EXIT; exit; } | : ; echo current shell + +: | { trap 'echo exit subshell 4' EXIT; exit; } | : ; echo current shell + +trap 'echo inherited exit trap' EXIT +: | { exit; } ; echo outside 1 +: | ( exit; ) ; echo outside 2 +: | { exit; } | : ; echo outside 3 +: | ( exit; ) | : ; echo outside 4 + +trap - EXIT + +# make sure group commands that are not at the beginning or end of pipelines +# run an EXIT trap, with and without the exit builtin +echo ignored | +{ + trap 'echo "in trap EXIT">&2' EXIT + sleep 4 & + echo 'sleep 2'>&2 + sleep 2 + echo 'wait $!'>&2 + wait $! + echo 'exit'>&2 + exit +} | cat + +echo ignored | +{ + trap 'echo "in trap EXIT">&2' EXIT + sleep 4 & + echo 'sleep 2'>&2 + sleep 2 + echo 'wait $!'>&2 + wait $! + echo 'exit'>&2 +} | cat diff --git a/tests/trap5.sub b/tests/trap5.sub new file mode 100644 index 0000000..7f3380b --- /dev/null +++ b/tests/trap5.sub @@ -0,0 +1,18 @@ +# make sure process substitution runs the exit trap +[[ -n $(< <(trap "cat /dev/fd/0" EXIT)) ]] <<<works && echo works || echo "fail :(" + +read foo < <(trap "echo bar" EXIT) +echo $foo + +cat <(trap "echo bar" EXIT) + +trap "echo bar" EXIT #should proc subst inherit this? +cat <(echo foo ; exit 0;) + +trap - 0 +trap + +cat <(echo foo; trap "echo bar" EXIT) + +trap "echo bar" EXIT #should proc subst inherit this? +cat <(echo foo) diff --git a/tests/trap6.sub b/tests/trap6.sub new file mode 100644 index 0000000..332a177 --- /dev/null +++ b/tests/trap6.sub @@ -0,0 +1,15 @@ +set -o functrace +fn() { return; } + +trap "echo fn ; fn" RETURN + +fn +echo after 1 + +unset -f fn + +fn() { eval return; } +fn +echo after 2 + +unset -f fn diff --git a/tests/type.right b/tests/type.right new file mode 100644 index 0000000..7ec6bfb --- /dev/null +++ b/tests/type.right @@ -0,0 +1,135 @@ +./type.tests: line 9: type: -r: invalid option +type: usage: type [-afptP] name [name ...] +./type.tests: line 12: type: notthere: not found +function +keyword +builtin +file +file +file +func is a function +func () +{ + echo this is func +} +while is a shell keyword +while is a shell keyword +builtin is a shell builtin +/bin/sh is /bin/sh +func +func is a function +func () +{ + echo this is func +} +while +while is a shell keyword +./type.tests: line 43: type: m: not found +alias m='more' +alias m='more' +m is aliased to `more' +alias +alias m='more' +alias m='more' +alias m='more' +m is aliased to `more' +builtin +builtin is a shell builtin +/bin/sh +/bin/sh is /bin/sh +./type.tests: line 65: type: func: not found +./type.tests: line 67: type: m: not found +/bin/sh +/tmp/bash +bash is hashed (/tmp/bash) +file +hits command + 3 /tmp/bash + 1 /bin/sh +f is a function +f () +{ + v='^A' +} +foo is a function +foo () +{ + echo $(<x1) +} +bar is a function +bar () +{ + echo $(<x1) +} +foo is a function +foo () +{ + echo; + cat <<END +bar +END + + cat <<EOF +qux +EOF + +} + +bar +qux + +bar +qux +foo is a function +foo () +{ + rm -f a b c; + for f in a b c; + do + cat <<-EOF >> ${f} +file +EOF + + done + grep . a b c +} +a:file +b:file +c:file +bb is a function +bb () +{ + ( cat <<EOF +foo +bar +EOF + ) + echo after subshell +} +mkcoprocs is a function +mkcoprocs () +{ + coproc a { + cat <<EOF1 +producer 1 +EOF1 + + } + coproc b { + cat <<EOF2 +producer 2 +EOF2 + + } + echo "coprocs created" +} +mkcoprocs is a function +mkcoprocs () +{ + coproc COPROC ( b cat <<EOF +heredoc +body +EOF + ) + echo "coprocs created" +} diff --git a/tests/type.tests b/tests/type.tests new file mode 100644 index 0000000..1c03e01 --- /dev/null +++ b/tests/type.tests @@ -0,0 +1,97 @@ +set +o posix + +hash -r +unalias -a + +# this should echo nothing +type +# this should be a usage error +type -r ${THIS_SH} + +# these should behave identically +type notthere +command -v notthere + +alias m=more + +unset -f func 2>/dev/null +func() { echo this is func; } + +type -t func +type -t while +type -t builtin +type -t /bin/sh +type -t ${THIS_SH} +type -t mv + +type func +# the following two should produce identical output +type while +type -a while +type builtin +type /bin/sh + +command -v func +command -V func +command -v while +command -V while + +# the following two lines should produce the same output +# post-3.0 patch makes command -v silent, as posix specifies +# first test with alias expansion off (should all fail or produce no output) +type -t m +type m +command -v m +alias -p +alias m + +# then test with alias expansion on +shopt -s expand_aliases +type m +type -t m +command -v m +alias -p +alias m + +command -V m +shopt -u expand_aliases + +command -v builtin +command -V builtin +command -v /bin/sh +command -V /bin/sh + +unset -f func +type func +unalias m +type m + +hash -r + +hash -p /bin/sh sh +type -p sh + +SHBASE=${THIS_SH##*/} +hash -p /tmp/$SHBASE $SHBASE +type -p $SHBASE +type $SHBASE + +type -t $SHBASE + +# make sure the hash table looks right +hash + +# bug in versions of bash up to and including bash-3.2 +f() { + v=$'\001' + } + +type f | cat -v + +${THIS_SH} type1.sub + +${THIS_SH} type2.sub + +${THIS_SH} type3.sub + +${THIS_SH} type4.sub diff --git a/tests/type1.sub b/tests/type1.sub new file mode 100644 index 0000000..95f96ae --- /dev/null +++ b/tests/type1.sub @@ -0,0 +1,10 @@ +foo() +{ + echo $(<x1) +} + +type foo + +eval "$(declare -f foo | sed 's:foo:bar:')" + +type bar diff --git a/tests/type2.sub b/tests/type2.sub new file mode 100644 index 0000000..3f85ead --- /dev/null +++ b/tests/type2.sub @@ -0,0 +1,16 @@ +foo() +{ + echo + cat <<END +bar +END + cat <<EOF +qux +EOF +} + +type foo +foo + +eval "$(type foo | sed 1d)" +foo diff --git a/tests/type3.sub b/tests/type3.sub new file mode 100644 index 0000000..442f22e --- /dev/null +++ b/tests/type3.sub @@ -0,0 +1,21 @@ +cd ${TMPDIR:-/tmp} + +foo() { + rm -f a b c + for f in a b c; do + cat <<-EOF >> ${f} + file + EOF + done + grep . a b c +} + +type foo + +eval "$(type foo | sed 1d)" +foo + +rm -f a b c + +cd $OLDPWD +exit 0 diff --git a/tests/type4.sub b/tests/type4.sub new file mode 100644 index 0000000..ed5bcf6 --- /dev/null +++ b/tests/type4.sub @@ -0,0 +1,43 @@ +bb() +{ + ( + cat << EOF +foo +bar +EOF + ) + echo after subshell +} + +type bb + + +mkcoprocs() +{ + coproc a { cat <<EOF1 +producer 1 +EOF1 +} +coproc b { cat << EOF2 +producer 2 +EOF2 +} + +echo "coprocs created" +} + +type mkcoprocs + +unset -f mkcoprocs + +mkcoprocs() +{ + coproc ( b cat << EOF +heredoc +body +EOF + ) +echo "coprocs created" +} + +type mkcoprocs diff --git a/tests/unicode1.sub b/tests/unicode1.sub new file mode 100644 index 0000000..baa92ea --- /dev/null +++ b/tests/unicode1.sub @@ -0,0 +1,583 @@ +unset LC_ALL + +ErrorCnt=0 +TestCnt=0 + + function check_valid_var_name { + case "${1:?Missing Variable Name}" in + [!a-zA-Z_]* | *[!a-zA-Z_0-9]* ) return 3;; + esac + } + # get_array_element VariableName ArrayName ArrayElement + function get_array_element { + check_valid_var_name "${1:?Missing Variable Name}" || return $? + check_valid_var_name "${2:?Missing Array Name}" || return $? + eval "${1}"'="${'"${2}"'["${3:?Missing Array Index}"]}"' + } + # unset_array_element VarName ArrayName + function get_array_element_cnt { + check_valid_var_name "${1:?Missing Variable Name}" || return $? + check_valid_var_name "${2:?Missing Array Name}" || return $? + eval "${1}"'="${#'"${2}"'[@]}"' + } + + +function TestCodePage { + local TargetCharset="${1:?Missing Test charset}" + local EChar RChar TCnt + get_array_element_cnt TCnt "${2:?Missing Array Name}" + for (( x=1 ; x<${TCnt} ; x++ )); do + get_array_element EChar "${2}" ${x} + if [ -n "${EChar}" ]; then + let TestCnt+=1 + printf -v UVal '\\U%08x' "${x}" + LC_CTYPE=${TargetCharset} printf -v RChar "${UVal}" 2>/dev/null + if [ "${EChar}" != "${RChar}" ]; then + let ErrorCnt+=1 + printf "${TargetCharset}: Error Encoding U+%08X to ${TL} [ \"%q\" != \"%q\" ]\n" "${x}" "${EChar}" "${RChar}" + fi + fi + done +} + + +#for ((x=1;x<255;x++)); do printf ' [0x%04x]=$'\''\%03o'\' $x $x ; [ $(($x%5)) = 0 ] && echo; done +fr_FR_ISO_8859_1=( + [0x0001]=$'\001' [0x0002]=$'\002' [0x0003]=$'\003' [0x0004]=$'\004' [0x0005]=$'\005' + [0x0006]=$'\006' [0x0007]=$'\007' [0x0008]=$'\010' [0x0009]=$'\011' [0x000a]=$'\012' + [0x000b]=$'\013' [0x000c]=$'\014' [0x000d]=$'\015' [0x000e]=$'\016' [0x000f]=$'\017' + [0x0010]=$'\020' [0x0011]=$'\021' [0x0012]=$'\022' [0x0013]=$'\023' [0x0014]=$'\024' + [0x0015]=$'\025' [0x0016]=$'\026' [0x0017]=$'\027' [0x0018]=$'\030' [0x0019]=$'\031' + [0x001a]=$'\032' [0x001b]=$'\033' [0x001c]=$'\034' [0x001d]=$'\035' [0x001e]=$'\036' + [0x001f]=$'\037' [0x0020]=$'\040' [0x0021]=$'\041' [0x0022]=$'\042' [0x0023]=$'\043' + [0x0024]=$'\044' [0x0025]=$'\045' [0x0026]=$'\046' [0x0027]=$'\047' [0x0028]=$'\050' + [0x0029]=$'\051' [0x002a]=$'\052' [0x002b]=$'\053' [0x002c]=$'\054' [0x002d]=$'\055' + [0x002e]=$'\056' [0x002f]=$'\057' [0x0030]=$'\060' [0x0031]=$'\061' [0x0032]=$'\062' + [0x0033]=$'\063' [0x0034]=$'\064' [0x0035]=$'\065' [0x0036]=$'\066' [0x0037]=$'\067' + [0x0038]=$'\070' [0x0039]=$'\071' [0x003a]=$'\072' [0x003b]=$'\073' [0x003c]=$'\074' + [0x003d]=$'\075' [0x003e]=$'\076' [0x003f]=$'\077' [0x0040]=$'\100' [0x0041]=$'\101' + [0x0042]=$'\102' [0x0043]=$'\103' [0x0044]=$'\104' [0x0045]=$'\105' [0x0046]=$'\106' + [0x0047]=$'\107' [0x0048]=$'\110' [0x0049]=$'\111' [0x004a]=$'\112' [0x004b]=$'\113' + [0x004c]=$'\114' [0x004d]=$'\115' [0x004e]=$'\116' [0x004f]=$'\117' [0x0050]=$'\120' + [0x0051]=$'\121' [0x0052]=$'\122' [0x0053]=$'\123' [0x0054]=$'\124' [0x0055]=$'\125' + [0x0056]=$'\126' [0x0057]=$'\127' [0x0058]=$'\130' [0x0059]=$'\131' [0x005a]=$'\132' + [0x005b]=$'\133' [0x005c]=$'\134' [0x005d]=$'\135' [0x005e]=$'\136' [0x005f]=$'\137' + [0x0060]=$'\140' [0x0061]=$'\141' [0x0062]=$'\142' [0x0063]=$'\143' [0x0064]=$'\144' + [0x0065]=$'\145' [0x0066]=$'\146' [0x0067]=$'\147' [0x0068]=$'\150' [0x0069]=$'\151' + [0x006a]=$'\152' [0x006b]=$'\153' [0x006c]=$'\154' [0x006d]=$'\155' [0x006e]=$'\156' + [0x006f]=$'\157' [0x0070]=$'\160' [0x0071]=$'\161' [0x0072]=$'\162' [0x0073]=$'\163' + [0x0074]=$'\164' [0x0075]=$'\165' [0x0076]=$'\166' [0x0077]=$'\167' [0x0078]=$'\170' + [0x0079]=$'\171' [0x007a]=$'\172' [0x007b]=$'\173' [0x007c]=$'\174' [0x007d]=$'\175' + [0x007e]=$'\176' [0x007f]=$'\177' [0x0080]=$'\200' [0x0081]=$'\201' [0x0082]=$'\202' + [0x0083]=$'\203' [0x0084]=$'\204' [0x0085]=$'\205' [0x0086]=$'\206' [0x0087]=$'\207' + [0x0088]=$'\210' [0x0089]=$'\211' [0x008a]=$'\212' [0x008b]=$'\213' [0x008c]=$'\214' + [0x008d]=$'\215' [0x008e]=$'\216' [0x008f]=$'\217' [0x0090]=$'\220' [0x0091]=$'\221' + [0x0092]=$'\222' [0x0093]=$'\223' [0x0094]=$'\224' [0x0095]=$'\225' [0x0096]=$'\226' + [0x0097]=$'\227' [0x0098]=$'\230' [0x0099]=$'\231' [0x009a]=$'\232' [0x009b]=$'\233' + [0x009c]=$'\234' [0x009d]=$'\235' [0x009e]=$'\236' [0x009f]=$'\237' [0x00a0]=$'\240' + [0x00a1]=$'\241' [0x00a2]=$'\242' [0x00a3]=$'\243' [0x00a4]=$'\244' [0x00a5]=$'\245' + [0x00a6]=$'\246' [0x00a7]=$'\247' [0x00a8]=$'\250' [0x00a9]=$'\251' [0x00aa]=$'\252' + [0x00ab]=$'\253' [0x00ac]=$'\254' [0x00ad]=$'\255' [0x00ae]=$'\256' [0x00af]=$'\257' + [0x00b0]=$'\260' [0x00b1]=$'\261' [0x00b2]=$'\262' [0x00b3]=$'\263' [0x00b4]=$'\264' + [0x00b5]=$'\265' [0x00b6]=$'\266' [0x00b7]=$'\267' [0x00b8]=$'\270' [0x00b9]=$'\271' + [0x00ba]=$'\272' [0x00bb]=$'\273' [0x00bc]=$'\274' [0x00bd]=$'\275' [0x00be]=$'\276' + [0x00bf]=$'\277' [0x00c0]=$'\300' [0x00c1]=$'\301' [0x00c2]=$'\302' [0x00c3]=$'\303' + [0x00c4]=$'\304' [0x00c5]=$'\305' [0x00c6]=$'\306' [0x00c7]=$'\307' [0x00c8]=$'\310' + [0x00c9]=$'\311' [0x00ca]=$'\312' [0x00cb]=$'\313' [0x00cc]=$'\314' [0x00cd]=$'\315' + [0x00ce]=$'\316' [0x00cf]=$'\317' [0x00d0]=$'\320' [0x00d1]=$'\321' [0x00d2]=$'\322' + [0x00d3]=$'\323' [0x00d4]=$'\324' [0x00d5]=$'\325' [0x00d6]=$'\326' [0x00d7]=$'\327' + [0x00d8]=$'\330' [0x00d9]=$'\331' [0x00da]=$'\332' [0x00db]=$'\333' [0x00dc]=$'\334' + [0x00dd]=$'\335' [0x00de]=$'\336' [0x00df]=$'\337' [0x00e0]=$'\340' [0x00e1]=$'\341' + [0x00e2]=$'\342' [0x00e3]=$'\343' [0x00e4]=$'\344' [0x00e5]=$'\345' [0x00e6]=$'\346' + [0x00e7]=$'\347' [0x00e8]=$'\350' [0x00e9]=$'\351' [0x00ea]=$'\352' [0x00eb]=$'\353' + [0x00ec]=$'\354' [0x00ed]=$'\355' [0x00ee]=$'\356' [0x00ef]=$'\357' [0x00f0]=$'\360' + [0x00f1]=$'\361' [0x00f2]=$'\362' [0x00f3]=$'\363' [0x00f4]=$'\364' [0x00f5]=$'\365' + [0x00f6]=$'\366' [0x00f7]=$'\367' [0x00f8]=$'\370' [0x00f9]=$'\371' [0x00fa]=$'\372' + [0x00fb]=$'\373' [0x00fc]=$'\374' [0x00fd]=$'\375' [0x00fe]=$'\376' +) + +TestCodePage fr_FR.ISO8859-1 fr_FR_ISO_8859_1 + +zh_TW_BIG5=( + [0x00f6]=$'\366' [0x00f7]=$'\367' [0x00f8]=$'\370' [0x00f9]=$'\371' [0x00fa]=$'\372' + [0x00fb]=$'\373' [0x00fc]=$'\374' [0x00fd]=$'\375' [0x00fe]=$'\376' +) +TestCodePage zh_TW.BIG5 zh_TW_BIG5 + +jp_JP_SHIFT_JIS=( + [0x0001]=$'\x01' # START OF HEADING + [0x0002]=$'\x02' # START OF TEXT + [0x0003]=$'\x03' # END OF TEXT + [0x0004]=$'\x04' # END OF TRANSMISSION + [0x0005]=$'\x05' # ENQUIRY + [0x0006]=$'\x06' # ACKNOWLEDGE + [0x0007]=$'\x07' # BELL + [0x0008]=$'\x08' # BACKSPACE + [0x0009]=$'\x09' # HORIZONTAL TABULATION + [0x000A]=$'\x0A' # LINE FEED + [0x000B]=$'\x0B' # VERTICAL TABULATION + [0x000C]=$'\x0C' # FORM FEED + [0x000D]=$'\x0D' # CARRIAGE RETURN + [0x000E]=$'\x0E' # SHIFT OUT + [0x000F]=$'\x0F' # SHIFT IN + [0x0010]=$'\x10' # DATA LINK ESCAPE + [0x0011]=$'\x11' # DEVICE CONTROL ONE + [0x0012]=$'\x12' # DEVICE CONTROL TWO + [0x0013]=$'\x13' # DEVICE CONTROL THREE + [0x0014]=$'\x14' # DEVICE CONTROL FOUR + [0x0015]=$'\x15' # NEGATIVE ACKNOWLEDGE + [0x0016]=$'\x16' # SYNCHRONOUS IDLE + [0x0017]=$'\x17' # END OF TRANSMISSION BLOCK + [0x0018]=$'\x18' # CANCEL + [0x0019]=$'\x19' # END OF MEDIUM + [0x001A]=$'\x1A' # SUBSTITUTE + [0x001B]=$'\x1B' # ESCAPE + [0x001C]=$'\x1C' # FILE SEPARATOR + [0x001D]=$'\x1D' # GROUP SEPARATOR + [0x001E]=$'\x1E' # RECORD SEPARATOR + [0x001F]=$'\x1F' # UNIT SEPARATOR + [0x0020]=$'\x20' # SPACE + [0x0021]=$'\x21' # EXCLAMATION MARK + [0x0022]=$'\x22' # QUOTATION MARK + [0x0023]=$'\x23' # NUMBER SIGN + [0x0024]=$'\x24' # DOLLAR SIGN + [0x0025]=$'\x25' # PERCENT SIGN + [0x0026]=$'\x26' # AMPERSAND + [0x0027]=$'\x27' # APOSTROPHE + [0x0028]=$'\x28' # LEFT PARENTHESIS + [0x0029]=$'\x29' # RIGHT PARENTHESIS + [0x002A]=$'\x2A' # ASTERISK + [0x002B]=$'\x2B' # PLUS SIGN + [0x002C]=$'\x2C' # COMMA + [0x002D]=$'\x2D' # HYPHEN-MINUS + [0x002E]=$'\x2E' # FULL STOP + [0x002F]=$'\x2F' # SOLIDUS + [0x0030]=$'\x30' # DIGIT ZERO + [0x0031]=$'\x31' # DIGIT ONE + [0x0032]=$'\x32' # DIGIT TWO + [0x0033]=$'\x33' # DIGIT THREE + [0x0034]=$'\x34' # DIGIT FOUR + [0x0035]=$'\x35' # DIGIT FIVE + [0x0036]=$'\x36' # DIGIT SIX + [0x0037]=$'\x37' # DIGIT SEVEN + [0x0038]=$'\x38' # DIGIT EIGHT + [0x0039]=$'\x39' # DIGIT NINE + [0x003A]=$'\x3A' # COLON + [0x003B]=$'\x3B' # SEMICOLON + [0x003C]=$'\x3C' # LESS-THAN SIGN + [0x003D]=$'\x3D' # EQUALS SIGN + [0x003E]=$'\x3E' # GREATER-THAN SIGN + [0x003F]=$'\x3F' # QUESTION MARK + [0x0040]=$'\x40' # COMMERCIAL AT + [0x0041]=$'\x41' # LATIN CAPITAL LETTER A + [0x0042]=$'\x42' # LATIN CAPITAL LETTER B + [0x0043]=$'\x43' # LATIN CAPITAL LETTER C + [0x0044]=$'\x44' # LATIN CAPITAL LETTER D + [0x0045]=$'\x45' # LATIN CAPITAL LETTER E + [0x0046]=$'\x46' # LATIN CAPITAL LETTER F + [0x0047]=$'\x47' # LATIN CAPITAL LETTER G + [0x0048]=$'\x48' # LATIN CAPITAL LETTER H + [0x0049]=$'\x49' # LATIN CAPITAL LETTER I + [0x004A]=$'\x4A' # LATIN CAPITAL LETTER J + [0x004B]=$'\x4B' # LATIN CAPITAL LETTER K + [0x004C]=$'\x4C' # LATIN CAPITAL LETTER L + [0x004D]=$'\x4D' # LATIN CAPITAL LETTER M + [0x004E]=$'\x4E' # LATIN CAPITAL LETTER N + [0x004F]=$'\x4F' # LATIN CAPITAL LETTER O + [0x0050]=$'\x50' # LATIN CAPITAL LETTER P + [0x0051]=$'\x51' # LATIN CAPITAL LETTER Q + [0x0052]=$'\x52' # LATIN CAPITAL LETTER R + [0x0053]=$'\x53' # LATIN CAPITAL LETTER S + [0x0054]=$'\x54' # LATIN CAPITAL LETTER T + [0x0055]=$'\x55' # LATIN CAPITAL LETTER U + [0x0056]=$'\x56' # LATIN CAPITAL LETTER V + [0x0057]=$'\x57' # LATIN CAPITAL LETTER W + [0x0058]=$'\x58' # LATIN CAPITAL LETTER X + [0x0059]=$'\x59' # LATIN CAPITAL LETTER Y + [0x005A]=$'\x5A' # LATIN CAPITAL LETTER Z + [0x005B]=$'\x5B' # LEFT SQUARE BRACKET + [0x005C]=$'\x5C' # REVERSE SOLIDUS (YEN SIGN) + [0x005D]=$'\x5D' # RIGHT SQUARE BRACKET + [0x005E]=$'\x5E' # CIRCUMFLEX ACCENT + [0x005F]=$'\x5F' # LOW LINE + [0x0060]=$'\x60' # GRAVE ACCENT + [0x0061]=$'\x61' # LATIN SMALL LETTER A + [0x0062]=$'\x62' # LATIN SMALL LETTER B + [0x0063]=$'\x63' # LATIN SMALL LETTER C + [0x0064]=$'\x64' # LATIN SMALL LETTER D + [0x0065]=$'\x65' # LATIN SMALL LETTER E + [0x0066]=$'\x66' # LATIN SMALL LETTER F + [0x0067]=$'\x67' # LATIN SMALL LETTER G + [0x0068]=$'\x68' # LATIN SMALL LETTER H + [0x0069]=$'\x69' # LATIN SMALL LETTER I + [0x006A]=$'\x6A' # LATIN SMALL LETTER J + [0x006B]=$'\x6B' # LATIN SMALL LETTER K + [0x006C]=$'\x6C' # LATIN SMALL LETTER L + [0x006D]=$'\x6D' # LATIN SMALL LETTER M + [0x006E]=$'\x6E' # LATIN SMALL LETTER N + [0x006F]=$'\x6F' # LATIN SMALL LETTER O + [0x0070]=$'\x70' # LATIN SMALL LETTER P + [0x0071]=$'\x71' # LATIN SMALL LETTER Q + [0x0072]=$'\x72' # LATIN SMALL LETTER R + [0x0073]=$'\x73' # LATIN SMALL LETTER S + [0x0074]=$'\x74' # LATIN SMALL LETTER T + [0x0075]=$'\x75' # LATIN SMALL LETTER U + [0x0076]=$'\x76' # LATIN SMALL LETTER V + [0x0077]=$'\x77' # LATIN SMALL LETTER W + [0x0078]=$'\x78' # LATIN SMALL LETTER X + [0x0079]=$'\x79' # LATIN SMALL LETTER Y + [0x007A]=$'\x7A' # LATIN SMALL LETTER Z + [0x007B]=$'\x7B' # LEFT CURLY BRACKET + [0x007C]=$'\x7C' # VERTICAL LINE + [0x007D]=$'\x7D' # RIGHT CURLY BRACKET + [0x007E]=$'\x7E' # TILDE + [0x007F]=$'\x7F' # DELETE + [0xFF61]=$'\xA1' # HALFWIDTH IDEOGRAPHIC FULL STOP + [0xFF62]=$'\xA2' # HALFWIDTH LEFT CORNER BRACKET + [0xFF63]=$'\xA3' # HALFWIDTH RIGHT CORNER BRACKET + [0xFF64]=$'\xA4' # HALFWIDTH IDEOGRAPHIC COMMA + [0xFF65]=$'\xA5' # HALFWIDTH KATAKANA MIDDLE DOT + [0xFF66]=$'\xA6' # HALFWIDTH KATAKANA LETTER WO + [0xFF67]=$'\xA7' # HALFWIDTH KATAKANA LETTER SMALL A + [0xFF68]=$'\xA8' # HALFWIDTH KATAKANA LETTER SMALL I + [0xFF69]=$'\xA9' # HALFWIDTH KATAKANA LETTER SMALL U + [0xFF6A]=$'\xAA' # HALFWIDTH KATAKANA LETTER SMALL E + [0xFF6B]=$'\xAB' # HALFWIDTH KATAKANA LETTER SMALL O + [0xFF6C]=$'\xAC' # HALFWIDTH KATAKANA LETTER SMALL YA + [0xFF6D]=$'\xAD' # HALFWIDTH KATAKANA LETTER SMALL YU + [0xFF6E]=$'\xAE' # HALFWIDTH KATAKANA LETTER SMALL YO + [0xFF6F]=$'\xAF' # HALFWIDTH KATAKANA LETTER SMALL TU + [0xFF70]=$'\xB0' # HALFWIDTH KATAKANA-HIRAGANA PROLONGED SOUND MARK + [0xFF71]=$'\xB1' # HALFWIDTH KATAKANA LETTER A + [0xFF72]=$'\xB2' # HALFWIDTH KATAKANA LETTER I + [0xFF73]=$'\xB3' # HALFWIDTH KATAKANA LETTER U + [0xFF74]=$'\xB4' # HALFWIDTH KATAKANA LETTER E + [0xFF75]=$'\xB5' # HALFWIDTH KATAKANA LETTER O + [0xFF76]=$'\xB6' # HALFWIDTH KATAKANA LETTER KA + [0xFF77]=$'\xB7' # HALFWIDTH KATAKANA LETTER KI + [0xFF78]=$'\xB8' # HALFWIDTH KATAKANA LETTER KU + [0xFF79]=$'\xB9' # HALFWIDTH KATAKANA LETTER KE + [0xFF7A]=$'\xBA' # HALFWIDTH KATAKANA LETTER KO + [0xFF7B]=$'\xBB' # HALFWIDTH KATAKANA LETTER SA + [0xFF7C]=$'\xBC' # HALFWIDTH KATAKANA LETTER SI + [0xFF7D]=$'\xBD' # HALFWIDTH KATAKANA LETTER SU + [0xFF7E]=$'\xBE' # HALFWIDTH KATAKANA LETTER SE + [0xFF7F]=$'\xBF' # HALFWIDTH KATAKANA LETTER SO + [0xFF80]=$'\xC0' # HALFWIDTH KATAKANA LETTER TA + [0xFF81]=$'\xC1' # HALFWIDTH KATAKANA LETTER TI + [0xFF82]=$'\xC2' # HALFWIDTH KATAKANA LETTER TU + [0xFF83]=$'\xC3' # HALFWIDTH KATAKANA LETTER TE + [0xFF84]=$'\xC4' # HALFWIDTH KATAKANA LETTER TO + [0xFF85]=$'\xC5' # HALFWIDTH KATAKANA LETTER NA + [0xFF86]=$'\xC6' # HALFWIDTH KATAKANA LETTER NI + [0xFF87]=$'\xC7' # HALFWIDTH KATAKANA LETTER NU + [0xFF88]=$'\xC8' # HALFWIDTH KATAKANA LETTER NE + [0xFF89]=$'\xC9' # HALFWIDTH KATAKANA LETTER NO + [0xFF8A]=$'\xCA' # HALFWIDTH KATAKANA LETTER HA + [0xFF8B]=$'\xCB' # HALFWIDTH KATAKANA LETTER HI + [0xFF8C]=$'\xCC' # HALFWIDTH KATAKANA LETTER HU + [0xFF8D]=$'\xCD' # HALFWIDTH KATAKANA LETTER HE + [0xFF8E]=$'\xCE' # HALFWIDTH KATAKANA LETTER HO + [0xFF8F]=$'\xCF' # HALFWIDTH KATAKANA LETTER MA + [0xFF90]=$'\xD0' # HALFWIDTH KATAKANA LETTER MI + [0xFF91]=$'\xD1' # HALFWIDTH KATAKANA LETTER MU + [0xFF92]=$'\xD2' # HALFWIDTH KATAKANA LETTER ME + [0xFF93]=$'\xD3' # HALFWIDTH KATAKANA LETTER MO + [0xFF94]=$'\xD4' # HALFWIDTH KATAKANA LETTER YA + [0xFF95]=$'\xD5' # HALFWIDTH KATAKANA LETTER YU + [0xFF96]=$'\xD6' # HALFWIDTH KATAKANA LETTER YO + [0xFF97]=$'\xD7' # HALFWIDTH KATAKANA LETTER RA + [0xFF98]=$'\xD8' # HALFWIDTH KATAKANA LETTER RI + [0xFF99]=$'\xD9' # HALFWIDTH KATAKANA LETTER RU + [0xFF9A]=$'\xDA' # HALFWIDTH KATAKANA LETTER RE + [0xFF9B]=$'\xDB' # HALFWIDTH KATAKANA LETTER RO + [0xFF9C]=$'\xDC' # HALFWIDTH KATAKANA LETTER WA + [0xFF9D]=$'\xDD' # HALFWIDTH KATAKANA LETTER N + [0xFF9E]=$'\xDE' # HALFWIDTH KATAKANA VOICED SOUND MARK + [0xFF9F]=$'\xDF' # HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK +) +#TestCodePage ja_JP.SHIFT_JIS jp_JP_SHIFT_JIS +TestCodePage ja_JP.SJIS jp_JP_SHIFT_JIS + +#for ((x=1;x<1000;x++)); do printf ' [0x%04x]=%-11q' "$x" "$(printf "$(printf '\\U%08x' $x)")" ; [ $(($x%5)) = 0 ] && echo; done +C_UTF_8=( + [0x0001]=$'\001' [0x0002]=$'\002' [0x0003]=$'\003' [0x0004]=$'\004' [0x0005]=$'\005' + [0x0006]=$'\006' [0x0007]=$'\a' [0x0008]=$'\b' [0x0009]=$'\t' [0x000a]='' + [0x000b]=$'\v' [0x000c]=$'\f' [0x000d]=$'\r' [0x000e]=$'\016' [0x000f]=$'\017' + [0x0010]=$'\020' [0x0011]=$'\021' [0x0012]=$'\022' [0x0013]=$'\023' [0x0014]=$'\024' + [0x0015]=$'\025' [0x0016]=$'\026' [0x0017]=$'\027' [0x0018]=$'\030' [0x0019]=$'\031' + [0x001a]=$'\032' [0x001b]=$'\E' [0x001c]=$'\034' [0x001d]=$'\035' [0x001e]=$'\036' + [0x001f]=$'\037' [0x0020]=\ [0x0021]=\! [0x0022]=\" [0x0023]=\# + [0x0024]=\$ [0x0025]=% [0x0026]=\& [0x0027]=\' [0x0028]=\( + [0x0029]=\) [0x002a]=\* [0x002b]=+ [0x002c]=\, [0x002d]=- + [0x002e]=. [0x002f]=/ [0x0030]=0 [0x0031]=1 [0x0032]=2 + [0x0033]=3 [0x0034]=4 [0x0035]=5 [0x0036]=6 [0x0037]=7 + [0x0038]=8 [0x0039]=9 [0x003a]=: [0x003b]=\; [0x003c]=\< + [0x003d]== [0x003e]=\> [0x003f]=\? [0x0040]=@ [0x0041]=A + [0x0042]=B [0x0043]=C [0x0044]=D [0x0045]=E [0x0046]=F + [0x0047]=G [0x0048]=H [0x0049]=I [0x004a]=J [0x004b]=K + [0x004c]=L [0x004d]=M [0x004e]=N [0x004f]=O [0x0050]=P + [0x0051]=Q [0x0052]=R [0x0053]=S [0x0054]=T [0x0055]=U + [0x0056]=V [0x0057]=W [0x0058]=X [0x0059]=Y [0x005a]=Z + [0x005b]=\[ [0x005c]=\\ [0x005d]=\] [0x005e]=\^ [0x005f]=_ + [0x0060]=\` [0x0061]=a [0x0062]=b [0x0063]=c [0x0064]=d + [0x0065]=e [0x0066]=f [0x0067]=g [0x0068]=h [0x0069]=i + [0x006a]=j [0x006b]=k [0x006c]=l [0x006d]=m [0x006e]=n + [0x006f]=o [0x0070]=p [0x0071]=q [0x0072]=r [0x0073]=s + [0x0074]=t [0x0075]=u [0x0076]=v [0x0077]=w [0x0078]=x + [0x0079]=y [0x007a]=z [0x007b]=\{ [0x007c]=\| [0x007d]=\} + [0x007e]="~" [0x007f]=$'\177' [0x0080]=$'\302\200' [0x0081]=$'\302\201' [0x0082]=$'\302\202' + [0x0083]=$'\302\203' [0x0084]=$'\302\204' [0x0085]=$'\302\205' [0x0086]=$'\302\206' [0x0087]=$'\302\207' + [0x0088]=$'\302\210' [0x0089]=$'\302\211' [0x008a]=$'\302\212' [0x008b]=$'\302\213' [0x008c]=$'\302\214' + [0x008d]=$'\302\215' [0x008e]=$'\302\216' [0x008f]=$'\302\217' [0x0090]=$'\302\220' [0x0091]=$'\302\221' + [0x0092]=$'\302\222' [0x0093]=$'\302\223' [0x0094]=$'\302\224' [0x0095]=$'\302\225' [0x0096]=$'\302\226' + [0x0097]=$'\302\227' [0x0098]=$'\302\230' [0x0099]=$'\302\231' [0x009a]=$'\302\232' [0x009b]=$'\302\233' + [0x009c]=$'\302\234' [0x009d]=$'\302\235' [0x009e]=$'\302\236' [0x009f]=$'\302\237' [0x00a0]=$'\302\240' + [0x00a1]=$'\302\241' [0x00a2]=$'\302\242' [0x00a3]=$'\302\243' [0x00a4]=$'\302\244' [0x00a5]=$'\302\245' + [0x00a6]=$'\302\246' [0x00a7]=$'\302\247' [0x00a8]=$'\302\250' [0x00a9]=$'\302\251' [0x00aa]=$'\302\252' + [0x00ab]=$'\302\253' [0x00ac]=$'\302\254' [0x00ad]=$'\302\255' [0x00ae]=$'\302\256' [0x00af]=$'\302\257' + [0x00b0]=$'\302\260' [0x00b1]=$'\302\261' [0x00b2]=$'\302\262' [0x00b3]=$'\302\263' [0x00b4]=$'\302\264' + [0x00b5]=$'\302\265' [0x00b6]=$'\302\266' [0x00b7]=$'\302\267' [0x00b8]=$'\302\270' [0x00b9]=$'\302\271' + [0x00ba]=$'\302\272' [0x00bb]=$'\302\273' [0x00bc]=$'\302\274' [0x00bd]=$'\302\275' [0x00be]=$'\302\276' + [0x00bf]=$'\302\277' [0x00c0]=$'\303\200' [0x00c1]=$'\303\201' [0x00c2]=$'\303\202' [0x00c3]=$'\303\203' + [0x00c4]=$'\303\204' [0x00c5]=$'\303\205' [0x00c6]=$'\303\206' [0x00c7]=$'\303\207' [0x00c8]=$'\303\210' + [0x00c9]=$'\303\211' [0x00ca]=$'\303\212' [0x00cb]=$'\303\213' [0x00cc]=$'\303\214' [0x00cd]=$'\303\215' + [0x00ce]=$'\303\216' [0x00cf]=$'\303\217' [0x00d0]=$'\303\220' [0x00d1]=$'\303\221' [0x00d2]=$'\303\222' + [0x00d3]=$'\303\223' [0x00d4]=$'\303\224' [0x00d5]=$'\303\225' [0x00d6]=$'\303\226' [0x00d7]=$'\303\227' + [0x00d8]=$'\303\230' [0x00d9]=$'\303\231' [0x00da]=$'\303\232' [0x00db]=$'\303\233' [0x00dc]=$'\303\234' + [0x00dd]=$'\303\235' [0x00de]=$'\303\236' [0x00df]=$'\303\237' [0x00e0]=$'\303\240' [0x00e1]=$'\303\241' + [0x00e2]=$'\303\242' [0x00e3]=$'\303\243' [0x00e4]=$'\303\244' [0x00e5]=$'\303\245' [0x00e6]=$'\303\246' + [0x00e7]=$'\303\247' [0x00e8]=$'\303\250' [0x00e9]=$'\303\251' [0x00ea]=$'\303\252' [0x00eb]=$'\303\253' + [0x00ec]=$'\303\254' [0x00ed]=$'\303\255' [0x00ee]=$'\303\256' [0x00ef]=$'\303\257' [0x00f0]=$'\303\260' + [0x00f1]=$'\303\261' [0x00f2]=$'\303\262' [0x00f3]=$'\303\263' [0x00f4]=$'\303\264' [0x00f5]=$'\303\265' + [0x00f6]=$'\303\266' [0x00f7]=$'\303\267' [0x00f8]=$'\303\270' [0x00f9]=$'\303\271' [0x00fa]=$'\303\272' + [0x00fb]=$'\303\273' [0x00fc]=$'\303\274' [0x00fd]=$'\303\275' [0x00fe]=$'\303\276' [0x00ff]=$'\303\277' + [0x0100]=$'\304\200' [0x0101]=$'\304\201' [0x0102]=$'\304\202' [0x0103]=$'\304\203' [0x0104]=$'\304\204' + [0x0105]=$'\304\205' [0x0106]=$'\304\206' [0x0107]=$'\304\207' [0x0108]=$'\304\210' [0x0109]=$'\304\211' + [0x010a]=$'\304\212' [0x010b]=$'\304\213' [0x010c]=$'\304\214' [0x010d]=$'\304\215' [0x010e]=$'\304\216' + [0x010f]=$'\304\217' [0x0110]=$'\304\220' [0x0111]=$'\304\221' [0x0112]=$'\304\222' [0x0113]=$'\304\223' + [0x0114]=$'\304\224' [0x0115]=$'\304\225' [0x0116]=$'\304\226' [0x0117]=$'\304\227' [0x0118]=$'\304\230' + [0x0119]=$'\304\231' [0x011a]=$'\304\232' [0x011b]=$'\304\233' [0x011c]=$'\304\234' [0x011d]=$'\304\235' + [0x011e]=$'\304\236' [0x011f]=$'\304\237' [0x0120]=$'\304\240' [0x0121]=$'\304\241' [0x0122]=$'\304\242' + [0x0123]=$'\304\243' [0x0124]=$'\304\244' [0x0125]=$'\304\245' [0x0126]=$'\304\246' [0x0127]=$'\304\247' + [0x0128]=$'\304\250' [0x0129]=$'\304\251' [0x012a]=$'\304\252' [0x012b]=$'\304\253' [0x012c]=$'\304\254' + [0x012d]=$'\304\255' [0x012e]=$'\304\256' [0x012f]=$'\304\257' [0x0130]=$'\304\260' [0x0131]=$'\304\261' + [0x0132]=$'\304\262' [0x0133]=$'\304\263' [0x0134]=$'\304\264' [0x0135]=$'\304\265' [0x0136]=$'\304\266' + [0x0137]=$'\304\267' [0x0138]=$'\304\270' [0x0139]=$'\304\271' [0x013a]=$'\304\272' [0x013b]=$'\304\273' + [0x013c]=$'\304\274' [0x013d]=$'\304\275' [0x013e]=$'\304\276' [0x013f]=$'\304\277' [0x0140]=$'\305\200' + [0x0141]=$'\305\201' [0x0142]=$'\305\202' [0x0143]=$'\305\203' [0x0144]=$'\305\204' [0x0145]=$'\305\205' + [0x0146]=$'\305\206' [0x0147]=$'\305\207' [0x0148]=$'\305\210' [0x0149]=$'\305\211' [0x014a]=$'\305\212' + [0x014b]=$'\305\213' [0x014c]=$'\305\214' [0x014d]=$'\305\215' [0x014e]=$'\305\216' [0x014f]=$'\305\217' + [0x0150]=$'\305\220' [0x0151]=$'\305\221' [0x0152]=$'\305\222' [0x0153]=$'\305\223' [0x0154]=$'\305\224' + [0x0155]=$'\305\225' [0x0156]=$'\305\226' [0x0157]=$'\305\227' [0x0158]=$'\305\230' [0x0159]=$'\305\231' + [0x015a]=$'\305\232' [0x015b]=$'\305\233' [0x015c]=$'\305\234' [0x015d]=$'\305\235' [0x015e]=$'\305\236' + [0x015f]=$'\305\237' [0x0160]=$'\305\240' [0x0161]=$'\305\241' [0x0162]=$'\305\242' [0x0163]=$'\305\243' + [0x0164]=$'\305\244' [0x0165]=$'\305\245' [0x0166]=$'\305\246' [0x0167]=$'\305\247' [0x0168]=$'\305\250' + [0x0169]=$'\305\251' [0x016a]=$'\305\252' [0x016b]=$'\305\253' [0x016c]=$'\305\254' [0x016d]=$'\305\255' + [0x016e]=$'\305\256' [0x016f]=$'\305\257' [0x0170]=$'\305\260' [0x0171]=$'\305\261' [0x0172]=$'\305\262' + [0x0173]=$'\305\263' [0x0174]=$'\305\264' [0x0175]=$'\305\265' [0x0176]=$'\305\266' [0x0177]=$'\305\267' + [0x0178]=$'\305\270' [0x0179]=$'\305\271' [0x017a]=$'\305\272' [0x017b]=$'\305\273' [0x017c]=$'\305\274' + [0x017d]=$'\305\275' [0x017e]=$'\305\276' [0x017f]=$'\305\277' [0x0180]=$'\306\200' [0x0181]=$'\306\201' + [0x0182]=$'\306\202' [0x0183]=$'\306\203' [0x0184]=$'\306\204' [0x0185]=$'\306\205' [0x0186]=$'\306\206' + [0x0187]=$'\306\207' [0x0188]=$'\306\210' [0x0189]=$'\306\211' [0x018a]=$'\306\212' [0x018b]=$'\306\213' + [0x018c]=$'\306\214' [0x018d]=$'\306\215' [0x018e]=$'\306\216' [0x018f]=$'\306\217' [0x0190]=$'\306\220' + [0x0191]=$'\306\221' [0x0192]=$'\306\222' [0x0193]=$'\306\223' [0x0194]=$'\306\224' [0x0195]=$'\306\225' + [0x0196]=$'\306\226' [0x0197]=$'\306\227' [0x0198]=$'\306\230' [0x0199]=$'\306\231' [0x019a]=$'\306\232' + [0x019b]=$'\306\233' [0x019c]=$'\306\234' [0x019d]=$'\306\235' [0x019e]=$'\306\236' [0x019f]=$'\306\237' + [0x01a0]=$'\306\240' [0x01a1]=$'\306\241' [0x01a2]=$'\306\242' [0x01a3]=$'\306\243' [0x01a4]=$'\306\244' + [0x01a5]=$'\306\245' [0x01a6]=$'\306\246' [0x01a7]=$'\306\247' [0x01a8]=$'\306\250' [0x01a9]=$'\306\251' + [0x01aa]=$'\306\252' [0x01ab]=$'\306\253' [0x01ac]=$'\306\254' [0x01ad]=$'\306\255' [0x01ae]=$'\306\256' + [0x01af]=$'\306\257' [0x01b0]=$'\306\260' [0x01b1]=$'\306\261' [0x01b2]=$'\306\262' [0x01b3]=$'\306\263' + [0x01b4]=$'\306\264' [0x01b5]=$'\306\265' [0x01b6]=$'\306\266' [0x01b7]=$'\306\267' [0x01b8]=$'\306\270' + [0x01b9]=$'\306\271' [0x01ba]=$'\306\272' [0x01bb]=$'\306\273' [0x01bc]=$'\306\274' [0x01bd]=$'\306\275' + [0x01be]=$'\306\276' [0x01bf]=$'\306\277' [0x01c0]=$'\307\200' [0x01c1]=$'\307\201' [0x01c2]=$'\307\202' + [0x01c3]=$'\307\203' [0x01c4]=$'\307\204' [0x01c5]=$'\307\205' [0x01c6]=$'\307\206' [0x01c7]=$'\307\207' + [0x01c8]=$'\307\210' [0x01c9]=$'\307\211' [0x01ca]=$'\307\212' [0x01cb]=$'\307\213' [0x01cc]=$'\307\214' + [0x01cd]=$'\307\215' [0x01ce]=$'\307\216' [0x01cf]=$'\307\217' [0x01d0]=$'\307\220' [0x01d1]=$'\307\221' + [0x01d2]=$'\307\222' [0x01d3]=$'\307\223' [0x01d4]=$'\307\224' [0x01d5]=$'\307\225' [0x01d6]=$'\307\226' + [0x01d7]=$'\307\227' [0x01d8]=$'\307\230' [0x01d9]=$'\307\231' [0x01da]=$'\307\232' [0x01db]=$'\307\233' + [0x01dc]=$'\307\234' [0x01dd]=$'\307\235' [0x01de]=$'\307\236' [0x01df]=$'\307\237' [0x01e0]=$'\307\240' + [0x01e1]=$'\307\241' [0x01e2]=$'\307\242' [0x01e3]=$'\307\243' [0x01e4]=$'\307\244' [0x01e5]=$'\307\245' + [0x01e6]=$'\307\246' [0x01e7]=$'\307\247' [0x01e8]=$'\307\250' [0x01e9]=$'\307\251' [0x01ea]=$'\307\252' + [0x01eb]=$'\307\253' [0x01ec]=$'\307\254' [0x01ed]=$'\307\255' [0x01ee]=$'\307\256' [0x01ef]=$'\307\257' + [0x01f0]=$'\307\260' [0x01f1]=$'\307\261' [0x01f2]=$'\307\262' [0x01f3]=$'\307\263' [0x01f4]=$'\307\264' + [0x01f5]=$'\307\265' [0x01f6]=$'\307\266' [0x01f7]=$'\307\267' [0x01f8]=$'\307\270' [0x01f9]=$'\307\271' + [0x01fa]=$'\307\272' [0x01fb]=$'\307\273' [0x01fc]=$'\307\274' [0x01fd]=$'\307\275' [0x01fe]=$'\307\276' + [0x01ff]=$'\307\277' [0x0200]=$'\310\200' [0x0201]=$'\310\201' [0x0202]=$'\310\202' [0x0203]=$'\310\203' + [0x0204]=$'\310\204' [0x0205]=$'\310\205' [0x0206]=$'\310\206' [0x0207]=$'\310\207' [0x0208]=$'\310\210' + [0x0209]=$'\310\211' [0x020a]=$'\310\212' [0x020b]=$'\310\213' [0x020c]=$'\310\214' [0x020d]=$'\310\215' + [0x020e]=$'\310\216' [0x020f]=$'\310\217' [0x0210]=$'\310\220' [0x0211]=$'\310\221' [0x0212]=$'\310\222' + [0x0213]=$'\310\223' [0x0214]=$'\310\224' [0x0215]=$'\310\225' [0x0216]=$'\310\226' [0x0217]=$'\310\227' + [0x0218]=$'\310\230' [0x0219]=$'\310\231' [0x021a]=$'\310\232' [0x021b]=$'\310\233' [0x021c]=$'\310\234' + [0x021d]=$'\310\235' [0x021e]=$'\310\236' [0x021f]=$'\310\237' [0x0220]=$'\310\240' [0x0221]=$'\310\241' + [0x0222]=$'\310\242' [0x0223]=$'\310\243' [0x0224]=$'\310\244' [0x0225]=$'\310\245' [0x0226]=$'\310\246' + [0x0227]=$'\310\247' [0x0228]=$'\310\250' [0x0229]=$'\310\251' [0x022a]=$'\310\252' [0x022b]=$'\310\253' + [0x022c]=$'\310\254' [0x022d]=$'\310\255' [0x022e]=$'\310\256' [0x022f]=$'\310\257' [0x0230]=$'\310\260' + [0x0231]=$'\310\261' [0x0232]=$'\310\262' [0x0233]=$'\310\263' [0x0234]=$'\310\264' [0x0235]=$'\310\265' + [0x0236]=$'\310\266' [0x0237]=$'\310\267' [0x0238]=$'\310\270' [0x0239]=$'\310\271' [0x023a]=$'\310\272' + [0x023b]=$'\310\273' [0x023c]=$'\310\274' [0x023d]=$'\310\275' [0x023e]=$'\310\276' [0x023f]=$'\310\277' + [0x0240]=$'\311\200' [0x0241]=$'\311\201' [0x0242]=$'\311\202' [0x0243]=$'\311\203' [0x0244]=$'\311\204' + [0x0245]=$'\311\205' [0x0246]=$'\311\206' [0x0247]=$'\311\207' [0x0248]=$'\311\210' [0x0249]=$'\311\211' + [0x024a]=$'\311\212' [0x024b]=$'\311\213' [0x024c]=$'\311\214' [0x024d]=$'\311\215' [0x024e]=$'\311\216' + [0x024f]=$'\311\217' [0x0250]=$'\311\220' [0x0251]=$'\311\221' [0x0252]=$'\311\222' [0x0253]=$'\311\223' + [0x0254]=$'\311\224' [0x0255]=$'\311\225' [0x0256]=$'\311\226' [0x0257]=$'\311\227' [0x0258]=$'\311\230' + [0x0259]=$'\311\231' [0x025a]=$'\311\232' [0x025b]=$'\311\233' [0x025c]=$'\311\234' [0x025d]=$'\311\235' + [0x025e]=$'\311\236' [0x025f]=$'\311\237' [0x0260]=$'\311\240' [0x0261]=$'\311\241' [0x0262]=$'\311\242' + [0x0263]=$'\311\243' [0x0264]=$'\311\244' [0x0265]=$'\311\245' [0x0266]=$'\311\246' [0x0267]=$'\311\247' + [0x0268]=$'\311\250' [0x0269]=$'\311\251' [0x026a]=$'\311\252' [0x026b]=$'\311\253' [0x026c]=$'\311\254' + [0x026d]=$'\311\255' [0x026e]=$'\311\256' [0x026f]=$'\311\257' [0x0270]=$'\311\260' [0x0271]=$'\311\261' + [0x0272]=$'\311\262' [0x0273]=$'\311\263' [0x0274]=$'\311\264' [0x0275]=$'\311\265' [0x0276]=$'\311\266' + [0x0277]=$'\311\267' [0x0278]=$'\311\270' [0x0279]=$'\311\271' [0x027a]=$'\311\272' [0x027b]=$'\311\273' + [0x027c]=$'\311\274' [0x027d]=$'\311\275' [0x027e]=$'\311\276' [0x027f]=$'\311\277' [0x0280]=$'\312\200' + [0x0281]=$'\312\201' [0x0282]=$'\312\202' [0x0283]=$'\312\203' [0x0284]=$'\312\204' [0x0285]=$'\312\205' + [0x0286]=$'\312\206' [0x0287]=$'\312\207' [0x0288]=$'\312\210' [0x0289]=$'\312\211' [0x028a]=$'\312\212' + [0x028b]=$'\312\213' [0x028c]=$'\312\214' [0x028d]=$'\312\215' [0x028e]=$'\312\216' [0x028f]=$'\312\217' + [0x0290]=$'\312\220' [0x0291]=$'\312\221' [0x0292]=$'\312\222' [0x0293]=$'\312\223' [0x0294]=$'\312\224' + [0x0295]=$'\312\225' [0x0296]=$'\312\226' [0x0297]=$'\312\227' [0x0298]=$'\312\230' [0x0299]=$'\312\231' + [0x029a]=$'\312\232' [0x029b]=$'\312\233' [0x029c]=$'\312\234' [0x029d]=$'\312\235' [0x029e]=$'\312\236' + [0x029f]=$'\312\237' [0x02a0]=$'\312\240' [0x02a1]=$'\312\241' [0x02a2]=$'\312\242' [0x02a3]=$'\312\243' + [0x02a4]=$'\312\244' [0x02a5]=$'\312\245' [0x02a6]=$'\312\246' [0x02a7]=$'\312\247' [0x02a8]=$'\312\250' + [0x02a9]=$'\312\251' [0x02aa]=$'\312\252' [0x02ab]=$'\312\253' [0x02ac]=$'\312\254' [0x02ad]=$'\312\255' + [0x02ae]=$'\312\256' [0x02af]=$'\312\257' [0x02b0]=$'\312\260' [0x02b1]=$'\312\261' [0x02b2]=$'\312\262' + [0x02b3]=$'\312\263' [0x02b4]=$'\312\264' [0x02b5]=$'\312\265' [0x02b6]=$'\312\266' [0x02b7]=$'\312\267' + [0x02b8]=$'\312\270' [0x02b9]=$'\312\271' [0x02ba]=$'\312\272' [0x02bb]=$'\312\273' [0x02bc]=$'\312\274' + [0x02bd]=$'\312\275' [0x02be]=$'\312\276' [0x02bf]=$'\312\277' [0x02c0]=$'\313\200' [0x02c1]=$'\313\201' + [0x02c2]=$'\313\202' [0x02c3]=$'\313\203' [0x02c4]=$'\313\204' [0x02c5]=$'\313\205' [0x02c6]=$'\313\206' + [0x02c7]=$'\313\207' [0x02c8]=$'\313\210' [0x02c9]=$'\313\211' [0x02ca]=$'\313\212' [0x02cb]=$'\313\213' + [0x02cc]=$'\313\214' [0x02cd]=$'\313\215' [0x02ce]=$'\313\216' [0x02cf]=$'\313\217' [0x02d0]=$'\313\220' + [0x02d1]=$'\313\221' [0x02d2]=$'\313\222' [0x02d3]=$'\313\223' [0x02d4]=$'\313\224' [0x02d5]=$'\313\225' + [0x02d6]=$'\313\226' [0x02d7]=$'\313\227' [0x02d8]=$'\313\230' [0x02d9]=$'\313\231' [0x02da]=$'\313\232' + [0x02db]=$'\313\233' [0x02dc]=$'\313\234' [0x02dd]=$'\313\235' [0x02de]=$'\313\236' [0x02df]=$'\313\237' + [0x02e0]=$'\313\240' [0x02e1]=$'\313\241' [0x02e2]=$'\313\242' [0x02e3]=$'\313\243' [0x02e4]=$'\313\244' + [0x02e5]=$'\313\245' [0x02e6]=$'\313\246' [0x02e7]=$'\313\247' [0x02e8]=$'\313\250' [0x02e9]=$'\313\251' + [0x02ea]=$'\313\252' [0x02eb]=$'\313\253' [0x02ec]=$'\313\254' [0x02ed]=$'\313\255' [0x02ee]=$'\313\256' + [0x02ef]=$'\313\257' [0x02f0]=$'\313\260' [0x02f1]=$'\313\261' [0x02f2]=$'\313\262' [0x02f3]=$'\313\263' + [0x02f4]=$'\313\264' [0x02f5]=$'\313\265' [0x02f6]=$'\313\266' [0x02f7]=$'\313\267' [0x02f8]=$'\313\270' + [0x02f9]=$'\313\271' [0x02fa]=$'\313\272' [0x02fb]=$'\313\273' [0x02fc]=$'\313\274' [0x02fd]=$'\313\275' + [0x02fe]=$'\313\276' [0x02ff]=$'\313\277' [0x0300]=$'\314\200' [0x0301]=$'\314\201' [0x0302]=$'\314\202' + [0x0303]=$'\314\203' [0x0304]=$'\314\204' [0x0305]=$'\314\205' [0x0306]=$'\314\206' [0x0307]=$'\314\207' + [0x0308]=$'\314\210' [0x0309]=$'\314\211' [0x030a]=$'\314\212' [0x030b]=$'\314\213' [0x030c]=$'\314\214' + [0x030d]=$'\314\215' [0x030e]=$'\314\216' [0x030f]=$'\314\217' [0x0310]=$'\314\220' [0x0311]=$'\314\221' + [0x0312]=$'\314\222' [0x0313]=$'\314\223' [0x0314]=$'\314\224' [0x0315]=$'\314\225' [0x0316]=$'\314\226' + [0x0317]=$'\314\227' [0x0318]=$'\314\230' [0x0319]=$'\314\231' [0x031a]=$'\314\232' [0x031b]=$'\314\233' + [0x031c]=$'\314\234' [0x031d]=$'\314\235' [0x031e]=$'\314\236' [0x031f]=$'\314\237' [0x0320]=$'\314\240' + [0x0321]=$'\314\241' [0x0322]=$'\314\242' [0x0323]=$'\314\243' [0x0324]=$'\314\244' [0x0325]=$'\314\245' + [0x0326]=$'\314\246' [0x0327]=$'\314\247' [0x0328]=$'\314\250' [0x0329]=$'\314\251' [0x032a]=$'\314\252' + [0x032b]=$'\314\253' [0x032c]=$'\314\254' [0x032d]=$'\314\255' [0x032e]=$'\314\256' [0x032f]=$'\314\257' + [0x0330]=$'\314\260' [0x0331]=$'\314\261' [0x0332]=$'\314\262' [0x0333]=$'\314\263' [0x0334]=$'\314\264' + [0x0335]=$'\314\265' [0x0336]=$'\314\266' [0x0337]=$'\314\267' [0x0338]=$'\314\270' [0x0339]=$'\314\271' + [0x033a]=$'\314\272' [0x033b]=$'\314\273' [0x033c]=$'\314\274' [0x033d]=$'\314\275' [0x033e]=$'\314\276' + [0x033f]=$'\314\277' [0x0340]=$'\315\200' [0x0341]=$'\315\201' [0x0342]=$'\315\202' [0x0343]=$'\315\203' + [0x0344]=$'\315\204' [0x0345]=$'\315\205' [0x0346]=$'\315\206' [0x0347]=$'\315\207' [0x0348]=$'\315\210' + [0x0349]=$'\315\211' [0x034a]=$'\315\212' [0x034b]=$'\315\213' [0x034c]=$'\315\214' [0x034d]=$'\315\215' + [0x034e]=$'\315\216' [0x034f]=$'\315\217' [0x0350]=$'\315\220' [0x0351]=$'\315\221' [0x0352]=$'\315\222' + [0x0353]=$'\315\223' [0x0354]=$'\315\224' [0x0355]=$'\315\225' [0x0356]=$'\315\226' [0x0357]=$'\315\227' + [0x0358]=$'\315\230' [0x0359]=$'\315\231' [0x035a]=$'\315\232' [0x035b]=$'\315\233' [0x035c]=$'\315\234' + [0x035d]=$'\315\235' [0x035e]=$'\315\236' [0x035f]=$'\315\237' [0x0360]=$'\315\240' [0x0361]=$'\315\241' + [0x0362]=$'\315\242' [0x0363]=$'\315\243' [0x0364]=$'\315\244' [0x0365]=$'\315\245' [0x0366]=$'\315\246' + [0x0367]=$'\315\247' [0x0368]=$'\315\250' [0x0369]=$'\315\251' [0x036a]=$'\315\252' [0x036b]=$'\315\253' + [0x036c]=$'\315\254' [0x036d]=$'\315\255' [0x036e]=$'\315\256' [0x036f]=$'\315\257' [0x0370]=$'\315\260' + [0x0371]=$'\315\261' [0x0372]=$'\315\262' [0x0373]=$'\315\263' [0x0374]=$'\315\264' [0x0375]=$'\315\265' + [0x0376]=$'\315\266' [0x0377]=$'\315\267' [0x0378]=$'\315\270' [0x0379]=$'\315\271' [0x037a]=$'\315\272' + [0x037b]=$'\315\273' [0x037c]=$'\315\274' [0x037d]=$'\315\275' [0x037e]=$'\315\276' [0x037f]=$'\315\277' + [0x0380]=$'\316\200' [0x0381]=$'\316\201' [0x0382]=$'\316\202' [0x0383]=$'\316\203' [0x0384]=$'\316\204' + [0x0385]=$'\316\205' [0x0386]=$'\316\206' [0x0387]=$'\316\207' [0x0388]=$'\316\210' [0x0389]=$'\316\211' + [0x038a]=$'\316\212' [0x038b]=$'\316\213' [0x038c]=$'\316\214' [0x038d]=$'\316\215' [0x038e]=$'\316\216' + [0x038f]=$'\316\217' [0x0390]=$'\316\220' [0x0391]=$'\316\221' [0x0392]=$'\316\222' [0x0393]=$'\316\223' + [0x0394]=$'\316\224' [0x0395]=$'\316\225' [0x0396]=$'\316\226' [0x0397]=$'\316\227' [0x0398]=$'\316\230' + [0x0399]=$'\316\231' [0x039a]=$'\316\232' [0x039b]=$'\316\233' [0x039c]=$'\316\234' [0x039d]=$'\316\235' + [0x039e]=$'\316\236' [0x039f]=$'\316\237' [0x03a0]=$'\316\240' [0x03a1]=$'\316\241' [0x03a2]=$'\316\242' + [0x03a3]=$'\316\243' [0x03a4]=$'\316\244' [0x03a5]=$'\316\245' [0x03a6]=$'\316\246' [0x03a7]=$'\316\247' + [0x03a8]=$'\316\250' [0x03a9]=$'\316\251' [0x03aa]=$'\316\252' [0x03ab]=$'\316\253' [0x03ac]=$'\316\254' + [0x03ad]=$'\316\255' [0x03ae]=$'\316\256' [0x03af]=$'\316\257' [0x03b0]=$'\316\260' [0x03b1]=$'\316\261' + [0x03b2]=$'\316\262' [0x03b3]=$'\316\263' [0x03b4]=$'\316\264' [0x03b5]=$'\316\265' [0x03b6]=$'\316\266' + [0x03b7]=$'\316\267' [0x03b8]=$'\316\270' [0x03b9]=$'\316\271' [0x03ba]=$'\316\272' [0x03bb]=$'\316\273' + [0x03bc]=$'\316\274' [0x03bd]=$'\316\275' [0x03be]=$'\316\276' [0x03bf]=$'\316\277' [0x03c0]=$'\317\200' + [0x03c1]=$'\317\201' [0x03c2]=$'\317\202' [0x03c3]=$'\317\203' [0x03c4]=$'\317\204' [0x03c5]=$'\317\205' + [0x03c6]=$'\317\206' [0x03c7]=$'\317\207' [0x03c8]=$'\317\210' [0x03c9]=$'\317\211' [0x03ca]=$'\317\212' + [0x03cb]=$'\317\213' [0x03cc]=$'\317\214' [0x03cd]=$'\317\215' [0x03ce]=$'\317\216' [0x03cf]=$'\317\217' + [0x03d0]=$'\317\220' [0x03d1]=$'\317\221' [0x03d2]=$'\317\222' [0x03d3]=$'\317\223' [0x03d4]=$'\317\224' + [0x03d5]=$'\317\225' [0x03d6]=$'\317\226' [0x03d7]=$'\317\227' [0x03d8]=$'\317\230' [0x03d9]=$'\317\231' + [0x03da]=$'\317\232' [0x03db]=$'\317\233' [0x03dc]=$'\317\234' [0x03dd]=$'\317\235' [0x03de]=$'\317\236' + [0x03df]=$'\317\237' [0x03e0]=$'\317\240' [0x03e1]=$'\317\241' [0x03e2]=$'\317\242' [0x03e3]=$'\317\243' + [0x03e4]=$'\317\244' [0x03e5]=$'\317\245' [0x03e6]=$'\317\246' [0x03e7]=$'\317\247' + + + [0x1000]=$'\341\200\200' [0x1001]=$'\341\200\201' [0x1002]=$'\341\200\202' [0x1003]=$'\341\200\203' [0x1004]=$'\341\200\204' + [0x1005]=$'\341\200\205' [0x1006]=$'\341\200\206' [0x1007]=$'\341\200\207' [0x1008]=$'\341\200\210' [0x1009]=$'\341\200\211' + [0x100a]=$'\341\200\212' [0x100b]=$'\341\200\213' [0x100c]=$'\341\200\214' [0x100d]=$'\341\200\215' [0x100e]=$'\341\200\216' + [0x100f]=$'\341\200\217' [0x1010]=$'\341\200\220' [0x1011]=$'\341\200\221' [0x1012]=$'\341\200\222' [0x1013]=$'\341\200\223' + [0x1014]=$'\341\200\224' [0x1015]=$'\341\200\225' [0x1016]=$'\341\200\226' [0x1017]=$'\341\200\227' [0x1018]=$'\341\200\230' + [0x1019]=$'\341\200\231' [0x101a]=$'\341\200\232' [0x101b]=$'\341\200\233' [0x101c]=$'\341\200\234' [0x101d]=$'\341\200\235' + [0x101e]=$'\341\200\236' [0x101f]=$'\341\200\237' [0x1020]=$'\341\200\240' [0x1021]=$'\341\200\241' [0x1022]=$'\341\200\242' + [0x1023]=$'\341\200\243' [0x1024]=$'\341\200\244' [0x1025]=$'\341\200\245' [0x1026]=$'\341\200\246' [0x1027]=$'\341\200\247' + [0x1028]=$'\341\200\250' [0x1029]=$'\341\200\251' [0x102a]=$'\341\200\252' [0x102b]=$'\341\200\253' [0x102c]=$'\341\200\254' + [0x102d]=$'\341\200\255' [0x102e]=$'\341\200\256' [0x102f]=$'\341\200\257' [0x1030]=$'\341\200\260' [0x1031]=$'\341\200\261' + [0x1032]=$'\341\200\262' [0x1033]=$'\341\200\263' [0x1034]=$'\341\200\264' [0x1035]=$'\341\200\265' [0x1036]=$'\341\200\266' + [0x1037]=$'\341\200\267' [0x1038]=$'\341\200\270' [0x1039]=$'\341\200\271' [0x103a]=$'\341\200\272' [0x103b]=$'\341\200\273' + [0x103c]=$'\341\200\274' [0x103d]=$'\341\200\275' [0x103e]=$'\341\200\276' [0x103f]=$'\341\200\277' [0x1040]=$'\341\201\200' + [0x1041]=$'\341\201\201' [0x1042]=$'\341\201\202' [0x1043]=$'\341\201\203' [0x1044]=$'\341\201\204' [0x1045]=$'\341\201\205' + [0x1046]=$'\341\201\206' [0x1047]=$'\341\201\207' [0x1048]=$'\341\201\210' [0x1049]=$'\341\201\211' [0x104a]=$'\341\201\212' + [0x104b]=$'\341\201\213' [0x104c]=$'\341\201\214' [0x104d]=$'\341\201\215' [0x104e]=$'\341\201\216' [0x104f]=$'\341\201\217' + + [0x10000]=$'\360\220\200\200' [0x10001]=$'\360\220\200\201' [0x10002]=$'\360\220\200\202' [0x10003]=$'\360\220\200\203' [0x10004]=$'\360\220\200\204' + [0x10005]=$'\360\220\200\205' [0x10006]=$'\360\220\200\206' [0x10007]=$'\360\220\200\207' [0x10008]=$'\360\220\200\210' [0x10009]=$'\360\220\200\211' + [0x1000a]=$'\360\220\200\212' [0x1000b]=$'\360\220\200\213' [0x1000c]=$'\360\220\200\214' [0x1000d]=$'\360\220\200\215' [0x1000e]=$'\360\220\200\216' + [0x1000f]=$'\360\220\200\217' [0x10010]=$'\360\220\200\220' [0x10011]=$'\360\220\200\221' [0x10012]=$'\360\220\200\222' [0x10013]=$'\360\220\200\223' + [0x10014]=$'\360\220\200\224' [0x10015]=$'\360\220\200\225' [0x10016]=$'\360\220\200\226' [0x10017]=$'\360\220\200\227' [0x10018]=$'\360\220\200\230' + [0x10019]=$'\360\220\200\231' [0x1001a]=$'\360\220\200\232' [0x1001b]=$'\360\220\200\233' [0x1001c]=$'\360\220\200\234' [0x1001d]=$'\360\220\200\235' + [0x1001e]=$'\360\220\200\236' [0x1001f]=$'\360\220\200\237' [0x10020]=$'\360\220\200\240' [0x10021]=$'\360\220\200\241' [0x10022]=$'\360\220\200\242' + [0x10023]=$'\360\220\200\243' [0x10024]=$'\360\220\200\244' [0x10025]=$'\360\220\200\245' [0x10026]=$'\360\220\200\246' [0x10027]=$'\360\220\200\247' + [0x10028]=$'\360\220\200\250' [0x10029]=$'\360\220\200\251' [0x1002a]=$'\360\220\200\252' [0x1002b]=$'\360\220\200\253' [0x1002c]=$'\360\220\200\254' + [0x1002d]=$'\360\220\200\255' [0x1002e]=$'\360\220\200\256' [0x1002f]=$'\360\220\200\257' [0x10030]=$'\360\220\200\260' [0x10031]=$'\360\220\200\261' + [0x10032]=$'\360\220\200\262' [0x10033]=$'\360\220\200\263' [0x10034]=$'\360\220\200\264' [0x10035]=$'\360\220\200\265' [0x10036]=$'\360\220\200\266' + [0x10037]=$'\360\220\200\267' [0x10038]=$'\360\220\200\270' [0x10039]=$'\360\220\200\271' [0x1003a]=$'\360\220\200\272' [0x1003b]=$'\360\220\200\273' + [0x1003c]=$'\360\220\200\274' [0x1003d]=$'\360\220\200\275' [0x1003e]=$'\360\220\200\276' [0x1003f]=$'\360\220\200\277' [0x10040]=$'\360\220\201\200' + [0x10041]=$'\360\220\201\201' [0x10042]=$'\360\220\201\202' [0x10043]=$'\360\220\201\203' [0x10044]=$'\360\220\201\204' [0x10045]=$'\360\220\201\205' + [0x10046]=$'\360\220\201\206' [0x10047]=$'\360\220\201\207' [0x10048]=$'\360\220\201\210' [0x10049]=$'\360\220\201\211' [0x1004a]=$'\360\220\201\212' + [0x1004b]=$'\360\220\201\213' [0x1004c]=$'\360\220\201\214' [0x1004d]=$'\360\220\201\215' [0x1004e]=$'\360\220\201\216' [0x1004f]=$'\360\220\201\217' + + [0x1000000]=$'\371\200\200\200\200' [0x1000001]=$'\371\200\200\200\201' [0x1000002]=$'\371\200\200\200\202' [0x1000003]=$'\371\200\200\200\203' [0x1000004]=$'\371\200\200\200\204' + [0x1000005]=$'\371\200\200\200\205' [0x1000006]=$'\371\200\200\200\206' [0x1000007]=$'\371\200\200\200\207' [0x1000008]=$'\371\200\200\200\210' [0x1000009]=$'\371\200\200\200\211' + [0x100000a]=$'\371\200\200\200\212' [0x100000b]=$'\371\200\200\200\213' [0x100000c]=$'\371\200\200\200\214' [0x100000d]=$'\371\200\200\200\215' [0x100000e]=$'\371\200\200\200\216' + [0x100000f]=$'\371\200\200\200\217' [0x1000010]=$'\371\200\200\200\220' [0x1000011]=$'\371\200\200\200\221' [0x1000012]=$'\371\200\200\200\222' [0x1000013]=$'\371\200\200\200\223' + [0x1000014]=$'\371\200\200\200\224' [0x1000015]=$'\371\200\200\200\225' [0x1000016]=$'\371\200\200\200\226' [0x1000017]=$'\371\200\200\200\227' [0x1000018]=$'\371\200\200\200\230' + [0x1000019]=$'\371\200\200\200\231' [0x100001a]=$'\371\200\200\200\232' [0x100001b]=$'\371\200\200\200\233' [0x100001c]=$'\371\200\200\200\234' [0x100001d]=$'\371\200\200\200\235' + [0x100001e]=$'\371\200\200\200\236' [0x100001f]=$'\371\200\200\200\237' [0x1000020]=$'\371\200\200\200\240' [0x1000021]=$'\371\200\200\200\241' [0x1000022]=$'\371\200\200\200\242' + [0x1000023]=$'\371\200\200\200\243' [0x1000024]=$'\371\200\200\200\244' [0x1000025]=$'\371\200\200\200\245' [0x1000026]=$'\371\200\200\200\246' [0x1000027]=$'\371\200\200\200\247' + [0x1000028]=$'\371\200\200\200\250' [0x1000029]=$'\371\200\200\200\251' [0x100002a]=$'\371\200\200\200\252' [0x100002b]=$'\371\200\200\200\253' [0x100002c]=$'\371\200\200\200\254' + [0x100002d]=$'\371\200\200\200\255' [0x100002e]=$'\371\200\200\200\256' [0x100002f]=$'\371\200\200\200\257' [0x1000030]=$'\371\200\200\200\260' [0x1000031]=$'\371\200\200\200\261' + [0x1000032]=$'\371\200\200\200\262' [0x1000033]=$'\371\200\200\200\263' [0x1000034]=$'\371\200\200\200\264' [0x1000035]=$'\371\200\200\200\265' [0x1000036]=$'\371\200\200\200\266' + [0x1000037]=$'\371\200\200\200\267' [0x1000038]=$'\371\200\200\200\270' [0x1000039]=$'\371\200\200\200\271' [0x100003a]=$'\371\200\200\200\272' [0x100003b]=$'\371\200\200\200\273' + [0x100003c]=$'\371\200\200\200\274' [0x100003d]=$'\371\200\200\200\275' [0x100003e]=$'\371\200\200\200\276' [0x100003f]=$'\371\200\200\200\277' [0x1000040]=$'\371\200\200\201\200' + [0x1000041]=$'\371\200\200\201\201' [0x1000042]=$'\371\200\200\201\202' [0x1000043]=$'\371\200\200\201\203' [0x1000044]=$'\371\200\200\201\204' [0x1000045]=$'\371\200\200\201\205' + [0x1000046]=$'\371\200\200\201\206' [0x1000047]=$'\371\200\200\201\207' [0x1000048]=$'\371\200\200\201\210' [0x1000049]=$'\371\200\200\201\211' [0x100004a]=$'\371\200\200\201\212' + [0x100004b]=$'\371\200\200\201\213' [0x100004c]=$'\371\200\200\201\214' [0x100004d]=$'\371\200\200\201\215' [0x100004e]=$'\371\200\200\201\216' [0x100004f]=$'\371\200\200\201\217' + + [0x70000000]=$'\375\260\200\200\200\200' [0x70000001]=$'\375\260\200\200\200\201' [0x70000002]=$'\375\260\200\200\200\202' [0x70000003]=$'\375\260\200\200\200\203' + [0x70000004]=$'\375\260\200\200\200\204' [0x70000005]=$'\375\260\200\200\200\205' [0x70000006]=$'\375\260\200\200\200\206' [0x70000007]=$'\375\260\200\200\200\207' [0x70000008]=$'\375\260\200\200\200\210' + [0x70000009]=$'\375\260\200\200\200\211' [0x7000000a]=$'\375\260\200\200\200\212' [0x7000000b]=$'\375\260\200\200\200\213' [0x7000000c]=$'\375\260\200\200\200\214' [0x7000000d]=$'\375\260\200\200\200\215' + [0x7000000e]=$'\375\260\200\200\200\216' [0x7000000f]=$'\375\260\200\200\200\217' [0x70000010]=$'\375\260\200\200\200\220' [0x70000011]=$'\375\260\200\200\200\221' [0x70000012]=$'\375\260\200\200\200\222' + [0x70000013]=$'\375\260\200\200\200\223' [0x70000014]=$'\375\260\200\200\200\224' [0x70000015]=$'\375\260\200\200\200\225' [0x70000016]=$'\375\260\200\200\200\226' [0x70000017]=$'\375\260\200\200\200\227' + [0x70000018]=$'\375\260\200\200\200\230' [0x70000019]=$'\375\260\200\200\200\231' [0x7000001a]=$'\375\260\200\200\200\232' [0x7000001b]=$'\375\260\200\200\200\233' [0x7000001c]=$'\375\260\200\200\200\234' + [0x7000001d]=$'\375\260\200\200\200\235' [0x7000001e]=$'\375\260\200\200\200\236' [0x7000001f]=$'\375\260\200\200\200\237' [0x70000020]=$'\375\260\200\200\200\240' [0x70000021]=$'\375\260\200\200\200\241' + [0x70000022]=$'\375\260\200\200\200\242' [0x70000023]=$'\375\260\200\200\200\243' [0x70000024]=$'\375\260\200\200\200\244' [0x70000025]=$'\375\260\200\200\200\245' [0x70000026]=$'\375\260\200\200\200\246' + [0x70000027]=$'\375\260\200\200\200\247' [0x70000028]=$'\375\260\200\200\200\250' [0x70000029]=$'\375\260\200\200\200\251' [0x7000002a]=$'\375\260\200\200\200\252' [0x7000002b]=$'\375\260\200\200\200\253' + [0x7000002c]=$'\375\260\200\200\200\254' [0x7000002d]=$'\375\260\200\200\200\255' [0x7000002e]=$'\375\260\200\200\200\256' [0x7000002f]=$'\375\260\200\200\200\257' [0x70000030]=$'\375\260\200\200\200\260' + [0x70000031]=$'\375\260\200\200\200\261' [0x70000032]=$'\375\260\200\200\200\262' [0x70000033]=$'\375\260\200\200\200\263' [0x70000034]=$'\375\260\200\200\200\264' [0x70000035]=$'\375\260\200\200\200\265' + [0x70000036]=$'\375\260\200\200\200\266' [0x70000037]=$'\375\260\200\200\200\267' [0x70000038]=$'\375\260\200\200\200\270' [0x70000039]=$'\375\260\200\200\200\271' [0x7000003a]=$'\375\260\200\200\200\272' + [0x7000003b]=$'\375\260\200\200\200\273' [0x7000003c]=$'\375\260\200\200\200\274' [0x7000003d]=$'\375\260\200\200\200\275' [0x7000003e]=$'\375\260\200\200\200\276' [0x7000003f]=$'\375\260\200\200\200\277' + [0x70000040]=$'\375\260\200\200\201\200' [0x70000041]=$'\375\260\200\200\201\201' [0x70000042]=$'\375\260\200\200\201\202' [0x70000043]=$'\375\260\200\200\201\203' [0x70000044]=$'\375\260\200\200\201\204' + [0x70000045]=$'\375\260\200\200\201\205' [0x70000046]=$'\375\260\200\200\201\206' [0x70000047]=$'\375\260\200\200\201\207' [0x70000048]=$'\375\260\200\200\201\210' [0x70000049]=$'\375\260\200\200\201\211' + [0x7000004a]=$'\375\260\200\200\201\212' [0x7000004b]=$'\375\260\200\200\201\213' [0x7000004c]=$'\375\260\200\200\201\214' [0x7000004d]=$'\375\260\200\200\201\215' [0x7000004e]=$'\375\260\200\200\201\216' + + + + ) +TestCodePage en_US.UTF-8 C_UTF_8 + +if [ ${ErrorCnt} -gt 0 ]; then + echo "Failed ${ErrorCnt} of ${TestCnt} Unicode tests" +else + echo "Passed all ${TestCnt} Unicode tests" +fi diff --git a/tests/unicode2.sub b/tests/unicode2.sub new file mode 100644 index 0000000..83ff274 --- /dev/null +++ b/tests/unicode2.sub @@ -0,0 +1,24 @@ +. ./test-glue-functions + +export LANG=en_US.UTF-8 + +printf '%s\n' "$(printf '\uff')" | od -b | _intl_normalize_spaces +printf '%s\n' $'\uff' | od -b | _intl_normalize_spaces + +printf '\uff'\\n | od -b | _intl_normalize_spaces +echo $'\uff' | od -b | _intl_normalize_spaces + +printf '\uffff'\\n | od -b | _intl_normalize_spaces +echo $'\uffff' | od -b | _intl_normalize_spaces + +printf '\Ufffffffe'\\n | od -b | _intl_normalize_spaces +echo $'\Ufffffffe' | od -b | _intl_normalize_spaces + +printf '\Uffffffff'\\n | od -b | _intl_normalize_spaces +echo $'\Uffffffff' | od -b | _intl_normalize_spaces + +LC_CTYPE=C printf '\uff'\\n | od -b | _intl_normalize_spaces +LC_CTYPE=ru_RU.CP1251 printf '\uff'\\n | od -b | _intl_normalize_spaces +LC_CTYPE=en_US.UTF-8 printf '\uff'\\n | od -b | _intl_normalize_spaces + +echo -e '\u0041 \u00a3 \u0152' | od -b | _intl_normalize_spaces diff --git a/tests/unicode3.sub b/tests/unicode3.sub new file mode 100644 index 0000000..cb1b873 --- /dev/null +++ b/tests/unicode3.sub @@ -0,0 +1,12 @@ +export LANG=en_US.UTF-8 # make sure + +cd $TMPDIR # try to avoid NFS artifacts +payload=$'\065\247\100\063\231\053\306\123\070\237\242\352\263' +"$payload" + +cd "$payload" +printf %q "$payload" +echo + +set -x ; : "$payload" ; set +x +cd $OLDPWD diff --git a/tests/varenv.right b/tests/varenv.right new file mode 100644 index 0000000..159a877 --- /dev/null +++ b/tests/varenv.right @@ -0,0 +1,212 @@ +3 4 +5 6 7 8 9 +7 8 9 +/usr/chet +/usr/chet +/usr/chet +/a/b/c +/usr/chet +/usr/chet 7 +/a/b/c 9 /a/b/c +/a/b/c 9 /a/b/c +/a/b/c /a/b/c +1 2 +1 1 +unset +toronto airport +AVAR +song by rush +BVAR +toronto airport +AVAR +AVAR +42 +/bin:/usr/bin:/usr/local/bin:. +avar=([0]="/bin:/usr/bin:/usr/local/bin:.") +z=yy +42 +declare -i ivar="10" +unset +declare -x ivar="42" +hB +braceexpand:hashall:interactive-comments +hBP +braceexpand:hashall:interactive-comments:physical +declare -r SHELLOPTS="braceexpand:hashall:interactive-comments:physical" +abcde +20 +30 +40 +50 +|0|10| +10 +|0|10| +10 +|0|10| +10 +|4| +4 +|0|11| +after fff3: x=4 +|0|12| +|y| +|y| +a:b:c:d +a-b-c-d +a:b:c:d +g: , +f: , +FIN: asdf fdsa, asdf fdsa +g: v = , w = +f: v = , w = +FIN: v = two, w = one +./varenv4.sub: line 54: bbb: unique: cannot convert indexed to associative array +after bbb: 1 +declare -Ar FOOBAR=([foo]="bar" ) +declare -Ar FOOBAR=([foo]="bar" ) +declare -ar FOOBAR2=([0]="bar") +declare -ar FOOBAR2=([0]="bar") +F OUTSIDE +F OUTSIDE +declare -ar outside=() +declare -ir outside1="1" +tempenv = foo +0 +declare -ar myvar=([0]="0") +1 +declare -ir myvar="1" +declare -rx tempvar1='foo' +declare -rx tempvar2='qux' +./varenv7.sub: line 44: local: var: readonly variable +inside: outside +outside: outside +local: unset1 unset2 +abc +abc +:1 +:2 +after: ---- +global:1 +global:2 +after: --global-- +after: ---- +x = :1:2 +in o1 (readonly modifying local scalars): +declare -r i1="a b c" +declare -r j1="1 2 3" +after o1: +./varenv9.sub: line 15: declare: i1: not found +./varenv9.sub: line 15: declare: j1: not found +in o2 (readonly setting global scalars): +declare -r i2="a b c" +declare -r j2="1 2 3" +after o2: +declare -r i2="a b c" +declare -r j2="1 2 3" +./varenv9.sub: line 33: unset: i2: cannot unset: readonly variable +./varenv9.sub: line 33: unset: j2: cannot unset: readonly variable +in o3 (readonly modifying locals, converting to arrays): +declare -ar i3=([0]="a" [1]="b" [2]="c") +declare -ar j3=([0]="1" [1]="2" [2]="3") +after o3: +./varenv9.sub: line 48: declare: i3: not found +./varenv9.sub: line 48: declare: j3: not found +in o4 (readonly setting global array variables): +declare -ar i4=([0]="a" [1]="b" [2]="c") +declare -ar j4=([0]="1" [1]="2" [2]="3") +after o4: +declare -ar i4=([0]="a" [1]="b" [2]="c") +declare -ar j4=([0]="1" [1]="2" [2]="3") +./varenv9.sub: line 66: unset: i4: cannot unset: readonly variable +./varenv9.sub: line 66: unset: j4: cannot unset: readonly variable +main: unset +inner: res unset +outer: res: X Y +main: after first call: X +inner: X +outer: res: X Y +main: after second call: X +func: null or unset +after func: x = outside +./varenv11.sub: line 4: local: qux: readonly variable +./varenv11.sub: line 5: qux: readonly variable +declare -A foo=([zero]="zero" [one]="one" ) +declare -a bar=([0]="zero" [1]="one") +declare -A foo=([zero]="zero" [one]="one" ) +declare -a bar=([0]="zero" [1]="one") +./varenv11.sub: line 29: a: readonly variable +foo=abc +func1: var = + +func1: var = + +inside: declare -- foo +outside: +declare -x foo="abc" +inside: declare -x var="value" +outside: declare -- var="one" +inside: declare -x var="value" +outside: declare -x var="value" +inside: declare -- var="local" +outside: declare -x var="global" +foo=<unset> environment foo= +foo=foo environment foo=foo +foo=foo environment foo=foo +./varenv13.sub: line 3: `var[0]': not a valid identifier +./varenv13.sub: line 3: `var[@]': not a valid identifier +./varenv13.sub: line 1: declare: var: not found +./varenv13.sub: line 12: var[@]: bad array subscript +declare -A var=([0]="X" ) +help +./varenv13.sub: line 21: `var[0]': not a valid identifier +1 +./varenv14.sub: line 6: warning: var: cannot inherit value from incompatible type +declare -a var=([0]="X") +./varenv14.sub: line 9: warning: var: cannot inherit value from incompatible type +declare -a var=([0]="Y") +./varenv14.sub: line 10: warning: var: cannot inherit value from incompatible type +declare -a var=([0]="Y") +./varenv14.sub: line 11: warning: var: cannot inherit value from incompatible type +declare -a var=() +./varenv14.sub: line 12: warning: var: cannot inherit value from incompatible type +declare -a var=() +./varenv14.sub: line 18: f: var: cannot convert indexed to associative array +declare -a a=([0]="X") +declare -a s=([0]="X") +declare -a a=([0]="X" [1]="Y") +declare -a s=([0]="X" [1]="Y") +declare -a a=([0]="XY") +declare -a s=([0]="XY") +f: 1 2 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 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 +f1: after: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 +done: 1 2 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 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 +f3:1 +f3:2 +f3:3 +f3:4 +f3:5 +f3:6 +f3:7 +f3:8 +f3:9 +f3:10 +f3:11 +f3:12 +f3:13 +f3:14 +f3:15 +f3:16 +f3:17 +f3:18 +f3:19 +f3:20 +before source: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 +varenv15.in: before set: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 +varenv15.in: after set: 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 +after source 1: 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 +varenv15.in: before set: one two three four five six seven eight nine ten +varenv15.in: after set: 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 +after source 2: 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=z +a=b +a=z diff --git a/tests/varenv.tests b/tests/varenv.tests new file mode 100644 index 0000000..34b8559 --- /dev/null +++ b/tests/varenv.tests @@ -0,0 +1,246 @@ +# +# varenv.sh +# +# Test the behavior of the shell with respect to variable and environment +# assignments +# +expect() +{ + echo expect "$@" +} + +a=1 +b=2 +c=3 +d=4 +e=5 +f=6 g=7 h=8 + +a=3 b=4 $CHMOD $MODE $FN + +# This should echo "3 4" according to Posix.2 +expect "3 4" +echo $a $b + +set -k + +# Assignment statements made when no words are left affect the shell's +# environment +a=5 b=6 $CHMOD c=7 $MODE d=8 $FN e=9 + +expect "5 6 7 8 9" +echo $a $b $c $d $e + +$CHMOD f=7 $MODE g=8 $FN h=9 +expect "7 8 9" +echo $f $g $h + +set +k + +# The temporary environment does not affect variable expansion, only the +# environment given to the command + +export HOME=/usr/chet +expect $HOME +echo $HOME + +expect $HOME +HOME=/a/b/c /bin/echo $HOME + +expect $HOME +echo $HOME + +# This should echo /a/b/c +expect /a/b/c +HOME=/a/b/c printenv HOME + +set -k + +# This should echo $HOME 9, NOT /a/b/c 9 + +expect "$HOME" +HOME=/a/b/c /bin/echo $HOME c=9 +expect "$HOME 7" +echo $HOME $c + +# I claim the next two echo calls should give identical output. +# ksh agrees, the System V.3 sh does not + +expect "/a/b/c 9 /a/b/c" +HOME=/a/b/c $ECHO a=$HOME c=9 +echo $HOME $c $a + +expect "/a/b/c 9 /a/b/c" +HOME=/a/b/c a=$HOME c=9 +echo $HOME $c $a +set +k + +# How do assignment statements affect subsequent assignments on the same +# line? +expect "/a/b/c /a/b/c" +HOME=/a/b/c a=$HOME +echo $HOME $a + +# The system V.3 sh does this wrong; the last echo should output "1 1", +# but the system V.3 sh has it output "2 2". Posix.2 says the assignment +# statements are processed left-to-right. bash and ksh output the right +# thing +c=1 +d=2 +expect "1 2" +echo $c $d +d=$c c=$d +expect "1 1" +echo $c $d + +# just for completeness +unset d c +expect unset +echo ${d-unset} + +# no output +export a +a=bcde +export a +/bin/true 2>/dev/null + +func() +{ + local YYZ + + YYZ="song by rush" + echo $YYZ + echo $A +} + +YYZ="toronto airport" +A="AVAR" +echo $YYZ +echo $A +A=BVAR func +echo $YYZ +echo $A + +export A +# Make sure expansion doesn't use assignment statements preceding a builtin +A=ZVAR echo $A + +XPATH=/bin:/usr/bin:/usr/local/bin:. +func2() +{ + local z=yy + local -a avar=( ${XPATH//: } ) + echo ${avar[@]} + local +} + +avar=42 +echo $avar +func2 +echo $avar + +# try to set an attribute for an unset variable; make sure it persists +# when the variable is assigned a value +declare -i ivar + +ivar=10 + +declare -p ivar +unset ivar + +# export an unset variable, make sure it is not suddenly set, but make +# sure the export attribute persists when the variable is assigned a +# value +export ivar +echo ${ivar-unset} + +ivar=42 +declare -p ivar + +# make sure set [-+]o ignoreeof and $IGNOREEOF are reflected +unset IGNOREEOF +set +o ignoreeof +set -o ignoreeof +if [ "$IGNOREEOF" -ne 10 ]; then + echo "./varenv.sh: set -o ignoreeof is not reflected in IGNOREEOF" >&2 +fi +unset IGNOREEOF +set +o ignoreeof + +# older versions of bash used to not reset RANDOM in subshells correctly +[[ $RANDOM -eq $(echo $RANDOM) ]] && echo "RANDOM: problem with subshells" + +# make sure that shopt -o is reflected in $SHELLOPTS +# first, get rid of things that might be set automatically via shell +# variables +set +o posix +set +o ignoreeof +set +o monitor +echo $- +echo ${SHELLOPTS} +shopt -so physical +echo $- +echo ${SHELLOPTS} + +# and make sure it is readonly +readonly -p | grep SHELLOPTS + +# This was an error in bash versions prior to bash-2.04. The `set -a' +# should cause the assignment statement that's an argument to typeset +# to create an exported variable +unset FOOFOO +FOOFOO=bar +set -a +typeset FOOFOO=abcde + +printenv FOOFOO + +# test out export behavior of variable assignments preceding builtins and +# functions +$THIS_SH ./varenv1.sub + +# more tests; bugs in bash up to version 2.05a +$THIS_SH ./varenv2.sub + +# more tests; bugs in bash IFS scoping up through version 4.2 +$THIS_SH ./varenv3.sub + +# scoping problems with declare -g through bash-4.2 +${THIS_SH} ./varenv4.sub + +# more scoping and declaration problems with -g and arrays through bash-4.2 +${THIS_SH} ./varenv5.sub + +# variable scoping in the presence of nameref +${THIS_SH} ./varenv6.sub + +# variable declaration problems with arrays and readonly local variables +${THIS_SH} ./varenv7.sub + +# variable visibility problems with process substitution subshells in +# redirections +${THIS_SH} ./varenv8.sub + +# make sure that builtins like readonly and export modify local array variables +# if executed in shell functions, like they modify local scalar variables +${THIS_SH} ./varenv9.sub + +# more tests of unset and local variables with dynamic scoping +${THIS_SH} ./varenv10.sub + +# tests of compound assignments in function scope +${THIS_SH} ./varenv11.sub + +# temporary environment variable propagation and scoping in posix mode +${THIS_SH} ./varenv12.sub + +# temporary environment and invalid shell indentifier names +${THIS_SH} ./varenv13.sub + +# localvar_inherit +${THIS_SH} ./varenv14.sub + +${THIS_SH} ./varenv15.sub + +# make sure variable scoping is done right +tt() { typeset a=b;echo a=$a; };a=z;echo a=$a;tt;echo a=$a diff --git a/tests/varenv1.sub b/tests/varenv1.sub new file mode 100644 index 0000000..168f87b --- /dev/null +++ b/tests/varenv1.sub @@ -0,0 +1,28 @@ +# test out the export behavior of variable assignments preceding `eval', `.' +# and shell functions + +func() +{ + printenv var +} + +export var=10 +echo expect 20 +var=20 eval printenv var + +: ${TMPDIR:=/tmp} +TMPFILE=$TMPDIR/evalsub.$$ + +rm -f $TMPFILE +echo 'printenv var' > $TMPFILE + +echo expect 30 +var=30 . $TMPFILE + +rm -f $TMPFILE + +echo expect 40 +var=40 func + +echo expect 50 +var=50 command printenv var diff --git a/tests/varenv10.sub b/tests/varenv10.sub new file mode 100644 index 0000000..887cfd2 --- /dev/null +++ b/tests/varenv10.sub @@ -0,0 +1,47 @@ +#!/bin/bash +# +# various tests of unset when applied to variables at different local scopes + +# function unsetting variable at previous local scope, uncovering global + +inner() +{ + unset res + echo ${FUNCNAME}: ${res-res unset} + if [[ $1 == "set" ]]; then + res[0]="X" + res[1]="Y" + fi +} + +outer() +{ + local res= + inner "$1" + echo ${FUNCNAME}: "res: ${res[@]}" +} + +echo main: ${res-unset} +outer set +echo main: after first call: ${res-unset} +outer dontset +echo main: after second call: ${res-unset} + +unset -f outer inner +unset res + +# local scope, unset variable at the same scope as local declaration +func() +{ + typeset x=4 + + unset x + echo ${FUNCNAME}: ${x:-null or unset} +} + +x=outside +func +echo after func: x = $x + +unset -f func +unset x diff --git a/tests/varenv11.sub b/tests/varenv11.sub new file mode 100644 index 0000000..d438498 --- /dev/null +++ b/tests/varenv11.sub @@ -0,0 +1,30 @@ +# couple of errors here +func() +{ + local qux=7 + local qux=(one two) + local what=(zero one two) +} + +readonly qux=42 +func + +func2() +{ + declare -gA foo=([zero]=zero [one]=one) + declare -ga bar=(zero one) +} + +foo=help +bar=me + +func2 + +declare -p foo bar +unset foo bar +func2 +declare -p foo bar + +readonly a=7 +a=(1 2 3) + diff --git a/tests/varenv12.sub b/tests/varenv12.sub new file mode 100644 index 0000000..edba3c9 --- /dev/null +++ b/tests/varenv12.sub @@ -0,0 +1,100 @@ +set -o posix + +fn() { foo=abc : ; typeset +x foo; printenv|grep ^foo=; } + +fn +unset -v foo +unset -f fn + +func1() { + var=1 + var=2 : # or 'var=2 return', or another special builtin + unset -v var + echo $FUNCNAME: var = $var +} +func2() { + func1 + unset -v var # bug: fails silently +} +func1 +echo ${var+"BUG: still set 1"} + +unset var +func2 +echo ${var+"BUG: still set 2"} + +unset -v var +unset -f func1 func2 + +fn() { foo=abc : ; typeset +x foo; echo -n 'inside: ' ; declare -p foo; } +fn +echo outside: +declare -p foo + +unset -v foo +unset -f fn + +func() +{ + var=value declare -x var + echo -n 'inside: ' ; declare -p var +} + +var=one +func +echo -n 'outside: ' ; declare -p var + +unset -v var +unset -f func + +# this will probably change behavior; export shouldn't behave like this when +# not in posix mode and the sequencing is probably wrong in posix mode. since +# export is a special builtin, the variable assignment should modify the +# global variable, leaving the local variable unchanged. all shells, including +# bash, modify the local variable; bash is the only one that propagates the +# value out to the calling environment. bash does that only when in posix +# mode. + +func() +{ + local var=inside + var=value export var + echo -n 'inside: ' ; declare -p var +} + +var=outside +func +echo -n 'outside: ' ; declare -p var + +unset -v var +unset -f func + +func() +{ + local var=local + var=global : + echo -n 'inside: ' ; declare -p var +} + +var=outside +func +echo -n 'outside: ' ; declare -p var + +unset -v var +unset -f func + +# test whether or not temporary environment assignments are exported +# in posix mode +showfoo() +{ + printf %s "foo=${foo-<unset>}" + echo -n ' environment foo=' + printenv foo || echo +} +unset foo +showfoo +foo=foo showfoo +showfoo + +unset -v foo +unset -f showfoo diff --git a/tests/varenv13.sub b/tests/varenv13.sub new file mode 100644 index 0000000..0e6a42c --- /dev/null +++ b/tests/varenv13.sub @@ -0,0 +1,23 @@ +f() { declare -p ${!var*} | grep ^var; declare -p var ; } + +var[0]=X var[@]=Y f + +unset -f f +unset -v var + +typeset -A var + +f() { declare -p ${!var*}; } + +var[0]=X var[@]=Y +f + +: ${THIS_SH:=./bash} +env 'v[0]=help' ${THIS_SH} -c 'printenv "v[0]"' + +unset -v var + +f() { test -v 'var[0]'; echo $?; } +var[0]=X f + +unset -v var diff --git a/tests/varenv14.sub b/tests/varenv14.sub new file mode 100644 index 0000000..52b20d8 --- /dev/null +++ b/tests/varenv14.sub @@ -0,0 +1,33 @@ +# testing framework for local variable inheritence + +shopt -s localvar_inherit +declare -A var + +f() { declare var+=([0]=X); declare -p var; } +f + +f() { declare var=([Y]=Y); declare -p var; }; f +f() { declare var+=([Y]=Y); declare -p var; }; f +f() { declare var+=(); declare -p var; }; f +f() { declare var=(); declare -p var; }; f + +unset -f f +unset -v var + +declare -a var=( [0]=12 ) +f() { declare -A var+=([0]=X); declare -p var; } +f + +unset -f f +unset a s + +a=(X) s=X + +f() { local -a a s; declare -p a s; } +f + +f() { local a+=(Y) s+=(Y); declare -p a s; } +f + +f() { local -a a+=Y s+=Y; declare -p a s; } +f diff --git a/tests/varenv15.in b/tests/varenv15.in new file mode 100644 index 0000000..e635b12 --- /dev/null +++ b/tests/varenv15.in @@ -0,0 +1,3 @@ +echo varenv15.in: before set: "$@" +set -- 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 +echo varenv15.in: after set: "$@" diff --git a/tests/varenv15.sub b/tests/varenv15.sub new file mode 100644 index 0000000..52c8a94 --- /dev/null +++ b/tests/varenv15.sub @@ -0,0 +1,38 @@ +# check saving and restoring positional parameters around function calls + +f() +{ + echo $FUNCNAME: "$@" +} + +f1() +{ + f {1..50} + echo $FUNCNAME: after: $@ +} + +set -- {1..100} + +f1 {1..20} +echo done: $@ + +f3() +{ + echo $FUNCNAME:$1 + shift + if [ $# -le 0 ]; then + return + fi + f3 "$@" +} + +f3 {1..20} + +# now let's try source with and without positional parameters + +set -- {1..20} +echo before source: "$@" +. ./varenv15.in +echo after source 1: "$@" +. ./varenv15.in one two three four five six seven eight nine ten +echo after source 2: "$@" diff --git a/tests/varenv2.sub b/tests/varenv2.sub new file mode 100644 index 0000000..b293572 --- /dev/null +++ b/tests/varenv2.sub @@ -0,0 +1,44 @@ +fff() +{ + typeset i=0 x=10 + echo "|$i|$x|" + export x + printenv x +} + +fff2() +{ + echo "|$x|" + export x + printenv x +} + +fff3() +{ + typeset i=0 x="${x-10}" + echo "|$i|$x|" +} + +fff4() +{ + typeset i=0 x + x="${x-10}" + echo "|$i|$x|" +} + +fff5() +{ + z=y typeset z + echo "|$z|" +} + +fff +x=10 fff +x=1 fff +x=4 fff2 +x=11 fff3 +echo after fff3: x=$x +x=12 fff4 + +fff5 +z=42 fff5 diff --git a/tests/varenv3.sub b/tests/varenv3.sub new file mode 100644 index 0000000..1384fcb --- /dev/null +++ b/tests/varenv3.sub @@ -0,0 +1,32 @@ +#!/bin/bash + +oifs=$IFS + +inner () { +#recho inner: "$IFS" >&2 + echo a/b/c/d + exit 0 +} + +outer() { +#recho outer: "$IFS" >&2 +for i in 1; do + IFS=/ read m v k a < <(IFS=$oifs inner) + +echo $m:$v:$k:$a +done +} + +outer +unset m k v a b c d + +for j in 1; do + IFS=: read a b c d +done < <(outer) + +echo $a-$b-$c-$d +unset m k v a b c d + +IFS=: read a b c d < <(outer) + +echo $a:$b:$c:$d diff --git a/tests/varenv4.sub b/tests/varenv4.sub new file mode 100644 index 0000000..b2df61c --- /dev/null +++ b/tests/varenv4.sub @@ -0,0 +1,58 @@ +f() +{ + local -a v + local -a w + + g + echo "f: ${v[@]}, ${w[@]}" +} + +g() +{ + aux=v + declare -ga "$aux=( asdf fdsa )" + declare -ga w=( asdf fdsa ) + + echo "g: ${v[@]}, ${w[@]}" +} + +f +echo "FIN: ${v[@]}, ${w[@]}" + +unset v w +unset -f f g + +f() +{ + local v + local w + + g + echo f: v = $v, w = $w +} + +g() +{ + aux=v + declare -g w=one + declare -g "$aux=two" + + echo g: v = $v, w = $w +} + +f +echo FIN: v = $v, w = $w + +# problem with error return propagation through bash-4.3 +unset -f aaa bbb +unset unique + +aaa() { + declare -g -a unique=() +} +bbb() { + declare -g -A unique=() +} +aaa +bbb +echo after bbb: $? diff --git a/tests/varenv5.sub b/tests/varenv5.sub new file mode 100644 index 0000000..8ebfa36 --- /dev/null +++ b/tests/varenv5.sub @@ -0,0 +1,16 @@ +function foobar { + declare -rgA FOOBAR=([foo]=bar) + declare -p FOOBAR +} +foobar +declare -p FOOBAR + +unset -f foobar + +foobar() { + declare -rga FOOBAR2=([foo]=bar) + declare -p FOOBAR2 +} + +foobar +declare -p FOOBAR2 diff --git a/tests/varenv6.sub b/tests/varenv6.sub new file mode 100644 index 0000000..d0269fb --- /dev/null +++ b/tests/varenv6.sub @@ -0,0 +1,28 @@ +f() +{ + local str=F + g str +} + +g() +{ + local -n ref=$1 + printf "%s " "$ref" + ref=G +} + +str=OUTSIDE; +f + +printf "%s\n" "$str" + +unset -f f g +unset str + +f() { local -a arr=(F); g arr; }; + +g() { local -n ref=$1; printf "%s " "${ref[0]}"; ref=(G); }; + +arr=(OUTSIDE); +f; +printf "%s\n" "${arr[0]}" diff --git a/tests/varenv7.sub b/tests/varenv7.sub new file mode 100644 index 0000000..45654da --- /dev/null +++ b/tests/varenv7.sub @@ -0,0 +1,62 @@ +foo() +{ + local -a myvar=() + local -r myvar=0 + + echo "${myvar[@]}" + declare -p myvar +} + +foo2() +{ + local -i myvar=0 + local -r myvar=1 + + echo "${myvar}" + declare -p myvar +} + +declare -a outside=() +declare -r outside +declare -p outside + +outside1=1 +declare -ir outside1 +declare -p outside1 + +tempenv=foo declare -r tempenv +echo tempenv = $tempenv + +foo +foo2 + +tempvar1=foo declare -r tempvar1 +echo ${tempvar1@A} + +tempvar2=bar declare -r tempvar2=qux +echo ${tempvar2@A} + +unset foo +readonly var=outside + +func() +{ + local var=inside + echo "inside: $var" +} + +func +echo outside: $var + +unset -f f +unset VAR1 VAR2 +export VAR1=abc VAR2=abc + +f() +{ + local VAR1; local VAR2 + echo local: ${VAR1-unset1} ${VAR2-unset2} + printenv VAR1 ; printenv VAR2 +} + +f diff --git a/tests/varenv8.sub b/tests/varenv8.sub new file mode 100644 index 0000000..cad2c6e --- /dev/null +++ b/tests/varenv8.sub @@ -0,0 +1,14 @@ +FOO=bar cat < <(echo $FOO:1; echo $FOO:2) +echo after: --${FOO}-- + +unset FOO +FOO=global + +FOO=bar cat < <(echo $FOO:1; echo $FOO:2) +echo after: --${FOO}-- + +unset FOO +FOO=bar read x < <(echo -n $FOO:1; echo $FOO:2) +echo after: --${FOO}-- +echo x = $x + diff --git a/tests/varenv9.sub b/tests/varenv9.sub new file mode 100644 index 0000000..eda1be3 --- /dev/null +++ b/tests/varenv9.sub @@ -0,0 +1,66 @@ +# case 1: readonly modifying local scalar variables +o1() { + local i1 j1 + readonly i1=$1 + readonly j1="1 2 3" + + echo "in o1 (readonly modifying local scalars):" + declare -p i1 + declare -p j1 +} + +o1 "a b c" + +echo after o1: +declare -p i1 j1 + +unset i1 j1 + +# case 2: readonly setting global scalar variables +o2() { + readonly i2=$1 + readonly j2="1 2 3" + + echo "in o2 (readonly setting global scalars):" + declare -p i2 + declare -p j2 +} + +o2 "a b c" +echo after o2: +declare -p i2 j2 + +unset i2 j2 + +# case 3: readonly modifying local variables, converting to arrays +o3() { + local i3 j3 + readonly i3=($1) + readonly j3=(1 2 3) + + echo "in o3 (readonly modifying locals, converting to arrays):" + declare -p i3 + declare -p j3 +} + +o3 "a b c" +echo after o3: +declare -p i3 j3 + +unset i3 j3 + +# case 4: readonly setting global array variables +o4() { + readonly i4=($1) + readonly j4=(1 2 3) + + echo "in o4 (readonly setting global array variables):" + declare -p i4 + declare -p j4 +} + +o4 "a b c" +echo after o4: +declare -p i4 j4 + +unset i4 j4 diff --git a/tests/version b/tests/version new file mode 100644 index 0000000..9ad08f7 --- /dev/null +++ b/tests/version @@ -0,0 +1,13 @@ +if (( $UID == 0 )); then + echo "${THIS_SH}: the test suite should not be run as root" >&2 + echo +fi + +echo Testing ${THIS_SH} + +echo version: $BASH_VERSION +echo versinfo: ${BASH_VERSINFO[@]} + +echo HOSTTYPE = $HOSTTYPE +echo OSTYPE = $OSTYPE +echo MACHTYPE = $MACHTYPE diff --git a/tests/version.mini b/tests/version.mini new file mode 100644 index 0000000..637565e --- /dev/null +++ b/tests/version.mini @@ -0,0 +1,13 @@ +if (( $UID == 0 )); then + echo "${THIS_SH}: the test suite should not be run as root" >&2 + echo +fi + +echo Testing ${THIS_SH} + +echo version: $BASH_VERSION +#echo versinfo: ${BASH_VERSINFO[@]} + +echo HOSTTYPE = $HOSTTYPE +echo OSTYPE = $OSTYPE +echo MACHTYPE = $MACHTYPE diff --git a/tests/vredir.right b/tests/vredir.right new file mode 100644 index 0000000..f4fe0db --- /dev/null +++ b/tests/vredir.right @@ -0,0 +1,100 @@ +10 +foo 1 +foo 2 +foo 3 +bar is a function +bar () +{ + exec {v}> $TMPFILE; + echo $v +} +./vredir.tests: line 6: v: readonly variable +./vredir.tests: line 6: v: cannot assign fd to variable +42 +bar is a function +bar () +{ + exec {v}> $TMPFILE; + echo $v +} +10 +line 1 +line 2 +line 3 +bar is a function +bar () +{ + exec {v}<<EOF +line 1 +line 2 +line 3 +EOF + + echo $v +} +10 +foo 1 +foo 2 +foo 3 +10 +/bin/bash +/bin/csh +/bin/ksh +/bin/sh +/bin/tcsh +/bin/zsh +oclosev is a function +oclosev () +{ + exec {v}>&- +} +iclosev is a function +iclosev () +{ + exec {v}>&- +} +/bin/bash +/bin/csh +/bin/ksh +/bin/sh +/bin/tcsh +/bin/zsh +./vredir3.sub: line 4: v: ambiguous redirect +after +10 11 +a +a +swizzle is a function +swizzle () +{ + fd0=0; + fd1=1; + exec {stdin}<&$fd0; + exec {stdout}>&$fd1 +} +12 10 +a +a +swizzle is a function +swizzle () +{ + exec {fd0}<&0; + exec {fd1}>&1; + exec {stdin}<&$fd0-; + exec {stdout}>&$fd1- +} +ok 1 +./vredir6.sub: redirection error: cannot duplicate fd: Invalid argument +./vredir6.sub: line 13: /dev/null: Invalid argument +unset +12 10 +a +a +swizzle is a function +swizzle () +{ + exec {fd[0]}<&0; + exec {fd[1]}>&1; + exec {stdin}<&${fd[0]}-; + exec {stdout}>&${fd[1]}- +} diff --git a/tests/vredir.tests b/tests/vredir.tests new file mode 100644 index 0000000..ce77deb --- /dev/null +++ b/tests/vredir.tests @@ -0,0 +1,48 @@ +: ${TMPDIR:=/var/tmp} +TMPFILE=$TMPDIR/foo + +bar() +{ +exec {v}>$TMPFILE +echo $v +} + +bar + +echo foo 1 >&$v +echo foo 2 >&$v +echo foo 3 >&$v + +cat $TMPFILE +rm -f $TMPFILE + +type bar +exec {v}>&- + +readonly v=42 +bar + +echo foo 1 2>&1 >&$v | { grep -q '\$v: Bad' || echo 'bad foo 1'; } +echo foo 2 2>&1 >&$v | { grep -q '\$v: Bad' || echo 'bad foo 2'; } +echo foo 3 2>&1 >&$v | { grep -q '\$v: Bad' || echo 'bad foo 3'; } + +cat $TMPFILE +rm -f $TMPFILE + +type bar + +${THIS_SH} ./vredir1.sub + +${THIS_SH} ./vredir2.sub + +${THIS_SH} ./vredir3.sub + +${THIS_SH} ./vredir4.sub + +${THIS_SH} ./vredir5.sub + +${THIS_SH} ./vredir6.sub + +${THIS_SH} ./vredir7.sub + +exit 0 diff --git a/tests/vredir1.sub b/tests/vredir1.sub new file mode 100644 index 0000000..403734c --- /dev/null +++ b/tests/vredir1.sub @@ -0,0 +1,17 @@ +bar() +{ +exec {v}<<EOF +line 1 +line 2 +line 3 +EOF +echo $v +} + +bar + +cat <&$v + +type bar + +exit 0 diff --git a/tests/vredir2.sub b/tests/vredir2.sub new file mode 100644 index 0000000..e1a380d --- /dev/null +++ b/tests/vredir2.sub @@ -0,0 +1,52 @@ +: ${TMPDIR:=/var/tmp} +SHELLSFILE=$TMPDIR/shells-$$ + +cat > $TMPDIR/shells-$$ <<EOF +/bin/bash +/bin/csh +/bin/ksh +/bin/sh +/bin/tcsh +/bin/zsh +EOF + +oclosev() +{ +exec {v}>&- +} + +iclosev() +{ +exec {v}<&- +} + +exec {v}>&1 +echo $v + +echo foo 1 >&$v +echo foo 2 >&$v +echo foo 3 >&$v + +oclosev + +exec {v}<$SHELLSFILE +echo $v + +while read line <&$v +do + echo $line +done + +iclosev + +type oclosev +type iclosev + +while read -r -u ${fd} +do + echo $REPLY +done {fd}<$SHELLSFILE + +rm -f $SHELLSFILE + +exit 0 diff --git a/tests/vredir3.sub b/tests/vredir3.sub new file mode 100644 index 0000000..358ded2 --- /dev/null +++ b/tests/vredir3.sub @@ -0,0 +1,8 @@ +# Right now, the {varname} mechanism does not honor set -u for compatibility +unset v +set -u +exec {v}>&- + +echo after + +exit 0 diff --git a/tests/vredir4.sub b/tests/vredir4.sub new file mode 100644 index 0000000..e1cef05 --- /dev/null +++ b/tests/vredir4.sub @@ -0,0 +1,22 @@ +swizzle() +{ +fd0=0 +fd1=1 + +exec {stdin}<&$fd0 +exec {stdout}>&$fd1 +} + +swizzle +echo $stdin $stdout + +read line <&$stdin <<EOF +a +EOF + +echo $line +echo $line >&$stdout + +type swizzle + +exit 0 diff --git a/tests/vredir5.sub b/tests/vredir5.sub new file mode 100644 index 0000000..d1531e9 --- /dev/null +++ b/tests/vredir5.sub @@ -0,0 +1,23 @@ +swizzle() +{ +exec {fd0}<&0 +exec {fd1}>&1 + +exec {stdin}<&$fd0- +exec {stdout}>&$fd1- +} + +swizzle + +echo $stdin $stdout + +read line <&$stdin <<EOF +a +EOF + +echo $line +echo $line >&$stdout + +type swizzle + +exit 0 diff --git a/tests/vredir6.sub b/tests/vredir6.sub new file mode 100644 index 0000000..224b96a --- /dev/null +++ b/tests/vredir6.sub @@ -0,0 +1,14 @@ +unset v +exec {v}</dev/null + +if (( v >= 10 )); then echo ok 1; else echo bad 1; fi + +exec {v}<&- + +ulimit -n 6 + +exec </dev/null + +unset v +exec {v}</dev/null +echo ${v-unset} diff --git a/tests/vredir7.sub b/tests/vredir7.sub new file mode 100644 index 0000000..8cb80ed --- /dev/null +++ b/tests/vredir7.sub @@ -0,0 +1,23 @@ +swizzle() +{ +exec {fd[0]}<&0 +exec {fd[1]}>&1 + +exec {stdin}<&${fd[0]}- +exec {stdout}>&${fd[1]}- +} + +swizzle + +echo $stdin $stdout + +read line <&$stdin <<EOF +a +EOF + +echo $line +echo $line >&$stdout + +type swizzle + +exit 0 |