summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/alias.right12
-rw-r--r--tests/alias.tests2
-rw-r--r--tests/alias3.sub12
-rw-r--r--tests/alias4.sub61
-rw-r--r--tests/arith-for.right8
-rw-r--r--tests/arith-for.tests14
-rw-r--r--tests/arith.right16
-rw-r--r--tests/arith.tests8
-rw-r--r--tests/arith8.sub37
-rw-r--r--tests/array.right155
-rw-r--r--tests/array.tests9
-rw-r--r--tests/array22.sub34
-rw-r--r--tests/array23.sub22
-rw-r--r--tests/array24.sub47
-rw-r--r--tests/array25.sub70
-rw-r--r--tests/array5.sub2
-rw-r--r--tests/assoc.right25
-rw-r--r--tests/assoc.tests12
-rw-r--r--tests/assoc9.sub110
-rw-r--r--tests/case.right35
-rw-r--r--tests/case.tests2
-rw-r--r--tests/case2.sub52
-rw-r--r--tests/case3.sub40
-rw-r--r--tests/comsub-posix.tests1
-rw-r--r--tests/comsub.right7
-rw-r--r--tests/comsub.tests13
-rw-r--r--tests/comsub1.sub6
-rw-r--r--tests/comsub2.sub6
-rw-r--r--tests/comsub4.sub27
-rw-r--r--tests/cond-regexp.sub42
-rw-r--r--tests/cond-regexp2.sub2
-rwxr-xr-xtests/cond.tests3
-rw-r--r--tests/coproc.tests4
-rwxr-xr-xtests/dollar-at-star31
-rw-r--r--tests/dollar-at-star4.sub2
-rw-r--r--tests/dollar-at7.sub46
-rw-r--r--tests/dollar-star8.sub21
-rw-r--r--tests/dollar-star9.sub46
-rw-r--r--tests/dollar.right99
-rw-r--r--tests/dstack2.tests3
-rw-r--r--tests/dynvar.right7
-rw-r--r--tests/dynvar.tests77
-rw-r--r--tests/errors.right56
-rw-r--r--tests/errors.tests3
-rw-r--r--tests/errors5.sub1
-rw-r--r--tests/errors6.sub23
-rw-r--r--tests/errors7.sub15
-rw-r--r--tests/exec12.sub1
-rw-r--r--tests/exec7.sub3
-rw-r--r--tests/execscript8
-rw-r--r--tests/exp.right71
-rw-r--r--tests/exp.tests3
-rw-r--r--tests/exp10.sub26
-rw-r--r--tests/exp11.sub92
-rw-r--r--tests/exp12.sub38
-rw-r--r--tests/exp5.sub5
-rw-r--r--tests/exp8.sub8
-rw-r--r--tests/extglob.right9
-rw-r--r--tests/extglob.tests2
-rw-r--r--tests/extglob1a.sub2
-rw-r--r--tests/extglob3.sub7
-rw-r--r--tests/extglob4.sub9
-rw-r--r--tests/extglob5.sub18
-rw-r--r--tests/getopts5.sub2
-rw-r--r--tests/glob.right59
-rw-r--r--tests/glob.tests4
-rw-r--r--tests/glob1.sub7
-rw-r--r--tests/glob2.sub44
-rw-r--r--tests/glob3.sub123
-rw-r--r--tests/globstar2.sub3
-rw-r--r--tests/heredoc.right28
-rw-r--r--tests/heredoc.tests14
-rw-r--r--tests/heredoc3.sub9
-rw-r--r--tests/heredoc4.sub12
-rw-r--r--tests/histexp.right13
-rw-r--r--tests/histexp.tests4
-rw-r--r--tests/histexp3.sub9
-rw-r--r--tests/history.right56
-rw-r--r--tests/history.tests6
-rw-r--r--tests/history3.sub36
-rw-r--r--tests/ifs.right2
-rw-r--r--tests/ifs.tests2
-rw-r--r--tests/ifs1.sub14
-rw-r--r--tests/jobs.right41
-rw-r--r--tests/jobs.tests3
-rw-r--r--tests/jobs1.sub2
-rw-r--r--tests/jobs4.sub10
-rw-r--r--tests/jobs6.sub14
-rw-r--r--tests/more-exp.tests4
-rw-r--r--tests/nameref.right49
-rw-r--r--tests/nameref11.sub22
-rw-r--r--tests/nameref15.sub18
-rw-r--r--tests/nameref19.sub51
-rw-r--r--tests/new-exp.right30
-rw-r--r--tests/new-exp.tests7
-rw-r--r--tests/new-exp1.sub11
-rw-r--r--tests/new-exp11.sub46
-rw-r--r--tests/new-exp2.sub13
-rw-r--r--tests/parser.right15
-rw-r--r--tests/parser.tests2
-rw-r--r--tests/posix2syntax.sub53
-rw-r--r--tests/posixexp.right242
-rw-r--r--tests/posixexp.tests5
-rw-r--r--tests/posixexp2.sub3
-rw-r--r--tests/posixexp2.tests2
-rw-r--r--tests/posixexp3.sub52
-rw-r--r--tests/posixexp4.sub31
-rw-r--r--tests/posixexp5.sub51
-rw-r--r--tests/posixexp6.sub57
-rw-r--r--tests/posixpat.tests7
-rw-r--r--tests/printf.right1
-rw-r--r--tests/printf.tests4
-rw-r--r--tests/printf3.sub4
-rw-r--r--tests/procsub.right29
-rw-r--r--tests/procsub.tests99
-rw-r--r--tests/procsub1.sub (renamed from tests/redir12.sub)0
-rw-r--r--tests/quote.right6
-rw-r--r--tests/quote.tests11
-rw-r--r--tests/quote1.sub2
-rw-r--r--tests/read.tests26
-rw-r--r--tests/redir.right5
-rw-r--r--tests/redir.tests1
-rw-r--r--tests/redir4.sub16
-rw-r--r--tests/redir6.sub2
-rw-r--r--tests/redir8.sub2
-rw-r--r--tests/rsh.right28
-rw-r--r--tests/rsh.tests3
-rw-r--r--tests/rsh1.sub16
-rw-r--r--tests/rsh2.sub17
-rw-r--r--tests/run-all12
-rw-r--r--tests/run-dynvar2
-rw-r--r--tests/run-minimal2
-rw-r--r--tests/run-procsub7
-rw-r--r--tests/set-x.right4
-rwxr-xr-xtests/set-x.tests5
-rw-r--r--tests/shopt.right9
-rw-r--r--tests/test-glue-functions6
-rw-r--r--tests/test.right4
-rw-r--r--tests/test.tests2
-rw-r--r--tests/test1.sub21
-rw-r--r--tests/tilde.tests4
-rw-r--r--tests/trap.right12
-rw-r--r--tests/trap.tests3
-rwxr-xr-xtests/trap2.sub24
-rw-r--r--tests/trap6.sub15
-rw-r--r--tests/type.right14
-rw-r--r--tests/type3.sub3
-rw-r--r--tests/varenv.right56
-rw-r--r--tests/varenv.sh13
-rw-r--r--tests/varenv10.sub47
-rw-r--r--tests/varenv11.sub30
-rw-r--r--tests/varenv12.sub62
-rw-r--r--tests/varenv9.sub66
-rw-r--r--tests/vredir.right2
154 files changed, 3359 insertions, 254 deletions
diff --git a/tests/alias.right b/tests/alias.right
index cab07a98..3ab9a717 100644
--- a/tests/alias.right
+++ b/tests/alias.right
@@ -18,3 +18,15 @@ one
two
three
four
+Error: bar
+ok 1
+ok 2
+text
+whoops: nullalias
+foo
+a
+a b
+a b
+a a b
+ok 3
+ok 4
diff --git a/tests/alias.tests b/tests/alias.tests
index d1ba97b3..6aa1218b 100644
--- a/tests/alias.tests
+++ b/tests/alias.tests
@@ -38,3 +38,5 @@ unalias foo bar baz
${THIS_SH} ./alias1.sub
${THIS_SH} ./alias2.sub
+${THIS_SH} ./alias3.sub
+${THIS_SH} ./alias4.sub
diff --git a/tests/alias3.sub b/tests/alias3.sub
new file mode 100644
index 00000000..bb94268a
--- /dev/null
+++ b/tests/alias3.sub
@@ -0,0 +1,12 @@
+#!/bin/bash
+shopt -s expand_aliases
+alias foo='oneword'
+foo_word='foo'
+#
+# Fails silently to match 'foo':
+#
+case "$foo_word"
+in
+ foo) ;;
+ *) echo bad 1;;
+esac
diff --git a/tests/alias4.sub b/tests/alias4.sub
new file mode 100644
index 00000000..966b93d1
--- /dev/null
+++ b/tests/alias4.sub
@@ -0,0 +1,61 @@
+shopt -s expand_aliases
+
+# from an austin-group report
+alias foo="echo 'Error:"
+foo bar'
+
+# from some FreeBSD sh tests
+
+v=1
+alias a='unalias -a
+v=2'
+eval a
+[ "$v" = 2 ] && echo ok 1
+v=1
+alias a='unalias a
+v=2'
+eval a
+[ "$v" = 2 ] && echo ok 2
+
+# make sure command doesn't ever reset anything even if it's made a keyword
+unalias -a
+alias command=command
+alias true='echo bad'
+eval 'command true'
+
+unalias -a
+alias alias0=command
+alias true='echo bad'
+eval 'alias0 true'
+
+# make sure null aliases are ok
+unalias -a
+alias nullalias=''
+alias foo='echo '
+foo nullalias text
+unalias foo
+
+# aliases shouldn't be expanded in quoted strings even when the previous word
+# is an alias whose expansion ends in a space
+alias foo="echo 'whoops: "
+foo nullalias'
+
+unalias -a
+
+# recursive alias definitions
+alias echo=echo
+eval echo foo
+
+alias echo='echo a'
+
+echo
+echo b
+eval echo b
+echo $(eval echo b)
+
+unalias -a
+
+# alias expansion when in a command position after redirections
+alias e=echo
+eval '</dev/null e ok 3'
+eval 'a=true e ok 4'
diff --git a/tests/arith-for.right b/tests/arith-for.right
index 5b25c5eb..5c09070b 100644
--- a/tests/arith-for.right
+++ b/tests/arith-for.right
@@ -64,11 +64,11 @@ fx ()
0
1
2
-./arith-for.tests: line 77: syntax error: arithmetic expression required
-./arith-for.tests: line 77: syntax error: `(( i=0; "i < 3" ))'
+bash: -c: line 0: syntax error: arithmetic expression required
+bash: -c: line 0: syntax error: `(( i=0; "i < 3" ))'
2
-./arith-for.tests: line 83: syntax error: `;' unexpected
-./arith-for.tests: line 83: syntax error: `(( i=0; i < 3; i++; 7 ))'
+bash: -c: line 0: syntax error: `;' unexpected
+bash: -c: line 0: syntax error: `(( i=0; i < 3; i++; 7 ))'
2
20
20
diff --git a/tests/arith-for.tests b/tests/arith-for.tests
index 00e2d4ae..33f4bd66 100644
--- a/tests/arith-for.tests
+++ b/tests/arith-for.tests
@@ -74,17 +74,19 @@ type fx
fx
# errors
-for (( i=0; "i < 3" ))
+{
+${THIS_SH} -c 'for (( i=0; "i < 3" ))
do
echo $i
-done
-echo $?
+done' ; echo $? ; } 2>&1 | sed 's|^.*/||'
+#echo $?
-for (( i=0; i < 3; i++; 7 ))
+{
+${THIS_SH} -c 'for (( i=0; i < 3; i++; 7 ))
do
echo $i
-done
-echo $?
+done' ; echo $?; } 2>&1 | sed 's|^.*/||'
+#echo $?
# one-liners added in post-bash-2.04
for ((i=0; i < 20; i++)) do : ; done
diff --git a/tests/arith.right b/tests/arith.right
index 13c8c710..2c3d172a 100644
--- a/tests/arith.right
+++ b/tests/arith.right
@@ -242,14 +242,22 @@ efg
e
abcdefg
efg
+0
+0
+0
+0
+0
+0
+0
8 12
-./arith.tests: line 294: ((: x=9 y=41 : syntax error in expression (error token is "y=41 ")
-./arith.tests: line 298: a b: syntax error in expression (error token is "b")
-./arith.tests: line 299: ((: a b: syntax error in expression (error token is "b")
+./arith.tests: line 297: ((: x=9 y=41 : syntax error in expression (error token is "y=41 ")
+./arith.tests: line 301: a b: syntax error in expression (error token is "b")
+./arith.tests: line 302: ((: a b: syntax error in expression (error token is "b")
42
42
42
42
42
42
-./arith.tests: line 310: b[c]d: syntax error in expression (error token is "d")
+./arith.tests: line 314: 'foo' : syntax error: operand expected (error token is "'foo' ")
+./arith.tests: line 318: b[c]d: syntax error in expression (error token is "d")
diff --git a/tests/arith.tests b/tests/arith.tests
index 79ce016d..bc9490e9 100644
--- a/tests/arith.tests
+++ b/tests/arith.tests
@@ -283,6 +283,9 @@ ${THIS_SH} ./arith6.sub
# part of word expansions such as substring extraction
${THIS_SH} ./arith7.sub
+# problems with evaluation of conditional expressions
+${THIS_SH} ./arith8.sub
+
x=4
y=7
@@ -306,5 +309,10 @@ printf "%u\n" $n
echo $(( 16#$(printf "%x\n" $n) ))
echo $(( 16#$(printf "%X\n" $n) ))
+# these are errors
+foo=1
+echo $(( 'foo' ))
+
+
# causes longjmp botches through bash-2.05b
a[b[c]d]=e
diff --git a/tests/arith8.sub b/tests/arith8.sub
new file mode 100644
index 00000000..1ab0895e
--- /dev/null
+++ b/tests/arith8.sub
@@ -0,0 +1,37 @@
+# problems with evaluation of wrong terms in conditional expressions through
+# bash-4.4
+
+a=0 x="a=1"
+((0?x:0))
+echo $a
+unset a x
+
+a=0 x="a=1"
+((1?0:x))
+echo $a
+unset a x
+
+a=0 x="a=1"
+((0?(x):0))
+echo $a
+unset a x
+
+a=0 x="a=1"
+((0?$x:0))
+echo $a
+unset a x
+
+a=0 x="a=1"
+((0&&x))
+echo $a
+unset a x
+
+a=0 x="a=1"
+((1||x))
+echo $a
+unset a x
+
+a=0
+((0?arr[a=1]:0))
+echo $a
+unset a
diff --git a/tests/array.right b/tests/array.right
index 031a0b7e..aab4153d 100644
--- a/tests/array.right
+++ b/tests/array.right
@@ -26,7 +26,7 @@ hello world
11
3
bdef hello world test expression test 2
-./array.tests: line 76: readonly: `a[5]': not a valid identifier
+./array.tests: line 79: readonly: `a[5]': not a valid identifier
declare -ar a=([1]="" [2]="bdef" [5]="hello world" [6]="test expression" [15]="test 2")
declare -ar c
declare -ar a=([1]="" [2]="bdef" [5]="hello world" [6]="test expression" [15]="test 2")
@@ -46,17 +46,17 @@ declare -ar c
declare -a d=([1]="" [2]="bdef" [5]="hello world" [6]="test" [9]="ninth element")
declare -a e=([0]="test")
declare -a f=([0]="" [1]="bdef" [2]="hello world" [3]="test" [4]="ninth element")
-./array.tests: line 100: a: readonly variable
-./array.tests: line 102: b[]: bad array subscript
-./array.tests: line 103: b[*]: bad array subscript
-./array.tests: line 104: ${b[ ]}: bad substitution
-./array.tests: line 106: c[-2]: bad array subscript
-./array.tests: line 107: c: bad array subscript
+./array.tests: line 103: a: readonly variable
+./array.tests: line 105: b[]: bad array subscript
+./array.tests: line 106: b[*]: bad array subscript
+./array.tests: line 107: ${b[ ]}: bad substitution
+./array.tests: line 109: c[-2]: bad array subscript
+./array.tests: line 110: c: bad array subscript
-./array.tests: line 109: d[7]: cannot assign list to array member
-./array.tests: line 111: []=abcde: bad array subscript
-./array.tests: line 111: [*]=last: cannot assign to non-numeric index
-./array.tests: line 111: [-65]=negative: bad array subscript
+./array.tests: line 112: d[7]: cannot assign list to array member
+./array.tests: line 114: []=abcde: bad array subscript
+./array.tests: line 114: [*]=last: cannot assign to non-numeric index
+./array.tests: line 114: [-65]=negative: bad array subscript
declare -a BASH_ARGC=()
declare -a BASH_ARGV=()
declare -a BASH_LINENO=([0]="0")
@@ -68,8 +68,8 @@ declare -a b=([0]="this" [1]="is" [2]="a" [3]="test" [4]="" [5]="/etc/passwd")
declare -ar c
declare -a d=([1]="test test")
declare -a f=([0]="" [1]="bdef" [2]="hello world" [3]="test" [4]="ninth element")
-./array.tests: line 119: unset: ps1: not an array variable
-./array.tests: line 123: declare: c: cannot destroy array variables in this way
+./array.tests: line 122: unset: ps1: not an array variable
+./array.tests: line 126: declare: c: cannot destroy array variables in this way
this of
this is a test of read using arrays
this test
@@ -127,7 +127,7 @@ grep [ 123 ] *
6 7 9 5
length = 3
value = new1 new2 new3
-./array.tests: line 239: narray: unbound variable
+./array.tests: line 242: narray: unbound variable
./array1.sub: line 1: syntax error near unexpected token `('
./array1.sub: line 1: `printf "%s\n" -a a=(a 'b c')'
./array2.sub: line 1: declare: `[]=asdf': not a valid identifier
@@ -154,10 +154,10 @@ for case if then else
12 14 16 18 20
4414758999202
aaa bbb
-./array.tests: line 289: syntax error near unexpected token `<>'
-./array.tests: line 289: `metas=( <> < > ! )'
-./array.tests: line 290: syntax error near unexpected token `<>'
-./array.tests: line 290: `metas=( [1]=<> [2]=< [3]=> [4]=! )'
+./array.tests: line 292: syntax error near unexpected token `<>'
+./array.tests: line 292: `metas=( <> < > ! )'
+./array.tests: line 293: syntax error near unexpected token `<>'
+./array.tests: line 293: `metas=( [1]=<> [2]=< [3]=> [4]=! )'
abc 3
case 4
abc case if then else 5
@@ -502,3 +502,122 @@ unset
declare -a a=()
declare -A A=()
declare -a foo=([0]="1" [1]="(4 5 6)" [2]="3")
+a1
+argv[1] = <>
+argv[2] = <>
+a2
+argv[1] = <>
+a3
+argv[1] = <>
+argv[2] = <x>
+a4
+argv[1] = <y>
+p1
+argv[1] = <>
+argv[2] = <>
+p2
+argv[1] = <>
+argv[2] = <x>
+p3
+argv[1] = <y>
+./array23.sub: line 9: $( echo >&2 foo ) : syntax error: operand expected (error token is "$( echo >&2 foo ) ")
+./array23.sub: line 10: $( echo >&2 foo ) : syntax error: operand expected (error token is "$( echo >&2 foo ) ")
+foo
+0
+foo
+foo
+foo
+6
+./array23.sub: line 21: $( echo >&2 foo ): syntax error: operand expected (error token is "$( echo >&2 foo )")
+./array23.sub: line 22: $( echo >&2 foo ): syntax error: operand expected (error token is "$( echo >&2 foo )")
+IFS=: ${var-$*}
+abc
+def ghi
+jkl
+abc
+def ghi
+jkl
+----
+IFS=: ${var=$*}
+abc
+def ghi
+jkl
+var=abc:def ghi:jkl
+abc
+def ghi
+jkl
+var=abc:def ghi:jkl
+----
+IFS=: ${var+$*}
+abc
+def ghi
+jkl
+abc
+def ghi
+jkl
+----
+IFS= ${var-$*}
+abc
+def ghi
+jkl
+abc
+def ghi
+jkl
+----
+IFS= ${var=$*}
+abcdef ghijkl
+var=abcdef ghijkl
+abcdef ghijkl
+var=abcdef ghijkl
+----
+IFS= ${var+$*}
+abc
+def ghi
+jkl
+abc
+def ghi
+jkl
+1. indexed:
+reference:
+./array25.sub: line 10: ${a[ ]}: bad substitution
+./array25.sub: line 11: ' ': syntax error: operand expected (error token is "' '")
+./array25.sub: line 12: ${a[ ]}: bad substitution
+4. 0
+5. 0
+6. 0
+assignment:
+1.declare -a a=([0]="10" [1]="1")
+2.declare -a a=([0]="11" [1]="1")
+3.declare -a a=([0]="12" [1]="1")
+4.declare -a a=([0]="13" [1]="1")
+arithmetic:
+1.declare -a a=([0]="0" [1]="1")
+2.declare -a a=([0]="0" [1]="1")
+3.declare -a a=([0]="0" [1]="1")
+4.declare -a a=([0]="0" [1]="1")
+5.declare -a a=([0]="0" [1]="1")
+6.declare -a a=([0]="11" [1]="1")
+7.declare -a a=([0]="0" [1]="1")
+8.declare -a a=([0]="13" [1]="1")
+2. associative:
+reference:
+./array25.sub: line 47: ${a[ ]}: bad substitution
+2.
+./array25.sub: line 49: ${a[ ]}: bad substitution
+4.
+5.
+6.
+assignment:
+1.declare -A a=([" "]="10" [0]="0" [1]="1" )
+2.declare -A a=([" "]="11" [0]="0" [1]="1" )
+3.declare -A a=([" "]="12" [0]="0" [1]="1" )
+4.declare -A a=([" "]="13" [0]="0" [1]="1" )
+arithmetic:
+1.declare -A a=([" "]="13" [0]="0" [1]="1" )
+2.declare -A a=([" "]="13" [0]="0" [1]="1" )
+3.declare -A a=([" "]="13" [0]="0" [1]="1" )
+4.declare -A a=([" "]="13" [0]="0" [1]="1" )
+5.declare -A a=([" "]="13" [0]="0" [1]="1" )
+6.declare -A a=([" "]="13" [0]="0" [1]="1" ["\" \""]="11" )
+7.declare -A a=([" "]="13" [0]="0" [1]="1" ["\" \""]="11" )
+8.declare -A a=([" "]="13" [0]="0" [1]="1" ["\" \""]="13" )
diff --git a/tests/array.tests b/tests/array.tests
index b1053937..e045d5c4 100644
--- a/tests/array.tests
+++ b/tests/array.tests
@@ -21,6 +21,9 @@ unset a
a=abcde
declare -a a
echo ${a[0]}
+if [ "$a" != "${a[0]}" ]; then
+ echo 'array.tests: $a and $a[0] array mismatch'
+fi
unset a
a=abcde
@@ -248,7 +251,7 @@ ${THIS_SH} ./array3.sub
${THIS_SH} ./array4.sub
set +u
-cd /tmp
+cd ${TMPDIR:=/tmp}
touch 1=bar
foo=([10]="bar")
@@ -397,3 +400,7 @@ ${THIS_SH} ./array18.sub
${THIS_SH} ./array19.sub
${THIS_SH} ./array20.sub
${THIS_SH} ./array21.sub
+${THIS_SH} ./array22.sub
+${THIS_SH} ./array23.sub
+${THIS_SH} ./array24.sub
+${THIS_SH} ./array25.sub
diff --git a/tests/array22.sub b/tests/array22.sub
new file mode 100644
index 00000000..e0463c34
--- /dev/null
+++ b/tests/array22.sub
@@ -0,0 +1,34 @@
+# This isn't perfect behavior, but it establishes a baseline and will provide
+# a way to detect behavior changes
+
+echo a1
+a[0]= a[1]=; recho "${a[@]:-y}"
+unset a
+
+echo a2
+a[1]=; recho "${a[@]:-y}"
+unset a
+
+echo a3
+a[0]= a[1]=x; recho "${a[@]:-y}"
+unset a
+
+echo a4
+a[0]= a[1]=x; recho ${a[@]:+y}
+unset a
+
+echo p1
+set '' ''
+recho "${@:-y}"
+
+shift $#
+
+echo p2
+set '' x
+recho "${@:-y}"
+
+shift $#
+
+echo p3
+set '' x
+recho ${@:+y}
diff --git a/tests/array23.sub b/tests/array23.sub
new file mode 100644
index 00000000..a762aadb
--- /dev/null
+++ b/tests/array23.sub
@@ -0,0 +1,22 @@
+# this captures how bash and ksh93 expand indexed array subscripts in
+# various contexts. if changes are ever made, or an option added to do
+# this differently, the diffs will show up here
+
+typeset -a array
+
+index='$( echo >&2 foo )' # Literal shell code should never be evaluated unless an 'eval' is involved.
+
+echo ${array[ $index ]} # [] expands $index, results in a literal that [] does not re-evaluate.
+echo $(( $index )) # (( )) expands $index, results in a literal that (( )) does not re-evaluate.
+echo $(( array[ $index ] )) # (( )) expands $index, results in a literal that [] DOES re-evaluate.
+
+(( array[ $index ] ))
+
+typeset -a a
+
+: $(( a[$index]=5 ))
+
+#shopt -s assoc_expand_once
+echo $((1+a[$index]))
+echo $((1+a[\$index]))
+echo "1+${a[$index]}"
diff --git a/tests/array24.sub b/tests/array24.sub
new file mode 100644
index 00000000..108f761b
--- /dev/null
+++ b/tests/array24.sub
@@ -0,0 +1,47 @@
+set -- "abc" "def ghi" "jkl"
+A=("$@")
+
+IFS=':'
+
+echo 'IFS=: ${var-$*}'
+unset var; printf '%s\n' ${var-$*}
+printf '%s\n' ${var-${A[*]}}
+
+echo "----"
+echo 'IFS=: ${var=$*}'
+
+unset var; printf '%s\n' ${var=$*}
+printf 'var=%s\n' "$var"
+
+unset var; printf '%s\n' ${var=${A[*]}}
+printf 'var=%s\n' "$var"
+
+echo "----"
+echo 'IFS=: ${var+$*}'
+
+printf '%s\n' ${var+$*}
+printf '%s\n' ${var+${A[*]}}
+
+echo "----"
+echo 'IFS= ${var-$*}'
+
+IFS=''
+unset var; printf '%s\n' ${var-$*}
+unset var; printf '%s\n' ${var-${A[*]}}
+
+echo "----"
+echo 'IFS= ${var=$*}'
+
+unset var
+printf '%s\n' ${var=$*}
+printf 'var=%s\n' "$var"
+
+unset var
+printf '%s\n' ${var=${A[*]}}
+printf 'var=%s\n' "$var"
+
+echo "----"
+echo 'IFS= ${var+$*}'
+
+printf '%s\n' ${var+$*}
+printf '%s\n' ${var+${A[*]}}
diff --git a/tests/array25.sub b/tests/array25.sub
new file mode 100644
index 00000000..b550d9d5
--- /dev/null
+++ b/tests/array25.sub
@@ -0,0 +1,70 @@
+# tests with blank subscripts, indexed and associative
+
+echo 1. indexed:
+a[0]=0 a[1]=1
+
+v=" "
+
+echo reference:
+
+echo 1. ${a[ ]}
+echo 2. ${a[' ']}
+echo 3. "${a[ ]}"
+echo 4. ${a[$v]}
+echo 5. ${a["$v"]}
+echo 6. "${a[$v]}"
+
+echo assignment:
+
+echo -n 1. ; a[ ]=10 ; typeset -p a ; a[0]=0
+echo -n 2. ; a[" "]=11 ; typeset -p a ; a[0]=0
+echo -n 3. ; a[$v]=12 ; typeset -p a ; a[0]=0
+echo -n 4. ; a["$v"]=13 ; typeset -p a ; a[0]=0
+
+echo arithmetic:
+
+echo -n 1. ; (( a[ ]=10 )); typeset -p a ; a[0]=0
+echo -n 2. ; (( a[" "]=11 )); typeset -p a ; a[0]=0
+echo -n 3. ; (( a[$v]=12 )); typeset -p a ; a[0]=0
+echo -n 4. ; (( a["$v"]=13 )); typeset -p a ; a[0]=0
+echo -n 5. ; let "a[ ]=10" ; typeset -p a ; a[0]=0
+echo -n 6. ; let "a[\" \"]=11" ; typeset -p a ; a[0]=0
+echo -n 7. ; let "a[$v]=12" ; typeset -p a ; a[0]=0
+echo -n 8. ; let "a[\"$v\"]=13" ; typeset -p a ; a[0]=0
+
+unset -v a v
+
+echo 2. associative:
+shopt -s assoc_expand_once
+
+typeset -A a
+a[0]=0 a[1]=1
+
+v=" "
+
+echo reference:
+
+echo 1. ${a[ ]}
+echo 2. ${a[' ']}
+echo 3. "${a[ ]}"
+echo 4. ${a[$v]}
+echo 5. ${a["$v"]}
+echo 6. "${a[$v]}"
+
+echo assignment:
+
+echo -n 1. ; a[ ]=10 ; typeset -p a ; a[0]=0
+echo -n 2. ; a[" "]=11 ; typeset -p a ; a[0]=0
+echo -n 3. ; a[$v]=12 ; typeset -p a ; a[0]=0
+echo -n 4. ; a["$v"]=13 ; typeset -p a ; a[0]=0
+
+echo arithmetic:
+
+echo -n 1. ; (( a[ ]=10 )); typeset -p a ; a[0]=0
+echo -n 2. ; (( a[" "]=11 )); typeset -p a ; a[0]=0
+echo -n 3. ; (( a[$v]=12 )); typeset -p a ; a[0]=0
+echo -n 4. ; (( a["$v"]=13 )); typeset -p a ; a[0]=0
+echo -n 5. ; let "a[ ]=10" ; typeset -p a ; a[0]=0
+echo -n 6. ; let "a[\" \"]=11" ; typeset -p a ; a[0]=0
+echo -n 7. ; let "a[$v]=12" ; typeset -p a ; a[0]=0
+echo -n 8. ; let "a[\"$v\"]=13" ; typeset -p a ; a[0]=0
diff --git a/tests/array5.sub b/tests/array5.sub
index 778a28df..00953c4a 100644
--- a/tests/array5.sub
+++ b/tests/array5.sub
@@ -4,7 +4,7 @@
mkdir $TMPDIR/bash-test-$$
cd $TMPDIR/bash-test-$$
-trap "cd / ; rm -rf $TMPDIR/bash-test-$$" 0 1 2 3 6 15
+trap "cd $OLDPWD ; rm -rf $TMPDIR/bash-test-$$" 0 1 2 3 6 15
touch '[3]=abcde'
diff --git a/tests/assoc.right b/tests/assoc.right
index 0a6951d4..e10636b2 100644
--- a/tests/assoc.right
+++ b/tests/assoc.right
@@ -195,3 +195,28 @@ declare -A assoc=([0]="assoc" )
assoc
declare -A assoc=([two]="twoless" [three]="three" [one]="onemore" )
declare -Ar assoc=([two]="twoless" [three]="three" [one]="onemore" )
+declare -A b=(["\""]="" [")"]="" ["\\"]="" ["]"]="" ["\`"]="" )
+declare -A b=(["]"]="" ["\`"]="" )
+declare -A dict=(["\""]="1" ["'"]="3" ["\\"]="4" ["\`"]="2" )
+./assoc9.sub: line 23: unset: `dict["]': not a valid identifier
+./assoc9.sub: line 23: unset: `dict[']': not a valid identifier
+./assoc9.sub: line 23: unset: `dict[\]': not a valid identifier
+./assoc9.sub: line 23: unset: `dict[`]': not a valid identifier
+declare -A dict=(["\""]="1" ["'"]="3" ["\\"]="4" ["\`"]="2" )
+declare -A dict=(["\""]="1" ["'"]="3" ["\\"]="4" ["\`"]="2" )
+declare -A dict=()
+4
+4
+a[$b]= 5
+declare -A a=(["80's"]="Depeche Mode" )
+./assoc9.sub: line 71: read: `a[80's]': not a valid identifier
+declare -A a
+declare -A a=(["80's"]="Depeche Mode" )
+./assoc9.sub: line 83: printf: `a[80's]': not a valid identifier
+declare -A a
+declare -A a=(["80's"]="Depeche Mode" )
+6
+1
+1+5
+declare -A a=(["\$(date >&2)"]="5" )
+declare -A myarray=([foo]="bleh" ["foo[bar"]="bleh" )
diff --git a/tests/assoc.tests b/tests/assoc.tests
index 32536b8d..24ab08c0 100644
--- a/tests/assoc.tests
+++ b/tests/assoc.tests
@@ -107,7 +107,7 @@ unset flix wheat
# TEST - index expansion: no word splitting or globbing
typeset -A wheat
-cd /tmp
+cd ${TMPDIR:=/tmp}
touch '[sfiri]'
wheat=([s*]=6 [foo bar]=flix )
@@ -174,6 +174,13 @@ T='([a]=1)'
echo "${T[@]}"
unset T
+# peculiar ksh93 semantics for unsubscripted assoc variable reference
+declare -A T
+T[0]='zero'
+if [ "$T" != "${T[0]}" ]; then
+ echo 'assoc.tests: $T and ${T[0]} mismatch'
+fi
+
${THIS_SH} ./assoc1.sub
${THIS_SH} ./assoc2.sub
@@ -207,3 +214,6 @@ readonly -A assoc
declare -p assoc
${THIS_SH} ./assoc8.sub
+
+# new shopt option to prevent multiple expansion of assoc array subscripts
+${THIS_SH} ./assoc9.sub
diff --git a/tests/assoc9.sub b/tests/assoc9.sub
new file mode 100644
index 00000000..c5fbe45b
--- /dev/null
+++ b/tests/assoc9.sub
@@ -0,0 +1,110 @@
+typeset -A a=( [\\]= [\"]= [\)]= ) b
+for x in "${!a[@]}"; do b[$x]=; done
+b+=([\`]= [\]]=)
+typeset -p b
+for x in "${!a[@]}"; do
+ unset -v 'b[$x]'
+done
+typeset -p b
+
+unset -v a b
+
+loaddict()
+{
+ dict['"']=1
+ dict['`']=2
+ dict["'"]=3
+ dict['\']=4
+ declare -p dict
+}
+
+del()
+{
+ unset -v dict["$1"];
+}
+
+declare -A dict
+loaddict
+for k in "${!dict[@]}"; do del "$k"; done
+declare -p dict
+
+unset 'dict[@]'
+
+shopt -s assoc_expand_once
+declare -A dict
+loaddict
+for k in "${!dict[@]}"; do del "$k"; done
+declare -p dict
+
+unset a b dict
+
+typeset -A a
+b="80's"
+
+((++a[$b]))
+
+((++a["$b"]))
+[[ $((++a[$b])) ]]
+[[ $((++a["$b"])) ]]
+echo ${a["$b"]}
+echo ${a[$b]}
+
+let "++a[$b]"
+
+echo 'a[$b]=' "${a[$b]}"
+
+unset a b
+
+declare -A a
+b="80's"
+
+: ${a[$b]:='Depeche Mode'}
+
+declare -p a
+
+unset a b
+shopt -u assoc_expand_once
+
+typeset -A a
+b="80's"
+
+read a[$b] <<<"Depeche Mode"
+typeset -p a
+
+shopt -s assoc_expand_once
+read a[$b] <<<"Depeche Mode"
+typeset -p a
+
+unset a
+shopt -u assoc_expand_once
+
+typeset -A a
+
+printf -v a[$b] "%s" "Depeche Mode"
+typeset -p a
+
+shopt -s assoc_expand_once
+
+printf -v a[$b] "%s" "Depeche Mode"
+typeset -p a
+
+unset a
+
+declare -A a
+x='$(date >&2)'
+a[$x]=5
+
+shopt -s assoc_expand_once
+echo $((1+a[$x]))
+echo $((1+a[\$x]))
+echo "1+${a[$x]}"
+
+declare -p a
+
+shopt -s assoc_expand_once
+declare -A myarray
+
+declare myarray["foo[bar"]=bleh
+myarray["foo"]=bleh
+
+declare -p myarray
diff --git a/tests/case.right b/tests/case.right
index a17234b9..d2055c9d 100644
--- a/tests/case.right
+++ b/tests/case.right
@@ -25,3 +25,38 @@ ok 8
ok 9
mysterious 1
mysterious 2
+argv[1] = <\a\b\c\^A\d\e\f>
+argv[1] = <\a\b\c\^A\d\e\f>
+argv[1] = <abc^Adef>
+ok 1
+ok 2
+ok 3
+ok 4
+ok 5
+ok 6
+ok 7
+ok 8
+--- testing: soh
+ok1ok2ok3ok4ok5
+ok1ok2ok3ok4ok5
+ok1ok2ok3ok4ok5
+ok1ok2ok3ok4ok5
+ok1ok2ok3ok4ok5
+ok1ok2ok3ok4ok5
+ok1ok2ok3ok4ok5
+--- testing: stx
+ok1ok2ok3ok4ok5
+ok1ok2ok3ok4ok5
+ok1ok2ok3ok4ok5
+ok1ok2ok3ok4ok5
+ok1ok2ok3ok4ok5
+ok1ok2ok3ok4ok5
+ok1ok2ok3ok4ok5
+--- testing: del
+ok1ok2ok3ok4ok5
+ok1ok2ok3ok4ok5
+ok1ok2ok3ok4ok5
+ok1ok2ok3ok4ok5
+ok1ok2ok3ok4ok5
+ok1ok2ok3ok4ok5
+ok1ok2ok3ok4ok5
diff --git a/tests/case.tests b/tests/case.tests
index 7ab316a7..cc73d8e1 100644
--- a/tests/case.tests
+++ b/tests/case.tests
@@ -51,3 +51,5 @@ case " " in ( [" "] ) echo ok;; ( * ) echo no;; esac
# tests of quote removal and pattern matching
${THIS_SH} ./case1.sub
+${THIS_SH} ./case2.sub
+${THIS_SH} ./case3.sub
diff --git a/tests/case2.sub b/tests/case2.sub
new file mode 100644
index 00000000..085f888c
--- /dev/null
+++ b/tests/case2.sub
@@ -0,0 +1,52 @@
+x=$'\\a\\b\\c\\\001\\d\\e\\f'
+y='\a\b\c\\d\e\f'
+z=$'abc\001def'
+
+recho "$x"
+recho "$y"
+recho "$z"
+
+case $'abc\001def' in
+$x) echo ok 1 ;;
+*) echo oops 1;;
+esac
+
+case $z in
+$x) echo ok 2 ;;
+*) echo oops 2;;
+esac
+
+case $'abc\001def' in
+$y) echo ok 3 ;;
+*) echo oops 3;;
+esac
+
+case $z in
+$y) echo ok 4 ;;
+*) echo oops 4;;
+esac
+
+# no backslash before \001
+x=$'\\a\\b\\c\001\\d\\e\\f'
+y='\a\b\c\d\e\f'
+
+case $'abc\001def' in
+$x) echo ok 5 ;;
+*) echo oops 5;;
+esac
+
+case $z in
+$x) echo ok 6 ;;
+*) echo oops 6;;
+esac
+
+case $'abc\001def' in
+$y) echo ok 7 ;;
+*) echo oops 7;;
+esac
+
+case $z in
+$y) echo ok 8 ;;
+*) echo oops 8;;
+esac
+
diff --git a/tests/case3.sub b/tests/case3.sub
new file mode 100644
index 00000000..77526c32
--- /dev/null
+++ b/tests/case3.sub
@@ -0,0 +1,40 @@
+#!/bin/sh
+
+testmatch() {
+ case $1 in
+ ( $2 ) printf ok1 ;;
+ ( * ) printf fail1 ;;
+ esac
+ case $1,$2 in
+ ( $2,"$2" ) printf ok2 ;;
+ ( * ) printf fail2 ;;
+ esac
+ case $1, in
+ ( $2, ) printf ok3 ;;
+ ( * ) printf fail3 ;;
+ esac
+ case ,$2 in
+ ( ,"$2" ) printf ok4 ;;
+ ( * ) printf fail4 ;;
+ esac
+ case "$1,$2" in
+ ( $2,"$2" ) printf ok5 ;;
+ ( * ) printf fail5 ;;
+ esac
+ echo
+}
+
+for c in $'\1' $'\2' $'\177'; do
+ echo -n "--- testing: "
+ echo "$c" | od -t a | awk 'NR==1 { print $2 } '
+ testmatch "${c}" "\\${c}"
+ testmatch "${c}x" "\\${c}\\x" # bash-git fails case 2 and 5 for $'\1'
+ testmatch "${c}x" "${c}\\x"
+ testmatch "${c}x" "${c}x"
+ testmatch "${c}x" "\\${c}x"
+ testmatch "x${c}" "\\x\\${c}"
+ testmatch "x${c}" "x\\${c}"
+done
+
+match() { case $1 in ( $2 ) ;; ( * ) return 1 ;; esac; }
+match $'? *x\1y\177z' $'??\\*\\x\\\1\\y\\\177\\z' || echo bad 6
diff --git a/tests/comsub-posix.tests b/tests/comsub-posix.tests
index 0650ca98..d53e6ebc 100644
--- a/tests/comsub-posix.tests
+++ b/tests/comsub-posix.tests
@@ -1,3 +1,4 @@
+: ${HOME:=/}
# works right
echo ab$(echo mnop)yz
diff --git a/tests/comsub.right b/tests/comsub.right
index 09518aae..71bb205a 100644
--- a/tests/comsub.right
+++ b/tests/comsub.right
@@ -28,6 +28,7 @@ ok 4
ok 5
ok 6
xyz
+ok 7
\/tmp\/foo\/bar
/tmp/foo/bar
/tmp/foo/bar
@@ -48,3 +49,9 @@ b
c
1
2
+d \
+g
+d \
+g
+d \
+g
diff --git a/tests/comsub.tests b/tests/comsub.tests
index 4defc31e..ed56007c 100644
--- a/tests/comsub.tests
+++ b/tests/comsub.tests
@@ -44,6 +44,19 @@ bar')
# long-standing parse error in all versions up through bash-4.3
echo ${foo:-$(echo a{b,c})} >/dev/null
+# parsing problem based on recursively calling bison parser through bash-4.4
+for (( INDEX=0; INDEX<$((10-$(echo length $V_NAME))); INDEX++ ))
+do
+ :
+done
+
+# problem with four-character words followed by a metachar through bash-4.4
+comsub_foo_1()
+{
+ echo $(while true; do case $HOME in /*) echo abs ;; esac; done)
+}
+
${THIS_SH} ./comsub1.sub
${THIS_SH} ./comsub2.sub
${THIS_SH} ./comsub3.sub
+${THIS_SH} ./comsub4.sub
diff --git a/tests/comsub1.sub b/tests/comsub1.sub
index 216e03f1..b1af263b 100644
--- a/tests/comsub1.sub
+++ b/tests/comsub1.sub
@@ -52,3 +52,9 @@ echo $( # we just took and pasted in some
# command substitution
echo xyz
)
+
+# problem with parse_comsub through bash-4.4
+case $(echo $$'x\nx') in
+x*) echo bad 7;;
+*) echo ok 7;;
+esac
diff --git a/tests/comsub2.sub b/tests/comsub2.sub
index a2d58ad0..d60ae6a0 100644
--- a/tests/comsub2.sub
+++ b/tests/comsub2.sub
@@ -3,6 +3,6 @@ qpath='\/tmp\/foo\/bar'
echo "$qpath"
# it's crazy that all three of these produce the same result
-echo ${qpath//\\/}
-echo ${qpath//"`echo \\`"/}
-echo ${qpath//`echo "\\\\\\\\"`/}
+printf "%s\n" ${qpath//\\/}
+printf "%s\n" ${qpath//"`printf '%s' \\`"/}
+printf "%s\n" ${qpath//`printf '%s' "\\\\\\\\"`/}
diff --git a/tests/comsub4.sub b/tests/comsub4.sub
new file mode 100644
index 00000000..461a9ad1
--- /dev/null
+++ b/tests/comsub4.sub
@@ -0,0 +1,27 @@
+x=$(cat <<'EOT'
+d \
+g
+EOT
+)
+
+echo "$x"
+unset x
+
+x=$( cat <<\EOT\
+4
+d \
+g
+EOT4
+)
+
+echo "$x"
+unset x
+
+x=$( cat <<\EOT
+d \
+g
+EOT
+)
+
+echo "$x"
+
diff --git a/tests/cond-regexp.sub b/tests/cond-regexp.sub
deleted file mode 100644
index 724957dd..00000000
--- a/tests/cond-regexp.sub
+++ /dev/null
@@ -1,42 +0,0 @@
-VAR='[[:alpha:]]'
-
-[[ $VAR =~ '[[:alpha:]]' ]] && echo match 1
-
-[[ a =~ '[[:alpha:]]' ]] || echo match 2
-
-[[ a =~ [[:alpha:]] ]] && echo match 3
-
-[[ a =~ $VAR ]] && echo match 4
-
-[[ a =~ "$VAR" ]] || echo match 5
-
-line=aab
-[[ $line =~ [[:space:]]*(a)?b ]] && echo match 6
-
-V="alphabet"
-[[ $V == alphabet ]] && echo yes 1
-[[ $V == "alphabet" ]] && echo yes 2
-[[ $V == 'alphabet' ]] && echo yes 3
-[[ $V =~ alphabet ]] && echo yes 4
-[[ $V =~ "alphabet" ]] && echo yes 5
-[[ $V =~ 'alphabet' ]] && echo yes 6
-
-DOG="Dog name - 01 - Wiggles"
-REPAT='([[:alpha:][:blank:]]*)- ([[:digit:]]*) - (.*)$'
-if [[ $DOG =~ ([[:alpha:][:blank:]]*)-\ ([[:digit:]]*)\ -\ (.*)$ ]]
-then
- echo Dog ${BASH_REMATCH[2]} is ${BASH_REMATCH[3]}
-fi
-if [[ $DOG =~ $REPAT ]]
-then
- echo Dog ${BASH_REMATCH[2]} is ${BASH_REMATCH[3]}
-fi
-
-[[ $REPAT =~ "$REPAT" ]] && echo rematch 1
-
-v="one two buckle my shoe"
-[[ ${v} =~ "one two" ]] && echo matches 7
-
-[[ ${v} =~ (one two) ]] && echo matches 8
-
-[[ ${v} =~ one\ two ]] && echo matches 9
diff --git a/tests/cond-regexp2.sub b/tests/cond-regexp2.sub
index 71abfb70..2bea6384 100644
--- a/tests/cond-regexp2.sub
+++ b/tests/cond-regexp2.sub
@@ -28,3 +28,5 @@
[[ ']' =~ [']'] ]] && echo ok 11
[[ a =~ ['a]'] ]] || echo ok 12
+
+[[ "\\" =~ [^]"."] ]] || echo unexpected
diff --git a/tests/cond.tests b/tests/cond.tests
index 8e4548ac..2cef9293 100755
--- a/tests/cond.tests
+++ b/tests/cond.tests
@@ -180,6 +180,9 @@ echo ${BASH_REMATCH[@]}
if [[ "123abc" == *?(a)bc ]]; then echo ok 42; else echo bad 42; fi
if [[ "123abc" == *?(a)bc ]]; then echo ok 43; else echo bad 43; fi
+match() { [[ $1 == $2 ]]; }
+match $'? *x\1y\177z' $'??\\*\\x\\\1\\y\\\177\\z' || echo bad 44
+
foo=""
[[ bar == *"${foo,,}"* ]] && echo ok 1
[[ bar == *${foo,,}* ]] && echo ok 2
diff --git a/tests/coproc.tests b/tests/coproc.tests
index d347eb74..5066f7c5 100644
--- a/tests/coproc.tests
+++ b/tests/coproc.tests
@@ -30,8 +30,8 @@ read LINE <&${REFLECT[0]}
echo $LINE
{ sleep 1; kill $REFLECT_PID; } &
-wait $REFLECT_PID >$TMPOUT 2>&1 || echo "coproc.tests: REFLECT: status $?"
-grep 'Terminated.*coproc.*REFLECT' < $TMPOUT >/dev/null 2>&1 || {
+wait $REFLECT_PID >$TMPOUT 2>&1 || { status=$? ; echo "coproc.tests: REFLECT: status $status" ; }
+[[ $status < 128 || $status == 143 ]] || {
echo "coproc.tests: wait for REFLECT failed" >&2
}
rm -f $TMPOUT
diff --git a/tests/dollar-at-star b/tests/dollar-at-star
index 2d2a1b66..0f713dc3 100755
--- a/tests/dollar-at-star
+++ b/tests/dollar-at-star
@@ -6,6 +6,23 @@ recho "$*"
recho $@
recho $*
+foo=$*
+foo=$@
+
+foo="$*"
+foo="$@"
+
+unset -v bar
+
+foo=${bar:-$*}
+foo=${bar:-$@}
+
+foo=${bar:-"$*"}
+foo=${bar:-"$@"}
+
+foo=${!*}
+foo=${!@}
+
set a b
recho "$*"
@@ -271,4 +288,18 @@ ${THIS_SH} ./dollar-star6.sub
# problem through bash-4.2
${THIS_SH} ./dollar-star7.sub
+# tests for expansions of $* (unquoted) when IFS is null and word splitting is
+# not going to be performed.
+# problem through bash-4.4 in some parameter expansion contexts
+${THIS_SH} ./dollar-star8.sub
+
+# tests for expansions of "$@" when there are no positional parameter or when
+# $1 == '' and the expansion is preceded by something that results in a quoted
+# null string
+${THIS_SH} ./dollar-at7.sub
+
+# tests for expansions of $* when in an assignment context (no splitting) and
+# IFS is null
+${THIS_SH} ./dollar-star9.sub
+
exit 0
diff --git a/tests/dollar-at-star4.sub b/tests/dollar-at-star4.sub
index 690eb677..be2892dd 100644
--- a/tests/dollar-at-star4.sub
+++ b/tests/dollar-at-star4.sub
@@ -33,10 +33,12 @@ unset a
unset IFS
set a b "c d"
printf '<%s>' $* ; echo
+printf '<%s>' ${q-$*} ; echo
IFS=
set a b "c d"
printf '<%s>' $* ; echo
+printf '<%s>' ${q-$*} ; echo
IFS=:
set a b
diff --git a/tests/dollar-at7.sub b/tests/dollar-at7.sub
new file mode 100644
index 00000000..311a6fef
--- /dev/null
+++ b/tests/dollar-at7.sub
@@ -0,0 +1,46 @@
+set -- ''
+
+recho 1 ''"$@"
+recho 2 """$@"
+
+recho 3 "$@""$@"
+recho 4 "$x""$@"
+
+set --
+
+echo -----
+recho 1 ''"$@"
+recho 2 """$@"
+
+recho 3 "$@""$@"
+recho 4 "$x""$@"
+
+set -- X
+
+echo ------
+recho 1 ''"${@/*}"
+recho 2 """${@/*}"
+
+recho 3 "$x""${@/*}"
+
+recho 4 ''"${@#X}"
+recho 5 """${@#X}"
+
+recho 6 "$x""${@#X}"
+
+set --
+
+echo -----
+recho 1 ''"${@/*}"
+recho 2 """${@/*}"
+
+recho 3 "$x""${@/*}"
+
+recho 4 ''"${@#X}"
+recho 5 """${@#X}"
+
+recho 6 "$x""${@#X}"
+
+echo -----
+recho 1 "$novar${*}$(echo)"
+recho 2 ''"$novar${@}$(echo)"
diff --git a/tests/dollar-star8.sub b/tests/dollar-star8.sub
new file mode 100644
index 00000000..72ba1080
--- /dev/null
+++ b/tests/dollar-star8.sub
@@ -0,0 +1,21 @@
+IFS=
+set "abc" "def ghi" "jkl"
+
+set ${1+$*}
+printf '<%s>\n' "$#" "$@"
+
+set "abc" "def ghi" "jkl"
+set $*
+printf '<%s>\n' "$#" "$@"
+
+printf '<%s>\n' $* ;
+printf '<%s>\n' ${q:-$*}
+printf '<%s>\n' "${q:-$*}"
+
+IFS=:
+printf '<%s>\n' $* ;
+printf '<%s>\n' ${q:-$*}
+printf '<%s>\n' "${q:-$*}"
+
+unset -v IFS
+printf '<%s>\n' $* $@
diff --git a/tests/dollar-star9.sub b/tests/dollar-star9.sub
new file mode 100644
index 00000000..26d0ed21
--- /dev/null
+++ b/tests/dollar-star9.sub
@@ -0,0 +1,46 @@
+set -- 1 2
+
+IFS=
+
+a=$* b=${*}
+c=${*/} d=${*#} e=${*%} f=${*:1}
+printf '<%s>' "$a" "$b" "$c" "$d" "$e" "$f"; echo
+
+unset a b c d e f
+: ${a=$*} ${b=${*}} ${c=${*/}}
+: ${d=${*#}} ${e=${*%}} ${f=${*:1}}
+printf '<%s>' "$a" "$b" "$c" "$d" "$e" "$f" ; echo
+
+unset f g
+f=${*,,} g=${*@Q}
+printf '<%s>' "$f" "$g" ; echo
+
+unset -v a b c d e f g
+unset var
+
+# resetting IFS here
+
+IFS=$' \t\n'
+
+printf '%s\n' "${*:1}"
+var=${*:1}; printf '%s\n' "$var"
+var="${*:1}"; printf '%s\n' "$var"
+
+unset var
+recho ${var-${*}}
+recho ${var-${*:1}}
+recho "${var-${*:1}}"
+recho ${var-"${*:1}"}
+
+unset var
+recho ${var=${*}}
+printf 'var=%s\n' "$var"
+unset var
+recho ${var=${*:1}}
+printf 'var=%s\n' "$var"
+
+a=${*:1}
+recho "$a"
+
+: ${b=${*:1}}
+recho "$b"
diff --git a/tests/dollar.right b/tests/dollar.right
index 1e48c24e..d72361f9 100644
--- a/tests/dollar.right
+++ b/tests/dollar.right
@@ -177,6 +177,8 @@ ab
a b
a b
<a><b><c><d>
+<a><b><c><d>
+<a><b><c d>
<a><b><c d>
<a><b>
<a:b>
@@ -478,3 +480,100 @@ argv[2] = <b>
argv[3] = <c>
argv[4] = <d>
argv[1] = <a b c d>
+<3>
+<abc>
+<def ghi>
+<jkl>
+<3>
+<abc>
+<def ghi>
+<jkl>
+<abc>
+<def ghi>
+<jkl>
+<abc>
+<def ghi>
+<jkl>
+<abcdef ghijkl>
+<abc>
+<def ghi>
+<jkl>
+<abc>
+<def ghi>
+<jkl>
+<abc:def ghi:jkl>
+<abc>
+<def>
+<ghi>
+<jkl>
+<abc>
+<def>
+<ghi>
+<jkl>
+argv[1] = <1>
+argv[2] = <>
+argv[1] = <2>
+argv[2] = <>
+argv[1] = <3>
+argv[2] = <>
+argv[1] = <4>
+argv[2] = <>
+-----
+argv[1] = <1>
+argv[2] = <>
+argv[1] = <2>
+argv[2] = <>
+argv[1] = <3>
+argv[1] = <4>
+argv[2] = <>
+------
+argv[1] = <1>
+argv[2] = <>
+argv[1] = <2>
+argv[2] = <>
+argv[1] = <3>
+argv[2] = <>
+argv[1] = <4>
+argv[2] = <>
+argv[1] = <5>
+argv[2] = <>
+argv[1] = <6>
+argv[2] = <>
+-----
+argv[1] = <1>
+argv[2] = <>
+argv[1] = <2>
+argv[2] = <>
+argv[1] = <3>
+argv[2] = <>
+argv[1] = <4>
+argv[2] = <>
+argv[1] = <5>
+argv[2] = <>
+argv[1] = <6>
+argv[2] = <>
+-----
+argv[1] = <1>
+argv[2] = <>
+argv[1] = <2>
+argv[2] = <>
+<12><12><12><12><12><12>
+<12><12><12><12><12><12>
+<12><'1''2'>
+1 2
+1 2
+1 2
+argv[1] = <1>
+argv[2] = <2>
+argv[1] = <1>
+argv[2] = <2>
+argv[1] = <1 2>
+argv[1] = <1 2>
+argv[1] = <1>
+argv[2] = <2>
+var=1 2
+argv[1] = <1>
+argv[2] = <2>
+var=1 2
+argv[1] = <1 2>
+argv[1] = <1 2>
diff --git a/tests/dstack2.tests b/tests/dstack2.tests
index d902bffb..3aa105b3 100644
--- a/tests/dstack2.tests
+++ b/tests/dstack2.tests
@@ -1,3 +1,4 @@
+wdir=$PWD
cd /
echo expect '~1'
@@ -31,3 +32,5 @@ dirs -v -1
echo these lines should be the same
dirs -0
echo ~-0 ${DIRSTACK[NDIRS]}
+
+cd "$wdir"
diff --git a/tests/dynvar.right b/tests/dynvar.right
new file mode 100644
index 00000000..e1344c60
--- /dev/null
+++ b/tests/dynvar.right
@@ -0,0 +1,7 @@
+BASHPID ok
+BASH_ARGV0 ok
+BASH_ARGV0 ok
+SECONDS ok
+EPOCHSECONDS ok
+EPOCHREALTIME ok
+echo $BASH_COMMAND
diff --git a/tests/dynvar.tests b/tests/dynvar.tests
new file mode 100644
index 00000000..a01f5ed2
--- /dev/null
+++ b/tests/dynvar.tests
@@ -0,0 +1,77 @@
+# specvar -- test some of the dynamic variables
+
+# BASHPID
+pid=$$
+bpid=$BASHPID
+subpid=$( (echo $BASHPID) )
+
+if [ "$bpid" -ne "$subpid" ]; then echo BASHPID ok; fi
+
+# BASH_ARGV0
+
+BASH_ARGV0=hello
+case $0 in
+hello) echo BASH_ARGV0 ok ;;
+*) echo "BASH_ARGV0 mismatch: $BASH_ARGV0 ($0)" >&2 ;;
+esac
+
+setarg0()
+{
+ BASH_ARGV0="$1"
+}
+
+setarg0 arg0
+case $0 in
+arg0) echo BASH_ARGV0 ok ;;
+*) echo "BASH_ARGV0 mismatch: $BASH_ARGV0 ($0)" >&2 ;;
+esac
+
+# SECONDS
+before=$SECONDS
+sleep 2
+after=$SECONDS
+
+if (( $after > $before )); then echo SECONDS ok; fi
+unset before after
+
+# EPOCHSECONDS
+
+# not exact, but should work
+
+now1=$(perl -e 'print time')
+now2=$EPOCHSECONDS
+
+case $now1 in
+$now2) echo EPOCHSECONDS ok ;;
+*) echo "current time via perl and EPOCHSECONDS possible mismatch|$now1|$now2" >&2 ;;
+esac
+unset now1 now2
+
+LC_ALL=C # force decimal point to `.'
+now1=$EPOCHREALTIME
+now2=$EPOCHREALTIME
+sec1=${now1%%.*}
+sec2=${now2%%.*}
+
+msec1=${now1##*.}
+msec2=${now2##*.}
+# cut off leading zeros
+shopt -s extglob
+msec1=${msec1##*(0)}
+msec2=${msec2##*(0)}
+
+dsec=$(( $sec2 - $sec1 ))
+dmsec=$(( $msec2 - $msec1 ))
+if (( $dmsec < 0 )); then
+ dmsec=$(( dmsec + 1000000 ))
+ dsec=$(( desc - 1 ))
+fi
+
+# not a real test, but ok for a start
+if (( $dmsec < 1000000 )); then echo EPOCHREALTIME ok; fi
+
+${THIS_SH} -c 'echo $BASH_COMMAND'
+
+# FUNCNAME tested in func.tests
+# RANDOM tested in varenv.sh
+# LINENO tested in dbg-support
diff --git a/tests/errors.right b/tests/errors.right
index 362855e3..4bf478b0 100644
--- a/tests/errors.right
+++ b/tests/errors.right
@@ -120,17 +120,61 @@ after readonly assignment
./errors4.sub: line 7: var: readonly variable
./errors5.sub: line 6: array: unbound variable
./errors5.sub: line 7: array: unbound variable
-./errors5.sub: line 10: 7: unbound variable
+./errors5.sub: line 8: array[7]: unbound variable
./errors5.sub: line 11: 7: unbound variable
+./errors5.sub: line 12: 7: unbound variable
after 1: 1
after 2: 1
after 3: 1
array after 1: 1
array after 2: 1
-./errors6.sub: line 18: ${-3}: bad substitution
-./errors6.sub: line 19: -3: bad substitution
+./errors6.sub: uvar: parameter not set
+./errors6.sub: uvar: parameter null or not set
+
+./errors6.sub: uvar: parameter null or not set
+./errors6.sub: line 25: ${-3:-${-3}}: bad substitution
+./errors6.sub: line 26: ${-3}: bad substitution
+./errors6.sub: line 27: -3: invalid variable name
after indir: 1
-./errors6.sub: line 18: ${-3}: bad substitution
-./errors6.sub: line 19: -3: bad substitution
+./errors6.sub: line 30: -3: invalid variable name
+
+unset
+./errors6.sub: line 37: var: invalid indirect expansion
+./errors6.sub: line 38: var: invalid indirect expansion
+./errors6.sub: line 41: invalid-ident: invalid variable name
+./errors6.sub: line 42: invalid-ident: invalid variable name
+./errors6.sub: line 43: invalid-ident: invalid variable name
+./errors6.sub: uvar: parameter not set
+./errors6.sub: uvar: parameter null or not set
+
+./errors6.sub: uvar: parameter null or not set
+./errors6.sub: line 25: ${-3:-${-3}}: bad substitution
+./errors6.sub: line 26: ${-3}: bad substitution
+./errors6.sub: line 27: -3: invalid variable name
after indir: 1
-./errors.tests: line 278: `!!': not a valid identifier
+./errors6.sub: line 30: -3: invalid variable name
+
+unset
+./errors6.sub: line 37: var: invalid indirect expansion
+./errors6.sub: line 38: var: invalid indirect expansion
+./errors6.sub: line 41: invalid-ident: invalid variable name
+./errors6.sub: line 42: invalid-ident: invalid variable name
+./errors6.sub: line 43: invalid-ident: invalid variable name
+./errors7.sub: line 8: x: readonly variable
+./errors7.sub: line 8: notthere: command not found
+after no such command: 127
+./errors7.sub: line 10: x: readonly variable
+echo builtin
+after non-special builtin: 0
+./errors7.sub: line 12: x: readonly variable
+after special builtin: 0
+./errors7.sub: line 14: x: readonly variable
+./errors7.sub: line 8: x: readonly variable
+./errors7.sub: line 8: notthere: command not found
+after no such command: 127
+./errors7.sub: line 10: x: readonly variable
+echo builtin
+after non-special builtin: 0
+./errors7.sub: line 12: x: readonly variable
+./errors7.sub: line 14: x: readonly variable
+./errors.tests: line 281: `!!': not a valid identifier
diff --git a/tests/errors.tests b/tests/errors.tests
index ff542f78..4183d024 100644
--- a/tests/errors.tests
+++ b/tests/errors.tests
@@ -270,6 +270,9 @@ ${THIS_SH} ./errors5.sub
${THIS_SH} ./errors6.sub
THIS_SH="${THIS_SH} -o posix" ${THIS_SH} ./errors6.sub
+${THIS_SH} ./errors7.sub
+${THIS_SH} -o posix ./errors7.sub
+
# this must be last!
# in posix mode, a function name must be a valid identifier
# this can't go in posix2.tests, since it causes the shell to exit
diff --git a/tests/errors5.sub b/tests/errors5.sub
index 7d9068b7..112b2a11 100644
--- a/tests/errors5.sub
+++ b/tests/errors5.sub
@@ -5,6 +5,7 @@ set -u
( echo ${#array} )
( echo ${array} )
+( echo ${array[7]} )
set -- 1 2 3
( echo ${#7} )
diff --git a/tests/errors6.sub b/tests/errors6.sub
index 3c05625a..b80580e7 100644
--- a/tests/errors6.sub
+++ b/tests/errors6.sub
@@ -15,6 +15,29 @@ echo array after 1: $?' 2>/dev/null
${THIS_SH} -c 'typeset -A v ; v["0"]=one ; echo ${v[ ]}
echo array after 2: $?' 2>/dev/null
+${THIS_SH} -c 'echo ${uvar?}' ./errors6.sub
+${THIS_SH} -c 'echo ${uvar:?}' ./errors6.sub
+export uvar=
+${THIS_SH} -c 'echo ${uvar?}' ./errors6.sub
+${THIS_SH} -c 'echo ${uvar:?}' ./errors6.sub
+unset uvar
+
+echo "${-3:-${-3}}"
echo ${-3}
x=-3; echo ${!x}
echo after indir: $?
+
+function ivar() { echo -n "${!1:-${1}}"; }
+ivar -3
+
+foo=bar
+echo ${!foo}
+echo ${!foo:-unset}
+
+echo ${!var:-unset}
+echo ${!var+unset}
+
+foo=invalid-ident
+echo ${!foo}
+echo ${!foo:-unset}
+echo ${!foo+unset}
diff --git a/tests/errors7.sub b/tests/errors7.sub
new file mode 100644
index 00000000..067867a1
--- /dev/null
+++ b/tests/errors7.sub
@@ -0,0 +1,15 @@
+: ${THIS_SH:=./bash}
+readonly x=4
+
+# in posix mode, these are all variable assignment errors, so strict conformance
+# implies that we exit after any of them. ksh93 doesn't do that. we more-or-less
+# emulate the ksh93 behavior
+
+x=8 notthere
+echo after no such command: $?
+x=8 echo echo builtin
+echo after non-special builtin: $?
+( x=8 : nosuchdir
+echo after special builtin: $? )
+( x=8 $nocmd
+echo after assignment error: $? )
diff --git a/tests/exec12.sub b/tests/exec12.sub
index 4bd6121b..bc627d2d 100644
--- a/tests/exec12.sub
+++ b/tests/exec12.sub
@@ -1,5 +1,6 @@
: ${TMPDIR:=/var/tmp}
TMPFILE=$TMPDIR/exitcode
+trap 'rm -f $TMPFILE' 0
rm -f $TMPFILE
set -e
diff --git a/tests/exec7.sub b/tests/exec7.sub
index ea2fd066..0267505c 100644
--- a/tests/exec7.sub
+++ b/tests/exec7.sub
@@ -18,3 +18,6 @@ chmod 755 testb/foo
PATH=$TMPDIR/testa:$TMPDIR/testb $THIS_SH -c foo
rm -rf testa testb
+
+cd $OLDPWD
+exit 0
diff --git a/tests/execscript b/tests/execscript
index 3415ae3c..c1819de7 100644
--- a/tests/execscript
+++ b/tests/execscript
@@ -59,10 +59,10 @@ echo $?
echo $?
# kill two birds with one test -- test out the BASH_ENV code
-echo echo this is bashenv > /tmp/bashenv
-export BASH_ENV=/tmp/bashenv
+echo echo this is bashenv > $TMPDIR/bashenv
+export BASH_ENV=$TMPDIR/bashenv
${THIS_SH} ./exec3.sub
-rm -f /tmp/bashenv
+rm -f $TMPDIR/bashenv
unset BASH_ENV
# we're resetting the $PATH to empty, so this should be last
@@ -108,7 +108,7 @@ ${THIS_SH} ./exec6.sub
# checks for properly deciding what constitutes an executable file
${THIS_SH} ./exec7.sub
-${THIS_SH} -i ./exec8.sub
+${THIS_SH} -i ${PWD}/exec8.sub
${THIS_SH} ./exec9.sub
diff --git a/tests/exp.right b/tests/exp.right
index 96617397..599482a7 100644
--- a/tests/exp.right
+++ b/tests/exp.right
@@ -210,11 +210,13 @@ argv[1] = <correct>
argv[2] = <a>
argv[1] = <correct>
argv[2] = <a>
+./exp7.sub: line 5: INFORM: dequote_string: string with bare CTLESC
argv[1] = <^A>
argv[1] = <3>
argv[2] = <^C>
argv[3] = <^C>
argv[4] = <^C>
+./exp7.sub: line 10: INFORM: dequote_string: string with bare CTLESC
argv[1] = <^A>
argv[1] = <x^Ay^?z>
argv[1] = <x^Ay^?z>
@@ -291,7 +293,9 @@ var=abc:def ghi:jkl
abcdef ghijkl
abcdef ghijkl
abcdef ghijkl
-abcdef ghijkl
+abc
+def ghi
+jkl
abcdef ghijkl
abcdef ghijkl
abcdef ghijkl
@@ -332,3 +336,68 @@ jkl
[]
[foo]
[]
+< A >< B >< A >< B >
+< A >< B >< A >< B >
+< A >< B >< a >< b >
+< A >< B >< A >< B >
+< A >< B ><' A '><' B '>
+-----
+< A >< B >< A >< B >
+< A >< B >< A >< B >
+< A >< B >< a >< b >
+< A >< B >< A >< B >
+< A >< B ><' A '><' B '>
+argv[1] = <1>
+argv[2] = <2>
+argv[1] = <1>
+argv[2] = <2>
+argv[1] = <1>
+argv[2] = <2>
+argv[1] = <1 2>
+argv[1] = <a b>
+argv[1] = <a>
+argv[2] = <b>
+argv[1] = <a b>
+argv[1] = <1>
+argv[2] = <2>
+argv[1] = <1>
+argv[2] = <2>
+argv[1] = <1>
+argv[2] = <2>
+argv[1] = <12>
+argv[1] = <12>
+argv[1] = <1>
+argv[2] = <2>
+argv[1] = <1>
+argv[2] = <2>
+argv[1] = < >
+argv[1] = < >
+argv[1] = < >
+argv[1] = < >
+argv[1] = < >
+argv[1] = <12>
+argv[1] = <12>
+argv[1] = <12>
+argv[1] = <12>
+ok 1
+ok 2
+ok 3
+ok 4
+ok 5
+ok 6
+ok 7
+ok 8
+ok 9
+argv[1] = <file.o>
+argv[1] = <posix>
+argv[1] = </src/cmd>
+argv[1] = <three>
+argv[1] = </one/two/three>
+abcdefg
+abcdefg
+abcdefg
+abcdefg
+cdefg
+abcdefg
+abcde
+abcdefg
diff --git a/tests/exp.tests b/tests/exp.tests
index b446d637..6e364f9c 100644
--- a/tests/exp.tests
+++ b/tests/exp.tests
@@ -405,3 +405,6 @@ ${THIS_SH} ./exp6.sub
${THIS_SH} ./exp7.sub
${THIS_SH} ./exp8.sub
${THIS_SH} ./exp9.sub
+${THIS_SH} ./exp10.sub
+${THIS_SH} ./exp11.sub
+${THIS_SH} ./exp12.sub
diff --git a/tests/exp10.sub b/tests/exp10.sub
new file mode 100644
index 00000000..6592bab9
--- /dev/null
+++ b/tests/exp10.sub
@@ -0,0 +1,26 @@
+set -- ' A ' ' B '
+IFS=
+
+printf '<%s>' ${*} ${*##}
+echo
+printf '<%s>' ${*} ${*/}
+echo
+printf '<%s>' ${*} ${*,,}
+echo
+printf '<%s>' ${*} ${*:1:2}
+echo
+printf '<%s>' ${*} ${*@Q}
+echo
+
+echo -----
+
+printf '<%s>' ${@} ${@##}
+echo
+printf '<%s>' ${@} ${@/}
+echo
+printf '<%s>' ${@} ${@,,}
+echo
+printf '<%s>' ${@} ${@:1:2}
+echo
+printf '<%s>' ${@} ${@@Q}
+echo
diff --git a/tests/exp11.sub b/tests/exp11.sub
new file mode 100644
index 00000000..cae7b19c
--- /dev/null
+++ b/tests/exp11.sub
@@ -0,0 +1,92 @@
+set -- '1 2'
+
+unset var
+recho ${var-${*:1}}
+
+unset var
+recho ${var=$*}
+
+unset var
+recho ${var=${*:1}}
+recho "$var"
+
+# posix interp 221
+unset var
+recho ${var:-a\ b}
+
+recho ${var:=a\ b}
+recho "$var"
+
+set -- 1 2
+IFS=
+
+unset a b c
+recho $*
+recho ${a-$*}
+recho ${b-${*/}}
+recho ${c=${*/}}
+recho "$c"
+recho ${b-${*,,}}
+recho ${d-${*,,}}
+
+unset -v a b c
+IFS=$' \t\n'
+
+set -- ' '
+A=(' ')
+
+IFS=
+unset var
+var=${*@E}
+recho "$var"
+
+unset var
+var=${A[*]@E}
+recho "$var"
+
+unset var
+var=${@@E}
+recho "$var"
+
+unset var
+var=${A[@]@E}
+recho "$var"
+
+unset novar
+recho ${novar-${A[*]@E}}
+
+unset -v var novar
+IFS=$' \t\n'
+
+set -- 1 2
+A=( 1 2 )
+IFS=
+
+a=$*
+recho "$a"
+b=${*@E}
+recho "$b"
+
+unset a b
+a=${A[*]}
+recho "$a"
+b=${A[*]@E}
+recho "$b"
+
+set -- $'\t'
+A=$1
+
+IFS=$1
+[[ ${A[@]} ]] && echo ok 1
+[[ ${A[*]} ]] && echo ok 2
+[[ ${A[0]} ]] && echo ok 3
+
+IFS=$' \t\n'
+[[ ${A[@]} ]] && echo ok 4
+[[ ${A[*]} ]] && echo ok 5
+[[ ${A[0]} ]] && echo ok 6
+
+IFS=
+[[ ${A[@]} ]] && echo ok 7
+[[ ${A[*]} ]] && echo ok 8
+[[ ${A[0]} ]] && echo ok 9
diff --git a/tests/exp12.sub b/tests/exp12.sub
new file mode 100644
index 00000000..0aaa2f44
--- /dev/null
+++ b/tests/exp12.sub
@@ -0,0 +1,38 @@
+# force single-byte versions of these functions
+
+export LANG=C
+
+# remove shortest trailing match
+x=file.c
+recho ${x%.c}.o
+
+# remove longest trailing match
+x=posix/src/std
+recho ${x%%/*}
+
+# remove shortest leading pattern
+x=$HOME/src/cmd
+recho ${x#$HOME}
+
+# remove longest leading pattern
+x=/one/two/three
+recho ${x##*/}
+
+# and no match thrown in for good measure
+recho ${x#nomatch}
+
+foo=abcdefg
+
+# fail
+echo ${foo%ab}
+echo ${foo%def}
+
+echo ${foo#fg}
+echo ${foo#def}
+
+# succeed
+echo ${foo#ab}
+echo ${foo#def}
+
+echo ${foo%fg}
+echo ${foo%def}
diff --git a/tests/exp5.sub b/tests/exp5.sub
index 9346b579..52dd4a15 100644
--- a/tests/exp5.sub
+++ b/tests/exp5.sub
@@ -1,15 +1,14 @@
# expansions involving patterns
-
var='[hello'
echo "${var//[/}"
red='\[\e[0;31m\]'
-echo "${red//\\[\\e/}"
+printf "%s\n" "${red//\\[\\e/}"
foo="${red//\\[\\e/}"
# foo == [0;31m\]
-echo "${foo//[0;31m\\/}"
+printf "%s\n" "${foo//[0;31m\\/}"
echo "${var//[]/}"
echo "${red//[]/}"
diff --git a/tests/exp8.sub b/tests/exp8.sub
index 99340838..ff44febc 100644
--- a/tests/exp8.sub
+++ b/tests/exp8.sub
@@ -10,11 +10,11 @@ declare -p var | sed -n l
recho ${var@Q}
recho ${var@P}
-echo ${var@A}
+echo -E ${var@A}
unset array
array=( [$'x\001y\177z']=foo ) # should be error
-echo ${array[@]@A}
+echo -E ${array[@]@A}
unset array
declare -a array=([0]=$'x\001y\177z')
@@ -23,9 +23,9 @@ declare -p array
unset array
array=( "$var" )
recho ${array[@]}
-echo ${array[@]@A}
+echo -E ${array[@]@A}
unset array
declare -A array
array=( [$'x\001y\177z']=$'a\242b\002c' )
-echo ${array[@]@A}
+echo -E ${array[@]@A}
diff --git a/tests/extglob.right b/tests/extglob.right
index efb7e5fb..691f6879 100644
--- a/tests/extglob.right
+++ b/tests/extglob.right
@@ -94,14 +94,23 @@ a ab
a
. ..
. .. a.log
+*(foo)
+*(foo|bar)
a.log
?(foo)
a.log
a.log
. ..
+. ..
+a.log
a.log
.x .y .z
a b c
.x .y .z a b c
a b c
a b c
+a b c
+a b c
+.x .y .z a b c
+.x .y .z a b c
+*
diff --git a/tests/extglob.tests b/tests/extglob.tests
index a51c4db1..32a6569f 100644
--- a/tests/extglob.tests
+++ b/tests/extglob.tests
@@ -374,4 +374,6 @@ ${THIS_SH} ./extglob3.sub
${THIS_SH} ./extglob4.sub
+${THIS_SH} ./extglob5.sub
+
exit 0
diff --git a/tests/extglob1a.sub b/tests/extglob1a.sub
index e029ea49..686dab74 100644
--- a/tests/extglob1a.sub
+++ b/tests/extglob1a.sub
@@ -12,5 +12,5 @@ echo a!(x)
echo a*?(x)
echo a?(x)
-builtin cd /
+builtin cd $OLDPWD
rm -rf $TESTDIR
diff --git a/tests/extglob3.sub b/tests/extglob3.sub
index 94567ee9..3f51c40c 100644
--- a/tests/extglob3.sub
+++ b/tests/extglob3.sub
@@ -1,5 +1,5 @@
shopt -s extglob
-DIR=/tmp/extglob-$$
+DIR=$TMPDIR/extglob-$$
mkdir $DIR
cd $DIR
@@ -7,15 +7,18 @@ touch a.log
echo *(.)
echo *(.)*
+echo *(foo)
+echo *(foo|bar)
echo ?(foo)*
echo ?(foo)
echo *(foo)*
echo @(|foo)*
echo *(foo).*
+echo *(foo|bar).*
echo !(foo)*
+echo !(foo|bar)*
cd $OLDPWD
rm -rf $DIR
-
diff --git a/tests/extglob4.sub b/tests/extglob4.sub
index 2ec8f319..2b4c53c9 100644
--- a/tests/extglob4.sub
+++ b/tests/extglob4.sub
@@ -19,7 +19,14 @@ echo @(*|.!(|.)) # wrong, adds . and ..
echo @(*|@(f)) # ??
echo @(*|@(ff))
-cd /
+echo !(f)
+echo !(f)!(f)
+
+shopt -s dotglob
+echo @(*|@(f))
+echo @(*|@(ff))
+
+cd $OLDPWD
rm -rf $GTDIR
[[ a = a*?(/)b ]] && echo bad match 1
diff --git a/tests/extglob5.sub b/tests/extglob5.sub
new file mode 100644
index 00000000..d400f839
--- /dev/null
+++ b/tests/extglob5.sub
@@ -0,0 +1,18 @@
+# globignore extglob patterns containing colons -- problem until bash-4.2
+
+: ${TMPDIR:=/tmp}
+TESTDIR=$TMPDIR/bash-globignore-$$
+[ -d "$TESTDIR" ] || mkdir "$TESTDIR"
+
+cd "$TESTDIR" || exit 2
+
+shopt -s extglob
+GLOBIGNORE='+([^[:alnum:]]):@([-.,:; _]):[![:alnum:]]'
+
+touch ';' '++'
+echo *
+
+rm ';' '++'
+
+cd $OLDPWD
+rmdir $TESTDIR
diff --git a/tests/getopts5.sub b/tests/getopts5.sub
index 30614ef9..874b2810 100644
--- a/tests/getopts5.sub
+++ b/tests/getopts5.sub
@@ -2,7 +2,7 @@
getop () {
- local OPTIND
+ local OPTIND=1
local OPTERR=1
echo getop: OPTERR=$OPTERR
diff --git a/tests/glob.right b/tests/glob.right
index 04a0fd5f..83b7bc7a 100644
--- a/tests/glob.right
+++ b/tests/glob.right
@@ -1,4 +1,61 @@
foo/bar foobar/bar
+ok 1
+ok 2
+ok 3
+ok 4
+ok 5
+b
+argv[1] = <A£\B>
+argv[1] = <A>
+argv[1] = <B>
+argv[1] = <a£\b>
+0000000 141 243 134 142
+0000004
+ok 6
+ok 7
+invalid bracket expression
+== LANG=C ==
+[[:alpha:]
+ok 1
+[a
+[[:alpha:]
+ok 2
+ok 3
+== LANG=en_US.UTF-8 ==
+[[:alpha:]
+ok 1
+[a
+[[:alpha:]
+ok 2
+ok 3
+invalid character class
+== LANG=C ==
+ok 1
+ok 2
+ok 3
+ok 4
+ok 5
+ok 6
+== LANG=en_US.UTF-8 ==
+ok 1
+ok 2
+ok 3
+ok 4
+ok 5
+ok 6
+invalid collating symbols
+== LANG=C ==
+ok 1
+ok 2
+ok 3
+ok 4
+ok 5
+== LANG=en_US.UTF-8 ==
+ok 1
+ok 2
+ok 3
+ok 4
+ok 5
argv[1] = <a>
argv[2] = <abc>
argv[3] = <abd>
@@ -13,7 +70,7 @@ argv[2] = <abc>
argv[3] = <abd>
argv[4] = <abe>
tmp/l1 tmp/l2 tmp/*4 tmp/l3
-./glob.tests: line 44: no match: tmp/*4
+./glob.tests: line 46: no match: tmp/*4
argv[1] = <bdir/>
argv[1] = <*>
argv[1] = <a*>
diff --git a/tests/glob.tests b/tests/glob.tests
index d32988bc..7ae51723 100644
--- a/tests/glob.tests
+++ b/tests/glob.tests
@@ -9,10 +9,12 @@ expect()
# First, a test that bash-2.01.1 fails
${THIS_SH} ./glob1.sub
+${THIS_SH} ./glob2.sub
+${THIS_SH} ./glob3.sub
MYDIR=$PWD # save where we are
-TESTDIR=/tmp/glob-test
+TESTDIR=$TMPDIR/glob-test-$$
mkdir $TESTDIR
builtin cd $TESTDIR || { echo $0: cannot cd to $TESTDIR >&2 ; exit 1; }
rm -rf *
diff --git a/tests/glob1.sub b/tests/glob1.sub
index 8745cd99..6b3b8ad1 100644
--- a/tests/glob1.sub
+++ b/tests/glob1.sub
@@ -1,7 +1,10 @@
# bash-2.01.1 failed this test
-FN=/tmp/bash-glob.$$
+: ${TMPDIR:=/var/tmp}
+
+FN=$TMPDIR/bash-glob.$$
mkdir $FN
cd $FN
+
mkdir foo
mkdir foobar
touch foo/bar
@@ -10,5 +13,5 @@ chmod 311 foo foobar
echo f*/bar
chmod 777 foo foobar
-cd /
+cd $OLDPWD
rm -rf $FN
diff --git a/tests/glob2.sub b/tests/glob2.sub
new file mode 100644
index 00000000..d33013b6
--- /dev/null
+++ b/tests/glob2.sub
@@ -0,0 +1,44 @@
+. ./test-glue-functions
+
+var='ab\'
+
+case $var in
+ab\\) echo ok 1;;
+*) echo bad 1;;
+esac
+
+case $var in
+$var) echo ok 2;;
+*) echo bad 2;;
+esac
+
+case $var in
+'ab\') echo ok 3;;
+*) echo bad 3;;
+esac
+
+[[ $var = $var ]] && echo ok 4
+[[ $var = $'ab\134' ]] && echo ok 5
+
+LC_ALL=zh_HK.big5hkscs
+
+read a b c <<< $'\u3b1 b c\n'
+echo $b
+unset a b c
+
+export alpha=$'\u3b1'
+
+printf -v v 'A%sB' "$alpha"
+recho "$v"
+IFS=$alpha read a b c <<<"$v"
+recho "$a"
+recho "$b"
+unset a b v
+
+recho "a${alpha}b"
+printf "%s" "a${alpha}b" | LC_ALL=C od -b | _intl_normalize_spaces
+
+a=$'\u3b1'
+[[ $a = $a ]] && echo ok 6
+
+LC_ALL=zh_HK.big5hkscs ${THIS_SH} -c $'[[ \u3b1 = \u3b1 ]]' && echo ok 7
diff --git a/tests/glob3.sub b/tests/glob3.sub
new file mode 100644
index 00000000..378234db
--- /dev/null
+++ b/tests/glob3.sub
@@ -0,0 +1,123 @@
+: ${TMPDIR:=/var/tmp}
+cd $TMPDIR
+
+matchfunc()
+{
+ echo == LANG=$LANG ==
+
+ touch a p
+ echo [[:alpha:]
+ rm a p
+
+ case l in
+ [[:alpha:]) echo bad 1;;
+ *) echo ok 1;;
+ esac
+
+ touch '[a' '[x'
+ echo [[:alpha:]
+ rm '[a'
+ echo [[:alpha:]
+ rm '[x'
+
+ case [a in
+ [[:alpha:]) echo ok 2;;
+ *) echo bad 2;;
+ esac
+
+ case [x in
+ [[:alpha:]) echo bad 3;;
+ *) echo ok 3;;
+ esac
+}
+
+echo invalid bracket expression
+export LANG=C
+matchfunc
+
+export LANG=en_US.UTF-8
+matchfunc
+
+unset -f matchfunc
+
+matchfunc()
+{
+ echo == LANG=$LANG ==
+
+ case a] in
+ [[:aleph:]]) echo bad 1;;
+ *) echo ok 1;;
+ esac
+
+ case a in
+ [[:aleph:]]) echo bad 2;;
+ *) echo ok 2;;
+ esac
+
+ case a] in
+ [[:"alpha":]]) echo bad 3;;
+ *) echo ok 3;;
+ esac
+
+ case a in
+ [[:"alpha":]]) echo bad 4;;
+ *) echo ok 4;;
+ esac
+
+ case a in
+ [abc[:foo:]]) echo ok 5;;
+ *) echo bad 5 ;;
+ esac
+
+ case a in
+ [[:foo:]abc]) echo ok 6;;
+ *) echo bad 6 ;;
+ esac
+}
+
+echo invalid character class
+export LANG=C
+matchfunc
+
+export LANG=en_US.UTF-8
+matchfunc
+
+unset -f matchfunc
+
+matchfunc()
+{
+ echo == LANG=$LANG ==
+
+ case h in
+ [[.hyphen.]) echo bad 1;;
+ *) echo ok 1;;
+ esac
+
+ case - in
+ [[.hyphen.]]) echo ok 2;;
+ *) echo bad 2;;
+ esac
+
+ case slash in
+ [[.slash.]]) echo bad 3;;
+ *) echo ok 3;;
+ esac
+
+ case a in
+ [abc[.nonsense.]]) echo ok 4;;
+ *) echo bad 4 ;;
+ esac
+
+ case a in
+ [[.nonsense.]abc]) echo ok 5;;
+ *) echo bad 5 ;;
+ esac
+}
+
+echo invalid collating symbols
+
+export LANG=C
+matchfunc
+
+export LANG=en_US.UTF-8
+matchfunc
diff --git a/tests/globstar2.sub b/tests/globstar2.sub
index f4bb1b1c..4e1a0245 100644
--- a/tests/globstar2.sub
+++ b/tests/globstar2.sub
@@ -1,5 +1,6 @@
olddir=$PWD
-EMPTY=/tmp/empty
+: ${TMPDIR:=/var/tmp}
+EMPTY=$TMPDIR/empty
shopt -s globstar
s()
diff --git a/tests/heredoc.right b/tests/heredoc.right
index 137a2956..f6541dca 100644
--- a/tests/heredoc.right
+++ b/tests/heredoc.right
@@ -20,7 +20,7 @@ jkl mno
fff is a function
fff ()
{
- ed /tmp/foo > /dev/null <<ENDOFINPUT
+ ed ${TMPDIR}/foo <<ENDOFINPUT > /dev/null
/^name/d
w
q
@@ -31,7 +31,7 @@ ENDOFINPUT
fff is a function
fff ()
{
- ed /tmp/foo > /dev/null <<ENDOFINPUT
+ ed ${TMPDIR}/foo <<ENDOFINPUT > /dev/null
/^name/d
w
q
@@ -43,11 +43,11 @@ foo is a function
foo ()
{
echo;
- cat <<END
+ cat <<END
bar
END
- cat <<EOF
+ cat <<EOF
qux
EOF
@@ -59,13 +59,13 @@ qux
bar
qux
abc def geh
-./heredoc3.sub: line 9: warning: here-document at line 7 delimited by end-of-file (wanted `EOF')
+./heredoc3.sub: line 10: warning: here-document at line 8 delimited by end-of-file (wanted `EOF')
= here is the text =
-./heredoc3.sub: line 15: warning: here-document at line 13 delimited by end-of-file (wanted `EOF')
+./heredoc3.sub: line 16: warning: here-document at line 14 delimited by end-of-file (wanted `EOF')
this paren ) is not a problem
-./heredoc3.sub: line 21: warning: here-document at line 19 delimited by end-of-file (wanted `EOF')
+./heredoc3.sub: line 22: warning: here-document at line 20 delimited by end-of-file (wanted `EOF')
these balanced parens ( ) are not a problem
-./heredoc3.sub: line 27: warning: here-document at line 25 delimited by end-of-file (wanted `EOF')
+./heredoc3.sub: line 28: warning: here-document at line 26 delimited by end-of-file (wanted `EOF')
quoted balanced parens \( ) are not a problem either
more text in a subshell
some more text in a different subshell
@@ -82,8 +82,16 @@ end helloEND
hello
\END
end hello<NL>\END
-./heredoc3.sub: line 78: warning: here-document at line 76 delimited by end-of-file (wanted `EOF')
-./heredoc3.sub: line 79: syntax error: unexpected end of file
+./heredoc3.sub: line 85: warning: here-document at line 83 delimited by end-of-file (wanted `EOF')
+./heredoc3.sub: line 86: syntax error: unexpected end of file
+heredoc1
+EOF
+Ok:0
+argv[1] = <onetwo>
+argv[2] = <threefour>
+argv[1] = <two>
+argv[2] = <threefi>
+argv[3] = <ve>
comsub here-string
./heredoc.tests: line 105: warning: here-document at line 103 delimited by end-of-file (wanted `EOF')
hi
diff --git a/tests/heredoc.tests b/tests/heredoc.tests
index ebc770ac..303949f4 100644
--- a/tests/heredoc.tests
+++ b/tests/heredoc.tests
@@ -59,22 +59,22 @@ cat <<- EOF
EOF
# check appending of text to file from here document
-rm -f /tmp/bash-zzz
-cat > /tmp/bash-zzz << EOF
+rm -f ${TMPDIR}/bash-zzz
+cat > ${TMPDIR}/bash-zzz << EOF
abc
EOF
-cat >> /tmp/bash-zzz << EOF
+cat >> ${TMPDIR}/bash-zzz << EOF
def ghi
jkl mno
EOF
-cat /tmp/bash-zzz
-rm -f /tmp/bash-zzz
+cat ${TMPDIR}/bash-zzz
+rm -f ${TMPDIR}/bash-zzz
# make sure command printing puts the here-document as the last redirection
# on the line, and the function export code preserves syntactic correctness
fff()
{
- ed /tmp/foo <<ENDOFINPUT >/dev/null
+ ed ${TMPDIR}/foo <<ENDOFINPUT >/dev/null
/^name/d
w
q
@@ -90,8 +90,8 @@ ${THIS_SH} ./heredoc1.sub
# test heredocs in command substitutions
${THIS_SH} ./heredoc2.sub
-
${THIS_SH} ./heredoc3.sub
+${THIS_SH} ./heredoc4.sub
echo $(
cat <<< "comsub here-string"
diff --git a/tests/heredoc3.sub b/tests/heredoc3.sub
index baf91c14..a5a2fbc0 100644
--- a/tests/heredoc3.sub
+++ b/tests/heredoc3.sub
@@ -1,4 +1,5 @@
SAVEPWD=$PWD
+: ${TMPDIR:=/tmp}
cd $TMPDIR || echo "heredoc3.sub: cannot cd to $TMPDIR" >&2
text=$(cat <<EOF
@@ -69,7 +70,13 @@ cat <<END
hello
\END
END
-echo end 'hello<NL>\END'
+echo -E end 'hello<NL>\END'
+
+# gprof
+if [ -n "$GMON_OUT_PREFIX" ]; then
+ mv ${GMON_OUT_PREFIX}.[0-9]* "$SAVEPWD" >/dev/null 2>&1
+fi
+cd "$SAVEPWD"
# this has to be last -- results in a syntax error
# doesn't currently parse because EOF is not on a line by itself -- should it?
diff --git a/tests/heredoc4.sub b/tests/heredoc4.sub
new file mode 100644
index 00000000..381b64a9
--- /dev/null
+++ b/tests/heredoc4.sub
@@ -0,0 +1,12 @@
+cat <<EO`true`F
+heredoc1
+EO`false`F
+EO`true`F
+echo Ok:$?
+
+one=one
+four=four
+five='fi ve'
+
+recho $one`echo two three`$four
+recho `echo two three`$five
diff --git a/tests/histexp.right b/tests/histexp.right
index ed6e0894..bcf5dea6 100644
--- a/tests/histexp.right
+++ b/tests/histexp.right
@@ -8,7 +8,7 @@ echo $BASH_VERSION
2 /bin/sh -c 'echo this is $0'
3 ls
4 echo $BASH_VERSION
- 5 HISTFILE=/tmp/newhistory
+ 5 HISTFILE=$TMPDIR/newhistory
6 echo line 2 for history
echo line 2 for history
echo line 2 for history
@@ -19,7 +19,7 @@ line 2 for history
2 /bin/sh -c 'echo this is $0'
3 ls
4 echo $BASH_VERSION
- 5 HISTFILE=/tmp/newhistory
+ 5 HISTFILE=$TMPDIR/newhistory
6 echo line 2 for history
7 set -H
8 echo line 2 for history
@@ -181,6 +181,15 @@ echo g
g
eval echo "echo g"
echo g
+h
+echo \!\! `echo echo h`
+!! echo h
+i
+echo echo i `echo echo i`
+echo i echo i
+j
+echo `echo j` echo j
+j echo j
a
cat < <(echo echo a)
echo a
diff --git a/tests/histexp.tests b/tests/histexp.tests
index 99c7520d..2901064f 100644
--- a/tests/histexp.tests
+++ b/tests/histexp.tests
@@ -1,6 +1,6 @@
LC_ALL=C
LANG=C
-trap 'rm /tmp/newhistory' 0
+trap 'rm $TMPDIR/newhistory' 0
file=bax
histchars='!^#' # make sure history comment char is set correctly
@@ -25,7 +25,7 @@ history -p '!!:z'
history
-HISTFILE=/tmp/newhistory
+HISTFILE=$TMPDIR/newhistory
history -a
history -w
diff --git a/tests/histexp3.sub b/tests/histexp3.sub
index ae2b4986..495f0952 100644
--- a/tests/histexp3.sub
+++ b/tests/histexp3.sub
@@ -31,5 +31,14 @@ echo "!!"
echo g
eval echo "!!"
+echo h
+echo \!\! `echo !!`
+
+echo i
+echo !! `echo !!`
+
+echo j
+echo `echo j` !!
+
set +o history
rm -f $HISTFILE # just in case
diff --git a/tests/history.right b/tests/history.right
index de8e22b4..d83fc718 100644
--- a/tests/history.right
+++ b/tests/history.right
@@ -36,13 +36,13 @@ echo line for history
echo line for history
displaying $HISTFILE after history -a
echo line for history
-HISTFILE=/tmp/newhistory
+HISTFILE=$TMPDIR/newhistory
1 for i in one two three; do echo $i; done
2 /bin/sh -c 'echo this is $0'
3 ls
4 echo $BASH_VERSION
5 echo line for history
- 6 HISTFILE=/tmp/newhistory
+ 6 HISTFILE=$TMPDIR/newhistory
7 echo displaying \$HISTFILE after history -a
8 cat $HISTFILE
for i in one two three; do echo $i; done
@@ -50,7 +50,7 @@ for i in one two three; do echo $i; done
ls
echo $BASH_VERSION
echo line for history
-HISTFILE=/tmp/newhistory
+HISTFILE=$TMPDIR/newhistory
echo displaying \$HISTFILE after history -a
cat $HISTFILE
1 for i in one two three; do echo $i; done
@@ -58,7 +58,7 @@ cat $HISTFILE
3 ls
4 echo $BASH_VERSION
5 echo line for history
- 6 HISTFILE=/tmp/newhistory
+ 6 HISTFILE=$TMPDIR/newhistory
7 echo displaying \$HISTFILE after history -a
8 cat $HISTFILE
9 echo line 2 for history
@@ -69,7 +69,7 @@ echo line 2 for history
3 ls
4 echo $BASH_VERSION
5 echo line for history
- 6 HISTFILE=/tmp/newhistory
+ 6 HISTFILE=$TMPDIR/newhistory
7 echo displaying \$HISTFILE after history -a
8 cat $HISTFILE
9 echo line 2 for history
@@ -80,7 +80,7 @@ echo line 2 for history
line 2 for history
4 echo $BASH_VERSION
5 echo line for history
-6 HISTFILE=/tmp/newhistory
+6 HISTFILE=$TMPDIR/newhistory
7 echo displaying \$HISTFILE after history -a
8 cat $HISTFILE
9 echo line 2 for history
@@ -94,10 +94,10 @@ line 2 for history
17 unset HISTFILE
4 echo $BASH_VERSION
5 echo line for history
-6 HISTFILE=/tmp/newhistory
+6 HISTFILE=$TMPDIR/newhistory
7 echo displaying \$HISTFILE after history -a
8 cat $HISTFILE
-./history.tests: line 75: fc: history specification out of range
+./history.tests: line 76: fc: history specification out of range
14 set -H
15 echo line 2 for history
16 unset HISTSIZE
@@ -107,7 +107,7 @@ echo xx xb xc
xx xb xc
echo 44 48 4c
44 48 4c
-./history.tests: line 90: fc: no command found
+./history.tests: line 91: fc: no command found
aa
bb
cc
@@ -140,7 +140,41 @@ three
one
two
three
-4.4
+5.0
echo ${BASH_VERSION%\.*}
-4.4
+5.0
echo ${BASH_VERSION%\.*}
+a
+b
+c
+d
+e
+ 1 echo a
+ 2 echo b
+ 3 echo c
+ 4 echo d
+ 5 echo e
+
+ 1 echo a
+ 2 echo e
+f
+g
+h
+i
+ 1 echo a
+ 2 echo e
+ 3 echo f
+ 4 echo g
+ 5 echo h
+
+./history3.sub: line 27: history: 16: history position out of range
+./history3.sub: line 28: history: 200: history position out of range
+./history3.sub: line 29: history: -20: history position out of range
+./history3.sub: line 30: history: -50: history position out of range
+./history3.sub: line 31: history: 5-0xaf: history position out of range
+ 1 echo a
+ 2 echo e
+ 3 echo f
+ 4 echo g
+ 5 echo h
+
diff --git a/tests/history.tests b/tests/history.tests
index f976fbdf..4001bd6c 100644
--- a/tests/history.tests
+++ b/tests/history.tests
@@ -1,4 +1,4 @@
-trap 'rm /tmp/newhistory' 0
+trap 'rm $TMPDIR/newhistory' 0
# bad options
history -x
@@ -20,6 +20,7 @@ HISTFILE=history.list
HISTCONTROL=ignoreboth
HISTIGNORE='&:history*:fc*'
HISTSIZE=32
+export HISTIGNORE
shopt -s cmdhist
set -o history
@@ -39,7 +40,7 @@ history -p '!!'
fc -nl
-HISTFILE=/tmp/newhistory
+HISTFILE=$TMPDIR/newhistory
history -a
echo displaying \$HISTFILE after history -a
cat $HISTFILE
@@ -112,3 +113,4 @@ ${THIS_SH} ./history1.sub
rm -f $TMPDIR/foohist-*
${THIS_SH} ./history2.sub
+${THIS_SH} ./history3.sub
diff --git a/tests/history3.sub b/tests/history3.sub
new file mode 100644
index 00000000..8722666c
--- /dev/null
+++ b/tests/history3.sub
@@ -0,0 +1,36 @@
+: ${TMPDIR:=/tmp}
+
+set -o history
+HISTFILE=$TMPDIR/history-$$
+
+history -c
+
+echo a
+echo b
+echo c
+echo d
+echo e
+
+history ; echo
+
+history -d 2-4
+
+history
+
+echo f
+echo g
+echo h
+echo i
+history -d 6--1
+history ; echo
+
+history -d 16-40
+history -d 1-200
+history -d -20-50
+history -d 1--50
+history -d 5-0xaf
+
+history ; echo
+
+unset HISTFILE
+exit 0
diff --git a/tests/ifs.right b/tests/ifs.right
index 512f6ee5..465efcf0 100644
--- a/tests/ifs.right
+++ b/tests/ifs.right
@@ -8,3 +8,5 @@ a:b:c:d:e
a:b:c:d:e
a b c d e
a b c d e
+argv[1] = <file>
+argv[1] = <*>
diff --git a/tests/ifs.tests b/tests/ifs.tests
index 763e2a00..71769005 100644
--- a/tests/ifs.tests
+++ b/tests/ifs.tests
@@ -59,3 +59,5 @@ IFS=: export x
echo $x
IFS="$DEFIFS"
+
+${THIS_SH} ./ifs1.sub
diff --git a/tests/ifs1.sub b/tests/ifs1.sub
new file mode 100644
index 00000000..6ea489af
--- /dev/null
+++ b/tests/ifs1.sub
@@ -0,0 +1,14 @@
+: ${TMPDIR:=/tmp}
+dir=bashtest-$$
+
+mkdir $TMPDIR/$dir || exit 1
+touch $TMPDIR/$dir/file || exit 2
+cd $TMPDIR/$dir || exit 3
+
+IFS='?*[]'
+recho *
+
+recho "*"
+
+cd $OLDPWD
+rm -rf $TMPDIR/$dir
diff --git a/tests/jobs.right b/tests/jobs.right
index c3ee9443..0e9d1d19 100644
--- a/tests/jobs.right
+++ b/tests/jobs.right
@@ -16,31 +16,32 @@ Waiting for job 6
job 6 returns 0
Waiting for job 7
job 7 returns 0
-[1] Running sleep 5 &
-[2] Running sleep 5 &
-[3] Running sleep 5 &
-[4]- Running sleep 5 &
-[5]+ Running ( sleep 5; exit 4 ) &
+[1] Running sleep 2 &
+[2] Running sleep 2 &
+[3] Running sleep 2 &
+[4]- Running sleep 2 &
+[5]+ Running ( sleep 2; exit 4 ) &
4
0
i killed it
12
[1]- Running sleep 20 &
[3]+ Running sleep 20 &
+child1 exit status 0
0
-./jobs.tests: line 22: wait: %1: no such job
-./jobs.tests: line 27: fg: no job control
+./jobs.tests: line 25: wait: %1: no such job
+./jobs.tests: line 30: fg: no job control
wait-for-pid
wait-errors
-./jobs.tests: line 40: wait: `1-1': not a pid or valid job spec
-./jobs.tests: line 41: wait: `-4': not a pid or valid job spec
+./jobs.tests: line 43: wait: `1-1': not a pid or valid job spec
+./jobs.tests: line 44: wait: `-4': not a pid or valid job spec
wait-for-background-pids
async list wait-for-background-pids
async list wait for child
forked
wait-when-no-children
wait-for-job
-./jobs.tests: line 63: wait: %2: no such job
+./jobs.tests: line 66: wait: %2: no such job
127
async list wait-for-job
forked
@@ -53,19 +54,19 @@ sleep 5
fg-bg 4
sleep 5
fg-bg 5
-./jobs.tests: line 90: fg: %2: no such job
-./jobs.tests: line 91: bg: job 1 already in background
+./jobs.tests: line 93: fg: %2: no such job
+./jobs.tests: line 94: bg: job 1 already in background
fg-bg 6
-./jobs.tests: line 98: fg: -s: invalid option
+./jobs.tests: line 101: fg: -s: invalid option
fg: usage: fg [job_spec]
-./jobs.tests: line 99: bg: -s: invalid option
+./jobs.tests: line 102: bg: -s: invalid option
bg: usage: bg [job_spec ...]
-./jobs.tests: line 104: disown: -s: invalid option
+./jobs.tests: line 107: disown: -s: invalid option
disown: usage: disown [-h] [-ar] [jobspec ... | pid ...]
-./jobs.tests: line 108: disown: %1: no such job
-./jobs.tests: line 111: disown: %2: no such job
+./jobs.tests: line 111: disown: %1: no such job
+./jobs.tests: line 114: disown: %2: no such job
wait-for-non-child
-./jobs.tests: line 114: wait: pid 1 is not a child of this shell
+./jobs.tests: line 117: wait: pid 1 is not a child of this shell
127
3 -- 1 2 3 -- 1 - 2 - 3
[1] Running sleep 300 &
@@ -75,8 +76,8 @@ running jobs:
[1] Running sleep 300 &
[2]- Running sleep 350 &
[3]+ Running sleep 400 &
-./jobs.tests: line 131: kill: %4: no such job
-./jobs.tests: line 133: jobs: %4: no such job
+./jobs.tests: line 134: kill: %4: no such job
+./jobs.tests: line 136: jobs: %4: no such job
current job:
[3]+ Running sleep 400 &
previous job:
diff --git a/tests/jobs.tests b/tests/jobs.tests
index c99f4f71..3c2eef31 100644
--- a/tests/jobs.tests
+++ b/tests/jobs.tests
@@ -15,6 +15,9 @@ ${THIS_SH} ./jobs4.sub
# test out wait -n framework
${THIS_SH} ./jobs5.sub
+# test out wait -f framework
+${THIS_SH} ./jobs6.sub
+
jobs
echo $?
diff --git a/tests/jobs1.sub b/tests/jobs1.sub
index aa9a3726..53f66cc6 100644
--- a/tests/jobs1.sub
+++ b/tests/jobs1.sub
@@ -2,7 +2,7 @@
set -m
sleep 60 &
-FN=/tmp/jobs-pid.$$
+FN=$TMPDIR/jobs-pid.$$
pid1=$!
jobs -p %+ > $FN
diff --git a/tests/jobs4.sub b/tests/jobs4.sub
index 2eb4197a..898b449b 100644
--- a/tests/jobs4.sub
+++ b/tests/jobs4.sub
@@ -1,12 +1,12 @@
# test being able to use job control notation in jobs/kill/wait without
# job control active, as the SUS requires
-sleep 5 &
+sleep 2 &
-sleep 5 &
-sleep 5 &
-sleep 5 &
-(sleep 5 ; exit 4) &
+sleep 2 &
+sleep 2 &
+sleep 2 &
+(sleep 2 ; exit 4) &
jobs
diff --git a/tests/jobs6.sub b/tests/jobs6.sub
new file mode 100644
index 00000000..9ed59ee5
--- /dev/null
+++ b/tests/jobs6.sub
@@ -0,0 +1,14 @@
+# framework to test `wait -f' which forces wait until a job exits
+set -o monitor
+sleep 5 &
+child1=$!
+
+( sleep 1; kill -STOP $child1 ; sleep 1 ; kill -CONT $child1 )&
+
+child2=$!
+
+wait -f %1
+echo child1 exit status $?
+
+wait $child2
+exit 0
diff --git a/tests/more-exp.tests b/tests/more-exp.tests
index 4a3cb7f5..10b3a47e 100644
--- a/tests/more-exp.tests
+++ b/tests/more-exp.tests
@@ -152,7 +152,7 @@ b1()
b2()
{
recho $*
- recho $#
+ recho ${#}
}
expect '<1>'
@@ -414,7 +414,7 @@ recho ${#}
expect '<5>'
recho ${#?:-xyz}
-shift $#
+shift ${#}
expect '<0>'
recho ${#:-foo}
diff --git a/tests/nameref.right b/tests/nameref.right
index 53002595..2ab62b09 100644
--- a/tests/nameref.right
+++ b/tests/nameref.right
@@ -48,7 +48,7 @@ argv[1] = <unset>
expect <bar>
argv[1] = <bar>
expect <unset>
-argv[1] = <unset>
+./nameref3.sub: line 16: foo: invalid indirect expansion
./nameref3.sub: line 21: unset: bar: cannot unset: readonly variable
expect <two>
two
@@ -226,6 +226,13 @@ declare -r RO="x"
./nameref11.sub: line 39: declare: RO_PID: not found
./nameref11.sub: line 41: RO2: readonly variable
declare -r RO2="a"
+2
+./nameref11.sub: line 52: typeset: `2': invalid variable name for name reference
+2
+./nameref11.sub: line 57: typeset: `2': invalid variable name for name reference
+2
+./nameref11.sub: line 62: foo[2]: invalid indirect expansion
+./nameref11.sub: line 63: bar: invalid indirect expansion
./nameref12.sub: line 6: declare: `/': invalid variable name for name reference
./nameref12.sub: line 9: declare: `%': invalid variable name for name reference
./nameref12.sub: line 13: `^': not a valid identifier
@@ -306,30 +313,38 @@ declare -a b=([0]="0")
./nameref15.sub: line 19: warning: ref: circular name reference
./nameref15.sub: line 20: warning: ref: circular name reference
./nameref15.sub: line 21: warning: ref: circular name reference
-inside
+inside X
outside X
-./nameref15.sub: line 29: typeset: ref: nameref variable self references not allowed
-./nameref15.sub: line 31: ref: nameref variable self references not allowed
+before: 7
+./nameref15.sub: line 32: typeset: warning: xxx: circular name reference
+./nameref15.sub: line 32: warning: xxx: circular name reference
+./nameref15.sub: line 33: warning: xxx: circular name reference
+declare -n xxx="xxx"
+./nameref15.sub: line 35: warning: xxx: circular name reference
+xxx_func: inside: xxx = foo
+after: foo
+./nameref15.sub: line 46: typeset: ref: nameref variable self references not allowed
+./nameref15.sub: line 48: ref: nameref variable self references not allowed
declare -n ref="re"
declare -n ref="re"
declare -- re="4"
4
declare -n foo="var[@]"
declare -n ref="var[@]"
-./nameref15.sub: line 48: var[@]: bad array subscript
+./nameref15.sub: line 65: var[@]: bad array subscript
declare -n bar="var[@]"
-./nameref15.sub: line 53: var[@]: bad array subscript
+./nameref15.sub: line 70: var[@]: bad array subscript
declare -n a="b"
declare -n b="a[1]"
-./nameref15.sub: line 61: warning: a: removing nameref attribute
+./nameref15.sub: line 78: warning: a: removing nameref attribute
declare -a a=([1]="foo")
declare -n b="a[1]"
-./nameref15.sub: line 66: warning: a: removing nameref attribute
+./nameref15.sub: line 83: warning: a: removing nameref attribute
declare -a a=([1]="foo")
declare -n b="a[1]"
declare -n n="v"
declare -a v=([1]="1")
-./nameref15.sub: line 82: typeset: n: not found
+./nameref15.sub: line 99: typeset: n: not found
declare -a v=([0]="0" [1]="1")
declare -n n="v[1]"
declare -a v=([0]="0")
@@ -409,3 +424,19 @@ declare -a var=([123]="")
declare -n ref="var[123]"
./nameref18.sub: line 54: declare: var[123]: not found
declare -a var=([123]="X")
+declare -n foo="bar"
+declare -- foo="bar"
+./nameref19.sub: line 9: declare: bar: not found
+declare -n foo="bar"
+declare -- foo="bar"
+declare -i bar="11"
+declare -inx foo6
+declare -ix foo6
+declare -n foo="bar"
+declare -- bar="Hello World!"
+declare -- foo="bar"
+declare -- bar="Hello World!"
+declare -n foo="bar"
+declare -- bar
+declare -- foo="bar"
+declare -- bar
diff --git a/tests/nameref11.sub b/tests/nameref11.sub
index 85feedfa..402e5015 100644
--- a/tests/nameref11.sub
+++ b/tests/nameref11.sub
@@ -39,3 +39,25 @@ unset -n ref ; unset ref
declare -r RO RO_PID; coproc RO { :; }; declare -p RO_PID; wait; declare -p RO RO_PID
declare -r RO2=a; declare -n ref_PID=RO2; coproc ref { :; }; wait; declare -p RO2
+
+unset x y
+set -- one two three
+
+y=2
+typeset -n x=y
+echo ${x}
+
+unset -n x
+
+typeset -n y
+echo $y
+
+unset -n y
+
+typeset -n y
+y=2
+echo ${y}
+
+declare -n foo=bar
+echo ${!foo[2]}
+echo ${!bar}
diff --git a/tests/nameref15.sub b/tests/nameref15.sub
index 6c9ace5e..9fbacd4f 100644
--- a/tests/nameref15.sub
+++ b/tests/nameref15.sub
@@ -26,6 +26,23 @@ add_X_echo ref
echo outside "$ref"
unset ref
+# same test, but assigning nameref variable circular reference directly
+xxx_func()
+{
+ typeset -n xxx=xxx
+ xxx=foo
+ declare -p xxx
+ echo $FUNCNAME: inside: xxx = $xxx
+}
+
+xxx=7
+echo before: $xxx
+xxx_func
+echo after: $xxx
+
+unset xxx
+unset -f xxx_func
+
typeset -n ref=ref
typeset -n ref=re ref+=f
@@ -85,4 +102,3 @@ v=(0 1)
declare -n n=v[1]
unset n
declare -p n v
-
diff --git a/tests/nameref19.sub b/tests/nameref19.sub
new file mode 100644
index 00000000..d46c003f
--- /dev/null
+++ b/tests/nameref19.sub
@@ -0,0 +1,51 @@
+# can we unset the nameref attribute on variables with values that reference
+# unset variables?
+
+unset bar
+declare -n foo="bar"
+declare -p foo
+
+declare +n foo
+declare -p foo bar
+
+declare -n foo
+declare -p foo
+
+# let's try removing the nameref attribute -- other attributes and assignments
+# apply to the nameref target
+
+declare +n -i foo=7+4
+declare -p foo bar
+
+unset foo bar
+
+# but if the nameref variable doesn't have a value, the attributes apply to
+# the nameref variable itself. thanks ksh93
+
+declare -n foo6
+declare -xi foo6
+declare -p foo6
+
+# and when we remove the nameref attribute, the other attributes remain
+
+declare +n foo6
+declare -p foo6
+
+unset foo6
+
+# make sure these cases continue to work
+
+# nameref referencing an existing, set variable
+declare -n foo=bar
+bar='Hello World!'
+declare -p foo bar
+declare +n foo
+declare -p foo bar
+unset foo bar
+
+# nameref referencing an existing, unset variable
+declare -n foo=bar
+declare bar
+declare -p foo bar
+declare +n foo
+declare -p foo bar
diff --git a/tests/new-exp.right b/tests/new-exp.right
index 9913fbd6..12fc18dd 100644
--- a/tests/new-exp.right
+++ b/tests/new-exp.right
@@ -169,11 +169,11 @@ lines.
This-string-has-multiple-lines.
this is a test of proc subst
this is test 2
-./new-exp2.sub: line 31: /tmp/bashtmp.x*: No such file or directory
-./new-exp2.sub: line 35: /tmp/redir-notthere: No such file or directory
+a
+./new-exp2.sub: line 42: /tmp/redir-notthere: No such file or directory
1
-./new-exp2.sub: line 42: 1111111111111111111111: command not found
+./new-exp2.sub: line 49: 1111111111111111111111: command not found
argv[1] = <6>
./new-exp.tests: line 285: ${#:}: bad substitution
@@ -624,7 +624,7 @@ c Sub = 0 2 4 8
<'ab cd'>
<'4'> <'ab cd'>
<>
-argv[1] = <host(2)[4.4]$ >
+argv[1] = <host(2)[5.0]$ >
<
>
<' \t\n'>
@@ -643,6 +643,26 @@ ir
a b c d e
5
a5b
+abcxxxdef
+abcådef
+ḅć
+Ã¥
+prependḅć
+Ã¥append
+prependå
+ḅćappend
+Ã¥
+ḅć
+ḅć
+ḅć
+Ã¥
+Ã¥
+Ã¥
+ḅć
+Ã¥
+Ã¥
+ḅć
+ḅć
argv[1] = </>
argv[1] = </>
-./new-exp.tests: line 608: ABXD: parameter unset
+./new-exp.tests: line 611: ABXD: parameter unset
diff --git a/tests/new-exp.tests b/tests/new-exp.tests
index c4aa9d16..31e15468 100644
--- a/tests/new-exp.tests
+++ b/tests/new-exp.tests
@@ -340,7 +340,7 @@ recho "${foo:-$@}"
expect '<ab> <cd> <ef> <gh>'
recho "${foo:-"$@"}"
-shift $#
+shift ${#}
expect nothing
recho $xxx"$@"
expect nothing
@@ -498,7 +498,7 @@ recho ${*%?}
recho ${@#?}
recho ${*#?}
-shift $#
+shift ${#}
set -u
( recho $9 ; echo after 1)
( recho ${9} ; echo after 2)
@@ -597,6 +597,9 @@ ${THIS_SH} ./new-exp9.sub
# new parameter transformation `@' expansion operator
${THIS_SH} ./new-exp10.sub
+# parameter substring replacement and removal operators with multibyte chars
+${THIS_SH} ./new-exp11.sub
+
# problems with stray CTLNUL in bash-4.0-alpha
unset a
a=/a
diff --git a/tests/new-exp1.sub b/tests/new-exp1.sub
index c015c223..2b621fca 100644
--- a/tests/new-exp1.sub
+++ b/tests/new-exp1.sub
@@ -1,3 +1,4 @@
+FN=${TMPDIR}/bashtest-$$
expect()
{
echo expect "$@"
@@ -5,7 +6,11 @@ expect()
expect this is a test of proc subst
cat <(echo this is a test of proc subst)
-echo this is test 2 > /tmp/x
+echo this is test 2 > $FN
expect this is test 2
-cat <(cat /tmp/x)
-rm -f /tmp/x
+cat <(cat $FN)
+rm -f $FN
+
+foo=
+expect a
+cat ${foo:-<(echo a)}
diff --git a/tests/new-exp11.sub b/tests/new-exp11.sub
new file mode 100644
index 00000000..da6b4e1f
--- /dev/null
+++ b/tests/new-exp11.sub
@@ -0,0 +1,46 @@
+# pattern matching and replacement operators with multibyte characters
+
+LANG=en_US.UTF-8
+
+s1='abcådef'
+s2='Ã¥'
+s3='ḅć'
+
+s23=${s2}${s3}
+
+echo ${s1/$s2/xxx}
+echo ${s1/$s3/xxx}
+
+echo ${s23/#$s2/}
+echo ${s23/%$s3/}
+
+echo ${s23/#$s2/prepend}
+echo ${s23/%$s3/append}
+
+echo ${s2/#/prepend}
+echo ${s3/%/append}
+
+echo ${s2/#/}
+echo ${s3/%/}
+
+recho ${s2/$s2/}
+recho ${s3/$s3/}
+
+# posix pattern replacements
+
+echo ${s23##$s2}
+echo ${s23#$s2}
+
+echo ${s23%%$s3}
+echo ${s23%$s3}
+
+# fail
+
+echo ${s2/#ab/xx}
+echo ${s3/%ab/xx}
+
+echo ${s2#ab}
+echo ${s2##ab}
+
+echo ${s3%ab}
+echo ${s3%%ab}
diff --git a/tests/new-exp2.sub b/tests/new-exp2.sub
index e8377799..ea52b3ce 100644
--- a/tests/new-exp2.sub
+++ b/tests/new-exp2.sub
@@ -4,7 +4,7 @@ export LANG=C
# test out the new $(< filename) code
# it should be exactly equivalent to $(cat filename)
-FILENAME=/tmp/bashtmp.x$$
+FILENAME=$TMPDIR/bashtmp.x$$
trap 'rm -f $FILENAME' 0
@@ -21,17 +21,24 @@ if [[ $LINES1 != $LINES2 ]]; then
echo 'whoops: $(< filename) failed'
fi
-LINES2=$(< /tmp/bashtmp.x*)
+LINES2=$(< $TMPDIR/bashtmp.x*)
if [[ $LINES1 != $LINES2 ]]; then
echo 'whoops: $(< filename) with glob expansion failed'
fi
# but the glob expansion in the redirection should fail in posix mode
set -o posix
-LINES2=$(< /tmp/bashtmp.x*)
+exec 3>&2
+exec 2>/dev/null
+LINES2=$(< $TMPDIR/bashtmp.x*)
+exec 2>&3
+if [[ $LINES2 -gt 0 ]]; then
+ echo "whoops: redirection glob expansion should be disabled in posix mode" >&2
+fi
set +o posix
# now see what happens when we try it with a non-existant file
+rm -f /tmp/redir-notthere
LINES3=$(< /tmp/redir-notthere)
echo $?
diff --git a/tests/parser.right b/tests/parser.right
index 43d5a8ed..cecbb222 100644
--- a/tests/parser.right
+++ b/tests/parser.right
@@ -1 +1,16 @@
AAA
+bash5: `invalid-name': not a valid identifier
+in
+in
+in
+in
+bash5: -c: line 0: syntax error near unexpected token `)'
+bash5: -c: line 0: `case x in esac) echo done; esac'
+in
+bash5: -c: line 0: syntax error near unexpected token `do'
+bash5: -c: line 0: `case in do do) echo in; esac'
+bash5: -c: line 0: syntax error near unexpected token `('
+bash5: -c: line 0: `for()'
+in
+done
+ok 1
diff --git a/tests/parser.tests b/tests/parser.tests
index 12ff88c2..6e020a4b 100644
--- a/tests/parser.tests
+++ b/tests/parser.tests
@@ -2,3 +2,5 @@
# this has to be in a separate file to get desired EOF behavior
${THIS_SH} ./parser1.sub
+
+${THIS_SH} ./posix2syntax.sub
diff --git a/tests/posix2syntax.sub b/tests/posix2syntax.sub
new file mode 100644
index 00000000..e7dda58f
--- /dev/null
+++ b/tests/posix2syntax.sub
@@ -0,0 +1,53 @@
+: ${THIS_SH:=./bash}
+bashname=bash${BASH_VERSION%%.*}
+
+# tests for Posix grammar special cases
+
+# Posix grammar rule 5
+${THIS_SH} -c 'for invalid-name in a b c; do echo error; done' $bashname
+
+# Posix grammar rule 6: third word in FOR or SELECT
+for i; do echo; done; echo in
+for i; do echo in; done
+for i do echo in; done
+
+select i; do echo; done; echo in
+select i; do echo in; done; echo in
+select i do echo in; done; echo in
+
+# Posix grammar rule 4: when PATTERN == ESAC, return ESAC
+${THIS_SH} -c 'case x in esac) echo done; esac' $bashname
+
+# Posix grammar rule 6: third word in CASE
+${THIS_SH} -c 'case in in in) echo in; esac;' $bashname
+${THIS_SH} -c 'case in do do) echo in; esac' $bashname
+
+# Posix grammar rule 8: function NAME
+${THIS_SH} -o posix -c 'for()
+{
+echo function for;
+}' $bashname
+
+for for in for; do echo in; echo done; done
+
+${THIS_SH} -c 'for (( i = 0; i < 5; i++ )) do : ; done' $bashname
+${THIS_SH} -c 'for (( i = 0; i < 5; i++ )) { : ; }' $bashname
+
+# bug report: IN turning on unwanted alias expansion
+${THIS_SH} -o posix -c '
+alias foo='two words'
+foo_word='foo'
+case "$foo_word"
+in
+ foo) echo "bad 1";;
+esac' $bashname
+
+${THIS_SH} -o posix -c '
+alias foo='oneword'
+foo_word='foo'
+case "$foo_word"
+in
+ foo) echo "ok 1";;
+esac' $bashname
+
+
diff --git a/tests/posixexp.right b/tests/posixexp.right
index 0ba6555a..1e81eadb 100644
--- a/tests/posixexp.right
+++ b/tests/posixexp.right
@@ -37,5 +37,243 @@ argv[1] = <'bar>
argv[1] = <foo 'bar baz>
argv[1] = <}z>
argv[1] = <''z}>
-./posixexp.tests: line 77: unexpected EOF while looking for matching `}'
-./posixexp.tests: line 78: syntax error: unexpected end of file
+argv[1] = <1>
+argv[2] = <2>
+argv[1] = <1>
+argv[2] = <2>
+argv[1] = <1>
+argv[2] = <2>
+argv[1] = <1 2>
+argv[1] = <1>
+argv[2] = <2>
+argv[1] = <1 2>
+argv[1] = <1>
+argv[2] = <2>
+argv[1] = <1 2>
+argv[1] = <1>
+argv[2] = <2>
+argv[1] = <1 2>
+argv[1] = <1>
+argv[2] = <2>
+argv[1] = <1 2>
+argv[1] = <1>
+argv[2] = <2>
+argv[1] = <1>
+argv[2] = <2>
+argv[1] = <1>
+argv[2] = <2>
+argv[1] = <12>
+argv[1] = <1 2>
+argv[1] = <1 2>
+argv[1] = <1 2>
+argv[1] = <1 2>
+argv[1] = <1 2>
+argv[1] = <1 2>
+argv[1] = <12>
+argv[1] = <12>
+argv[1] = <12>
+argv[1] = <12>
+argv[1] = <12>
+argv[1] = <12>
+argv[1] = <1 2>
+argv[1] = <1 2>
+argv[1] = <12>
+argv[1] = <12>
+normal IFS
+argv[1] = <abc>
+argv[2] = <def>
+argv[3] = <ghi>
+argv[4] = <jkl>
+argv[1] = <abc>
+argv[2] = <def>
+argv[3] = <ghi>
+argv[4] = <jkl>
+argv[1] = <abc>
+argv[2] = <def>
+argv[3] = <ghi>
+argv[4] = <jkl>
+null IFS
+argv[1] = < abc>
+argv[2] = <def ghi>
+argv[3] = <jkl >
+argv[1] = < abc def ghi jkl >
+argv[1] = < abc>
+argv[2] = <def ghi>
+argv[3] = <jkl >
+non-standard IFS
+argv[1] = < abc>
+argv[2] = <def ghi>
+argv[3] = <jkl >
+argv[1] = < abc def ghi jkl >
+argv[1] = < abc def ghi jkl >
+unset IFS
+argv[1] = < abc>
+argv[2] = <def ghi>
+argv[3] = <jkl >
+argv[1] = < abc def ghi jkl >
+argv[1] = < abc def ghi jkl >
+
+001: IFS = (unset): unset -v foo; set -- ${foo=$*}
+soh stx etx del / soh stx etx del
+
+002: IFS = (unset): unset -v foo; set -- ${foo="$*"}
+soh stx etx del / soh stx etx del
+
+003: IFS = (unset): unset -v foo; set -- "${foo=$*}"
+soh stx etx del / soh stx etx del
+
+004: IFS = (unset): foo=; set -- ${foo:=$*}
+soh stx etx del / soh stx etx del
+
+005: IFS = (unset): foo=; set -- ${foo:="$*"}
+soh stx etx del / soh stx etx del
+
+006: IFS = (unset): foo=; set -- "${foo:=$*}"
+soh stx etx del / soh stx etx del
+
+007: IFS = (unset): unset -v foo; set -- ${foo=$@}
+soh stx etx del / soh stx etx del
+
+008: IFS = (unset): unset -v foo; set -- ${foo="$@"}
+soh stx etx del / soh stx etx del
+
+009: IFS = (unset): unset -v foo; set -- "${foo=$@}"
+soh stx etx del / soh stx etx del
+
+010: IFS = (unset): foo=; set -- ${foo:=$@}
+soh stx etx del / soh stx etx del
+
+011: IFS = (unset): foo=; set -- ${foo:="$@"}
+soh stx etx del / soh stx etx del
+
+012: IFS = (unset): foo=; set -- "${foo:=$@}"
+soh stx etx del / soh stx etx del
+
+013: IFS = (null): unset -v foo; set -- ${foo=$*}
+soh stx etx del / soh stx etx del
+
+014: IFS = (null): unset -v foo; set -- ${foo="$*"}
+soh stx etx del / soh stx etx del
+
+015: IFS = (null): unset -v foo; set -- "${foo=$*}"
+soh stx etx del / soh stx etx del
+
+016: IFS = (null): foo=; set -- ${foo:=$*}
+soh stx etx del / soh stx etx del
+
+017: IFS = (null): foo=; set -- ${foo:="$*"}
+soh stx etx del / soh stx etx del
+
+018: IFS = (null): foo=; set -- "${foo:=$*}"
+soh stx etx del / soh stx etx del
+
+019: IFS = (null): unset -v foo; set -- ${foo=$@}
+soh stx etx del / soh stx etx del
+
+020: IFS = (null): unset -v foo; set -- ${foo="$@"}
+soh stx etx del / soh stx etx del
+
+021: IFS = (null): unset -v foo; set -- "${foo=$@}"
+soh stx etx del / soh stx etx del
+
+022: IFS = (null): foo=; set -- ${foo:=$@}
+soh stx etx del / soh stx etx del
+
+023: IFS = (null): foo=; set -- ${foo:="$@"}
+soh stx etx del / soh stx etx del
+
+024: IFS = (null): foo=; set -- "${foo:=$@}"
+soh stx etx del / soh stx etx del
+
+025: IFS = x: unset -v foo; set -- ${foo=$*}
+soh stx etx del / soh stx etx del
+
+026: IFS = x: unset -v foo; set -- ${foo="$*"}
+soh stx etx del / soh stx etx del
+
+027: IFS = x: unset -v foo; set -- "${foo=$*}"
+soh stx etx del / soh stx etx del
+
+028: IFS = x: foo=; set -- ${foo:=$*}
+soh stx etx del / soh stx etx del
+
+029: IFS = x: foo=; set -- ${foo:="$*"}
+soh stx etx del / soh stx etx del
+
+030: IFS = x: foo=; set -- "${foo:=$*}"
+soh stx etx del / soh stx etx del
+
+031: IFS = x: unset -v foo; set -- ${foo=$@}
+soh stx etx del / soh stx etx del
+
+032: IFS = x: unset -v foo; set -- ${foo="$@"}
+soh stx etx del / soh stx etx del
+
+033: IFS = x: unset -v foo; set -- "${foo=$@}"
+soh stx etx del / soh stx etx del
+
+034: IFS = x: foo=; set -- ${foo:=$@}
+soh stx etx del / soh stx etx del
+
+035: IFS = x: foo=; set -- ${foo:="$@"}
+soh stx etx del / soh stx etx del
+
+036: IFS = x: foo=; set -- "${foo:=$@}"
+soh stx etx del / soh stx etx del
+
+037: IFS = sp ht nl: unset -v foo; set -- ${foo=$*}
+soh stx etx del / soh stx etx del
+
+038: IFS = sp ht nl: unset -v foo; set -- ${foo="$*"}
+soh stx etx del / soh stx etx del
+
+039: IFS = sp ht nl: unset -v foo; set -- "${foo=$*}"
+soh stx etx del / soh stx etx del
+
+040: IFS = sp ht nl: foo=; set -- ${foo:=$*}
+soh stx etx del / soh stx etx del
+
+041: IFS = sp ht nl: foo=; set -- ${foo:="$*"}
+soh stx etx del / soh stx etx del
+
+042: IFS = sp ht nl: foo=; set -- "${foo:=$*}"
+soh stx etx del / soh stx etx del
+
+043: IFS = sp ht nl: unset -v foo; set -- ${foo=$@}
+soh stx etx del / soh stx etx del
+
+044: IFS = sp ht nl: unset -v foo; set -- ${foo="$@"}
+soh stx etx del / soh stx etx del
+
+045: IFS = sp ht nl: unset -v foo; set -- "${foo=$@}"
+soh stx etx del / soh stx etx del
+
+046: IFS = sp ht nl: foo=; set -- ${foo:=$@}
+soh stx etx del / soh stx etx del
+
+047: IFS = sp ht nl: foo=; set -- ${foo:="$@"}
+soh stx etx del / soh stx etx del
+
+048: IFS = sp ht nl: foo=; set -- "${foo:=$@}"
+soh stx etx del / soh stx etx del
+argv[1] = <^A^B^C^?>
+argv[1] = <^A^B^C^?>
+argv[1] = <^A^B^C^?>
+argv[1] = <^A^B^C^?>
+argv[1] = <^A^B^C^?>
+argv[1] = <^A^B^C^?>
+argv[1] = <^A^B^C^?>
+argv[1] = <^A^B^C^?>
+argv[1] = <a>
+argv[2] = <b>
+argv[1] = <a>
+argv[2] = <b>
+argv[1] = <a>
+argv[2] = <b>
+argv[1] = <a>
+argv[2] = <b>
+[ abc def ghi jkl / abc def ghi jkl ]
+[ abc def ghi jkl ]
+[ abc def ghi jkl / abc def ghi jkl / abc def ghi jkl ]
+./posixexp.tests: line 82: unexpected EOF while looking for matching `}'
+./posixexp.tests: line 83: syntax error: unexpected end of file
diff --git a/tests/posixexp.tests b/tests/posixexp.tests
index 60be1c74..76dfede9 100644
--- a/tests/posixexp.tests
+++ b/tests/posixexp.tests
@@ -72,6 +72,11 @@ ${THIS_SH} ./posixexp1.sub || echo "bash posixexp1.sub: test $? failed"
THIS_SH=$TMPDIR/sh ${THIS_SH} ./posixexp2.sub || echo "sh posixexp2.sub: test $? failed"
rm -f $TMPDIR/sh
+${THIS_SH} ./posixexp3.sub
+${THIS_SH} ./posixexp4.sub
+${THIS_SH} ./posixexp5.sub
+${THIS_SH} ./posixexp6.sub
+
# this will be an error
foo=bar
echo "${foo:-"a}"
diff --git a/tests/posixexp2.sub b/tests/posixexp2.sub
index f48d0887..397769da 100644
--- a/tests/posixexp2.sub
+++ b/tests/posixexp2.sub
@@ -18,4 +18,7 @@ ${THIS_SH} -c 'echo ${1?}' 2>/dev/null && exit 11
${THIS_SH} -c 'echo ${1?}' ${THIS_SH} x >/dev/null || exit 12
${THIS_SH} -c 'echo ${2?}' ${THIS_SH} x 2>/dev/null && exit 13
${THIS_SH} -c 'echo ${2?}' ${THIS_SH} x y >/dev/null || exit 14
+
+${THIS_SH} -c $'echo $(( x+ )) \n exit 0' ${THIS_SH} 2>/dev/null && exit 15
+
exit 0
diff --git a/tests/posixexp2.tests b/tests/posixexp2.tests
index 57dd767d..2bec58e0 100644
--- a/tests/posixexp2.tests
+++ b/tests/posixexp2.tests
@@ -1,6 +1,6 @@
# From mksh
-set -o posix
+set -o posix ; shopt -u xpg_echo
(echo 1 ${IFS+'}'z}) 2>&- || echo failed in 1
(echo 2 "${IFS+'}'z}") 2>&- || echo failed in 2
diff --git a/tests/posixexp3.sub b/tests/posixexp3.sub
new file mode 100644
index 00000000..c40afa94
--- /dev/null
+++ b/tests/posixexp3.sub
@@ -0,0 +1,52 @@
+set -- 1 2
+
+unset var
+recho ${var-$@}
+recho ${var-"$@"}
+recho ${var-$*}
+recho ${var-"$*"}
+
+unset -v a b c d
+recho ${a=$@}
+recho "$a"
+recho ${b="$@"}
+recho "$b"
+recho ${c=$*}
+recho "$c"
+recho ${d="$*"}
+recho "$d"
+
+IFS=
+unset var
+recho ${var-$@}
+recho ${var-"$@"}
+recho ${var-$*}
+recho ${var-"$*"}
+
+unset -v a b c d
+# Posix interp 221
+# there should never be any word splitting because IFS is null
+recho ${a=$@}
+recho "$a"
+recho $a
+recho ${b="$@"}
+recho "$b"
+recho $b
+recho ${c=$*}
+recho "$c"
+recho $c
+recho ${d="$*"}
+recho "$d"
+recho $d
+
+unset -v a b c d
+a=$@
+recho $a
+b="$@"
+recho $b
+c=$*
+recho $c
+d="$*"
+recho $d
+
+unset -v parameter a b c d
diff --git a/tests/posixexp4.sub b/tests/posixexp4.sub
new file mode 100644
index 00000000..22bfeca8
--- /dev/null
+++ b/tests/posixexp4.sub
@@ -0,0 +1,31 @@
+set -- ' abc' 'def ghi' 'jkl '
+
+echo normal IFS
+recho $@
+: ${var=$@}
+recho $var
+unset -v var
+recho ${var-$@}
+
+echo null IFS
+IFS=
+recho $@
+: ${var=$@}
+recho $var
+unset -v var
+recho ${var-$@}
+
+echo non-standard IFS
+IFS=:
+recho $@
+: ${var=$@}
+recho $var
+unset -v var
+recho ${var-$@} # this is inconsistent
+
+echo unset IFS
+recho $@
+: ${var=$@}
+recho $var
+unset -v var
+recho ${var-$@}
diff --git a/tests/posixexp5.sub b/tests/posixexp5.sub
new file mode 100644
index 00000000..cceeb00c
--- /dev/null
+++ b/tests/posixexp5.sub
@@ -0,0 +1,51 @@
+# test suite contribution from Martijn Dekker
+
+defaultIFS=$IFS
+set -o errexit -o noglob
+(set -o pipefail) 2>/dev/null && set -o pipefail
+teststring=$(printf '\1\2\3\177')
+n=0
+
+trim_od() {
+ od -a | sed -n '1 { s/^0*[[:blank:]]*//; s/[[:blank:]]*$//; p; }'
+}
+
+doTest() {
+ set -- "$teststring"
+ eval "$testcmd"
+ case ${IFS+s}${IFS:+n} in
+ ( sn ) i=$(printf %s "$IFS" | trim_od) ;;
+ ( s ) i='(null)' ;;
+ ( '' ) i='(unset)' ;;
+ ( * ) echo 'internal error!' >&2; exit 125 ;;
+ esac
+ printf '\n%03d: IFS = %s: %s\n' "$((n+=1))" "$i" "$testcmd"
+ printf %s "$*${foo+/}${foo-}" | trim_od
+}
+
+doAllTests() {
+ for testcmd in \
+ 'unset -v foo; set -- ${foo=$*}' \
+ 'unset -v foo; set -- ${foo="$*"}' \
+ 'unset -v foo; set -- "${foo=$*}"' \
+ \
+ 'foo=; set -- ${foo:=$*}' \
+ 'foo=; set -- ${foo:="$*"}' \
+ 'foo=; set -- "${foo:=$*}"' \
+ \
+ 'unset -v foo; set -- ${foo=$@}' \
+ 'unset -v foo; set -- ${foo="$@"}' \
+ 'unset -v foo; set -- "${foo=$@}"' \
+ \
+ 'foo=; set -- ${foo:=$@}' \
+ 'foo=; set -- ${foo:="$@"}' \
+ 'foo=; set -- "${foo:=$@}"'
+ do
+ doTest "$testcmd"
+ done
+}
+
+unset -v IFS; doAllTests
+IFS=''; doAllTests
+IFS='x'; doAllTests
+IFS=$defaultIFS; doAllTests
diff --git a/tests/posixexp6.sub b/tests/posixexp6.sub
new file mode 100644
index 00000000..ed38d535
--- /dev/null
+++ b/tests/posixexp6.sub
@@ -0,0 +1,57 @@
+var=$'\01\02\03\177'
+
+bar=${unset:-$var}
+recho "$bar"
+unset -v bar
+bar=${unset:-"$var"}
+recho "$bar"
+
+foo=${parameter:=$var}
+
+recho "$foo"
+recho "$parameter"
+
+unset -v foo parameter
+
+foo=${parameter:="$var"}
+
+recho "$foo"
+recho "$parameter"
+
+unset -v foo parameter
+
+foo="${parameter:=$var}"
+
+recho "$foo"
+recho "$parameter"
+
+unset -v foo parameter
+
+recho ${parameter:=a\ b}
+unset -v parameter
+
+recho ${parameter:="a b"}
+unset -v parameter
+
+v='a b'
+
+recho ${parameter:=$v}
+unset -v parameter
+
+recho ${parameter:="$v"}
+unset -v parameter
+
+# unsetting IFS here
+
+set " abc " " def ghi " "jkl "
+unset -v IFS var
+var=${var-$*}/${var-$*}
+printf '[%s]\n' "$var"
+
+unset -v var
+: ${var=$*}
+printf '[%s]\n' "$var"
+
+unset -v var
+: ${var:=$*/$*/${var-$*}}
+printf '[%s]\n' "$var"
diff --git a/tests/posixpat.tests b/tests/posixpat.tests
index 91fac3b8..65c557a3 100644
--- a/tests/posixpat.tests
+++ b/tests/posixpat.tests
@@ -20,13 +20,15 @@ case 9 in
[![:alpha:]]) echo ok 4;;
esac
-# invalid character class expressions are just characters to be matched
case a in
[:al:]) echo ok 5;;
esac
+# invalid character class expressions are no longer just characters to be
+# matched
case a in
-[[:al:]) echo ok 6;;
+[[:al:]) echo bad 6;;
+*) echo ok 6;;
esac
case '!' in
@@ -230,4 +232,3 @@ case a in
[[=b=]) echo oops;; # an incomplete equiv class is just a string
*) echo ok 3;;
esac
-
diff --git a/tests/printf.right b/tests/printf.right
index ae34a890..593f084b 100644
--- a/tests/printf.right
+++ b/tests/printf.right
@@ -148,6 +148,7 @@ b
xx
xx
+< >< >
one
one\ctwo
4\.2
diff --git a/tests/printf.tests b/tests/printf.tests
index e72f5c8b..9dbac6f0 100644
--- a/tests/printf.tests
+++ b/tests/printf.tests
@@ -308,6 +308,9 @@ shopt -s nullglob extglob
echo "x$(printf "%b" @(hugo))x"
printf -v var "%b" @(hugo); echo "x${var}x"
+# make sure that missing arguments are always handled like the empty string
+printf "<%3s><%3b>\n"
+
# tests variable assignment with -v
${THIS_SH} ./printf1.sub
@@ -316,4 +319,3 @@ ${THIS_SH} ./printf2.sub
${THIS_SH} ./printf3.sub
${THIS_SH} ./printf4.sub
-
diff --git a/tests/printf3.sub b/tests/printf3.sub
index ec14fa34..d45e101c 100644
--- a/tests/printf3.sub
+++ b/tests/printf3.sub
@@ -6,7 +6,7 @@ SECS=1275250155
export TZ=EST5EDT
case $SHELLSTART in
-*s*) SHELLSTART=$(perl -e 'print time') ; DATESECS=false ;; # take a shot
+*s*) SHELLSTART=$EPOCHSECONDS ; DATESECS=false ;; # take a shot
*) DATESECS=true ;;
esac
@@ -15,7 +15,7 @@ printf "%(abde)Z\n" -1
printf "%(%e-%b-%Y %T)T\n" $SECS
-printf -v v1 "%(%e-%b-%Y %T)T\n" $( $DATESECS && date +%s || perl -e 'print time')
+printf -v v1 "%(%e-%b-%Y %T)T\n" $( $DATESECS && date +%s || echo $EPOCHSECONDS )
printf -v v2 "%(%e-%b-%Y %T)T\n" -1
case $v1 in
diff --git a/tests/procsub.right b/tests/procsub.right
new file mode 100644
index 00000000..cf1dbb10
--- /dev/null
+++ b/tests/procsub.right
@@ -0,0 +1,29 @@
+test1
+foo
+test2
+test3
+test4
+8
+test5
+test6
+test7
+test8
+test8a
+test9
+hi
+bye
+l8r
+::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+intern
+1
+0
+0
+0
+0
+extern
+1
+0
+0
+0
+0
+123
diff --git a/tests/procsub.tests b/tests/procsub.tests
new file mode 100644
index 00000000..4678ac69
--- /dev/null
+++ b/tests/procsub.tests
@@ -0,0 +1,99 @@
+# process substitution constructs that have caused problems in the past
+. ./test-glue-functions
+
+eval cat <(echo test1)
+eval "echo foo;cat" <(echo test2)
+
+unset f
+f=<(echo test3); cat "$f"
+
+unset f
+eval f=<(echo test4) "; cat \$f"
+
+unset f
+
+FN=$TMPDIR/bashtest-procsub-$$
+cat >"$FN" <<EOF
+echo "test 12" | wc -c | _cut_leading_spaces
+cat "\$1"
+EOF
+
+source "$FN" <(echo test5)
+rm -f "$FN"
+unset FN
+
+cat <( echo test6 ) <( echo test7 )
+cat <( echo test8 ; sleep 2; echo test8a ) <( echo test9 )
+
+# Zev Weiss 11/7/2012
+fn() { cat | cat "$1"; }
+fn <(:) < /dev/null
+
+unset -f fn
+
+f1(){
+ cat $1
+ date >/dev/null
+}
+f2(){
+ date >/dev/null
+ cat $1
+}
+cat <(echo hi)
+f1 <(echo bye)
+f2 <(echo l8r)
+
+unset -f f1 f2
+
+# set up conditions for test
+ulimit -n 256
+
+bug()
+{
+c=$(ulimit -n)
+let c+=100
+while let c--
+do
+ while read -ru3 x
+ do
+ echo -n :
+ done 3< <(echo x)
+done
+echo
+}
+
+bug
+unset -f bug
+
+count_lines()
+{
+ wc -l < $1
+ wc -l < $1
+ wc -l < $1
+ true | wc -l < $1
+ wc -l < $1
+}
+
+echo intern
+count_lines <(date) | _cut_leading_spaces
+unset -f count_lines
+
+echo extern
+FN=$TMPDIR/bashtest-$$
+cat >$FN <<EOF
+wc -l < \$1
+wc -l < \$1
+wc -l < \$1
+true | wc -l < \$1
+wc -l < \$1
+EOF
+
+${THIS_SH} -c "source $FN <(date)" | _cut_leading_spaces
+rm -f $FN
+
+moo() { ls -l "$1" >/dev/null; ls -l "$1" >/dev/null; }; moo >(true)
+moo() { ls -al "$1" >/dev/null; (true); ls -al "$1" >/dev/null; }; moo >(true)
+
+unset -f moo
+
+${THIS_SH} ./procsub1.sub
diff --git a/tests/redir12.sub b/tests/procsub1.sub
index 0e68f3b2..0e68f3b2 100644
--- a/tests/redir12.sub
+++ b/tests/procsub1.sub
diff --git a/tests/quote.right b/tests/quote.right
index 00b55c62..e4c25741 100644
--- a/tests/quote.right
+++ b/tests/quote.right
@@ -66,6 +66,12 @@ argv[2] = <ab>
${
argv[1] = <(")>
argv[1] = <(")>
+string \
+string \
+string \
+string \
+string \
+string \}
'weferfds'\''dsfsdf'
'weferfdsdsfsdf'
'weferfds'\''dsfsdf'
diff --git a/tests/quote.tests b/tests/quote.tests
index 0c55293b..57ee7e58 100644
--- a/tests/quote.tests
+++ b/tests/quote.tests
@@ -109,4 +109,15 @@ recho `echo "(\\")"`
# ultimate workaround
recho `echo "(\")"`
+# various strings ending in backslashes
+
+echo 'string \'
+echo "string \\"
+
+echo string\ \\
+
+echo ${foo:-'string \'}
+echo "${foo:-string \\}"
+echo ${foo:-string \\\}}
+
${THIS_SH} ./quote1.sub
diff --git a/tests/quote1.sub b/tests/quote1.sub
index c83e64ac..a9a1ef15 100644
--- a/tests/quote1.sub
+++ b/tests/quote1.sub
@@ -14,7 +14,7 @@ echo "'${test//"'"/}'"
echo "'${test//"'"/"'\\''"}'"
-echo "'${test//"'"/\'\\'\'}'"
+printf "%s\n" "'${test//"'"/\'\\'\'}'"
#echo "'${test//'/}'" # hangs waiting for '
#echo "'${test//"'"/'\\''}'" # hangs waiting for '
diff --git a/tests/read.tests b/tests/read.tests
index fe27dae3..f67cd00e 100644
--- a/tests/read.tests
+++ b/tests/read.tests
@@ -25,43 +25,43 @@ echo $'\177' | ( read ; recho "$REPLY" )
# the input stream
echo $'ab\\\ncd' | ( read ; recho "$REPLY" )
-echo "A B " > /tmp/IN
+echo "A B " > $TMPDIR/IN
unset x y z
-read x y z < /tmp/IN
+read x y z < $TMPDIR/IN
echo 1: "x[$x] y[$y] z[$z]"
echo 1a: ${z-z not set}
-read x < /tmp/IN
+read x < $TMPDIR/IN
echo 2: "x[$x]"
-rm /tmp/IN
+rm $TMPDIR/IN
# this is where the bash `read' behavior with respect to $REPLY differs
# from ksh93
-echo "A B " > /tmp/IN
+echo "A B " > $TMPDIR/IN
-read < /tmp/IN
+read < $TMPDIR/IN
echo "[$REPLY]"
-rm /tmp/IN
+rm $TMPDIR/IN
-echo " A B " > /tmp/IN
+echo " A B " > $TMPDIR/IN
-read < /tmp/IN
+read < $TMPDIR/IN
echo "[$REPLY]"
-rm /tmp/IN
+rm $TMPDIR/IN
# make sure that read with more variables than words sets the extra
# variables to the empty string
bvar=bvar
cvar=cvar
-echo aa > /tmp/IN
-read avar bvar cvar < /tmp/IN
+echo aa > $TMPDIR/IN
+read avar bvar cvar < $TMPDIR/IN
echo =="$avar"==
echo =="$bvar"==
echo =="$cvar"==
-rm /tmp/IN
+rm $TMPDIR/IN
# test behavior of read with various settings of IFS
diff --git a/tests/redir.right b/tests/redir.right
index c158e251..ab737d49 100644
--- a/tests/redir.right
+++ b/tests/redir.right
@@ -26,10 +26,10 @@ from stdin: aa
to stdout
./redir4.sub: line 32: $fd: ambiguous redirect
./redir4.sub: line 33: $fd: ambiguous redirect
-/tmp/err-and-out:
+err-and-out:
to stdout
to stderr
-/tmp/err-and-out:
+err-and-out:
to stdout
to stderr
0 -- 3 0
@@ -157,4 +157,3 @@ a+=3
foo
foo
./redir11.sub: line 53: $(echo $a): Bad file descriptor
-123
diff --git a/tests/redir.tests b/tests/redir.tests
index 24e3cd1a..7b74ac53 100644
--- a/tests/redir.tests
+++ b/tests/redir.tests
@@ -191,4 +191,3 @@ ${THIS_SH} ./redir9.sub
${THIS_SH} ./redir10.sub
${THIS_SH} ./redir11.sub
-${THIS_SH} ./redir12.sub
diff --git a/tests/redir4.sub b/tests/redir4.sub
index 47344554..14406d01 100644
--- a/tests/redir4.sub
+++ b/tests/redir4.sub
@@ -34,23 +34,23 @@ exec 4>&$fd
exec 3>&1 4>&2
-exec >&/tmp/err-and-out
+exec >&${TMPDIR}/err-and-out
echo to stdout
echo to stderr >&2
exec 1>&3 2>&4
-echo /tmp/err-and-out:
-cat /tmp/err-and-out
+echo err-and-out:
+cat ${TMPDIR}/err-and-out
-rm /tmp/err-and-out
+rm ${TMPDIR}/err-and-out
-fd=/tmp/err-and-out
+fd=${TMPDIR}/err-and-out
exec >&$fd
echo to stdout
echo to stderr >&2
exec 1>&3 2>&4
-echo /tmp/err-and-out:
-cat /tmp/err-and-out
+echo err-and-out:
+cat ${TMPDIR}/err-and-out
-rm /tmp/err-and-out
+rm ${TMPDIR}/err-and-out
diff --git a/tests/redir6.sub b/tests/redir6.sub
index 60cc68b0..c735e523 100644
--- a/tests/redir6.sub
+++ b/tests/redir6.sub
@@ -6,3 +6,5 @@ pwd
echo $?
echo $?
echo $?
+
+cd $OLDPWD
diff --git a/tests/redir8.sub b/tests/redir8.sub
index 5f972a14..88753f2f 100644
--- a/tests/redir8.sub
+++ b/tests/redir8.sub
@@ -56,4 +56,6 @@ exec 0<&7
exec 7<&-
rm -f infile
+
+cd $OLDPWD
exit 0
diff --git a/tests/rsh.right b/tests/rsh.right
index 022b2ca1..a728f137 100644
--- a/tests/rsh.right
+++ b/tests/rsh.right
@@ -1,13 +1,19 @@
-./rsh.tests: line 9: cd: restricted
-./rsh.tests: line 10: PATH: readonly variable
-./rsh.tests: line 11: SHELL: readonly variable
-./rsh.tests: line 12: /bin/sh: restricted: cannot specify `/' in command names
-./rsh.tests: line 14: .: ./source.sub3: restricted
-./rsh.tests: line 17: /tmp/restricted: restricted: cannot redirect output
-./rsh.tests: line 21: /tmp/restricted: restricted: cannot redirect output
-./rsh.tests: line 26: command: -p: restricted
-./rsh.tests: line 28: set: +r: invalid option
+./rsh1.sub: line 9: /bin/sh: restricted
+./rsh1.sub: line 11: sh: not found
+./rsh1.sub: line 12: a: command not found
+./rsh2.sub: line 10: hash: /bin/sh: restricted
+./rsh2.sub: line 12: hash: sh: not found
+./rsh2.sub: line 13: a: command not found
+./rsh.tests: line 12: cd: restricted
+./rsh.tests: line 13: PATH: readonly variable
+./rsh.tests: line 14: SHELL: readonly variable
+./rsh.tests: line 15: /bin/sh: restricted: cannot specify `/' in command names
+./rsh.tests: line 17: .: ./source.sub3: restricted
+./rsh.tests: line 20: /tmp/restricted: restricted: cannot redirect output
+./rsh.tests: line 24: /tmp/restricted: restricted: cannot redirect output
+./rsh.tests: line 29: command: -p: restricted
+./rsh.tests: line 31: set: +r: invalid option
set: usage: set [-abefhkmnptuvxBCHP] [-o option-name] [--] [arg ...]
-./rsh.tests: line 29: set: restricted: invalid option name
-./rsh.tests: line 31: exec: restricted
+./rsh.tests: line 32: set: restricted: invalid option name
+./rsh.tests: line 34: exec: restricted
./rsh.tests: after exec
diff --git a/tests/rsh.tests b/tests/rsh.tests
index ffdf6e55..d1d77784 100644
--- a/tests/rsh.tests
+++ b/tests/rsh.tests
@@ -4,6 +4,9 @@
# adding builtins dynamically with enable -f
# importing function definitions from environment
+${THIS_SH} ./rsh1.sub
+${THIS_SH} ./rsh2.sub
+
set -r
cd /
diff --git a/tests/rsh1.sub b/tests/rsh1.sub
new file mode 100644
index 00000000..fdd4ddd9
--- /dev/null
+++ b/tests/rsh1.sub
@@ -0,0 +1,16 @@
+cd ${TMPDIR:-/tmp}
+cp /bin/sh .
+
+PATH=/rbin:/usr/local/rbin
+hash -p /bin/rm rm
+
+set -r
+
+BASH_CMDS[x]=/bin/sh
+
+BASH_CMDS[a]="sh"
+a -c 'echo hello'
+
+rm -f sh a
+
+exit 0
diff --git a/tests/rsh2.sub b/tests/rsh2.sub
new file mode 100644
index 00000000..8c82c68b
--- /dev/null
+++ b/tests/rsh2.sub
@@ -0,0 +1,17 @@
+cd ${TMPDIR:-/tmp}
+cp /bin/sh .
+ln sh a
+
+PATH=/rbin:/usr/local/rbin
+hash -p /bin/rm rm
+
+set -r
+
+hash -p /bin/sh sh
+
+hash -p sh a
+a -c 'echo hello'
+
+rm -f sh a
+
+exit 0
diff --git a/tests/run-all b/tests/run-all
index 2882fe07..34d3e4c8 100644
--- a/tests/run-all
+++ b/tests/run-all
@@ -9,15 +9,21 @@ SUFFIX=`${THIS_SH} -c 'echo $(( $RANDOM + $BASHPID ))'`
BASH_TSTOUT=${TMPDIR}/bashtst-$SUFFIX # for now
export BASH_TSTOUT
-trap 'rm -f $BASH_TSTOUT' 0
+trap 'rm -f $BASH_TSTOUT' 0 1 2 3 15
PATH=.:$PATH # just to get recho/zecho/printenv if not run via `make tests'
export PATH
# unset BASH_ENV only if it is set
[ "${BASH_ENV+set}" = "set" ] && unset BASH_ENV
-# ditto for SHELLOPTS
-#[ "${SHELLOPTS+set}" = "set" ] && unset SHELLOPTS
+# can't reliably do it for SHELLOPTS; SHELLOPTS is readonly in bash
+if [ "${BASH_VERSION+set}" = "set" ]; then
+ export -n SHELLOPTS # just make sure its not exported
+ set +o posix
+ typeset -p SHELLOPTS
+else
+ [ "${SHELLOPTS+set}" = "set" ] && unset SHELLOPTS 2>/dev/null
+fi
: ${THIS_SH:=../bash}
export THIS_SH
diff --git a/tests/run-dynvar b/tests/run-dynvar
new file mode 100644
index 00000000..26c5434b
--- /dev/null
+++ b/tests/run-dynvar
@@ -0,0 +1,2 @@
+${THIS_SH} ./dynvar.tests > ${BASH_TSTOUT} 2>&1
+diff ${BASH_TSTOUT} dynvar.right && rm -f ${BASH_TSTOUT}
diff --git a/tests/run-minimal b/tests/run-minimal
index c7fba73e..bbb9da18 100644
--- a/tests/run-minimal
+++ b/tests/run-minimal
@@ -41,6 +41,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 ;;
+ ;;
*) ;;
esac
rm -f "$BASH_TSTOUT"
diff --git a/tests/run-procsub b/tests/run-procsub
new file mode 100644
index 00000000..796faaa8
--- /dev/null
+++ b/tests/run-procsub
@@ -0,0 +1,7 @@
+echo "warning: all of these tests will fail if process substitution has not" >&2
+echo "warning: been compiled into the shell or if the OS does not provide" >&2
+echo "warning: FIFOs or /dev/fd. Some tests may fail if the OS does not" >&2
+echo "warning: provide FIFOs." >&2
+
+${THIS_SH} ./procsub.tests > ${BASH_TSTOUT} 2>&1
+diff ${BASH_TSTOUT} procsub.right && rm -f ${BASH_TSTOUT}
diff --git a/tests/set-x.right b/tests/set-x.right
index a41a382a..259602e5 100644
--- a/tests/set-x.right
+++ b/tests/set-x.right
@@ -26,6 +26,10 @@
+ x=i
+ case x in
+ x=i
++ foo=one
++ foo+=two
++ echo onetwo
+onetwo
+ set +x
1
2
diff --git a/tests/set-x.tests b/tests/set-x.tests
index 648f0a9e..531c53f6 100755
--- a/tests/set-x.tests
+++ b/tests/set-x.tests
@@ -14,6 +14,11 @@ case x in
0) x=i ;;
*) x=i ;;
esac
+
+foo=one
+foo+=two
+echo $foo
+
set +x
# test BASH_XTRACEFD
diff --git a/tests/shopt.right b/tests/shopt.right
index 86d9ed6b..bb0ac696 100644
--- a/tests/shopt.right
+++ b/tests/shopt.right
@@ -2,6 +2,7 @@
shopt: usage: shopt [-pqsu] [-o] [optname ...]
--
shopt -u autocd
+shopt -u assoc_expand_once
shopt -u cdable_vars
shopt -s cdspell
shopt -u checkhash
@@ -14,6 +15,7 @@ shopt -u compat40
shopt -u compat41
shopt -u compat42
shopt -u compat43
+shopt -u compat44
shopt -s complete_fullquote
shopt -u direxpand
shopt -u dirspell
@@ -37,6 +39,7 @@ shopt -u inherit_errexit
shopt -s interactive_comments
shopt -u lastpipe
shopt -u lithist
+shopt -u localvar_inherit
shopt -u login_shell
shopt -u mailwarn
shopt -u no_empty_cmd_completion
@@ -67,6 +70,7 @@ shopt -s promptvars
shopt -s sourcepath
--
shopt -u autocd
+shopt -u assoc_expand_once
shopt -u cdable_vars
shopt -u checkhash
shopt -u checkjobs
@@ -77,6 +81,7 @@ shopt -u compat40
shopt -u compat41
shopt -u compat42
shopt -u compat43
+shopt -u compat44
shopt -u direxpand
shopt -u dirspell
shopt -u dotglob
@@ -94,6 +99,7 @@ shopt -u huponexit
shopt -u inherit_errexit
shopt -u lastpipe
shopt -u lithist
+shopt -u localvar_inherit
shopt -u login_shell
shopt -u mailwarn
shopt -u no_empty_cmd_completion
@@ -105,6 +111,7 @@ shopt -u shift_verbose
shopt -u xpg_echo
--
autocd off
+assoc_expand_once off
cdable_vars off
checkhash off
checkjobs off
@@ -115,6 +122,7 @@ compat40 off
compat41 off
compat42 off
compat43 off
+compat44 off
direxpand off
dirspell off
dotglob off
@@ -132,6 +140,7 @@ huponexit off
inherit_errexit off
lastpipe off
lithist off
+localvar_inherit off
login_shell off
mailwarn off
no_empty_cmd_completion off
diff --git a/tests/test-glue-functions b/tests/test-glue-functions
index 2b2f61d0..b958ab71 100644
--- a/tests/test-glue-functions
+++ b/tests/test-glue-functions
@@ -6,4 +6,8 @@ _intl_normalize_spaces()
sed -e 's/[[:space:]]\{1,\}/ /g' -e 's/[[:space:]]*$//'
}
-
+# avoid whitespace differences in wc implementations
+_cut_leading_spaces()
+{
+ sed -e 's/^[[:space:]]*//g'
+}
diff --git a/tests/test.right b/tests/test.right
index 7fcd9964..9832bd6d 100644
--- a/tests/test.right
+++ b/tests/test.right
@@ -289,3 +289,7 @@ t -t /dev/tty4
t -t /dev/tty4444444...
1
1
+t -p /dev/fd/6
+1
+t -p /dev/fd/6
+0
diff --git a/tests/test.tests b/tests/test.tests
index 47eef354..07a87a0b 100644
--- a/tests/test.tests
+++ b/tests/test.tests
@@ -436,3 +436,5 @@ t -t /dev/tty4444444...
# fixed in bash-4.0-beta
t -t ' '
+
+${THIS_SH} ./test1.sub
diff --git a/tests/test1.sub b/tests/test1.sub
new file mode 100644
index 00000000..a1c58170
--- /dev/null
+++ b/tests/test1.sub
@@ -0,0 +1,21 @@
+# some systems, like old SunOS, have stat on /dev/fd/N and fstat(N, ...)
+# return different results
+: ${TMPDIR:=/tmp}
+
+trap 'rm -f ${TMPDIR}/pipe' 0 1 2 3 6 15
+
+exec 6>&-
+echo "t -p /dev/fd/6"
+test -p /dev/fd/6
+echo $?
+
+rm -f ${TMPDIR}/pipe 2>/dev/null
+mkfifo ${TMPDIR}/pipe
+cat < ${TMPDIR}/pipe &
+exec 6>&-
+exec 6>${TMPDIR}/pipe
+echo "t -p /dev/fd/6"
+test -p /dev/fd/6
+echo $?
+exec 2>/dev/null # disable process termination message
+kill $! 2>/dev/null
diff --git a/tests/tilde.tests b/tests/tilde.tests
index 50f19e98..8a9f1369 100644
--- a/tests/tilde.tests
+++ b/tests/tilde.tests
@@ -1,3 +1,4 @@
+wdir=$PWD
# this is needed because posix mode restricts tilde expansion to assignment
# statements preceding a command, instead of the default of expanding all
# assignment statements on the line (e.g., after `export'). Without this,
@@ -69,3 +70,6 @@ esac
USER=root # should exist just about everywhere
echo ~$USER
+
+cd "$wdir"
+exit 0
diff --git a/tests/trap.right b/tests/trap.right
index 1f68d331..41658293 100644
--- a/tests/trap.right
+++ b/tests/trap.right
@@ -64,6 +64,14 @@ after while
before false in trap2a.sub
after false in trap2a.sub
command substitution
+ERRTRAP
+ERRTRAP
+bar
+ERRTRAP
+ERRTRAP
+ERRTRAP
+ERRTRAP
+ERRTRAP
+[6] echo 1
1
+[7] echo 2
@@ -93,6 +101,10 @@ sleep 2
wait $!
exit
in trap EXIT
+fn
+after 1
+fn
+after 2
caught a child death
caught a child death
caught a child death
diff --git a/tests/trap.tests b/tests/trap.tests
index 4176df08..637bfd28 100644
--- a/tests/trap.tests
+++ b/tests/trap.tests
@@ -74,6 +74,9 @@ ${THIS_SH} ./trap4.sub
# This doesn't work right on all Unix versions
#${THIS_SH} ./trap5.sub
+# Return trap issues
+${THIS_SH} ./trap6.sub
+
#
# show that setting a trap on SIGCHLD is not disastrous.
#
diff --git a/tests/trap2.sub b/tests/trap2.sub
index 73357df2..0f1f2d96 100755
--- a/tests/trap2.sub
+++ b/tests/trap2.sub
@@ -23,3 +23,27 @@ echo after while
./trap2a.sub
echo $(false ; echo command substitution)
+
+# test behavior of failed commands following `command' builtin
+command false
+
+(command false)
+command false | echo bar
+
+(false)
+
+exit 42 | command false
+
+command command command false
+
+unset FALSE
+if [ -x /bin/false ]; then
+ FALSE=/bin/false
+elif [ -x /usr/bin/false ]; then
+ FALSE=/usr/bin/false
+else
+ FALSE='command false'
+fi
+
+command $FALSE
+command command command $FALSE
diff --git a/tests/trap6.sub b/tests/trap6.sub
new file mode 100644
index 00000000..332a1773
--- /dev/null
+++ b/tests/trap6.sub
@@ -0,0 +1,15 @@
+set -o functrace
+fn() { return; }
+
+trap "echo fn ; fn" RETURN
+
+fn
+echo after 1
+
+unset -f fn
+
+fn() { eval return; }
+fn
+echo after 2
+
+unset -f fn
diff --git a/tests/type.right b/tests/type.right
index 3f7d26e2..7ec6bfba 100644
--- a/tests/type.right
+++ b/tests/type.right
@@ -65,11 +65,11 @@ foo is a function
foo ()
{
echo;
- cat <<END
+ cat <<END
bar
END
- cat <<EOF
+ cat <<EOF
qux
EOF
@@ -86,7 +86,7 @@ foo ()
rm -f a b c;
for f in a b c;
do
- cat >> ${f} <<-EOF
+ cat <<-EOF >> ${f}
file
EOF
@@ -99,7 +99,7 @@ c:file
bb is a function
bb ()
{
- ( cat <<EOF
+ ( cat <<EOF
foo
bar
EOF
@@ -110,13 +110,13 @@ mkcoprocs is a function
mkcoprocs ()
{
coproc a {
- cat <<EOF1
+ cat <<EOF1
producer 1
EOF1
}
coproc b {
- cat <<EOF2
+ cat <<EOF2
producer 2
EOF2
@@ -126,7 +126,7 @@ EOF2
mkcoprocs is a function
mkcoprocs ()
{
- coproc COPROC ( b cat <<EOF
+ coproc COPROC ( b cat <<EOF
heredoc
body
EOF
diff --git a/tests/type3.sub b/tests/type3.sub
index a90afef0..442f22e4 100644
--- a/tests/type3.sub
+++ b/tests/type3.sub
@@ -16,3 +16,6 @@ eval "$(type foo | sed 1d)"
foo
rm -f a b c
+
+cd $OLDPWD
+exit 0
diff --git a/tests/varenv.right b/tests/varenv.right
index 38d1ce7d..7ca5f661 100644
--- a/tests/varenv.right
+++ b/tests/varenv.right
@@ -91,6 +91,62 @@ global:2
after: --global--
after: ----
x = :1:2
+in o1 (readonly modifying local scalars):
+declare -r i1="a b c"
+declare -r j1="1 2 3"
+after o1:
+./varenv9.sub: line 15: declare: i1: not found
+./varenv9.sub: line 15: declare: j1: not found
+in o2 (readonly setting global scalars):
+declare -r i2="a b c"
+declare -r j2="1 2 3"
+after o2:
+declare -r i2="a b c"
+declare -r j2="1 2 3"
+./varenv9.sub: line 33: unset: i2: cannot unset: readonly variable
+./varenv9.sub: line 33: unset: j2: cannot unset: readonly variable
+in o3 (readonly modifying locals, converting to arrays):
+declare -ar i3=([0]="a" [1]="b" [2]="c")
+declare -ar j3=([0]="1" [1]="2" [2]="3")
+after o3:
+./varenv9.sub: line 48: declare: i3: not found
+./varenv9.sub: line 48: declare: j3: not found
+in o4 (readonly setting global array variables):
+declare -ar i4=([0]="a" [1]="b" [2]="c")
+declare -ar j4=([0]="1" [1]="2" [2]="3")
+after o4:
+declare -ar i4=([0]="a" [1]="b" [2]="c")
+declare -ar j4=([0]="1" [1]="2" [2]="3")
+./varenv9.sub: line 66: unset: i4: cannot unset: readonly variable
+./varenv9.sub: line 66: unset: j4: cannot unset: readonly variable
+main: unset
+inner: res unset
+outer: res: X Y
+main: after first call: X
+inner: X
+outer: res: X Y
+main: after second call: X
+func: null or unset
+after func: x = outside
+./varenv11.sub: line 4: local: qux: readonly variable
+./varenv11.sub: line 5: qux: readonly variable
+declare -A foo=([one]="one" [zero]="zero" )
+declare -a bar=([0]="zero" [1]="one")
+declare -A foo=([one]="one" [zero]="zero" )
+declare -a bar=([0]="zero" [1]="one")
+./varenv11.sub: line 29: a: readonly variable
+foo=abc
+func1: var =
+
+func1: var =
+
+inside: declare -- foo
+outside:
+declare -x foo="abc"
+inside: declare -x var="value"
+outside: declare -- var="one"
+inside: declare -- var="local"
+outside: declare -x var="global"
a=z
a=b
a=z
diff --git a/tests/varenv.sh b/tests/varenv.sh
index a0d31690..f2299b43 100644
--- a/tests/varenv.sh
+++ b/tests/varenv.sh
@@ -221,5 +221,18 @@ ${THIS_SH} ./varenv7.sub
# redirections
${THIS_SH} ./varenv8.sub
+# make sure that builtins like readonly and export modify local array variables
+# if executed in shell functions, like they modify local scalar variables
+${THIS_SH} ./varenv9.sub
+
+# more tests of unset and local variables with dynamic scoping
+${THIS_SH} ./varenv10.sub
+
+# tests of compound assignments in function scope
+${THIS_SH} ./varenv11.sub
+
+# temporary environment variable propagation and scoping in posix mode
+${THIS_SH} ./varenv12.sub
+
# 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/varenv10.sub b/tests/varenv10.sub
new file mode 100644
index 00000000..887cfd2c
--- /dev/null
+++ b/tests/varenv10.sub
@@ -0,0 +1,47 @@
+#!/bin/bash
+#
+# various tests of unset when applied to variables at different local scopes
+
+# function unsetting variable at previous local scope, uncovering global
+
+inner()
+{
+ unset res
+ echo ${FUNCNAME}: ${res-res unset}
+ if [[ $1 == "set" ]]; then
+ res[0]="X"
+ res[1]="Y"
+ fi
+}
+
+outer()
+{
+ local res=
+ inner "$1"
+ echo ${FUNCNAME}: "res: ${res[@]}"
+}
+
+echo main: ${res-unset}
+outer set
+echo main: after first call: ${res-unset}
+outer dontset
+echo main: after second call: ${res-unset}
+
+unset -f outer inner
+unset res
+
+# local scope, unset variable at the same scope as local declaration
+func()
+{
+ typeset x=4
+
+ unset x
+ echo ${FUNCNAME}: ${x:-null or unset}
+}
+
+x=outside
+func
+echo after func: x = $x
+
+unset -f func
+unset x
diff --git a/tests/varenv11.sub b/tests/varenv11.sub
new file mode 100644
index 00000000..d4384983
--- /dev/null
+++ b/tests/varenv11.sub
@@ -0,0 +1,30 @@
+# couple of errors here
+func()
+{
+ local qux=7
+ local qux=(one two)
+ local what=(zero one two)
+}
+
+readonly qux=42
+func
+
+func2()
+{
+ declare -gA foo=([zero]=zero [one]=one)
+ declare -ga bar=(zero one)
+}
+
+foo=help
+bar=me
+
+func2
+
+declare -p foo bar
+unset foo bar
+func2
+declare -p foo bar
+
+readonly a=7
+a=(1 2 3)
+
diff --git a/tests/varenv12.sub b/tests/varenv12.sub
new file mode 100644
index 00000000..6aaf512b
--- /dev/null
+++ b/tests/varenv12.sub
@@ -0,0 +1,62 @@
+set -o posix
+
+fn() { foo=abc : ; typeset +x foo; printenv|grep ^foo=; }
+
+fn
+unset -v foo
+unset -f fn
+
+func1() {
+ var=1
+ var=2 : # or 'var=2 return', or another special builtin
+ unset -v var
+ echo $FUNCNAME: var = $var
+}
+func2() {
+ func1
+ unset -v var # bug: fails silently
+}
+func1
+echo ${var+"BUG: still set 1"}
+
+unset var
+func2
+echo ${var+"BUG: still set 2"}
+
+unset -v var
+unset -f func1 func2
+
+fn() { foo=abc : ; typeset +x foo; echo -n 'inside: ' ; declare -p foo; }
+fn
+echo outside:
+declare -p foo
+
+unset -v foo
+unset -f fn
+
+func()
+{
+ var=value declare -x var
+ echo -n 'inside: ' ; declare -p var
+}
+
+var=one
+func
+echo -n 'outside: ' ; declare -p var
+
+unset -v var
+unset -f func
+
+func()
+{
+ local var=local
+ var=global :
+ echo -n 'inside: ' ; declare -p var
+}
+
+var=outside
+func
+echo -n 'outside: ' ; declare -p var
+
+unset -v var
+unset -f func
diff --git a/tests/varenv9.sub b/tests/varenv9.sub
new file mode 100644
index 00000000..eda1be3f
--- /dev/null
+++ b/tests/varenv9.sub
@@ -0,0 +1,66 @@
+# case 1: readonly modifying local scalar variables
+o1() {
+ local i1 j1
+ readonly i1=$1
+ readonly j1="1 2 3"
+
+ echo "in o1 (readonly modifying local scalars):"
+ declare -p i1
+ declare -p j1
+}
+
+o1 "a b c"
+
+echo after o1:
+declare -p i1 j1
+
+unset i1 j1
+
+# case 2: readonly setting global scalar variables
+o2() {
+ readonly i2=$1
+ readonly j2="1 2 3"
+
+ echo "in o2 (readonly setting global scalars):"
+ declare -p i2
+ declare -p j2
+}
+
+o2 "a b c"
+echo after o2:
+declare -p i2 j2
+
+unset i2 j2
+
+# case 3: readonly modifying local variables, converting to arrays
+o3() {
+ local i3 j3
+ readonly i3=($1)
+ readonly j3=(1 2 3)
+
+ echo "in o3 (readonly modifying locals, converting to arrays):"
+ declare -p i3
+ declare -p j3
+}
+
+o3 "a b c"
+echo after o3:
+declare -p i3 j3
+
+unset i3 j3
+
+# case 4: readonly setting global array variables
+o4() {
+ readonly i4=($1)
+ readonly j4=(1 2 3)
+
+ echo "in o4 (readonly setting global array variables):"
+ declare -p i4
+ declare -p j4
+}
+
+o4 "a b c"
+echo after o4:
+declare -p i4 j4
+
+unset i4 j4
diff --git a/tests/vredir.right b/tests/vredir.right
index 3985f22d..f449ae6f 100644
--- a/tests/vredir.right
+++ b/tests/vredir.right
@@ -27,7 +27,7 @@ line 3
bar is a function
bar ()
{
- exec {v}<<EOF
+ exec {v}<<EOF
line 1
line 2
line 3