diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 15:38:56 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 15:38:56 +0000 |
commit | 6c20c8ed2cb9ab69a1a57ccb2b9b79969a808321 (patch) | |
tree | f63ce19d57fad3ac4a15bc26dbfbfa2b834111b5 /tests | |
parent | Initial commit. (diff) | |
download | bash-6c20c8ed2cb9ab69a1a57ccb2b9b79969a808321.tar.xz bash-6c20c8ed2cb9ab69a1a57ccb2b9b79969a808321.zip |
Adding upstream version 5.2.15.upstream/5.2.15upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'tests')
668 files changed, 45150 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..76f3207 --- /dev/null +++ b/tests/alias.right @@ -0,0 +1,45 @@ +alias: 0 +alias: 0 +./alias.tests: line 38: qfoo: command not found +quux +hi +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 +bar +bad +0 +<|cat> +foo +bar +baz +foo +bar +baz +<áa> +<aá> diff --git a/tests/alias.tests b/tests/alias.tests new file mode 100644 index 0000000..15eac5b --- /dev/null +++ b/tests/alias.tests @@ -0,0 +1,65 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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 + +# post bash-5.1 problems with compound array assignment during multiline +# alias expansion +alias foo='a=() b="" +for i in 1; do echo hi; done' +foo + +unalias foo + +${THIS_SH} ./alias1.sub +${THIS_SH} ./alias2.sub +${THIS_SH} ./alias3.sub +${THIS_SH} ./alias4.sub +${THIS_SH} ./alias5.sub +${THIS_SH} ./alias6.sub diff --git a/tests/alias1.sub b/tests/alias1.sub new file mode 100644 index 0000000..9a90b2e --- /dev/null +++ b/tests/alias1.sub @@ -0,0 +1,33 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..e35fb76 --- /dev/null +++ b/tests/alias2.sub @@ -0,0 +1,35 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..304e926 --- /dev/null +++ b/tests/alias3.sub @@ -0,0 +1,11 @@ +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..0864a3c --- /dev/null +++ b/tests/alias4.sub @@ -0,0 +1,100 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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 + +# alias ending in a tab +alias foo="\ + echo \"bar\" \ + " + +foo + +alias foo=$'echo bad \t' +foo + +# this should probably just echo a blank line to stdout +alias foo='echo 0' +foo>&2 + +alias a='printf "<%s>\n" \' +a|cat diff --git a/tests/alias5.sub b/tests/alias5.sub new file mode 100644 index 0000000..7f8e86d --- /dev/null +++ b/tests/alias5.sub @@ -0,0 +1,28 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# -c commands ending with multi-line aliases; post-bash-5.0 + +: ${THIS_SH:=./bash} + +${THIS_SH} -c "shopt -s expand_aliases &>/dev/null; +alias myalias='/bin/echo foo +echo bar +echo baz' +myalias" + +${THIS_SH} -c "shopt -s expand_aliases &>/dev/null; +alias myalias='echo foo +echo bar +echo baz' +myalias" diff --git a/tests/alias6.sub b/tests/alias6.sub new file mode 100644 index 0000000..d2d7daf --- /dev/null +++ b/tests/alias6.sub @@ -0,0 +1,13 @@ +# make sure aliases that end in multibyte characters don't interfere with the +# space sentinel alias expansion adds; problem through bash-5.1 +shopt -s expand_aliases + +LC_ALL=en_US.UTF-8 + +alias a1='printf "<%s>\\n" áa' +a1 + +alias a2='printf "<%s>\\n" aá' +a2 + +unalias a1 a2 diff --git a/tests/appendop.right b/tests/appendop.right new file mode 100644 index 0000000..f72696b --- /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 97: x: readonly variable +declare -A foo=([two]="baz" [three]="quux" [one]="bar" ) +declare -A foo=([0]="zero" [two]="baz" [three]="quux" [one]="bar" ) +declare -A foo=([four]="four" [0]="zero" [two]="baz" [three]="quux" [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..61b38fc --- /dev/null +++ b/tests/appendop.tests @@ -0,0 +1,100 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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..60e7014 --- /dev/null +++ b/tests/appendop1.sub @@ -0,0 +1,28 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..e497beb --- /dev/null +++ b/tests/appendop2.sub @@ -0,0 +1,31 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..06127be --- /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 1: syntax error: arithmetic expression required +bash: -c: line 1: syntax error: `(( i=0; "i < 3" ))' +2 +bash: -c: line 1: syntax error: `;' unexpected +bash: -c: line 1: 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..db913da --- /dev/null +++ b/tests/arith-for.tests @@ -0,0 +1,128 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..0268781 --- /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 127: 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 162: 3425#56: invalid arithmetic base (error token is "3425#56") +./arith.tests: line 165: 2#: invalid integer constant (error token is "2#") +./arith.tests: line 168: 7 = 43 : attempted assignment to non-variable (error token is "= 43 ") +./arith.tests: line 169: 2#44: value too great for base (error token is "2#44") +./arith.tests: line 170: 44 / 0 : division by 0 (error token is "0 ") +./arith.tests: line 171: let: jv += $iv: syntax error: operand expected (error token is "$iv") +./arith.tests: line 172: jv += $iv : syntax error: operand expected (error token is "$iv ") +./arith.tests: line 173: let: rv = 7 + (43 * 6: missing `)' (error token is "6") +./arith.tests: line 177: 0#4: invalid number (error token is "0#4") +./arith.tests: line 178: 2#110#11: invalid number (error token is "2#110#11") +abc +def +ghi +ok +6 +1 +0 +./arith.tests: line 196: 4 + : syntax error: operand expected (error token is "+ ") +16 +./arith.tests: line 201: 4 ? : 3 + 5 : expression expected (error token is ": 3 + 5 ") +./arith.tests: line 202: 1 ? 20 : `:' expected for conditional expression (error token is "20 ") +./arith.tests: line 203: 4 ? 20 : : expression expected (error token is ": ") +9 +./arith.tests: line 209: 0 && B=42 : attempted assignment to non-variable (error token is "=42 ") +9 +./arith.tests: line 212: 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 260: 7-- : syntax error: operand expected (error token is "- ") +./arith.tests: line 262: --x=7 : attempted assignment to non-variable (error token is "=7 ") +./arith.tests: line 263: ++x=7 : attempted assignment to non-variable (error token is "=7 ") +./arith.tests: line 265: x++=7 : attempted assignment to non-variable (error token is "=7 ") +./arith.tests: line 266: x--=7 : attempted assignment to non-variable (error token is "=7 ") +4 +7 +-7 +7 +7 +2 +2 +./arith1.sub: line 15: 4-- : syntax error: operand expected (error token is "- ") +./arith1.sub: line 16: 4++ : syntax error: operand expected (error token is "+ ") +./arith1.sub: line 17: 4 -- : syntax error: operand expected (error token is "- ") +./arith1.sub: line 18: 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 48: ((: ++ : syntax error: operand expected (error token is "+ ") +7 +7 +./arith1.sub: line 51: ((: -- : 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 46: ((: -- : syntax error: operand expected (error token is "- ") +-7 +-7 +./arith2.sub: line 50: ((: ++ : 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 310: ((: x=9 y=41 : syntax error in expression (error token is "y=41 ") +./arith.tests: line 314: a b: syntax error in expression (error token is "b") +./arith.tests: line 315: ((: a b: syntax error in expression (error token is "b") +42 +42 +42 +42 +42 +42 +./arith.tests: line 330: 'foo' : syntax error: operand expected (error token is "'foo' ") +./arith.tests: line 333: 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..e9ab576 --- /dev/null +++ b/tests/arith.tests @@ -0,0 +1,333 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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 now generates an error +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) )) + +# allow reserved words after an arithmetic command just because +if ((expr)) then ((expr)) fi + +# 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..3168fcb --- /dev/null +++ b/tests/arith1.sub @@ -0,0 +1,51 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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..5475012 --- /dev/null +++ b/tests/arith2.sub @@ -0,0 +1,58 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..b4b1825 --- /dev/null +++ b/tests/arith3.sub @@ -0,0 +1,60 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# this depends on the sequence of random numbers from the internal LCRNG +RANDOM=42 +(( dice[RANDOM%6+1 + RANDOM%6+1]++ )) +echo ${dice[6]} + +(( ++dice[RANDOM%6+1 + RANDOM%6+1] )) +echo ${dice[7]} + +v=4 +DIND=20 + +(( dice[DIND%6 + 1]=v )) +echo ${dice[3]} +(( dice[DIND/v]+=2 )) + +RANDOM=42 + +(( dice[RANDOM%6+1 + RANDOM%6+1]+=v )) +echo ${dice[6]} + +(( dice[RANDOM%6+1 + RANDOM%6+1]-=v )) +echo ${dice[7]} + +(( dice[RANDOM%6+1 + RANDOM%6+1]+=2 )) +echo ${dice[8]} + +(( dice[RANDOM%6+1 + RANDOM%6+1]*=2 )) +echo ${dice[5]} + +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..7d5c779 --- /dev/null +++ b/tests/arith5.sub @@ -0,0 +1,72 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# a lot of this is technically undefined behavior due to signed 64-bit +# integer overflow, but we're testing exception handling here + +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..dec8fd0 --- /dev/null +++ b/tests/arith6.sub @@ -0,0 +1,65 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..e6f1b0d --- /dev/null +++ b/tests/arith8.sub @@ -0,0 +1,50 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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 100644 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..6227885 --- /dev/null +++ b/tests/array.right @@ -0,0 +1,787 @@ + +./array.tests: line 28: syntax error near unexpected token `&' +./array.tests: line 28: `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 92: 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 116: a: readonly variable +./array.tests: line 118: b[]: bad array subscript +./array.tests: line 119: b[*]: bad array subscript +this +./array.tests: line 122: c[-2]: bad array subscript +./array.tests: line 123: c: bad array subscript + +./array.tests: line 125: d[7]: cannot assign list to array member +./array.tests: line 127: []=abcde: bad array subscript +./array.tests: line 127: [*]=last: cannot assign to non-numeric index +./array.tests: line 127: [-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 e=() +declare -a f=([0]="" [1]="bdef" [2]="hello world" [3]="test" [4]="ninth element") +./array.tests: line 135: unset: ps1: not an array variable +./array.tests: line 139: 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 e=() +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 255: 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 305: syntax error near unexpected token `<>' +./array.tests: line 305: `metas=( <> < > ! )' +./array.tests: line 306: syntax error near unexpected token `<>' +./array.tests: line 306: `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 +declare -a A=([0]="X=a" [1]="b") +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 +foo[bar] version[agent] +bowl version.agent +foobar] foo foo[bar] +bleh bbb 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 24: 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 +declare -ai arr=([0]="2" [1]="4" [2]="6") +declare -a arr=([0]="hello" [1]="world") +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 43: ~: syntax error: operand expected (error token is "~") +0 +0 +3 +3 +0 +0 +zero +zero +one +one +one +one +two +two +./array17.sub: line 89: ~ : syntax error: operand expected (error token is "~ ") +1 +argv[1] = <> +argv[2] = <> +argv[3] = <> +argv[1] = <bar> +argv[1] = <-> +argv[2] = <-> +argv[1] = < > +argv[1] = <qux> +argv[1] = <-> +argv[2] = <-> +argv[1] = < > +argv[1] = <> +argv[2] = <> +argv[3] = <> +argv[1] = <bar> +argv[1] = <-> +argv[2] = <-> +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") +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 89: 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 128: 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") +declare -A a=([0]="a b" ) +declare -A b=([0]="/scratch/bash" ) +declare -A c=([1]="2" ) +declare -A d=(["a b"]="" ) +declare -A e=([Darwin]="" ) +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 +declare -a a=() +declare -A A=([four]="4" [two]="2" [three]="3" [one]="1" ) +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 22: $( echo >&2 foo ) : syntax error: operand expected (error token is "$( echo >&2 foo ) ") +./array23.sub: line 23: $( echo >&2 foo ) : syntax error: operand expected (error token is "$( echo >&2 foo ) ") +./array23.sub: line 24: $( echo >&2 foo ) : syntax error: operand expected (error token is "$( echo >&2 foo ) ") +./array23.sub: line 26: $( echo >&2 foo ) : syntax error: operand expected (error token is "$( echo >&2 foo ) ") +./array23.sub: line 30: $( echo >&2 foo ): syntax error: operand expected (error token is "$( echo >&2 foo )") +./array23.sub: line 33: $( echo >&2 foo ): syntax error: operand expected (error token is "$( echo >&2 foo )") +./array23.sub: line 34: $index: syntax error: operand expected (error token is "$index") +./array23.sub: line 35: $( 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 24: ' ': 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 +7 +declare -A A=([$'\t']="2" [" "]="2" ) +declare -A A=([$'\t']="2" ["*"]="2" [" "]="2" ["]"]="2" ["@"]="2" ) +declare -A A=([$'\t']="2" ["*"]="2" [" "]="2" ["]"]="2" ["@"]="2" ) +./array27.sub: line 52: read: `A[]]': not a valid identifier +declare -A A=([$'\t']="X" ["*"]="X" [" "]="X" ["@"]="X" ) +./array27.sub: line 60: printf: `A[]]': not a valid identifier +declare -A A=([$'\t']="X" ["*"]="X" [" "]="X" ["@"]="X" ) +./array27.sub: line 68: declare: `A[]]=X': not a valid identifier +declare -A A=(["*"]="X" ["@"]="X" ) +./array27.sub: line 76: declare: `A[]]=X': not a valid identifier +declare -A A=(["*"]="X" ["@"]="X" ) +declare -a bug4=([0]="" [1]="5" [2]="" [3]="1" [4]="") +declare -a bug=([0]="" [1]="5" [2]="" [3]="1" [4]="") +declare -a bug2=([0]="") +declare -a bug3=([0]="" [1]="5" [2]="" [3]="1" [4]="") +declare -a not_bug=([0]="no" [1]="nulls") +declare -a workaround=([0]="") +declare -a var=([0]=$'\001\001\001\001') +declare -A v2=([$'\001']=$'ab\001c' ) +declare -a foo=([0]=$'\001\001\001\001') +declare -A foo=([$'\001']=$'ab\001c' ) +declare -a foo=([0]=$'\001\001\001\001') +declare -a foo=([0]=$'\001\001\001\001') +declare -A foo=([v]=$'\001\001\001\001' ) +declare -A foo=([v]=$'\001\001\001\001' ) +declare -A foo=([$'\001']=$'ab\001c' ) +declare -A foo=([$'\001']=$'ab\001c' ) +foo +declare -a a=([42]="foo") +foo +declare -a a=([42]="foo") +7 +declare -ai a=([42]="7") +42 +declare -ai a=([42]="42") +FOO +declare -Au A=([Darwin]="FOO" ) +FOO +declare -Au A=(["@"]="FOO" ) diff --git a/tests/array.tests b/tests/array.tests new file mode 100644 index 0000000..d0bb08b --- /dev/null +++ b/tests/array.tests @@ -0,0 +1,429 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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 parameters 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 assignment 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[@]}" + +unset A Z +Z='a b' +A=( X=$Z ) +declare -p A + +# 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 +${THIS_SH} ./array28.sub +${THIS_SH} ./array29.sub +${THIS_SH} ./array30.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..7182480 --- /dev/null +++ b/tests/array10.sub @@ -0,0 +1,65 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..5961902 --- /dev/null +++ b/tests/array11.sub @@ -0,0 +1,48 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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..fbf5eeb --- /dev/null +++ b/tests/array12.sub @@ -0,0 +1,34 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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..635cb97 --- /dev/null +++ b/tests/array13.sub @@ -0,0 +1,12 @@ + +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..57a455a --- /dev/null +++ b/tests/array14.sub @@ -0,0 +1,43 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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..12f5391 --- /dev/null +++ b/tests/array15.sub @@ -0,0 +1,52 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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[@]}" + +unset foo + +# test options to declare that disable attributes that affect how values +# are expanded +# +# we already handle options that set attributes specially, so we should +# handle attributes that unset those attributes specially as well + +unset arr +declare -i -a arr=(1+1 2+2 3+3) +declare -p arr + +declare +i arr=(hello world) +declare -p arr diff --git a/tests/array16.sub b/tests/array16.sub new file mode 100644 index 0000000..b82dbca --- /dev/null +++ b/tests/array16.sub @@ -0,0 +1,34 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..dd0c0f6 --- /dev/null +++ b/tests/array17.sub @@ -0,0 +1,91 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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..9503081 --- /dev/null +++ b/tests/array18.sub @@ -0,0 +1,47 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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..1d02f74 --- /dev/null +++ b/tests/array19.sub @@ -0,0 +1,175 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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='([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..24dff93 --- /dev/null +++ b/tests/array20.sub @@ -0,0 +1,47 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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..97ff093 --- /dev/null +++ b/tests/array21.sub @@ -0,0 +1,50 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..3374ef2 --- /dev/null +++ b/tests/array22.sub @@ -0,0 +1,59 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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..02d271d --- /dev/null +++ b/tests/array23.sub @@ -0,0 +1,41 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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..461b406 --- /dev/null +++ b/tests/array24.sub @@ -0,0 +1,60 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..fe6bb34 --- /dev/null +++ b/tests/array25.sub @@ -0,0 +1,83 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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..0f6cc8f --- /dev/null +++ b/tests/array26.sub @@ -0,0 +1,131 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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..e2a1e70 --- /dev/null +++ b/tests/array27.sub @@ -0,0 +1,78 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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 + 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/array28.sub b/tests/array28.sub new file mode 100644 index 0000000..e11cdb6 --- /dev/null +++ b/tests/array28.sub @@ -0,0 +1,30 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +# tests for assigning empty string array elements without subscripts +function foo() +{ + local bug=("" "5" "" 1 "") + declare -a bug2=("") + declare -ga bug3=("" "5" "" 1 "") + local not_bug=("no" "nulls") + local workaround; workaround=("") + + declare -p bug bug2 bug3 not_bug workaround +} + +declare -a bug4=("" "5" "" 1 "") +declare -p bug4 + +foo diff --git a/tests/array29.sub b/tests/array29.sub new file mode 100644 index 0000000..f73c2d1 --- /dev/null +++ b/tests/array29.sub @@ -0,0 +1,86 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# Issues with CTLESC characters in array subscripts and values. Bash-5.1 and +# earlier didn't quote them correctly and therefore halved the number of +# CTLESCs. + +declare -a var +var=( $'\x01\x01\x01\x01' ) +declare -p var +declare -A v2 +v2=( $'\x01' ab$'\x01'c ) +declare -p v2 + +pv() +{ + local -a foo + foo=( "${var[@]}" ) + declare -p foo +} +pv + +unset -f pv +pv() +{ + local -A foo + eval foo=\( "${v2[@]@k}" \) + declare -p foo +} +pv + +# these are wrong through bash-5.1; there is a fix tagged for bash-5.2 +# when I uncomment that fix, these results will reflect it + +pv1() +{ + local -a foo=( "${var[@]}" ) + declare -p foo +} +pv1 + +pv2() +{ + local -a foo=( [0]="${var[@]}" ) + declare -p foo +} +pv2 + +pv3() +{ + local -A foo=( v "${var[@]}" ) + declare -p foo +} +pv3 + +pv4() +{ + local -A foo=( [v]="${var[@]}" ) + declare -p foo +} +pv4 + +unset -f pv3 pv4 +pv3() +{ + local -A foo=( $'\x01' "${v2[@]}" ) + declare -p foo +} +pv3 + +pv4() +{ + local -A foo=( [$'\x01']="${v2[@]}" ) + declare -p foo +} +pv4 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/array30.sub b/tests/array30.sub new file mode 100644 index 0000000..14f9798 --- /dev/null +++ b/tests/array30.sub @@ -0,0 +1,46 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +declare -a a +a=() + +echo ${a[42]=foo} +declare -p a + +a=() +echo ${a[$(echo 42)]=foo} +declare -p a + +unset a + +declare -ai a +a=() +echo ${a[42]=4+3} +declare -p a + +a=() +echo ${a[$(echo 42)]=42} +declare -p a + +unset a + +declare -A A +declare -u A +A=() +echo ${A[$(echo Darwin)]=foo} + +declare -p A +A=() + +echo ${A[@]:=foo} +declare -p A diff --git a/tests/array4.sub b/tests/array4.sub new file mode 100644 index 0000000..443a0fd --- /dev/null +++ b/tests/array4.sub @@ -0,0 +1,45 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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..0dda696 --- /dev/null +++ b/tests/array5.sub @@ -0,0 +1,47 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +: ${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..2c6c350 --- /dev/null +++ b/tests/array6.sub @@ -0,0 +1,128 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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..6e7e2d6 --- /dev/null +++ b/tests/array8.sub @@ -0,0 +1,36 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..c3aa31d --- /dev/null +++ b/tests/array9.sub @@ -0,0 +1,40 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..9a1662c --- /dev/null +++ b/tests/assoc.right @@ -0,0 +1,400 @@ +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=([qux]="assigned" [bar]="newval" ) +./assoc.tests: line 39: chaff: four: must use subscript when assigning associative array +declare -A BASH_ALIASES=() +declare -A BASH_CMDS=() +declare -Ai chaff=([one]="10" [zero]="5" ) +declare -Ar waste=([pid]="42134" [lineno]="41" [source]="./assoc.tests" [version]="4.0-devel" ) +declare -A wheat=([two]="b" [three]="c" [one]="a" [zero]="0" ) +declare -A chaff=(["hello world"]="flip" [one]="10" [zero]="5" ) +./assoc.tests: line 51: waste: readonly variable +./assoc.tests: line 52: unset: waste: cannot unset: readonly variable +declare -A chaff=(["*"]="12" ["hello world"]="flip" [one]="a" ) +flip +argv[1] = <multiple> +argv[2] = <words> +argv[3] = <12> +argv[4] = <flip> +argv[5] = <a> +argv[1] = <multiple words> +argv[2] = <12> +argv[3] = <flip> +argv[4] = <a> +argv[1] = <multiple> +argv[2] = <words> +argv[3] = <12> +argv[4] = <flip> +argv[5] = <a> +argv[1] = <multiple words 12 flip a> +./assoc.tests: line 71: declare: chaff: cannot destroy array variables in this way +declare -A wheat=([six]="6" ["foo bar"]="qux qix" ) +argv[1] = <qux> +argv[2] = <qix> +argv[1] = <qux qix> +declare -A wheat=([six]="6" ["foo bar"]="qux qix" ) +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] = <6> +argv[2] = <flix> +argv[1] = <six> +argv[2] = <foo> +argv[3] = <bar> +argv[1] = <six> +argv[2] = <foo bar> +8 +/usr/local/bin /bin . /usr/bin /usr/ucb /usr/sbin /bin /sbin +bin bin . bin ucb sbin bin sbin +bin +/ / / / / / / +/ +argv[1] = <bin> +argv[1] = </> +argv[1] = <sbin> +argv[1] = </> +8 +/usr/local/bin /bin . /usr/bin /usr/ucb /usr/sbin /bin /sbin +bin bin . bin ucb sbin bin sbin +/ / / / / / / +8 +4 -- /bin +^usr^local^bin ^bin . ^usr^bin ^usr^ucb ^usr^sbin ^bin ^sbin +^usr^local^bin ^bin . ^usr^bin ^usr^ucb ^usr^sbin ^bin ^sbin +\usr/local/bin \bin . \usr/bin \usr/ucb \usr/sbin \bin \sbin +\usr\local\bin \bin . \usr\bin \usr\ucb \usr\sbin \bin \sbin +\usr\local\bin \bin . \usr\bin \usr\ucb \usr\sbin \bin \sbin +([a]=1) + +foo qux +/usr/sbin/foo /usr/local/bin/qux +hits command + 0 /usr/sbin/foo + 0 /bin/sh + 0 /sbin/blat + 0 /usr/local/bin/qux +foo sh blat qux +/usr/sbin/foo /bin/sh /sbin/blat /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=([six]="six" ["foo bar"]="foo quux" ) +argv[1] = <inside:> +argv[2] = <six> +argv[3] = <foo quux> +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 26: declare: `myarray[foo[bar]=bleh': not a valid identifier +def bleh abc +myarray=(["]"]="def" [foo]="bleh" ["a]a"]="abc" ["a]=test1;#a"]="123" ) + +123 +myarray=(["]"]="def" ["a]=test2;#a"]="def" [foo]="bleh" ["a]a"]="abc" ["a]=test1;#a"]="123" ) +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 hash=([key]="value1" ) +declare -A hash=([key]="value1 value2" ) +declare -A b=([")"]="" ["\""]="" ["]"]="" ["\\"]="" ["\`"]="" ) +declare -A b=(["]"]="" ["\`"]="" ) +declare -A dict=(["'"]="3" ["\""]="1" ["\\"]="4" ["\`"]="2" ) +declare -A dict=() +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 84: read: `a[80's]': not a valid identifier +declare -A a +declare -A a=(["80's"]="Depeche Mode" ) +./assoc9.sub: line 96: 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" ) +foo +declare -A assoc=(["\$var"]="value" ) +declare -A assoc=(["\$var"]="value" ) +declare -A assoc=(["\$var"]="value" ) +declare -A assoc=() +./assoc9.sub: line 154: typeset: `foo[foo]bar]=bax': not a valid identifier +foo]bar +bip +declare -A foo=(["foo]bar"]="bip" ) +./assoc10.sub: line 14: declare: a: cannot convert indexed to associative array +f: declare -a a +./assoc10.sub: line 17: 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" +declare -A a=([3]="" [1]="2" ) +declare -A foo=([d]="4" [c]="3" [b]="2" [a]="1" ) +foo=( d "4" c "3" b "2" a "1" ) +declare -A foo=(["\\"]="5" ["@"]="3" ["holy hell this works"]="4" ["a b"]="1" ["spa ces"]="2" ) +foo=( echo "\\" "5" "@" "3" "holy hell this works" "4" "a b" "1" "spa ces" "2" ) +./assoc11.sub: line 34: "": bad array subscript +declare -A foo=([";"]="semicolon" ["]"]="def" [a=b]="assignment" ["a]a"]="abc" ["foo[bar"]="bleh" ) +foo=( ";" "semicolon" "]" "def" a=b "assignment" "a]a" "abc" "foo[bar" "bleh" ) +declare -A foo=(["'"]="squote" ["\""]="dquote" ["\\"]="bslash" ["\`"]="backquote" ) +foo=( "'" "squote" "\"" "dquote" "\\" "bslash" "\`" "backquote" ) +declare -A foo=(["bar]bie"]="doll" ["a]=test1;#a"]="123" ["bar\"bie"]="doll" ) +foo=( "bar]bie" "doll" "a]=test1;#a" "123" "bar\"bie" "doll" ) +declare -A inside=([c]="3" [b]="2" [a]="1" ) +inside=( c "3" b "2" a "1" ) +declare -A dict=(["?"]="quest" ["*"]="star" ["'"]="squote" ["\$"]="dol" ["\""]="dquote" ["\\"]="bslash" ["@"]="at" ["}"]="rbrace" ["{"]="lbrace" ["\`"]="bquote" ) +dict=( "?" "quest" "*" "star" "'" "squote" "\$" "dol" "\"" "dquote" "\\" "bslash" "@" "at" "}" "rbrace" "{" "lbrace" "\`" "bquote" ) +declare -A foo=([two]="" [one]="1" ) +foo=( two "" one "1" ) +rparen dquote rbracket bs +declare -A a=([")"]="rparen" ["\""]="dquote" ["]"]="rbracket" ["\\"]="bs" ) +")" "rparen" "\"" "dquote" "]" "rbracket" "\\" "bs" +declare -A a=([")"]="rparen" ["\""]="dquote" ["]"]="rbracket" ["\\"]="bs" ) +declare -A a=([")"]="rparen" ["\""]="dquote" ["]"]="rbracket" ["\\"]="bs" ) +declare -A a=([")"]="rparen" ["\""]="dquote" ["]"]="rbracket" ["\\"]="bs" ) +declare -Arx foo=([two]="2" [three]="3" [one]="1" ) +./assoc11.sub: line 90: foo: readonly variable +declare -A v1=(["1 2"]="3" ) +declare -A v2=(["1 2"]="3" ) +declare -A v3=(["1 2"]="3" ) +declare -A v1=(["1 2"]="3 4 5" ) +declare -A v2=(["1 2"]="3 4 5" ) +declare -A v3=(["1 2"]="3 4 5" ) +declare -A v1=(["1 2"]="3 4 5" ) +declare -A v2=(["1 2"]="3 4 5" ) +declare -A v3=(["1 2"]="3 4 5" ) +declare -A v1=(["1 2"]="3 4 5" ) +declare -A v2=(["1 2"]="3 4 5" ) +declare -A v3=(["1 2"]="3 4 5" ) +declare -A v1=(["20 40 80"]="xtra" ["1 2"]="3 4 5" ) +declare -A v2=(["20 40 80"]="xtra" ["1 2"]="3 4 5" ) +declare -A v3=(["1 2"]="3 4 5" ["\$xtra"]="xtra" ) +declare -A v1=(["20 40 80"]="new xtra" ["1 2"]="3 4 5" ) +declare -A v2=(["20 40 80"]="new xtra" ["1 2"]="3 4 5" ) +declare -A v3=(["1 2"]="3 4 5" ["\$xtra"]="new xtra" ) +declare -A assoc=(["*"]="star" ["!"]="bang" ["@"]="at" ) +at +star +declare -A a=(["@"]="at" ) +./assoc13.sub: line 22: ia[@]: bad array subscript +declare -a ia +declare -A a=(["@"]="at2" ) +declare -A a=(["@"]=" string" ) +declare -A a=(["*"]="star2" ["@"]="at" ) +declare -A assoc=([hello]="world" ["key with spaces"]="value with spaces" [foo]="bar" [one]="1" ) +argv[1] = <world> +argv[2] = <value with spaces> +argv[3] = <bar> +argv[4] = <1> +argv[1] = <hello> +argv[2] = <world> +argv[3] = <key with spaces> +argv[4] = <value with spaces> +argv[5] = <foo> +argv[6] = <bar> +argv[7] = <one> +argv[8] = <1> +argv[1] = <world value with spaces bar 1> +argv[1] = <hello world key with spaces value with spaces foo bar one 1> +argv[1] = <hello> +argv[2] = <world> +argv[3] = <key with spaces> +argv[4] = <value with spaces> +argv[5] = <one> +argv[6] = <1> +argv[7] = <foo> +argv[8] = <bar> +argv[1] = <'hello'> +argv[2] = <'world'> +argv[3] = <'key with spaces'> +argv[4] = <'value with spaces'> +argv[5] = <'one'> +argv[6] = <'1'> +argv[7] = <'foo'> +argv[8] = <'bar'> +argv[1] = <'hello'> +argv[2] = <'world'> +argv[3] = <'key with spaces'> +argv[4] = <'value with spaces'> +argv[5] = <'one'> +argv[6] = <'1'> +argv[7] = <'foo'> +argv[8] = <'bar'> +declare -A clone=([hello]="world" ["key with spaces"]="value with spaces" [foo]="bar" [one]="1" ) +declare -A posparams=([hello]="world" ["key with spaces"]="value with spaces" [foo]="bar" [one]="1" ) +declare -A var=([$'\001']=$'\001\001\001\001' ) +declare -A v2=([$'\001']=$'\001\001\001\001' ) +argv[1] = <^A> +argv[2] = <^A^A^A^A> +declare -A foo=([$'\001']=$'\001\001\001\001' ) +declare -A var=([$'\001']=$'\001\001\001\001' ) +argv[1] = <^A> +argv[2] = <^A^A^A^A> +declare -A foo=([$'\001']=$'\001\001\001\001' ) +declare -A var=([$'\001']=$'\001\001\001\001' ) +argv[1] = <^A> +argv[2] = <^A^A^A^A> +declare -A foo=([$'\001']=$'\001\001\001\001' ) +declare -a var=([0]=$'\001\001\001\001') +argv[1] = <$'\001\001\001\001'> +declare -a foo=([0]=$'\001\001\001\001') +declare -a var=([0]=$'\001\001\001\001') +argv[1] = <$'\001\001\001\001'> +declare -a foo=([0]=$'\001\001\001\001') +declare -A var=([two]=$'ab\001cd' [one]=$'\001\001\001\001' ) +declare -A foo=([two]=$'ab\001cd' [one]=$'\001\001\001\001' ) +declare -A foo=([$'\001']=$'ab\001cd' ) +declare -A foo=([$'\001']=$'\001\001\001\001' ) +declare -A A=(["\$(echo Darwin ; echo stderr>&2)"]="darjeeling" [Darwin]="darjeeling" ) +stderr +darjsharking +darjsharking +stderr +darj +darj +stderr +DARJEELING +DARJEELING +stderr +'darjeeling' +'darjeeling' +stderr +darjeel +darjeel +stderr +10 +10 +stderr +darjeeling +darjeeling +stderr +set +set +stderr +set +set +stderr +42 +42 +declare -A A=(["]"]="rbracket" ["["]="lbracket" ) +declare -A A=() +declare -A A=(["]"]="rbracket" ["["]="lbracket" ) +declare -A A=() +declare -A A=(["]"]="rbracket" ["["]="lbracket" ) +declare -A A=() +declare -A A=(["]"]="rbracket" ["["]="lbracket" ) +declare -A A=() +declare -A A=(["]"]="rbracket" ["["]="lbracket" ) +declare -A A=() +declare -A A=(["]"]="rbracket" ["["]="lbracket" ) +declare -A A=() +declare -A A=(["]"]="rbracket" ["["]="lbracket" ) +declare -A A=() +5: ok 1 diff --git a/tests/assoc.tests b/tests/assoc.tests new file mode 100644 index 0000000..c656536 --- /dev/null +++ b/tests/assoc.tests @@ -0,0 +1,268 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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 - compound 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 - no longer 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 + +declare -A hash + +hash=(["key"]="value1") +declare -p hash +hash=(["key"]="${hash["key"]} value2") +declare -p hash + +unset hash + +${THIS_SH} ./assoc8.sub + +# new shopt option to prevent multiple expansion of assoc array subscripts +${THIS_SH} ./assoc9.sub + +${THIS_SH} ./assoc10.sub + +# test assigning associative arrays using compound key/value pair assignments +${THIS_SH} ./assoc11.sub + +# more kvpair associative array assignment tests +${THIS_SH} ./assoc12.sub + +# assignment to @ and * +${THIS_SH} ./assoc13.sub + +# tests of the @k transformation on associative arrays +${THIS_SH} ./assoc14.sub + +# tests with subscripts and values containing 0x01 (some indexed array tests too) +${THIS_SH} ./assoc15.sub + +# tests with subscripts being expanded more than one in ${xxx} word expansions +${THIS_SH} ./assoc16.sub + +# tests with `[' and `]' subscripts and `unset' +${THIS_SH} ./assoc17.sub + +# tests with `[' and `]' subscripts and printf/read/wait builtins +${THIS_SH} ./assoc18.sub + diff --git a/tests/assoc1.sub b/tests/assoc1.sub new file mode 100644 index 0000000..99a6e22 --- /dev/null +++ b/tests/assoc1.sub @@ -0,0 +1,29 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..5b21525 --- /dev/null +++ b/tests/assoc10.sub @@ -0,0 +1,30 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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/assoc11.sub b/tests/assoc11.sub new file mode 100644 index 0000000..9d9afae --- /dev/null +++ b/tests/assoc11.sub @@ -0,0 +1,90 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# these tests were previously in array19.sub, but they are acceptable syntax now + +declare -A a +declare a='(1 2 3)' +declare -p a +unset a + +declare -A foo + +v1='spa ces' +v2=@ + +foo=(a 1 b 2 c 3 d 4 ) +declare -p foo +echo foo=\( ${foo[@]@K} \) + +foo=('a b' 1 "$v1" 2 "$v2" 3 'holy hell this works' 4 \\ 5) +declare -p foo +echo foo=\( echo ${foo[@]@K} \) + +foo=( "" null ) + +foo=('a]a' abc ']' def $(echo 'foo[bar') bleh \; semicolon a=b assignment) +declare -p foo +echo foo=\( ${foo[@]@K} \) + +foo=('`' backquote '"' dquote "'" squote \\ bslash) +declare -p foo +echo foo=\( ${foo[@]@K} \) + +bar='a]=test1;#a' +foo=( $bar 123 bar\"bie doll bar]bie doll ) +declare -p foo +echo foo=\( ${foo[@]@K} \) + +func() +{ + declare -A inside=(a 1 b 2 c 3) + declare -p inside + echo inside=\( ${inside[@]@K} \) +} +func + +loaddict() +{ + dict=( '"' dquote '`' bquote "'" squote '\' bslash) + dict+=( '$' dol @ at * star \{ lbrace \} rbrace ? quest) + + declare -p dict + echo dict=\( ${dict[@]@K} \) +} +declare -A dict +loaddict + +foo=(one 1 two) +declare -p foo +echo foo=\( ${foo[@]@K} \) + +typeset -A a=( [\\]=bs [\"]=dquote [\)]=rparen [\]]=rbracket ) +echo ${a[@]} +declare -p a + +echo ${a[@]@K} +echo ${a[@]@A} + +eval "${a[@]@A}" +declare -p a + +eval "a=( ${a[@]@K} )" +declare -p a + +unset a foo +readonly -A foo=( one 1 two 2 three 3 ) + +export foo +declare -p foo +declare foo+=( seven 7 eight 8 ) diff --git a/tests/assoc12.sub b/tests/assoc12.sub new file mode 100644 index 0000000..359dc0b --- /dev/null +++ b/tests/assoc12.sub @@ -0,0 +1,74 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +foo='1 2' +bar='3 4 5' +xtra='20 40 80' + +declare -A v1=( $foo 3 ) +declare -p v1 + +declare -A v2=( [$foo]=3 ) +declare -p v2 + +declare -A v3 +v3=( $foo 3 ) +declare -p v3 + +unset v1 v2 v3 + +declare -A v1=( $foo $bar ) +declare -p v1 + +declare -A v2=( [$foo]=$bar ) +declare -p v2 + +declare -A v3 +v3=( $foo $bar ) +declare -p v3 + +unset v1 v2 v3 + +declare -A v1=( "$foo" $bar ) +declare -p v1 + +declare -A v2=( ["$foo"]=$bar ) +declare -p v2 + +declare -A v3 +v3=( "$foo" $bar ) +declare -p v3 + +unset v1 v2 v3 + +declare -A v1=( "$foo" "$bar" ) +declare -p v1 + +declare -A v2=( ["$foo"]="$bar" ) +declare -p v2 + +declare -A v3 +v3=( "$foo" "$bar" ) +declare -p v3 + +v1+=( $xtra xtra ) +v2+=( "$xtra" xtra ) +v3+=( '$xtra' xtra ) + +declare -p v1 v2 v3 + +v1+=( [$xtra]='new xtra' ) +v2+=( ["$xtra"]='new xtra' ) +v3+=( ['$xtra']='new xtra' ) + +declare -p v1 v2 v3 diff --git a/tests/assoc13.sub b/tests/assoc13.sub new file mode 100644 index 0000000..7e66972 --- /dev/null +++ b/tests/assoc13.sub @@ -0,0 +1,44 @@ +# assignment to @ and * + +declare -A assoc +key=@ +key2=* + +assoc[$key]=at +assoc[$key2]=star +assoc[!]=bang +declare -p assoc + +echo ${assoc[$key]} +echo ${assoc[$key2]} +unset assoc + +declare -A a + +a[@]=at +declare -p a + +declare -a ia +ia[@]=garbage + +declare -p ia + +declare a[@]=at2 +declare -p a + +unset a ia + +declare -A a +printf -v a[@] "%10s" string + +declare -p a +unset a + +declare -A a +declare a[$key2]=star +declare a[@]=at +declare a[*]=star2 + +declare -p a +unset a + diff --git a/tests/assoc14.sub b/tests/assoc14.sub new file mode 100644 index 0000000..95df049 --- /dev/null +++ b/tests/assoc14.sub @@ -0,0 +1,35 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +declare -A assoc=(hello world "key with spaces" "value with spaces" one 1 foo bar) +declare -p assoc + +recho "${assoc[@]}" +recho "${assoc[@]@k}" + +recho "${assoc[*]}" +recho "${assoc[*]@k}" + +set -- hello world "key with spaces" "value with spaces" one 1 foo bar +recho "${@}" +recho "${@@K}" +recho "${@@k}" + +declare -A clone +eval clone=\( "${assoc[@]@K}" \) +declare -p clone + +declare -A posparams +eval posparams=\( "${@@K}" \) +declare -p posparams diff --git a/tests/assoc15.sub b/tests/assoc15.sub new file mode 100644 index 0000000..c47b153 --- /dev/null +++ b/tests/assoc15.sub @@ -0,0 +1,92 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +# associative arrays first + +v=$'\x01' + +declare -A var foo v2 +var=( $'\x01' $'\x01\x01\x01\x01' ) +declare -p var +v2=( $v $v$v$v$v ) +declare -p v2 + +recho "${var[@]@k}" +eval foo=\( "${var[@]@k}" \) +declare -p foo + +var=( ) +declare -p var + +recho "${var[@]@k}" +eval foo=\( "${var[@]@k}" \) +declare -p foo + +var=( []= ) +declare -p var + +recho "${var[@]@k}" +eval foo=\( "${var[@]@k}" \) +declare -p foo + +# now indexed arrays +unset -v var foo + +declare -a var +var=( [0]= ) +declare -p var + +declare -a foo +recho "${var[@]@Q}" +eval foo=\( "${var[@]@Q}" \) +declare -p foo + +var=( ) +declare -p var + +unset foo + +declare -a foo +recho "${var[@]@Q}" +eval foo=\( "${var[@]@Q}" \) +declare -p foo + +# similar to array29.sub +unset -v var foo v2 + +declare -A var +var=( one $'\x01\x01\x01\x01' two ab$'\001'cd ) +declare -p var + +pv() +{ + local -A foo + eval foo=\( "${var[@]@k}" \) + declare -p foo +} +pv + +pv1() +{ + local -A foo=( $'\x01' "${var[two]}" ) + declare -p foo +} +pv1 + +pv2() +{ + local -A foo=( [$'\x01']="${var[one]}" ) + declare -p foo +} +pv2 diff --git a/tests/assoc16.sub b/tests/assoc16.sub new file mode 100644 index 0000000..ae8296b --- /dev/null +++ b/tests/assoc16.sub @@ -0,0 +1,56 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +# bash versions up to and including bash-5.1 expanded these subscripts more +# than once + +declare -A A + +A["Darwin"]=darjeeling +A['$(echo Darwin ; echo stderr>&2)']=darjeeling + +declare -p A + +echo ${A[$(echo Darwin ; echo stderr>&2)]//eel/shark} +echo ${A['$(echo Darwin ; echo stderr>&2)']//eel/shark} + +echo ${A[$(echo Darwin ; echo stderr>&2)]:0:4} +echo ${A['$(echo Darwin ; echo stderr>&2)']:0:4} + +echo ${A[$(echo Darwin ; echo stderr>&2)]^^} +echo ${A['$(echo Darwin ; echo stderr>&2)']^^} + +echo ${A[$(echo Darwin ; echo stderr>&2)]@Q} +echo ${A['$(echo Darwin ; echo stderr>&2)']@Q} + +echo ${A[$(echo Darwin ; echo stderr>&2)]%ing} +echo ${A['$(echo Darwin ; echo stderr>&2)']%ing} + +echo ${#A[$(echo Darwin ; echo stderr>&2)]} +echo ${#A['$(echo Darwin ; echo stderr>&2)']} + +echo ${A[$(echo Darwin ; echo stderr>&2)]:-value} +echo ${A['$(echo Darwin ; echo stderr>&2)']:-value} + +echo ${A[$(echo Darwin ; echo stderr>&2)]:+set} +echo ${A['$(echo Darwin ; echo stderr>&2)']:+set} + +echo ${A[$(echo Darwin ; echo stderr>&2)]:+set} +echo ${A['$(echo Darwin ; echo stderr>&2)']:+set} + +darjeeling=7*6 +Darwin=7*4 + +echo $(( ${A[$(echo Darwin ; echo stderr>&2)]} )) +echo $(( ${A['$(echo Darwin ; echo stderr>&2)']} )) diff --git a/tests/assoc17.sub b/tests/assoc17.sub new file mode 100644 index 0000000..a98aaa1 --- /dev/null +++ b/tests/assoc17.sub @@ -0,0 +1,58 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# test behavior with `unset' and `[' and ']' subscripts + +declare -A A +rkey=']' +lkey='[' + +A[$rkey]=rbracket +A[$lkey]=lbracket +declare -p A + +unset A[$rkey] +unset A[$lkey] +declare -p A + +A["$rkey"]=rbracket +A["$lkey"]=lbracket +declare -p A + +unset A["$rkey"] +unset A["$lkey"] +declare -p A + +A[\]]=rbracket +A[\[]=lbracket +declare -p A + +unset A[\]] +unset A[\[] +declare -p A + +A[']']=rbracket +A['[']=lbracket +declare -p A + +unset A[']'] +unset A['['] +declare -p A + +A["]"]=rbracket +A["["]=lbracket +declare -p A + +unset A["]"] +unset A["["] +declare -p A diff --git a/tests/assoc18.sub b/tests/assoc18.sub new file mode 100644 index 0000000..0597609 --- /dev/null +++ b/tests/assoc18.sub @@ -0,0 +1,59 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +# test behavior of builtins that can take array subscript arguments, make +# sure they work in the presence of associative arrays and `problematic' keys +# if assoc_expand_once is set +# +# affected builtins: printf, read, wait + +declare -A A +rkey=']' +lkey='[' + +shopt -s assoc_expand_once + +printf -v A[$rkey] rbracket +printf -v A[$lkey] lbracket +declare -p A + +unset A[$rkey] +unset A[$lkey] +declare -p A + +unset A +declare -A A + +read A[$rkey] <<<rbracket +read A[$lkey] <<<lbracket +declare -p A + +unset A[$rkey] +unset A[$lkey] +declare -p A + +unset A +declare -A A + +{ sleep 1 ; exit 4; } & +{ sleep 2 ; exit 5; } & bgpid1=$! +{ sleep 4 ; exit 6; } & + +wait -p A[$rkey] -n %2 %3 +case "${A[$rkey]}" in +$bgpid1) echo $?: ok 1;; +*) echo bad 1;; +esac + +exit 0 diff --git a/tests/assoc2.sub b/tests/assoc2.sub new file mode 100644 index 0000000..470e2c9 --- /dev/null +++ b/tests/assoc2.sub @@ -0,0 +1,28 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..a7eeb26 --- /dev/null +++ b/tests/assoc3.sub @@ -0,0 +1,28 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..eff9d0e --- /dev/null +++ b/tests/assoc4.sub @@ -0,0 +1,35 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..844d944 --- /dev/null +++ b/tests/assoc5.sub @@ -0,0 +1,40 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..88b8eaf --- /dev/null +++ b/tests/assoc6.sub @@ -0,0 +1,159 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..cae57c5 --- /dev/null +++ b/tests/assoc7.sub @@ -0,0 +1,29 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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..f83ac6d --- /dev/null +++ b/tests/assoc9.sub @@ -0,0 +1,159 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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 + +key='$(date >&2)' +declare -A aa +aa[$key]=foo +echo "${aa[$key]}" + +[[ -v aa[$key] ]] || echo bad assoc expansion + +shopt -u assoc_expand_once + +declare -A assoc + +var=x123 +assoc['$var']=value + +declare -p assoc + +unset "assoc[$var]" +declare -p assoc + +unset 'assoc[$var]' +declare -p assoc + +shopt -s assoc_expand_once +unset 'assoc[$var]' +declare -p assoc + +typeset -A foo + +foo["foo]bar"]=bip +typeset foo["foo]bar"]=bax + +echo ${!foo[@]} +echo ${foo[@]} + +declare -p foo diff --git a/tests/attr.right b/tests/attr.right new file mode 100644 index 0000000..d2d28b7 --- /dev/null +++ b/tests/attr.right @@ -0,0 +1,37 @@ +after f1:declare -ar a=([0]="1") +./attr.tests: line 17: a: readonly variable +after f2:declare -ar a=([0]="1") +./attr.tests: line 18: a: readonly variable +after f3:declare -ar a=([0]="1") +./attr.tests: line 19: 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 26: p: readonly variable +declare -r p="1" +./attr1.sub: line 32: r: readonly variable +declare -ar r=([0]="1") +./attr1.sub: line 36: r: readonly variable +declare -ar r=([0]="1") +./attr1.sub: line 40: r: readonly variable +declare -ar r=([0]="1") +./attr1.sub: line 44: 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..4874d9a --- /dev/null +++ b/tests/attr.tests @@ -0,0 +1,54 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..4424be9 --- /dev/null +++ b/tests/attr1.sub @@ -0,0 +1,68 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..dadca10 --- /dev/null +++ b/tests/attr2.sub @@ -0,0 +1,37 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..da0b624 --- /dev/null +++ b/tests/braces.tests @@ -0,0 +1,132 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..4f51d43 --- /dev/null +++ b/tests/builtins.right @@ -0,0 +1,281 @@ +1000 +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 23: /tmp/source-notthere: No such file or directory +after bad source 1 +./source5.sub: line 30: /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 228: declare: FOO: not found +declare -x FOO="\$\$" +ok +ok +./builtins.tests: line 260: 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 +0 +0 +assoc A unset +array a +assoc A +array a +assoc B unset +array b unset +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 41: declare: f1: not found +./builtins6.sub: line 41: 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 +bash: line 1: notthere: No such file or directory +one +bash: line 1: notthere: No such file or directory +two +bash: line 1: .: notthere: file not found +one +bash: line 1: .: notthere: file not found +0 +0 +0 +0 +argv[1] = <one> +0 +argv[1] = <two> +0 +three +0 +four +0 +./builtins7.sub: line 19: : command not found +127 +0 +./builtins7.sub: line 27: notthere: No such file or directory +after 1 +./builtins7.sub: line 28: notthere: No such file or directory +after 2 +type is a shell builtin ++ command -v type +type ++ command command -v type +type ++ command -p command -v type +type ++ command -p -- command -v type +type ++ set +x +./builtins.tests: line 284: exit: status: numeric argument required diff --git a/tests/builtins.tests b/tests/builtins.tests new file mode 100644 index 0000000..8eee43e --- /dev/null +++ b/tests/builtins.tests @@ -0,0 +1,286 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# tests for miscellaneous builtins not tested elsewhere +set +p +set +o posix + +ulimit -S -c 0 2>/dev/null +ulimit -c -S -- 1000 2>/dev/null +ulimit -c 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 utilities +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-existent 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 + +# test behavior of command builtin after changing it to a pseudo-keyword +${THIS_SH} ./builtins7.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..058ee2c --- /dev/null +++ b/tests/builtins4.sub @@ -0,0 +1,57 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..4fcf793 --- /dev/null +++ b/tests/builtins5.sub @@ -0,0 +1,83 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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 + +echo ${#B[@]} +echo ${#b[@]} + +scalar1=foo +scalar2= + +# this now checks for A[@] treating @ as a valid key - post-bash-5.1 +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 [ ${#A[@]} -gt 0 ]; then echo assoc A; else echo assoc A unset; fi +if [ ${#a[@]} -gt 0 ]; 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 [ ${#B[@]} -gt 0 ]; then echo assoc B; else echo assoc B unset; fi +if [ ${#b[@]} -gt 0 ]; 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..d4fdf4a --- /dev/null +++ b/tests/builtins6.sub @@ -0,0 +1,81 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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/builtins7.sub b/tests/builtins7.sub new file mode 100644 index 0000000..67e5e61 --- /dev/null +++ b/tests/builtins7.sub @@ -0,0 +1,38 @@ +: ${THIS_SH:=./bash} + +${THIS_SH} -c 'command . notthere ; echo one' bash +${THIS_SH} -c '. notthere ; echo two' bash + +${THIS_SH} -o posix -c 'command . notthere ; echo one' bash +${THIS_SH} -o posix -c '. notthere ; echo two' bash + +command ; echo $? +command -- ; echo $? +command -p ; echo $? +command -p -- ; echo $? + +command recho one; echo $? +command -- recho two; echo $? +command -p echo three; echo $? +command -p -- echo four ; echo $? + +command '' +echo $? + +command -p +echo $? + +${THIS_SH} -c 'set -e ; command false ; echo after' bash + +command command command -p . notthere ; echo after 1 +command -p command command . notthere ; echo after 2 + +command -p command -V type + +set -x +command -v type +command command -v type +command -p command -v type +command -p -- command -v type +set +x + diff --git a/tests/case.right b/tests/case.right new file mode 100644 index 0000000..d33c8c5 --- /dev/null +++ b/tests/case.right @@ -0,0 +1,63 @@ +fallthrough +to here +and here +retest +and match +no more clauses +1.0 +./case.tests: line 42: xx: readonly variable +1.1 +matches 1 +no +no +no +no +no +ok +esac +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..7ad4c68 --- /dev/null +++ b/tests/case.tests @@ -0,0 +1,73 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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 + +# posix issue discovered after bash-5.1 was released +case esac in (esac) echo esac;; esac +case k in else|done|time|esac) for f in 1 2 3 ; do :; done 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..8077111 --- /dev/null +++ b/tests/case1.sub @@ -0,0 +1,77 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..6c3be38 --- /dev/null +++ b/tests/case2.sub @@ -0,0 +1,65 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..1e8d785 --- /dev/null +++ b/tests/case3.sub @@ -0,0 +1,52 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +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..ababeb9 --- /dev/null +++ b/tests/case4.sub @@ -0,0 +1,38 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..df12475 --- /dev/null +++ b/tests/casemod.right @@ -0,0 +1,47 @@ +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 +abcdexyz +ABCDEXYZ diff --git a/tests/casemod.tests b/tests/casemod.tests new file mode 100644 index 0000000..56ab20d --- /dev/null +++ b/tests/casemod.tests @@ -0,0 +1,126 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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/complete.right b/tests/complete.right new file mode 100644 index 0000000..c8bf1dc --- /dev/null +++ b/tests/complete.right @@ -0,0 +1,63 @@ +complete -f -X '!*.+(ps|PS)' gs +complete -e printenv +complete -f -X '!*.texi*' texi2html +complete -g groupmod +complete -v -S '=' typeset +complete -c nohup +complete -a unalias +complete -g groupdel +complete -A hostname telnet +complete -v -S '=' local +complete -v -S '=' readonly +complete -o bashdefault -o filenames -o nospace -F _comp_cd cd +complete -c type +complete -f ln +complete -f -X '!*.+(gz|tgz)' gunzip +complete -f -X '!*.texi*' makeinfo +complete -j -P '%' jobs +complete -o dirnames -o filenames -o nospace -d pushd +complete -f -X '!*.pdf' acroread +complete -v unset +complete -f -X '!*.+(ps|PS)' ghostview +complete -A hostname rsh +complete -c exec +complete -A signal kill +complete -c eval +complete -f chown +complete -f gzip +complete -W '"${GROUPS[@]}"' newgrp +complete -A shopt shopt +complete -A hostname ftp +complete -A hostname rlogin +complete -v getopts +complete -c nice +complete -c gdb +complete -j -P '%' fg +complete -f -X '!*.dvi' dvips +complete -f -X '!*.texi*' texi2dvi +complete -f . +complete -v -S '=' declare +complete -v -S '=' export +complete -f -X '!*.dvi' xdvi +complete -u su +complete -o dirnames -o filenames -o nospace -d popd +complete -A signal trap +complete -j -W '$(ps -x | tail +2 | cut -c1-5)' -P '%' wait +complete -f -X '!*.Z' zmore +complete -j -P '%' disown +complete -f -X '!*.+(ps|PS)' gs +complete -f -X '!*.+(ps|PS)' gv +complete -f source +complete -c make +complete -A stopped -P '%' bg +complete -f cat +complete -d mkdir +complete -A helptopic help +complete -v read +complete -c -k time +complete -f -X '!*.Z' zcat +complete -f -X '!*.Z' uncompress +complete -d rmdir +complete -f more +complete -f -X '!*.+(gz|tgz)' gzcat +./complete.tests: line 123: complete: notthere: no completion specification diff --git a/tests/complete.tests b/tests/complete.tests new file mode 100644 index 0000000..36a3983 --- /dev/null +++ b/tests/complete.tests @@ -0,0 +1,126 @@ +# Chet Ramey <chet.ramey@case.edu> +# +# Copyright 2002-2020 Chester Ramey +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# TThis program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +complete + +# from zsh, just for testing +complete -A stopped -P '%' bg +complete -j -P '%' fg jobs disown +# this is wrong at this point +complete -j -P '%' -W '$(ps -x | tail +2 | cut -c1-5)' wait +complete -c type +complete -a unalias +complete -v getopts read unset +complete -v -S '=' declare export local readonly typeset +complete -f -- . source +complete -A shopt shopt +complete -e printenv + +complete -A helptopic help + +complete -c nohup exec nice eval +complete -c -k time + +complete -A signal trap kill + +complete -f chown ln more cat +complete -d mkdir rmdir + +complete -f -X '!*.+(gz|tgz)' gunzip gzcat zcat zmore +complete -f -X '!*.Z' uncompress zmore zcat +complete -f gzip + +complete -o dirnames -o filenames -o nospace -d pushd popd + +_comp_cd() +{ + local IFS=$' \t\n' # normalize IFS + local cur _skipdot _cdpath + local i j k + + # Tilde expansion, with side effect of expanding tilde to full pathname + case "$2" in + \~*) eval cur="$2" ;; + *) cur=$2 ;; + esac + + # no cdpath or absolute pathname -- straight directory completion + if [[ -z "${CDPATH:-}" ]] || [[ "$cur" == @(./*|../*|/*) ]]; then + # compgen prints paths one per line; could also use while loop + IFS=$'\n' + COMPREPLY=( $(compgen -d -- "$cur") ) + IFS=$' \t\n' + # CDPATH+directories in the current directory if not in CDPATH + else + IFS=$'\n' + _skipdot=false + # preprocess CDPATH to convert null directory names to . + _cdpath=${CDPATH/#:/.:} + _cdpath=${_cdpath//::/:.:} + _cdpath=${_cdpath/%:/:.} + for i in ${_cdpath//:/$'\n'}; do + if [[ $i -ef . ]]; then _skipdot=true; fi + k="${#COMPREPLY[@]}" + for j in $( compgen -d -- "$i/$cur" ); do + COMPREPLY[k++]=${j#$i/} # cut off directory + done + done + $_skipdot || COMPREPLY+=( $(compgen -d -- "$cur") ) + IFS=$' \t\n' + fi + + # variable names if appropriate shell option set and no completions + if shopt -q cdable_vars && [[ ${#COMPREPLY[@]} -eq 0 ]]; then + COMPREPLY=( $(compgen -v -- "$cur") ) + fi + + # append slash to passed directory name that is the only completion. + # readline will not do this if we complete from CDPATH + if [[ ${#COMPREPLY[@]} -eq 1 ]]; then + i=${COMPREPLY[0]} # shorthand + if [[ "$cur" == "$i" ]] && [[ "$i" != "*/" ]]; then + COMPREPLY[0]+=/ + fi + fi + return 0 +} + +complete -o filenames -o nospace -o bashdefault -F _comp_cd cd + +complete -A hostname rsh telnet rlogin ftp + +complete -u su +complete -W '"${GROUPS[@]}"' newgrp +complete -g groupdel groupmod + +complete -f -X '!*.+(ps|PS)' gs gv ghostview +complete -f -X '!*.dvi' dvips xdvi +complete -f -X '!*.pdf' acroread + +complete -f -X '!*.texi*' makeinfo texi2dvi texi2html + +complete -c gdb make + +complete -p gs +complete -p + +complete -r xdvi +complete -r notthere + +complete -r +complete diff --git a/tests/comsub-eof.right b/tests/comsub-eof.right new file mode 100644 index 0000000..cd5ab69 --- /dev/null +++ b/tests/comsub-eof.right @@ -0,0 +1,17 @@ +./comsub-eof0.sub: line 5: warning: here-document at line 3 delimited by end-of-file (wanted `EOF') +hi +hi +./comsub-eof2.sub: line 2: warning: here-document at line 1 delimited by end-of-file (wanted `EOF') +hi +./comsub-eof3.sub: line 4: warning: here-document at line 1 delimited by end-of-file (wanted `EOF') +./comsub-eof3.sub: line 5: unexpected EOF while looking for matching `)' +./comsub-eof4.sub: line 3: warning: here-document at line 1 delimited by end-of-file (wanted `EOF') +contents +./comsub-eof5.sub: line 4: warning: here-document at line 2 delimited by end-of-file (wanted `)') +hi +./comsub-eof5.sub: line 9: warning: here-document at line 7 delimited by end-of-file (wanted `EOF') +hi +./comsub-eof5.sub: line 15: warning: here-document at line 13 delimited by end-of-file (wanted `)') +hi +./comsub-eof6.sub: command substitution: line 3: unexpected EOF while looking for matching `)' + diff --git a/tests/comsub-eof.tests b/tests/comsub-eof.tests new file mode 100644 index 0000000..398746a --- /dev/null +++ b/tests/comsub-eof.tests @@ -0,0 +1,13 @@ +${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 + +${THIS_SH} ./comsub-eof6.sub diff --git a/tests/comsub-eof0.sub b/tests/comsub-eof0.sub new file mode 100644 index 0000000..7490faa --- /dev/null +++ b/tests/comsub-eof0.sub @@ -0,0 +1,6 @@ +# it's only the space before the paren that makes this an error +# when I fix it, it will show up here +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..4bada67 --- /dev/null +++ b/tests/comsub-eof5.sub @@ -0,0 +1,15 @@ +echo $( +cat <<\) +hi +)) + +echo $( +cat <<\EOF +hi +EOF) + +# this is currently an error; if I fix it it will show up here +echo "$( +cat <<\) +hi +))" diff --git a/tests/comsub-eof6.sub b/tests/comsub-eof6.sub new file mode 100644 index 0000000..c0e63dd --- /dev/null +++ b/tests/comsub-eof6.sub @@ -0,0 +1,5 @@ +read foo <<EOF +$(seq 10 +EOF + +echo "$foo" diff --git a/tests/comsub-posix.right b/tests/comsub-posix.right new file mode 100644 index 0000000..037f0ed --- /dev/null +++ b/tests/comsub-posix.right @@ -0,0 +1,100 @@ +abmnopyz +abmnopyz +ab + + +abcd +abcd +mnop +qrst +sh_352.26ax +sh_352.26ay +sh_352.25a sh_352.25b +sh_352.27 ) ) ) +abc +def +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 +x +quoted ) +comment +here-doc with ) +here-doc with \() +here-doc terminated with a parenthesis +' # or a single back- or doublequote +line terminated with a backslash +./comsub-posix1.sub: line 1: syntax error near unexpected token `)' +./comsub-posix1.sub: line 1: `echo $( if x; then echo foo )' +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 +} +bash: -c: line 1: syntax error near unexpected token `done' +bash: -c: line 1: `: $(case x in x) ;; x) done esac)' +bash: -c: line 1: syntax error near unexpected token `done' +bash: -c: line 1: `: $(case x in x) ;; x) done ;; esac)' +bash: -c: line 1: syntax error near unexpected token `esac' +bash: -c: line 1: `: $(case x in x) (esac) esac)' +bash: -c: line 1: syntax error near unexpected token `in' +bash: -c: line 1: `: $(case x in esac|in) foo;; esac)' +bash: -c: line 1: syntax error near unexpected token `done' +bash: -c: line 1: `: $(case x in x) ;; x) done)' +case: -c: line 3: syntax error near unexpected token `esac' +case: -c: line 3: `$( esac ; bar=foo ; echo "$bar")) echo bad 2;;' +ok 2 +inside outside +ok 3 +syntax-error: -c: line 2: syntax error near unexpected token `done' +syntax-error: -c: line 2: `: $(case x in x) ;; x) done ;; esac)' +yes + + + +ab cde diff --git a/tests/comsub-posix.tests b/tests/comsub-posix.tests new file mode 100644 index 0000000..ab7cd29 --- /dev/null +++ b/tests/comsub-posix.tests @@ -0,0 +1,286 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +: ${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 ab$( )cd +echo mn$( +)op +echo qr$( + + )st + +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 $(#a comment with ) +echo def) + +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 # followed by a comment +) + +echo $( + case x in (x) echo x;; esac +) + +echo $( + echo 'quoted )' +) + +echo $( + echo comment # with ) +) + +echo $( +cat <<\eof + here-doc with ) +eof +) + +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 +) + +echo $( + echo line terminated with a backslash # \ +) + +${THIS_SH} ./comsub-posix1.sub +${THIS_SH} ./comsub-posix2.sub +${THIS_SH} ./comsub-posix3.sub + +#${THIS_SH} ./comsub-posix4.sub +${THIS_SH} ./comsub-posix5.sub +${THIS_SH} ./comsub-posix6.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) + +: $(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 +) + +# sanity check for empty comsubs +echo $() +echo $( +) + +echo $( + + ) + +# 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..de6f473 --- /dev/null +++ b/tests/comsub-posix1.sub @@ -0,0 +1,3 @@ +echo $( if x; then echo foo ) + +echo should not see this diff --git a/tests/comsub-posix2.sub b/tests/comsub-posix2.sub new file mode 100644 index 0000000..d556fa9 --- /dev/null +++ b/tests/comsub-posix2.sub @@ -0,0 +1,29 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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..39262b2 --- /dev/null +++ b/tests/comsub-posix3.sub @@ -0,0 +1,35 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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-posix5.sub b/tests/comsub-posix5.sub new file mode 100644 index 0000000..f10e773 --- /dev/null +++ b/tests/comsub-posix5.sub @@ -0,0 +1,70 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +: ${THIS_SH:=./bash} + +# problems with recognzing `esac' after a right paren in a command substitution + +: $(case x in x) esac) +: $(case x in x) ;; x) esac) +# non-reserved word beginning with e +: $(case x in x) ;; x) echo ;; esac) +# reserved word beginning with e +: $(case x in x) ;; x) eval esac ;; esac) + +: $(case x in x ) esac) +: $(case x in x ) ;; x) esac) + +: $(case x in (x) esac) +: $(case x in (x) ;; (x) esac) +: $(case x in (x) ;; x) esac) +: $(case x in (x) (echo a) esac) + +: $(case x in (x) (echo esac) esac) +: $(case x in x) (echo esac) esac) + +# these errors should be caught sooner +${THIS_SH} -c ': $(case x in x) ;; x) done esac)' bash +${THIS_SH} -c ': $(case x in x) ;; x) done ;; esac)' bash +${THIS_SH} -c ': $(case x in x) (esac) esac)' bash + +# these are not errors +: $(case x in x) ;; x) eval done ;; esac) + +# these are just ridiculous +: $(case x in (x) a() { echo a; } esac) +: $(case x in (x) if :; then echo a; fi esac) +: $(case x in (x) { echo a; } esac) +: $(case x in (x) while false; do echo a; done esac) +: $(case x in (x) case y in (y) echo a;; esac esac) +: $(case x in (x) case y in (y) echo a;; esac ;; (y) foo ;; esac) + +: $(case x in x) a() { echo a; } esac) +: $(case x in x) if :; then echo a; fi esac) +: $(case x in x) { echo a; } esac) +: $(case x in x) while false; do echo a; done esac) +: $(case x in x) case y in (y) echo a;; esac esac) +: $(case x in x) case y in (y) echo a;; esac ;; y) foo ;; esac) +: $(case x in x) case y in y) echo a;; esac ;; y) foo ;; esac) + +: $(case ni in esac) +: $(case in in esac) + +: $(case x in in|esac) foo;; esac) +: $(case esac in (esac) echo esac;; esac) +: $(case k in else|done|time|esac) for f in 1 2 3 ; do :; done esac) + +# this is an error +${THIS_SH} -c ': $(case x in esac|in) foo;; esac)' bash + +${THIS_SH} -c ': $(case x in x) ;; x) done)' bash diff --git a/tests/comsub-posix6.sub b/tests/comsub-posix6.sub new file mode 100644 index 0000000..212ad20 --- /dev/null +++ b/tests/comsub-posix6.sub @@ -0,0 +1,43 @@ +: ${THIS_SH:=./bash} + +# comsub should not inherit PST_COMPASSIGN + +C=($(echo "${A[@]}" | \ + (while read -d ' ' i; do + C=(${C/ ${i%% *} / }) + done + echo ${C[@]}))) + +# comsub should not inherit PST_CASEPAT + +${THIS_SH} -c ' +case foo in +$( esac ; bar=foo ; echo "$bar")) echo bad 2;; +*) echo ok 2;; +esac + +echo we should not see this' case + +# comsub should not inherit PST_SUBSHELL + +${THIS_SH} -c '( case foo in + ( $(echo foo | cat )) echo ok 2;; + *) echo bad 2;; + esac + + echo $( echo inside ) outside )' subshell + +# comsub should not inherit PST_REDIRLIST + +${THIS_SH} -c ' +{fd}</dev/null {fd2}<$(foo=/dev/null ; echo $foo) exec +case $fd2 in +[0-9]*) echo ok 3 ;; +*) echo bad 3 ;; +esac' redirlist + +# comsub should exit on syntax error while parsing +${THIS_SH} -c ' +: $(case x in x) ;; x) done ;; esac) + +echo after syntax error' syntax-error diff --git a/tests/comsub.right b/tests/comsub.right new file mode 100644 index 0000000..eae8c3b --- /dev/null +++ b/tests/comsub.right @@ -0,0 +1,79 @@ +./comsub.tests: line 20: 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> +nested +#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 +ok 1 +ok 2 +ok 3 +ok 4 +ok 5 +ok 6 +ok 7 +ok 9 +ok 8 +ok 8 +Mon Aug 29 20:03:02 EDT 2022 +post foo +Mon Aug 29 20:03:02 EDT 2022 +post foo1 +Mon Aug 29 20:03:02 EDT 2022 +Mon Aug 29 20:03:02 EDT 2022 after +7 +Mon Aug 29 20:03:02 EDT 2022 +hey after x +./comsub6.sub: line 40: syntax error near unexpected token `)' +./comsub6.sub: line 40: `math1)' diff --git a/tests/comsub.tests b/tests/comsub.tests new file mode 100644 index 0000000..698ce30 --- /dev/null +++ b/tests/comsub.tests @@ -0,0 +1,84 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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) +} + +echo $( +echo $( +echo $(echo $( echo nested ) +) +) +) + +${THIS_SH} ./comsub1.sub +${THIS_SH} ./comsub2.sub +${THIS_SH} ./comsub3.sub +${THIS_SH} ./comsub4.sub +${THIS_SH} ./comsub5.sub +${THIS_SH} ./comsub6.sub diff --git a/tests/comsub1.sub b/tests/comsub1.sub new file mode 100644 index 0000000..ca72243 --- /dev/null +++ b/tests/comsub1.sub @@ -0,0 +1,73 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +: $(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..757fbca --- /dev/null +++ b/tests/comsub3.sub @@ -0,0 +1,44 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..e7a1c55 --- /dev/null +++ b/tests/comsub4.sub @@ -0,0 +1,40 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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/comsub5.sub b/tests/comsub5.sub new file mode 100644 index 0000000..cc83374 --- /dev/null +++ b/tests/comsub5.sub @@ -0,0 +1,51 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +# this is a new feature: expanding aliases when initially parsing command +# substitutions. required by posix, so enabled in posix mode. default mode +# stays backwards compatible. + +shopt -s expand_aliases +set -o posix + +alias switch=case + +switch foo in foo) echo ok 1;; esac + +echo $( switch foo in foo) echo ok 2;; esac ) +echo "$( switch foo in foo) echo ok 3;; esac )" + +echo $( switch foo in (foo) echo ok 4;; esac ) +echo "$( switch foo in (foo) echo ok 5;; esac )" + +alias nest='(' + +echo $( nest echo ok 6 ) ) +echo "$( nest echo ok 7 ) )" + +alias short='echo ok 8 )' + +alias DO='{ ' +alias DONE='}' +got=$(DO +echo ok 9; DONE) +echo "$got" + +echo $( short +echo "$( short " + +# remember that short" won't work because you start a new quoting context +# inside $( and the token (`short') won't be delimited by the ending double +# quote, so there's no opportunity to perform the alias expansion that would +# terminate the command substitution diff --git a/tests/comsub6.sub b/tests/comsub6.sub new file mode 100644 index 0000000..d2b02bf --- /dev/null +++ b/tests/comsub6.sub @@ -0,0 +1,40 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +DATE='Mon Aug 29 20:03:02 EDT 2022' +shopt -s expand_aliases + +alias foo='echo $(echo $DATE)' +alias foo1='echo $(echo $DATE) ' + +foo +echo post foo + +foo1 +echo post foo1 + +alias comsub0='echo $(echo $DATE' +comsub0) +comsub0 ) after + +alias math0='echo $(( 4+3 )' +math0) + +alias x='VAR=$(echo hey)' +x +foo + +echo $VAR after x + +alias math1='echo $( date )' +math1) diff --git a/tests/cond-regexp1.sub b/tests/cond-regexp1.sub new file mode 100644 index 0000000..1ba9197 --- /dev/null +++ b/tests/cond-regexp1.sub @@ -0,0 +1,69 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..4da0a88 --- /dev/null +++ b/tests/cond-regexp2.sub @@ -0,0 +1,45 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +[[ "\\" =~ ["."] ]] && 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..d939548 --- /dev/null +++ b/tests/cond-regexp3.sub @@ -0,0 +1,86 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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..a72a153 --- /dev/null +++ b/tests/cond.right @@ -0,0 +1,142 @@ +returns: 0 +returns: 0 +returns: 1 +returns: 0 +1 +0 +1 +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 122: [[: 4+: syntax error: operand expected (error token is "+") +returns: 1 +returns: 0 +returns: 0 +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 100644 index 0000000..c0747e9 --- /dev/null +++ b/tests/cond.tests @@ -0,0 +1,232 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# +# 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: $? + +# ! toggles on and off rather than just setting an `invert result' flag +# this differs from ksh93 +[[ ! 1 -eq 1 ]]; echo $? +[[ ! ! 1 -eq 1 ]]; echo $? + +[[ ! ! ! 1 -eq 1 ]]; echo $? +[[ ! ! ! ! 1 -eq 1 ]]; echo $? + +# 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: $? + +[[ "$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 + +# allow reserved words after a conditional command just because +if [[ str ]] then [[ str ]] fi + +${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..a735932 --- /dev/null +++ b/tests/coproc.tests @@ -0,0 +1,78 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +: ${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..269136d --- /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..e598f8c --- /dev/null +++ b/tests/cprint.tests @@ -0,0 +1,80 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# +# 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..6e2194a --- /dev/null +++ b/tests/dbg-support.right @@ -0,0 +1,371 @@ +debug lineno: 74 main +debug lineno: 77 main +FUNCNAME main +debug lineno: 81 main +debug lineno: 30 fn1 +debug lineno: 31 fn1 +LINENO 31 +debug lineno: 32 fn1 +LINENO 32 +debug lineno: 33 fn1 +BASH_SOURCE[0] ./dbg-support.tests +debug lineno: 34 fn1 +FUNCNAME[0] fn1 +debug lineno: 35 fn1 +debug lineno: 35 fn1 81 ./dbg-support.tests +debug lineno: 36 fn1 +debug lineno: 36 fn1 81 main ./dbg-support.tests +debug lineno: 37 fn1 +debug lineno: 37 fn1 +debug lineno: 38 fn1 +./dbg-support.tests: line 38: caller: foo: invalid number +caller: usage: caller [expr] +debug lineno: 38 fn1 +debug lineno: 30 fn1 +debug lineno: 25 print_return_trap +debug lineno: 26 print_return_trap +return lineno: 30 fn1 +debug lineno: 27 print_return_trap +debug lineno: 82 main +debug lineno: 41 fn2 +debug lineno: 42 fn2 +fn2 here. Calling fn1... +debug lineno: 43 fn2 +debug lineno: 30 fn1 +debug lineno: 31 fn1 +LINENO 31 +debug lineno: 32 fn1 +LINENO 32 +debug lineno: 33 fn1 +BASH_SOURCE[0] ./dbg-support.tests +debug lineno: 34 fn1 +FUNCNAME[0] fn1 +debug lineno: 35 fn1 +debug lineno: 35 fn1 43 ./dbg-support.tests +debug lineno: 36 fn1 +debug lineno: 36 fn1 43 fn2 ./dbg-support.tests +debug lineno: 37 fn1 +debug lineno: 37 fn1 82 main ./dbg-support.tests +debug lineno: 38 fn1 +./dbg-support.tests: line 38: caller: foo: invalid number +caller: usage: caller [expr] +debug lineno: 38 fn1 +debug lineno: 30 fn1 +debug lineno: 25 print_return_trap +debug lineno: 26 print_return_trap +return lineno: 30 fn1 +debug lineno: 27 print_return_trap +debug lineno: 41 fn2 +debug lineno: 25 print_return_trap +debug lineno: 26 print_return_trap +return lineno: 41 fn2 +debug lineno: 27 print_return_trap +debug lineno: 83 main +debug lineno: 46 fn3 +debug lineno: 47 fn3 +LINENO 47 +debug lineno: 48 fn3 +BASH_SOURCE[0] ./dbg-support.tests +debug lineno: 51 fn3 +debug lineno: 52 fn3 +debug lineno: 53 fn3 +debug lineno: 53 fn3 +debug lineno: 54 fn3 +debug lineno: 55 fn3 +debug lineno: 56 fn3 +fn3 called from file `./dbg-support.tests' at line 0 +debug lineno: 53 fn3 +debug lineno: 53 fn3 +debug lineno: 54 fn3 +debug lineno: 55 fn3 +debug lineno: 55 fn3 +debug lineno: 56 fn3 +main called from file `./dbg-support.tests' at line 0 +debug lineno: 53 fn3 +debug lineno: 53 fn3 +debug lineno: 59 fn3 +debug lineno: 31 source +SOURCED LINENO 31 +debug lineno: 32 source +SOURCED BASH_SOURCE[0] ./dbg-support.sub +debug lineno: 33 source +debug lineno: 16 sourced_fn +debug lineno: 17 sourced_fn +debug lineno: 18 sourced_fn +SOURCED FN LINENO 18 +debug lineno: 21 sourced_fn +debug lineno: 22 sourced_fn +debug lineno: 23 sourced_fn +debug lineno: 23 sourced_fn +debug lineno: 24 sourced_fn +debug lineno: 25 sourced_fn +debug lineno: 26 sourced_fn +FUNCNAME[0]: sourced_fn called from ./dbg-support.sub at line 33 +debug lineno: 23 sourced_fn +debug lineno: 23 sourced_fn +debug lineno: 24 sourced_fn +debug lineno: 25 sourced_fn +debug lineno: 26 sourced_fn +FUNCNAME[1]: source called from ./dbg-support.tests at line 59 +debug lineno: 23 sourced_fn +debug lineno: 23 sourced_fn +debug lineno: 24 sourced_fn +debug lineno: 25 sourced_fn +debug lineno: 26 sourced_fn +FUNCNAME[2]: fn3 called from ./dbg-support.tests at line 83 +debug lineno: 23 sourced_fn +debug lineno: 23 sourced_fn +debug lineno: 24 sourced_fn +debug lineno: 25 sourced_fn +debug lineno: 25 sourced_fn +debug lineno: 26 sourced_fn +FUNCNAME[3]: main called from ./dbg-support.tests at line 0 +debug lineno: 23 sourced_fn +debug lineno: 23 sourced_fn +debug lineno: 16 sourced_fn +debug lineno: 25 print_return_trap +debug lineno: 26 print_return_trap +return lineno: 16 sourced_fn +debug lineno: 27 print_return_trap +debug lineno: 59 fn3 +debug lineno: 25 print_return_trap +debug lineno: 26 print_return_trap +return lineno: 59 fn3 +debug lineno: 27 print_return_trap +debug lineno: 46 fn3 +debug lineno: 25 print_return_trap +debug lineno: 26 print_return_trap +return lineno: 46 fn3 +debug lineno: 27 print_return_trap +debug lineno: 84 main +debug lineno: 31 source +SOURCED LINENO 31 +debug lineno: 32 source +SOURCED BASH_SOURCE[0] ./dbg-support.sub +debug lineno: 33 source +debug lineno: 16 sourced_fn +debug lineno: 17 sourced_fn +debug lineno: 18 sourced_fn +SOURCED FN LINENO 18 +debug lineno: 21 sourced_fn +debug lineno: 22 sourced_fn +debug lineno: 23 sourced_fn +debug lineno: 23 sourced_fn +debug lineno: 24 sourced_fn +debug lineno: 25 sourced_fn +debug lineno: 26 sourced_fn +FUNCNAME[0]: sourced_fn called from ./dbg-support.sub at line 33 +debug lineno: 23 sourced_fn +debug lineno: 23 sourced_fn +debug lineno: 24 sourced_fn +debug lineno: 25 sourced_fn +debug lineno: 26 sourced_fn +FUNCNAME[1]: source called from ./dbg-support.tests at line 84 +debug lineno: 23 sourced_fn +debug lineno: 23 sourced_fn +debug lineno: 24 sourced_fn +debug lineno: 25 sourced_fn +debug lineno: 25 sourced_fn +debug lineno: 26 sourced_fn +FUNCNAME[2]: main called from ./dbg-support.tests at line 0 +debug lineno: 23 sourced_fn +debug lineno: 23 sourced_fn +debug lineno: 16 sourced_fn +debug lineno: 25 print_return_trap +debug lineno: 26 print_return_trap +return lineno: 16 sourced_fn +debug lineno: 27 print_return_trap +debug lineno: 84 main +debug lineno: 25 print_return_trap +debug lineno: 26 print_return_trap +return lineno: 84 main +debug lineno: 27 print_return_trap +debug lineno: 87 main +debug lineno: 90 main +LINENO 31 +LINENO 32 +BASH_SOURCE[0] ./dbg-support.tests +FUNCNAME[0] fn1 +90 ./dbg-support.tests +90 main ./dbg-support.tests + +./dbg-support.tests: line 38: caller: foo: invalid number +caller: usage: caller [expr] + +debug lineno: 91 main +fn2 here. Calling fn1... +LINENO 31 +LINENO 32 +BASH_SOURCE[0] ./dbg-support.tests +FUNCNAME[0] fn1 +43 ./dbg-support.tests +43 fn2 ./dbg-support.tests +91 main ./dbg-support.tests +./dbg-support.tests: line 38: caller: foo: invalid number +caller: usage: caller [expr] + +debug lineno: 92 main +LINENO 47 +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 31 +SOURCED BASH_SOURCE[0] ./dbg-support.sub +SOURCED FN LINENO 18 +FUNCNAME[0]: sourced_fn called from ./dbg-support.sub at line 33 +FUNCNAME[1]: source called from ./dbg-support.tests at line 59 +FUNCNAME[2]: fn3 called from ./dbg-support.tests at line 92 +FUNCNAME[3]: main called from ./dbg-support.tests at line 0 +debug lineno: 93 main +fn4 here. Calling fn3... +LINENO 47 +BASH_SOURCE[0] ./dbg-support.tests +fn3 called from file `./dbg-support.tests' at line 93 +fn4 called from file `./dbg-support.tests' at line 0 +main called from file `./dbg-support.tests' at line 0 +SOURCED LINENO 31 +SOURCED BASH_SOURCE[0] ./dbg-support.sub +SOURCED FN LINENO 18 +FUNCNAME[0]: sourced_fn called from ./dbg-support.sub at line 33 +FUNCNAME[1]: source called from ./dbg-support.tests at line 59 +FUNCNAME[2]: fn3 called from ./dbg-support.tests at line 64 +FUNCNAME[3]: fn4 called from ./dbg-support.tests at line 93 +FUNCNAME[4]: main called from ./dbg-support.tests at line 0 +debug lineno: 94 main +SOURCED LINENO 31 +SOURCED BASH_SOURCE[0] ./dbg-support.sub +SOURCED FN LINENO 18 +FUNCNAME[0]: sourced_fn called from ./dbg-support.sub at line 33 +FUNCNAME[1]: source called from ./dbg-support.tests at line 94 +FUNCNAME[2]: main called from ./dbg-support.tests at line 0 +return lineno: 94 main +debug lineno: 97 main +debug lineno: 100 main +debug lineno: 31 source +SOURCED LINENO 31 +debug lineno: 32 source +SOURCED BASH_SOURCE[0] ./dbg-support.sub +debug lineno: 33 source +debug lineno: 16 sourced_fn +debug lineno: 17 sourced_fn +debug lineno: 18 sourced_fn +SOURCED FN LINENO 18 +debug lineno: 21 sourced_fn +debug lineno: 22 sourced_fn +debug lineno: 23 sourced_fn +debug lineno: 23 sourced_fn +debug lineno: 24 sourced_fn +debug lineno: 25 sourced_fn +debug lineno: 26 sourced_fn +FUNCNAME[0]: sourced_fn called from ./dbg-support.sub at line 33 +debug lineno: 23 sourced_fn +debug lineno: 23 sourced_fn +debug lineno: 24 sourced_fn +debug lineno: 25 sourced_fn +debug lineno: 26 sourced_fn +FUNCNAME[1]: source called from ./dbg-support.tests at line 100 +debug lineno: 23 sourced_fn +debug lineno: 23 sourced_fn +debug lineno: 24 sourced_fn +debug lineno: 25 sourced_fn +debug lineno: 25 sourced_fn +debug lineno: 26 sourced_fn +FUNCNAME[2]: main called from ./dbg-support.tests at line 0 +debug lineno: 23 sourced_fn +debug lineno: 23 sourced_fn +debug lineno: 16 sourced_fn +debug lineno: 25 print_return_trap +debug lineno: 26 print_return_trap +return lineno: 16 sourced_fn +debug lineno: 27 print_return_trap +debug lineno: 100 main +debug lineno: 25 print_return_trap +debug lineno: 26 print_return_trap +return lineno: 100 main +debug lineno: 27 print_return_trap +debug lineno: 101 main +debug lineno: 104 main +debug lineno: 104 main +debug lineno: 105 main +debug lineno: 108 main +debug lineno: 104 main +debug lineno: 104 main +debug lineno: 105 main +debug lineno: 108 main +debug lineno: 104 main +debug lineno: 104 main +debug lineno: 105 main +debug lineno: 106 main +Hit 2 +debug lineno: 108 main +debug lineno: 104 main +debug lineno: 104 main +debug lineno: 114 main +SOURCED FN LINENO 18 FUNCNAME[0]: sourced_fn called from ./dbg-support.tests at line 114 FUNCNAME[1]: main called from ./dbg-support.tests at line 0 +debug lineno: 115 main +SOURCED FN LINENO 18 FUNCNAME[0]: sourced_fn called from ./dbg-support.tests at line 115 FUNCNAME[1]: main called from ./dbg-support.tests at line 0 +debug lineno: 116 main +debug lineno: 117 main +SOURCED FN LINENO 18 +FUNCNAME[0]: sourced_fn called from ./dbg-support.tests at line 117 +FUNCNAME[1]: main called from ./dbg-support.tests at line 0 +debug lineno: 121 main +debug lineno: 122 main +debug lineno: 16 sourced_fn +debug lineno: 17 sourced_fn +debug lineno: 18 sourced_fn +SOURCED FN LINENO 18 +debug lineno: 21 sourced_fn +debug lineno: 22 sourced_fn +debug lineno: 23 sourced_fn +debug lineno: 23 sourced_fn +debug lineno: 24 sourced_fn +debug lineno: 25 sourced_fn +debug lineno: 26 sourced_fn +FUNCNAME[0]: sourced_fn called from ./dbg-support.tests at line 122 +debug lineno: 23 sourced_fn +debug lineno: 23 sourced_fn +debug lineno: 24 sourced_fn +debug lineno: 25 sourced_fn +debug lineno: 25 sourced_fn +debug lineno: 26 sourced_fn +FUNCNAME[1]: main called from ./dbg-support.tests at line 0 +debug lineno: 23 sourced_fn +debug lineno: 23 sourced_fn +debug lineno: 16 sourced_fn +debug lineno: 25 print_return_trap +debug lineno: 26 print_return_trap +return lineno: 16 sourced_fn +debug lineno: 27 print_return_trap +debug lineno: 125 main +debug lineno: 130 main +debug lineno: 134 main +got it +debug lineno: 142 main +debug lineno: 143 main +debug lineno: 144 main +debug lineno: 143 main +debug lineno: 144 main +debug lineno: 142 main +debug lineno: 143 main +debug lineno: 144 main +debug lineno: 143 main +debug lineno: 144 main +debug lineno: 148 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 +39 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..8c82c80 --- /dev/null +++ b/tests/dbg-support.sub @@ -0,0 +1,39 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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 100644 index 0000000..b4a58e4 --- /dev/null +++ b/tests/dbg-support.tests @@ -0,0 +1,148 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +# +# 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 +} + +# +# 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 command 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 diff --git a/tests/dbg-support2.right b/tests/dbg-support2.right new file mode 100644 index 0000000..5727d1f --- /dev/null +++ b/tests/dbg-support2.right @@ -0,0 +1,7 @@ +lineno: 29 (18) main +lineno: 30 (18) main +x is 1 +lineno: 31 (18) main +lineno: 32 (18) main +lineno: 33 (18) main +x is 1 diff --git a/tests/dbg-support2.tests b/tests/dbg-support2.tests new file mode 100644 index 0000000..c33251d --- /dev/null +++ b/tests/dbg-support2.tests @@ -0,0 +1,33 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# +# 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" diff --git a/tests/dbg-support3.sub b/tests/dbg-support3.sub new file mode 100644 index 0000000..146831f --- /dev/null +++ b/tests/dbg-support3.sub @@ -0,0 +1,52 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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 100644 index 0000000..721eea1 --- /dev/null +++ b/tests/dollar-at-star @@ -0,0 +1,332 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +# 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 + +# more tests of the expansions of $@ and $* (and their array equivalents) +# with different values for IFS +${THIS_SH} ./dollar-at-star9.sub + +# tests for expansions of "$*" and "$@" and their array equivalents when $1 == '' +# and we're using the POSIX word expansions +${THIS_SH} ./dollar-at-star10.sub +${THIS_SH} ./dollar-at-star11.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 + +# more tests for expansions of $* when not splitting with IFS set or unset and +# null strings as the positional parameters +${THIS_SH} ./dollar-star10.sub + +exit 0 diff --git a/tests/dollar-at-star1.sub b/tests/dollar-at-star1.sub new file mode 100644 index 0000000..ef15efc --- /dev/null +++ b/tests/dollar-at-star1.sub @@ -0,0 +1,36 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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-star10.sub b/tests/dollar-at-star10.sub new file mode 100644 index 0000000..6b52b01 --- /dev/null +++ b/tests/dollar-at-star10.sub @@ -0,0 +1,66 @@ +# checks for array variables and positional parameter expansions losing quoted +# null string expansions -- problem through bash-5.1 + +set -- '' +myvar[0]= +a="${myvar[*]}" + +recho "$*" +recho "${*}" + +recho "${a}" +recho "${myvar[*]}" + +recho "${a:+nonnull}" +recho "${myvar[*]:+nonnull}" + +a="${myvar[@]}" + +recho "$@" +recho "${@}" + +recho "${a}" +recho "${myvar[@]}" + +recho "${a:+nonnull}" +recho "${myvar[@]:+nonnull}" + +# check to make sure literal CTLNULs are handled correctly +set -- $'\x7f' + +recho "$@" +recho "${@}" +recho "${@:+nonnull}" + +recho "$*" +recho "${*}" +recho "${*:+nonnull}" + +shift $# + +# these should echo nothing +recho "${@}" +recho "${@:+nonnull}" + +unset -v a + +# make sure that other null expansions result in null strings where appropriate +set -- '' +a[0]= + +recho "$*"$x +recho "${*}"$x + +recho "$@"$x +recho "${@}"$x + +recho "${a[*]}"$x +recho "${a[@]}"$x + + +recho "$@"$x +recho "${@}"$x + +recho "${a[*]}" +recho "${a[@]}" + diff --git a/tests/dollar-at-star11.sub b/tests/dollar-at-star11.sub new file mode 100644 index 0000000..b7a6ec4 --- /dev/null +++ b/tests/dollar-at-star11.sub @@ -0,0 +1,80 @@ +a[0]='/' +set -- / + +# these should all result in the empty (null) string + +recho "${a[0]%?}" +recho "${a[*]%?}" +recho "${a[@]%?}" + +recho "${*%?}" +recho "${@%?}" + +recho "${a[0]#?}" +recho "${a[*]#?}" +recho "${a[@]#?}" + +recho "${*#?}" +recho "${@#?}" + +recho "${a[0]/\//}" +recho "${a[*]/\//}" +recho "${a[@]/\//}" + +recho "${*/\//}" +recho "${@/\//}" + +recho "${a[0]:1:1}" +# these next four will all echo / + +# arrays are zero-based +recho "${a[*]:0:1}" +recho "${a[@]:0:1}" +# but the positional parameters start at 1 +recho "${*:1:1}" +recho "${@:1:1}" + +a[0]='' +set -- '' + +# arrays are zero-based +recho "${a[*]:0:1}" +recho "${a[@]:0:1}" + +recho "${*:1:1}" +recho "${@:1:1}" + +# these should all result in the empty (null) string, or quoted as such + +recho "${a[0]@Q}" +recho "${a[*]@Q}" +recho "${a[@]@Q}" + +recho "${*@Q}" +recho "${@@Q}" + +recho "${a[0]@L}" +recho "${a[*]@L}" +recho "${a[@]@L}" + +recho "${*@L}" +recho "${@@L}" + +# examples from the bug report +unset -v a + +a[0]='/' +for i in "${a[@]%/}"; do recho "$i"; done + +a[0]='' +for i in "${a[@]}"; do recho "$i"; done + +a[0]='/' +a[1]="//" +for i in "${a[@]%/}"; do recho "$i"; done + +unset -v x y +x=('/') +y=("${x[@]%/}") + +echo "${#x[@]}:${#y[@]}" diff --git a/tests/dollar-at-star2.sub b/tests/dollar-at-star2.sub new file mode 100644 index 0000000..64ab1eb --- /dev/null +++ b/tests/dollar-at-star2.sub @@ -0,0 +1,220 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..da05444 --- /dev/null +++ b/tests/dollar-at-star3.sub @@ -0,0 +1,57 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..9f7da8e --- /dev/null +++ b/tests/dollar-at-star4.sub @@ -0,0 +1,112 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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..d07c61a --- /dev/null +++ b/tests/dollar-at-star5.sub @@ -0,0 +1,66 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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..09353b8 --- /dev/null +++ b/tests/dollar-at-star6.sub @@ -0,0 +1,42 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..e4e63b7 --- /dev/null +++ b/tests/dollar-at-star7.sub @@ -0,0 +1,38 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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-at-star9.sub b/tests/dollar-at-star9.sub new file mode 100644 index 0000000..e5062f7 --- /dev/null +++ b/tests/dollar-at-star9.sub @@ -0,0 +1,278 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +IFS=$' \t\n' # or any other IFS +set -- '' +recho ${v= "$*" } +recho "$v" +unset -v v + +IFS='' +set -- '' '' +recho ${v= "$*" } +recho "$v" +unset -v v + +IFS=$' \t\n' # or any other IFS +unset -v v + +set -- '' +recho ${v= "$@" } +recho "$v" +unset v +recho ${v= $@ } +recho "$v" +unset v +recho ${v= $@"" } +recho "$v" +unset v +recho ${v= ${@} } +recho "$v" +unset v +recho ${v= ${@}"" } +recho "$v" +unset v + +set -- '' '' +recho ${v= $@ } +recho "$v" +unset v +recho ${v= "$@" } +recho "$v" +unset v +recho "${v= $@}" +recho "$v" +unset v +recho ${v= "$@"} +recho "$v" +unset v + +IFS= + +set -- X +X=X + +recho ${0+ "$@" } +recho ${0+ $@ } +recho ${0+ $* } + +recho ${0+ "$X" } +recho ${0+ $X } +recho ${0+ $X } + +recho ${0+ "$@" } +recho "$Y" +unset Y +recho ${0+ $@ } +recho "$Y" +unset Y +recho ${0+ $* } +recho "$Y" +unset Y + +recho ${Y:= "$X" } +recho "$Y" +unset Y +recho ${Y:= $X } +recho "$Y" +unset Y +recho ${Y:= $X } +recho "$Y" +unset Y + +IFS= + +unset -v X Y + +set -- X Y +X='X Y' + +recho ${0+ "$@" } +recho ${0+ $@ } +recho ${0+ $* } + +recho ${0+ "$X" } +recho ${0+ $X } +recho ${0+ $X } + +recho ${Y:= "$@" } +recho "$Y" +unset Y +recho ${Y:= $@ } +recho "$Y" +unset Y +recho ${Y:= $* } +recho "$Y" +unset Y + +recho ${Y:= "$X" } +recho "$Y" +unset Y +recho ${Y:= $X } +recho "$Y" +unset Y +recho ${Y:= $X } +recho "$Y" +unset Y + +IFS='' +set -- ' X ' + +unset x y + +x=$* +y=${*:1} + +recho "$x" +recho "$y" + +unset x y + +recho ${x=$*} +recho ${y=${*:1}} + +set -- b a +declare -A A=([b]= [a]=) + +x=$* +y=${!A[*]} + +unset A + +recho "$x" +recho "$y" + +unset x y + +recho ${x=$*} +recho ${y=${!A[*]}} + +unset x y + +recho ${x-$*} +recho ${y-${!A[*]}} # this isn't right yet + +IFS=: +set -- a b +ind=* + +unset x y + +x=$* +y=${!ind} + +recho "$x" +recho "$y" + +unset x y + +recho ${x-$*} +recho ${y-${!ind}} # this isn't right yet + +unset x y + +recho ${x=$*} +recho ${y=${!ind}} + +set -- ' X ' +IFS=$' \t\n' + +x=$* +y=${!ind}; + +recho "$x" +recho "$y" + +IFS='' +x=$* +y=${!ind} + +recho "$x" +recho "$y" + +IFS=: +set -- a b +ind=* + +unset x y + +recho ${x-$*} +recho ${y-${!ind}} # this isn't right yet + +unset x y + +recho ${x=$*} +recho ${y=${!ind}} + +set -- ' X ' +IFS=$' \t\n' + +unset x y + +x=$* +y=${!ind}; + +recho "$x" +recho "$y" + +IFS='' +x=$* +y=${!ind} + +recho "$x" +recho "$y" + +IFS='' +set -- $'\177' + +unset -v var + +recho "${*:1}" +var=${*:1} +recho "$var" + +unset var +recho ${var=${*:1}} +recho "$var" + +declare -a a=($'\177') + +unset var +var=${a[*]:0} +recho "$var" + +unset var +recho ${var=${a[*]:0}} +unset var + +set -- $'\177' +ind='*' + +recho $* +var=${!ind} +recho "$var" + +unset var +recho ${var=${!ind}} +recho "$var" + +declare -A A=([0]=$'\177') + +unset var +var=${A[*]:0} +recho "$var" + +# this isn't really right yet +unset var +recho ${var=${A[*]:0}} +recho "$var" diff --git a/tests/dollar-at1.sub b/tests/dollar-at1.sub new file mode 100644 index 0000000..c5079d6 --- /dev/null +++ b/tests/dollar-at1.sub @@ -0,0 +1,42 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..16defbd --- /dev/null +++ b/tests/dollar-at2.sub @@ -0,0 +1,32 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..9b26c39 --- /dev/null +++ b/tests/dollar-at5.sub @@ -0,0 +1,95 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..791fd89 --- /dev/null +++ b/tests/dollar-at6.sub @@ -0,0 +1,43 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..cde1164 --- /dev/null +++ b/tests/dollar-at7.sub @@ -0,0 +1,59 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..3e5ec36 --- /dev/null +++ b/tests/dollar-star1.sub @@ -0,0 +1,44 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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-star10.sub b/tests/dollar-star10.sub new file mode 100644 index 0000000..fce9ec1 --- /dev/null +++ b/tests/dollar-star10.sub @@ -0,0 +1,92 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +oIFS=$IFS + +set -- '' + +unset v +recho ${v= ''} +recho $v +unset v +recho ${v=''} +recho $v +unset v +recho ${v= $*} +recho $v +unset v +recho ${v=$*} +recho $v +unset v +recho ${v='' } +recho $v +unset v +recho ${v= '' } +recho $v +unset v +recho ${v=$* } +recho $v +unset v +recho ${v= $* } +recho $v + +unset IFS + +unset v +recho ${v= ''} +recho $v +unset v +recho ${v=''} +recho $v +unset v +recho ${v= $*} +recho $v +unset v +recho ${v=$*} +recho $v +unset v +recho ${v='' } +recho $v +unset v +recho ${v= '' } +recho $v +unset v +recho ${v=$* } +recho $v +unset v +recho ${v= $* } +recho $v + +unset -v v +IFS=$oIFS + +# This shouldn't output anything +set -- '' '' + +unset -v v +recho ${v=$*} +unset -v v +recho ${v= $*} +unset -v v +recho ${v=$* } +unset -v v +recho ${v= $* } + +unset -v v IFS +recho ${v=$*} +unset -v v +recho ${v= $*} +unset -v v +recho ${v= $* } +unset -v v +recho ${v= $*} diff --git a/tests/dollar-star2.sub b/tests/dollar-star2.sub new file mode 100644 index 0000000..78e00a0 --- /dev/null +++ b/tests/dollar-star2.sub @@ -0,0 +1,39 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..a6ef09f --- /dev/null +++ b/tests/dollar-star3.sub @@ -0,0 +1,31 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..abd8bcc --- /dev/null +++ b/tests/dollar-star5.sub @@ -0,0 +1,29 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..095ec04 --- /dev/null +++ b/tests/dollar-star6.sub @@ -0,0 +1,32 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..db352bf --- /dev/null +++ b/tests/dollar-star7.sub @@ -0,0 +1,43 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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..e626564 --- /dev/null +++ b/tests/dollar-star8.sub @@ -0,0 +1,34 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..d46de46 --- /dev/null +++ b/tests/dollar-star9.sub @@ -0,0 +1,59 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..10c5cca --- /dev/null +++ b/tests/dollar.right @@ -0,0 +1,744 @@ +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 $@ +argv[1] = <> +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 +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] = < X > +argv[1] = < X > +argv[1] = < X > +argv[1] = < X > +argv[1] = < X > +argv[1] = < X > +argv[1] = <> +argv[1] = < X > +argv[1] = <> +argv[1] = < X > +argv[1] = <> +argv[1] = < X > +argv[1] = < X > +argv[1] = < X > +argv[1] = < X > +argv[1] = < X > +argv[1] = < X > +argv[1] = < X> +argv[2] = <Y > +argv[1] = < X> +argv[2] = <Y > +argv[1] = < X> +argv[2] = <Y > +argv[1] = < X Y > +argv[1] = < X Y > +argv[1] = < X Y > +argv[1] = < X Y > +argv[1] = < X Y > +argv[1] = < X Y > +argv[1] = < X Y > +argv[1] = < XY > +argv[1] = < XY > +argv[1] = < X Y > +argv[1] = < X Y > +argv[1] = < X Y > +argv[1] = < X Y > +argv[1] = < X Y > +argv[1] = < X Y > +argv[1] = < X > +argv[1] = < X > +argv[1] = < X > +argv[1] = < X > +argv[1] = <ba> +argv[1] = <ba> +argv[1] = <ba> +argv[1] = <b> +argv[2] = <a> +argv[1] = <a:b> +argv[1] = <a:b> +argv[1] = <a> +argv[2] = <b> +argv[1] = <a> +argv[2] = <b> +argv[1] = <a> +argv[2] = <b> +argv[1] = <a> +argv[2] = <b> +argv[1] = < X > +argv[1] = < X > +argv[1] = < X > +argv[1] = < X > +argv[1] = <a> +argv[2] = <b> +argv[1] = <a> +argv[2] = <b> +argv[1] = <a> +argv[2] = <b> +argv[1] = <a> +argv[2] = <b> +argv[1] = < X > +argv[1] = < X > +argv[1] = < X > +argv[1] = < X > +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] = <nonnull> +argv[1] = <^?> +argv[1] = <^?> +argv[1] = <nonnull> +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] = <> +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] = </> +1:1 +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..8f9d38c --- /dev/null +++ b/tests/dstack.right @@ -0,0 +1,55 @@ +./dstack.tests: line 19: pushd: /tmp/xxx-notthere: No such file or directory +./dstack.tests: line 22: pushd: no other directory +./dstack.tests: line 23: popd: directory stack empty +./dstack.tests: line 26: pushd: -m: invalid number +pushd: usage: pushd [-n] [+N | -N | dir] +./dstack.tests: line 27: popd: -m: invalid number +popd: usage: popd [-n] [+N | -N] +./dstack.tests: line 28: dirs: -m: invalid number +dirs: usage: dirs [-clpv] [+N] [-N] +./dstack.tests: line 29: 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 71: dirs: 9: directory stack index out of range +./dstack.tests: line 71: dirs: 9: directory stack index out of range +./dstack.tests: line 72: pushd: +9: directory stack index out of range +./dstack.tests: line 72: pushd: -9: directory stack index out of range +./dstack.tests: line 73: popd: +9: directory stack index out of range +./dstack.tests: line 73: 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..116e935 --- /dev/null +++ b/tests/dstack.tests @@ -0,0 +1,100 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +export LC_ALL=C +export LANG=C + +dirs -c +# error -- non-existent 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..0873319 --- /dev/null +++ b/tests/dstack2.tests @@ -0,0 +1,49 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..ddf69ed --- /dev/null +++ b/tests/dynvar.tests @@ -0,0 +1,102 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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 +# date +%s should be portable enough now +# then try gawk, perl, python in that order +now1=$(date +%s 2>/dev/null) D=date +[ -z "$now1" ] && +{ + now1=$(gawk 'BEGIN { print systime(); }' 2>/dev/null) D=gawk + [ -z "$now1" ] && now1=$(perl -e 'print time' 2>/dev/null) D=perl + [ -z "$now1" ] && now1=$(python -c 'import time; ts = int(time.time()); print(ts)' 2>/dev/null) D=python +} +now2=$EPOCHSECONDS + +# use a window of +-1 second +offset=1 +if [[ -z $now1 ]]; then + echo "cannot get current time using date/gawk/perl/python" >&2 +elif (( $now1 - $offset <= $now2 && $now2 <= $now1 + $offset )); then + echo EPOCHSECONDS ok +else + echo "current time via $D and EPOCHSECONDS possible mismatch|$now1|$now2|offset=$offset" >&2 +fi +unset now1 now2 D + +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..0bd88ef --- /dev/null +++ b/tests/errors.right @@ -0,0 +1,208 @@ +./errors.tests: line 30: alias: -x: invalid option +alias: usage: alias [-p] [name[=value] ... ] +./errors.tests: line 31: unalias: -x: invalid option +unalias: usage: unalias [-a] name [name ...] +./errors.tests: line 32: alias: hoowah: not found +./errors.tests: line 33: unalias: hoowah: not found +./errors.tests: line 36: `1': not a valid identifier +declare -fr func +./errors.tests: line 49: func: readonly function +./errors.tests: line 52: unset: -x: invalid option +unset: usage: unset [-f] [-v] [-n] [name ...] +./errors.tests: line 55: unset: func: cannot unset: readonly function +./errors.tests: line 58: declare: func: readonly function +./errors.tests: line 62: declare: -a: invalid option +./errors.tests: line 63: declare: -i: invalid option +./errors.tests: line 67: unset: XPATH: cannot unset: readonly variable +./errors.tests: line 73: unset: cannot simultaneously unset a function and a variable +./errors.tests: line 76: declare: -z: invalid option +declare: usage: declare [-aAfFgiIlnrtux] [name[=value] ...] or declare -p [-aAfFilnrtux] [name ...] +./errors.tests: line 78: declare: `-z': not a valid identifier +./errors.tests: line 79: declare: `/bin/sh': not a valid identifier +./errors.tests: line 83: declare: cannot use `-f' to make functions +./errors.tests: line 86: exec: -i: invalid option +exec: usage: exec [-cl] [-a name] [command [argument ...]] [redirection ...] +./errors.tests: line 90: export: XPATH: not a function +./errors.tests: line 93: break: only meaningful in a `for', `while', or `until' loop +./errors.tests: line 94: continue: only meaningful in a `for', `while', or `until' loop +./errors.tests: line 97: shift: label: numeric argument required +./errors.tests: line 102: shift: too many arguments +./errors.tests: line 108: let: expression expected +./errors.tests: line 111: local: can only be used in a function +./errors.tests: line 114: logout: not login shell: use `exit' +./errors.tests: line 117: hash: notthere: not found +./errors.tests: line 120: hash: -v: invalid option +hash: usage: hash [-lr] [-p pathname] [-dt] [name ...] +./errors.tests: line 124: hash: hashing disabled +./errors.tests: line 127: export: `AA[4]': not a valid identifier +./errors.tests: line 128: readonly: `AA[4]': not a valid identifier +./errors.tests: line 131: unset: [-2]: bad array subscript +./errors.tests: line 135: AA: readonly variable +./errors.tests: line 139: AA: readonly variable +./errors.tests: line 147: shift: 5: shift count out of range +./errors.tests: line 148: shift: -2: shift count out of range +./errors.tests: line 151: shopt: no_such_option: invalid shell option name +./errors.tests: line 152: shopt: no_such_option: invalid shell option name +./errors.tests: line 155: umask: 09: octal number out of range +./errors.tests: line 156: umask: `:': invalid symbolic mode character +./errors.tests: line 157: umask: `:': invalid symbolic mode operator +./errors.tests: line 160: umask: -i: invalid option +umask: usage: umask [-p] [-S] [mode] +./errors.tests: line 164: umask: `u': invalid symbolic mode character +./errors.tests: line 173: VAR: readonly variable +./errors.tests: line 176: declare: VAR: readonly variable +./errors.tests: line 177: declare: VAR: readonly variable +./errors.tests: line 179: declare: unset: not found +./errors.tests: line 182: VAR: readonly variable +comsub: -c: line 1: syntax error near unexpected token `)' +comsub: -c: line 1: `: $( for z in 1 2 3; do )' +comsub: -c: line 1: syntax error near unexpected token `done' +comsub: -c: line 1: `: $( for z in 1 2 3; done )' +./errors.tests: line 189: cd: HOME not set +./errors.tests: line 190: cd: /tmp/xyz.bash: No such file or directory +./errors.tests: line 192: cd: OLDPWD not set +./errors.tests: line 193: cd: /bin/sh: Not a directory +./errors.tests: line 195: cd: /tmp/cd-notthere: No such file or directory +./errors.tests: line 198: .: filename argument required +.: usage: . filename [arguments] +./errors.tests: line 199: source: filename argument required +source: usage: source filename [arguments] +./errors.tests: line 202: .: -i: invalid option +.: usage: . filename [arguments] +./errors.tests: line 205: set: -q: invalid option +set: usage: set [-abefhkmnptuvxBCEHPT] [-o option-name] [--] [-] [arg ...] +./errors.tests: line 208: enable: sh: not a shell builtin +./errors.tests: line 208: enable: bash: not a shell builtin +./errors.tests: line 211: shopt: cannot set and unset shell options simultaneously +./errors.tests: line 214: read: var: invalid timeout specification +./errors.tests: line 217: read: `/bin/sh': not a valid identifier +./errors.tests: line 220: VAR: readonly variable +./errors.tests: line 223: readonly: -x: invalid option +readonly: usage: readonly [-aAf] [name[=value] ...] or readonly -p +./errors.tests: line 226: eval: -i: invalid option +eval: usage: eval [arg ...] +./errors.tests: line 227: command: -i: invalid option +command: usage: command [-pVv] command [arg ...] +./errors.tests: line 230: /bin/sh + 0: syntax error: operand expected (error token is "/bin/sh + 0") +./errors.tests: line 231: /bin/sh + 0: syntax error: operand expected (error token is "/bin/sh + 0") +./errors.tests: line 234: trap: NOSIG: invalid signal specification +./errors.tests: line 237: trap: -s: invalid option +trap: usage: trap [-lp] [[arg] signal_spec ...] +./errors.tests: line 243: return: can only `return' from a function or sourced script +./errors.tests: line 247: break: 0: loop count out of range +./errors.tests: line 251: continue: 0: loop count out of range +./errors.tests: line 256: builtin: bash: not a shell builtin +./errors.tests: line 260: bg: no job control +./errors.tests: line 261: fg: no job control +./errors.tests: line 264: kill: -s: option requires an argument +./errors.tests: line 266: kill: S: invalid signal specification +./errors.tests: line 268: 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 273: set: trackall: invalid option name +./errors.tests: line 277: xx: readonly variable +1 +./errors1.sub: line 14: .: -i: invalid option +.: usage: . filename [arguments] +./errors1.sub: line 22: shift: -4: shift count out of range +./errors1.sub: line 27: 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 20: var: readonly variable +after readonly assignment +./errors4.sub: line 26: break: x: numeric argument required +1 +2 +./errors4.sub: line 20: 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: line 1: uvar: parameter not set +./errors6.sub: line 1: uvar: parameter null or not set + +./errors6.sub: line 1: uvar: parameter null or not set +./errors6.sub: line 38: ${-3:-${-3}}: bad substitution +./errors6.sub: line 39: ${-3}: bad substitution +./errors6.sub: line 40: -3: invalid variable name +after indir: 1 +./errors6.sub: line 43: -3: invalid variable name + +unset +./errors6.sub: line 50: var: invalid indirect expansion +./errors6.sub: line 51: var: invalid indirect expansion +./errors6.sub: line 54: invalid-ident: invalid variable name +./errors6.sub: line 55: invalid-ident: invalid variable name +./errors6.sub: line 56: invalid-ident: invalid variable name +4 +array after 1: 0 + +array after 2: 0 +./errors6.sub: line 1: uvar: parameter not set +./errors6.sub: line 1: uvar: parameter null or not set + +./errors6.sub: line 1: uvar: parameter null or not set +./errors6.sub: line 38: ${-3:-${-3}}: bad substitution +./errors6.sub: line 39: ${-3}: bad substitution +./errors6.sub: line 40: -3: invalid variable name +after indir: 1 +./errors6.sub: line 43: -3: invalid variable name + +unset +./errors6.sub: line 50: var: invalid indirect expansion +./errors6.sub: line 51: var: invalid indirect expansion +./errors6.sub: line 54: invalid-ident: invalid variable name +./errors6.sub: line 55: invalid-ident: invalid variable name +./errors6.sub: line 56: invalid-ident: invalid variable name +./errors7.sub: line 21: x: readonly variable +./errors7.sub: line 21: notthere: command not found +after no such command: 127 +./errors7.sub: line 23: x: readonly variable +echo builtin +after non-special builtin: 0 +./errors7.sub: line 25: x: readonly variable +after special builtin: 0 +./errors7.sub: line 27: x: readonly variable +./errors7.sub: line 29: x: readonly variable +./errors7.sub: line 21: x: readonly variable +after no such command: 1 +./errors7.sub: line 23: x: readonly variable +after non-special builtin: 1 +./errors7.sub: line 25: x: readonly variable +./errors7.sub: line 27: x: readonly variable +./errors7.sub: line 29: 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 +DEBUG +./errors9.sub: line 6: [[: ++: syntax error: operand expected (error token is "+") +DEBUG +./errors9.sub: line 8: ((: -- : syntax error: operand expected (error token is "- ") +DEBUG +./errors9.sub: line 10: ((: -- : syntax error: operand expected (error token is "- ") +bash: line 1: return: can only `return' from a function or sourced script +after return +bash: line 1: return: can only `return' from a function or sourced script +./errors.tests: line 305: `!!': not a valid identifier diff --git a/tests/errors.tests b/tests/errors.tests new file mode 100644 index 0000000..0880bb5 --- /dev/null +++ b/tests/errors.tests @@ -0,0 +1,308 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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 + +# cannot use declare -f in combination with other attributes +a() { echo a; } +declare -f -a a +declare -f -i b c + +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-existent 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; caught early so we have to run them in subshells +${THIS_SH} -c ': $( for z in 1 2 3; do )' comsub +${THIS_SH} -c ': $( for z in 1 2 3; done )' comsub + +# 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_SH} ./errors9.sub + +${THIS_SH} -c 'return ; echo after return' bash +${THIS_SH} -o posix -c 'return ; echo after return' bash + +# 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..52a9e34 --- /dev/null +++ b/tests/errors1.sub @@ -0,0 +1,40 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +. -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..6b40502 --- /dev/null +++ b/tests/errors4.sub @@ -0,0 +1,31 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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..cac2c55 --- /dev/null +++ b/tests/errors6.sub @@ -0,0 +1,56 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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..544e3e4 --- /dev/null +++ b/tests/errors7.sub @@ -0,0 +1,30 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +: ${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: $? ) +( x=8 +echo after assignment statement 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/errors9.sub b/tests/errors9.sub new file mode 100644 index 0000000..3a26704 --- /dev/null +++ b/tests/errors9.sub @@ -0,0 +1,14 @@ +trap 'echo DEBUG' DEBUG + +# make sure that the right command name appears in the error messages and +# that the DEBUG trap doesn't overwrite it + +[[ ++ -gt 3 ]] + +(( -- )) + +for (( -- ; ++; -- )) +do + echo bogus +done + diff --git a/tests/exec.right b/tests/exec.right new file mode 100644 index 0000000..ef02fbb --- /dev/null +++ b/tests/exec.right @@ -0,0 +1,172 @@ +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 +trap -- 'echo EXIT' EXIT +trap -- '' SIGTERM +trap -- 'echo USR1' SIGUSR1 +USR1 +./exec3.sub: line 27: /tmp/bash-notthere: No such file or directory +./exec3.sub: after failed exec: 127 +trap -- 'echo EXIT' EXIT +trap -- '' SIGTERM +trap -- 'echo USR1' SIGUSR1 +USR1 +EXIT +./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 +WORKS +done +WORKS +WORKS +a +b +c +d +a +b +c +d +e +A +B +c +d +c +d +e +x +y +z +WORKS +w +x +y +z +===== +WORKS +done +WORKS +a +b +c +d +a +b +c +d +e +A +B +c +d +c +d +e +x +y +z +WORKS +w +x +y +z 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..db6a671 --- /dev/null +++ b/tests/exec10.sub @@ -0,0 +1,47 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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..0d7c8b8 --- /dev/null +++ b/tests/exec12.sub @@ -0,0 +1,32 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +: ${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..76e1324 --- /dev/null +++ b/tests/exec13.sub @@ -0,0 +1,34 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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/exec14.sub b/tests/exec14.sub new file mode 100644 index 0000000..eddd33f --- /dev/null +++ b/tests/exec14.sub @@ -0,0 +1,64 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +# test that optimizing command lists doesn't inappropriately short-cut commands + +# also includes optimizing last command in a list separated by `;' + +if [ -x /bin/echo ] ; then + binecho=/bin/echo +elif [ -x /usr/bin/echo ]; then + binecho=/usr/bin/echo +else + enable -n echo + binecho=echo +fi + +export binecho + +: ${THIS_SH:=./bash} ${TMPDIR:=/var/tmp} + +${THIS_SH} -c 'trap "echo WORKS && rm $TMPDIR/x$$" EXIT && touch $TMPDIR/x$$' +${THIS_SH} -c 'trap "echo WORKS && rm $TMPDIR/x$$" EXIT && touch $TMPDIR/x$$ ; $binecho done' + +( trap "echo WORKS && rm $TMPDIR/x$$" EXIT && touch $TMPDIR/x$$ ) + +${THIS_SH} -c 'echo a && { $binecho b && $binecho c ; } && echo d' +${THIS_SH} -c 'echo a && { $binecho b && $binecho c ; } && echo d ; $binecho e' + +${THIS_SH} -c 'echo A && $binecho B' +${THIS_SH} -c '$binecho c && echo d' + +$THIS_SH -c '$binecho c && $binecho d && echo e' + +$THIS_SH -c 'trap "echo WORKS" EXIT ; $binecho x ; $binecho y ; $binecho z' + +${THIS_SH} -c 'echo w ; { echo x ; $binecho y; }; $binecho z' + +echo ===== + +( trap "echo WORKS && rm $TMPDIR/x$$" EXIT && touch $TMPDIR/x$$ ) +( trap "echo WORKS && rm $TMPDIR/x$$" EXIT && touch $TMPDIR/x$$ ; $binecho done ) + +( echo a && { $binecho b && $binecho c ; } && echo d ) +( echo a && { $binecho b && $binecho c ; } && echo d ; $binecho e ) + +( echo A && $binecho B ) +( $binecho c && echo d ) + +( $binecho c && $binecho d && echo e ) + +( trap "echo WORKS" EXIT ; $binecho x ; $binecho y ; $binecho z ) + +( echo w ; { echo x ; $binecho y; }; $binecho z ) 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..81b53b7 --- /dev/null +++ b/tests/exec3.sub @@ -0,0 +1,37 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# test the behavior of `execfail' not exiting an interactive shell +# added tests for changes in 10/2021 for preserving the traps across a failed +# exec + +shopt -s execfail + +trap 'echo EXIT' EXIT +trap 'echo USR1' USR1 +trap '' TERM +trap + +kill -s USR1 $$ # should run the trap + +exec /tmp/bash-notthere + +# make sure we're still around +echo $0: after failed exec: $? + +trap +kill -s USR1 $$ # should run the trap +kill -s TERM $$ # should still be ignored + +# this should run the exit trap +exit 0 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..dd53e74 --- /dev/null +++ b/tests/exec6.sub @@ -0,0 +1,67 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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..0c8c7ca --- /dev/null +++ b/tests/exec7.sub @@ -0,0 +1,36 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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..a47dfd0 --- /dev/null +++ b/tests/exec9.sub @@ -0,0 +1,33 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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..2809676 --- /dev/null +++ b/tests/execscript @@ -0,0 +1,160 @@ +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 +${THIS_SH} ./exec14.sub diff --git a/tests/exp.right b/tests/exp.right new file mode 100644 index 0000000..60241a1 --- /dev/null +++ b/tests/exp.right @@ -0,0 +1,419 @@ +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] = <a> +argv[2] = <b> +argv[3] = <> +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=$'x\001y\177z' +argv[1] = <declare> +argv[2] = <--> +argv[3] = <var=$'x\001y\177z'> +var=x\001y\177z$ +declare -- var="x\001y\177z"$ +argv[1] = <$'x\001y\177z'> +argv[1] = <x^Ay^?z> +var=$'x\001y\177z' +./exp8.sub: line 30: 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 +foo +declare -- a="foo" +7 +declare -i a="7" +42 +declare -- a="42" +FOO +declare -u A="FOO" diff --git a/tests/exp.tests b/tests/exp.tests new file mode 100644 index 0000000..61a39d3 --- /dev/null +++ b/tests/exp.tests @@ -0,0 +1,426 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# +# 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} -c 'var=a:b: ; IFS=" :" ; recho $var""' bash + +${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 +${THIS_SH} ./exp13.sub diff --git a/tests/exp1.sub b/tests/exp1.sub new file mode 100644 index 0000000..3dbe3d9 --- /dev/null +++ b/tests/exp1.sub @@ -0,0 +1,34 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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..42bdaf8 --- /dev/null +++ b/tests/exp10.sub @@ -0,0 +1,39 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..b3e02e0 --- /dev/null +++ b/tests/exp11.sub @@ -0,0 +1,105 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..8c5005d --- /dev/null +++ b/tests/exp12.sub @@ -0,0 +1,51 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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/exp13.sub b/tests/exp13.sub new file mode 100644 index 0000000..80e1463 --- /dev/null +++ b/tests/exp13.sub @@ -0,0 +1,34 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +unset a + +echo ${a:=foo} +declare -p a + +unset a + +declare -i a +echo ${a:=4+3} +declare -p a + +unset a +echo ${a:=42} +declare -p a + +unset a +declare -u A +A= +echo ${A:=foo} + +declare -p A 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..5cf8ed7 --- /dev/null +++ b/tests/exp5.sub @@ -0,0 +1,34 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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..582617c --- /dev/null +++ b/tests/exp6.sub @@ -0,0 +1,43 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..a3993b5 --- /dev/null +++ b/tests/exp7.sub @@ -0,0 +1,36 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..7dd5a28 --- /dev/null +++ b/tests/exp8.sub @@ -0,0 +1,45 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +var=$'x\001y\177z' + +recho "$var" +recho $var + +declare -p var +recho $(declare -p var) + +echo "var=$var" | sed -n l +echo "declare -- var=\"$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..7e4a3b6 --- /dev/null +++ b/tests/exp9.sub @@ -0,0 +1,82 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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..890bdfa --- /dev/null +++ b/tests/exportfunc.right @@ -0,0 +1,14 @@ +exportfunc ok 1 +exportfunc ok 2 +./exportfunc.tests: line 37: cve7169-bad: No such file or directory +./exportfunc.tests: eval: line 44: syntax error: unexpected end of file +./exportfunc.tests: line 43: cve7169-bad2: No such file or directory +./exportfunc1.sub: line 14: maximum here-document count exceeded +./exportfunc.tests: line 72: HELLO_WORLD: No such file or directory +eval ok +./exportfunc3.sub: line 23: export: foo=bar: cannot export +status: 1 +equals-1 +bad echo +./exportfunc3.sub: line 36: export: /bin/echo: cannot export +bar diff --git a/tests/exportfunc.tests b/tests/exportfunc.tests new file mode 100644 index 0000000..d06b1a3 --- /dev/null +++ b/tests/exportfunc.tests @@ -0,0 +1,92 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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 +A100=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +A1000=${A100} + +for (( i = 0; i < 999; i++ )) +do + A1000+=${A100} +done + +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;}<<${A1000} 0" ${THIS_SH} -c foo 2>/dev/null +${THIS_SH} -c "f(){ x(){ _;}; x(){ _;}<<a;}" 2>/dev/null +unset A100 A1000 + +# 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..53b4c1f --- /dev/null +++ b/tests/exportfunc1.sub @@ -0,0 +1,34 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..cf5df57 --- /dev/null +++ b/tests/exportfunc2.sub @@ -0,0 +1,413 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..af3125b --- /dev/null +++ b/tests/exportfunc3.sub @@ -0,0 +1,38 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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..2974cec --- /dev/null +++ b/tests/extglob.right @@ -0,0 +1,184 @@ +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 +*(foo).* +*(foo|bar).* +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 +* +.b a +.b a +a .b +.b +.b +.b a +.b a +a .b +.b +.b +dotglob: .a .foo bar +@(.foo) +.foo +!(.foo) +.a bar +@(.foo|*) +.a .foo bar +!(.foo|*) +!(.foo|*) +@(*) +.a .foo bar +!(*) +!(*) +.* +. .. .a .foo +@(.*) +. .. .a .foo +!(.*) +bar +no dotglob: .a .foo bar +@(.foo) +.foo +!(.foo) +bar +@(.foo|*) +.foo bar +!(.foo|*) +!(.foo|*) +!(bar).foo +!(bar).foo +*(bar).foo +.foo +?(bar).foo +.foo +.? +.. .a +@(.?) +.. .a +!(.?) +bar +dotglob: .a .foo bar +@(?|.?) +.. .a +@(?|.*) +. .. .a .foo +? .* +? . .. .a .foo +* +.a .foo bar +no dotglob: .a .foo bar +@(?|.?) +.. .a +@(?|.*) +. .. .a .foo +? .* +? . .. .a .foo +* +bar diff --git a/tests/extglob.tests b/tests/extglob.tests new file mode 100644 index 0000000..7a7cf91 --- /dev/null +++ b/tests/extglob.tests @@ -0,0 +1,390 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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 +${THIS_SH} ./extglob6.sub +${THIS_SH} ./extglob7.sub + +exit 0 diff --git a/tests/extglob1.sub b/tests/extglob1.sub new file mode 100644 index 0000000..c73b1ea --- /dev/null +++ b/tests/extglob1.sub @@ -0,0 +1,50 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..1470386 --- /dev/null +++ b/tests/extglob1a.sub @@ -0,0 +1,29 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..1088111 --- /dev/null +++ b/tests/extglob2.sub @@ -0,0 +1,31 @@ +LANG=en_US.UTF-8 + +shopt -s extglob +a="aaaäöü" +a1=${a:3:3} + +[[ "${a}" == "${a1}" ]] || { + echo cond ok 1 +} + +case "${a//?aa}" in +"${a1}") echo ok 1;; +*) echo bad 1;; +esac + +case "${a//\aaa}" in +"${a1}") echo ok 2;; +*) echo bad 2;; +esac + +case "${a//aaa}" in +"${a1}") echo ok 3;; +*) echo bad 3;; +esac + +case "${a//@(?aa)}" in +"${a1}") echo ok 4;; +*) echo bad 4;; +esac + +exit 0 diff --git a/tests/extglob2.tests b/tests/extglob2.tests new file mode 100644 index 0000000..187253b --- /dev/null +++ b/tests/extglob2.tests @@ -0,0 +1,103 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# +# 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..bf5d263 --- /dev/null +++ b/tests/extglob3.sub @@ -0,0 +1,37 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..56f8b39 --- /dev/null +++ b/tests/extglob3.tests @@ -0,0 +1,69 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..5369cd6 --- /dev/null +++ b/tests/extglob4.sub @@ -0,0 +1,45 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..580229b --- /dev/null +++ b/tests/extglob5.sub @@ -0,0 +1,31 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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/extglob6.sub b/tests/extglob6.sub new file mode 100644 index 0000000..5e2aafb --- /dev/null +++ b/tests/extglob6.sub @@ -0,0 +1,43 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# issues with ? matching "." in certain special circumstances with dotglob set + +shopt -s dotglob extglob + +DIR=$TMPDIR/extglob-$$ +mkdir $DIR +cd $DIR + +touch a .b + +LC_COLLATE=C # fix sort order + +echo @(?|.?) +echo @(.?|?) +echo ? .? + +echo .* +echo \.* + +shopt -u dotglob + +echo @(?|.?) +echo @(.?|?) +echo ? .? + +echo .* +echo \.* + +cd $OLDPWD +rm -rf $DIR diff --git a/tests/extglob7.sub b/tests/extglob7.sub new file mode 100644 index 0000000..5fab9cd --- /dev/null +++ b/tests/extglob7.sub @@ -0,0 +1,97 @@ +: ${TMPDIR:=/tmp} + +TESTDIR=$TMPDIR/glob-test-$$ +mkdir $TESTDIR || { + echo "$TESTDIR: cannot create" >&2 + exit 1 +} +cd $TESTDIR || { + echo "$TESTDIR: cannot cd" >&2 + exit 1 +} + +LC_CTYPE=C LC_COLLATE=C +shopt -s extglob dotglob +shopt -u globskipdots # XXX - backwards compatibility +touch .foo bar .a + +echo dotglob: .a .foo bar + +echo '@(.foo)' +echo @(.foo) +echo '!(.foo)' +echo !(.foo) + +echo '@(.foo|*)' +echo @(.foo|*) +echo '!(.foo|*)' +echo !(.foo|*) + +echo '@(*)' +echo @(*) +echo '!(*)' +echo !(*) + +echo '.*' +echo .* +echo '@(.*)' +echo @(.*) +echo '!(.*)' +echo !(.*) + +shopt -u dotglob + +echo no dotglob: .a .foo bar + +echo '@(.foo)' +echo @(.foo) +echo '!(.foo)' +echo !(.foo) + +echo '@(.foo|*)' +echo @(.foo|*) +echo '!(.foo|*)' +echo !(.foo|*) + +echo '!(bar).foo' +echo !(bar).foo +echo '*(bar).foo' +echo *(bar).foo +echo '?(bar).foo' +echo ?(bar).foo + +echo '.?' +echo .? +echo '@(.?)' +echo @(.?) +echo '!(.?)' +echo !(.?) + +shopt -s dotglob +echo dotglob: .a .foo bar + +echo '@(?|.?)' +echo @(?|.?) +echo '@(?|.*)' +echo @(?|.*) +echo '? .*' +echo ? .* +echo '*' +echo * + +shopt -u dotglob +echo no dotglob: .a .foo bar + +echo '@(?|.?)' +echo @(?|.?) +echo '@(?|.*)' +echo @(?|.*) +echo '? .*' +echo ? .* +echo '*' +echo * + +rm -f .a bar .foo + +cd $OLDPWD +rm -rf $TESTDIR diff --git a/tests/func.right b/tests/func.right new file mode 100644 index 0000000..f4db4d1 --- /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 20 +5 20 +expect 2 40 +2 40 +expect 5 20 +5 20 +./func4.sub: line 23: foo: maximum function nesting level exceeded (100) +1 +after: f = 100 +./func4.sub: line 23: 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 23: 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..e35ec2b --- /dev/null +++ b/tests/func.tests @@ -0,0 +1,198 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# since we look at functions below, remove all functions now +funcs=$(compgen -A function) +if [ -n "$funcs" ]; then + unset -f $funcs +fi + +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..f7e84f4 --- /dev/null +++ b/tests/func1.sub @@ -0,0 +1,68 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# +# 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..9caabfc --- /dev/null +++ b/tests/func2.sub @@ -0,0 +1,40 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..5c0eac2 --- /dev/null +++ b/tests/func3.sub @@ -0,0 +1,67 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# +# 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 20 +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..69f15e4 --- /dev/null +++ b/tests/func4.sub @@ -0,0 +1,52 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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..599d830 --- /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 23: 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 17: 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 16: 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..06cc29a --- /dev/null +++ b/tests/getopts.tests @@ -0,0 +1,56 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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..5145879 --- /dev/null +++ b/tests/getopts1.sub @@ -0,0 +1,39 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..49b2bfe --- /dev/null +++ b/tests/getopts10.sub @@ -0,0 +1,30 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..6bb8af5 --- /dev/null +++ b/tests/getopts2.sub @@ -0,0 +1,39 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..6769c49 --- /dev/null +++ b/tests/getopts3.sub @@ -0,0 +1,40 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..5fbe954 --- /dev/null +++ b/tests/getopts4.sub @@ -0,0 +1,43 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..bf52310 --- /dev/null +++ b/tests/getopts5.sub @@ -0,0 +1,62 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +#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..d969ece --- /dev/null +++ b/tests/getopts6.sub @@ -0,0 +1,40 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..de7d7a6 --- /dev/null +++ b/tests/getopts7.sub @@ -0,0 +1,43 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..f7dcabc --- /dev/null +++ b/tests/getopts9.sub @@ -0,0 +1,29 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..723ee7b --- /dev/null +++ b/tests/glob.right @@ -0,0 +1,261 @@ +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 2.1 +ok 3 +ok 4 +== LANG=en_US.UTF-8 == +[[:alpha:] +ok 1 +[a +[[:alpha:] +ok 2 +ok 2.1 +ok 3 +ok 4 +invalid character class +== LANG=C == +p +p +ok 1 +ok 2 +ok 3 +ok 4 +ok 5 +ok 6 +== LANG=en_US.UTF-8 == +p +p +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\? +a\a +<define\/\ +/> +./tmp/a/b/c ./tmp/a/b/c ./tmp/a/b/c +./tmp/a/b/c ./tmp/a/b/c ./tmp/a/b/c +./tmp/a/b/c +./tmp/a/b/c +./tmp\/a/b/c +./tm[p]\/a/b/c +./tmp/a/b/c +argv[1] = <./tmp/a/*> +argv[1] = <./tmp/a/*> +argv[1] = <./tmp/a/b/c> +argv[1] = <./tmp/a/*> +argv[1] = <./tmp/a/b/c> +argv[1] = <./t\mp/a/*> +argv[1] = <./tmp/a/b/c> +argv[1] = <./tmp/a/> +argv[1] = <./tmp/a/b/> +argv[1] = <./t\mp/a/> +argv[1] = <./t\mp/a/b/> +argv[1] = <./tmp/a/*> +argv[1] = <./tmp/a/b/c> +argv[1] = <./tmp/a> +argv[1] = <./tmp/a/b*> +argv[1] = <./tmp/a> +argv[1] = <./tmp/a/b*> +argv[1] = <./tmp/> +argv[1] = <\$foo> +argv[2] = <\$foo> +argv[1] = <mixed\$foo/> +<abcdefg> +<\.> +*abc.c +searchable/\. +searchable/\./. +readable/\. +readable/\./. +searchable/\. +readable/\. +searchable/. +searchable/. +searchable/. +1: [qwe/qwe] +2: [qwe/ +3: [qwe/] +4: +5: [qwe/ +6: +a\*b +a\*b* +é/* +é/* +a aa b bb +.a .aa .b .bb a aa b bb +.a .aa .b .bb +. .. .a .aa .b .bb +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 66: 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..02d5302 --- /dev/null +++ b/tests/glob.tests @@ -0,0 +1,410 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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 +${THIS_SH} ./glob5.sub +${THIS_SH} ./glob6.sub +${THIS_SH} ./glob7.sub +${THIS_SH} ./glob8.sub +${THIS_SH} ./glob9.sub +${THIS_SH} ./glob10.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..27c216b --- /dev/null +++ b/tests/glob1.sub @@ -0,0 +1,30 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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/glob10.sub b/tests/glob10.sub new file mode 100644 index 0000000..7c14c0d --- /dev/null +++ b/tests/glob10.sub @@ -0,0 +1,32 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +# test basic behavior of globskipdots +TDIR=/tmp/dotglob-$$ + +{ mkdir $TDIR && cd $TDIR; } || exit 1 + +touch a b aa bb .a .b .aa .bb + +echo * +shopt -s dotglob +echo * + +shopt -s globskipdots +echo .* +shopt -u globskipdots +echo .* + +cd $OLDPWD +rm -rf $TDIR diff --git a/tests/glob2.sub b/tests/glob2.sub new file mode 100644 index 0000000..09cb6d5 --- /dev/null +++ b/tests/glob2.sub @@ -0,0 +1,65 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +. ./test-glue-functions + +# this locale causes problems all over the place +if locale -a | grep -i '^zh_HK\.big5hkscs' >/dev/null ; then + : +else + echo "glob2.sub: warning: you do not have the zh_HK.big5hkscs locale installed;" >&2 + echo "glob2.sub: warning: that will cause some of these tests to fail." >&2 +fi + +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..662c65e --- /dev/null +++ b/tests/glob3.sub @@ -0,0 +1,163 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +: ${TMPDIR:=/var/tmp} + +TESTDIR=${TMPDIR}/glob-test-$$ +mkdir ${TESTDIR} +cd $TESTDIR || { + echo "$TESTDIR: cannot cd" >&2 + exit 1 +} + +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 + [[:aeioux:]) echo bad 2.1 ;; + *) echo ok 2.1 ;; + esac + + case [x in + [[:alpha:]) echo bad 3;; + *) echo ok 3;; + esac + + # unclosed bracket char class expression just matches against ":alpha" + case a in + [[:alpha]) echo ok 4;; + *) echo bad 4;; + esac +} + +echo invalid bracket expression +export LANG=C +matchfunc + +export LANG=en_US.UTF-8 +matchfunc + +unset -f matchfunc + +matchfunc() +{ + echo == LANG=$LANG == + + touch p + # quoted character classes work as if they were unquoted now + echo [[:alpha:]] + echo [[:"alpha":]] + rm -f p + + 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 + + # Posix says quoted character class names work now + case x in + [[:"alpha":]]) echo ok 4;; + *) echo bad 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 + +cd $OLDPWD +rm -rf $TESTDIR diff --git a/tests/glob4.sub b/tests/glob4.sub new file mode 100644 index 0000000..779c854 --- /dev/null +++ b/tests/glob4.sub @@ -0,0 +1,41 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +: ${TMPDIR:=/var/tmp} + +FN=$TMPDIR/bash-glob.$$ +mkdir $FN || { echo "glob4.sub: cannot mkdir $FN" >&2 ; exit 1; } +builtin cd $FN || { echo "glob4.sub: cannot change directory to $FN" >&2 ; exit 1; } +rm -f * + +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} + +# shell's idea of a glob pattern and libglob's idea of a glob pattern have to +# be identical +PRE='\/' +printf '<%s>\n' 'define'${PRE}'\ +/' + +builtin cd $OLDPWD +rm -rf $FN diff --git a/tests/glob5.sub b/tests/glob5.sub new file mode 100644 index 0000000..a0dd623 --- /dev/null +++ b/tests/glob5.sub @@ -0,0 +1,78 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +[ $UID -eq 0 ] && { echo "glob5.sub: the test suite should not be run as root" >&2 ; } + +ORIGD=$PWD +: ${TMPDIR:=/var/tmp} + +SD=$TMPDIR/bash-glob-$$ +[ -d $SD ] || mkdir $SD +builtin cd $SD || { echo "glob5.sub: cannot change directory to $SD" >&2 ; exit 1; } +mkdir tmp + +D=./tmp/a +D1='./t\mp/a' + +mkdir -m700 ./tmp/a ./tmp/a/b +touch ./tmp/a/b/c + +echo ./tmp/a/b/* "./tmp/a/"b/* "./tmp/a/b"/* + +chmod -r ./tmp/a +echo ./tmp/a/b/* "./tmp/a/"b/* "./tmp/a/b"/* +echo "./tmp/a/b"/* + +bs=\\ +echo ./tmp${bs}/a/b/* +echo ./tmp${bs}/a/b/c +echo ./tm[p]${bs}/a/b/c +echo ./t${bs}mp/a/b/* + +recho "./tmp/a"/* +recho "$D"/* +recho "$D"/b/* + +recho $D/* +recho $D/b/* +recho $D1/* +recho $D1/b/* +recho $D/ +recho $D/b/ +recho $D1/ +recho $D1/b/ + +recho ./t\mp/a/* +recho ./t\mp/a/b/* + +recho ./tmp/a* +recho ./tmp/a/b* +recho ./t\mp/a* +recho ./t\mp/a/b* + +recho ./t\mp/ + +chmod +r ./tmp/a +rm -rf ./tmp/a + +a='$foo' +b='$bar' +a=$(echo "$a" | sed 's/\$/\\$/g') + +recho $a "$a" +recho 'mixed'$a/ + +unset a b + +cd $ORIGD +rm -rf $SD diff --git a/tests/glob6.sub b/tests/glob6.sub new file mode 100644 index 0000000..8842983 --- /dev/null +++ b/tests/glob6.sub @@ -0,0 +1,69 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# tests of the backslash-in-glob-patterns discussion on the austin-group ML +[ $UID -eq 0 ] && { echo "glob6.sub: the test suite should not be run as root" >&2 ; } + +: ${TMPDIR:=/var/tmp} + +ORIG=$PWD +GLOBDIR=$TMPDIR/bash-glob-$$ +mkdir $GLOBDIR || { echo "glob6.sub: cannot make directory $GLOBDIR" >&2 ; exit 1; } +builtin cd $GLOBDIR || { echo "glob6.sub: cannot change directory to $GLOBDIR" >&2 ; exit 1; } + +# does the pattern matcher allow backslashes as escape characters and remove +# them as part of matching? +touch abcdefg +pat='ab\cd*' +printf '<%s>\n' $pat +pat='\.' +printf '<%s>\n' $pat +rm abcdefg + +# how about when escaping pattern characters? +touch '*abc.c' +a='\**.c' +printf '%s\n' $a +rm -f '*abc.c' + +# how about when making the distinction between readable and searchable path +# components? +mkdir -m a=x searchable +mkdir -m a=r readable + +p='searchable/\.' +printf "%s\n" $p + +p='searchable/\./.' +printf "%s\n" $p + +p='readable/\.' +printf "%s\n" $p + +p='readable/\./.' +printf "%s\n" $p + +printf "%s\n" 'searchable/\.' +printf "%s\n" 'readable/\.' + +echo */. + +p='*/\.' +echo $p + +echo */'.' + +rmdir searchable readable + +cd $ORIG +rmdir $GLOBDIR diff --git a/tests/glob7.sub b/tests/glob7.sub new file mode 100644 index 0000000..0212b8e --- /dev/null +++ b/tests/glob7.sub @@ -0,0 +1,11 @@ +# according to Posix 2.13.3, a slash in a bracket expression renders that +# bracket expression invalid +shopt -s nullglob + +echo 1: [qwe/qwe] +echo 2: [qwe/ +echo 3: [qwe/] + +echo 4: [qwe\/qwe] +echo 5: [qwe\/ +echo 6: [qwe\/] diff --git a/tests/glob8.sub b/tests/glob8.sub new file mode 100644 index 0000000..dca54fc --- /dev/null +++ b/tests/glob8.sub @@ -0,0 +1,31 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +: ${TMPDIR:=/var/tmp} + +TESTDIR=${TMPDIR}/glob-test-$$ +mkdir ${TESTDIR} +cd $TESTDIR || { + echo "$TESTDIR: cannot cd" >&2 + exit 1 +} + +trap 'cd $OLDPWD && rm -rf $TESTDIR' EXIT + +var='a\' +touch 'a*b' 'a\*b' + +printf '%s\n' $var\*b* + +var1=a\\$'\001' +printf '%s\n' $var1\*b* diff --git a/tests/glob9.sub b/tests/glob9.sub new file mode 100644 index 0000000..ef2af2b --- /dev/null +++ b/tests/glob9.sub @@ -0,0 +1,13 @@ +LANG=en_US.UTF-8 # safest +: ${TMPDIR:=/var/tmp} +HOME=${TMPDIR} + +mkdir ~/ಇಳಿಕೆಗಳೠ+touch ~/ಇಳಿಕೆಗಳà³/{a,b}.txt +echo ~/ಇಳಿಕೆಗಳà³/*.txt >/dev/null + +rm -rf ${TMPDIR}/ಇಳಿಕೆಗಳೠ+ +LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8 +echo é/* +echo 'é'/* diff --git a/tests/globstar.right b/tests/globstar.right new file mode 100644 index 0000000..c8211bc --- /dev/null +++ b/tests/globstar.right @@ -0,0 +1,587 @@ +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> +a a/aa a/ab b b/bb b/bc c +a/ b/ c/ +a/ab b b/bb diff --git a/tests/globstar.tests b/tests/globstar.tests new file mode 100644 index 0000000..33714b4 --- /dev/null +++ b/tests/globstar.tests @@ -0,0 +1,56 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +: ${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 +${THIS_SH} ./globstar3.sub diff --git a/tests/globstar1.sub b/tests/globstar1.sub new file mode 100644 index 0000000..7097f5d --- /dev/null +++ b/tests/globstar1.sub @@ -0,0 +1,34 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..ccf413b --- /dev/null +++ b/tests/globstar2.sub @@ -0,0 +1,97 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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/globstar3.sub b/tests/globstar3.sub new file mode 100644 index 0000000..771d906 --- /dev/null +++ b/tests/globstar3.sub @@ -0,0 +1,37 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +olddir=$PWD +: ${TMPDIR:=/var/tmp} + +SCRATCH=${TMPDIR}/scratch-$$ +rm -rf $SCRATCH +mkdir $SCRATCH || exit 1 + +cd $SCRATCH + +mkdir a b +touch a/aa a/ab +touch b/bb b/bc + +ln -s a c + +shopt -s globstar + +echo ** +echo **/ + +echo **/*b + +cd "$olddir" +rm -rf $SCRATCH diff --git a/tests/heredoc.right b/tests/heredoc.right new file mode 100644 index 0000000..cc193f6 --- /dev/null +++ b/tests/heredoc.right @@ -0,0 +1,133 @@ +a +b +c +a +$PS4 + + + +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 20: warning: here-document at line 18 delimited by end-of-file (wanted `EOF') += here is the text = +./heredoc3.sub: line 26: warning: here-document at line 24 delimited by end-of-file (wanted `EOF') +this paren ) is not a problem +./heredoc3.sub: line 32: warning: here-document at line 30 delimited by end-of-file (wanted `EOF') +these balanced parens ( ) are not a problem +./heredoc3.sub: line 38: warning: here-document at line 36 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 98: warning: here-document at line 96 delimited by end-of-file (wanted `EOF') +./heredoc3.sub: line 99: 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> +1: OK +2: OK +3: OK +4: OK +5: OK +6: OK +7: OK +1: OK +2: OK +3: OK +4: OK +5: OK +5: OK +1: ${x#$'no\t'} +2: O${x#$'no\t'O} +3: ${x#n$'o\t'} +4: ${x#'no '} +5: ${x#$pat} +6: ${y#$'not'} +7: ${y#'not'} +./heredoc7.sub: line 17: warning: command substitution: 1 unterminated here-document +foo bar +./heredoc7.sub: line 21: after: command not found +./heredoc7.sub: line 29: warning: here-document at line 29 delimited by end-of-file (wanted `EOF') +./heredoc7.sub: line 29: foobar: command not found +./heredoc7.sub: line 30: EOF: command not found +grep: *.c: No such file or directory +comsub here-string +./heredoc.tests: line 156: warning: here-document at line 154 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..d10a7c1 --- /dev/null +++ b/tests/heredoc.tests @@ -0,0 +1,156 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# basics +cat <<EOF +a +b +c +EOF +read x <<EOF +a +b +c +EOF +echo "$x" +read x y <<\EOF +$PS4 +EOF +echo "$x" + +# empty here-documents +read x <<EOF +EOF +echo "$x" +read x <<\EOF +EOF +echo "$x" +read x <<EOF +$empty +EOF +echo "$x" + +# 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 + +# heredoc tests that use different size documents to test pipe implementation +${THIS_SH} ./heredoc5.sub + +# test $'...' and $"..." quoted strings in here-documents +${THIS_SH} ./heredoc6.sub + +# interaction between here-documents and command substitutions +${THIS_SH} ./heredoc7.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..34977c5 --- /dev/null +++ b/tests/heredoc1.sub @@ -0,0 +1,29 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..efbdf7d --- /dev/null +++ b/tests/heredoc3.sub @@ -0,0 +1,98 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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/heredoc5.sub b/tests/heredoc5.sub new file mode 100644 index 0000000..d7b5926 --- /dev/null +++ b/tests/heredoc5.sub @@ -0,0 +1,41 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# test here documents for sizes > 65536 (max pipe capacity I've seen), +# 4096 < size < 65536 (for smaller pipe capacities) +# 512 < size < 4096 (PIPE_BUF) +# +# There are tests in other scripts for here documents shorter than 512 bytes +# +# This should return the same results regardless of the pipe capacity + +: ${TMPDIR:=/tmp} +FILENAME=${TMPDIR}/catfile-$$ + +catfile() +{ + cat <<- EOF > $FILENAME + $(cat $1) +EOF + cmp $FILENAME $1 + rm -f $FILENAME +} + + +if [ -f $BUILD_DIR/y.tab.c ]; then + catfile $BUILD_DIR/y.tab.c +else + catfile ../y.tab.c +fi +catfile ${BUILD_DIR}/config.h +catfile ${BUILD_DIR}/version.h diff --git a/tests/heredoc6.sub b/tests/heredoc6.sub new file mode 100644 index 0000000..1d5fff0 --- /dev/null +++ b/tests/heredoc6.sub @@ -0,0 +1,50 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +# test $'...' and $"..." strings in here documents (problem through bash-5.1) + +pat=$'no\t' +x=$'no\tOK' +y=notOK + +cat <<EOF +1: ${x#$'no\t'} +2: O${x#$'no\t'O} +3: ${x#n$'o\t'} +4: ${x#'no '} +5: ${x#$pat} +6: ${y#$'not'} +7: ${y#'not'} +EOF + +cat <<EOF +1: ${x#$"no "} +2: ${x#n$"o "} +3: O${x#n$"o "O} +4: ${x#"no "} +5: ${y#$"not"} +5: ${y#"not"} +EOF + +# we don't perform dollar-quote expansion if the here-doc delimiter is quoted + +cat <<\EOF +1: ${x#$'no\t'} +2: O${x#$'no\t'O} +3: ${x#n$'o\t'} +4: ${x#'no '} +5: ${x#$pat} +6: ${y#$'not'} +7: ${y#'not'} +EOF diff --git a/tests/heredoc7.sub b/tests/heredoc7.sub new file mode 100644 index 0000000..4119df1 --- /dev/null +++ b/tests/heredoc7.sub @@ -0,0 +1,29 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +# should characters outside a command substitution be interpreted as a delimiter +# for a here-document started inside it? +echo $(cat << EOF) +foo +bar +EOF +after + +# should characters inside a command substitution be interpreted as a delimiter +# for a here-document started outside of it? + +cat <<EOF && grep $( + foobar +EOF +echo notthereanywhere) *.c diff --git a/tests/herestr.right b/tests/herestr.right new file mode 100644 index 0000000..4ac2cc6 --- /dev/null +++ b/tests/herestr.right @@ -0,0 +1,38 @@ +alpha +beta +4 +4 + + + +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..c97fa4f --- /dev/null +++ b/tests/herestr.tests @@ -0,0 +1,80 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# since we look at functions below, remove all functions now +funcs=$(compgen -A function) +if [ -n "$funcs" ]; then + unset -f $funcs +fi + +# basics +read x <<<"alpha" +echo "$x" +read x <<<beta +echo "$x" +X=4 +read x <<<$X +echo "$x" +read x <<<"$X" +echo "$x" +unset X + +# empty here-strings +read x <<<"" +echo "$x" +read x <<<"$empty" +echo "$x" +read x <<<$empty +echo "$x" + +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..341252c --- /dev/null +++ b/tests/histexp.right @@ -0,0 +1,246 @@ +echo $BASH_VERSION +./histexp.tests: line 37: 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 33: !': 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 +a +echo !! +--between-- +echo !! diff --git a/tests/histexp.tests b/tests/histexp.tests new file mode 100644 index 0000000..91a36f2 --- /dev/null +++ b/tests/histexp.tests @@ -0,0 +1,158 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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 +${THIS_SH} ./histexp7.sub diff --git a/tests/histexp1.sub b/tests/histexp1.sub new file mode 100644 index 0000000..cc2c5d1 --- /dev/null +++ b/tests/histexp1.sub @@ -0,0 +1,36 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..4962436 --- /dev/null +++ b/tests/histexp3.sub @@ -0,0 +1,57 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..9cae0e3 --- /dev/null +++ b/tests/histexp4.sub @@ -0,0 +1,36 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..9e6d01b --- /dev/null +++ b/tests/histexp5.sub @@ -0,0 +1,41 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..d52e5ea --- /dev/null +++ b/tests/histexp6.sub @@ -0,0 +1,37 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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/histexp7.sub b/tests/histexp7.sub new file mode 100644 index 0000000..8822205 --- /dev/null +++ b/tests/histexp7.sub @@ -0,0 +1,18 @@ +# make sure history expansion doesn't take place while parsing command +# substitutions + +set -o history +set -o histexpand +echo a + +echo $( cat <<EOF +echo !! +EOF +) + +echo --between-- + +cat <( cat <<'EOF' +echo !! +EOF +) 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..5273de6 --- /dev/null +++ b/tests/history.right @@ -0,0 +1,299 @@ +./history.tests: line 17: history: -x: invalid option +history: usage: history [-c] [-d offset] [n] or history -anrw [filename] or history -ps arg [arg...] +./history.tests: line 19: history: cannot use more than one of -anrw +./history.tests: line 22: 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 90: fc: no command found + 15 echo line 2 for history + 16 unset HISTSIZE + 17 unset HISTFILE + 18 # now an out-of-range error because of the one=two not found in history +aa ab ac +echo xx xb xc +xx xb xc +echo 44 48 4c +44 48 4c +./history.tests: line 105: 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.2 +echo ${BASH_VERSION%\.*} +5.2 + 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 40: history: 16: history position out of range +./history3.sub: line 41: history: 200: history position out of range +./history3.sub: line 42: history: -20: history position out of range +./history3.sub: line 43: history: -50: history position out of range +./history3.sub: line 44: history: 5-0xaf: history position out of range + 1 echo a + 2 echo e + 3 echo f + 4 echo g + 5 echo h + + +0 +1 +2 +(left +mid +right) +A +B + +(left +mid +right) +A +B + +(left +mid +right) +A +B + +0 +1 +2 +(left +mid +right) +A +B +(left +mid +right) +A +B + +0 +1 +2 +(left +mid +right) +A +B +(left +mid +right) +A +B +a +b +./history5.sub: line 24: fc: history specification out of range +./history5.sub: line 25: fc: no command found +1 echo a +2 echo b +3 fc -0 # error +4 fc -s -0 # error +c +6 echo c +8 fc -l -0 +d +echo d +d +a +b +c +d +e +f +4 echo d +5 echo e +6 echo f +out of range 1 +6 echo f +7 fc -l +8 echo out of range 1 +out of range 2 +8 echo out of range 1 +9 fc -l 502 498 +10 echo out of range 2 +out of range 3 +10 echo out of range 2 +11 fc -l 498 502 +12 echo out of range 3 +out of range 4 +13 fc -l 1 99 +1 +2 +3 +4 +5 +6 + 3 echo 3 + 4 echo 4 + 5 echo 5 + 6 echo 6 + 3 echo 3 + 4 echo 4 + 5 echo 5 +6 +7 + 4 echo 4 + 5 echo 5 + 6 echo 6 + 7 echo 7 + 4 echo 4 + 5 echo 5 + 6 echo 6 +7 +8 + 5 echo 5 + 6 echo 6 +9 +10 + 5 echo 5 + 6 echo 6 + 7 echo 9 + 8 echo 10 + 5 echo 10 diff --git a/tests/history.tests b/tests/history.tests new file mode 100644 index 0000000..5826d13 --- /dev/null +++ b/tests/history.tests @@ -0,0 +1,133 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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 + +# now an out-of-range error because of the one=two not found in history +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 +${THIS_SH} ./history4.sub +${THIS_SH} ./history5.sub +${THIS_SH} ./history6.sub diff --git a/tests/history1.sub b/tests/history1.sub new file mode 100644 index 0000000..b67a0ef --- /dev/null +++ b/tests/history1.sub @@ -0,0 +1,28 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..d8a2203 --- /dev/null +++ b/tests/history3.sub @@ -0,0 +1,49 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +: ${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/history4.sub b/tests/history4.sub new file mode 100644 index 0000000..651374c --- /dev/null +++ b/tests/history4.sub @@ -0,0 +1,47 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +HISTFILE=$TMPDIR/newhistory-$$ +export HISTFILE + +trap 'rm -f $HISTFILE' EXIT + +HISTSIZE=32 +HISTFILESIZE=32 +echo +set -o history +history -c +echo 0 +echo 1 +echo 2 +echo "(left +mid +right)" +echo A +echo B +history -w +set +o history + +echo +printf $'HISTFILE=\n\cRleft\cO\cO\cO\cO\n' | HISTSIZE= ${THIS_SH} --norc -i 2>/dev/null +echo +printf $'HISTFILE=\n\cRleft\cO\cO\cO\cO\n' | HISTSIZE=8 ${THIS_SH} --norc -i 2>/dev/null + +input="$(cat $HISTFILE) +"$'\cP\cP\cP\cO\cO +' + +echo +printf "$input" | HISTSIZE= HISTFILE= ${THIS_SH} --norc -i 2>/dev/null +echo +printf "$input" | HISTSIZE=6 HISTFILE= ${THIS_SH} --norc -i 2>/dev/null diff --git a/tests/history5.sub b/tests/history5.sub new file mode 100644 index 0000000..245c28d --- /dev/null +++ b/tests/history5.sub @@ -0,0 +1,57 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +trap 'rm -f "$OUT"' 0 1 2 3 6 15 + +HISTFILE=$TMPDIR/fchist-$$ ; OUT=$HISTFILE +unset HISTIGNORE HISTCONTROL +set -o history + +echo a +echo b + +fc -0 # error +fc -s -0 # error + +fc -l + +echo c +fc -l 0 +fc -l -0 + +echo d +fc -s 0 + +HISTSIZE=4 +history -c + +echo a +echo b +echo c +echo d +echo e +echo f +fc -l + +echo out of range 1 +fc -l 502 498 +echo out of range 2 +fc -l 498 502 +echo out of range 3 +fc -l 1 99 +# other out-of-range behavior for future work +echo out of range 4 +fc -l -20 -40 + +unset HISTFILE # suppress writing history file diff --git a/tests/history6.sub b/tests/history6.sub new file mode 100644 index 0000000..a21d8d3 --- /dev/null +++ b/tests/history6.sub @@ -0,0 +1,55 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +: ${TMPDIR:=/tmp} + +HISTFILE=${TMPDIR}/history-$$ +HISTSIZE=4 +HISTIGNORE="history*" + +set -o history + +history -c + +echo 1 +echo 2 +echo 3 +echo 4 +echo 5 +echo 6 + +history + +history -d -1 +history + +echo 6 +echo 7 + +history +history -d -1 +history + +echo 7 +echo 8 +history -d -2--1 +history + +echo 9 +echo 10 +history +history -d 5-7 +history + +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..21a9063 --- /dev/null +++ b/tests/ifs-posix.tests @@ -0,0 +1,270 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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..27f27dd --- /dev/null +++ b/tests/ifs.tests @@ -0,0 +1,76 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..c4ff02c --- /dev/null +++ b/tests/intl.tests @@ -0,0 +1,68 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..2f3236e --- /dev/null +++ b/tests/intl2.sub @@ -0,0 +1,31 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# this locale causes problems all over the place +unset LC_ALL LC_NUMERIC +if locale -a | grep -i '^de_DE\.UTF.*8' >/dev/null ; then + export LANG=de_DE.UTF-8 +else + echo "intl2.sub: warning: you do not have the de_DE.UTF-8 locale installed;" >&2 + echo "intl2.sub: that will cause some of these tests to fail." >&2 +fi + +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..56c8678 --- /dev/null +++ b/tests/intl3.sub @@ -0,0 +1,36 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +. ./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..f339d41 --- /dev/null +++ b/tests/invert.tests @@ -0,0 +1,32 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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..8411c8a --- /dev/null +++ b/tests/iquote.tests @@ -0,0 +1,158 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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..685a80e --- /dev/null +++ b/tests/iquote1.sub @@ -0,0 +1,56 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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..0510e04 --- /dev/null +++ b/tests/jobs.right @@ -0,0 +1,120 @@ +./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 & +5: ok 1 +./jobs5.sub: line 40: wait: %8: no such job +2: ok 2 +2: ok 3 +127 +./jobs5.sub: line 71: declare: wpid: not found +child1 exit status 0 +[1]+ Running sleep 20 & +./jobs7.sub: line 5: fg: no current jobs +[1]+ Running sleep 20 & +0 +./jobs.tests: line 40: wait: %1: no such job +./jobs.tests: line 45: fg: no job control +wait-for-pid +wait-errors +./jobs.tests: line 58: wait: `1-1': not a pid or valid job spec +./jobs.tests: line 59: 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 +posix jobs output +[1]+ Done sleep 1 +wait-for-job +./jobs.tests: line 84: wait: %2: no such job +127 +async list wait-for-job +forked +fg-bg 1 +sleep 2 +fg-bg 2 +sleep 2 +fg-bg 3 +sleep 2 +fg-bg 4 +sleep 2 +fg-bg 5 +./jobs.tests: line 111: fg: %2: no such job +./jobs.tests: line 112: bg: job 1 already in background +fg-bg 6 +./jobs.tests: line 119: fg: -s: invalid option +fg: usage: fg [job_spec] +./jobs.tests: line 120: bg: -s: invalid option +bg: usage: bg [job_spec ...] +./jobs.tests: line 125: disown: -s: invalid option +disown: usage: disown [-h] [-ar] [jobspec ... | pid ...] +./jobs.tests: line 129: disown: %1: no such job +./jobs.tests: line 132: disown: %2: no such job +wait-for-non-child +./jobs.tests: line 135: 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 152: kill: %4: no such job +./jobs.tests: line 154: 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 4 +done diff --git a/tests/jobs.tests b/tests/jobs.tests new file mode 100644 index 0000000..dacdc15 --- /dev/null +++ b/tests/jobs.tests @@ -0,0 +1,209 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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 + +${THIS_SH} ./jobs7.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 4 & +wait $! + +echo wait-errors +wait 1-1 +wait -- -4 + +echo wait-for-background-pids +sleep 2 & +sleep 4 & +wait + +echo async list wait-for-background-pids +sleep 2 & sleep 4 & +wait + +echo async list wait for child +sleep 2 & echo forked +wait + +echo wait-when-no-children +wait + +echo posix jobs output +${THIS_SH} -o posix -c 'sleep 1 & P=$! ; sleep 2; jobs; wait' + +set -m + +echo wait-for-job +sleep 3 & +wait %2 # this should be a no-such-job error +echo $? +wait %1 + +echo async list wait-for-job +sleep 2 & echo forked +wait %1 + +echo fg-bg 1 +sleep 2 & +%1 + +echo fg-bg 2 +sleep 2 & +fg %% + +echo fg-bg 3 +sleep 2 & +fg %s + +echo fg-bg 4 +sleep 2 & +fg %?ee + +# these next two are error cases +echo fg-bg 5 +sleep 2 & +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 2 & +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 3 # 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 3 # 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 4 & +kill -STOP %1 +sleep 2 # 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..84919d9 --- /dev/null +++ b/tests/jobs1.sub @@ -0,0 +1,30 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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..1337fc1 --- /dev/null +++ b/tests/jobs3.sub @@ -0,0 +1,39 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +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..9f1cd04 --- /dev/null +++ b/tests/jobs4.sub @@ -0,0 +1,39 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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 ) & +# suppress any message about terminated process +exec 2>/dev/null +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..e348f2e --- /dev/null +++ b/tests/jobs5.sub @@ -0,0 +1,71 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +# framework to test new `wait -n' option that waits for any job to finish + +set -m + +sleep 20 & +{ sleep 2; exit 12; } & +sleep 20 & + +wait -n +echo $? + +jobs +disown -a + +{ sleep 1 ; exit 4; } & +{ sleep 2 ; exit 5; } & bgpid1=$! +{ sleep 4 ; exit 6; } & + +wait -p wvar -n %2 %3 +case "$wvar" in +$bgpid1) echo $?: ok 1;; +*) echo bad 1;; +esac + +{ sleep 1 ; exit 2; } & bgpid2=$! +wait -p wvar -n %8 $! +case $wvar in +$bgpid2) echo $?: ok 2;; +*) echo bad 2;; +esac + +disown -a + +{ sleep 3; exit 1; } & { sleep 1; exit 2; } & bgpid3=$! +{ sleep 3; exit 3; } & { sleep 3; exit 4; } & + +wait -n -p wpid %1 %2 %3 %4 + +case $wpid in +$bgpid3) echo $?: ok 3;; +*) echo bad 3 ;; +esac + +disown -a + +unset bgpid1 bgpid2 bgpid3 +unset wpid + +# now that we have no jobs, make sure that wait -n -p var leaves var unset +jobs +wait -n -p wpid +echo $wpid $? + +# make sure wait -p var does something useful without the -n option +jobs +wait -p wpid +declare -p wpid 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/jobs7.sub b/tests/jobs7.sub new file mode 100644 index 0000000..582365f --- /dev/null +++ b/tests/jobs7.sub @@ -0,0 +1,8 @@ +# make sure fg in a subshell doesn't try to start a parent's job +set -m +sleep 20 & +echo $(jobs) +echo $(fg %% ; jobs) +# suppress any message about sleep 20 being terminated +exec 2>/dev/null +kill %1 diff --git a/tests/lastpipe.right b/tests/lastpipe.right new file mode 100644 index 0000000..84e1e2e --- /dev/null +++ b/tests/lastpipe.right @@ -0,0 +1,22 @@ +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 +x=x +x=x diff --git a/tests/lastpipe.tests b/tests/lastpipe.tests new file mode 100644 index 0000000..f9d669d --- /dev/null +++ b/tests/lastpipe.tests @@ -0,0 +1,74 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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=false +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 +${THIS_SH} ./lastpipe3.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..a460286 --- /dev/null +++ b/tests/lastpipe2.sub @@ -0,0 +1,43 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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/lastpipe3.sub b/tests/lastpipe3.sub new file mode 100644 index 0000000..b9222b8 --- /dev/null +++ b/tests/lastpipe3.sub @@ -0,0 +1,11 @@ +# problem in bash-5.1 running lastpipe in subshell if fd 0 is closed + +shopt -s lastpipe +exec 0<&- + +echo x | read x +echo x=$x +unset x + +echo x | cat | read x +echo x=$x 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..4452232 --- /dev/null +++ b/tests/mapfile.right @@ -0,0 +1,170 @@ +[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 +declare -a array=([0]="a" [1]="b" [2]="c" [3]=$'\n') +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..c2ea7d2 --- /dev/null +++ b/tests/mapfile.tests @@ -0,0 +1,62 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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 + +unset -v s array +s=$'a\xffb\xffc\xff' +mapfile -t -d $'\xff' array <<<"$s" +declare -p array +unset -v s array + +${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 100644 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 100644 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 100644 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 100644 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 100644 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..f5f37c9 --- /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 285: 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 436: ${#:}: bad substitution +./more-exp.tests: line 438: ${#/}: bad substitution +./more-exp.tests: line 440: ${#%}: bad substitution +./more-exp.tests: line 442: ${#=}: bad substitution +./more-exp.tests: line 444: ${#+}: bad substitution +./more-exp.tests: line 446: ${#1xyz}: bad substitution +./more-exp.tests: line 449: #: %: 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..df12b99 --- /dev/null +++ b/tests/more-exp.tests @@ -0,0 +1,517 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..83e9ee5 --- /dev/null +++ b/tests/nameref.right @@ -0,0 +1,560 @@ +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 106: foo: readonly variable +./nameref.tests: line 107: foo: readonly variable +one +one +./nameref.tests: line 119: foo: readonly variable +./nameref.tests: line 116: 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 29: foo: invalid indirect expansion +./nameref3.sub: line 34: 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 56: 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 15: typeset: x: nameref variable self references not allowed +./nameref6.sub: line 18: typeset: x[3]: reference variable cannot be an array +./nameref6.sub: line 25: 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 16: typeset: warning: v: circular name reference +./nameref8.sub: line 16: warning: v: circular name reference +./nameref8.sub: line 18: warning: v: circular name reference +inside +inside: two +outside: +./nameref8.sub: line 42: typeset: warning: x: circular name reference +./nameref8.sub: line 42: warning: x: circular name reference +./nameref8.sub: line 44: warning: x: circular name reference +foo +./nameref8.sub: line 51: typeset: warning: v: circular name reference +./nameref8.sub: line 51: warning: v: circular name reference +./nameref8.sub: line 51: warning: v: circular name reference +local +./nameref8.sub: line 60: typeset: v: nameref variable self references not allowed +./nameref8.sub: line 67: warning: x: circular name reference +./nameref8.sub: line 68: 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 51: 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 62: typeset: somevariable: not found +./nameref10.sub: line 64: typeset: foo: not found +./nameref10.sub: line 64: typeset: somevariable: not found +declare -n foo="bar" +./nameref10.sub: line 68: typeset: bar: not found +declare -n foo="bar" +./nameref10.sub: line 70: typeset: bar: not found +declare -n foo="bar" +declare -i bar="8" +8 +declare -n foo="bar" +./nameref10.sub: line 77: typeset: bar: not found +./nameref11.sub: line 14: declare: `/': invalid variable name for name reference +./nameref11.sub: line 15: declare: `/': invalid variable name for name reference +./nameref11.sub: line 16: `/': not a valid identifier +./nameref11.sub: line 17: declare: `/': not a valid identifier +./nameref11.sub: line 18: `/': not a valid identifier +1) / +#? ./nameref11.sub: line 19: `/': not a valid identifier +x + +./nameref11.sub: line 20: ((: `0': not a valid identifier +./nameref11.sub: line 21: declare: `0': invalid variable name for name reference +./nameref11.sub: line 22: declare: `/': invalid variable name for name reference +./nameref11.sub: line 23: declare: `/': invalid variable name for name reference +/ +./nameref11.sub: line 25: `/': not a valid identifier +./nameref11.sub: line 26: exec: `10': not a valid identifier +./nameref11.sub: line 26: r: cannot assign fd to variable +./nameref11.sub: line 27: warning: r: removing nameref attribute +63 +./nameref11.sub: line 28: declare: RO: readonly variable +./nameref11.sub: line 28: RO: readonly variable +./nameref11.sub: line 29: declare: `/': invalid variable name for name reference +/ +./nameref11.sub: line 30: declare: `/': invalid variable name for name reference +./nameref11.sub: illegal option -- h +./nameref11.sub: line 31: getopts: `?': not a valid identifier +./nameref11.sub: line 32: warning: r: removing nameref attribute +declare -a r=() +./nameref11.sub: line 33: declare: r: reference variable cannot be an array +./nameref11.sub: line 34: printf: `/': not a valid identifier +./nameref11.sub: line 36: `': not a valid identifier +./nameref11.sub: line 37: declare: `': not a valid identifier +./nameref11.sub: line 38: `': not a valid identifier +./nameref11.sub: line 39: printf: `': not a valid identifier +./nameref11.sub: line 40: declare: `': invalid variable name for name reference +declare -r ROVAR="42" +./nameref11.sub: line 45: ROVAR: readonly variable +./nameref11.sub: line 45: ROVAR: cannot unset: readonly variable +declare -r ROVAR="42" +./nameref11.sub +./nameref11.sub: line 47: `@': not a valid identifier +./nameref11.sub +declare -n ref="x" +./nameref11.sub: line 52: RO: readonly variable +declare -r RO_PID +./nameref11.sub: line 52: RO: cannot unset: readonly variable +declare -r RO="x" +./nameref11.sub: line 52: declare: RO_PID: not found +./nameref11.sub: line 54: RO2: readonly variable +declare -r RO2="a" +2 +./nameref11.sub: line 65: typeset: `2': invalid variable name for name reference +2 +./nameref11.sub: line 70: typeset: `2': invalid variable name for name reference +2 +./nameref11.sub: line 75: foo[2]: invalid indirect expansion +./nameref11.sub: line 76: bar: invalid indirect expansion +./nameref12.sub: line 19: declare: `/': invalid variable name for name reference +./nameref12.sub: line 22: declare: `%': invalid variable name for name reference +./nameref12.sub: line 26: `^': not a valid identifier +declare -n r +declare -a foo +declare -a foo=([0]="7") +./nameref12.sub: line 39: declare: `42': not a valid identifier +./nameref12.sub: line 40: declare: x: not found +declare -nr RO="foo" +/ +./nameref12.sub: line 58: declare: `7*6': not a valid identifier +./nameref12.sub: line 58: declare: foo: not found +./nameref12.sub: line 60: `7*6': not a valid identifier +declare -n ref="var" +declare -n ref="var" +./nameref12.sub: line 87: 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 104: `': not a valid identifier +declare -n ref +declare -- ref="global" +declare -a var=([0]="foo2") +./nameref12.sub: line 113: 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 101: typeset: `12345': invalid variable name for name reference +declare -n foo +./nameref13.sub: line 110: 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 36: 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 45: typeset: var: not found +declare -n ref="var" +./nameref15.sub: line 14: local: warning: a: circular name reference +./nameref15.sub: line 14: warning: a: circular name reference +./nameref15.sub: line 14: `a[0]': not a valid identifier +declare -a a=([0]="0") +./nameref15.sub: line 14: local: warning: a: circular name reference +./nameref15.sub: line 14: warning: a: circular name reference +./nameref15.sub: line 14: warning: a: circular name reference +declare -a a=([0]="X") +declare -a b=([0]="X") +./nameref15.sub: line 14: local: warning: a: circular name reference +./nameref15.sub: line 14: warning: a: circular name reference +./nameref15.sub: line 14: `a[0]': not a valid identifier +declare -a b=([0]="0") +./nameref15.sub: line 32: typeset: warning: ref: circular name reference +./nameref15.sub: line 32: warning: ref: circular name reference +./nameref15.sub: line 33: warning: ref: circular name reference +./nameref15.sub: line 34: warning: ref: circular name reference +inside X +outside X +before: 7 +./nameref15.sub: line 45: typeset: warning: xxx: circular name reference +./nameref15.sub: line 45: warning: xxx: circular name reference +./nameref15.sub: line 46: warning: xxx: circular name reference +declare -n xxx="xxx" +./nameref15.sub: line 48: warning: xxx: circular name reference +xxx_func: inside: xxx = foo +after: foo +./nameref15.sub: line 59: typeset: ref: nameref variable self references not allowed +./nameref15.sub: line 61: 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 78: var[@]: bad array subscript +declare -n bar="var[@]" +./nameref15.sub: line 83: var[@]: bad array subscript +declare -n a="b" +declare -n b="a[1]" +./nameref15.sub: line 91: warning: a: removing nameref attribute +declare -a a=([1]="foo") +declare -n b="a[1]" +./nameref15.sub: line 96: 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 112: typeset: n: not found +declare -a v=([0]="0" [1]="1") +declare -n n="v[1]" +declare -a v=([0]="0") +./nameref15.sub: line 120: warning: xref: removing nameref attribute +declare -a xref=([1]="one") +./nameref15.sub: line 126: warning: xref: removing nameref attribute +declare -a xref=([1]="one") +declare -n r1="y" +declare -n r2="x" +./nameref16.sub: line 25: typeset: x: not found +./nameref16.sub: line 25: typeset: y: not found +declare -n r1="y" +declare -n r2="x" +./nameref16.sub: line 34: typeset: x: not found +./nameref16.sub: line 34: typeset: y: not found +declare -n r1="y" +declare -n r2="x" +./nameref16.sub: line 46: typeset: x: not found +./nameref16.sub: line 46: typeset: y: not found +declare -n r1="y" +declare -n r2="x" +declare -- x="one" +declare -- y="two" +./nameref17.sub: line 21: declare: bar: not found +./nameref17.sub: line 22: unset: foo0: cannot unset: readonly variable +declare -nr foo0="bar" +declare -nr foo0="bar" +declare -- bar +./nameref17.sub: line 27: declare: foo0: readonly variable +./nameref17.sub: line 28: declare: foo0: readonly variable +declare -nr foo1 +./nameref17.sub: line 37: typeset: foo1: readonly variable +declare -nr foo1 +declare -n foo2="bar" +declare -r bar +./nameref17.sub: line 48: bar: readonly variable +./nameref17.sub: line 49: typeset: bar: readonly variable +declare -n foo2="bar" +declare -r bar +declare -- bar3="three" +./nameref17.sub: line 59: unset: foo3: cannot unset: readonly variable +./nameref17.sub: line 62: declare: bar3: readonly variable +declare -nr foo3="bar3" +declare -r bar3="three" +./nameref17.sub: line 64: declare: foo3: readonly variable +declare -nr foo4="bar4" +declare -- bar4="four" +./nameref17.sub: line 76: typeset: foo4: readonly variable +declare -nr foo4="bar4" +declare -nr foo4="bar4" +declare -- bar4="four" +./nameref17.sub: line 92: 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 15: mapfile: `XXX[0]': not a valid identifier +./nameref18.sub: line 16: declare: XXX[0]: not found +./nameref18.sub: line 22: `XXX[0]': not a valid identifier +./nameref18.sub: line 23: declare: XXX[0]: not found +declare -n ref="XXX[0]" +declare -a XXX=([0]="4") +./nameref18.sub: line 37: `XXX[0]': not a valid identifier +declare -n ref="XXX[0]" +./nameref18.sub: line 38: declare: XXX[0]: not found +./nameref18.sub: line 42: read: `XXX[0]': not a valid identifier +./nameref18.sub: line 43: declare: XXX[0]: not found +./nameref18.sub: line 48: `XXX[0]': not a valid identifier +declare -n ref="XXX[0]" +./nameref18.sub: line 51: `XXX[0]': not a valid identifier +./nameref18.sub: line 51: declare: XXX[0]: not found +declare -n ref="var[123]" +./nameref18.sub: line 59: declare: var[123]: not found +declare -a var=([123]="") +declare -n ref="var[123]" +./nameref18.sub: line 63: declare: var[123]: not found +declare -a var=([123]="") +declare -n ref="var[123]" +./nameref18.sub: line 67: declare: var[123]: not found +declare -a var=([123]="X") +argv[1] = <1> +argv[2] = <2> +argv[3] = <3> +argv[1] = <1> +argv[2] = <2> +argv[3] = <3> +argv[1] = <1> +argv[2] = <2> +argv[3] = <3> +argv[1] = <1> +argv[2] = <2> +argv[3] = <3> +argv[1] = <1> +argv[2] = <2> +argv[3] = <31> +argv[4] = <2> +argv[5] = <3> +declare -n foo="bar" +declare -- foo="bar" +./nameref19.sub: line 22: 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 +8 +declare -n ivar="foo" +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 36: declare: var: not found +outside: +declare -a foo=([0]="X") +declare -n ref="var" +declare -a var=([0]="X") +outside: +./nameref20.sub: line 51: declare: ref: not found +./nameref20.sub: line 51: declare: var: not found +declare -n ref="var" +declare -- var="X" +outside: +./nameref20.sub: line 58: declare: ref: not found +./nameref20.sub: line 58: declare: var: not found +declare -n ref="var" +declare -a var=([0]="Y") +declare -- ref="Y" +declare -- var="X" +declare -- ref="Y" +declare -- ref="Y" +./nameref20.sub: line 74: declare: var: not found +declare -- 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" +a string with spaces +many spaces +declare -n foo="bar[0]" +declare -a bar=([0]=" still more spaces") +declare -n foo="bar[0]" +declare -a bar=([0]="spaces still more spaces") +./nameref22.sub: line 50: declare: array: reference variable cannot be an array +./nameref22.sub: line 53: declare: array[128]: reference variable cannot be an array +declare -a array=([0]="one" [1]="two" [2]="three") +declare -- array="(one two three)" +declare -a array=([0]="one" [1]="two" [2]="three") +./nameref22.sub: line 69: declare: `(one two three)': invalid variable name for name reference +./nameref22.sub: line 70: declare: array: reference variable cannot be an array +declare -a array=([0]="zero") +./nameref22.sub: line 74: declare: array: reference variable cannot be an array +declare -a array=([0]="one" [1]="two" [2]="three") +./nameref22.sub: line 79: declare: array: reference variable cannot be an array +declare -a array +declare -ai array=([0]="one") +declare -a array=([0]="zero") +declare -a array=([0]="one" [1]="two" [2]="three") +declare -ai a=([0]="5") +declare -ai a=([0]="6") +declare -ai a=([0]="1") +./nameref23.sub: line 15: declare: b: not found +declare -ai a=([0]="1") +declare -- b="1" +declare -ai a=([0]="1") +declare -- b="11" +declare -ai a=([0]="1") +declare -- b="110" +./nameref23.sub: line 25: declare: `1': invalid variable name for name reference +declare -ai a=([0]="1") +./nameref23.sub: line 27: declare: b: not found +declare -ai a=([0]="4") +declare -in b="a[0]" +declare -ai a=([0]="6") +declare -in b="a[0]" +foo +foo bar +declare -a a=([0]="" [1]="foo bar") +declare -n b="a[1]" +foo +foo bar +declare -a a=([0]="" [1]="foo bar") +declare -n b="a[1]" +12 +16 +declare -ai a=([0]="0" [1]="16") +12 +16 +declare -ai a=([0]="0" [1]="16") diff --git a/tests/nameref.tests b/tests/nameref.tests new file mode 100644 index 0000000..3a6c5d9 --- /dev/null +++ b/tests/nameref.tests @@ -0,0 +1,133 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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..742755b --- /dev/null +++ b/tests/nameref10.sub @@ -0,0 +1,77 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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..ea14c0d --- /dev/null +++ b/tests/nameref11.sub @@ -0,0 +1,76 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..199b51c --- /dev/null +++ b/tests/nameref12.sub @@ -0,0 +1,113 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..5c56428 --- /dev/null +++ b/tests/nameref13.sub @@ -0,0 +1,115 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..a14c440 --- /dev/null +++ b/tests/nameref14.sub @@ -0,0 +1,56 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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..e9a09ee --- /dev/null +++ b/tests/nameref15.sub @@ -0,0 +1,127 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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 + +declare -n xref +declare -a xref[1]=one +declare -p xref + +unset xref +declare -n xref +xref=array +declare -a xref[1]=one +declare -p xref diff --git a/tests/nameref16.sub b/tests/nameref16.sub new file mode 100644 index 0000000..d07a3a0 --- /dev/null +++ b/tests/nameref16.sub @@ -0,0 +1,57 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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..b8c3cc7 --- /dev/null +++ b/tests/nameref17.sub @@ -0,0 +1,116 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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..7a32877 --- /dev/null +++ b/tests/nameref18.sub @@ -0,0 +1,83 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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 + +unset -n ref +unset var + +arr=(1 2 3) + +indir='arr[@]' +declare -n ref='arr[@]' + +recho "${!indir}" +recho ${!indir} + +recho "$ref" +recho $ref + +recho "${!indir}$ref" diff --git a/tests/nameref19.sub b/tests/nameref19.sub new file mode 100644 index 0000000..d4b900e --- /dev/null +++ b/tests/nameref19.sub @@ -0,0 +1,73 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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 + +# but when we add the nameref attribute, we remove other attributes + +declare -i ivar +ivar=4+4 +echo $ivar + +declare -n ivar=foo +declare -p ivar 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..715bc4d --- /dev/null +++ b/tests/nameref20.sub @@ -0,0 +1,84 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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..08d8f56 --- /dev/null +++ b/tests/nameref21.sub @@ -0,0 +1,69 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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/nameref22.sub b/tests/nameref22.sub new file mode 100644 index 0000000..4e44fbb --- /dev/null +++ b/tests/nameref22.sub @@ -0,0 +1,97 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +declare -n foo=bar + +declare foo='a string with spaces' +echo $foo + +unset foo +declare foo+='many spaces' +echo $foo + +unset foo # unsets bar +unset -n foo + +declare -a bar +declare -n foo='bar[0]' +declare foo+=' still more spaces' + +declare -p foo bar +unset -n foo +unset bar + +declare -a bar +declare -n foo='bar[0]' +declare foo=spaces +declare foo+=' still more spaces' + +declare -p foo bar + +unset -n foo +unset bar + +ray=ray + +declare -a array +array[0]=zero + +declare -n array +unset array + +declare -n array[128] +unset array + +declare -a array='(one two three)' +declare -p array +unset array + +declare array='(one two three)' +declare -p array +unset array + +declare -a ar$ray='(one two three)' +declare -p ar$ray +unset array + +declare -a array=(zero) +declare -n array='(one two three)' +declare -n array=three +declare -p array +unset array + +declare -n array=(one two three) +declare -p array +unset array + +declare -a array +declare -n array=one +declare -p array +unset array + +array=one +declare -i array[64]; +declare -p array +unset array + +declare -a array=zero +declare -p array +unset array + +declare -a array +declare array='(one two three)' +declare -p array +unset array + + diff --git a/tests/nameref23.sub b/tests/nameref23.sub new file mode 100644 index 0000000..358c381 --- /dev/null +++ b/tests/nameref23.sub @@ -0,0 +1,82 @@ +declare -ai a +a[0]=4 +declare -n b='a[0]' + +b+=1 ; declare -p a + +declare b+=1 ; declare -p a + +unset a b +unset -n b + +###### +declare -ai a=(1) +declare -in b="a[0]" +declare -p a b + +b+=1 ; declare -p a b +b+=1 ; declare -p a b +b+=0 ; declare -p a b + +unset a b + +##### +declare -ai a=(1) +declare -n b="1" +declare -p a +declare -np b + +unset a ; unset -n b + +##### +declare -ai a=('4'); +declare -n b='a[0]'; +declare -ni b; # this should maybe not be allowed, but it is for now +declare -p a b + +b+=2; +declare -p a b + +unset a ; unset -n b + +##### +f() +{ + local -a a=('' 'foo'); + local -n b=a[1]; + echo $b; + b+=\ bar; + echo $b; + declare -p a b; +} +f + +declare -a a=('' 'foo'); +declare -n b=a[1]; +echo $b; +b+=\ bar; +echo $b; +declare -p a b + +unset a ; unset -n b + +unset -f f +f() +{ + local -ai a=(0 12); + local -n b=a[1]; + echo $b; + b+=4; + echo $b; + declare -p a; +} +f + +declare -ai a=(0 12); +declare -n b=a[1]; +echo $b; +b+=4; +echo $b; +declare -p a + +unset a ; unset -n b diff --git a/tests/nameref3.sub b/tests/nameref3.sub new file mode 100644 index 0000000..67cb098 --- /dev/null +++ b/tests/nameref3.sub @@ -0,0 +1,50 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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..6367d56 --- /dev/null +++ b/tests/nameref4.sub @@ -0,0 +1,234 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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..6855e99 --- /dev/null +++ b/tests/nameref5.sub @@ -0,0 +1,63 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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..8497967 --- /dev/null +++ b/tests/nameref6.sub @@ -0,0 +1,57 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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..5e67ac0 --- /dev/null +++ b/tests/nameref7.sub @@ -0,0 +1,31 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..465463b --- /dev/null +++ b/tests/nameref8.sub @@ -0,0 +1,74 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..e3dc40e --- /dev/null +++ b/tests/new-exp.right @@ -0,0 +1,795 @@ +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 41: 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 197: ABX: unbound variable +./new-exp.tests: line 201: $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 55: /tmp/redir-notthere: No such file or directory +1 + +./new-exp2.sub: line 62: 1111111111111111111111: command not found + +argv[1] = <6> +./new-exp.tests: line 302: ${#:}: 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 520: $9: unbound variable +./new-exp.tests: line 521: 9: unbound variable +./new-exp.tests: line 522: UNSET: unbound variable +./new-exp.tests: line 523: UNSET: unbound variable +./new-exp.tests: line 524: UNSET: unbound variable +./new-exp.tests: line 525: UNSET: unbound variable +./new-exp.tests: line 526: 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 36: ${!_Q* }: bad substitution +./new-exp3.sub: line 41: ${!1*}: bad substitution +./new-exp3.sub: line 43: ${!@*}: 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 546: ${$(($#-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 565: $(($# - 2)): substring expression < 0 +./new-exp.tests: line 567: -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'> +bash: line 1: ${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.2]$ > +< +> +<' \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=([four]="de" [two]="b c" [three]="" [one]="1" ) +r +a +A +ir +a b c d e +5 +a5b +i +declare -i foo +A +declare -A foo +./new-exp10.sub: line 118: ${V@}: bad substitution +abcxxxdef +abcÃ¥def +ḅć +Ã¥ +prependḅć +Ã¥append +prependÃ¥ +ḅćappend +Ã¥ +ḅć +ḅć +ḅć +Ã¥ +Ã¥ +Ã¥ +ḅć +Ã¥ +Ã¥ +ḅć +ḅć +HELLO;1 foo;2 foo; +PASS;1 foo;2 foo; +after: PASS +'zzz' +'zzz' +declare -rl VAR1 +declare -rl VAR1 +declare -rl VAR1 +declare -rl VAR1 +rl +rl +rl +rl +declare -arl VAR3 +declare -arl VAR3 +declare -arl VAR3 +declare -arl VAR3 +arl +arl +arl +arl +one +one +'aaa' +'aaa' 'bbb' +./new-exp13.sub: line 56: aaa bbb: invalid variable name +aaa bbb +0 1 +'aaa' +'aaa' 'bbb' +'aaa' 'bbb' +'aaa' 'bbb' +a bbb +aaa bb +'string' +'string' +'value with spaces' +'value with spaces' +'a b' 'c d' 'e f' +'a b' 'c d' 'e f' +0 "zero" 1 "one" 2 "two" 3 "three" +0 "zero z" 1 "one o" 2 "two t" 3 "three t" +argv[1] = <0> +argv[2] = <zero z> +argv[3] = <1> +argv[4] = <one o> +argv[5] = <2> +argv[6] = <two t> +argv[7] = <3> +argv[8] = <three t> +declare -a foo=() +ai +declare -ai foo +bash: line 1: foo: unbound variable +ai +declare -ai foo +bash: line 1: !bar: unbound variable +a +a +a +a +/homes/chetdefg +/homes/chetdefg +~defg +defg +defg +defg +$'&' $'&' $'&' $'&' $'&' $'&' $'&' +$'a' $'b' $'c' $'d' $'e' $'f' $'g' +a b c d e f g +a b c d e f g +& & & & & & & +& & & & & & & +& & & & & & & +\& \& \& \& \& \& \& +a a a a a a a +3 3 3 3 3 3 3 +abc defg +abc defg +& defg +& defg +& defg +\& defg +\abc defg +abcdefg +&defg +\abcdefg +\&defg +\&defg +\abcdefg +\\&defg +&defg +&defg +\&defg +\&defg +\\&defg +letx&yee +letx&yee +letxssyee +letxssyee +letx\&yee +letx\&yee +letx&yee +letx&yee +let\&ee +let\\ssee +let\ssee +let\ssee +let\&ee +let\&ee +let&ee +let&ee +twoone +&twoone +onetwo +one&two +two +&two +otwone +&twone +argv[1] = </> +argv[1] = </> + +./new-exp.tests: line 1: ABXD: parameter unset diff --git a/tests/new-exp.tests b/tests/new-exp.tests new file mode 100644 index 0000000..c542313 --- /dev/null +++ b/tests/new-exp.tests @@ -0,0 +1,654 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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))} +set a b c d e +recho ${@: -3:-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 + +# indirect expansion with arrays and local variables +${THIS_SH} ./new-exp12.sub + +# more indirect expansion and parameter transformation issues +${THIS_SH} ./new-exp13.sub + +# new K parameter transformation operator +${THIS_SH} ./new-exp14.sub + +# ongoing work with a/A parameter transformations and `nounset' +${THIS_SH} ./new-exp15.sub + +# pattern substitution with `&' (quoted and unquoted) in the replacement string +${THIS_SH} ./new-exp16.sub + + +# problems with stray CTLNUL in bash-4.0-alpha +unset a +a=/a +recho "/${a%/*}" +recho "/${a///a/}" + +patfunc() +{ + echo ${1##*"${1##*}"} +} +patfunc foo + +# caused core dumps because of bad bracket expression parsing in bash-5.0 +eval : $'${x/#[0\xef\xbf\xbd\\Z[:]]}' + +expect $0: 'ABXD: parameter unset' +${THIS_SH} -c 'recho ${ABXD:?"parameter unset"}' $0 diff --git a/tests/new-exp1.sub b/tests/new-exp1.sub new file mode 100644 index 0000000..d29b93c --- /dev/null +++ b/tests/new-exp1.sub @@ -0,0 +1,29 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..5b199d4 --- /dev/null +++ b/tests/new-exp10.sub @@ -0,0 +1,118 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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 + +# this needs to be run in a subshell because invalid transformation operators +# are now treated as substitution errors, fatal in non-interactive shells +${THIS_SH} -c 'x=abcdef ; printf "<%s>" "${x@C}"' bash + +# 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 + +V=42 +echo ${V@} # error diff --git a/tests/new-exp11.sub b/tests/new-exp11.sub new file mode 100644 index 0000000..6a9edd5 --- /dev/null +++ b/tests/new-exp11.sub @@ -0,0 +1,59 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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-exp12.sub b/tests/new-exp12.sub new file mode 100644 index 0000000..1fbd5d6 --- /dev/null +++ b/tests/new-exp12.sub @@ -0,0 +1,40 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# +# make sure indirect expansion for arrays uses the closest-scope instance +# of the resulting variable name + +array_1=("PASS") +array_2=("1 foo" "2 foo") + +unsafe_fn () +{ + local array_1=('HELLO') + local a=("${!1}") b=("${!2}") + printf '%s;' "${a[@]}" "${b[@]}" + printf '\n' +} + +safe_fn () +{ + local a=("${!1}") b=("${!2}") + local array_1=('FAIL') + printf '%s;' "${a[@]}" "${b[@]}" + printf '\n' +} + +unsafe_fn 'array_1[@]' 'array_2[@]' +safe_fn 'array_1[@]' 'array_2[@]' + +echo after: ${array_1[@]} diff --git a/tests/new-exp13.sub b/tests/new-exp13.sub new file mode 100644 index 0000000..7e8ed32 --- /dev/null +++ b/tests/new-exp13.sub @@ -0,0 +1,72 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +declare -lr VAR1 +declare -lr VAR2=zzz +declare -alr VAR3 + +var=VAR2 + +echo ${!var@Q} +echo ${VAR2@Q} + +echo ${VAR1@A} +echo ${VAR1[@]@A} +echo "${VAR1@A}" +echo "${VAR1[@]@A}" + +echo "${VAR1[@]@a}" +echo ${VAR1[@]@a} +echo "${VAR1@a}" +echo ${VAR1@a} + +echo ${VAR3@A} +echo ${VAR3[@]@A} +echo "${VAR3@A}" +echo "${VAR3[@]@A}" + +echo "${VAR3[@]@a}" +echo ${VAR3[@]@a} +echo "${VAR3@a}" +echo ${VAR3@a} + +var=one + +echo ${var} +echo ${var[@]} + +VAR4=(aaa bbb) + +varname=VAR4 + +echo ${!varname[@]@Q} + +echo ${VAR4[@]@Q} +echo ${!VAR4[@]@Q} + +echo ${VAR4[@]} +echo ${!VAR4[@]} + +VAR5=(aaa bbb) +varname="VAR5[@]" + +echo "${VAR5@Q}" +echo "${VAR5[@]@Q}" + +echo "${!varname@Q}" +echo "${!varname[@]@Q}" + +# caused core dumps through bash-5.0 +echo "${!varname##aa}" +echo "${!varname[@]%b}" diff --git a/tests/new-exp14.sub b/tests/new-exp14.sub new file mode 100644 index 0000000..92f51ea --- /dev/null +++ b/tests/new-exp14.sub @@ -0,0 +1,36 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +# test the other uses of the 'K' transform operator and its sibling 'k' +# the associative array tests are performed separately, since that was the +# original motivation for this feature +foo=string +bar='value with spaces' + +set -- 'a b' 'c d' 'e f' + +echo ${foo@K} +echo ${foo@k} +echo ${bar@K} +echo ${bar@k} + +echo ${@@K} +echo "${@@K}" + +foo=( zero one two three ) +echo ${foo[@]@K} + +foo=( 'zero z' 'one o' 'two t' 'three t' ) +echo ${foo[@]@K} +recho "${foo[@]@k}" diff --git a/tests/new-exp15.sub b/tests/new-exp15.sub new file mode 100644 index 0000000..f8b9ed8 --- /dev/null +++ b/tests/new-exp15.sub @@ -0,0 +1,29 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +: ${THIS_SH:=./bash} + +${THIS_SH} -c 'declare -a foo=() ; declare -p foo' bash + +${THIS_SH} -c 'declare -ia foo=() ; echo ${foo@a} ; echo ${foo@A}' bash +${THIS_SH} -uc 'declare -ia foo=() ; echo ${foo@a} ; echo ${foo@A}' bash + +${THIS_SH} -c 'declare -ia foo=() ; bar=foo; echo ${!bar@a} ; echo ${!bar@A}' bash +${THIS_SH} -uc 'declare -ia foo=() ; bar=foo; echo ${!bar@a} ; echo ${!bar@A}' bash + +${THIS_SH} -c 'declare -a foo=( [1]=one ) ; echo ${foo@a}' bash +${THIS_SH} -uc 'declare -a foo=( [1]=one ) ; echo ${foo@a}' bash + +${THIS_SH} -c 'declare -a foo=( [1]=one ) ; bar=foo; echo ${!bar@a}' bash +${THIS_SH} -uc 'declare -a foo=( [1]=one ) ; bar=foo; echo ${!bar@a}' bash diff --git a/tests/new-exp16.sub b/tests/new-exp16.sub new file mode 100644 index 0000000..2ed751d --- /dev/null +++ b/tests/new-exp16.sub @@ -0,0 +1,120 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +HOME=/homes/chet +string=abcdefg +set -- a b c + +shopt -u patsub_replacement + +# verify existing behavior +echo ${string/abc/~} +echo "${string/abc/~}" +echo ${string/abc/"~"} + +echo ${string/abc/$notthere} +echo "${string/abc/$notthere}" +echo "${string/abc/"$notthere"}" + +echo ${string//?/\$\'&\' } + +shopt -s patsub_replacement + +echo ${string//?/\$\'&\' } + +echo ${string//?/& } +echo "${string//?/& }" + +echo ${string//?/\& } +echo "${string//?/\& }" +echo ${string//?/"& "} +echo ${string//?/"\& "} + +echo "${string//?/"a "}" +echo "${string//?/"$# "}" + +echo ${string/abc/& } +echo "${string/abc/& }" +echo ${string/abc/"& "} + +echo ${string/abc/\& } +echo "${string/abc/\& }" +echo ${string/abc/"\& "} +echo ${string/abc/\\& } + +rep='\\&' + +echo "${string/abc/&}" +echo ${string/abc/\&} +echo "${string/abc/\\&}" +echo ${string/abc/"\\&"} +echo "${string/abc/"\\&"}" +echo ${string/abc/$rep} +echo ${string/abc/"$rep"} + +shopt -u patsub_replacement + +echo "${string/abc/&}" +echo ${string/abc/\&} +echo "${string/abc/\\&}" +echo "${string/abc/"\\&"}" +echo ${string/abc/"$rep"} + +shopt -s patsub_replacement + +repl='x&y' +r2='x\&y' +var='letssee' + +pat=ss + +echo ${var//$pat/"$repl"} +echo "${var//$pat/"$repl"}" +echo ${var//$pat/$repl} +echo "${var//$pat/$repl}" + +echo ${var//$pat/"$r2"} +echo "${var//$pat/"$r2"}" +echo ${var//$pat/$r2} +echo "${var//$pat/$r2}" + +r2='\\&' +r3='\&' + +echo ${var//$pat/\\\&} +echo ${var//$pat/\\$r2} +echo ${var//$pat/\\&} +echo ${var//$pat/$r2} + +echo ${var//$pat/"\&"} +echo ${var//$pat/"$r3"} +echo ${var//$pat/"&"} +echo ${var//$pat/$r3} + +# these cases provide the same functionality as sed when given a BRE like +# `^' or `$', or when passed a null input line +one=one +null= + +echo ${one/#/&two} +echo ${one/#/\&two} + +echo ${one/%/&two} +echo ${one/%/\&two} + +echo ${null/#/&two} +echo ${null/#/\&two} + +echo ${one/#?/&two} +echo ${one/#?/\&two} diff --git a/tests/new-exp2.sub b/tests/new-exp2.sub new file mode 100644 index 0000000..8dfe788 --- /dev/null +++ b/tests/new-exp2.sub @@ -0,0 +1,62 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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-existent 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..a0c6586 --- /dev/null +++ b/tests/new-exp3.sub @@ -0,0 +1,43 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +: +# 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..e491f5c --- /dev/null +++ b/tests/new-exp4.sub @@ -0,0 +1,43 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +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..cb203a7 --- /dev/null +++ b/tests/new-exp5.sub @@ -0,0 +1,53 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..83b041a --- /dev/null +++ b/tests/new-exp6.sub @@ -0,0 +1,42 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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..9effec5 --- /dev/null +++ b/tests/new-exp8.sub @@ -0,0 +1,129 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..799f192 --- /dev/null +++ b/tests/new-exp9.sub @@ -0,0 +1,44 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..31c35c3 --- /dev/null +++ b/tests/nquote.right @@ -0,0 +1,80 @@ +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'> +argv[1] = <a^Ib^Ic> +argv[1] = <$'a\tb\tc'> + AD +E +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 +foo +./nquote4.sub: line 6: quux: command not found +argv[1] = <a^A)b> +argv[1] = <a^Ab> +argv[1] = <^A> +argv[1] = <\^A> +0000000 a $ ' \ 0 1 ' b \n a 001 b \n +0000015 +0000000 a $ ' \ 0 1 ' b \n a 001 b \n +0000015 +0000000 A \n A \n +0000004 diff --git a/tests/nquote.tests b/tests/nquote.tests new file mode 100644 index 0000000..e4d1a56 --- /dev/null +++ b/tests/nquote.tests @@ -0,0 +1,142 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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' )" + +# tests for $'...' not being expanded when inside double quotes +recho $'a\tb\tc' +recho "$'a\tb\tc'" + +# tests for $'...' being expanded in command substitution, and when +echo "$(echo $'\t\t\101\104\n\105')" + +${THIS_SH} ./nquote1.sub +${THIS_SH} ./nquote2.sub +${THIS_SH} ./nquote3.sub +${THIS_SH} ./nquote4.sub +${THIS_SH} ./nquote5.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..679976c --- /dev/null +++ b/tests/nquote1.tests @@ -0,0 +1,119 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..bfe2b19 --- /dev/null +++ b/tests/nquote2.sub @@ -0,0 +1,42 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..e3af99a --- /dev/null +++ b/tests/nquote2.tests @@ -0,0 +1,95 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..44b51c4 --- /dev/null +++ b/tests/nquote3.tests @@ -0,0 +1,98 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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.sub b/tests/nquote4.sub new file mode 100644 index 0000000..0d4a495 --- /dev/null +++ b/tests/nquote4.sub @@ -0,0 +1,6 @@ +# make sure aliases containing new-style single quotes are expanded correctly + +shopt -s expand_aliases +alias foo=$'echo foo\n\nquux\n' + +foo diff --git a/tests/nquote4.tests b/tests/nquote4.tests new file mode 100644 index 0000000..5c67705 --- /dev/null +++ b/tests/nquote4.tests @@ -0,0 +1,37 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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.sub b/tests/nquote5.sub new file mode 100644 index 0000000..97cbadc --- /dev/null +++ b/tests/nquote5.sub @@ -0,0 +1,36 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +. test-glue-functions + +recho $( echo a$'\01)'b ) +recho $( echo ab ) +recho $( echo \ ) +recho $( echo \\ ) + +LC_CTYPE=C +od -c <<EOF | _intl_normalize_spaces +a$'\01'b +ab +EOF + +od -c <<EOF | _intl_normalize_spaces +${none-a$'\01'b} +${none-ab} +EOF + +V=Aa$'\01'b +od -c <<EOF | _intl_normalize_spaces +${V%a$'\01'b} +${V%ab} +EOF diff --git a/tests/nquote5.tests b/tests/nquote5.tests new file mode 100644 index 0000000..ca0308d --- /dev/null +++ b/tests/nquote5.tests @@ -0,0 +1,76 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..3a01004 --- /dev/null +++ b/tests/parser.right @@ -0,0 +1,16 @@ +AAA +bash5: line 1: `invalid-name': not a valid identifier +in +in +in +in +bash5: -c: line 1: syntax error near unexpected token `)' +bash5: -c: line 1: `case x in esac) echo done; esac' +in +bash5: -c: line 1: syntax error near unexpected token `do' +bash5: -c: line 1: `case in do do) echo in; esac' +bash5: -c: line 1: syntax error near unexpected token `(' +bash5: -c: line 1: `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..5d3f734 --- /dev/null +++ b/tests/posix2.right @@ -0,0 +1,4 @@ +Testing for POSIX.2 conformance +./posix2.tests: eval: line 199: syntax error near unexpected token `)' +./posix2.tests: eval: line 199: `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..0f5fce1 --- /dev/null +++ b/tests/posix2.tests @@ -0,0 +1,206 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +# 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 + +# POSIX.2 grammar rule 4 problem through bash-5.1 +newtest +eval 'case esac in (esac) ;; *) testfail "case esac test 3" ;; esac' + +# these are supposed to be syntax errors +newtest +eval 'case esac in esac) ;; *) echo "case esac test 4";; esac' && testfail 'case esac test 4' + +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..39af9a5 --- /dev/null +++ b/tests/posix2syntax.sub @@ -0,0 +1,66 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +: ${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..7204b96 --- /dev/null +++ b/tests/posixexp.right @@ -0,0 +1,308 @@ +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 ] +1: OK +2: $'not' +3: OK +4: OK +5: tOK +OK +OK +$'not' +OK +tOK +6: $'not\ttoo\nbad' +OKa ' b +OKa ' b +7: OK +8: OKa ' b +9: OKa " b +10: OKa " b +tOK +tOK +tOK +tOK +./posixexp7.sub: line 69: ${'x1'%'t'}: bad substitution +./posixexp7.sub: line 70: ${'x1'%'t'}: bad substitution +./posixexp7.sub: line 73: ${'x1'%'t'}: bad substitution +./posixexp7.sub: line 74: ${'x1'%'t'}: bad substitution +"A" +A +argv[1] = <"A"> +argv[1] = <A> +argv[1] = <A> +./posixexp.tests: line 97: unexpected EOF while looking for matching `}' diff --git a/tests/posixexp.tests b/tests/posixexp.tests new file mode 100644 index 0000000..d8f6644 --- /dev/null +++ b/tests/posixexp.tests @@ -0,0 +1,97 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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_SH} ./posixexp8.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..c0d6861 --- /dev/null +++ b/tests/posixexp1.sub @@ -0,0 +1,51 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# $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..5c46192 --- /dev/null +++ b/tests/posixexp2.sub @@ -0,0 +1,37 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +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..5f2392b --- /dev/null +++ b/tests/posixexp2.tests @@ -0,0 +1,60 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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..343adfe --- /dev/null +++ b/tests/posixexp3.sub @@ -0,0 +1,65 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..9d48b2f --- /dev/null +++ b/tests/posixexp4.sub @@ -0,0 +1,44 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..b0e1c03 --- /dev/null +++ b/tests/posixexp5.sub @@ -0,0 +1,64 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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..b89b87f --- /dev/null +++ b/tests/posixexp6.sub @@ -0,0 +1,70 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..4e3fa00 --- /dev/null +++ b/tests/posixexp7.sub @@ -0,0 +1,76 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# test the effect of quotes on the WORD in the posix pattern removal operators +# +x=notOK +x1=not + +cat <<EOF +1: ${x#$'not'} +2: $'not' +3: ${x#"not"} +4: ${x#'not'} +5: ${x#${x1%'t'}} +EOF + +echo "${x#'not'}" +echo "${x#$'not'}" + +echo "$'not'" +echo "${x#"not"}" +echo "${x#${x1%'t'}}" + +cat <<EOF +6: $'not\ttoo\nbad' +EOF + +x=OK$'a\t\'\tb' +echo OK$'a\t\'\tb' +echo "$x" + +cat <<EOF +7: ${x%$'a\t\'\tb'} +8: ${x#$'a\t\'\tb'} +EOF + +x=OK'a " b' + +cat <<EOF +9: ${x#'a " b'} +10: ${x#$'a " b'} +EOF + +x=notOK +x1=not + +# extquote makes these work +echo "${x#${$'x1'%$'t'}}" +cat <<EOF +${x#${$'x1'%$'t'}} +EOF +echo "${x#${$'x1'%'t'}}" +cat <<EOF +${x#${$'x1'%'t'}} +EOF + +# syntax errors + +echo "${x#${'x1'%'t'}}" +cat <<EOF +${x#${'x1'%'t'}} +EOF +echo "${x#${'x1'%$'t'}}" +cat <<EOF +${x#${'x1'%$'t'}} +EOF diff --git a/tests/posixexp8.sub b/tests/posixexp8.sub new file mode 100644 index 0000000..383851c --- /dev/null +++ b/tests/posixexp8.sub @@ -0,0 +1,11 @@ +P=A + +cat << EOF +${P+\"$P\"} +${P+"$P"} +EOF + +recho "${P+\"$P\"}" + +recho "${P+"$P"}" +recho ${P+"$P"} 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..5a7bafd --- /dev/null +++ b/tests/posixpat.tests @@ -0,0 +1,247 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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..fa8febe --- /dev/null +++ b/tests/posixpipe.tests @@ -0,0 +1,56 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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.tests b/tests/precedence.tests new file mode 100644 index 0000000..111bd23 --- /dev/null +++ b/tests/precedence.tests @@ -0,0 +1,90 @@ +# @(#)precedence_test 1.0 91/07/24 Maarten Litmaath + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +# 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..b032dcb --- /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 95: 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 219: printf: `%10': missing format character +./printf.tests: line 220: printf: `M': invalid format character +ab./printf.tests: line 223: printf: `y': invalid format character +./printf.tests: line 226: printf: GNU: invalid number +0 +./printf.tests: line 227: 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 107: 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 293: printf: `%10': missing format character +./printf1.sub: line 294: printf: `M': invalid format character +./printf1.sub: line 297: printf: `y': invalid format character +./printf1.sub: line 300: printf: GNU: invalid number +0 +./printf1.sub: line 302: printf: GNU: invalid number +0 +- +(foo )(bar ) +0 + ab cd ef +13 +^G +^G +^Ge +"? +16:09:15 +./printf3.sub: line 27: 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..df37e47 --- /dev/null +++ b/tests/printf.tests @@ -0,0 +1,334 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..2cbbc6a --- /dev/null +++ b/tests/printf1.sub @@ -0,0 +1,348 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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 preserved +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..94a2bb1 --- /dev/null +++ b/tests/printf2.sub @@ -0,0 +1,13 @@ +unset LC_ALL LC_CTYPE + +export LANG=C +case $(printf %d\\n \'A) in +65) ;; +*) echo "printf2.sub: character conversion failed" >&2 ;; +esac + +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..4c54aa1 --- /dev/null +++ b/tests/printf3.sub @@ -0,0 +1,75 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..ed4c538 --- /dev/null +++ b/tests/printf4.sub @@ -0,0 +1,82 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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..c6471c5 --- /dev/null +++ b/tests/procsub.right @@ -0,0 +1,33 @@ +test1 +foo +test2 +test4 +8 +test5 +test6 +test7 +test8 +test8a +test9 +hi +bye +l8r +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +intern +1 +0 +0 +0 +0 +extern +1 +0 +0 +0 +0 +123 +bar1 +ouch +bar2 +foo +subshell diff --git a/tests/procsub.tests b/tests/procsub.tests new file mode 100644 index 0000000..946d2c2 --- /dev/null +++ b/tests/procsub.tests @@ -0,0 +1,121 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# process substitution constructs that have caused problems in the past +. ./test-glue-functions + +eval cat <(echo test1) +eval "echo foo;cat" <(echo test2) + +# this doesn't work, and it never should have +#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 +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 +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 +${THIS_SH} ./procsub2.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/procsub2.sub b/tests/procsub2.sub new file mode 100644 index 0000000..75ad2d0 --- /dev/null +++ b/tests/procsub2.sub @@ -0,0 +1,36 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +# test whether or not we remove FIFOs and close pipe file descriptors too +# aggressively + +ouch() +{ + while read foo; do echo "$foo"; done < <(echo bar1) + cat "$1" +} + +ouch <(echo ouch ) + +ouch2() +{ + { cat; } < <(echo bar2) + cat "$1" +} + +exec 4< <(echo subshell) +ouch2 <(echo foo ) + +read var <&4 +echo $var diff --git a/tests/quote.right b/tests/quote.right new file mode 100644 index 0000000..303e685 --- /dev/null +++ b/tests/quote.right @@ -0,0 +1,182 @@ +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[2] = <> +argv[1] = <> +argv[2] = <> +argv[1] = <> +===== +argv[1] = <> +argv[1] = <> +argv[1] = <> +argv[1] = <> +argv[2] = <> +argv[1] = <> +argv[1] = <> +argv[1] = <> +argv[2] = <> +===== +argv[1] = <> +argv[1] = <> +argv[1] = <> +argv[1] = <> +argv[1] = <> +argv[2] = <> +argv[1] = <> +argv[2] = <> +argv[1] = <> +===== +argv[1] = <> +argv[1] = <> +argv[1] = <> +argv[1] = <> +argv[1] = <> +argv[2] = <> +argv[1] = <> +argv[2] = <> +argv[1] = <> +argv[1] = <4> +argv[2] = <> +argv[1] = <ab> +argv[2] = <> +argv[1] = <ab> +argv[2] = <> +argv[1] = <ab> +argv[2] = <> +argv[1] = <ab> +argv[2] = <> +argv[1] = <ab ''> +argv[1] = <ab > +argv[1] = <ab ''> +argv[1] = <ab > +0 +1 +1 +1 +1 +1 +1 +1 +2 +2 +2 +2 +0 +1 +1 +1 +1 +1 +1 +1 +2 +2 +2 +2 +0 +0 +0 +2 +2 +4 +4 +3 +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..0a0b4af --- /dev/null +++ b/tests/quote.tests @@ -0,0 +1,139 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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 +${THIS_SH} ./quote3.sub +${THIS_SH} ./quote4.sub diff --git a/tests/quote1.sub b/tests/quote1.sub new file mode 100644 index 0000000..86f9786 --- /dev/null +++ b/tests/quote1.sub @@ -0,0 +1,62 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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..1012b8f --- /dev/null +++ b/tests/quote2.sub @@ -0,0 +1,55 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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/quote3.sub b/tests/quote3.sub new file mode 100644 index 0000000..54bc5ed --- /dev/null +++ b/tests/quote3.sub @@ -0,0 +1,31 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# new tests +x=4 +sp=' ' + +# word +recho ${x}${sp}'' + +# unquoted +recho ${x+ab "$y"} +recho ${x+ab ''} +recho ${x+ab "$( : )"} +recho ${x+ab "${yy}"} + +# quoted +recho "${x+ab ''}" +recho "${x+ab ""}" +recho "${x+ab '${yy}'}" +recho "${x+ab "${yy}"}" diff --git a/tests/quote4.sub b/tests/quote4.sub new file mode 100644 index 0000000..ab534c8 --- /dev/null +++ b/tests/quote4.sub @@ -0,0 +1,101 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +n() { echo $#; } + +set -- + +n "$@" + +# should be 1 +n "$@"'' +n ''"$@" +n ''"$@"'' + +set -- '' + +n "$@" +# should be 1 +n "$@"'' +n ''"$@" +n ''"$@"'' + +set -- '' '' + +n "$@" +# should be 2 +n ''"$@" +# should be 2 +n "$@"'' +# should be 2 +n ''"$@"'' + +x=x + +set -- + +n ${x+"$@"} + +# should be 1 +n ${x+"$@"''} +n ${x+''"$@"} +n ${x+''"$@"''} + +set -- '' + +n ${x+"$@"} +# should be 1 +n ${x+"$@"''} +n ${x+''"$@"} +n ${x+''"$@"''} + +set -- '' '' + +n ${x+"$@"} +# should be 2 +n ${x+''"$@"} +# should be 2 +n ${x+"$@"''} +# should be 2 +n ${x+''"$@"''} + + +set -- + +n "$@" "$@" +n "$@""$@" + +n ${x+"$@" "$@"} + +set -- '' + +n ${x+"$@" "$@"} +n "$@" "$@" + +set -- '' '' + +n ${x+"$@" "$@"} +n "$@" "$@" +n "$@""$@" + +# new tests +unset -v x +v=$'\177' + +recho ''$'\177''' +recho $'\177''' +recho ''$'\177' + +recho ''$v'' +recho ''$v +recho $v'' diff --git a/tests/quotearray.right b/tests/quotearray.right new file mode 100644 index 0000000..e689365 --- /dev/null +++ b/tests/quotearray.right @@ -0,0 +1,152 @@ +declare -A assoc=(["x],b[\$(echo uname >&2)"]="1" ) +declare -A assoc=(["\$key"]="1" ["x],b[\$(echo uname >&2)"]="1" ) +declare -A assoc=(["\$key"]="1" ["x],b[\$(echo uname >&2)"]="2" ) +./quotearray.tests: line 31: ((: 'assoc[x\],b\[\$(echo uname >&2)]++' : syntax error: operand expected (error token is "'assoc[x\],b\[\$(echo uname >&2)]++' ") +declare -A assoc=(["\$key"]="1" ["x],b[\$(echo uname >&2)"]="2" ) +./quotearray.tests: line 34: ((: 'assoc[x\],b\[\$(echo uname >&2)]'++ : syntax error: operand expected (error token is "'assoc[x\],b\[\$(echo uname >&2)]'++ ") +declare -A assoc=(["\$key"]="1" ["x],b[\$(echo uname >&2)"]="2" ) +declare -A assoc=(["\$key"]="1" ["x],b[\$(echo uname >&2)"]="3" ) +4 +klmnopqrst +klmnopqrst +klmno +klmnopqrst +declare -A A=(["\$(echo %)"]="5" [%]="10" ["]"]="10" ) +declare -A A=(["~"]="42" ) +42 +declare -A A=(["~"]="43" ) +42 +declare -A A=(["~"]="43" ["~0"]="43" ) +12 +declare -a a=([0]="12" [1]="42") +2 +2 +declare -Ai assoc=(["']"]="3" ["\$var"]="1" ) +105 +declare -A assoc=(["\` echo >&2 foo\`"]="42" ["\$( echo >&2 bar)"]="63" ) +./quotearray.tests: line 140: x],b[$(echo uname >&2): syntax error: invalid arithmetic operator (error token is "],b[$(echo uname >&2)") +./quotearray.tests: line 144: x],b[$(echo uname >&2): syntax error: invalid arithmetic operator (error token is "],b[$(echo uname >&2)") +1 +./quotearray.tests: line 147: x],b[$(echo uname >&2): syntax error: invalid arithmetic operator (error token is "],b[$(echo uname >&2)") +1 +./quotearray.tests: line 150: x],b[$(echo uname >&2): syntax error: invalid arithmetic operator (error token is "],b[$(echo uname >&2)") +1 +./quotearray.tests: line 153: x],b[$(echo uname >&2): syntax error: invalid arithmetic operator (error token is "],b[$(echo uname >&2)") +1 +declare -A assoc +0 +0 +1 +0 +0 +0 +declare -A assoc=(["\` echo >&2 foo\`"]="128" [0]="0" ["]"]="12" ["x],b[\$(echo uname >&2)"]="42" ["~"]="42" ["\$( echo 2>& date)"]="foo" ) +foo +0 +0 +./quotearray1.sub: line 68: 0\],b\[1: syntax error: invalid arithmetic operator (error token is "\],b\[1") +declare -a array +0 +0 +0 +0 +1 +1 +declare -A aa=(["\$( echo 2>& date)"]="foo" ) +foo +0 +1 +1 +./quotearray1.sub: line 113: test: aa[$(echo: binary operator expected +2 +[[ -v assoc[a] ]]; $?=0 +[[ -v assoc["] ]]; $?=0 +declare -A assoc=(["\""]="123" [a]="123" ) +declare -A a=([1]="1" [0]="0" [" "]="11" ) +7 +7 +declare -A A=([$'\t']="2" [" "]="2" ) +declare -A A=([$'\t']="2" ["*"]="2" [" "]="2" ["]"]="2" ["@"]="2" ) +./quotearray2.sub: line 54: read: `A[]]': not a valid identifier +declare -A A=([$'\t']="X" ["*"]="X" [" "]="X" ["@"]="X" ) +./quotearray2.sub: line 62: printf: `A[]]': not a valid identifier +declare -A A=([$'\t']="X" ["*"]="X" [" "]="X" ["@"]="X" ) +./quotearray2.sub: line 70: declare: `A[]]=X': not a valid identifier +declare -A A=(["*"]="X" ["@"]="X" ) +./quotearray2.sub: line 78: declare: `A[]]=X': not a valid identifier +declare -A A=(["*"]="X" ["@"]="X" ) +./quotearray2.sub: line 89: let: assoc[x],b[$(echo: bad array subscript (error token is "b[$(echo") +declare -A assoc +declare -A assoc=(["\$(echo foo)"]="1" ) +0 +declare -A assoc=(["\$var"]="value" ) +declare -A assoc=(["\$var"]="value" ) +declare -A assoc=(["\$var"]="value" ) +declare -A assoc=() +declare -A a=(["\$(echo foo)"]="1" ) +declare -A a=() +declare -A a=(["\$(echo foo)"]="1" ) +declare -A a=(["\$(echo foo)"]="1" ) +declare -A assoc=(["!"]="bang" ) +1 +1 +declare -A assoc=(["!"]="bang" ["@"]="at" ) +declare -A assoc=(["!"]="bang" ) +declare -a array=([0]="1" [1]="2" [2]="3") +declare -a array=() +./quotearray3.sub: line 98: declare: array: not found +declare -A map=(["foo\$(uname >/dev/tty)bar"]="1" ) +1 +declare -A map=() +$(DOESNOTEXIST) +declare -A blah=() +declare -A assoc=(["*"]="star" ["!"]="bang" ["@"]="at" ) +declare -A assoc=(["*"]="star" ["!"]="bang" ) +declare -A assoc=(["!"]="bang" ) +./quotearray4.sub: line 41: declare: assoc: not found +declare -A assoc=(["*"]="star" ["!"]="bang" ["@"]="at" ) +declare -A assoc=(["*"]="star" ["!"]="bang" ) +declare -A assoc=(["!"]="bang" ) +declare -A assoc=(["*"]="star" ["!"]="bang" ) +declare -A assoc=(["!"]="bang" ) +star bang at +star bang at +0 +0 +0 +1 +1 +declare -A assoc=(["*"]="star" ["!"]="bang" ["@"]=" key" ) +=== +1 +1 +declare -a array=([0]="1" [1]="2" [2]="3") +1 2 3 +1 2 3 +0 +0 +./quotearray4.sub: line 115: array[@]: bad array subscript +declare -a array=([0]="1" [1]="2" [2]="3") +./quotearray5.sub: line 27: unset: `a[$(echo': not a valid identifier +./quotearray5.sub: line 27: unset: `foo)]': not a valid identifier +declare -A a=() +declare -A a=() +declare -A a=() +----- +declare -A a=(["\$(echo foo)"]="1" ) +declare -A a=() +declare -A a=() +declare -A a=() +----- +declare -A a=() +declare -A a=() +declare -A a=() +---------- +declare -A a=([.]="v1" ) +declare -A a=([.]="v1" ) +----- +declare -A a=([.]="v1" ) +declare -A a=([.]="v1" ) +----- +declare -A a=([.]="v1" ) +declare -A a=([.]="v1" ) diff --git a/tests/quotearray.tests b/tests/quotearray.tests new file mode 100644 index 0000000..e1ed83b --- /dev/null +++ b/tests/quotearray.tests @@ -0,0 +1,164 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +# a set of tests for associative arrays in arithmetic contexts + +declare -A assoc +key='x],b[$(echo uname >&2)' + +(( assoc[$key]++ )) +declare -p assoc + +(( assoc['$key']++ )) +declare -p assoc + +(( assoc["$key"]++ )) +declare -p assoc + +declare -A assoc + +(( 'assoc[$key]++' )) +declare -p assoc + +(( 'assoc[$key]'++ )) +declare -p assoc + +(( "assoc[$key]++" )) +declare -p assoc + +unset assoc + +typeset -A a +b="80's" + +((++a[$b])) + +((++a["$b"])) +[[ $((++a[$b])) ]] +[[ $((++a["$b"])) ]] + +echo ${a[$b]} +unset a + +declare -A A + +string=abcdefghijklmnopqrstuvwxyz + +echo ${string:10:10} +k1='%' +k2='$(echo %)' + +A[%]=10 +A[']']=10 +A[$k2]=5 + +k3=']' + +echo ${string:A[%]:A[$k1]} +echo ${string:A[%]:A[$k2]} +echo ${string:A[%]:A[$k3]} + +declare -p A + +unset A string key + +key='~' + +declare -A A +A[$key]=42 + +declare -p A + +echo $(( A[$key]++ )) +declare -p A + +key='~0' +A[$key]=42 +echo $(( A[$key]++ )) +declare -p A + +declare -a a +key='~-2' +a[0]=12 +a[$key]=42 +echo $(( a[7<(4+2)] )) + +declare -p a + +unset A a key + +declare -A A +declare -a a + +sString="devel packager's guide" +i=2 + +A["$sString"]=$i +a[$i]=$sString + +echo "${A[${a[i]}]}" +echo ${A["${a[i]}"]} + +unset A a + +#LANG=C +unset var assoc +var=\'\] +declare -Ai assoc +assoc[$var]=1 +assoc[$var]+=1 +((assoc['$var']++)) +((assoc[$var]++)) +typeset -p assoc + +unset assoc + +declare -A assoc +key1='` echo >&2 foo`' +key2='$( echo >&2 bar)' + +assoc[$key1]=42 +assoc[$key2]=63 + +echo $(( assoc[$key1] + assoc[$key2] )) +declare -p assoc +unset assoc + +declare -a a +key='x],b[$(echo uname >&2)' +a[$key]=42 + +expr='a[$key]' + +(( $expr )) +echo $? + +echo $(( $expr )) +echo $? + +echo $(( expr )) +echo $? + +(( expr )) +echo $? + +${THIS_SH} ./quotearray1.sub +${THIS_SH} ./quotearray2.sub +${THIS_SH} ./quotearray3.sub + +# behavior of builtins with array subscripts @ and * +${THIS_SH} ./quotearray4.sub + +# behavior of unset with quoted and unquoted array arguments +${THIS_SH} ./quotearray5.sub diff --git a/tests/quotearray1.sub b/tests/quotearray1.sub new file mode 100644 index 0000000..19741b1 --- /dev/null +++ b/tests/quotearray1.sub @@ -0,0 +1,131 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +# arithmetic operators for conditional commands and arithmetic commands + +declare -A assoc +declare -a index + +key='x],b[$(echo uname >&2)' +key1=']' +key2='` echo >&2 foo`' +key3='~' +key4='7<(4+2)' +key5='$( echo 2>& date)' +key6='$(echo foo)' + +[[ -n assoc[$key] ]] +declare -p assoc + +assoc[$key]=42 +assoc[$key1]=12 +assoc[$key2]=128 +assoc[$key3]=42 +assoc[0]=0 + +[[ assoc[$key] -eq assoc[$key] ]] +echo $? + +[[ assoc[$key] -gt assoc[$key1] ]] +echo $? + +[[ assoc[$key2] -lt assoc[$key] ]] +echo $? + +[[ assoc[$key] -eq assoc[$key3] ]] +echo $? + +[[ index[7<(4+2)] -le assoc[0] ]] +echo $? +[[ index[$key4] -le assoc[0] ]] +echo $? + +assoc[$key5]=foo +declare -p assoc + +echo "${assoc[$key5]}" + +[[ -v assoc[$key5] ]] +echo $? +[[ -v assoc[$key] ]] +echo $? + +unset assoc + +declare -a array +index='0],b[1'; +((array[$index]++)) + +declare -p array + +unset array + +declare -A assoc + +assoc[$key]=42 +assoc[$key4]=42 + +[[ -v assoc[$key] ]] +echo $? +[[ -v assoc["$key"] ]] +echo $? + +[[ -v assoc[$key4] ]] +echo $? +[[ -v assoc["$key4"] ]] +echo $? + +[[ -v assoc['$key'] ]] +echo $? +[[ -v assoc['$key4'] ]] +echo $? + +unset -v assoc + +declare -A aa +aa[$key5]=foo + +declare -p aa +echo "${aa[$key5]}" + +[[ -v aa[$key5] ]] +echo $? + +[[ -v aa[$key] ]] +echo $? + +aa[$key6]=42 +# this still performs expansion +test -v aa["$key6"] +echo $? +# should be an error +test -v aa[$key6] +echo $? + +unset aa key + +declare -A assoc + +mytest () +{ + assoc["$1"]=123 + [[ -v assoc["$1"] ]] + printf '[[ -v assoc[%s] ]]; $?=%s\n' "$1" "$?" +} + +mytest 'a' +mytest '"' +declare -p assoc +unset -v assoc +unset -f mytest diff --git a/tests/quotearray2.sub b/tests/quotearray2.sub new file mode 100644 index 0000000..056f8ca --- /dev/null +++ b/tests/quotearray2.sub @@ -0,0 +1,107 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +# assoc_expand_once for builtins + +typeset -A a +a[0]=0 a[1]=1 + +let "a[\" \"]=11" ; typeset -p a ; a[0]=0 + +unset a + +# 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 + +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 + +unset A + +# this isn't right yet, but changes will show up here +shopt -s assoc_expand_once +declare -A assoc +key='x],b[$(echo uname >&2)' + +let assoc[$key]++ +declare -p assoc + +unset assoc + +typeset -A assoc +at=@ + +key='$(echo foo)' + +assoc[$key]=1 +declare -p assoc + +shopt -s assoc_expand_once +test -v assoc["$key"] ; echo $? + +unset assoc +shopt -u assoc_expand_once + diff --git a/tests/quotearray3.sub b/tests/quotearray3.sub new file mode 100644 index 0000000..65f950d --- /dev/null +++ b/tests/quotearray3.sub @@ -0,0 +1,117 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +# assoc_expand_once and unset builtin, which is treated specially + +declare -A assoc + +var=x123 +assoc['$var']=value +declare -p assoc + +shopt -u assoc_expand_once +unset "assoc[$var]" +declare -p assoc + +unset 'assoc[$var]' +declare -p assoc + +assoc['$var']=value +shopt -s assoc_expand_once +unset 'assoc[$var]' +declare -p assoc + +unset assoc +shopt -u assoc_expand_once + +declare -A a +a['$(echo foo)']=1 + +unset 'a[$(echo foo)]' +declare -p a + +key='$(echo foo)' +a[$key]=1 + +unset 'a[$key]' +declare -p a + +a[$key]=1 +unset "a[$key]" +declare -p a + +a[$key]=1 +unset a[$key] +declare -p a + +unset a + +typeset -A assoc +key=@ + +assoc[@]=at +assoc[!]=bang + +# this should only unset the element with key `@' +unset -v assoc[$key] +typeset -p assoc + +# this should check for assoc[@] and return 1 +test -v assoc[$key] +echo $? + +# this should too +[[ -v assoc[$key] ]] +echo $? + +unset assoc array + +declare -A assoc +declare -a array + +assoc=([@]=at [!]=bang) +declare -p assoc + +unset assoc[@] +declare -p assoc + +array=(1 2 3) +declare -p array + +# right now, this still unsets the entire array +unset array[@] +declare -p array + +BASH_COMPAT=51 +unset array[@] +declare -p array + +declare -A map; key='foo$(uname >/dev/tty)bar'; map[$key]=1 +declare -p map +echo ${map["$key"]} + +unset map["$key"] +declare -p map +unset map + +declare -A blah +blah['$(DOESNOTEXIST)']=broken +for i in "${!blah[@]}"; do echo "$i"; done + +for i in "${!blah[@]}"; do unset blah["$i"]; done +declare -p blah +unset blah + + + diff --git a/tests/quotearray4.sub b/tests/quotearray4.sub new file mode 100644 index 0000000..964aac7 --- /dev/null +++ b/tests/quotearray4.sub @@ -0,0 +1,116 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +# tests for builtins handling associative array keys `*' and `@', with some +# indexed array tests as well (backwards compatible) + +# derived from test cases posted to bug-bash by myoga.murase@gmail.com + +declare -A assoc +declare -a array + +assoc[@]=at +assoc[*]=star +assoc[!]=bang + +key=@ + +iref='array[@]' +aref='assoc[@]' + +declare -p assoc + +unset assoc[@] +declare -p assoc + +unset assoc[*] +declare -p assoc + +unset assoc +declare -p assoc + +declare -A assoc +assoc[@]=at +assoc[*]=star +assoc[!]=bang + +declare -p assoc + +unset assoc["$key"] +declare -p assoc + +unset assoc["*"] +declare -p assoc + +assoc[@]=at assoc[*]=star + +unset assoc['@'] +declare -p assoc + +unset assoc['*'] + +declare -p assoc + +assoc[@]=at assoc[*]=star +echo ${!aref} + +declare -n nref=$aref +echo ${nref} +unset -n nref + +# for associative arrays, test -v treats @ and * as keys + +test -v 'assoc[@]' +echo $? +test -v assoc[$key] +echo $? +[[ -v assoc[$key] ]] +echo $? + +unset -v 'assoc[@]' + +test -v 'assoc[@]' +echo $? +[[ -v assoc[@] ]] +echo $? + +assoc[@]=at + +printf -v assoc[@] "%10s" key +declare -p assoc + +echo === +array=() +test -v array[@] +echo $? +[[ -v array[@] ]] +echo $? + +array=(1 2 3) +declare -p array + +echo ${!iref} +declare -n nref=$iref + +echo $nref +unset -n nref + +# but for indexed arrays, test -v treats @ and * as standing for the entire array +test -v 'array[@]' +echo $? +[[ -v array[@] ]] +echo $? + +printf -v array[@] "%-10s" key +declare -p array diff --git a/tests/quotearray5.sub b/tests/quotearray5.sub new file mode 100644 index 0000000..5366a99 --- /dev/null +++ b/tests/quotearray5.sub @@ -0,0 +1,124 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +# a set of tests for unset to try to ensure that subscripts are only expanded +# once. Derived from tests submitted by konsolebox@gmail.com + +declare -A a +key='$(echo foo)' + +# Here the tokens are valid array references and pass that fact to unset +# post-expansion + +# This solves the surprise expansion issues. + +a[$key]=1 +unset -v a[$key] # this performs normal word splitting +unset -v a["$key"] # prevent word splitting +declare -p a # Displays no element + +a['$key']=2 +unset -v a['$key'] +declare -p a # Displays no element + +a["foo"]=3 +unset -v a["foo"] +declare -p a # Displays no element + +echo ----- + +# Here the tokens are "strings". They expand and keep the +# original behavior and allows existing scripts to not break. +# It also allows nref or iref references to be transparently +# referenced in it. + +# the quotes prevent the arguments from being recognized as valid array +# references before word expansion. since unset doesn't know to treat +# them specially, they're treated as in previous versions and expansion +# is performed as part of evaluating the subscript + +a[$key]=1 +declare -p a +unset 'a[$key]' # Transforms to a[$key] after expansion +declare -p a # Displays no element + +a['$key']=2 +unset "a['\$key']" # Transforms to a['$key'] after expansion +declare -p a # Displays no element + +a["foo"]=3 +unset 'a["foo"]' # Transforms to a["foo"] after expansion +declare -p a # Displays no element + +echo ----- + +# The update also keeps compatibility with already existing behavior of +# unset when assoc_expand_once is enabled, but only for quoted tokens. + +a=() +shopt -s assoc_expand_once + +a[$key]=1 +unset "a[$key]" +declare -p a # Displays no element + +a['$key']=2 +unset "a[\$key]" +declare -p a # Displays no element + +a["foo"]=3 +unset "a[foo]" +declare -p a # Displays no element + +echo ---------- + +# For unsetting '@' and all elements: + +key=@ + +declare -A a=(@ v0 . v1) +unset a[$key] +declare -p a # Displays 'declare -A a=([.]="v1" )' + +declare -A a=(@ v0 . v1) +unset a[@] +declare -p a # same behavior + +echo ----- + +# these are quoted strings and unset doesn't treat them specially + +unset a +shopt -u assoc_expand_once + +declare -A a=(@ v0 . v1) +unset 'a[$key]' +declare -p a # Displays 'declare -A a=([.]="v1" )' + +declare -A a=(@ v0 . v1) +unset 'a[@]' +declare -p a # same behavior + +echo ----- + +unset a +shopt -s assoc_expand_once + +declare -A a=(@ v0 . v1) +unset "a[$key]" # $key is expanded +declare -p a # Displays 'declare -A a=([.]="v1" )' + +declare -A a=(@ v0 . v1) +unset 'a[@]' +declare -p a # same behavior diff --git a/tests/read.right b/tests/read.right new file mode 100644 index 0000000..e21fcb5 --- /dev/null +++ b/tests/read.right @@ -0,0 +1,85 @@ +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 +xyz +a = xyz +a = -xyz 123- +a = abc +timeout 1: ok +unset or null 1 +timeout 2: ok +unset or null 2 +timeout 3: ok +unset or null 3 +./read2.sub: line 45: read: -3: invalid timeout specification +1 + +abcde +abcde +./read3.sub: line 17: read: -1: invalid number +abc +defg +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 +timeout 1: ok +unset or null 1 +timeout 2: ok +unset or null 2 +timeout 3: ok +unset or null 3 +timeout 4: ok +abcde +abcde + +one +two three four +one +two three four diff --git a/tests/read.tests b/tests/read.tests new file mode 100644 index 0000000..6132b6f --- /dev/null +++ b/tests/read.tests @@ -0,0 +1,117 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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 + +# test behavior of readline timeouts +${THIS_SH} ./read7.sub + +# test behavior of read -n and read -d on regular files +${THIS_SH} ./read8.sub diff --git a/tests/read1.sub b/tests/read1.sub new file mode 100644 index 0000000..cf00398 --- /dev/null +++ b/tests/read1.sub @@ -0,0 +1,37 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +a=7 +echo 'abcdefg|xyz' | { + read -d '|' a + echo a = "${a-unset}" + cat - # make sure we don't read too much +} + +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..d353011 --- /dev/null +++ b/tests/read2.sub @@ -0,0 +1,72 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +: ${TMPDIR:=/var/tmp} + +a=4 + +read -t 1 a < /dev/tty +estat=$? +if [ $estat -gt 128 ]; then + echo timeout 1: ok +else + echo $estat +fi +echo ${a:-unset or null 1} + +read -t 0.000001 a < /dev/tty +estat=$? +if [ $estat -gt 128 ]; then + echo timeout 2: ok +else + echo $estat +fi +echo ${a:-unset or null 2} + +sleep 1 | read -t 0.25 a +estat=$? +if [ $estat -gt 128 ]; then + echo timeout 3: ok +else + echo $estat +fi +echo ${a:-unset or null 3} + +read -t -3 a < /dev/tty +echo $? + +echo $a + +# the above should all time out +echo abcde | { + read -t 0.5 a + echo $a +} + +read -t .0001 a <<<abcde +echo $a + +# this is the original test that prompted the change to sh_timers +cd $TMPDIR +rm -f a.pipe +mkfifo a.pipe +exec 9<> a.pipe +rm -f a.pipe + +for c in {0..2000}; do + (eval "echo {0..$c}" & read -u 9 -t 0.0001) >/dev/null + printf $'ok %d' "$c" >/dev/null +done + +cd $OLDPWD +rm -f $TMPDIR/a.pipe # paranoia diff --git a/tests/read3.sub b/tests/read3.sub new file mode 100644 index 0000000..8a24040 --- /dev/null +++ b/tests/read3.sub @@ -0,0 +1,38 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# non-interactive + +# error +read -n -1 + +# from pipe -- should work, but doesn't change tty attributes +echo abcdefg | { + read -n 3 xyz + echo $xyz + cat - # make sure we don't read too much +} + +# 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..e42a5be --- /dev/null +++ b/tests/read5.sub @@ -0,0 +1,48 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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/read7.sub b/tests/read7.sub new file mode 100644 index 0000000..553070f --- /dev/null +++ b/tests/read7.sub @@ -0,0 +1,66 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# test behavior of native readline timeouts + +# turn off bracketed paste to avoid spurious output +bind 'set enable-bracketed-paste off' 2>/dev/null + +read -t 0.00001 -e var +estat=$? +if [ $estat -gt 128 ]; then + echo timeout 1: ok +else + echo $estat +fi +echo ${var:-unset or null 1} + +read -e -t 0.1 var +estat=$? +if [ $estat -gt 128 ]; then + echo timeout 2: ok +else + echo $estat +fi +echo ${var:-unset or null 2} + +read -e -t 1 var < /dev/tty +estat=$? +if [ $estat -gt 128 ]; then + echo timeout 3: ok +else + echo $estat +fi +echo ${var:-unset or null 3} + +sleep 1 | read -t 0.25 -e a +estat=$? +if [ $estat -gt 128 ]; then + echo timeout 4: ok +else + echo $estat +fi + +# the above should all time out +echo abcde | { + read -e -t 0.5 a + echo $a +} + +read -e -t .0001 a <<<abcde +echo $a + +set -o posix +read -t 0.1 a </dev/tty +echo $a + diff --git a/tests/read8.sub b/tests/read8.sub new file mode 100644 index 0000000..d5b7af8 --- /dev/null +++ b/tests/read8.sub @@ -0,0 +1,15 @@ +tmpf=$TMPDIR/tmp-$$ +printf "%s\n" "one two three four" > $tmpf + +# make sure we rewind the input properly when reading a specific number of +# characters or using a non-standard delimiter from a regular file + +exec <$tmpf +read -n 4 input && echo "$input" +cat - + +exec <$tmpf +read -d ' ' input && echo "$input" +cat - + +rm -f $tmpf diff --git a/tests/redir.right b/tests/redir.right new file mode 100644 index 0000000..8db1041 --- /dev/null +++ b/tests/redir.right @@ -0,0 +1,163 @@ +abc +./redir.tests: line 28: /tmp/redir-test: cannot overwrite existing file +abc +def +def +./redir.tests: line 44: $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 45: $fd: ambiguous redirect +./redir4.sub: line 46: $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 170: redir1.*: No such file or directory +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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 +# This program is free software: you can redistribute it and/or modify +/ +/ +/ +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 53: $(ss= declare -i ss): ambiguous redirect +after: 42 +a+=3 +foo +foo +./redir11.sub: line 75: 42: No such file or directory +42 diff --git a/tests/redir.tests b/tests/redir.tests new file mode 100644 index 0000000..63bd4d3 --- /dev/null +++ b/tests/redir.tests @@ -0,0 +1,209 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +: ${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..7b1d682 --- /dev/null +++ b/tests/redir10.sub @@ -0,0 +1,37 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# +# 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..d417cdb --- /dev/null +++ b/tests/redir11.sub @@ -0,0 +1,76 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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'; } + +# double expansion of filenames when used in redirection error messages +# present in bash versions back to at least bash-1.13 +# this is executed in the tests subdirectory of the source directory, so there +# definitely should not be a file named `42' + +unset foo +: <$((foo+=42)) +echo $foo 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..b9fd0fd --- /dev/null +++ b/tests/redir3.sub @@ -0,0 +1,39 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..a482985 --- /dev/null +++ b/tests/redir4.sub @@ -0,0 +1,69 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..fa0f0c0 --- /dev/null +++ b/tests/redir5.sub @@ -0,0 +1,44 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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..65ca473 --- /dev/null +++ b/tests/redir7.sub @@ -0,0 +1,82 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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..d2d700c --- /dev/null +++ b/tests/redir8.sub @@ -0,0 +1,74 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..9050a94 --- /dev/null +++ b/tests/redir9.sub @@ -0,0 +1,63 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +: ${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..6abdd2a --- /dev/null +++ b/tests/rhs-exp.tests @@ -0,0 +1,64 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..b194bf0 --- /dev/null +++ b/tests/rhs-exp1.sub @@ -0,0 +1,116 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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..5f64049 --- /dev/null +++ b/tests/rsh.right @@ -0,0 +1,19 @@ +./rsh1.sub: line 22: /bin/sh: restricted +./rsh1.sub: line 24: sh: not found +./rsh1.sub: line 25: a: command not found +./rsh2.sub: line 23: hash: /bin/sh: restricted +./rsh2.sub: line 25: hash: sh: not found +./rsh2.sub: line 26: a: command not found +./rsh.tests: line 25: cd: restricted +./rsh.tests: line 26: PATH: readonly variable +./rsh.tests: line 27: SHELL: readonly variable +./rsh.tests: line 28: /bin/sh: restricted: cannot specify `/' in command names +./rsh.tests: line 30: .: ./source.sub3: restricted +./rsh.tests: line 33: /tmp/restricted: restricted: cannot redirect output +./rsh.tests: line 37: /tmp/restricted: restricted: cannot redirect output +./rsh.tests: line 42: command: -p: restricted +./rsh.tests: line 44: set: +r: invalid option +set: usage: set [-abefhkmnptuvxBCEHPT] [-o option-name] [--] [-] [arg ...] +./rsh.tests: line 45: set: restricted: invalid option name +./rsh.tests: line 47: exec: restricted +./rsh.tests: after exec diff --git a/tests/rsh.tests b/tests/rsh.tests new file mode 100644 index 0000000..0d06fa1 --- /dev/null +++ b/tests/rsh.tests @@ -0,0 +1,49 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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..1539d74 --- /dev/null +++ b/tests/rsh1.sub @@ -0,0 +1,29 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..7259dfb --- /dev/null +++ b/tests/rsh2.sub @@ -0,0 +1,30 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..1f74923 --- /dev/null +++ b/tests/run-all @@ -0,0 +1,64 @@ +#! /bin/sh +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +: ${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 ; exit' 1 2 3 15 +trap 'rm -f $BASH_TSTOUT' 0 + +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 + +: ${BUILD_DIR:=..} +export BUILD_DIR + +${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-complete b/tests/run-complete new file mode 100644 index 0000000..f1cef84 --- /dev/null +++ b/tests/run-complete @@ -0,0 +1,2 @@ +${THIS_SH} ./complete.tests > ${BASH_TSTOUT} 2>&1 +diff ${BASH_TSTOUT} complete.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..af64517 --- /dev/null +++ b/tests/run-dbg-support @@ -0,0 +1,9 @@ + +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..375c32f --- /dev/null +++ b/tests/run-dbg-support2 @@ -0,0 +1,9 @@ + +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 $? 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..c3ed53e --- /dev/null +++ b/tests/run-execscript @@ -0,0 +1,26 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +echo "warning: the text of a system error message may vary between systems and" >&2 +echo "warning: produce diff output." >&2 +echo "warning: UNIX versions number signals 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 +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..8234f28 --- /dev/null +++ b/tests/run-intl @@ -0,0 +1,5 @@ +# See whether or not we can use `diff -a' +( diff -a ./intl.right ./intl.right >/dev/null 2>&1 ) && AFLAG=-a + +${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..0c3a2e5 --- /dev/null +++ b/tests/run-minimal @@ -0,0 +1,68 @@ +#! /bin/sh +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# +# 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 + +: ${BUILD_DIR:=..} +export BUILD_DIR + +${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|run-iquote) echo $x ; sh $x ;; + run-type|run-comsub-eof|run-comsub-posix) 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..06ac343 --- /dev/null +++ b/tests/run-precedence @@ -0,0 +1,2 @@ +${THIS_SH} ./precedence.tests > ${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-quotearray b/tests/run-quotearray new file mode 100644 index 0000000..06e5e6e --- /dev/null +++ b/tests/run-quotearray @@ -0,0 +1,2 @@ +${THIS_SH} ./quotearray.tests >${BASH_TSTOUT} 2>&1 +diff ${BASH_TSTOUT} quotearray.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..be394cc --- /dev/null +++ b/tests/run-varenv @@ -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} ./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..2bdc1b8 --- /dev/null +++ b/tests/run-vredir @@ -0,0 +1,4 @@ +echo "warning: the text of a system error message may vary between systems and" >&2 +echo "warning: produce diff output." >&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..3e0d669 --- /dev/null +++ b/tests/set-e.tests @@ -0,0 +1,124 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..cdd4d63 --- /dev/null +++ b/tests/set-e1.sub @@ -0,0 +1,72 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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 100644 index 0000000..3723552 --- /dev/null +++ b/tests/set-x.tests @@ -0,0 +1,38 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +# $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..cb7fa82 --- /dev/null +++ b/tests/set-x1.sub @@ -0,0 +1,38 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +: ${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..d617c1d --- /dev/null +++ b/tests/shopt.right @@ -0,0 +1,312 @@ +./shopt.tests: line 15: 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 -s globskipdots +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 noexpand_translation +shopt -u nullglob +shopt -s patsub_replacement +shopt -s progcomp +shopt -u progcomp_alias +shopt -s promptvars +shopt -u restricted_shell +shopt -u shift_verbose +shopt -s sourcepath +shopt -u varredir_close +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 globskipdots +shopt -s hostcomplete +shopt -s interactive_comments +shopt -s patsub_replacement +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 noexpand_translation +shopt -u nullglob +shopt -u progcomp_alias +shopt -u restricted_shell +shopt -u shift_verbose +shopt -u varredir_close +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 +noexpand_translation off +nullglob off +progcomp_alias off +restricted_shell off +shift_verbose off +varredir_close 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 106: shopt: xyz1: invalid shell option name +./shopt.tests: line 107: shopt: xyz1: invalid option name +28c28 +< globskipdots off +--- +> globskipdots on +expand_aliases on +expand_aliases on diff --git a/tests/shopt.tests b/tests/shopt.tests new file mode 100644 index 0000000..c31870c --- /dev/null +++ b/tests/shopt.tests @@ -0,0 +1,113 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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 + +${THIS_SH} ./shopt1.sub + +# test whether or not temporary variable assignments that manipulate posix +# mode restore the previous state or the default non-posix state +${THIS_SH} -c 'shopt -s expand_aliases ; shopt expand_aliases ; POSIXLY_CORRECT=y true ; shopt expand_aliases' diff --git a/tests/shopt1.sub b/tests/shopt1.sub new file mode 100644 index 0000000..8c1150f --- /dev/null +++ b/tests/shopt1.sub @@ -0,0 +1,52 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +# verify all shopt options are reset properly when the shell is reinitialized + +: ${TMPDIR:=/var/tmp} ${THIS_SH:=$PWD/bash} + +t1=$(mktemp) +t2=$(mktemp) + +if [ ! -e "$t1" ] ; then + S1=$RANDOM + S2=$RANDOM + t1=$TMPDIR/s-$S1 + t2=$TMPDIR/s-$S2 + touch "$t1" "$t2" +fi + +chmod +x "$t1" "$t2" + +echo "shopt" > "$t1" + +echo "#!${THIS_SH}" > "$t2" +echo "shopt" >> "$t2" + +for o in $(compgen -A shopt) +do + case $o in + extdebug) ;; + *) shopt -s $o ;; + esac +done +diff <("$t1") <("$t2") + +for o in $(compgen -A shopt) +do + shopt -u $o; +done +diff <("$t1") <("$t2") + +rm "$t1" "$t2" 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..4149c11 --- /dev/null +++ b/tests/source5.sub @@ -0,0 +1,32 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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-existent 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..2437292 --- /dev/null +++ b/tests/source6.sub @@ -0,0 +1,49 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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..474a66f --- /dev/null +++ b/tests/source7.sub @@ -0,0 +1,53 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..b16705f --- /dev/null +++ b/tests/strip.tests @@ -0,0 +1,35 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..4be22f4 --- /dev/null +++ b/tests/test.right @@ -0,0 +1,297 @@ +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 ! ! "$z" +0 +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 26: test: 4+3: integer expression expected +2 +b 4-5 -eq 7 +./test.tests: line 20: [: 4+3: integer expression expected +2 +t 9 -eq 4+5 +./test.tests: line 26: test: 4+5: integer expression expected +2 +b 9 -eq 4+5 +./test.tests: line 20: [: 4+5: integer expression expected +2 +t A -eq 7 +./test.tests: line 26: test: A: integer expression expected +2 +b A -eq 7 +./test.tests: line 20: [: A: integer expression expected +2 +t 9 -eq B +./test.tests: line 26: test: B: integer expression expected +2 +b 9 -eq B +./test.tests: line 20: [: B: integer expression expected +2 +t ( 1 = 2 +./test.tests: line 26: test: `)' expected +2 +b ( 1 = 2 +./test.tests: line 20: [: `)' expected, found ] +2 +./test.tests: line 26: test: a: unary operator expected +2 +./test.tests: line 26: test: b: binary operator expected +2 +./test.tests: line 26: test: -A: unary operator expected +2 +./test.tests: line 26: test: syntax error: `-ne' unexpected +2 +./test.tests: line 26: test: too many arguments +2 +./test.tests: line 434: [: missing `]' +2 +./test.tests: line 26: 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..df4b850 --- /dev/null +++ b/tests/test.tests @@ -0,0 +1,456 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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 ; sleep 1; echo "hello" > /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" + +echo 't ! ! "$z"' +t ! ! "$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..d25e0dc --- /dev/null +++ b/tests/test1.sub @@ -0,0 +1,34 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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..1301c0b --- /dev/null +++ b/tests/tilde.right @@ -0,0 +1,28 @@ +~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 +foo=bar:/usr/xyz +foo=bar:~ diff --git a/tests/tilde.tests b/tests/tilde.tests new file mode 100644 index 0000000..20268a7 --- /dev/null +++ b/tests/tilde.tests @@ -0,0 +1,94 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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" + +# this test is incomplete; should also test assignment statements (tilde3.sub) +echo foo=bar:~ +set -o posix +echo foo=bar:~ + +exit 0 diff --git a/tests/tilde2.right b/tests/tilde2.right new file mode 100644 index 0000000..f383e3a --- /dev/null +++ b/tests/tilde2.right @@ -0,0 +1,28 @@ +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 +foo=/home/xyz:/home/xyz +/home/xyz:/home/xyz +foo=~:~ +/home/xyz:/home/xyz diff --git a/tests/tilde2.tests b/tests/tilde2.tests new file mode 100644 index 0000000..d2415cb --- /dev/null +++ b/tests/tilde2.tests @@ -0,0 +1,85 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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 + +$THIS_SH ./tilde3.sub diff --git a/tests/tilde3.sub b/tests/tilde3.sub new file mode 100644 index 0000000..c35ea50 --- /dev/null +++ b/tests/tilde3.sub @@ -0,0 +1,26 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# regression test for tilde expansion following unquoted colons in posix mode + +HOME=/home/xyz + +echo foo=~:~ +foo=~:~ +printf "%s\n" $foo + +set -o posix + +echo foo=~:~ +foo=~:~ +printf "%s\n" $foo diff --git a/tests/trap.right b/tests/trap.right new file mode 100644 index 0000000..4338ff4 --- /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 +[33] debug +debug line +[35] 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 +[37] debug +func[29] funcdebug +funcdebug line +./trap.tests[39] 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[41] funcdebug +./trap.tests[46] debug +./trap.tests[47] debug +func2[43] debug +func2[44] debug +func2debug line +./trap.tests[49] debug +./trap.tests[51] 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] false ++[8] false ++[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..4f808be --- /dev/null +++ b/tests/trap.tests @@ -0,0 +1,114 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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..bd9a76b --- /dev/null +++ b/tests/trap2.sub @@ -0,0 +1,62 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..1490a76 --- /dev/null +++ b/tests/trap3.sub @@ -0,0 +1,9 @@ +PS4='+[$LINENO] ' +trap 'echo trap: $LINENO' ERR + +set -x + +echo 1 +echo 2 +false | false | false +echo 4 diff --git a/tests/trap4.sub b/tests/trap4.sub new file mode 100644 index 0000000..c84b54e --- /dev/null +++ b/tests/trap4.sub @@ -0,0 +1,55 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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..826b794 --- /dev/null +++ b/tests/trap5.sub @@ -0,0 +1,31 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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..7268558 --- /dev/null +++ b/tests/trap6.sub @@ -0,0 +1,28 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..bbc228e --- /dev/null +++ b/tests/type.right @@ -0,0 +1,135 @@ +./type.tests: line 22: type: -r: invalid option +type: usage: type [-afptP] name [name ...] +./type.tests: line 25: 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 56: 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 78: type: func: not found +./type.tests: line 80: type: m: not found +/bin/sh +/tmp/bash +bash is hashed (/tmp/bash) +file +hits command + 1 /bin/sh + 3 /tmp/bash +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..fd39c18 --- /dev/null +++ b/tests/type.tests @@ -0,0 +1,110 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..34977c5 --- /dev/null +++ b/tests/type2.sub @@ -0,0 +1,29 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..1a95de3 --- /dev/null +++ b/tests/type3.sub @@ -0,0 +1,34 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..937f998 --- /dev/null +++ b/tests/type4.sub @@ -0,0 +1,56 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..713ab40 --- /dev/null +++ b/tests/unicode1.sub @@ -0,0 +1,608 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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' +) + +# this locale causes problems all over the place +if locale -a | grep -i '^fr_FR\.ISO8859.*1$' >/dev/null ; then + TestCodePage fr_FR.ISO8859-1 fr_FR_ISO_8859_1 +else + echo "unicode1.sub: warning: you do not have the fr_FR.ISO8859-1 locale installed;" >&2 + echo "unicode1.sub: that will cause some of these tests to be skipped." >&2 +fi + +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 +if locale -a | grep -i '^ja_JP.SJIS' >/dev/null ; then + TestCodePage ja_JP.SJIS jp_JP_SHIFT_JIS +else + echo "unicode1.sub: warning: you do not have the ja_JP.SJIS locale installed;" >&2 + echo "unicode1.sub: that will cause some of these tests to be skipped." >&2 +fi + +#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..16dd604 --- /dev/null +++ b/tests/unicode2.sub @@ -0,0 +1,37 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +. ./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..f6bd1b5 --- /dev/null +++ b/tests/varenv.right @@ -0,0 +1,277 @@ +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:. +declare -a avar=([0]="/bin:/usr/bin:/usr/local/bin:.") +declare -- 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 67: bbb: unique: cannot convert indexed to associative array +./varenv4.sub: line 67: declare: 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 57: 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 28: declare: i1: not found +./varenv9.sub: line 28: 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 46: unset: i2: cannot unset: readonly variable +./varenv9.sub: line 46: 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 61: declare: i3: not found +./varenv9.sub: line 61: 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 79: unset: i4: cannot unset: readonly variable +./varenv9.sub: line 79: 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 17: local: qux: readonly variable +./varenv11.sub: line 18: qux: readonly variable +./varenv11.sub: line 18: local: qux: readonly variable +declare -A foo=([zero]="zero" [one]="one" ) +declare -a bar=([0]="zero" [1]="one") +declare -A foo=([one]="one" [zero]="zero" ) +declare -a bar=([0]="zero" [1]="one") +./varenv11.sub: line 42: 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 -- var="outside" +inside: declare -x var="inside" +outside: declare -- var="outside" +outside 1.0: var=one +outside 1.1: var=one +inside func: var=two +outside 2.0: var=<unset> +inside func: var=two +outside 2.1: var=global +inside func1: var=value +outside 3.0: var=value +inside func2: var=global +outside 4.0: var=outside +foo: hello world +after foo: var=global +bar: hello world +after bar: var=global +./varenv13.sub: line 16: `var[0]': not a valid identifier +./varenv13.sub: line 16: `var[@]': not a valid identifier +./varenv13.sub: line 14: declare: var: not found +declare -A var=([0]="X" ["@"]="Y" ) +help +./varenv13.sub: line 35: `var[0]': not a valid identifier +1 +declare -A var=([0]="X" ) +declare -A var=([Y]="Y" ) +declare -A var=([Y]="Y" ) +declare -A var=() +declare -A var=() +./varenv14.sub: line 31: f: var: cannot convert indexed to associative array +./varenv14.sub: line 31: declare: var: cannot convert indexed to associative array +declare -a var=([0]="12") +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 +foo=showfoo environment foo=showfoo +foo=showfoo environment foo=showfoo +foo=showfoo environment foo=showfoo +outside: foo=<unset> + +posix mode +foo=showfoo environment foo=showfoo +outside 1.0: foo=<unset> +foo=showfoo environment foo=showfoo +foo=showfoo environment foo=showfoo +outside 1.1: foo=<unset> +foo=<unset> environment foo= +outside 2.0: foo=<unset> +foo=foo environment foo=foo +foo=<unset> environment foo= +outside 2.1: foo=<unset> +declare -- var="global" +declare -- var +declare -- var="local" +declare -- var="global" +declare -- var="local" +declare -- var +declare -- var="local" +declare -- var +declare -- var="local" +declare -- var +declare -- var="local" +declare -- var="f1" +declare -- var="local" +declare -a arr=([0]="zero" [1]="one" [2]="two" [3]="three" [4]="four" [5]="five") +declare -a arr=([0]="zero" [1]="one" [2]="two") +declare -a arr=([0]="three" [1]="four" [2]="five") +declare -a arr=([0]="zero" [1]="one" [2]="two") +ddd 0 +aaa 1 2 3 +bbb 4 5 6 +ccc 7 8 9 +declare -a x=([0]="one" [1]="two" [2]="three") +./varenv19.sub: line 51: declare: x: not found +declare -x v="x" +declare -x v="t" +declare -- v +declare -x v +ignoreeof on +ignoreeof off +ignoreeof on +10 +match 1 +trap -- 'echo trap:$FUNCNAME' EXIT +trap:f +trap -- 'echo trap:$FUNCNAME' EXIT +trap:f +trap -- 'echo trap:$FUNCNAME' EXIT +trap:f +trap -- 'echo trap:$FUNCNAME' EXIT +trap:f +a=z +a=b +a=z diff --git a/tests/varenv.tests b/tests/varenv.tests new file mode 100644 index 0000000..68c619e --- /dev/null +++ b/tests/varenv.tests @@ -0,0 +1,265 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# +# 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 identifier names +${THIS_SH} ./varenv13.sub + +# localvar_inherit +${THIS_SH} ./varenv14.sub +${THIS_SH} ./varenv15.sub +${THIS_SH} ./varenv16.sub +${THIS_SH} ./varenv17.sub +${THIS_SH} ./varenv18.sub +${THIS_SH} ./varenv19.sub +${THIS_SH} ./varenv20.sub +${THIS_SH} ./varenv21.sub +${THIS_SH} ./varenv22.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..8def153 --- /dev/null +++ b/tests/varenv1.sub @@ -0,0 +1,41 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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..aa0175a --- /dev/null +++ b/tests/varenv10.sub @@ -0,0 +1,59 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# +# 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..638aa2c --- /dev/null +++ b/tests/varenv11.sub @@ -0,0 +1,43 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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..92b3692 --- /dev/null +++ b/tests/varenv12.sub @@ -0,0 +1,171 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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 +# local variable, as if a standalone assignment statement had been executed +# (posix modifying "the current execution environment") leaving the global +# variable unchanged. all shells, including bash, modify the local variable; +# bash was the only one that propagates the value out to the calling +# environment, but no longer does so. + +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=inside : + echo -n 'inside: ' ; declare -p var +} + +var=outside +func +echo -n 'outside: ' ; declare -p var + +unset -v var +unset -f func + +func() +{ + echo -n 'inside func: ' ; echo "var=${var-<unset>}" +} + +unset -v var +var=one : +echo -n 'outside 1.0: ' ; echo "var=${var-<unset>}" + +unset -v var +var=one eval ':' +echo -n 'outside 1.1: ' ; echo "var=${var-<unset>}" + +unset -v var + +var=two func +echo -n 'outside 2.0: ' ; echo "var=${var-<unset>}" +var=global +var=two func +echo -n 'outside 2.1: ' ; echo "var=${var-<unset>}" + +unset -v var +unset -f func + +func1() +{ + var=value export var + echo -n 'inside func1: ' ; echo "var=${var-<unset>}" +} + +var=outside +func1 +echo -n 'outside 3.0: ' ; echo "var=${var-<unset>}" + +unset -v var +unset -f func1 + +func2() +{ + local var=local + var=global : + echo -n 'inside func2: ' ; echo "var=${var-<unset>}" +} + +var=outside +func2 +echo -n 'outside 4.0: ' ; echo "var=${var-<unset>}" + +unset -v var +unset -f fecho foo bar + +fecho() { + echo $var +} + +foo() { + local var="foo: bye bye" + var="foo: hello world" fecho +} + +bar() { + var="bar: hello world" fecho +} + +var=global +var=outside foo +echo after foo: var=$var +var=global +var=outside bar +echo after bar: var=$var + +unset -v var diff --git a/tests/varenv13.sub b/tests/varenv13.sub new file mode 100644 index 0000000..1fa7d5b --- /dev/null +++ b/tests/varenv13.sub @@ -0,0 +1,37 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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*}; } + +# this is no longer an error +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..091c470 --- /dev/null +++ b/tests/varenv14.sub @@ -0,0 +1,46 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# testing framework for local variable inheritance + +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..4c9ef0e --- /dev/null +++ b/tests/varenv15.sub @@ -0,0 +1,51 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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/varenv16.sub b/tests/varenv16.sub new file mode 100644 index 0000000..847926c --- /dev/null +++ b/tests/varenv16.sub @@ -0,0 +1,51 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# test whether or not temporary environment assignments are exported +# in posix mode. works now, posix says it will not work in the future + +show2() +{ + printf %s "foo=${foo-<unset>}" + echo -n ' environment foo=' + printenv foo || echo +} + +showfoo() +{ + local foo + + foo=showfoo show2 +} + +unset foo +showfoo +foo=foo showfoo +showfoo +echo outside: "foo=${foo-<unset>}" + +echo ; echo 'posix mode' +set -o posix +unset foo +showfoo +echo outside 1.0: "foo=${foo-<unset>}" +foo=foo showfoo +showfoo +echo outside 1.1: "foo=${foo-<unset>}" + +unset foo +show2 +echo outside 2.0: "foo=${foo-<unset>}" +foo=foo show2 +show2 +echo outside 2.1: "foo=${foo-<unset>}" diff --git a/tests/varenv17.sub b/tests/varenv17.sub new file mode 100644 index 0000000..1f9278c --- /dev/null +++ b/tests/varenv17.sub @@ -0,0 +1,44 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +# testing -I and local variable inheritance +var=global + +f() +{ + local $1 var + declare -p var + + var=local + declare -p var +} + +declare -I var +declare -p var + +f +f -I +unset var +f +f -I + +f1() +{ + var=$FUNCNAME + + f + f -I +} + +f1 diff --git a/tests/varenv18.sub b/tests/varenv18.sub new file mode 100644 index 0000000..4ad7f1a --- /dev/null +++ b/tests/varenv18.sub @@ -0,0 +1,41 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +arr=(zero one two) +four=four + +f() +{ + local -a arr=( "${arr[@]}" ) + arr+=(three four five) + declare -p arr +} +f +declare -p arr + +f1() +{ + local -a arr=(three $four five) + declare -p arr +} +f1 + +set -u +name='arr[@]' +f2() +{ + local -a arr=("${!name}") + declare -p arr +} +f2 diff --git a/tests/varenv19.sub b/tests/varenv19.sub new file mode 100644 index 0000000..753f508 --- /dev/null +++ b/tests/varenv19.sub @@ -0,0 +1,51 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +# variable attribute inheritance problems without specifying -a or -A + +function aaa() { + local x='1 2 3' + echo "aaa ${x}" +} + +function bbb { + local x + x=(4 5 6) + echo "bbb ${x[*]}" +} + +ccc() +{ + local x=(7 8 9) + echo "ccc ${x[*]}" +} + +function ddd +{ + local -r x='0' + echo "ddd ${x}" + aaa + bbb + ccc +} + +ddd + +f() +{ + local x=(one two three) + declare -p x +} +f +declare -p x diff --git a/tests/varenv2.sub b/tests/varenv2.sub new file mode 100644 index 0000000..0fde5b2 --- /dev/null +++ b/tests/varenv2.sub @@ -0,0 +1,57 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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/varenv20.sub b/tests/varenv20.sub new file mode 100644 index 0000000..5fba8c4 --- /dev/null +++ b/tests/varenv20.sub @@ -0,0 +1,13 @@ +# tests of local variables with the same name as variables passed in the +# temporary environment + +f() { local v=x; local -p; } +v=t f + +f() { local v; declare -p v; } +v=t f + +f() { local v=x; unset v; declare -p v; } +v=g +f +v=t f diff --git a/tests/varenv21.sub b/tests/varenv21.sub new file mode 100644 index 0000000..613e475 --- /dev/null +++ b/tests/varenv21.sub @@ -0,0 +1,48 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# test behavior of `local -' inside shell functions + +IGNOREEOF=0 +shopt -o ignoreeof + +f() +{ + local - + set +o ignoreeof + shopt -o ignoreeof +} + +f +shopt -o ignoreeof +echo $IGNOREEOF + +unset -f f + +f() +{ + local - + set -m -H +B + set -u +} + +before="$-|$SHELLOPTS" +f +after="$-|$SHELLOPTS" + +case "$after" in +$before) echo match 1 ;; +*) echo bad 1 ;; +esac + +unset -f f diff --git a/tests/varenv22.sub b/tests/varenv22.sub new file mode 100644 index 0000000..6d42bb5 --- /dev/null +++ b/tests/varenv22.sub @@ -0,0 +1,17 @@ +# test behavior of FUNCNAME in and out of parse_and_execute scenarios + +# in parse_and_execute +${THIS_SH} -c 'trap "echo trap:\$FUNCNAME" EXIT ; trap ; f() { exit; } ; f' bash + +${THIS_SH} << \EOF +eval "trap 'echo trap:\$FUNCNAME' EXIT ; trap; f() { exit; } ; f" +EOF + +# not in parse_and_execute +${THIS_SH} << \EOF +trap 'echo trap:$FUNCNAME' EXIT ; trap; f() { exit; } ; f +EOF + +# this has to be last +trap 'echo trap:$FUNCNAME' EXIT ; trap; f() { exit; } ; f + diff --git a/tests/varenv3.sub b/tests/varenv3.sub new file mode 100644 index 0000000..854e483 --- /dev/null +++ b/tests/varenv3.sub @@ -0,0 +1,44 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +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..9735b61 --- /dev/null +++ b/tests/varenv4.sub @@ -0,0 +1,71 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..b6eb70c --- /dev/null +++ b/tests/varenv5.sub @@ -0,0 +1,29 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..8cf21f7 --- /dev/null +++ b/tests/varenv6.sub @@ -0,0 +1,41 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..4b25960 --- /dev/null +++ b/tests/varenv7.sub @@ -0,0 +1,75 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..5837aa5 --- /dev/null +++ b/tests/varenv9.sub @@ -0,0 +1,79 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# 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..6465595 --- /dev/null +++ b/tests/vredir.right @@ -0,0 +1,101 @@ +10 +foo 1 +foo 2 +foo 3 +bar is a function +bar () +{ + exec {v}> $TMPFILE; + echo $v +} +./vredir.tests: line 19: v: readonly variable +./vredir.tests: line 19: 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]}- +} +./vredir8.sub: line 12: $fd: Bad file descriptor diff --git a/tests/vredir.tests b/tests/vredir.tests new file mode 100644 index 0000000..bd4cb77 --- /dev/null +++ b/tests/vredir.tests @@ -0,0 +1,62 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +: ${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 +${THIS_SH} ./vredir8.sub + +exit 0 diff --git a/tests/vredir1.sub b/tests/vredir1.sub new file mode 100644 index 0000000..484f313 --- /dev/null +++ b/tests/vredir1.sub @@ -0,0 +1,30 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..4f9e7bb --- /dev/null +++ b/tests/vredir2.sub @@ -0,0 +1,65 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +: ${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..f861bcf --- /dev/null +++ b/tests/vredir4.sub @@ -0,0 +1,35 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..beb45ac --- /dev/null +++ b/tests/vredir5.sub @@ -0,0 +1,36 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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..0f76f40 --- /dev/null +++ b/tests/vredir7.sub @@ -0,0 +1,36 @@ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +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 diff --git a/tests/vredir8.sub b/tests/vredir8.sub new file mode 100644 index 0000000..e87b45b --- /dev/null +++ b/tests/vredir8.sub @@ -0,0 +1,13 @@ +# test varredir_close + +: {fd}<>/dev/null + +echo redir 1 >&$fd +exec {fd}>&- + +shopt -s varredir_close + +: {fd}<>/dev/tty + +echo redir 2 >&$fd +exec {fd}>&- |