summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/alias.right3
-rw-r--r--tests/alias.tests9
-rw-r--r--tests/alias6.sub13
-rw-r--r--tests/arith.right4
-rw-r--r--tests/arith.tests4
-rw-r--r--[-rwxr-xr-x]tests/array-at-star0
-rw-r--r--tests/array.right60
-rw-r--r--tests/array.tests2
-rw-r--r--tests/array15.sub15
-rw-r--r--tests/array27.sub8
-rw-r--r--tests/array29.sub86
-rw-r--r--tests/array30.sub46
-rw-r--r--tests/assoc.right184
-rw-r--r--tests/assoc.tests24
-rw-r--r--tests/assoc11.sub2
-rw-r--r--tests/assoc12.sub74
-rw-r--r--tests/assoc13.sub44
-rw-r--r--tests/assoc14.sub35
-rw-r--r--tests/assoc15.sub92
-rw-r--r--tests/assoc16.sub56
-rw-r--r--tests/assoc17.sub58
-rw-r--r--tests/assoc18.sub59
-rw-r--r--tests/assoc9.sub29
-rw-r--r--tests/builtins.right13
-rw-r--r--tests/builtins.tests4
-rw-r--r--tests/builtins5.sub11
-rw-r--r--tests/case.right1
-rw-r--r--tests/case.tests4
-rw-r--r--tests/complete.right44
-rw-r--r--tests/comsub-eof.right18
-rw-r--r--tests/comsub-eof0.sub2
-rw-r--r--tests/comsub-eof5.sub6
-rw-r--r--tests/comsub-posix.right28
-rw-r--r--tests/comsub-posix.tests29
-rw-r--r--tests/comsub-posix1.sub2
-rw-r--r--tests/comsub-posix5.sub70
-rw-r--r--tests/comsub-posix6.sub43
-rw-r--r--tests/comsub.right22
-rw-r--r--tests/comsub.tests9
-rw-r--r--tests/comsub5.sub51
-rw-r--r--tests/comsub6.sub40
-rw-r--r--tests/cond.right8
-rw-r--r--tests/cond.tests18
-rw-r--r--tests/cprint.right2
-rw-r--r--[-rwxr-xr-x]tests/dollar-at-star19
-rw-r--r--tests/dollar-at-star10.sub66
-rw-r--r--tests/dollar-at-star11.sub80
-rw-r--r--tests/dollar.right67
-rw-r--r--tests/dynvar.tests26
-rw-r--r--tests/errors.right170
-rw-r--r--tests/errors.tests12
-rw-r--r--tests/errors7.sub2
-rw-r--r--tests/errors9.sub14
-rw-r--r--tests/exec.right41
-rw-r--r--tests/exec14.sub17
-rw-r--r--tests/exec3.sub33
-rw-r--r--tests/exp.right15
-rw-r--r--tests/exp.tests1
-rw-r--r--tests/exp13.sub34
-rw-r--r--tests/exp8.sub3
-rw-r--r--tests/exportfunc.right2
-rw-r--r--tests/exportfunc.tests10
-rw-r--r--tests/extglob.right76
-rw-r--r--tests/extglob.tests6
-rw-r--r--tests/extglob2.sub26
-rw-r--r--tests/extglob6.sub43
-rw-r--r--tests/extglob7.sub97
-rw-r--r--tests/func.tests6
-rw-r--r--tests/getopts10.sub4
-rw-r--r--tests/glob.right6
-rw-r--r--tests/glob.tests1
-rw-r--r--tests/glob10.sub32
-rw-r--r--tests/glob2.sub8
-rw-r--r--tests/glob5.sub2
-rw-r--r--tests/glob6.sub1
-rw-r--r--tests/heredoc.right37
-rw-r--r--tests/heredoc.tests7
-rw-r--r--tests/heredoc6.sub50
-rw-r--r--tests/heredoc7.sub29
-rw-r--r--tests/herestr.tests6
-rw-r--r--tests/history.right37
-rw-r--r--tests/history.tests1
-rw-r--r--tests/history6.sub55
-rw-r--r--tests/intl.tests2
-rw-r--r--tests/intl2.sub22
-rw-r--r--tests/jobs.right2
-rw-r--r--tests/jobs4.sub2
-rw-r--r--tests/jobs5.sub10
-rw-r--r--tests/jobs7.sub2
-rw-r--r--tests/lastpipe.right2
-rw-r--r--tests/lastpipe.tests1
-rw-r--r--tests/lastpipe3.sub11
-rw-r--r--tests/mapfile.right1
-rw-r--r--tests/mapfile.tests7
-rw-r--r--[-rwxr-xr-x]tests/misc/run-r2.sh0
-rw-r--r--[-rwxr-xr-x]tests/misc/sigint-1.sh0
-rw-r--r--[-rwxr-xr-x]tests/misc/sigint-2.sh0
-rw-r--r--[-rwxr-xr-x]tests/misc/sigint-3.sh0
-rw-r--r--[-rwxr-xr-x]tests/misc/sigint-4.sh0
-rw-r--r--tests/nameref.right75
-rw-r--r--tests/nameref15.sub10
-rw-r--r--tests/nameref18.sub16
-rw-r--r--tests/nameref19.sub9
-rw-r--r--tests/nameref22.sub97
-rw-r--r--tests/nameref23.sub82
-rw-r--r--tests/new-exp.right74
-rw-r--r--tests/new-exp.tests4
-rw-r--r--tests/new-exp10.sub7
-rw-r--r--tests/new-exp14.sub19
-rw-r--r--tests/new-exp16.sub120
-rw-r--r--tests/nquote.right16
-rw-r--r--tests/nquote.tests9
-rw-r--r--tests/nquote4.sub6
-rw-r--r--tests/nquote5.sub36
-rw-r--r--tests/posix2.right6
-rw-r--r--tests/posix2.tests8
-rw-r--r--tests/posixexp.right26
-rw-r--r--tests/posixexp7.sub69
-rw-r--r--[-rwxr-xr-x]tests/precedence.tests0
-rw-r--r--tests/printf1.sub2
-rw-r--r--tests/printf2.sub8
-rw-r--r--tests/quotearray.right152
-rw-r--r--tests/quotearray.tests164
-rw-r--r--tests/quotearray1.sub131
-rw-r--r--tests/quotearray2.sub107
-rw-r--r--tests/quotearray3.sub117
-rw-r--r--tests/quotearray4.sub116
-rw-r--r--tests/quotearray5.sub124
-rw-r--r--tests/read.right25
-rw-r--r--tests/read.tests6
-rw-r--r--tests/read1.sub1
-rw-r--r--tests/read2.sub39
-rw-r--r--tests/read3.sub1
-rw-r--r--tests/read7.sub66
-rw-r--r--tests/read8.sub15
-rw-r--r--tests/rsh.right2
-rw-r--r--tests/run-all4
-rw-r--r--tests/run-execscript17
-rw-r--r--tests/run-intl3
-rw-r--r--tests/run-minimal4
-rw-r--r--tests/run-quotearray2
-rw-r--r--tests/shopt.right14
-rw-r--r--tests/test.right4
-rw-r--r--tests/test.tests3
-rw-r--r--tests/tilde.tests4
-rw-r--r--tests/tilde2.right4
-rw-r--r--tests/tilde2.tests2
-rw-r--r--tests/tilde3.sub26
-rw-r--r--tests/type.right4
-rw-r--r--tests/unicode1.sub16
-rw-r--r--tests/varenv.right13
-rw-r--r--tests/varenv.tests1
-rw-r--r--tests/varenv13.sub1
-rw-r--r--tests/varenv22.sub17
-rw-r--r--tests/vredir.right1
-rw-r--r--tests/vredir.tests1
-rw-r--r--tests/vredir8.sub13
157 files changed, 4198 insertions, 257 deletions
diff --git a/tests/alias.right b/tests/alias.right
index 9e33036b..76f32076 100644
--- a/tests/alias.right
+++ b/tests/alias.right
@@ -2,6 +2,7 @@ alias: 0
alias: 0
./alias.tests: line 38: qfoo: command not found
quux
+hi
bar
value
bar
@@ -40,3 +41,5 @@ baz
foo
bar
baz
+<áa>
+<aá>
diff --git a/tests/alias.tests b/tests/alias.tests
index 0280c16d..15eac5b1 100644
--- a/tests/alias.tests
+++ b/tests/alias.tests
@@ -49,8 +49,17 @@ 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/alias6.sub b/tests/alias6.sub
new file mode 100644
index 00000000..d2d7daf5
--- /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/arith.right b/tests/arith.right
index c74602e3..02687815 100644
--- a/tests/arith.right
+++ b/tests/arith.right
@@ -259,5 +259,5 @@ efg
42
42
42
-./arith.tests: line 327: 'foo' : syntax error: operand expected (error token is "'foo' ")
-./arith.tests: line 331: b[c]d: syntax error in expression (error token is "d")
+./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
index 1a3501aa..e9ab5765 100644
--- a/tests/arith.tests
+++ b/tests/arith.tests
@@ -322,10 +322,12 @@ 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/array-at-star b/tests/array-at-star
index 80f039d2..80f039d2 100755..100644
--- a/tests/array-at-star
+++ b/tests/array-at-star
diff --git a/tests/array.right b/tests/array.right
index 2d1c51db..62278852 100644
--- a/tests/array.right
+++ b/tests/array.right
@@ -67,6 +67,7 @@ declare -ar a=([1]="" [2]="bdef" [5]="hello world" [6]="test expression" [15]="t
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
@@ -84,6 +85,7 @@ declare -ar a=([1]="" [2]="bdef" [5]="hello world" [6]="test expression" [15]="t
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
@@ -381,6 +383,8 @@ strlen(4four) = 5
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
@@ -492,8 +496,8 @@ x b c
declare -a a=([1]="2" [2]="3" [3]="4")
abcd
unset
-./array21.sub: line 30: typeset: a: not found
-./array21.sub: line 33: typeset: A: not found
+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")
@@ -520,13 +524,11 @@ argv[1] = <y>
<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 ) ")
-foo
-0
-foo
-foo
-foo
-6
-./array23.sub: line 34: $( 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
@@ -743,23 +745,43 @@ argv[1] = <b>
argv[2] = <a>
argv[1] = <b+a>
7
-./array27.sub: line 24: a[]]=7 : syntax error: invalid arithmetic operator (error token is "]=7 ")
+7
declare -A A=([$'\t']="2" [" "]="2" )
-./array27.sub: line 36: ((: A[]]=2 : syntax error: invalid arithmetic operator (error token is "]=2 ")
-declare -A A=([$'\t']="2" ["*"]="2" [" "]="2" ["@"]="2" )
-./array27.sub: line 45: A[]]: bad array subscript
+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 53: A[]]: bad array subscript
+./array27.sub: line 60: printf: `A[]]': not a valid identifier
declare -A A=([$'\t']="X" ["*"]="X" [" "]="X" ["@"]="X" )
-./array27.sub: line 61: declare: `A[]]=X': not a valid identifier
+./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" )
-./array27.sub: line 69: declare: `A[]]=X': not a valid identifier
-./array27.sub: line 69: A[*]: bad array subscript
-./array27.sub: line 69: A[@]: bad array subscript
-declare -A A
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
index ba8e2254..d0bb08b7 100644
--- a/tests/array.tests
+++ b/tests/array.tests
@@ -425,3 +425,5 @@ ${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/array15.sub b/tests/array15.sub
index 47796b95..12f5391e 100644
--- a/tests/array15.sub
+++ b/tests/array15.sub
@@ -35,3 +35,18 @@ func()
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/array27.sub b/tests/array27.sub
index 44ed444d..e2a1e708 100644
--- a/tests/array27.sub
+++ b/tests/array27.sub
@@ -40,6 +40,13 @@ 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
@@ -69,4 +76,3 @@ for k in ']' '*' '@'; do
declare "A[$k]=X"
done
declare -p A
-
diff --git a/tests/array29.sub b/tests/array29.sub
new file mode 100644
index 00000000..f73c2d1c
--- /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/array30.sub b/tests/array30.sub
new file mode 100644
index 00000000..14f97980
--- /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/assoc.right b/tests/assoc.right
index e9aa9172..9a1662c4 100644
--- a/tests/assoc.right
+++ b/tests/assoc.right
@@ -16,25 +16,24 @@ 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
-./assoc.tests: line 53: chaff[*]: bad array subscript
-./assoc.tests: line 54: [*]=12: invalid associative array key
-declare -A chaff=(["hello world"]="flip" [one]="a" )
+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 words>
-argv[2] = <flip>
-argv[3] = <a>
argv[1] = <multiple>
argv[2] = <words>
-argv[3] = <flip>
-argv[4] = <a>
-argv[1] = <multiple words flip a>
+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
-./assoc.tests: line 73: chaff[*]: bad array subscript
-./assoc.tests: line 74: [*]=12: invalid associative array key
declare -A wheat=([six]="6" ["foo bar"]="qux qix" )
argv[1] = <qux>
argv[2] = <qix>
@@ -200,11 +199,7 @@ declare -A hash=([key]="value1 value2" )
declare -A b=([")"]="" ["\""]="" ["]"]="" ["\\"]="" ["\`"]="" )
declare -A b=(["]"]="" ["\`"]="" )
declare -A dict=(["'"]="3" ["\""]="1" ["\\"]="4" ["\`"]="2" )
-./assoc9.sub: line 36: unset: `dict[']': not a valid identifier
-./assoc9.sub: line 36: unset: `dict["]': not a valid identifier
-./assoc9.sub: line 36: unset: `dict[\]': not a valid identifier
-./assoc9.sub: line 36: unset: `dict[`]': not a valid identifier
-declare -A dict=(["'"]="3" ["\""]="1" ["\\"]="4" ["\`"]="2" )
+declare -A dict=()
declare -A dict=(["'"]="3" ["\""]="1" ["\\"]="4" ["\`"]="2" )
declare -A dict=()
4
@@ -223,6 +218,14 @@ declare -A a=(["80's"]="Depeche Mode" )
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
@@ -250,11 +253,148 @@ declare -A dict=(["?"]="quest" ["*"]="star" ["'"]="squote" ["\$"]="dol" ["\""]="
dict=( "?" "quest" "*" "star" "'" "squote" "\$" "dol" "\"" "dquote" "\\" "bslash" "@" "at" "}" "rbrace" "{" "lbrace" "\`" "bquote" )
declare -A foo=([two]="" [one]="1" )
foo=( two "" one "1" )
-rparen dquote rbrace bs
-declare -A a=([")"]="rparen" ["\""]="dquote" ["]"]="rbrace" ["\\"]="bs" )
-")" "rparen" "\"" "dquote" "]" "rbrace" "\\" "bs"
-declare -A a=([")"]="rparen" ["\""]="dquote" ["]"]="rbrace" ["\\"]="bs" )
-declare -A a=([")"]="rparen" ["\""]="dquote" ["]"]="rbrace" ["\\"]="bs" )
-declare -A a=([")"]="rparen" ["\""]="dquote" ["]"]="rbrace" ["\\"]="bs" )
+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
index 8d5c8927..c656536b 100644
--- a/tests/assoc.tests
+++ b/tests/assoc.tests
@@ -47,7 +47,7 @@ declare +i chaff
chaff[hello world]=flip
declare -p chaff
-# TEST - errors
+# TEST - no longer errors
waste[stuff]=other
unset waste
chaff[*]=12
@@ -244,3 +244,25 @@ ${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/assoc11.sub b/tests/assoc11.sub
index 13111a52..9d9afae9 100644
--- a/tests/assoc11.sub
+++ b/tests/assoc11.sub
@@ -69,7 +69,7 @@ foo=(one 1 two)
declare -p foo
echo foo=\( ${foo[@]@K} \)
-typeset -A a=( [\\]=bs [\"]=dquote [\)]=rparen [\]]=rbrace )
+typeset -A a=( [\\]=bs [\"]=dquote [\)]=rparen [\]]=rbracket )
echo ${a[@]}
declare -p a
diff --git a/tests/assoc12.sub b/tests/assoc12.sub
new file mode 100644
index 00000000..359dc0b3
--- /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 00000000..7e669727
--- /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 00000000..95df0492
--- /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 00000000..c47b1535
--- /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 00000000..ae8296b3
--- /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 00000000..a98aaa15
--- /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 00000000..05976093
--- /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/assoc9.sub b/tests/assoc9.sub
index b8867187..f83ac6d5 100644
--- a/tests/assoc9.sub
+++ b/tests/assoc9.sub
@@ -128,3 +128,32 @@ 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/builtins.right b/tests/builtins.right
index 832472f6..4f51d436 100644
--- a/tests/builtins.right
+++ b/tests/builtins.right
@@ -1,3 +1,4 @@
+1000
a
end-1
a
@@ -144,11 +145,11 @@ AVAR
foo
declare -x foo=""
declare -x FOO="\$\$"
-./builtins.tests: line 226: declare: FOO: not found
+./builtins.tests: line 228: declare: FOO: not found
declare -x FOO="\$\$"
ok
ok
-./builtins.tests: line 258: kill: 4096: invalid signal specification
+./builtins.tests: line 260: kill: 4096: invalid signal specification
1
a\n\n\nb
a
@@ -178,10 +179,16 @@ unset2
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
@@ -271,4 +278,4 @@ type
+ command -p -- command -v type
type
+ set +x
-./builtins.tests: line 282: exit: status: numeric argument required
+./builtins.tests: line 284: exit: status: numeric argument required
diff --git a/tests/builtins.tests b/tests/builtins.tests
index 00ebc0fd..8eee43e6 100644
--- a/tests/builtins.tests
+++ b/tests/builtins.tests
@@ -15,7 +15,9 @@
set +p
set +o posix
-ulimit -c 0 2>/dev/null
+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
diff --git a/tests/builtins5.sub b/tests/builtins5.sub
index d36e03a5..4fcf793d 100644
--- a/tests/builtins5.sub
+++ b/tests/builtins5.sub
@@ -36,15 +36,25 @@ 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
@@ -71,4 +81,3 @@ echo scalar: ${#scalar3}
echo scalar: ${#scalar3[@]}
-
diff --git a/tests/case.right b/tests/case.right
index 557bcadf..d33c8c5a 100644
--- a/tests/case.right
+++ b/tests/case.right
@@ -14,6 +14,7 @@ no
no
no
ok
+esac
ok 1
ok 2
ok 3
diff --git a/tests/case.tests b/tests/case.tests
index 2ffcb906..7ad4c683 100644
--- a/tests/case.tests
+++ b/tests/case.tests
@@ -62,6 +62,10 @@ 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
diff --git a/tests/complete.right b/tests/complete.right
index 5bc89a05..c8bf1dc0 100644
--- a/tests/complete.right
+++ b/tests/complete.right
@@ -1,41 +1,49 @@
complete -f -X '!*.+(ps|PS)' gs
-complete -c nice
complete -e printenv
-complete -c gdb
complete -f -X '!*.texi*' texi2html
-complete -j -P '%' fg
complete -g groupmod
-complete -f -X '!*.dvi' dvips
-complete -f -X '!*.texi*' texi2dvi
complete -v -S '=' typeset
-complete -f .
complete -c nohup
complete -a unalias
complete -g groupdel
complete -A hostname telnet
-complete -v -S '=' declare
-complete -v -S '=' export
complete -v -S '=' local
complete -v -S '=' readonly
complete -o bashdefault -o filenames -o nospace -F _comp_cd cd
-complete -f -X '!*.dvi' xdvi
complete -c type
complete -f ln
complete -f -X '!*.+(gz|tgz)' gunzip
complete -f -X '!*.texi*' makeinfo
-complete -u su
complete -j -P '%' jobs
-complete -o dirnames -o filenames -o nospace -d popd
-complete -A signal trap
complete -o dirnames -o filenames -o nospace -d pushd
complete -f -X '!*.pdf' acroread
complete -v unset
complete -f -X '!*.+(ps|PS)' ghostview
-complete -j -W '$(ps -x | tail +2 | cut -c1-5)' -P '%' wait
complete -A hostname rsh
complete -c exec
-complete -f -X '!*.Z' zmore
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
@@ -45,19 +53,11 @@ complete -A stopped -P '%' bg
complete -f cat
complete -d mkdir
complete -A helptopic help
-complete -c eval
-complete -f chown
complete -v read
complete -c -k time
complete -f -X '!*.Z' zcat
-complete -f gzip
-complete -W '"${GROUPS[@]}"' newgrp
complete -f -X '!*.Z' uncompress
complete -d rmdir
-complete -A shopt shopt
-complete -A hostname ftp
complete -f more
-complete -A hostname rlogin
-complete -v getopts
complete -f -X '!*.+(gz|tgz)' gzcat
./complete.tests: line 123: complete: notthere: no completion specification
diff --git a/tests/comsub-eof.right b/tests/comsub-eof.right
index 42677985..cd5ab692 100644
--- a/tests/comsub-eof.right
+++ b/tests/comsub-eof.right
@@ -1,15 +1,17 @@
-./comsub-eof0.sub: line 1: unexpected EOF while looking for matching `)'
-./comsub-eof0.sub: line 5: syntax error: unexpected end of file
+./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 1: unexpected EOF while looking for matching `)'
-./comsub-eof3.sub: line 5: syntax error: unexpected end of file
-./comsub-eof4.sub: line 6: warning: here-document at line 4 delimited by end-of-file (wanted `EOF')
+./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 8: warning: here-document at line 6 delimited by end-of-file (wanted `)')
+./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 13: warning: here-document at line 11 delimited by end-of-file (wanted `EOF')
+./comsub-eof5.sub: line 15: warning: here-document at line 13 delimited by end-of-file (wanted `)')
hi
-./comsub-eof6.sub: line 1: unexpected EOF while looking for matching `)'
+./comsub-eof6.sub: command substitution: line 3: unexpected EOF while looking for matching `)'
diff --git a/tests/comsub-eof0.sub b/tests/comsub-eof0.sub
index 7b0775fb..7490faab 100644
--- a/tests/comsub-eof0.sub
+++ b/tests/comsub-eof0.sub
@@ -1,3 +1,5 @@
+# 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 )
diff --git a/tests/comsub-eof5.sub b/tests/comsub-eof5.sub
index 3da9107e..4bada675 100644
--- a/tests/comsub-eof5.sub
+++ b/tests/comsub-eof5.sub
@@ -7,3 +7,9 @@ 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-posix.right b/tests/comsub-posix.right
index 9aebb848..037f0ed2 100644
--- a/tests/comsub-posix.right
+++ b/tests/comsub-posix.right
@@ -5,11 +5,14 @@ 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
@@ -56,9 +59,8 @@ here-doc with \()
here-doc terminated with a parenthesis
' # or a single back- or doublequote
line terminated with a backslash
-./comsub-posix1.sub: command substitution: line 2: syntax error near unexpected token `)'
-./comsub-posix1.sub: command substitution: line 2: ` if x; then echo foo )'
-after
+./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 ()
{
@@ -74,5 +76,25 @@ swap32_posix ()
));
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
index 4fe1dfaa..ab7cd295 100644
--- a/tests/comsub-posix.tests
+++ b/tests/comsub-posix.tests
@@ -28,6 +28,11 @@ 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)
@@ -42,6 +47,9 @@ echo $(
echo abc # a comment with )
)
+echo $(#a comment with )
+echo def)
+
echo $(
cat <<eof
here doc with )
@@ -226,11 +234,13 @@ echo $(
)
${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)"
"
@@ -247,6 +257,12 @@ unset x
: $(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
@@ -257,5 +273,14 @@ testing=$(
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
index bbcc60fb..de6f473a 100644
--- a/tests/comsub-posix1.sub
+++ b/tests/comsub-posix1.sub
@@ -1,3 +1,3 @@
echo $( if x; then echo foo )
-echo after
+echo should not see this
diff --git a/tests/comsub-posix5.sub b/tests/comsub-posix5.sub
new file mode 100644
index 00000000..f10e773a
--- /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 00000000..212ad204
--- /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
index a329c832..eae8c3b2 100644
--- a/tests/comsub.right
+++ b/tests/comsub.right
@@ -19,6 +19,7 @@ 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
@@ -55,3 +56,24 @@ 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
index 47863024..698ce30b 100644
--- a/tests/comsub.tests
+++ b/tests/comsub.tests
@@ -69,7 +69,16 @@ 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/comsub5.sub b/tests/comsub5.sub
new file mode 100644
index 00000000..cc83374c
--- /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 00000000..d2b02bf4
--- /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.right b/tests/cond.right
index 59a4a886..a72a1537 100644
--- a/tests/cond.right
+++ b/tests/cond.right
@@ -2,6 +2,10 @@ returns: 0
returns: 0
returns: 1
returns: 0
+1
+0
+1
+0
returns: 0
returns: 0
returns: 0
@@ -23,10 +27,12 @@ returns: 0
returns: 1
returns: 1
returns: 0
-./cond.tests: line 114: [[: 4+: syntax error: operand expected (error token is "+")
+./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
diff --git a/tests/cond.tests b/tests/cond.tests
index aa6a8104..c0747e98 100644
--- a/tests/cond.tests
+++ b/tests/cond.tests
@@ -33,6 +33,14 @@ echo returns: $?
[[ ! 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: $?
@@ -122,6 +130,13 @@ 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
@@ -207,6 +222,9 @@ del=$'\177'
[[ "" == "$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
diff --git a/tests/cprint.right b/tests/cprint.right
index 20000724..269136dc 100644
--- a/tests/cprint.right
+++ b/tests/cprint.right
@@ -19,7 +19,7 @@ tf ()
i=$(( i + 1 ));
done;
[[ -r /dev/fd/0 && -w /dev/fd/1 ]] || echo oops > /dev/null;
- for name in $( echo 1 2 3 );
+ for name in $(echo 1 2 3);
do
test -r /dev/fd/$name;
done;
diff --git a/tests/dollar-at-star b/tests/dollar-at-star
index d4808989..721eea12 100755..100644
--- a/tests/dollar-at-star
+++ b/tests/dollar-at-star
@@ -1,3 +1,17 @@
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# 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 "$@"
@@ -246,6 +260,11 @@ ${THIS_SH} ./dollar-at-star8.sub
# 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
diff --git a/tests/dollar-at-star10.sub b/tests/dollar-at-star10.sub
new file mode 100644
index 00000000..6b52b015
--- /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 00000000..b7a6ec46
--- /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.right b/tests/dollar.right
index 09910d7e..10c5cca1 100644
--- a/tests/dollar.right
+++ b/tests/dollar.right
@@ -399,6 +399,73 @@ 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
diff --git a/tests/dynvar.tests b/tests/dynvar.tests
index 5aefab64..ddf69ed1 100644
--- a/tests/dynvar.tests
+++ b/tests/dynvar.tests
@@ -50,15 +50,27 @@ unset before after
# EPOCHSECONDS
# not exact, but should work
-# could also use python -c 'import time; ts = int(time.time()); print(ts)'
-now1=$(perl -e 'print time')
+# 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
-case $now1 in
-$now2) echo EPOCHSECONDS ok ;;
-*) echo "current time via perl and EPOCHSECONDS possible mismatch|$now1|$now2" >&2 ;;
-esac
-unset now1 now2
+# 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
diff --git a/tests/errors.right b/tests/errors.right
index be0c8959..0bd88efb 100644
--- a/tests/errors.right
+++ b/tests/errors.right
@@ -11,93 +11,95 @@ declare -fr func
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: unset: XPATH: cannot unset: readonly variable
-./errors.tests: line 68: unset: cannot simultaneously unset a function and a variable
-./errors.tests: line 71: declare: -z: invalid option
-declare: usage: declare [-aAfFgiIlnrtux] [-p] [name[=value] ...]
-./errors.tests: line 73: declare: `-z': not a valid identifier
-./errors.tests: line 74: declare: `/bin/sh': not a valid identifier
-./errors.tests: line 78: declare: cannot use `-f' to make functions
-./errors.tests: line 81: exec: -i: invalid option
+./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 85: export: XPATH: not a function
-./errors.tests: line 88: break: only meaningful in a `for', `while', or `until' loop
-./errors.tests: line 89: continue: only meaningful in a `for', `while', or `until' loop
-./errors.tests: line 92: shift: label: numeric argument required
-./errors.tests: line 97: shift: too many arguments
-./errors.tests: line 103: let: expression expected
-./errors.tests: line 106: local: can only be used in a function
-./errors.tests: line 109: logout: not login shell: use `exit'
-./errors.tests: line 112: hash: notthere: not found
-./errors.tests: line 115: hash: -v: invalid option
+./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 119: hash: hashing disabled
-./errors.tests: line 122: export: `AA[4]': not a valid identifier
-./errors.tests: line 123: readonly: `AA[4]': not a valid identifier
-./errors.tests: line 126: unset: [-2]: bad array subscript
-./errors.tests: line 130: AA: readonly variable
-./errors.tests: line 134: AA: readonly variable
-./errors.tests: line 142: shift: 5: shift count out of range
-./errors.tests: line 143: shift: -2: shift count out of range
-./errors.tests: line 146: shopt: no_such_option: invalid shell option name
-./errors.tests: line 147: shopt: no_such_option: invalid shell option name
-./errors.tests: line 150: umask: 09: octal number out of range
-./errors.tests: line 151: umask: `:': invalid symbolic mode character
-./errors.tests: line 152: umask: `:': invalid symbolic mode operator
-./errors.tests: line 155: umask: -i: invalid option
+./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 159: umask: `u': invalid symbolic mode character
-./errors.tests: line 168: VAR: readonly variable
-./errors.tests: line 171: declare: VAR: readonly variable
-./errors.tests: line 172: declare: VAR: readonly variable
-./errors.tests: line 174: declare: unset: not found
-./errors.tests: line 177: VAR: readonly variable
-./errors.tests: command substitution: line 181: syntax error near unexpected token `)'
-./errors.tests: command substitution: line 181: ` for z in 1 2 3; do )'
-./errors.tests: command substitution: line 182: syntax error near unexpected token `done'
-./errors.tests: command substitution: line 182: ` for z in 1 2 3; done )'
-./errors.tests: line 184: cd: HOME not set
-./errors.tests: line 185: cd: /tmp/xyz.bash: No such file or directory
-./errors.tests: line 187: cd: OLDPWD not set
-./errors.tests: line 188: cd: /bin/sh: Not a directory
-./errors.tests: line 190: cd: /tmp/cd-notthere: No such file or directory
-./errors.tests: line 193: .: filename argument required
+./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 194: source: filename argument required
+./errors.tests: line 199: source: filename argument required
source: usage: source filename [arguments]
-./errors.tests: line 197: .: -i: invalid option
+./errors.tests: line 202: .: -i: invalid option
.: usage: . filename [arguments]
-./errors.tests: line 200: set: -q: invalid option
-set: usage: set [-abefhkmnptuvxBCHP] [-o option-name] [--] [arg ...]
-./errors.tests: line 203: enable: sh: not a shell builtin
-./errors.tests: line 203: enable: bash: not a shell builtin
-./errors.tests: line 206: shopt: cannot set and unset shell options simultaneously
-./errors.tests: line 209: read: var: invalid timeout specification
-./errors.tests: line 212: read: `/bin/sh': not a valid identifier
-./errors.tests: line 215: VAR: readonly variable
-./errors.tests: line 218: readonly: -x: invalid option
+./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 221: eval: -i: invalid option
+./errors.tests: line 226: eval: -i: invalid option
eval: usage: eval [arg ...]
-./errors.tests: line 222: command: -i: invalid option
+./errors.tests: line 227: command: -i: invalid option
command: usage: command [-pVv] command [arg ...]
-./errors.tests: line 225: /bin/sh + 0: syntax error: operand expected (error token is "/bin/sh + 0")
-./errors.tests: line 226: /bin/sh + 0: syntax error: operand expected (error token is "/bin/sh + 0")
-./errors.tests: line 229: trap: NOSIG: invalid signal specification
-./errors.tests: line 232: trap: -s: invalid option
+./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 238: return: can only `return' from a function or sourced script
-./errors.tests: line 242: break: 0: loop count out of range
-./errors.tests: line 246: continue: 0: loop count out of range
-./errors.tests: line 251: builtin: bash: not a shell builtin
-./errors.tests: line 255: bg: no job control
-./errors.tests: line 256: fg: no job control
-./errors.tests: line 259: kill: -s: option requires an argument
-./errors.tests: line 261: kill: S: invalid signal specification
-./errors.tests: line 263: kill: `': not a pid or valid job 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 268: set: trackall: invalid option name
-./errors.tests: line 272: xx: readonly variable
+./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]
@@ -174,14 +176,14 @@ 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
-./errors7.sub: line 21: notthere: command not found
-after no such command: 127
+after no such command: 1
./errors7.sub: line 23: x: readonly variable
-echo builtin
-after non-special builtin: 0
+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
@@ -194,7 +196,13 @@ ok 4
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 299: `!!': not a valid identifier
+./errors.tests: line 305: `!!': not a valid identifier
diff --git a/tests/errors.tests b/tests/errors.tests
index 531b625b..0880bb55 100644
--- a/tests/errors.tests
+++ b/tests/errors.tests
@@ -57,6 +57,11 @@ unset -f func
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
@@ -176,9 +181,9 @@ declare -p unset
# iteration variable in a for statement being readonly
for VAR in 1 2 3 ; do echo $VAR; done
-# parser errors
-: $( for z in 1 2 3; do )
-: $( for z in 1 2 3; done )
+# 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 )
@@ -287,6 +292,7 @@ ${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
diff --git a/tests/errors7.sub b/tests/errors7.sub
index add8782a..544e3e4c 100644
--- a/tests/errors7.sub
+++ b/tests/errors7.sub
@@ -26,3 +26,5 @@ echo after non-special builtin: $?
echo after special builtin: $? )
( x=8 $nocmd
echo after assignment error: $? )
+( x=8
+echo after assignment statement error: $? )
diff --git a/tests/errors9.sub b/tests/errors9.sub
new file mode 100644
index 00000000..3a267046
--- /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
index 0a249dda..ef02fbb4 100644
--- a/tests/exec.right
+++ b/tests/exec.right
@@ -20,8 +20,17 @@ after exec1.sub: one two three
126
0
this is bashenv
-./exec3.sub: line 3: /tmp/bash-notthere: No such file or directory
-127
+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
@@ -133,3 +142,31 @@ 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/exec14.sub b/tests/exec14.sub
index 3402fb95..eddd33fa 100644
--- a/tests/exec14.sub
+++ b/tests/exec14.sub
@@ -45,3 +45,20 @@ $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/exec3.sub b/tests/exec3.sub
index 4f2f8e21..81b53b72 100644
--- a/tests/exec3.sub
+++ b/tests/exec3.sub
@@ -1,6 +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 $?
+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/exp.right b/tests/exp.right
index 4e88ca9b..60241a1d 100644
--- a/tests/exp.right
+++ b/tests/exp.right
@@ -227,15 +227,16 @@ argv[2] = <Y>
argv[1] = <XY^AY>
argv[1] = <x^Ay^?z>
argv[1] = <x^Ay^?z>
-declare -- var="xyz"
+declare -- var=$'x\001y\177z'
argv[1] = <declare>
argv[2] = <-->
-argv[3] = <var="x^Ay^?z">
+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 29: xyz: syntax error: invalid arithmetic operator (error token is "z")
+./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>
@@ -408,3 +409,11 @@ 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
index 3e69db4f..61a39d3b 100644
--- a/tests/exp.tests
+++ b/tests/exp.tests
@@ -423,3 +423,4 @@ ${THIS_SH} ./exp9.sub
${THIS_SH} ./exp10.sub
${THIS_SH} ./exp11.sub
${THIS_SH} ./exp12.sub
+${THIS_SH} ./exp13.sub
diff --git a/tests/exp13.sub b/tests/exp13.sub
new file mode 100644
index 00000000..80e14635
--- /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/exp8.sub b/tests/exp8.sub
index 4c2870ca..7dd5a286 100644
--- a/tests/exp8.sub
+++ b/tests/exp8.sub
@@ -19,7 +19,8 @@ recho $var
declare -p var
recho $(declare -p var)
-declare -p var | sed -n l
+echo "var=$var" | sed -n l
+echo "declare -- var=\"$var\"" | sed -n l
recho ${var@Q}
recho ${var@P}
diff --git a/tests/exportfunc.right b/tests/exportfunc.right
index ff7fc8d9..890bdfa4 100644
--- a/tests/exportfunc.right
+++ b/tests/exportfunc.right
@@ -4,7 +4,7 @@ exportfunc ok 2
./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 64: HELLO_WORLD: No such file or directory
+./exportfunc.tests: line 72: HELLO_WORLD: No such file or directory
eval ok
./exportfunc3.sub: line 23: export: foo=bar: cannot export
status: 1
diff --git a/tests/exportfunc.tests b/tests/exportfunc.tests
index b2742d2c..d06b1a33 100644
--- a/tests/exportfunc.tests
+++ b/tests/exportfunc.tests
@@ -50,10 +50,18 @@ ${THIS_SH} ./exportfunc1.sub
${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;}<<`perl -e '{print "A"x100000}'` 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
diff --git a/tests/extglob.right b/tests/extglob.right
index 691f6879..2974ceca 100644
--- a/tests/extglob.right
+++ b/tests/extglob.right
@@ -92,16 +92,16 @@ a ab
a ab
a ab
a
-. ..
-. .. a.log
+*(.)
+a.log
*(foo)
*(foo|bar)
a.log
?(foo)
a.log
a.log
-. ..
-. ..
+*(foo).*
+*(foo|bar).*
a.log
a.log
.x .y .z
@@ -114,3 +114,71 @@ 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
index 4cb671a8..7a7cf91b 100644
--- a/tests/extglob.tests
+++ b/tests/extglob.tests
@@ -380,13 +380,11 @@ shopt -u globstar
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/extglob2.sub b/tests/extglob2.sub
index f4a3b374..1088111f 100644
--- a/tests/extglob2.sub
+++ b/tests/extglob2.sub
@@ -2,6 +2,30 @@ 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
-echo "${a}" "${a//?aa}" "${a//\aaa}"
exit 0
diff --git a/tests/extglob6.sub b/tests/extglob6.sub
new file mode 100644
index 00000000..5e2aafbe
--- /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 00000000..5fab9cda
--- /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.tests b/tests/func.tests
index fffe3d2b..e35ec2b8 100644
--- a/tests/func.tests
+++ b/tests/func.tests
@@ -11,6 +11,12 @@
# 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))
diff --git a/tests/getopts10.sub b/tests/getopts10.sub
index cc8acb0c..49b2bfe9 100644
--- a/tests/getopts10.sub
+++ b/tests/getopts10.sub
@@ -15,10 +15,10 @@ set -- -a bb
readonly OPTARG
getopts :x x
-echo OPTARG = $OPTARG x = $x
+echo OPTARG = $OPTARG x = "$x"
getopts x x
-echo ${OPTARG-unset} x = $x
+echo ${OPTARG-unset} x = "$x"
typeset -r RO=foo
typeset -n OPTARG=RO
diff --git a/tests/glob.right b/tests/glob.right
index 94966905..723ee7b4 100644
--- a/tests/glob.right
+++ b/tests/glob.right
@@ -121,6 +121,10 @@ 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>
@@ -135,7 +139,7 @@ argv[2] = <abc>
argv[3] = <abd>
argv[4] = <abe>
tmp/l1 tmp/l2 tmp/*4 tmp/l3
-./glob.tests: line 65: no match: tmp/*4
+./glob.tests: line 66: no match: tmp/*4
argv[1] = <bdir/>
argv[1] = <*>
argv[1] = <a*>
diff --git a/tests/glob.tests b/tests/glob.tests
index b35d7336..02d53026 100644
--- a/tests/glob.tests
+++ b/tests/glob.tests
@@ -30,6 +30,7 @@ ${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
diff --git a/tests/glob10.sub b/tests/glob10.sub
new file mode 100644
index 00000000..7c14c0d2
--- /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
index cabc3502..09cb6d51 100644
--- a/tests/glob2.sub
+++ b/tests/glob2.sub
@@ -13,6 +13,14 @@
#
. ./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
diff --git a/tests/glob5.sub b/tests/glob5.sub
index 5735715d..a0dd623f 100644
--- a/tests/glob5.sub
+++ b/tests/glob5.sub
@@ -11,6 +11,8 @@
# 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}
diff --git a/tests/glob6.sub b/tests/glob6.sub
index f26ae4d6..88429838 100644
--- a/tests/glob6.sub
+++ b/tests/glob6.sub
@@ -12,6 +12,7 @@
# 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}
diff --git a/tests/heredoc.right b/tests/heredoc.right
index f6e53bea..cc193f66 100644
--- a/tests/heredoc.right
+++ b/tests/heredoc.right
@@ -67,13 +67,13 @@ qux
bar
qux
abc def geh
-./heredoc3.sub: line 23: warning: here-document at line 21 delimited by end-of-file (wanted `EOF')
+./heredoc3.sub: line 20: warning: here-document at line 18 delimited by end-of-file (wanted `EOF')
= here is the text =
-./heredoc3.sub: line 29: warning: here-document at line 27 delimited by end-of-file (wanted `EOF')
+./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 35: warning: here-document at line 33 delimited by end-of-file (wanted `EOF')
+./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 41: warning: here-document at line 39 delimited by end-of-file (wanted `EOF')
+./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
@@ -100,7 +100,34 @@ 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 149: warning: here-document at line 147 delimited by end-of-file (wanted `EOF')
+./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
index 430302f5..d10a7c10 100644
--- a/tests/heredoc.tests
+++ b/tests/heredoc.tests
@@ -137,6 +137,13 @@ ${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"
)
diff --git a/tests/heredoc6.sub b/tests/heredoc6.sub
new file mode 100644
index 00000000..1d5fff09
--- /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 00000000..4119df19
--- /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.tests b/tests/herestr.tests
index 6f4c74c2..c97fa4f2 100644
--- a/tests/herestr.tests
+++ b/tests/herestr.tests
@@ -11,6 +11,12 @@
# 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"
diff --git a/tests/history.right b/tests/history.right
index 379de48b..5273de6b 100644
--- a/tests/history.right
+++ b/tests/history.right
@@ -140,9 +140,9 @@ three
one
two
three
-5.1
+5.2
echo ${BASH_VERSION%\.*}
-5.1
+5.2
echo ${BASH_VERSION%\.*}
a
b
@@ -264,3 +264,36 @@ out of range 3
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
index 53321f05..5826d130 100644
--- a/tests/history.tests
+++ b/tests/history.tests
@@ -130,3 +130,4 @@ ${THIS_SH} ./history2.sub
${THIS_SH} ./history3.sub
${THIS_SH} ./history4.sub
${THIS_SH} ./history5.sub
+${THIS_SH} ./history6.sub
diff --git a/tests/history6.sub b/tests/history6.sub
new file mode 100644
index 00000000..a21d8d38
--- /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/intl.tests b/tests/intl.tests
index c3000fc7..c4ff02c3 100644
--- a/tests/intl.tests
+++ b/tests/intl.tests
@@ -62,7 +62,7 @@ ${THIS_SH} ./intl2.sub
# test splitting on characters instead of bytes
${THIS_SH} ./intl3.sub
-${THIS_SH} ./unicode1.sub 2>/dev/null
+${THIS_SH} ./unicode1.sub # 2>/dev/null
${THIS_SH} ./unicode2.sub
${THIS_SH} ./unicode3.sub 2>&1
diff --git a/tests/intl2.sub b/tests/intl2.sub
index 64961bcb..2f3236e6 100644
--- a/tests/intl2.sub
+++ b/tests/intl2.sub
@@ -1,5 +1,25 @@
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# 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
-export LANG=de_DE.UTF-8
+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
diff --git a/tests/jobs.right b/tests/jobs.right
index 5d03b76b..0510e044 100644
--- a/tests/jobs.right
+++ b/tests/jobs.right
@@ -31,6 +31,8 @@ i killed it
./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
diff --git a/tests/jobs4.sub b/tests/jobs4.sub
index 7ecd7123..9f1cd040 100644
--- a/tests/jobs4.sub
+++ b/tests/jobs4.sub
@@ -34,4 +34,6 @@ 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
index e6ffb44e..e348f2e2 100644
--- a/tests/jobs5.sub
+++ b/tests/jobs5.sub
@@ -59,3 +59,13 @@ 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/jobs7.sub b/tests/jobs7.sub
index 3e76db37..582365ff 100644
--- a/tests/jobs7.sub
+++ b/tests/jobs7.sub
@@ -3,4 +3,6 @@ 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
index cca5938d..84e1e2ea 100644
--- a/tests/lastpipe.right
+++ b/tests/lastpipe.right
@@ -18,3 +18,5 @@ A2
B1
B2
HI -- 42 -- 0 42
+x=x
+x=x
diff --git a/tests/lastpipe.tests b/tests/lastpipe.tests
index 775e81dd..f9d669dd 100644
--- a/tests/lastpipe.tests
+++ b/tests/lastpipe.tests
@@ -71,3 +71,4 @@ ${THIS_SH} ./lastpipe1.sub
echo lastpipe1.sub returns $?
${THIS_SH} ./lastpipe2.sub
+${THIS_SH} ./lastpipe3.sub
diff --git a/tests/lastpipe3.sub b/tests/lastpipe3.sub
new file mode 100644
index 00000000..b9222b8a
--- /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.right b/tests/mapfile.right
index 143d6ddc..4452232d 100644
--- a/tests/mapfile.right
+++ b/tests/mapfile.right
@@ -151,6 +151,7 @@ a
[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
diff --git a/tests/mapfile.tests b/tests/mapfile.tests
index 01f1f2e5..c2ea7d24 100644
--- a/tests/mapfile.tests
+++ b/tests/mapfile.tests
@@ -52,6 +52,11 @@ for (( i = 0 ; i < ${#E[@]} ; i++ )); do
echo "${E[${i}]}"
done
-${THIS_SH} ./mapfile1.sub
+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/misc/run-r2.sh b/tests/misc/run-r2.sh
index 0321a1bd..0321a1bd 100755..100644
--- a/tests/misc/run-r2.sh
+++ b/tests/misc/run-r2.sh
diff --git a/tests/misc/sigint-1.sh b/tests/misc/sigint-1.sh
index 7b74c307..7b74c307 100755..100644
--- a/tests/misc/sigint-1.sh
+++ b/tests/misc/sigint-1.sh
diff --git a/tests/misc/sigint-2.sh b/tests/misc/sigint-2.sh
index 69eaf56a..69eaf56a 100755..100644
--- a/tests/misc/sigint-2.sh
+++ b/tests/misc/sigint-2.sh
diff --git a/tests/misc/sigint-3.sh b/tests/misc/sigint-3.sh
index 2627fe6c..2627fe6c 100755..100644
--- a/tests/misc/sigint-3.sh
+++ b/tests/misc/sigint-3.sh
diff --git a/tests/misc/sigint-4.sh b/tests/misc/sigint-4.sh
index 587dd265..587dd265 100755..100644
--- a/tests/misc/sigint-4.sh
+++ b/tests/misc/sigint-4.sh
diff --git a/tests/nameref.right b/tests/nameref.right
index 296105c9..83e9ee5b 100644
--- a/tests/nameref.right
+++ b/tests/nameref.right
@@ -348,6 +348,10 @@ declare -a v=([1]="1")
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
@@ -424,6 +428,23 @@ 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
@@ -440,6 +461,8 @@ 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>
@@ -483,3 +506,55 @@ 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/nameref15.sub b/tests/nameref15.sub
index cce8fbd9..e9a09eeb 100644
--- a/tests/nameref15.sub
+++ b/tests/nameref15.sub
@@ -115,3 +115,13 @@ 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/nameref18.sub b/tests/nameref18.sub
index a29fe379..7a32877f 100644
--- a/tests/nameref18.sub
+++ b/tests/nameref18.sub
@@ -65,3 +65,19 @@ 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
index b00f68e5..d4b900e8 100644
--- a/tests/nameref19.sub
+++ b/tests/nameref19.sub
@@ -62,3 +62,12 @@ 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/nameref22.sub b/tests/nameref22.sub
new file mode 100644
index 00000000..4e44fbb3
--- /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 00000000..358c381e
--- /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/new-exp.right b/tests/new-exp.right
index 752bba5c..e3dc40e1 100644
--- a/tests/new-exp.right
+++ b/tests/new-exp.right
@@ -617,7 +617,7 @@ c Sub = 0 2 4 8
<>
<>
<'ab '\''cd'\'' ef'>
-./new-exp10.sub: line 24: ${x@C}: bad substitution
+bash: line 1: ${x@C}: bad substitution
<'ab'> <'cd ef'> <''> <'gh'>
<'ab' 'cd ef' '' 'gh'>
<'ab'> <'cd> <ef'> <''> <'gh'>
@@ -625,7 +625,7 @@ c Sub = 0 2 4 8
<'ab cd'>
<'4'> <'ab cd'>
<>
-argv[1] = <host(2)[5.1]$ >
+argv[1] = <host(2)[5.2]$ >
<
>
<' \t\n'>
@@ -648,6 +648,7 @@ i
declare -i foo
A
declare -A foo
+./new-exp10.sub: line 118: ${V@}: bad substitution
abcxxxdef
abcådef
ḅć
@@ -703,11 +704,21 @@ 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
@@ -719,6 +730,65 @@ 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] = </>
diff --git a/tests/new-exp.tests b/tests/new-exp.tests
index 079426cb..c542313f 100644
--- a/tests/new-exp.tests
+++ b/tests/new-exp.tests
@@ -631,6 +631,10 @@ ${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
diff --git a/tests/new-exp10.sub b/tests/new-exp10.sub
index bf9ebe7a..5b199d4f 100644
--- a/tests/new-exp10.sub
+++ b/tests/new-exp10.sub
@@ -21,7 +21,9 @@ printf "<%s>" "${x@A}" ; echo
x="ab 'cd' ef"
printf "<%s> " "${x@Q}" ; echo
-printf "<%s>" "${x@C}"
+# 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
@@ -111,3 +113,6 @@ declare -A foo
echo ${foo@a}
declare -p foo
+
+V=42
+echo ${V@} # error
diff --git a/tests/new-exp14.sub b/tests/new-exp14.sub
index b8bda8de..92f51ea1 100644
--- a/tests/new-exp14.sub
+++ b/tests/new-exp14.sub
@@ -1,4 +1,18 @@
-# test the other uses of the 'K' tranform operator
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# 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
@@ -7,7 +21,9 @@ 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}"
@@ -17,3 +33,4 @@ echo ${foo[@]@K}
foo=( 'zero z' 'one o' 'two t' 'three t' )
echo ${foo[@]@K}
+recho "${foo[@]@k}"
diff --git a/tests/new-exp16.sub b/tests/new-exp16.sub
new file mode 100644
index 00000000..2ed751d3
--- /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/nquote.right b/tests/nquote.right
index e3ae5558..31c35c3b 100644
--- a/tests/nquote.right
+++ b/tests/nquote.right
@@ -35,6 +35,10 @@ argv[1] = <hello, $world>
;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!
@@ -62,3 +66,15 @@ argv[1] = <^?>
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
index 20d6415d..e4d1a56f 100644
--- a/tests/nquote.tests
+++ b/tests/nquote.tests
@@ -128,6 +128,15 @@ 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/nquote4.sub b/tests/nquote4.sub
new file mode 100644
index 00000000..0d4a4955
--- /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/nquote5.sub b/tests/nquote5.sub
new file mode 100644
index 00000000..97cbadc4
--- /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/posix2.right b/tests/posix2.right
index 40aea039..5d3f734a 100644
--- a/tests/posix2.right
+++ b/tests/posix2.right
@@ -1,6 +1,4 @@
Testing for POSIX.2 conformance
-./posix2.tests: eval: line 195: syntax error near unexpected token `esac'
-./posix2.tests: eval: line 195: `case esac in (esac) ;; *) echo "case esac test 3" ;; esac'
-./posix2.tests: eval: line 197: syntax error near unexpected token `)'
-./posix2.tests: eval: line 197: `case esac in esac) ;; *) echo "case esac test 4";; esac'
+./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
index 9b6c0932..0f5fce15 100644
--- a/tests/posix2.tests
+++ b/tests/posix2.tests
@@ -190,11 +190,13 @@ case esac in (foo|esac) ;; *) testfail "case esac test 1" ;; esac
newtest
case esac in foo|esac) ;; *) testfail "case esac test 2" ;; esac
-# these are supposed to be syntax errors
+# POSIX.2 grammar rule 4 problem through bash-5.1
newtest
-eval 'case esac in (esac) ;; *) echo "case esac test 3" ;; esac'
+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'
+eval 'case esac in esac) ;; *) echo "case esac test 4";; esac' && testfail 'case esac test 4'
if [ $exitval = 0 ]; then
echo "All tests passed"
diff --git a/tests/posixexp.right b/tests/posixexp.right
index e6bdbf4b..7204b960 100644
--- a/tests/posixexp.right
+++ b/tests/posixexp.right
@@ -275,14 +275,34 @@ argv[2] = <b>
[ abc def ghi jkl / abc def ghi jkl ]
[ abc def ghi jkl ]
[ abc def ghi jkl / abc def ghi jkl / abc def ghi jkl ]
-5: notOK
+1: OK
+2: $'not'
+3: OK
+4: OK
+5: tOK
OK
OK
-5: $'not\ttoo\nbad'
+$'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 `}'
-./posixexp.tests: line 98: syntax error: unexpected end of file
diff --git a/tests/posixexp7.sub b/tests/posixexp7.sub
index 2e230cf8..4e3fa007 100644
--- a/tests/posixexp7.sub
+++ b/tests/posixexp7.sub
@@ -1,13 +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
-# a here document does not behave the same as double quotes
+#
x=notOK
+x1=not
+
cat <<EOF
-5: ${x#$'not'}
+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
-5: $'not\ttoo\nbad'
+${x#${'x1'%$'t'}}
EOF
diff --git a/tests/precedence.tests b/tests/precedence.tests
index 111bd231..111bd231 100755..100644
--- a/tests/precedence.tests
+++ b/tests/precedence.tests
diff --git a/tests/printf1.sub b/tests/printf1.sub
index e4fb54b8..2cbbc6a6 100644
--- a/tests/printf1.sub
+++ b/tests/printf1.sub
@@ -24,7 +24,7 @@ printf "%s" "$vv"
printf -v vv "one\ctwo\n"
printf "%s" "$vv"
-# and unrecognized backslash escapes should have the backslash preserverd
+# and unrecognized backslash escapes should have the backslash preserved
printf -v vv "4\.2\n"
printf "%s" "$vv"
diff --git a/tests/printf2.sub b/tests/printf2.sub
index 45c48d4c..94a2bb10 100644
--- a/tests/printf2.sub
+++ b/tests/printf2.sub
@@ -1,6 +1,12 @@
unset LC_ALL LC_CTYPE
-export LANG=en_US.UTF-8
+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 ;;
diff --git a/tests/quotearray.right b/tests/quotearray.right
new file mode 100644
index 00000000..e6893659
--- /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 00000000..e1ed83b0
--- /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 00000000..19741b1f
--- /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 00000000..056f8ca2
--- /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 00000000..65f950d5
--- /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 00000000..964aac75
--- /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 00000000..5366a999
--- /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
index 11440837..e21fcb5f 100644
--- a/tests/read.right
+++ b/tests/read.right
@@ -30,19 +30,24 @@ 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
-
-./read2.sub: line 36: read: -3: invalid timeout specification
+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
#
@@ -64,3 +69,17 @@ FOO
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
index 7384f05f..6132b6fe 100644
--- a/tests/read.tests
+++ b/tests/read.tests
@@ -109,3 +109,9 @@ ${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
index b3b85157..cf003986 100644
--- a/tests/read1.sub
+++ b/tests/read1.sub
@@ -15,6 +15,7 @@ a=7
echo 'abcdefg|xyz' | {
read -d '|' a
echo a = "${a-unset}"
+ cat - # make sure we don't read too much
}
echo xyz 123 | {
diff --git a/tests/read2.sub b/tests/read2.sub
index 41698e46..d3530115 100644
--- a/tests/read2.sub
+++ b/tests/read2.sub
@@ -11,27 +11,36 @@
# 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 2 a < /dev/tty
+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}
-echo $a
-
-sleep 5 | read -t 1 a
+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}
-echo $a
+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 $?
@@ -40,6 +49,24 @@ echo $a
# the above should all time out
echo abcde | {
- read -t 2 a
+ 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
index d413f7db..8a240401 100644
--- a/tests/read3.sub
+++ b/tests/read3.sub
@@ -20,6 +20,7 @@ read -n -1
echo abcdefg | {
read -n 3 xyz
echo $xyz
+ cat - # make sure we don't read too much
}
# fewer chars than specified
diff --git a/tests/read7.sub b/tests/read7.sub
new file mode 100644
index 00000000..553070f4
--- /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 00000000..d5b7af8d
--- /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/rsh.right b/tests/rsh.right
index a91974a5..5f64049b 100644
--- a/tests/rsh.right
+++ b/tests/rsh.right
@@ -13,7 +13,7 @@
./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 [-abefhkmnptuvxBCHP] [-o option-name] [--] [arg ...]
+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/run-all b/tests/run-all
index b8219b2d..1f749239 100644
--- a/tests/run-all
+++ b/tests/run-all
@@ -23,12 +23,12 @@ SUFFIX=`${THIS_SH} -c 'echo $(( $RANDOM + $BASHPID ))'`
BASH_TSTOUT=${TMPDIR}/bashtst-$SUFFIX # for now
export BASH_TSTOUT
-trap 'rm -f $BASH_TSTOUT' 0 1 2 3 15
+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
diff --git a/tests/run-execscript b/tests/run-execscript
index de786442..c3ed53e6 100644
--- a/tests/run-execscript
+++ b/tests/run-execscript
@@ -1,5 +1,22 @@
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# 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
diff --git a/tests/run-intl b/tests/run-intl
index c31d1d0a..8234f280 100644
--- a/tests/run-intl
+++ b/tests/run-intl
@@ -1,8 +1,5 @@
# See whether or not we can use `diff -a'
( diff -a ./intl.right ./intl.right >/dev/null 2>&1 ) && AFLAG=-a
-echo "warning: some of these tests will fail if you do not have UTF-8" >&2
-echo "warning: locales installed on your system." >&2
-
${THIS_SH} ./intl.tests > ${BASH_TSTOUT}
diff $AFLAG ${BASH_TSTOUT} intl.right && rm -f ${BASH_TSTOUT}
diff --git a/tests/run-minimal b/tests/run-minimal
index ade30b15..0c3a2e5f 100644
--- a/tests/run-minimal
+++ b/tests/run-minimal
@@ -58,8 +58,8 @@ do
run-ifs-tests|run-input-test|run-invert|run-more-exp|run-nquote) echo $x ; sh $x ;;
run-ifs-posix|run-posix2|run-posixpat|run-posixpipe) echo $x ; sh $x ;;
run-precedence|run-quote|run-read|run-rhs-exp|run-strip|run-tilde) echo $x ; sh $x ;;
- run-dynvar) echo $x ; sh $x ;;
- ;;
+ 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"
diff --git a/tests/run-quotearray b/tests/run-quotearray
new file mode 100644
index 00000000..06e5e6eb
--- /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/shopt.right b/tests/shopt.right
index 8cf46db6..d617c1d7 100644
--- a/tests/shopt.right
+++ b/tests/shopt.right
@@ -28,6 +28,7 @@ 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
@@ -46,13 +47,16 @@ 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
@@ -66,8 +70,10 @@ 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
@@ -108,10 +114,12 @@ 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
@@ -150,10 +158,12 @@ 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
@@ -294,5 +304,9 @@ 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/test.right b/tests/test.right
index 391edbbd..4be22f4b 100644
--- a/tests/test.right
+++ b/tests/test.right
@@ -220,6 +220,8 @@ t ! -z "$z"
0
t ! -n "$z"
1
+t ! ! "$z"
+0
t "$zero"
1
t ! "$zero"
@@ -272,7 +274,7 @@ b ( 1 = 2
2
./test.tests: line 26: test: too many arguments
2
-./test.tests: line 431: [: missing `]'
+./test.tests: line 434: [: missing `]'
2
./test.tests: line 26: test: (: unary operator expected
2
diff --git a/tests/test.tests b/tests/test.tests
index 03e2754a..df4b8509 100644
--- a/tests/test.tests
+++ b/tests/test.tests
@@ -358,6 +358,9 @@ t ! -z "$z"
echo 't ! -n "$z"'
t ! -n "$z"
+echo 't ! ! "$z"'
+t ! ! "$z"
+
zero=
echo 't "$zero"'
t "$zero"
diff --git a/tests/tilde.tests b/tests/tilde.tests
index 374f3e6d..20268a73 100644
--- a/tests/tilde.tests
+++ b/tests/tilde.tests
@@ -86,7 +86,9 @@ echo ~$USER
cd "$wdir"
+# this test is incomplete; should also test assignment statements (tilde3.sub)
+echo foo=bar:~
+set -o posix
echo foo=bar:~
-set -o posix; echo foo=bar:~
exit 0
diff --git a/tests/tilde2.right b/tests/tilde2.right
index fce04687..f383e3a3 100644
--- a/tests/tilde2.right
+++ b/tests/tilde2.right
@@ -22,3 +22,7 @@ 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
index cc5dba9f..d2415cb3 100644
--- a/tests/tilde2.tests
+++ b/tests/tilde2.tests
@@ -81,3 +81,5 @@ 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 00000000..c35ea500
--- /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/type.right b/tests/type.right
index f876715a..bbc228e8 100644
--- a/tests/type.right
+++ b/tests/type.right
@@ -54,12 +54,12 @@ f ()
foo is a function
foo ()
{
- echo $(<x1)
+ echo $(< x1)
}
bar is a function
bar ()
{
- echo $(<x1)
+ echo $(< x1)
}
foo is a function
foo ()
diff --git a/tests/unicode1.sub b/tests/unicode1.sub
index fc742855..713ab40f 100644
--- a/tests/unicode1.sub
+++ b/tests/unicode1.sub
@@ -109,7 +109,13 @@ fr_FR_ISO_8859_1=(
[0x00fb]=$'\373' [0x00fc]=$'\374' [0x00fd]=$'\375' [0x00fe]=$'\376'
)
-TestCodePage fr_FR.ISO8859-1 fr_FR_ISO_8859_1
+# 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'
@@ -309,8 +315,14 @@ jp_JP_SHIFT_JIS=(
[0xFF9E]=$'\xDE' # HALFWIDTH KATAKANA VOICED SOUND MARK
[0xFF9F]=$'\xDF' # HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK
)
+
#TestCodePage ja_JP.SHIFT_JIS jp_JP_SHIFT_JIS
-TestCodePage ja_JP.SJIS jp_JP_SHIFT_JIS
+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=(
diff --git a/tests/varenv.right b/tests/varenv.right
index 358f5dc7..f6bd1b5b 100644
--- a/tests/varenv.right
+++ b/tests/varenv.right
@@ -168,10 +168,9 @@ 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
-./varenv13.sub: line 25: var[@]: bad array subscript
-declare -A var=([0]="X" )
+declare -A var=([0]="X" ["@"]="Y" )
help
-./varenv13.sub: line 34: `var[0]': not a valid identifier
+./varenv13.sub: line 35: `var[0]': not a valid identifier
1
declare -A var=([0]="X" )
declare -A var=([Y]="Y" )
@@ -265,6 +264,14 @@ 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
index b058ed4f..68c619ec 100644
--- a/tests/varenv.tests
+++ b/tests/varenv.tests
@@ -259,6 +259,7 @@ ${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/varenv13.sub b/tests/varenv13.sub
index 1f837ec7..1fa7d5b3 100644
--- a/tests/varenv13.sub
+++ b/tests/varenv13.sub
@@ -22,6 +22,7 @@ typeset -A var
f() { declare -p ${!var*}; }
+# this is no longer an error
var[0]=X var[@]=Y
f
diff --git a/tests/varenv22.sub b/tests/varenv22.sub
new file mode 100644
index 00000000..6d42bb57
--- /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/vredir.right b/tests/vredir.right
index b2c4cc9c..6465595b 100644
--- a/tests/vredir.right
+++ b/tests/vredir.right
@@ -98,3 +98,4 @@ swizzle ()
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
index ea59eecd..bd4cb775 100644
--- a/tests/vredir.tests
+++ b/tests/vredir.tests
@@ -57,5 +57,6 @@ ${THIS_SH} ./vredir5.sub
${THIS_SH} ./vredir6.sub
${THIS_SH} ./vredir7.sub
+${THIS_SH} ./vredir8.sub
exit 0
diff --git a/tests/vredir8.sub b/tests/vredir8.sub
new file mode 100644
index 00000000..e87b45b3
--- /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}>&-