summaryrefslogtreecommitdiff
path: root/src/cmd/ksh93/tests
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/ksh93/tests')
-rwxr-xr-xsrc/cmd/ksh93/tests/alias.sh102
-rwxr-xr-xsrc/cmd/ksh93/tests/append.sh86
-rwxr-xr-xsrc/cmd/ksh93/tests/arith.sh737
-rwxr-xr-xsrc/cmd/ksh93/tests/arrays.sh588
-rwxr-xr-xsrc/cmd/ksh93/tests/arrays2.sh212
-rwxr-xr-xsrc/cmd/ksh93/tests/attributes.sh418
-rwxr-xr-xsrc/cmd/ksh93/tests/basic.sh513
-rwxr-xr-xsrc/cmd/ksh93/tests/bracket.sh340
-rwxr-xr-xsrc/cmd/ksh93/tests/builtins.sh562
-rwxr-xr-xsrc/cmd/ksh93/tests/case.sh85
-rwxr-xr-xsrc/cmd/ksh93/tests/comvar.sh689
-rw-r--r--src/cmd/ksh93/tests/comvario.sh686
-rwxr-xr-xsrc/cmd/ksh93/tests/coprocess.sh360
-rwxr-xr-xsrc/cmd/ksh93/tests/cubetype.sh213
-rwxr-xr-xsrc/cmd/ksh93/tests/enum.sh68
-rwxr-xr-xsrc/cmd/ksh93/tests/exit.sh80
-rwxr-xr-xsrc/cmd/ksh93/tests/expand.sh126
-rwxr-xr-xsrc/cmd/ksh93/tests/functions.sh1157
-rwxr-xr-xsrc/cmd/ksh93/tests/glob.sh374
-rwxr-xr-xsrc/cmd/ksh93/tests/grep.sh105
-rwxr-xr-xsrc/cmd/ksh93/tests/heredoc.sh496
-rwxr-xr-xsrc/cmd/ksh93/tests/io.sh484
-rwxr-xr-xsrc/cmd/ksh93/tests/leaks.sh68
-rwxr-xr-xsrc/cmd/ksh93/tests/locale.sh319
-rw-r--r--src/cmd/ksh93/tests/math.sh202
-rwxr-xr-xsrc/cmd/ksh93/tests/nameref.sh658
-rwxr-xr-xsrc/cmd/ksh93/tests/options.sh544
-rwxr-xr-xsrc/cmd/ksh93/tests/path.sh375
-rwxr-xr-xsrc/cmd/ksh93/tests/pointtype.sh138
-rwxr-xr-xsrc/cmd/ksh93/tests/pty.sh442
-rwxr-xr-xsrc/cmd/ksh93/tests/quoting.sh369
-rwxr-xr-xsrc/cmd/ksh93/tests/quoting2.sh215
-rw-r--r--src/cmd/ksh93/tests/readcsv.sh65
-rwxr-xr-xsrc/cmd/ksh93/tests/recttype.sh70
-rwxr-xr-xsrc/cmd/ksh93/tests/restricted.sh83
-rwxr-xr-xsrc/cmd/ksh93/tests/return.sh183
-rwxr-xr-xsrc/cmd/ksh93/tests/select.sh67
-rwxr-xr-xsrc/cmd/ksh93/tests/shtests235
-rwxr-xr-xsrc/cmd/ksh93/tests/sigchld.sh160
-rwxr-xr-xsrc/cmd/ksh93/tests/signal.sh435
-rwxr-xr-xsrc/cmd/ksh93/tests/statics.sh690
-rwxr-xr-xsrc/cmd/ksh93/tests/subshell.sh582
-rwxr-xr-xsrc/cmd/ksh93/tests/substring.sh628
-rwxr-xr-xsrc/cmd/ksh93/tests/tilde.sh101
-rwxr-xr-xsrc/cmd/ksh93/tests/timetype.sh81
-rwxr-xr-xsrc/cmd/ksh93/tests/treemove.sh163
-rwxr-xr-xsrc/cmd/ksh93/tests/types.sh632
-rwxr-xr-xsrc/cmd/ksh93/tests/variables.sh665
-rwxr-xr-xsrc/cmd/ksh93/tests/vartree1.sh215
-rwxr-xr-xsrc/cmd/ksh93/tests/vartree2.sh335
50 files changed, 17201 insertions, 0 deletions
diff --git a/src/cmd/ksh93/tests/alias.sh b/src/cmd/ksh93/tests/alias.sh
new file mode 100755
index 0000000..5a75fa3
--- /dev/null
+++ b/src/cmd/ksh93/tests/alias.sh
@@ -0,0 +1,102 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+alias foo='print hello'
+if [[ $(foo) != hello ]]
+then err_exit 'foo, where foo is alias for "print hello" failed'
+fi
+if [[ $(foo world) != 'hello world' ]]
+then err_exit 'foo world, where foo is alias for "print hello" failed'
+fi
+alias foo='print hello '
+alias bar=world
+if [[ $(foo bar) != 'hello world' ]]
+then err_exit 'foo bar, where foo is alias for "print hello " failed'
+fi
+if [[ $(foo \bar) != 'hello bar' ]]
+then err_exit 'foo \bar, where foo is alias for "print hello " failed'
+fi
+alias bar='foo world'
+if [[ $(bar) != 'hello world' ]]
+then err_exit 'bar, where bar is alias for "foo world" failed'
+fi
+if [[ $(alias bar) != "bar='foo world'" ]]
+then err_exit 'alias bar, where bar is alias for "foo world" failed'
+fi
+unalias foo || err_exit "unalias foo failed"
+alias foo 2> /dev/null && err_exit "alias for non-existent alias foo returns true"
+unset bar
+alias bar="print foo$bar"
+bar=bar
+if [[ $(bar) != foo ]]
+then err_exit 'alias bar, where bar is alias for "print foo$bar" failed'
+fi
+unset bar
+alias bar='print hello'
+if [[ $bar != '' ]]
+then err_exit 'alias bar cause variable bar to be set'
+fi
+alias !!=print
+if [[ $(!! hello 2>/dev/null) != hello ]]
+then err_exit 'alias for !!=print not working'
+fi
+alias foo=echo
+if [[ $(print "$(foo bar)" ) != bar ]]
+then err_exit 'alias in command substitution not working'
+fi
+( unalias foo)
+if [[ $(foo bar 2> /dev/null) != bar ]]
+then err_exit 'alias not working after unalias in subshell'
+fi
+builtin -d rm 2> /dev/null
+if whence rm > /dev/null
+then [[ ! $(alias -t | grep rm= ) ]] && err_exit 'tracked alias not set'
+ PATH=$PATH
+ [[ $(alias -t | grep rm= ) ]] && err_exit 'tracked alias not cleared'
+fi
+if hash -r 2>/dev/null && [[ ! $(hash) ]]
+then PATH=$tmp:/bin:/usr/bin
+ for i in foo -foo --
+ do print ':' > $tmp/$i
+ chmod +x $tmp/$i
+ hash -r -- $i 2>/dev/null || err_exit "hash -r -- $i failed"
+ [[ $(hash) == $i=$tmp/$i ]] || err_exit "hash -r -- $i failed, expected $i=$tmp/$i, got $(hash)"
+ done
+else err_exit 'hash -r failed'
+fi
+( alias :pr=print) 2> /dev/null || err_exit 'alias beginning with : fails'
+( alias p:r=print) 2> /dev/null || err_exit 'alias with : in name fails'
+
+unalias no_such_alias && err_exit 'unalias should return non-zero for unknown alias'
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/append.sh b/src/cmd/ksh93/tests/append.sh
new file mode 100755
index 0000000..80a7f25
--- /dev/null
+++ b/src/cmd/ksh93/tests/append.sh
@@ -0,0 +1,86 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+{
+x=abc
+x+=def ;} 2> /dev/null
+if [[ $x != abcdef ]]
+then err_exit 'abc+def != abcdef'
+fi
+integer i=3
+{ i+=4;} 2> /dev/null
+if (( i != 7 ))
+then err_exit '3+4!=7'
+fi
+iarray=( one two three )
+{ iarray+= (four five six) ;} 2> /dev/null
+if [[ ${iarray[@]} != 'one two three four five six' ]]
+then err_exit 'index array append fails'
+fi
+unset iarray
+iarray=one
+{ iarray+= (four five six) ;} 2> /dev/null
+if [[ ${iarray[@]} != 'one four five six' ]]
+then err_exit 'index array append to scalar fails'
+fi
+typeset -A aarray
+aarray=( [1]=1 [3]=4 [xyz]=xyz )
+aarray+=( [2]=2 [3]=3 [foo]=bar )
+if [[ ${aarray[3]} != 3 ]]
+then err_exit 'associative array append fails'
+fi
+if [[ ${#aarray[@]} != 5 ]]
+then err_exit 'number of elements of associative array append fails'
+fi
+point=(x=1 y=2)
+point+=( y=3 z=4)
+if [[ ${point.y} != 3 ]]
+then err_exit 'compound append fails'
+fi
+if [[ ${point.x} != 1 ]]
+then err_exit 'compound append to compound variable unsets existing variables'
+fi
+unset foo
+foo=one
+foo+=(two)
+if [[ ${foo[@]} != 'one two' ]]
+then err_exit 'array append to non array variable fails'
+fi
+unset foo
+foo[0]=(x=3)
+foo+=(x=4)
+[[ ${foo[1].x} == 4 ]] || err_exit 'compound append to index array not working'
+[[ ${foo[0].x} == 3 ]] || err_exit 'compound append to index array unsets existing variables'
+
+unset foo
+foo=a
+foo+=''
+[[ $foo == 'a' ]] || err_exit 'appending an empty string not working'
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/arith.sh b/src/cmd/ksh93/tests/arith.sh
new file mode 100755
index 0000000..4d48ac2
--- /dev/null
+++ b/src/cmd/ksh93/tests/arith.sh
@@ -0,0 +1,737 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2012 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+trap '' FPE # NOTE: osf.alpha requires this (no ieee math)
+
+integer x=1 y=2 z=3
+if (( 2+2 != 4 ))
+then err_exit 2+2!=4
+fi
+if ((x+y!=z))
+then err_exit x+y!=z
+fi
+if (($x+$y!=$z))
+then err_exit $x+$y!=$z
+fi
+if (((x|y)!=z))
+then err_exit "(x|y)!=z"
+fi
+if ((y >= z))
+then err_exit "y>=z"
+fi
+if ((y+3 != z+2))
+then err_exit "y+3!=z+2"
+fi
+if ((y<<2 != 1<<3))
+then err_exit "y<<2!=1<<3"
+fi
+if ((133%10 != 3))
+then err_exit "133%10!=3"
+ if (( 2.5 != 2.5 ))
+ then err_exit 2.5!=2.5
+ fi
+fi
+d=0
+((d || 1)) || err_exit 'd=0; ((d||1))'
+if (( d++!=0))
+then err_exit "d++!=0"
+fi
+if (( --d!=0))
+then err_exit "--d!=0"
+fi
+if (( (d++,6)!=6 && d!=1))
+then err_exit '(d++,6)!=6 && d!=1'
+fi
+d=0
+if (( (1?2+1:3*4+d++)!=3 || d!=0))
+then err_exit '(1?2+1:3*4+d++) !=3'
+fi
+for ((i=0; i < 20; i++))
+do :
+done
+if (( i != 20))
+then err_exit 'for (( expr)) failed'
+fi
+for ((i=0; i < 20; i++)); do : ; done
+if (( i != 20))
+then err_exit 'for (( expr));... failed'
+fi
+for ((i=0; i < 20; i++)) do : ; done
+if (( i != 20))
+then err_exit 'for (( expr))... failed'
+fi
+if (( (i?0:1) ))
+then err_exit '(( (i?0:1) )) failed'
+fi
+if (( (1 || 1 && 0) != 1 ))
+then err_exit '( (1 || 1 && 0) != 1) failed'
+fi
+if (( (_=1)+(_x=0)-_ ))
+then err_exit '(_=1)+(_x=0)-_ failed'
+fi
+if (( (3^6) != 5))
+then err_exit '((3^6) != 5) failed'
+fi
+integer x=1
+if (( (x=-x) != -1 ))
+then err_exit '(x=-x) != -1 failed'
+fi
+i=2
+if (( 1$(($i))3 != 123 ))
+then err_exit ' 1$(($i))3 failed'
+fi
+((pi=4*atan(1.)))
+point=(
+ float x
+ float y
+)
+(( point.x = cos(pi/6), point.y = sin(pi/6) ))
+if (( point.x*point.x + point.y*point.y > 1.01 ))
+then err_exit 'cos*cos +sin*sin > 1.01'
+fi
+if (( point.x*point.x + point.y*point.y < .99 ))
+then err_exit 'cos*cos +sin*sin < .99'
+fi
+if [[ $((y=x=1.5)) != 1 ]]
+then err_exit 'typecast not working in arithmetic evaluation'
+fi
+typeset -E x=1.5
+( ((x++)) ) 2>/dev/null
+if [[ $? == 0 ]]
+then err_exit 'postincrement of floating point allowed'
+fi
+( ((++x)) ) 2>/dev/null
+if [[ $? == 0 ]]
+then err_exit 'preincrement of floating point allowed'
+fi
+x=1.5
+( ((x%1.1)) ) 2>/dev/null
+if [[ $? == 0 ]]
+then err_exit 'floating point allowed with % operator'
+fi
+x=.125
+if [[ $(( 4 * x/2 )) != 0.25 ]]
+then err_exit '(( 4 * x/2 )) is not 0.25, with x=.125'
+fi
+if [[ $(( pow(2,3) )) != 8 ]]
+then err_exit '$(( pow(2,3) )) != 8'
+fi
+( [[ $(( pow(2,(3)) )) == 8 ]] ) 2> /dev/null
+if (( $? ))
+then err_exit '$(( pow(2,(3)) )) != 8'
+fi
+unset x
+integer x=1; integer x=1
+if [[ $x != 1 ]]
+then err_exit 'two consecutive integer x=1 not working'
+fi
+unset z
+{ z=$(typeset -RZ2 z2; (( z2 = 8 )); print $z2) ;} 2>/dev/null
+if [[ $z != "08" ]]
+then err_exit "typeset -RZ2 leading 0 decimal not working [z=$z]"
+fi
+{ z=$(typeset -RZ3 z3; (( z3 = 8 )); print $z3) ;} 2>/dev/null
+if [[ $z != "008" ]]
+then err_exit "typeset -RZ3 leading 0 decimal not working [z=$z]"
+fi
+unset z
+typeset -Z3 z=010
+(( z=z+1))
+if [[ $z != 011 ]]
+then err_exit "leading 0's in -Z not treated as decimal"
+fi
+unset x
+integer x=0
+if [[ $((x+=1)) != 1 ]] || ((x!=1))
+then err_exit "+= not working"
+ x=1
+fi
+x=1
+if [[ $((x*=5)) != 5 ]] || ((x!=5))
+then err_exit "*= not working"
+ x=5
+fi
+if [[ $((x%=4)) != 1 ]] || ((x!=1))
+then err_exit "%= not working"
+ x=1
+fi
+if [[ $((x|=6)) != 7 ]] || ((x!=7))
+then err_exit "|= not working"
+ x=7
+fi
+if [[ $((x&=5)) != 5 ]] || ((x!=5))
+then err_exit "&= not working"
+ x=5
+fi
+function newscope
+{
+ float x=1.5
+ (( x += 1 ))
+ print -r -- $x
+}
+if [[ $(newscope) != 2.5 ]]
+then err_exit "arithmetic using wrong scope"
+fi
+unset x
+integer y[3]=9 y[4]=2 i=3
+(( x = y[3] + y[4] ))
+if [[ $x != 11 ]]
+then err_exit "constant index array arithmetic failure"
+fi
+(( x = $empty y[3] + y[4] ))
+if [[ $x != 11 ]]
+then err_exit "empty constant index array arithmetic failure"
+fi
+(( x = y[i] + y[i+1] ))
+if [[ $x != 11 ]]
+then err_exit "variable subscript index array arithmetic failure"
+fi
+integer a[5]=3 a[2]=4
+(( x = y[a[5]] + y[a[2]] ))
+if [[ $x != 11 ]]
+then err_exit "nested subscript index array arithmetic failure"
+fi
+unset y
+typeset -Ai y
+y[three]=9 y[four]=2
+three=four
+four=three
+(( x = y[three] + y[four] ))
+if [[ $x != 11 ]]
+then err_exit "constant associative array arithmetic failure"
+fi
+(( x = y[$three] + y[$four] ))
+if [[ $x != 11 ]]
+then err_exit "variable subscript associative array arithmetic failure"
+fi
+$SHELL -nc '((a = 1))' 2> /dev/null || err_exit "sh -n fails with arithmetic"
+$SHELL -nc '((a.b++))' 2> /dev/null || err_exit "sh -n fails with arithmetic2"
+unset z
+float z=7.5
+if { (( z%2 != 1));} 2> /dev/null
+then err_exit '% not working on floating point'
+fi
+chr=(a ' ' '=' '\r' '\n' '\\' '\"' '$' "\\'" '[' ']' '(' ')' '<' '\xab' '\040' '`' '{' '}' '*' '\E')
+if (('a' == 97))
+then val=(97 32 61 13 10 92 34 36 39 91 93 40 41 60 171 32 96 123 125 42 27)
+else val=(129 64 126 13 21 224 127 91 125 173 189 77 93 76 171 32 121 192 208 92 39 21)
+fi
+q=0
+for ((i=0; i < ${#chr[@]}; i++))
+do if (( '${chr[i]}' != ${val[i]} ))
+ then err_exit "(( '${chr[i]}' != ${val[i]} ))"
+ fi
+ if [[ $(( '${chr[i]}' )) != ${val[i]} ]]
+ then err_exit "(( '${chr[i]}' )) != ${val[i]}"
+ fi
+ if [[ $(( L'${chr[i]}' )) != ${val[i]} ]]
+ then err_exit "(( '${chr[i]}' )) != ${val[i]}"
+ fi
+ if eval '((' "'${chr[i]}'" != ${val[i]} '))'
+ then err_exit "eval (( '${chr[i]}' != ${val[i]} ))"
+ fi
+ if eval '((' "'${chr[i]}'" != ${val[i]} ' + $q ))'
+ then err_exit "eval (( '${chr[i]}' != ${val[i]} ))"
+ fi
+done
+unset x
+typeset -ui x=4294967293
+[[ $x != 4294967293 ]] && err_exit "unsigned integers not working"
+x=32767
+x=x+1
+[[ $x != 32768 ]] && err_exit "unsigned integer addition not working"
+unset x
+float x=99999999999999999999999999
+if (( x < 1e20 ))
+then err_exit 'large integer constants not working'
+fi
+unset x y
+function foobar
+{
+ nameref x=$1
+ (( x +=1 ))
+ print $x
+}
+x=0 y=4
+if [[ $(foobar y) != 5 ]]
+then err_exit 'name references in arithmetic statements in functions broken'
+fi
+if (( 2**3 != pow(2,3) ))
+then err_exit '2**3 not working'
+fi
+if (( 2**3*2 != pow(2,3)*2 ))
+then err_exit '2**3*2 not working'
+fi
+if (( 4**3**2 != pow(4,pow(3,2)) ))
+then err_exit '4**3**2 not working'
+fi
+if (( (4**3)**2 != pow(pow(4,3),2) ))
+then err_exit '(4**3)**2 not working'
+fi
+typeset -Z3 x=11
+typeset -i x
+if (( x != 11 ))
+then err_exit '-Z3 not treated as decimal'
+fi
+unset x
+typeset -ui x=-1
+(( x >= 0 )) || err_exit 'unsigned integer not working'
+(( $x >= 0 )) || err_exit 'unsigned integer not working as $x'
+unset x
+typeset -ui42 x=50
+if [[ $x != 42#18 ]]
+then err_exit 'display of unsigned integers in non-decimal bases wrong'
+fi
+$SHELL -c 'i=0;(( ofiles[i] != -1 && (ofiles[i] < mins || mins == -1) ));exit 0' 2> /dev/null || err_exit 'lexical error with arithemtic expression'
+$SHELL -c '(( +1 == 1))' 2> /dev/null || err_exit 'unary + not working'
+typeset -E20 val=123.01234567890
+[[ $val == 123.0123456789 ]] || err_exit "rounding error val=$val"
+if [[ $(print x$((10))=foo) != x10=foo ]]
+then err_exit 'parsing error with x$((10))=foo'
+fi
+$SHELL -c 'typeset x$((10))=foo' 2> /dev/null || err_exit 'typeset x$((10)) parse error'
+unset x
+x=$(( exp(log(2.0)) ))
+(( x > 1.999 && x < 2.001 )) || err_exit 'composite functions not working'
+unset x y n
+typeset -Z8 x=0 y=0
+integer n
+for (( n=0; n < 20; n++ ))
+do let "x = $x+1"
+ (( y = $y+1 ))
+done
+(( x == n )) || err_exit 'let with zero filled fields not working'
+(( y == n )) || err_exit '((...)) with zero filled fields not working'
+typeset -RZ3 x=10
+[[ $(($x)) == 10 && $((1$x)) == 1010 ]] || err_exit 'zero filled fields not preserving leading zeros'
+unset y
+[[ $(let y=$x;print $y) == 10 && $(let y=1$x;print $y) == 1010 ]] || err_exit 'zero filled fields not preserving leading zeros with let'
+unset i ip ipx
+typeset -i hex=( 172 30 18 1)
+typeset -ui ip=0 ipx=0
+integer i
+for ((i=0; i < 4; i++))
+do (( ip = (ip<<8) | hex[i]))
+done
+for ((i=0; i < 4; i++))
+do (( ipx = ip % 256 ))
+ (( ip /= 256 ))
+ (( ipx != hex[3-i] )) && err_exit "hex digit $((3-i)) not correct"
+done
+unset x
+x=010
+(( x == 10 )) || err_exit 'leading zeros in x treated as octal arithmetic with $((x))'
+(( $x == 8 )) || err_exit 'leading zeros not treated as octal arithmetic with $x'
+unset x
+typeset -Z x=010
+(( x == 10 )) || err_exit 'leading zeros not ignored for arithmetic'
+(( $x == 10 )) || err_exit 'leading zeros not ignored for arithmetic with $x'
+typeset -i i=x
+(( i == 10 )) || err_exit 'leading zeros not ignored for arithmetic assignment'
+(( ${x:0:1} == 0 )) || err_exit 'leading zero should not be stripped for x:a:b'
+c010=3
+(( c$x == 3 )) || err_exit 'leading zero with variable should not be stripped'
+[[ $( ($SHELL -c '((++1))' 2>&1) 2>/dev/null ) == *++1:* ]] || err_exit "((++1)) not generating error message"
+i=2
+(( "22" == 22 )) || err_exit "double quoted constants fail"
+(( "2$i" == 22 )) || err_exit "double quoted variables fail"
+(( "18+$i+2" == 22 )) || err_exit "double quoted expressions fail"
+# 04-04-28 bug fix
+unset i; typeset -i i=01-2
+(( i == -1 )) || err_exit "01-2 is not -1"
+
+cat > $tmp/script <<-\!
+tests=$*
+typeset -A blop
+function blop.get
+{
+ .sh.value=777
+}
+function mkobj
+{
+ nameref obj=$1
+ obj=()
+ [[ $tests == *1* ]] && {
+ (( obj.foo = 1 ))
+ (( obj.bar = 2 ))
+ (( obj.baz = obj.foo + obj.bar )) # ok
+ echo $obj
+ }
+ [[ $tests == *2* ]] && {
+ (( obj.faz = faz = obj.foo + obj.bar )) # ok
+ echo $obj
+ }
+ [[ $tests == *3* ]] && {
+ # case 3, 'active' variable involved, w/ intermediate variable
+ (( obj.foz = foz = ${blop[1]} )) # coredump
+ echo $obj
+ }
+ [[ $tests == *4* ]] && {
+ # case 4, 'active' variable, in two steps
+ (( foz = ${blop[1]} )) # ok
+ (( obj.foz = foz )) # ok
+ echo $obj
+ }
+ [[ $tests == *5* ]] && {
+ # case 5, 'active' variable involved, w/o intermediate variable
+ (( obj.fuz = ${blop[1]} )) # coredump
+ echo $obj
+ }
+ [[ $tests == *6* ]] && {
+ echo $(( obj.baz = obj.foo + obj.bar )) # coredump
+ }
+ [[ $tests == *7* ]] && {
+ echo $(( obj.foo + obj.bar )) # coredump
+ }
+}
+mkobj bla
+!
+chmod +x $tmp/script
+[[ $($tmp/script 1) != '( bar=2 baz=3 foo=1 )' ]] 2>/dev/null && err_exit 'compound var arithmetic failed'
+[[ $($tmp/script 2) != '( faz=0 )' ]] 2>/dev/null && err_exit 'compound var arithmetic failed'
+[[ $($tmp/script 3) != '( foz=777 )' ]] 2>/dev/null && err_exit 'compound var arithmetic failed'
+[[ $($tmp/script 4) != '( foz=777 )' ]] 2>/dev/null && err_exit 'compound var arithmetic failed'
+[[ $($tmp/script 5) != '( fuz=777 )' ]] 2>/dev/null && err_exit 'compound var arithmetic failed'
+[[ $($tmp/script 6) != '0' ]] 2>/dev/null && err_exit 'compound var arithmetic failed'
+[[ $($tmp/script 7) != '0' ]] 2>/dev/null && err_exit 'compound var arithmetic failed'
+unset foo
+typeset -F1 foo=123456789.19
+[[ $foo == 123456789.2 ]] || err_exit 'typeset -F1 not working correctly'
+
+# divide by zero
+
+for expr in '1/(1/2)' '8%(1/2)' '8%(1.0/2)'
+do [[ $( ( $SHELL -c "( (($expr)) ) || print ok" ) 2>/dev/null ) == ok ]] || err_exit "divide by zero not trapped: $expr"
+done
+
+for expr in '1/(1.0/2)' '1/(1/2.0)'
+do [[ $( ( $SHELL -c "( print -r -- \$(($expr)) )" ) 2>/dev/null ) == 2 ]] || err_exit "invalid value for: $expr"
+done
+[[ $((5||0)) == 1 ]] || err_exit '$((5||0))'" == $((5||0)) should be 1"
+$SHELL -c 'integer x=3 y=2; (( (y += x += 2) == 7 && x==5))' 2> /dev/null || err_exit '((y += x += 2)) not working'
+$SHELL -c 'b=0; [[ $((b?a=1:b=9)) == 9 ]]' 2> /dev/null || err_exit 'b?a=1:b=9 not working'
+unset x
+(( x = 4*atan(1.0) ))
+[[ $x == "$((x))" ]] || err_exit '$x !- $((x)) when x is pi'
+$SHELL -c "[[ ${x//./} == {14,100}(\d) ]]" 2> /dev/null || err_exit 'pi has less than 14 significant places'
+if (( Inf+1 == Inf ))
+then set \
+ Inf inf \
+ -Inf -inf \
+ Nan nan \
+ -Nan -nan \
+ 1.0/0.0 inf
+ while (( $# >= 2 ))
+ do x=$(printf "%g\n" $(($1)))
+ [[ $x == $2 ]] || err_exit "printf '%g\\n' \$(($1)) failed -- expected $2, got $x"
+ x=$(printf "%g\n" $1)
+ [[ $x == $2 ]] || err_exit "printf '%g\\n' $1 failed -- expected $2, got $x"
+ x=$(printf -- $(($1)))
+ [[ $x == $2 ]] || err_exit "print -- \$(($1)) failed -- expected $2, got $x"
+ shift 2
+ done
+ (( 1.0/0.0 == Inf )) || err_exit '1.0/0.0 != Inf'
+ [[ $(print -- $((0.0/0.0))) == ?(-)nan ]] || err_exit '0.0/0.0 != NaN'
+ (( Inf*Inf == Inf )) || err_exit 'Inf*Inf != Inf'
+ (( NaN != NaN )) || err_exit 'NaN == NaN'
+ (( -5*Inf == -Inf )) || err_exit '-5*Inf != -Inf'
+ [[ $(print -- $((sqrt(-1.0)))) == ?(-)nan ]]|| err_exit 'sqrt(-1.0) != NaN'
+ (( pow(1.0,Inf) == 1.0 )) || err_exit 'pow(1.0,Inf) != 1.0'
+ (( pow(Inf,0.0) == 1.0 )) || err_exit 'pow(Inf,0.0) != 1.0'
+ [[ $(print -- $((NaN/Inf))) == ?(-)nan ]] || err_exit 'NaN/Inf != NaN'
+ (( 4.0/Inf == 0.0 )) || err_exit '4.0/Inf != 0.0'
+else err_exit 'Inf and NaN not working'
+fi
+unset x y n r
+n=14.555
+float x=$n y
+y=$(printf "%a" x)
+r=$y
+[[ $r == $n ]] || err_exit "output of printf %a not self preserving -- expected $x, got $y"
+unset x y r
+x=-0
+y=$(printf "%g %g %g %g %g %g\n" -0. -0 $((-0)) x $x $((x)))
+r="-0 -0 -0 -0 -0 -0"
+[[ $y == "$r" ]] || err_exit "-0 vs -0.0 inconsistency -- expected '$r', got '$y'"
+$SHELL -c '(( x=));:' 2> /dev/null && err_exit '((x=)) should be an error'
+$SHELL -c '(( x+=));:' 2> /dev/null && err_exit '((x+=)) should be an error'
+$SHELL -c '(( x=+));:' 2> /dev/null && err_exit '((x=+)) should be an error'
+$SHELL -c 'x=();x.arr[0]=(z=3); ((x.arr[0].z=2))' 2> /dev/null || err_exit '(((x.arr[0].z=2)) should not be an error'
+
+float t
+typeset a b r
+v="-0.0 0.0 +0.0 -1.0 1.0 +1.0"
+for a in $v
+do for b in $v
+ do (( r = copysign(a,b) ))
+ (( t = copysign(a,b) ))
+ [[ $r == $t ]] || err_exit $(printf "float t=copysign(%3.1f,%3.1f) => %3.1f -- expected %3.1f\n" a b t r)
+ done
+done
+
+typeset -l y y_ascii
+(( y=sin(90) ))
+y_ascii=$y
+(( y == y_ascii )) || err_exit "no match,\n\t$(printf "%a\n" y)\n!=\n\t$(printf "%a\n" y_ascii)"
+
+( $SHELL <<- \EOF
+ p=5
+ t[p]=6
+ while (( t[p] != 0 )) ; do
+ ((
+ p+=1 ,
+ t[p]+=2 ,
+ p+=3 ,
+ t[p]+=5 ,
+ p+=1 ,
+ t[p]+=2 ,
+ p+=1 ,
+ t[p]+=1 ,
+ p-=6 ,
+ t[p]-=1
+ ))
+ :
+ done
+EOF) 2> /dev/null || err_exit 'error with comma expression'
+
+N=(89551 89557)
+i=0 j=1
+[[ $(printf "%d" N[j]-N[i]) == 6 ]] || err_exit 'printf %d N[i]-N[j] failed'
+[[ $((N[j]-N[i])) == 6 ]] || err_exit '$((N[j]-N[i])) incorrect'
+
+unset a x
+x=0
+((a[++x]++))
+(( x==1)) || err_exit '((a[++x]++)) should only increment x once'
+(( a[1]==1)) || err_exit 'a[1] not incremented'
+unset a
+x=0
+((a[x++]++))
+(( x==1)) || err_exit '((a[x++]++)) should only increment x once'
+(( a[0]==1)) || err_exit 'a[0] not incremented'
+unset a
+x=0
+((a[x+=2]+=1))
+(( x==2)) || err_exit '((a[x+=2]++)) should result in x==2'
+(( a[2]==1)) || err_exit 'a[0] not 1'
+
+unset a i
+typeset -a a
+i=1
+(( a[i]=1 ))
+(( a[0] == 0 )) || err_exit 'a[0] not 0'
+(( a[1] == 1 )) || err_exit 'a[1] not 1'
+
+unset a
+typeset -i a
+for ((i=0;i<1000;i++))
+do ((a[RANDOM%2]++))
+done
+(( (a[0]+a[1])==1000)) || err_exit '(a[0]+a[1])!=1000'
+
+(( 4.**3/10 == 6.4 )) || err_exit '4.**3/10!=6.4'
+(( (.5+3)/7 == .5 )) || err_exit '(.5+3)/7!==.5'
+
+function .sh.math.mysin x
+{
+ ((.sh.value = x - x**3/6. + x**5/120.-x**7/5040. + x**9/362880.))
+}
+
+(( abs(sin(.5)-mysin(.5)) < 1e-6 )) || err_exit 'mysin() not close to sin()'
+
+$SHELL 2> /dev/null <<- \EOF || err_exit "arithmetic functions defined and referenced in compound command not working"
+{
+ function .sh.math.mysin x
+ {
+ ((.sh.value = x-x**3/6. + x**5/120.-x**7/5040. + x**9/362880.))
+ }
+ (( abs(sin(.5)-mysin(.5)) < 1e-6 ))
+ exit 0
+}
+EOF
+
+
+
+function .sh.math.max x y z
+{
+ .sh.value=x
+ (( y > x )) && .sh.value=y
+ (( z > .sh.value )) && .sh.value=z
+}
+(( max(max(3,8,5),7,5)==8)) || err_exit 'max(max(3,8,5),7,5)!=8'
+(( max(max(3,8,5),7,9)==9)) || err_exit 'max(max(3,8,9),7,5)!=9'
+(( max(6,max(3,9,5),7)==9 )) || err_exit 'max(6,max(3,8,5),7)!=9'
+(( max(6,7, max(3,8,5))==8 )) || err_exit 'max(6,7,max(3,8,5))!=8'
+
+enum color_t=(red green blue yellow)
+color_t shirt pants=blue
+(( pants == blue )) || err_exit 'pants should be blue'
+(( shirt == red )) || err_exit 'pants should be red'
+(( shirt != green )) || err_exit 'shirt should not be green'
+(( pants != shirt )) || err_exit 'pants should be the same as shirt'
+(( pants = yellow ))
+(( pants == yellow )) || err_exit 'pants should be yellow'
+
+unset z
+integer -a z=( [1]=90 )
+function x
+{
+ nameref nz=$1
+ float x y
+ float x=$((log10(nz))) y=$((log10($nz)))
+ (( abs(x-y) < 1e-10 )) || err_exit '$nz and nz differs in arithmetic expression when nz is reference to array instance'
+}
+x z[1]
+
+unset x
+float x
+x=$( ($SHELL -c 'print -- $(( asinh(acosh(atanh(sin(cos(tan(atan(acos(asin(tanh(cosh(sinh(asinh(acosh(atanh(sin(cos(tan(atan(acos(asin(tanh(cosh(sinh(.5)))))))))))))))))))))))) )) ';:) 2> /dev/null)
+(( abs(x-.5) < 1.e-10 )) || err_exit 'bug in composite function evaluation'
+
+unset x
+typeset -X x=16
+{ (( $x == 16 )) ;} 2> /dev/null || err_exit 'expansions of hexfloat not working in arithmetic expansions'
+
+unset foo
+function foobar
+{
+ (( foo = 8))
+}
+typeset -i foo
+foobar
+(( foo == 8 )) || err_exit 'arithmetic assignment binding to the wrong scope'
+
+(( tgamma(4)/12 )) || err_exit 'floating point attribute for functions not preserved'
+
+unset F
+function f
+{
+ ((F=1))
+}
+f
+[[ $F == 1 ]] || err_exit 'scoping bug with arithmetic expression'
+
+F=1
+function f
+{
+ typeset F
+ ((F=2))
+}
+[[ $F == 1 ]] || err_exit 'scoping bug2 with arithmetic expression'
+
+unset play foo x z
+typeset -A play
+x=foo
+play[$x]=(x=2)
+for ((i=0; i < 2; i++))
+do (( play[$x].y , z++ ))
+done
+(( z==2 )) || err_exit 'unset compound array variable error with for loop optimization'
+
+[[ $($SHELL 2> /dev/null -c 'print -- $(( ldexp(1, 4) ))' ) == 16 ]] || err_exit 'function ldexp not implement or not working correctly'
+
+
+$SHELL 2> /dev/null -c 'str="0x1.df768ed398ee1e01329a130627ae0000p-1";typeset -l -E x;((x=str))' || err_exit '((x=var)) fails for hexfloat with var begining with 0x1.nnn'
+
+x=(3 6 12)
+(( x[2] /= x[0]))
+(( x[2] == 4 )) || err_exit '(( x[2] /= x[0])) fails for index array'
+
+x=([0]=3 [1]=6 [2]=12)
+(( x[2] /= x[0]))
+(( x[2] == 4 )) || err_exit '(( x[2] /= x[0])) fails for associative array'
+
+got=$($SHELL 2> /dev/null -c 'compound -a x;compound -a x[0].y; integer -a x[0].y[0].z; (( x[0].y[0].z[2]=3 )); typeset -p x')
+exp='typeset -C -a x=((typeset -C -a y=( [0]=(typeset -a -l -i z=([2]=3);));))'
+[[ $got == "$exp" ]] || err_exit '(( x[0].y[0].z[2]=3 )) not working'
+
+unset x
+let x=010
+[[ $x == 10 ]] || err_exit 'let treating 010 as octal'
+set -o letoctal
+let x=010
+[[ $x == 8 ]] || err_exit 'let not treating 010 as octal with letoctal on'
+
+float z=0
+integer aa=2 a=1
+typeset -A A
+A[a]=(typeset -A AA)
+A[a].AA[aa]=1
+(( z= A[a].AA[aa]++ ))
+(( z == 1 )) || err_exit "z should be 1 but is $z for associative array of
+associative array arithmetic"
+[[ ${A[a].AA[aa]} == 2 ]] || err_exit '${A[a].AA[aa]} should be 2 after ++ operation for associative array of associative array arithmetic'
+unset A[a]
+
+A[a]=(typeset -a AA)
+A[a].AA[aa]=1
+(( z += A[a].AA[aa++]++ ))
+(( z == 2 )) || err_exit "z should be 2 but is $z for associative array of
+index array arithmetic"
+(( aa == 3 )) || err_exit "subscript aa should be 3 but is $aa after ++"
+[[ ${A[a].AA[aa-1]} == 2 ]] || err_exit '${A[a].AA[aa]} should be 2 after ++ operation for ssociative array of index array arithmetic'
+unset A
+
+typeset -a A
+A[a]=(typeset -A AA)
+A[a].AA[aa]=1
+(( z += A[a].AA[aa]++ ))
+(( z == 3 )) || err_exit "z should be 3 but is $z for index array of
+associative array arithmetic"
+[[ ${A[a].AA[aa]} == 2 ]] || err_exit '${A[a].AA[aa]} should be 2 after ++ operation for index array of associative array arithmetic'
+unset A[a]
+
+A[a]=(typeset -a AA)
+A[a].AA[aa]=1
+(( z += A[a++].AA[aa++]++ ))
+(( z == 4 )) || err_exit "z should be 4 but is $z for index array of
+index array arithmetic"
+[[ ${A[a-1].AA[aa-1]} == 2 ]] || err_exit '${A[a].AA[aa]} should be 2 after ++ operation for index array of index array arithmetic'
+(( aa == 4 )) || err_exit "subscript aa should be 4 but is $aa after ++"
+(( a == 2 )) || err_exit "subscript a should be 2 but is $a after ++"
+unset A
+
+unset r x
+integer x
+r=020
+(($r == 16)) || err_exit 'leading 0 not treated as octal inside ((...))'
+x=$(($r))
+(( x == 16 )) || err_exit 'leading 0 not treated as octal inside $((...))'
+x=$r
+((x == 20 )) || err_exit 'leading 0 should not be treated as octal outside ((...))'
+print -- -020 | read x
+((x == -20)) || err_exit 'numbers with leading -0 should not be treated as octal outside ((...))'
+print -- -8#20 | read x
+((x == -16)) || err_exit 'numbers with leading -8# should be treated as octal'
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/arrays.sh b/src/cmd/ksh93/tests/arrays.sh
new file mode 100755
index 0000000..8aec386
--- /dev/null
+++ b/src/cmd/ksh93/tests/arrays.sh
@@ -0,0 +1,588 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+function fun
+{
+ integer i
+ unset xxx
+ for i in 0 1
+ do xxx[$i]=$i
+ done
+}
+
+set -A x zero one two three four 'five six'
+if [[ $x != zero ]]
+then err_exit '$x is not element 0'
+fi
+if [[ ${x[0]} != zero ]]
+then err_exit '${x[0] is not element 0'
+fi
+if (( ${#x[0]} != 4 ))
+then err_exit "length of ${x[0]} is not 4"
+fi
+if (( ${#x[@]} != 6 ))
+then err_exit 'number of elements of x is not 6'
+fi
+if [[ ${x[2]} != two ]]
+then err_exit ' element two is not 2'
+fi
+if [[ ${x[@]:2:1} != two ]]
+then err_exit ' ${x[@]:2:1} is not two'
+fi
+set -A y -- ${x[*]}
+if [[ $y != zero ]]
+then err_exit '$x is not element 0'
+fi
+if [[ ${y[0]} != zero ]]
+then err_exit '${y[0] is not element 0'
+fi
+if (( ${#y[@]} != 7 ))
+then err_exit 'number of elements of y is not 7'
+fi
+if [[ ${y[2]} != two ]]
+then err_exit ' element two is not 2'
+fi
+set +A y nine ten
+if [[ ${y[2]} != two ]]
+then err_exit ' element two is not 2'
+fi
+if [[ ${y[0]} != nine ]]
+then err_exit '${y[0] is not nine'
+fi
+unset y[4]
+if (( ${#y[@]} != 6 ))
+then err_exit 'number of elements of y is not 6'
+fi
+if (( ${#y[4]} != 0 ))
+then err_exit 'string length of unset element is not 0'
+fi
+unset foo
+if (( ${#foo[@]} != 0 ))
+then err_exit 'number of elements of unset variable foo is not 0'
+fi
+foo=''
+if (( ${#foo[0]} != 0 ))
+then err_exit 'string length of null element is not 0'
+fi
+if (( ${#foo[@]} != 1 ))
+then err_exit 'number of elements of null variable foo is not 1'
+fi
+unset foo
+foo[0]=foo
+foo[3]=bar
+unset foo[0]
+unset foo[3]
+if (( ${#foo[@]} != 0 ))
+then err_exit 'number of elements of left in variable foo is not 0'
+fi
+unset foo
+foo[3]=bar
+foo[0]=foo
+unset foo[3]
+unset foo[0]
+if (( ${#foo[@]} != 0 ))
+then err_exit 'number of elements of left in variable foo again is not 0'
+fi
+fun
+if (( ${#xxx[@]} != 2 ))
+then err_exit 'number of elements of left in variable xxx is not 2'
+fi
+fun
+if (( ${#xxx[@]} != 2 ))
+then err_exit 'number of elements of left in variable xxx again is not 2'
+fi
+set -A foo -- "${x[@]}"
+if (( ${#foo[@]} != 6 ))
+then err_exit 'number of elements of foo is not 6'
+fi
+if (( ${#PWD[@]} != 1 ))
+then err_exit 'number of elements of PWD is not 1'
+fi
+unset x
+x[2]=foo x[4]=bar
+if (( ${#x[@]} != 2 ))
+then err_exit 'number of elements of x is not 2'
+fi
+s[1]=1 c[1]=foo
+if [[ ${c[s[1]]} != foo ]]
+then err_exit 'c[1]=foo s[1]=1; ${c[s[1]]} != foo'
+fi
+unset s
+typeset -Ai s
+y=* z=[
+s[$y]=1
+s[$z]=2
+if (( ${#s[@]} != 2 ))
+then err_exit 'number of elements of is not 2'
+fi
+(( s[$z] = s[$z] + ${s[$y]} ))
+if [[ ${s[$z]} != 3 ]]
+then err_exit '[[ ${s[$z]} != 3 ]]'
+fi
+if (( s[$z] != 3 ))
+then err_exit '(( s[$z] != 3 ))'
+fi
+(( s[$y] = s[$y] + ${s[$z]} ))
+if [[ ${s[$y]} != 4 ]]
+then err_exit '[[ ${s[$y]} != 4 ]]'
+fi
+if (( s[$y] != 4 ))
+then err_exit '(( s[$y] != 4 ))'
+fi
+set -A y 2 4 6
+typeset -i y
+z=${y[@]}
+typeset -R12 y
+typeset -i y
+if [[ ${y[@]} != "$z" ]]
+then err_exit 'error in array conversion from int to R12'
+fi
+if (( ${#y[@]} != 3 ))
+then err_exit 'error in count of array conversion from int to R12'
+fi
+unset abcdefg
+: ${abcdefg[1]}
+set | grep '^abcdefg$' >/dev/null && err_exit 'empty array variable in set list'
+unset x y
+x=1
+typeset -i y[$x]=4
+if [[ ${y[1]} != 4 ]]
+then err_exit 'arithmetic expressions in typeset not working'
+fi
+unset foo
+typeset foo=bar
+typeset -A foo
+if [[ ${foo[0]} != bar ]]
+then err_exit 'initial value not preserved when typecast to associative'
+fi
+unset foo
+foo=(one two)
+typeset -A foo
+foo[two]=3
+if [[ ${#foo[*]} != 3 ]]
+then err_exit 'conversion of indexed to associative array failed'
+fi
+set a b c d e f g h i j k l m
+if [[ ${#} != 13 ]]
+then err_exit '${#} not 13'
+fi
+unset xxx
+xxx=foo
+if [[ ${!xxx[@]} != 0 ]]
+then err_exit '${!xxx[@]} for scalar not 0'
+fi
+if [[ ${11} != k ]]
+then err_exit '${11} not working'
+fi
+if [[ ${@:4:1} != d ]]
+then err_exit '${@:4:1} not working'
+fi
+foovar1=abc
+foovar2=def
+if [[ ${!foovar@} != +(foovar[[:alnum:]]?([ ])) ]]
+then err_exit '${!foovar@} does not expand correctly'
+fi
+if [[ ${!foovar1} != foovar1 ]]
+then err_exit '${!foovar1} != foovar1'
+fi
+unset xxx
+: ${xxx[3]}
+if [[ ${!xxx[@]} ]]
+then err_exit '${!xxx[@]} should be null'
+fi
+integer i=0
+{
+ set -x
+ xxx[++i]=1
+ set +x
+} 2> /dev/null
+if (( i != 1))
+then err_exit 'execution trace side effects with array subscripts'
+fi
+unset list
+: $(set -A list foo bar)
+if (( ${#list[@]} != 0))
+then err_exit '$(set -A list ...) leaves side effects'
+fi
+unset list
+list= (foo bar bam)
+( set -A list one two three four)
+if [[ ${list[1]} != bar ]]
+then err_exit 'array not restored after subshell'
+fi
+XPATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:.:/sbin:/usr/sbin
+xpath=( $( IFS=: ; echo $XPATH ) )
+if [[ $(print -r "${xpath[@]##*/}") != 'bin bin ucb bin . sbin sbin' ]]
+then err_exit '${xpath[@]##*/} not applied to each element'
+fi
+foo=( zero one '' three four '' six)
+integer n=-1
+if [[ ${foo[@]:n} != six ]]
+then err_exit 'array offset of -1 not working'
+fi
+if [[ ${foo[@]: -3:1} != four ]]
+then err_exit 'array offset of -3:1 not working'
+fi
+$SHELL -c 'x=(if then else fi)' 2> /dev/null || err_exit 'reserved words in x=() assignment not working'
+unset foo
+foo=one
+foo=( $foo two)
+if [[ ${#foo[@]} != 2 ]]
+then err_exit 'array getting unset before right hand side evaluation'
+fi
+foo=(143 3643 38732)
+export foo
+typeset -i foo
+if [[ $($SHELL -c 'print $foo') != 143 ]]
+then err_exit 'exporting indexed array not exporting 0-th element'
+fi
+( $SHELL -c '
+ unset foo
+ typeset -A foo=([0]=143 [1]=3643 [2]=38732)
+ export foo
+ typeset -i foo
+ [[ $($SHELL -c "print $foo") == 143 ]]'
+) 2> /dev/null ||
+ err_exit 'exporting associative array not exporting 0-th element'
+unset foo
+typeset -A foo
+foo[$((10))]=ok 2> /dev/null || err_exit 'arithmetic expression as subscript not working'
+unset foo
+typeset -A foo
+integer foo=0
+[[ $foo == 0 ]] || err_exit 'zero element of associative array not being set'
+unset foo
+typeset -A foo=( [two]=1)
+for i in one three four five
+do : ${foo[$i]}
+done
+if [[ ${!foo[@]} != two ]]
+then err_exit 'error in subscript names'
+fi
+unset x
+x=( 1 2 3)
+(x[1]=8)
+[[ ${x[1]} == 2 ]] || err_exit 'index array produce side effects in subshells'
+x=( 1 2 3)
+(
+ x+=(8)
+ [[ ${#x[@]} == 4 ]] || err_exit 'index array append in subshell error'
+)
+[[ ${#x[@]} == 3 ]] || err_exit 'index array append in subshell effects parent'
+x=( [one]=1 [two]=2 [three]=3)
+(x[two]=8)
+[[ ${x[two]} == 2 ]] || err_exit 'associative array produce side effects in subshells'
+unset x
+x=( [one]=1 [two]=2 [three]=3)
+(
+ x+=( [four]=4 )
+ [[ ${#x[@]} == 4 ]] || err_exit 'associative array append in subshell error'
+)
+[[ ${#x[@]} == 3 ]] || err_exit 'associative array append in subshell effects parent'
+unset x
+integer i
+for ((i=0; i < 40; i++))
+do x[i]=$i
+done
+[[ ${#x[@]} == 40 ]] || err_exit 'index arrays loosing values'
+[[ $( ($SHELL -c 'typeset -A var; (IFS=: ; set -A var a:b:c ;print ${var[@]});:' )2>/dev/null) == 'a b c' ]] || err_exit 'change associative to index failed'
+unset foo
+[[ $(foo=good
+for ((i=0; i < 2; i++))
+do [[ ${foo[i]} ]] && print ok
+done) == ok ]] || err_exit 'invalid optimization for subscripted variables'
+(
+x=([foo]=bar)
+set +A x bam
+) 2> /dev/null && err_exit 'set +A with associative array should be an error'
+unset bam foo
+foo=0
+typeset -A bam
+unset bam[foo]
+bam[foo]=value
+[[ $bam == value ]] && err_exit 'unset associative array element error'
+: only first element of an array can be exported
+unset bam
+print 'print ${var[0]} ${var[1]}' > $tmp/script
+chmod +x $tmp/script
+[[ $($SHELL -c "var=(foo bar);export var;$tmp/script") == foo ]] || err_exit 'export array not exporting just first element'
+
+unset foo
+set --allexport
+foo=one
+foo[1]=two
+foo[0]=three
+[[ $foo == three ]] || err_exit '--allexport not working with arrays'
+set --noallexport
+unset foo
+
+cat > $tmp/script <<- \!
+ typeset -A foo
+ print foo${foo[abc]}
+!
+[[ $($SHELL -c "typeset -A foo;$tmp/script") == foo ]] 2> /dev/null || err_exit 'empty associative arrays not being cleared correctly before scripts'
+[[ $($SHELL -c "typeset -A foo;foo[abc]=abc;$tmp/script") == foo ]] 2> /dev/null || err_exit 'associative arrays not being cleared correctly before scripts'
+unset foo
+foo=(one two)
+[[ ${foo[@]:1} == two ]] || err_exit '${foo[@]:1} == two'
+[[ ! ${foo[@]:2} ]] || err_exit '${foo[@]:2} not null'
+unset foo
+foo=one
+[[ ! ${foo[@]:1} ]] || err_exit '${foo[@]:1} not null'
+function EMPTY
+{
+ typeset i
+ typeset -n ARRAY=$1
+ for i in ${!ARRAY[@]}
+ do unset ARRAY[$i]
+ done
+}
+unset foo
+typeset -A foo
+foo[bar]=bam
+foo[x]=y
+EMPTY foo
+[[ $(typeset | grep foo$) == *associative* ]] || err_exit 'array lost associative attribute'
+[[ ! ${foo[@]} ]] || err_exit 'array not empty'
+[[ ! ${!foo[@]} ]] || err_exit 'array names not empty'
+unset foo
+foo=bar
+set -- "${foo[@]:1}"
+(( $# == 0 )) || err_exit '${foo[@]:1} should not have any values'
+unset bar
+exp=4
+: ${_foo[bar=4]}
+(( bar == 4 )) || err_exit "subscript of unset variable not evaluated -- expected '4', got '$got'"
+unset bar
+: ${_foo[bar=$exp]}
+(( bar == $exp )) || err_exit "subscript of unset variable not evaluated -- expected '$exp', got '$got'"
+unset foo bar
+foo[5]=4
+bar[4]=3
+bar[0]=foo
+foo[0]=bam
+foo[4]=5
+[[ ${!foo[2+2]} == 'foo[4]' ]] || err_exit '${!var[sub]} should be var[sub]'
+[[ ${bar[${foo[5]}]} == 3 ]] || err_exit 'array subscript cannot be an array instance'
+[[ $bar[4] == 3 ]] || err_exit '$bar[x] != ${bar[x]} inside [[ ]]'
+(( $bar[4] == 3 )) || err_exit '$bar[x] != ${bar[x]} inside (( ))'
+[[ $bar[$foo[5]] == 3 ]] || err_exit '$bar[foo[x]] != ${bar[foo[x]]} inside [[ ]]'
+(( $bar[$foo[5]] == 3 )) || err_exit '$bar[foo[x]] != ${bar[foo[x]]} inside (( ))'
+x=$bar[4]
+[[ $x == 4 ]] && err_exit '$bar[4] should not be an array in an assignment'
+x=${bar[$foo[5]]}
+(( $x == 3 )) || err_exit '${bar[$foo[sub]]} not working'
+[[ $($SHELL <<- \++EOF+++
+ typeset -i test_variable=0
+ typeset -A test_array
+ test_array[1]=100
+ read test_array[2] <<-!
+ 2
+ !
+ read test_array[3] <<-!
+ 3
+ !
+ test_array[3]=4
+ print "val=${test_array[3]}"
+++EOF+++
+) == val=4 ]] 2> /dev/null || err_exit 'after reading array[j] and assign array[j] fails'
+[[ $($SHELL <<- \+++EOF+++
+ pastebin=( typeset -a form)
+ pastebin.form+=( name="name" data="clueless" )
+ print -r -- ${pastebin.form[0].name}
++++EOF+++
+) == name ]] 2> /dev/null || err_exit 'indexed array in compound variable not working'
+unset foo bar
+: ${foo[bar=2]}
+[[ $bar == 2 ]] || err_exit 'subscript not evaluated for unset variable'
+unset foo bar
+bar=1
+typeset -a foo=([1]=ok [2]=no)
+[[ $foo[bar] == ok ]] || err_exit 'typeset -a not working for simple assignment'
+unset foo
+typeset -a foo=([1]=(x=ok) [2]=(x=no))
+[[ $(typeset | grep 'foo$') == *index* ]] || err_exit 'typeset -a not creating an indexed array'
+foo+=([5]=good)
+[[ $(typeset | grep 'foo$') == *index* ]] || err_exit 'append to indexed array not preserving array type'
+unset foo
+typeset -A foo=([1]=ok [2]=no)
+[[ $foo[bar] == ok ]] && err_exit 'typeset -A not working for simple assignment'
+unset foo
+typeset -A foo=([1]=(x=ok) [2]=(x=no))
+[[ ${foo[bar].x} == ok ]] && err_exit 'typeset -A not working for compound assignment'
+[[ $($SHELL -c 'typeset -a foo;typeset | grep "foo$"' 2> /dev/null) == *index* ]] || err_exit 'typeset fails for indexed array with no elements'
+xxxxx=(one)
+[[ $(typeset | grep xxxxx$) == *'indexed array'* ]] || err_exit 'array of one element not an indexed array'
+unset foo
+foo[1]=(x=3 y=4)
+{ [[ ${!foo[1].*} == 'foo[1].x foo[1].y' ]] ;} 2> /dev/null || err_exit '${!foo[sub].*} not expanding correctly'
+unset x
+x=( typeset -a foo=( [0]="a" [1]="b" [2]="c" ))
+[[ ${@x.foo} == 'typeset -a'* ]] || err_exit 'x.foo is not an indexed array'
+x=( typeset -A foo=( [0]="a" [1]="b" [2]="c" ))
+[[ ${@x.foo} == 'typeset -A'* ]] || err_exit 'x.foo is not an associative array'
+$SHELL -c $'x=(foo\n\tbar\nbam\n)' 2> /dev/null || err_exit 'compound array assignment with new-lines not working'
+$SHELL -c $'x=(foo\n\tbar:\nbam\n)' 2> /dev/null || err_exit 'compound array assignment with labels not working'
+$SHELL -c $'x=(foo\n\tdone\nbam\n)' 2> /dev/null || err_exit 'compound array assignment with reserved words not working'
+[[ $($SHELL -c 'typeset -A A; print $(( A[foo].bar ))' 2> /dev/null) == 0 ]] || err_exit 'unset variable not evaluating to 0'
+unset a
+typeset -A a
+a[a].z=1
+a[z].z=2
+unset a[a]
+[[ ${!a[@]} == z ]] || err_exit '"unset a[a]" unsets entire array'
+unset a
+a=([x]=1 [y]=2 [z]=(foo=3 bar=4))
+eval "b=$(printf "%B\n" a)"
+eval "c=$(printf "%#B\n" a)"
+[[ ${a[*]} == "${b[*]}" ]] || err_exit 'printf %B not preserving values for arrays'
+[[ ${a[*]} == "${c[*]}" ]] || err_exit 'printf %#B not preserving values for arrays'
+unset a
+a=(zero one two three four)
+a[6]=six
+[[ ${a[-1]} == six ]] || err_exit 'a[-1] should be six'
+[[ ${a[-3]} == four ]] || err_exit 'a[-3] should be four'
+[[ ${a[-3..-1]} == 'four six' ]] || err_exit "a[-3,-1] should be 'four six'"
+
+FILTER=(typeset scope)
+FILTER[0].scope=include
+FILTER[1].scope=exclude
+[[ ${#FILTER[@]} == 2 ]] || err_exit "FILTER array should have two elements not ${#FILTER[@]}"
+
+unset x
+function x.get
+{
+ print sub=${.sh.subscript}
+}
+x[2]=
+z=$(: ${x[1]} )
+[[ $z == sub=1 ]] || err_exit 'get function not invoked for index array'
+
+unset x
+typeset -A x
+function x.get
+{
+ print sub=${.sh.subscript}
+}
+x[2]=
+z=$(: ${x[1]} )
+[[ $z == sub=1 ]] || err_exit 'get function not invoked for associative array'
+
+unset y
+i=1
+a=(11 22)
+typeset -m y=a[i]
+[[ $y == 22 ]] || err_exit 'typeset -m for index array not working'
+[[ ${a[i]} || ${a[0]} != 11 ]] && err_exit 'typeset -m for index array not deleting element'
+
+unset y
+a=([0]=11 [1]=22)
+typeset -m y=a[$i]
+[[ $y == 22 ]] || err_exit 'typeset -m for associative array not working'
+[[ ${a[$i]} || ${a[0]} != 11 ]] && err_exit 'typeset -m for associative array not deleting element'
+unset x a j
+
+typeset -a a=( [0]="aa" [1]="bb" [2]="cc" )
+typeset -m 'j=a[0]'
+typeset -m 'a[0]=a[1]'
+typeset -m 'a[1]=j'
+[[ ${a[@]} == 'bb aa cc' ]] || err_exit 'moving index array elements not working'
+unset a j
+
+typeset -A a=( [0]="aa" [1]="bb" [2]="cc" )
+typeset -m 'j=a[0]'
+typeset -m 'a[0]=a[1]'
+typeset -m 'a[1]=j'
+[[ ${a[@]} == 'bb aa cc' ]] || err_exit 'moving associative array elements not working'
+unset a j
+
+z=(a b c)
+unset x
+typeset -m x[1]=z
+[[ ${x[1][@]} == 'a b c' ]] || err_exit 'moving indexed array to index array element not working'
+
+unset x z
+z=([0]=a [1]=b [2]=c)
+typeset -m x[1]=z
+[[ ${x[1][@]} == 'a b c' ]] || err_exit 'moving associative array to index array element not working'
+
+{
+typeset -a arr=(
+ float
+)
+} 2> /dev/null
+[[ ${arr[0]} == float ]] || err_exit 'typeset -a should not expand alias for float'
+unset arr
+
+{
+typeset -r -a arr=(
+ float
+)
+} 2> /dev/null
+[[ ${arr[0]} == float ]] || err_exit 'typeset -r -a should not expand alias for float'
+{
+typeset -a arr2=(
+ typeset +r
+)
+} 2> /dev/null
+[[ ${arr2[0]} == typeset ]] || err_exit 'typeset -a should not process declarations'
+unset arr2
+
+$SHELL 2> /dev/null -c $'typeset -a arr=(\nfor)' || err_exit 'typeset -a should allow reserved words as first argument'
+
+$SHELL 2> /dev/null -c $'typeset -r -a arr=(\nfor)' || err_exit 'typeset -r -a should allow reserved words as first argument'
+
+typeset arr2[6]
+[[ ${#arr2[@]} == 0 ]] || err_exit 'declartion "typeset array[6]" should not show any elements'
+
+arr2[1]=def
+[[ ${arr2[1]} == def ]] || err_exit 'declaration "typeset array[6]" causes arrays causes wrong side effects'
+
+unset foo
+typeset foo[7]
+[[ ${#foo[@]} == 0 ]] || err_exit 'typeset foo[7] should not have one element'
+
+a=123 $SHELL 2> /dev/null -c 'integer a[5]=3 a[2]=4; unset a;x=0; ((a[++x]++));:' || err_exit 'unsetting array variable leaves side effect'
+
+unset foo
+foo=(aa bb cc)
+foo=( ${foo[@]:1} )
+[[ ${foo[@]} == 'bb cc' ]] || err_exit "indexed array assignment using parts of array for values gives wrong result of ${foo[@]}"
+
+unset foo
+foo=([xx]=aa [yy]=bb [zz]=cc)
+foo=( ${foo[yy]} ${foo[zz]} )
+[[ ${foo[@]} == 'bb cc' ]] || err_exit "associative array assignment using parts of array for values gives wrong result of ${foo[@]}"
+
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/arrays2.sh b/src/cmd/ksh93/tests/arrays2.sh
new file mode 100755
index 0000000..70de3b0
--- /dev/null
+++ b/src/cmd/ksh93/tests/arrays2.sh
@@ -0,0 +1,212 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+for ((i=0; i < 4; i++ ))
+do for ((j=0; j < 5; j++ ))
+ do a[i][j]=$i$j
+ done
+done
+for ((i=0; i < 4; i++ ))
+do for ((j=0; j < 5; j++ ))
+ do [[ ${a[i][j]} == "$i$j" ]] || err_exit "\${a[$i][$j]} != $i$j"
+ done
+done
+for ((i=0; i < 4; i++ ))
+do j=0;for k in ${a[i][@]}
+ do [[ $k == "$i$j" ]] || err_exit "\${a[i][@]} != $i$j"
+ (( j++ ))
+ done
+done
+unset a
+a=(
+ ( 00 01 02 03 04 )
+ ( 10 11 12 13 14 15)
+ ( 20 21 22 23 24 )
+ ( 30 31 32 33 34 )
+)
+
+function check
+{
+ nameref a=$1
+ nameref b=a[2]
+ typeset c=$1
+ integer i j
+ for ((i=0; i < 4; i++ ))
+ do for ((j=0; j < 5; j++ ))
+ do [[ ${a[$i][$j]} == "$i$j" ]] || err_exit "\${$c[$i][$j]} != $i$j"
+ done
+ done
+ (( ${#a[@]} == 4 )) || err_exit "\${#$c[@]} not 4"
+ (( ${#a[0][@]} == 5 )) || err_exit "\${#$c[0][@]} not 5"
+ (( ${#a[1][@]} == 6 )) || err_exit "\${#$c[1][@]} not 6"
+ set -s -- ${!a[@]}
+ [[ ${@} == '0 1 2 3' ]] || err_exit "\${!$c[@]} not 0 1 2 3"
+ set -s -- ${!a[0][@]}
+ [[ ${@} == '0 1 2 3 4' ]] || err_exit "\${!$c[0][@]} not 0 1 2 3 4"
+ set -s -- ${!a[1][@]}
+ [[ ${@} == '0 1 2 3 4 5' ]] || err_exit "\${!$c[1][@]} not 0 1 2 3 4 5"
+ [[ $a == 00 ]] || err_exit "\$$c is not 00"
+ [[ ${a[0]} == 00 ]] || err_exit "\${$a[0]} is not 00"
+ [[ ${a[0][0]} == 00 ]] || err_exit "${a[0][0]} is not 00"
+ [[ ${a[0][0][0]} == 00 ]] || err_exit "\${$c[0][0][0]} is not 00"
+ [[ ${a[0][0][1]} == '' ]] || err_exit "\${$c[0][0][1]} is not empty"
+ [[ ${b[3]} == 23 ]] || err_exit "${!b}[3] not = 23"
+}
+
+check a
+
+unset a
+typeset -A a
+for ((i=0; i < 4; i++ ))
+do for ((j=0; j < 5; j++ ))
+ do a[$i][j]=$i$j
+ done
+done
+for ((i=0; i < 4; i++ ))
+do for ((j=0; j < 5; j++ ))
+ do [[ ${a[$i][j]} == "$i$j" ]] || err_exit "\${a[$i][$j]} == $i$j"
+ done
+done
+a[1][5]=15
+b=(
+ [0]=( 00 01 02 03 04 )
+ [1]=( 10 11 12 13 14 15)
+ [2]=( 20 21 22 23 24 )
+ [3]=( 30 31 32 33 34 )
+)
+check b
+[[ ${a[1][@]} == "${b[1][@]}" ]] || err_exit "a[1] not equal to b[1]"
+c=(
+ [0]=( [0]=00 [1]=01 [2]=02 [3]=03 [4]=04 )
+ [1]=( [0]=10 [1]=11 [2]=12 [3]=13 [4]=14 [5]=15)
+ [2]=( [0]=20 [1]=21 [2]=22 [3]=23 [4]=24 )
+ [3]=( [0]=30 [1]=31 [2]=32 [3]=33 [4]=34 )
+)
+check c
+typeset -A d
+d[0]=( [0]=00 [1]=01 [2]=02 [3]=03 [4]=04 )
+d[1]=( [0]=10 [1]=11 [2]=12 [3]=13 [4]=14 [5]=15)
+d[2]=( [0]=20 [1]=21 [2]=22 [3]=23 [4]=24 )
+d[3]=( [0]=30 [1]=31 [2]=32 [3]=33 [4]=34 )
+check d
+unset a b c d
+[[ ${a-set} ]] || err_exit "a is set after unset"
+[[ ${b-set} ]] || err_exit "b is set after unset"
+[[ ${c-set} ]] || err_exit "c is set after unset"
+[[ ${d-set} ]] || err_exit "c is set after unset"
+
+$SHELL 2> /dev/null <<\+++ || err_exit 'input of 3 dimensional array not working'
+typeset x=(
+ ( (g G) (h H) (i I) )
+ ( (d D) (e E) (f F) )
+ ( (a A) (b B) (c C) )
+)
+[[ ${x[0][0][0]} == g ]] || err_exit '${x[0][0][0]} == G'
+[[ ${x[1][1][0]} == e ]] || err_exit '${x[1][1][0]} == e'
+[[ ${x[1][1][1]} == E ]] || err_exit '${x[2][2][1]} == C'
+[[ ${x[0][2][1]} == I ]] || err_exit '${x[0][2][1]} == I'
++++
+
+typeset -a -si x=( [0]=(1 2 3) [1]=(4 5 6) [2]=(7 8 9) )
+[[ ${x[1][1]} == 5 ]] || err_exit 'changing two dimensional indexed array to short integer failed'
+unset x
+typeset -A -si x=( [0]=(1 2 3) [1]=(4 5 6) [2]=(7 8 9) )
+[[ ${x[1][2]} == 6 ]] || err_exit 'changing two dimensional associative array to short integer failed'
+
+unset ar x y
+integer -a ar
+integer i x y
+for (( i=0 ; i < 100 ; i++ ))
+do (( ar[y][x++]=i ))
+ (( x > 9 )) && (( y++ , x=0 ))
+done
+[[ ${#ar[0][*]} == 10 ]] || err_exit "\${#ar[0][*]} is '${#ar[0][*]}', should be 10"
+[[ ${#ar[*]} == 10 ]] || err_exit "\${#ar[*]} is '${#ar[*]}', should be 10"
+[[ ${ar[5][5]} == 55 ]] || err_exit "ar[5][5] is '${ar[5][5]}', should be 55"
+
+unset ar
+integer -a ar
+x=0 y=0
+for (( i=0 ; i < 81 ; i++ ))
+do nameref ar_y=ar[$y]
+ (( ar_y[x++]=i ))
+ (( x > 8 )) && (( y++ , x=0 ))
+ typeset +n ar_y
+done
+[[ ${#ar[0][*]} == 9 ]] || err_exit "\${#ar[0][*]} is '${#ar[0][*]}', should be 9"
+[[ ${#ar[*]} == 9 ]] || err_exit "\${#ar[*]} is '${#ar[*]}', should be 9"
+[[ ${ar[4][4]} == 40 ]] || err_exit "ar[4][4] is '${ar[4][4]}', should be 40"
+
+$SHELL 2> /dev/null -c 'compound c;float -a c.ar;(( c.ar[2][3][3] = 5))' || 'multi-dimensional arrays in arithemtic expressions not working'
+
+expected='typeset -a -l -E c.ar=([2]=([3]=([3]=5) ) )'
+unset c
+float c.ar
+c.ar[2][3][3]=5
+[[ $(typeset -p c.ar) == "$expected" ]] || err_exit "c.ar[2][3][3]=5;typeset -c c.ar expands to $(typeset -p c.ar)"
+
+unset values
+float -a values=( [1][3]=90 [1][4]=89 )
+function fx
+{
+ nameref arg=$1
+ [[ ${arg[0..5]} == '90 89' ]] || err_exit '${arg[0..5]} not correct where arg is a nameref to values[1]'
+}
+fx values[1]
+
+function test_short_integer
+{
+ compound out=( typeset stdout stderr ; integer res )
+ compound -r -a tests=(
+ ( cmd='integer -s -r -a x=( 1 2 3 ) ; print "${x[2]}"' stdoutpattern='3' )
+ ( cmd='integer -s -r -A x=( [0]=1 [1]=2 [2]=3 ) ; print "${x[2]}"' stdoutpattern='3' )
+ # 2D integer arrays: the following two tests crash for both "integer -s" and "integer"
+ ( cmd='integer -r -a x=( [0]=( [0]=1 [1]=2 [2]=3 ) [1]=( [0]=4 [1]=5 [2]=6 ) [2]=( [0]=7 [1]=8 [2]=9 ) ) ; print "${x[1][1]}"' stdoutpattern='5' )
+ ( cmd='integer -s -r -a x=( [0]=( [0]=1 [1]=2 [2]=3 ) [1]=( [0]=4 [1]=5 [2]=6 ) [2]=( [0]=7 [1]=8 [2]=9 ) ) ; print "${x[1][1]}"' stdoutpattern='5' )
+ )
+ typeset testname
+ integer i
+
+ for (( i=0 ; i < ${#tests[@]} ; i++ )) ; do
+ nameref tst=tests[i]
+ testname="${0}/${i}"
+
+ out.stderr="${ { out.stdout="${ ${SHELL} -o nounset -o errexit -c "${tst.cmd}" ; (( out.res=$? )) ; }" ; } 2>&1 ; }"
+
+ [[ "${out.stdout}" == ${tst.stdoutpattern} ]] || err_exit "${testname}: Expected stdout to match $(printf '%q\n' "${tst.stdoutpattern}"), got $(printf '%q\n' "${out.stdout}")"
+ [[ "${out.stderr}" == '' ]] || err_exit "${testname}: Expected empty stderr, got $(printf '%q\n' "${out.stderr}")"
+ (( out.res == 0 )) || err_exit "${testname}: Unexpected exit code ${out.res}"
+ done
+
+ return 0
+}
+# run tests
+test_short_integer
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/attributes.sh b/src/cmd/ksh93/tests/attributes.sh
new file mode 100755
index 0000000..9deca59
--- /dev/null
+++ b/src/cmd/ksh93/tests/attributes.sh
@@ -0,0 +1,418 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2012 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+r=readonly u=Uppercase l=Lowercase i=22 i8=10 L=abc L5=def uL5=abcdef xi=20
+x=export t=tagged H=hostname LZ5=026 RZ5=026 Z5=123 lR5=ABcdef R5=def n=l
+for option in u l i i8 L L5 LZ5 RZ5 Z5 r x H t R5 uL5 lR5 xi n
+do typeset -$option $option
+done
+(r=newval) 2> /dev/null && err_exit readonly attribute fails
+i=i+5
+if ((i != 27))
+then err_exit integer attributes fails
+fi
+if [[ $i8 != 8#12 ]]
+then err_exit integer base 8 fails
+fi
+if [[ $u != UPPERCASE ]]
+then err_exit uppercase fails
+fi
+if [[ $l != lowercase ]]
+then err_exit lowercase fails
+fi
+if [[ $n != lowercase ]]
+then err_exit reference variables fail
+fi
+if [[ t=tagged != $(typeset -t) ]]
+then err_exit tagged fails
+fi
+if [[ t != $(typeset +t) ]]
+then err_exit tagged fails
+fi
+if [[ $Z5 != 00123 ]]
+then err_exit zerofill fails
+fi
+if [[ $RZ5 != 00026 ]]
+then err_exit right zerofill fails
+fi
+L=12345
+if [[ $L != 123 ]]
+then err_exit leftjust fails
+fi
+if [[ $L5 != "def " ]]
+then err_exit leftjust fails
+fi
+if [[ $uL5 != ABCDE ]]
+then err_exit leftjust uppercase fails
+fi
+if [[ $lR5 != bcdef ]]
+then err_exit rightjust fails
+fi
+if [[ $R5 != " def" ]]
+then err_exit rightjust fails
+fi
+if [[ $($SHELL -c 'echo $x') != export ]]
+then err_exit export fails
+fi
+if [[ $($SHELL -c 'xi=xi+4;echo $xi') != 24 ]]
+then err_exit export attributes fails
+fi
+x=$(foo=abc $SHELL <<!
+ foo=bar
+ $SHELL -c 'print \$foo'
+!
+)
+if [[ $x != bar ]]
+then err_exit 'environment variables require re-export'
+fi
+(typeset + ) > /dev/null 2>&1 || err_exit 'typeset + not working'
+(typeset -L-5 buf="A" 2>/dev/null)
+if [[ $? == 0 ]]
+then err_exit 'typeset allows negative field for left/right adjust'
+fi
+a=b
+readonly $a=foo
+if [[ $b != foo ]]
+then err_exit 'readonly $a=b not working'
+fi
+if [[ $(export | grep '^PATH=') != PATH=* ]]
+then err_exit 'export not working'
+fi
+picture=(
+ bitmap=/fruit
+ size=(typeset -E x=2.5)
+)
+string="$(print $picture)"
+if [[ "${string}" != *'size=( typeset -E'* ]]
+then err_exit 'print of compound exponential variable not working'
+fi
+sz=(typeset -E y=2.2)
+string="$(print $sz)"
+if [[ "${sz}" == *'typeset -E -F'* ]]
+then err_exit 'print of exponential shows both -E and -F attributes'
+fi
+print 'typeset -i m=48/4+1;print -- $m' > $tmp/script
+chmod +x $tmp/script
+typeset -Z2 m
+if [[ $($tmp/script) != 13 ]]
+then err_exit 'attributes not cleared for script execution'
+fi
+print 'print VAR=$VAR' > $tmp/script
+typeset -L70 VAR=var
+$tmp/script > $tmp/script.1
+[[ $(< $tmp/script.1) == VAR= ]] || err_exit 'typeset -L should not be inherited'
+typeset -Z LAST=00
+unset -f foo
+function foo
+{
+ if [[ $1 ]]
+ then LAST=$1
+ else ((LAST++))
+ fi
+}
+foo 1
+if (( ${#LAST} != 2 ))
+then err_exit 'LAST!=2'
+fi
+foo
+if (( ${#LAST} != 2 ))
+then err_exit 'LAST!=2'
+fi
+[[ $(set | grep LAST) == LAST=02 ]] || err_exit "LAST not correct in set list"
+set -a
+unset foo
+foo=bar
+if [[ $(export | grep ^foo=) != 'foo=bar' ]]
+then err_exit 'all export not working'
+fi
+unset foo
+read foo <<!
+bar
+!
+if [[ $(export | grep ^foo=) != 'foo=bar' ]]
+then err_exit 'all export not working with read'
+fi
+if [[ $(typeset | grep PS2) == PS2 ]]
+then err_exit 'typeset without arguments outputs names without attributes'
+fi
+unset a z q x
+w1=hello
+w2=world
+t1="$w1 $w2"
+if (( 'a' == 97 ))
+then b1=aGVsbG8gd29ybGQ=
+ b2=aGVsbG8gd29ybGRoZWxsbyB3b3JsZA==
+else b1=iIWTk5ZAppaZk4Q=
+ b2=iIWTk5ZAppaZk4SIhZOTlkCmlpmThA==
+fi
+z=$b1
+typeset -b x=$b1
+[[ $x == "$z" ]] || print -u2 'binary variable not expanding correctly'
+[[ $(printf "%B" x) == $t1 ]] || err_exit 'typeset -b not working'
+typeset -b -Z5 a=$b1
+[[ $(printf "%B" a) == $w1 ]] || err_exit 'typeset -b -Z5 not working'
+typeset -b q=$x$x
+[[ $q == $b2 ]] || err_exit 'typeset -b not working with concatination'
+[[ $(printf "%B" q) == $t1$t1 ]] || err_exit 'typeset -b concatination not working'
+x+=$b1
+[[ $x == $b2 ]] || err_exit 'typeset -b not working with append'
+[[ $(printf "%B" x) == $t1$t1 ]] || err_exit 'typeset -b append not working'
+typeset -b -Z20 z=$b1
+(( $(printf "%B" z | wc -c) == 20 )) || err_exit 'typeset -b -Z20 not storing 20 bytes'
+{
+ typeset -b v1 v2
+ read -N11 v1
+ read -N22 v2
+} << !
+hello worldhello worldhello world
+!
+[[ $v1 == "$b1" ]] || err_exit "v1=$v1 should be $b1"
+[[ $v2 == "$x" ]] || err_exit "v1=$v2 should be $x"
+if env '!=1' >/dev/null 2>&1
+then [[ $(env '!=1' $SHELL -c 'echo ok' 2>/dev/null) == ok ]] || err_exit 'malformed environment terminates shell'
+fi
+unset var
+typeset -b var
+printf '12%Z34' | read -r -N 5 var
+[[ $var == MTIAMzQ= ]] || err_exit 'binary files with zeros not working'
+unset var
+if command typeset -usi var=0xfffff 2> /dev/null
+then (( $var == 0xffff )) || err_exit 'unsigned short integers not working'
+else err_exit 'typeset -usi cannot be used for unsigned short'
+fi
+[[ $($SHELL -c 'unset foo;typeset -Z2 foo; print ${foo:-3}' 2> /dev/null) == 3 ]] || err_exit '${foo:-3} not 3 when typeset -Z2 field undefined'
+[[ $($SHELL -c 'unset foo;typeset -Z2 foo; print ${foo:=3}' 2> /dev/null) == 03 ]] || err_exit '${foo:=-3} not 3 when typeset -Z2 foo undefined'
+unset foo bar
+unset -f fun
+function fun
+{
+ export foo=hello
+ typeset -x bar=world
+ [[ $foo == hello ]] || err_exit 'export scoping problem in function'
+}
+fun
+[[ $(export | grep foo) == 'foo=hello' ]] || err_exit 'export not working in functions'
+[[ $(export | grep bar) ]] && err_exit 'typeset -x not local'
+[[ $($SHELL -c 'typeset -r IFS=;print -r $(pwd)' 2> /dev/null) == "$(pwd)" ]] || err_exit 'readonly IFS causes command substitution to fail'
+fred[66]=88
+[[ $(typeset -pa) == *fred* ]] || err_exit 'typeset -pa not working'
+unset x y z
+typeset -LZ3 x=abcd y z=00abcd
+y=03
+[[ $y == "3 " ]] || err_exit '-LZ3 not working for value 03'
+[[ $x == "abc" ]] || err_exit '-LZ3 not working for value abcd'
+[[ $x == "abc" ]] || err_exit '-LZ3 not working for value 00abcd'
+unset x z
+set +a
+[[ $(typeset -p z) ]] && err_exit "typeset -p for z undefined failed"
+unset z
+x='typeset -i z=45'
+eval "$x"
+[[ $(typeset -p z) == "$x" ]] || err_exit "typeset -p for '$x' failed"
+[[ $(typeset +p z) == "${x%=*}" ]] || err_exit "typeset +p for '$x' failed"
+unset z
+x='typeset -a z=(a b c)'
+eval "$x"
+[[ $(typeset -p z) == "$x" ]] || err_exit "typeset -p for '$x' failed"
+[[ $(typeset +p z) == "${x%=*}" ]] || err_exit "typeset +p for '$x' failed"
+unset z
+x='typeset -C z=(
+ foo=bar
+ xxx=bam
+)'
+eval "$x"
+x=${x//$'\t'}
+x=${x//$'(\n'/'('}
+x=${x//$'\n'/';'}
+x=${x%';)'}')'
+[[ $(typeset -p z) == "$x" ]] || err_exit "typeset -p for '$x' failed"
+[[ $(typeset +p z) == "${x%%=*}" ]] || err_exit "typeset +p for '$x' failed"
+unset z
+x='typeset -A z=([bar]=bam [xyz]=bar)'
+eval "$x"
+[[ $(typeset -p z) == "$x" ]] || err_exit "typeset -p for '$x' failed"
+[[ $(typeset +p z) == "${x%%=*}" ]] || err_exit "typeset +p for '$x' failed"
+unset z
+foo=abc
+x='typeset -n z=foo'
+eval "$x"
+[[ $(typeset -p z) == "$x" ]] || err_exit "typeset -p for '$x' failed"
+[[ $(typeset +p z) == "${x%%=*}" ]] || err_exit "typeset +p for '$x' failed"
+typeset +n z
+unset foo z
+typeset -T Pt_t=(
+ float x=1 y=2
+)
+Pt_t z
+x=${z//$'\t'}
+x=${x//$'(\n'/'('}
+x=${x//$'\n'/';'}
+x=${x%';)'}')'
+[[ $(typeset -p z) == "Pt_t z=$x" ]] || err_exit "typeset -p for type failed"
+[[ $(typeset +p z) == "Pt_t z" ]] || err_exit "typeset +p for type failed"
+unset z
+function foo
+{
+ typeset -p bar
+}
+bar=xxx
+[[ $(foo) == bar=xxx ]] || err_exit 'typeset -p not working inside a function'
+unset foo
+typeset -L5 foo
+[[ $(typeset -p foo) == 'typeset -L 5 foo' ]] || err_exit 'typeset -p not working for variables with attributes but without a value'
+{ $SHELL <<- EOF
+ typeset -L3 foo=aaa
+ typeset -L6 foo=bbbbbb
+ [[ \$foo == bbbbbb ]]
+EOF
+} || err_exit 'typeset -L should not preserve old attributes'
+{ $SHELL <<- EOF
+ typeset -R3 foo=aaa
+ typeset -R6 foo=bbbbbb
+ [[ \$foo == bbbbbb ]]
+EOF
+} 2> /dev/null || err_exit 'typeset -R should not preserve old attributes'
+
+expected='YWJjZGVmZ2hpag=='
+unset foo
+typeset -b -Z10 foo
+read foo <<< 'abcdefghijklmnop'
+[[ $foo == "$expected" ]] || err_exit 'read foo, where foo is "typeset -b -Z10" not working'
+unset foo
+typeset -b -Z10 foo
+read -N10 foo <<< 'abcdefghijklmnop'
+[[ $foo == "$expected" ]] || err_exit 'read -N10 foo, where foo is "typeset -b -Z10" not working'
+unset foo
+typeset -b -A foo
+read -N10 foo[4] <<< 'abcdefghijklmnop'
+[[ ${foo[4]} == "$expected" ]] || err_exit 'read -N10 foo, where foo is "typeset -b -A" foo not working'
+unset foo
+typeset -b -a foo
+read -N10 foo[4] <<< 'abcdefghijklmnop'
+[[ ${foo[4]} == "$expected" ]] || err_exit 'read -N10 foo, where foo is "typeset -b -a" foo not working'
+[[ $(printf %B foo[4]) == abcdefghij ]] || err_exit 'printf %B for binary associative array element not working'
+[[ $(printf %B foo[4]) == abcdefghij ]] || err_exit 'printf %B for binary indexed array element not working'
+unset foo
+
+$SHELL 2> /dev/null -c 'export foo=(bar=3)' && err_exit 'compound variables cannot be exported'
+
+$SHELL -c 'builtin date' >/dev/null 2>&1 &&
+{
+
+# check env var changes against a builtin that uses the env var
+
+SEC=1234252800
+ETZ=EST5EDT
+EDT=03
+PTZ=PST8PDT
+PDT=00
+
+CMD="date -f%H \\#$SEC"
+
+export TZ=$ETZ
+
+set -- \
+ "$EDT $PDT $EDT" "" "TZ=$PTZ" "" \
+ "$EDT $PDT $EDT" "" "TZ=$PTZ" "TZ=$ETZ" \
+ "$EDT $PDT $EDT" "TZ=$ETZ" "TZ=$PTZ" "TZ=$ETZ" \
+ "$PDT $EDT $PDT" "TZ=$PTZ" "" "TZ=$PTZ" \
+ "$PDT $EDT $PDT" "TZ=$PTZ" "TZ=$ETZ" "TZ=$PTZ" \
+ "$EDT $PDT $EDT" "foo=bar" "TZ=$PTZ" "TZ=$ETZ" \
+
+while (( $# >= 4 ))
+do exp=$1
+ got=$(print $($SHELL -c "builtin date; $2 $CMD; $3 $CMD; $4 $CMD"))
+ [[ $got == $exp ]] || err_exit "[ '$2' '$3' '$4' ] env sequence failed -- expected '$exp', got '$got'"
+ shift 4
+done
+
+}
+
+unset v
+typeset -H v=/dev/null
+[[ $v == *nul* ]] || err_exit 'typeset -H for /dev/null not working'
+
+unset x
+(typeset +C x) 2> /dev/null && err_exit 'typeset +C should be an error'
+(typeset +A x) 2> /dev/null && err_exit 'typeset +A should be an error'
+(typeset +a x) 2> /dev/null && err_exit 'typeset +a should be an error'
+
+unset x
+{
+x=$($SHELL -c 'integer -s x=5;print -r -- $x')
+} 2> /dev/null
+[[ $x == 5 ]] || err_exit 'integer -s not working'
+
+[[ $(typeset -l) == *namespace*.sh* ]] && err_exit 'typeset -l should not contain namespace .sh'
+
+unset got
+typeset -u got
+exp=100
+((got=$exp))
+[[ $got == $exp ]] || err_exit "typeset -l fails on numeric value -- expected '$exp', got '$got'"
+
+unset s
+typeset -a -u s=( hello world chicken )
+[[ ${s[2]} == CHICKEN ]] || err_exit 'typeset -u not working with indexed arrays'
+unset s
+typeset -A -u s=( [1]=hello [0]=world [2]=chicken )
+[[ ${s[2]} == CHICKEN ]] || err_exit 'typeset -u not working with associative arrays'
+expected=$'(\n\t[0]=WORLD\n\t[1]=HELLO\n\t[2]=CHICKEN\n)'
+[[ $(print -v s) == "$expected" ]] || err_exit 'typeset -u for associative array does not display correctly'
+
+unset s
+if command typeset -M totitle s 2> /dev/null
+then [[ $(typeset +p s) == 'typeset -M totitle s' ]] || err_exit 'typeset -M totitle does not display correctly with typeset -p'
+fi
+
+{ $SHELL <<- \EOF
+ compound -a a1
+ for ((i=1 ; i < 100 ; i++ ))
+ do [[ "$( typeset + a1[$i] )" == '' ]] && a1[$i].text='hello'
+ done
+ [[ ${a1[70].text} == hello ]]
+EOF
+} 2> /dev/null
+(( $? )) && err_exit 'typeset + a[i] not working'
+
+typeset groupDB="" userDB=""
+typeset -l -L1 DBPick=""
+[[ -n "$groupDB" ]] && err_exit 'typeset -l -L1 causes unwanted side effect'
+
+HISTFILE=foo
+typeset -u PS1='hello --- '
+HISTFILE=foo
+[[ $HISTFILE == foo ]] || err_exit 'typeset -u PS1 affects HISTFILE'
+
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/basic.sh b/src/cmd/ksh93/tests/basic.sh
new file mode 100755
index 0000000..2941543
--- /dev/null
+++ b/src/cmd/ksh93/tests/basic.sh
@@ -0,0 +1,513 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+# test basic file operations like redirection, pipes, file expansion
+set -- \
+ go+r 0000 \
+ go-r 0044 \
+ ug=r 0330 \
+ go+w 0000 \
+ go-w 0022 \
+ ug=w 0550 \
+ go+x 0000 \
+ go-x 0011 \
+ ug=x 0660 \
+ go-rx 0055 \
+ uo-wx 0303 \
+ ug-rw 0660 \
+ o= 0007
+while (( $# >= 2 ))
+do umask 0
+ umask $1
+ g=$(umask)
+ [[ $g == $2 ]] || err_exit "umask 0; umask $1 failed -- expected $2, got $g"
+ shift 2
+done
+umask u=rwx,go=rx || err_exit "umask u=rws,go=rx failed"
+if [[ $(umask -S) != u=rwx,g=rx,o=rx ]]
+then err_exit 'umask -S incorrect'
+fi
+pwd=$PWD
+[[ $SHELL != /* ]] && SHELL=$pwd/$SHELL
+cd $tmp || { err_exit "cd $tmp failed"; exit 1; }
+um=$(umask -S)
+( umask 0777; > foobar )
+rm -f foobar
+> foobar
+[[ -r foobar ]] || err_exit 'umask not being restored after subshell'
+umask "$um"
+rm -f foobar
+# optimizer bug test
+> foobar
+for i in 1 2
+do print foobar*
+ rm -f foobar
+done > out
+if [[ "$(<out)" != "foobar"$'\n'"foobar*" ]]
+then print -u2 "optimizer bug with file expansion"
+fi
+rm -f out foobar
+mkdir dir
+if [[ $(print */) != dir/ ]]
+then err_exit 'file expansion with trailing / not working'
+fi
+if [[ $(print *) != dir ]]
+then err_exit 'file expansion with single file not working'
+fi
+print hi > .foo
+if [[ $(print *) != dir ]]
+then err_exit 'file expansion leading . not working'
+fi
+date > dat1 || err_exit "date > dat1 failed"
+test -r dat1 || err_exit "dat1 is not readable"
+x=dat1
+cat <$x > dat2 || err_exit "cat < $x > dat2 failed"
+cat dat1 dat2 | cat | cat | cat > dat3 || err_exit "cat pipe failed"
+cat > dat4 <<!
+$(date)
+!
+cat dat1 dat2 | cat | cat | cat > dat5 &
+wait $!
+set -- dat*
+if (( $# != 5 ))
+then err_exit "dat* matches only $# files"
+fi
+if (command > foo\\abc) 2> /dev/null
+then set -- foo*
+ if [[ $1 != 'foo\abc' ]]
+ then err_exit 'foo* does not match foo\abc'
+ fi
+fi
+if ( : > TT* && : > TTfoo ) 2>/dev/null
+then set -- TT*
+ if (( $# < 2 ))
+ then err_exit 'TT* not expanding when file TT* exists'
+ fi
+fi
+cd ~- || err_exit "cd back failed"
+cat > $tmp/script <<- !
+ #! $SHELL
+ print -r -- \$0
+!
+chmod 755 $tmp/script
+if [[ $($tmp/script) != "$tmp/script" ]]
+then err_exit '$0 not correct for #! script'
+fi
+bar=foo
+eval foo=\$bar
+if [[ $foo != foo ]]
+then err_exit 'eval foo=\$bar not working'
+fi
+bar='foo=foo\ bar'
+eval $bar
+if [[ $foo != 'foo bar' ]]
+then err_exit 'eval foo=\$bar, with bar="foo\ bar" not working'
+fi
+cd /tmp
+cd ../../tmp || err_exit "cd ../../tmp failed"
+if [[ $PWD != /tmp ]]
+then err_exit 'cd ../../tmp is not /tmp'
+fi
+( sleep 2; cat <<!
+foobar
+!
+) | cat > $tmp/foobar &
+wait $!
+foobar=$( < $tmp/foobar)
+if [[ $foobar != foobar ]]
+then err_exit "$foobar is not foobar"
+fi
+{
+ print foo
+ /bin/echo bar
+ print bam
+} > $tmp/foobar
+if [[ $( < $tmp/foobar) != $'foo\nbar\nbam' ]]
+then err_exit "output file pointer not shared correctly"
+fi
+cat > $tmp/foobar <<\!
+ print foo
+ /bin/echo bar
+ print bam
+!
+chmod +x $tmp/foobar
+if [[ $($tmp/foobar) != $'foo\nbar\nbam' ]]
+then err_exit "script not working"
+fi
+if [[ $($tmp/foobar | /bin/cat) != $'foo\nbar\nbam' ]]
+then err_exit "script | cat not working"
+fi
+if [[ $( $tmp/foobar) != $'foo\nbar\nbam' ]]
+then err_exit "output file pointer not shared correctly"
+fi
+rm -f $tmp/foobar
+x=$( (print foo) ; (print bar) )
+if [[ $x != $'foo\nbar' ]]
+then err_exit " ( (print foo);(print bar ) failed"
+fi
+x=$( (/bin/echo foo) ; (print bar) )
+if [[ $x != $'foo\nbar' ]]
+then err_exit " ( (/bin/echo);(print bar ) failed"
+fi
+x=$( (/bin/echo foo) ; (/bin/echo bar) )
+if [[ $x != $'foo\nbar' ]]
+then err_exit " ( (/bin/echo);(/bin/echo bar ) failed"
+fi
+cat > $tmp/script <<\!
+if [[ -p /dev/fd/0 ]]
+then builtin cat
+ cat - > /dev/null
+ [[ -p /dev/fd/0 ]] && print ok
+else print no
+fi
+!
+chmod +x $tmp/script
+case $( (print) | $tmp/script;:) in
+ok) ;;
+no) err_exit "[[ -p /dev/fd/0 ]] fails for standard input pipe" ;;
+*) err_exit "builtin replaces standard input pipe" ;;
+esac
+print 'print $0' > $tmp/script
+print ". $tmp/script" > $tmp/scriptx
+chmod +x $tmp/scriptx
+if [[ $($tmp/scriptx) != $tmp/scriptx ]]
+then err_exit '$0 not correct for . script'
+fi
+cd $tmp || { err_exit "cd $tmp failed"; exit 1; }
+print ./b > ./a; print ./c > b; print ./d > c; print ./e > d; print "echo \"hello there\"" > e
+chmod 755 a b c d e
+x=$(./a)
+if [[ $x != "hello there" ]]
+then err_exit "nested scripts failed"
+fi
+x=$( (./a) | cat)
+if [[ $x != "hello there" ]]
+then err_exit "scripts in subshells fail"
+fi
+cd ~- || err_exit "cd back failed"
+x=$( (/bin/echo foo) 2> /dev/null )
+if [[ $x != foo ]]
+then err_exit "subshell in command substitution fails"
+fi
+exec 9>& 1
+exec 1>&-
+x=$(print hello)
+if [[ $x != hello ]]
+then err_exit "command subsitution with stdout closed failed"
+fi
+exec >& 9
+cd $pwd
+x=$(cat <<\! | $SHELL
+/bin/echo | /bin/cat
+/bin/echo hello
+!
+)
+if [[ $x != $'\n'hello ]]
+then err_exit "$SHELL not working when standard input is a pipe"
+fi
+x=$( (/bin/echo hello) 2> /dev/null )
+if [[ $x != hello ]]
+then err_exit "subshell in command substitution with 1 closed fails"
+fi
+cat > $tmp/script <<- \!
+read line 2> /dev/null
+print done
+!
+if [[ $($SHELL $tmp/script <&-) != done ]]
+then err_exit "executing script with 0 closed fails"
+fi
+trap '' INT
+cat > $tmp/script <<- \!
+trap 'print bad' INT
+kill -s INT $$
+print good
+!
+chmod +x $tmp/script
+if [[ $($SHELL $tmp/script) != good ]]
+then err_exit "traps ignored by parent not ignored"
+fi
+trap - INT
+cat > $tmp/script <<- \!
+read line
+/bin/cat
+!
+if [[ $($SHELL $tmp/script <<!
+one
+two
+!
+) != two ]]
+then err_exit "standard input not positioned correctly"
+fi
+word=$(print $'foo\nbar' | { read line; /bin/cat;})
+if [[ $word != bar ]]
+then err_exit "pipe to { read line; /bin/cat;} not working"
+fi
+word=$(print $'foo\nbar' | ( read line; /bin/cat) )
+if [[ $word != bar ]]
+then err_exit "pipe to ( read line; /bin/cat) not working"
+fi
+if [[ $(print x{a,b}y) != 'xay xby' ]]
+then err_exit 'brace expansion not working'
+fi
+if [[ $(for i in foo bar
+ do ( tgz=$(print $i)
+ print $tgz)
+ done) != $'foo\nbar' ]]
+then err_exit 'for loop subshell optimizer bug'
+fi
+unset a1
+optbug()
+{
+ set -A a1 foo bar bam
+ integer i
+ for ((i=0; i < 3; i++))
+ do
+ (( ${#a1[@]} < 2 )) && return 0
+ set -- "${a1[@]}"
+ shift
+ set -A a1 -- "$@"
+ done
+ return 1
+}
+optbug || err_exit 'array size optimzation bug'
+wait # not running --pipefail which would interfere with subsequent tests
+: $(jobs -p) # required to clear jobs for next jobs -p (interactive side effect)
+sleep 20 &
+pids=$!
+if [[ $(jobs -p) != $! ]]
+then err_exit 'jobs -p not reporting a background job'
+fi
+sleep 20 &
+pids="$pids $!"
+foo()
+{
+ set -- $(jobs -p)
+ (( $# == 2 )) || err_exit "$# jobs not reported -- 2 expected"
+}
+foo
+kill $pids
+
+[[ $( (trap 'print alarm' ALRM; sleep 4) & sleep 2; kill -ALRM $!; sleep 2; wait) == alarm ]] || err_exit 'ALRM signal not working'
+[[ $($SHELL -c 'trap "" HUP; $SHELL -c "(sleep 2;kill -HUP $$)& sleep 4;print done"') != done ]] && err_exit 'ignored traps not being ignored'
+[[ $($SHELL -c 'o=foobar; for x in foo bar; do (o=save);print $o;done' 2> /dev/null ) == $'foobar\nfoobar' ]] || err_exit 'for loop optimization subshell bug'
+command exec 3<> /dev/null
+if cat /dev/fd/3 >/dev/null 2>&1 || whence mkfifo > /dev/null
+then [[ $($SHELL -c 'cat <(print foo)' 2> /dev/null) == foo ]] || err_exit 'process substitution not working'
+ [[ $($SHELL -c $'tee >(grep \'1$\' > '$tmp/scriptx$') > /dev/null <<- \!!!
+ line0
+ line1
+ line2
+ !!!
+ wait
+ cat '$tmp/scriptx 2> /dev/null) == line1 ]] || err_exit '>() process substitution fails'
+ > $tmp/scriptx
+ [[ $($SHELL -c $'
+ for i in 1
+ do tee >(grep \'1$\' > '$tmp/scriptx$') > /dev/null <<- \!!!
+ line0
+ line1
+ line2
+ !!!
+ done
+ wait
+ cat '$tmp/scriptx 2>> /dev/null) == line1 ]] || err_exit '>() process substitution fails in for loop'
+ [[ $({ $SHELL -c 'cat <(for i in x y z; do print $i; done)';} 2> /dev/null) == $'x\ny\nz' ]] ||
+ err_exit 'process substitution of compound commands not working'
+fi
+[[ $($SHELL -r 'command -p :' 2>&1) == *restricted* ]] || err_exit 'command -p not restricted'
+print cat > $tmp/scriptx
+chmod +x $tmp/scriptx
+[[ $($SHELL -c "print foo | $tmp/scriptx ;:" 2> /dev/null ) == foo ]] || err_exit 'piping into script fails'
+[[ $($SHELL -c 'X=1;print -r -- ${X:=$(expr "a(0)" : '"'a*(\([^)]\))')}'" 2> /dev/null) == 1 ]] || err_exit 'x=1;${x:=$(..."...")} failure'
+[[ $($SHELL -c 'print -r -- ${X:=$(expr "a(0)" : '"'a*(\([^)]\))')}'" 2> /dev/null) == 0 ]] || err_exit '${x:=$(..."...")} failure'
+if cat /dev/fd/3 >/dev/null 2>&1 || whence mkfifo > /dev/null
+then [[ $(cat <(print hello) ) == hello ]] || err_exit "process substitution not working outside for or while loop"
+ $SHELL -c '[[ $(for i in 1;do cat <(print hello);done ) == hello ]]' 2> /dev/null|| err_exit "process substitution not working in for or while loop"
+fi
+exec 3> /dev/null
+print 'print foo "$@"' > $tmp/scriptx
+[[ $( print "($tmp/scriptx bar)" | $SHELL 2>/dev/null) == 'foo bar' ]] || err_exit 'script pipe to shell fails'
+print "#! $SHELL" > $tmp/scriptx
+print 'print -- $0' >> $tmp/scriptx
+chmod +x $tmp/scriptx
+[[ $($tmp/scriptx) == $tmp/scriptx ]] || err_exit "\$0 is $0 instead of $tmp/scriptx"
+cat > $tmp/scriptx <<- \EOF
+ myfilter() { x=$(print ok | cat); print -r -- $SECONDS;}
+ set -o pipefail
+ sleep 3 | myfilter
+EOF
+(( $($SHELL $tmp/scriptx) > 2.0 )) && err_exit 'command substitution causes pipefail option to hang'
+exec 3<&-
+( typeset -r foo=bar) 2> /dev/null || err_exit 'readonly variables set in a subshell cannot unset'
+$SHELL -c 'x=${ print hello;}; [[ $x == hello ]]' 2> /dev/null || err_exit '${ command;} not supported'
+$SHELL 2> /dev/null <<- \EOF || err_exit 'multiline ${...} command substitution not supported'
+ x=${
+ print hello
+ }
+ [[ $x == hello ]]
+EOF
+$SHELL 2> /dev/null <<- \EOF || err_exit '${...} command substitution with side effects not supported '
+ y=bye
+ x=${
+ y=hello
+ print hello
+ }
+ [[ $y == $x ]]
+EOF
+$SHELL 2> /dev/null <<- \EOF || err_exit 'nested ${...} command substitution not supported'
+ x=${
+ print ${ print hello;} $(print world)
+ }
+ [[ $x == 'hello world' ]]
+EOF
+$SHELL 2> /dev/null <<- \EOF || err_exit 'terminating } is not a reserved word with ${ command }'
+ x=${ { print -n } ; print -n hello ; } ; print ' world' }
+ [[ $x == '}hello world' ]]
+EOF
+$SHELL 2> /dev/null <<- \EOF || err_exit '${ command;}xxx not working'
+ f()
+ {
+ print foo
+ }
+ [[ ${ f;}bar == foobar ]]
+EOF
+
+unset foo
+[[ ! ${foo[@]} ]] || err_exit '${foo[@]} is not empty when foo is unset'
+[[ ! ${foo[3]} ]] || err_exit '${foo[3]} is not empty when foo is unset'
+[[ $(print "[${ print foo }]") == '[foo]' ]] || err_exit '${...} not working when } is followed by ]'
+[[ $(print "${ print "[${ print foo }]" }") == '[foo]' ]] || err_exit 'nested ${...} not working when } is followed by ]'
+unset foo
+foo=$(false) > /dev/null && err_exit 'failed command substitution with redirection not returning false'
+expected=foreback
+got=$(print -n fore; (sleep 2;print back)&)
+[[ $got == $expected ]] || err_exit "command substitution background process output error -- got '$got', expected '$expected'"
+
+binfalse=$(whence -p false)
+for false in false $binfalse
+do x=$($false) && err_exit "x=\$($false) should fail"
+ $($false) && err_exit "\$($false) should fail"
+ $($false) > /dev/null && err_exit "\$($false) > /dev/null should fail"
+done
+if env x-a=y >/dev/null 2>&1
+then [[ $(env 'x-a=y' $SHELL -c 'env | grep x-a') == *x-a=y* ]] || err_exit 'invalid environment variables not preserved'
+fi
+float s=SECONDS
+sleep=$(whence -p sleep)
+for i in 1 2
+do print $i
+done | while read sec; do ( $sleep $sec; $sleep $sec) done
+(( (SECONDS-s) < 4)) && err_exit '"command | while read...done" finishing too fast'
+s=SECONDS
+set -o pipefail
+for ((i=0; i < 30; i++))
+do print hello
+ sleep .1
+done | $sleep 1
+(( (SECONDS-s) < 2 )) || err_exit 'early termination not causing broken pipe'
+[[ $({ trap 'print trap' 0; print -n | $(whence -p cat); } & wait $!) == trap ]] || err_exit 'trap on exit not getting triggered'
+var=$({ trap 'print trap' ERR; print -n | $binfalse; } & wait $!)
+[[ $var == trap ]] || err_exit 'trap on ERR not getting triggered'
+
+exp=
+got=$(
+ function fun
+ {
+ $binfalse && echo FAILED
+ }
+ : works if this line deleted : |
+ fun
+ : works if this line deleted :
+)
+[[ $got == $exp ]] || err_exit "pipe to function with conditional fails -- expected '$exp', got '$got'"
+got=$(
+ : works if this line deleted : |
+ { $binfalse && echo FAILED; }
+ : works if this line deleted :
+)
+[[ $got == $exp ]] || err_exit "pipe to { ... } with conditional fails -- expected '$exp', got '$got'"
+
+got=$(
+ : works if this line deleted : |
+ ( $binfalse && echo FAILED )
+ : works if this line deleted :
+)
+[[ $got == $exp ]] || err_exit "pipe to ( ... ) with conditional fails -- expected '$exp', got '$got'"
+
+( $SHELL -c 'trap : DEBUG; x=( $foo); exit 0') 2> /dev/null || err_exit 'trap DEBUG fails'
+
+bintrue=$(whence -p true)
+set -o pipefail
+float start=$SECONDS end
+for ((i=0; i < 2; i++))
+do print foo
+ sleep 1.5
+done | { read; $bintrue; end=$SECONDS ;}
+(( (SECONDS-start) < 1 )) && err_exit "pipefail not waiting for pipe to finish"
+set +o pipefail
+(( (SECONDS-end) > 2 )) && err_exit "pipefail causing $bintrue to wait for other end of pipe"
+
+
+{ env A__z=C+SHLVL $SHELL -c : ;} 2> /dev/null || err_exit "SHLVL with wrong attribute fails"
+
+if [[ $bintrue ]]
+then float t0=SECONDS
+ { time sleep 1.5 | $bintrue ;} 2> /dev/null
+ (( (SECONDS-t0) < 1 )) && err_exit 'time not waiting for pipeline to complete'
+fi
+
+cat > $tmp/foo.sh <<- \EOF
+ eval "cat > /dev/null < /dev/null"
+ sleep 1
+EOF
+float sec=SECONDS
+. $tmp/foo.sh | cat > /dev/null
+(( (SECONDS-sec) < .7 )) && err_exit '. script does not restore output redirection with eval'
+
+file=$tmp/foobar
+builtin cat
+for ((n=0; n < 1000; n++))
+do
+ > $file
+ { sleep .001;echo $? >$file;} | cat > /dev/null
+ if [[ ! -s $file ]]
+ then err_exit 'output from pipe is lost with pipe to builtin'
+ break;
+ fi
+done
+
+$SHELL -c 'kill -0 123456789123456789123456789' 2> /dev/null && err_exit 'kill not catching process id overflows'
+
+[[ $($SHELL -c '{ cd..; print ok;}' 2> /dev/null) == ok ]] || err_exit 'command name ending in .. causes shell to abort'
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/bracket.sh b/src/cmd/ksh93/tests/bracket.sh
new file mode 100755
index 0000000..cfe4055
--- /dev/null
+++ b/src/cmd/ksh93/tests/bracket.sh
@@ -0,0 +1,340 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+null=''
+if [[ ! -z $null ]]
+then err_exit "-z: null string should be of zero length"
+fi
+file=$tmp/original
+newer_file=$tmp/newer
+if [[ -z $file ]]
+then err_exit "-z: $file string should not be of zero length"
+fi
+if [[ -a $file ]]
+then err_exit "-a: $file shouldn't exist"
+fi
+if [[ -e $file ]]
+then err_exit "-e: $file shouldn't exist"
+fi
+> $file
+if [[ ! -a $file ]]
+then err_exit "-a: $file should exist"
+fi
+if [[ ! -e $file ]]
+then err_exit "-e: $file should exist"
+fi
+chmod 777 $file
+if [[ ! -r $file ]]
+then err_exit "-r: $file should be readable"
+fi
+if [[ ! -w $file ]]
+then err_exit "-w: $file should be writable"
+fi
+if [[ ! -w $file ]]
+then err_exit "-x: $file should be executable"
+fi
+if [[ ! -w $file || ! -r $file ]]
+then err_exit "-rw: $file should be readable/writable"
+fi
+if [[ -s $file ]]
+then err_exit "-s: $file should be of zero size"
+fi
+if [[ ! -f $file ]]
+then err_exit "-f: $file should be an ordinary file"
+fi
+if [[ -d $file ]]
+then err_exit "-f: $file should not be a directory file"
+fi
+if [[ ! -d . ]]
+then err_exit "-d: . should not be a directory file"
+fi
+if [[ -f /dev/null ]]
+then err_exit "-f: /dev/null should not be an ordinary file"
+fi
+chmod 000 $file
+if [[ -r $file ]]
+then err_exit "-r: $file should not be readable"
+fi
+if [[ ! -O $file ]]
+then err_exit "-r: $file should be owned by me"
+fi
+if [[ -w $file ]]
+then err_exit "-w: $file should not be writable"
+fi
+if [[ -w $file ]]
+then err_exit "-x: $file should not be executable"
+fi
+if [[ -w $file || -r $file ]]
+then err_exit "-rw: $file should not be readable/writable"
+fi
+if [[ -z x && -z x || ! -z x ]]
+then :
+else err_exit " wrong precedence"
+fi
+if [[ -z x && (-z x || ! -z x) ]]
+then err_exit " () grouping not working"
+fi
+if [[ foo < bar ]]
+then err_exit "foo comes before bar"
+fi
+[[ . -ef $(pwd) ]] || err_exit ". is not $PWD"
+set -o allexport
+[[ -o allexport ]] || err_exit '-o: did not set allexport option'
+if [[ -n $null ]]
+then err_exit "'$null' has non-zero length"
+fi
+if [[ ! -r /dev/fd/0 ]]
+then err_exit "/dev/fd/0 not open for reading"
+fi
+if [[ ! -w /dev/fd/2 ]]
+then err_exit "/dev/fd/2 not open for writing"
+fi
+sleep 1
+> $newer_file
+if [[ ! $file -ot $newer_file ]]
+then err_exit "$file should be older than $newer_file"
+fi
+if [[ $file -nt $newer_file ]]
+then err_exit "$newer_file should be newer than $file"
+fi
+if [[ $file != $tmp/* ]]
+then err_exit "$file should match $tmp/*"
+fi
+if [[ $file == $tmp'/*' ]]
+then err_exit "$file should not equal $tmp'/*'"
+fi
+[[ ! ( ! -z $null && ! -z x) ]] || err_exit "negation and grouping"
+[[ -z '' || -z '' || -z '' ]] || err_exit "three ors not working"
+[[ -z '' && -z '' && -z '' ]] || err_exit "three ors not working"
+(exit 8)
+if [[ $? -ne 8 || $? -ne 8 ]]
+then err_exit 'value $? within [[...]]'
+fi
+x='(x'
+if [[ '(x' != '('* ]]
+then err_exit " '(x' does not match '('* within [[...]]"
+fi
+if [[ '(x' != "("* ]]
+then err_exit ' "(x" does not match "("* within [[...]]'
+fi
+if [[ '(x' != \(* ]]
+then err_exit ' "(x" does not match \(* within [[...]]'
+fi
+if [[ 'x(' != *'(' ]]
+then err_exit " 'x(' does not match '('* within [[...]]"
+fi
+if [[ 'x&' != *'&' ]]
+then err_exit " 'x&' does not match '&'* within [[...]]"
+fi
+if [[ 'xy' == *'*' ]]
+then err_exit " 'xy' matches *'*' within [[...]]"
+fi
+if [[ 3 > 4 ]]
+then err_exit '3 < 4'
+fi
+if [[ 4 < 3 ]]
+then err_exit '3 > 4'
+fi
+if [[ 3x > 4x ]]
+then err_exit '3x < 4x'
+fi
+x='@(bin|dev|?)'
+cd /
+if [[ $(print $x) != "$x" ]]
+then err_exit 'extended pattern matching on command arguments'
+fi
+if [[ dev != $x ]]
+then err_exit 'extended pattern matching not working on variables'
+fi
+if [[ -u $SHELL ]]
+then err_exit "setuid on $SHELL"
+fi
+if [[ -g $SHELL ]]
+then err_exit "setgid on $SHELL"
+fi
+test -d . -a '(' ! -f . ')' || err_exit 'test not working'
+if [[ '!' != ! ]]
+then err_exit 'quoting unary operator not working'
+fi
+test \( -n x \) -o \( -n y \) 2> /dev/null || err_exit 'test ( -n x ) -o ( -n y) not working'
+test \( -n x \) -o -n y 2> /dev/null || err_exit 'test ( -n x ) -o -n y not working'
+chmod 600 $file
+exec 4> $file
+print -u4 foobar
+if [[ ! -s $file ]]
+then err_exit "-s: $file should be non-zero"
+fi
+exec 4>&-
+if [[ 011 -ne 11 ]]
+then err_exit "leading zeros in arithmetic compares not ignored"
+fi
+{
+ set -x
+ [[ foo > bar ]]
+} 2> /dev/null || { set +x; err_exit "foo<bar with -x enabled" ;}
+set +x
+(
+ eval "[[ (a) ]]"
+) 2> /dev/null || err_exit "[[ (a) ]] not working"
+> $file
+chmod 4755 "$file"
+if test -u $file && test ! -u $file
+then err_exit "test ! -u suidfile not working"
+fi
+for i in '(' ')' '[' ']'
+do [[ $i == $i ]] || err_exit "[[ $i != $i ]]"
+done
+(
+ [[ aaaa == {4}(a) ]] || err_exit 'aaaa != {4}(a)'
+ [[ aaaa == {2,5}(a) ]] || err_exit 'aaaa != {2,4}(a)'
+ [[ abcdcdabcd == {3,6}(ab|cd) ]] || err_exit 'abcdcdabcd == {3,4}(ab|cd)'
+ [[ abcdcdabcde == {5}(ab|cd)e ]] || err_exit 'abcdcdabcd == {5}(ab|cd)e'
+) || err_exit 'errors with {..}(...) patterns'
+[[ D290.2003.02.16.temp == D290.+(2003.02.16).temp* ]] || err_exit 'pattern match bug with +(...)'
+rm -rf $file
+{
+[[ -N $file ]] && err_exit 'test -N $tmp/*: st_mtime>st_atime after creat'
+sleep 2
+print 'hello world'
+[[ -N $file ]] || err_exit 'test -N $tmp/*: st_mtime<=st_atime after write'
+sleep 2
+read
+[[ -N $file ]] && err_exit 'test -N $tmp/*: st_mtime>st_atime after read'
+} > $file < $file
+if rm -rf "$file" && ln -s / "$file"
+then [[ -L "$file" ]] || err_exit '-L not working'
+ [[ -L "$file"/ ]] && err_exit '-L with file/ not working'
+fi
+$SHELL -c 't=1234567890; [[ $t == @({10}(\d)) ]]' 2> /dev/null || err_exit ' @({10}(\d)) pattern not working'
+$SHELL -c '[[ att_ == ~(E)(att|cus)_.* ]]' 2> /dev/null || err_exit ' ~(E)(att|cus)_* pattern not working'
+$SHELL -c '[[ att_ =~ (att|cus)_.* ]]' 2> /dev/null || err_exit ' =~ ere not working'
+$SHELL -c '[[ abc =~ a(b)c ]]' 2> /dev/null || err_exit '[[ abc =~ a(b)c ]] fails'
+$SHELL -xc '[[ abc =~ \babc\b ]]' 2> /dev/null || err_exit '[[ abc =~ \babc\b ]] fails'
+[[ abc == ~(E)\babc\b ]] || err_exit '\b not preserved for ere when not in ()'
+[[ abc == ~(iEi)\babc\b ]] || err_exit '\b not preserved for ~(iEi) when not in ()'
+
+e=$($SHELL -c '[ -z "" -a -z "" ]' 2>&1)
+[[ $e ]] && err_exit "[ ... ] compatibility check failed -- $e"
+i=hell
+[[ hell0 == $i[0] ]] || err_exit 'pattern $i[0] interpreded as array ref'
+test '(' = ')' && err_exit '"test ( = )" should not be true'
+[[ $($SHELL -c 'case F in ~(Eilr)[a-z0-9#]) print ok;;esac' 2> /dev/null) == ok ]] || err_exit '~(Eilr) not working in case command'
+[[ $($SHELL -c "case Q in ~(Fi)q | \$'\E') print ok;;esac" 2> /dev/null) == ok ]] || err_exit '~(Fi)q | \E not working in case command'
+
+for l in C en_US.ISO8859-15
+do [[ $($SHELL -c "LC_COLLATE=$l" 2>&1) ]] && continue
+ export LC_COLLATE=$l
+ set -- \
+ 'A' 0 1 1 0 1 1 1 0 0 1 0 0 \
+ 'Z' 0 1 1 0 1 1 1 0 0 1 0 0 \
+ '/' 0 0 0 0 0 0 1 1 1 1 1 1 \
+ '.' 0 0 0 0 0 0 1 1 1 1 1 1 \
+ '_' 0 0 0 0 0 0 1 1 1 1 1 1 \
+ '-' 1 1 1 1 1 1 0 0 0 0 0 0 \
+ '%' 0 0 0 0 0 0 1 1 1 1 1 1 \
+ '@' 0 0 0 0 0 0 1 1 1 1 1 1 \
+ '!' 0 0 0 0 0 0 1 1 1 1 1 1 \
+ '^' 0 0 0 0 0 0 1 1 1 1 1 1 \
+ # retain this line #
+ while (( $# >= 13 ))
+ do c=$1
+ shift
+ for p in \
+ '[![.-.]]' \
+ '[![.-.][:upper:]]' \
+ '[![.-.]A-Z]' \
+ '[!-]' \
+ '[!-[:upper:]]' \
+ '[!-A-Z]' \
+ '[[.-.]]' \
+ '[[.-.][:upper:]]' \
+ '[[.-.]A-Z]' \
+ '[-]' \
+ '[-[:upper:]]' \
+ '[-A-Z]' \
+ # retain this line #
+ do e=$1
+ shift
+ [[ $c == $p ]]
+ g=$?
+ [[ $g == $e ]] || err_exit "[[ '$c' == $p ]] for LC_COLLATE=$l failed -- expected $e, got $g"
+ done
+ done
+done
+integer n
+if ( : < /dev/tty ) 2>/dev/null && exec {n}< /dev/tty
+then [[ -t $n ]] || err_exit "[[ -t n ]] fails when n > 9"
+fi
+foo=([1]=a [2]=b [3]=c)
+[[ -v foo[1] ]] || err_exit 'foo[1] should be set'
+[[ ${foo[1]+x} ]] || err_exit '${foo[1]+x} should be x'
+[[ ${foo[@]+x} ]] || err_exit '${foo[@]+x} should be x'
+unset foo[1]
+[[ -v foo[1] ]] && err_exit 'foo[1] should not be set'
+[[ ${foo[1]+x} ]] && err_exit '${foo[1]+x} should be empty'
+bar=(a b c)
+[[ -v bar[1] ]] || err_exit 'bar[1] should be set'
+[[ ${bar[1]+x} ]] || err_exit '${foo[1]+x} should be x'
+unset bar[1]
+[[ ${bar[1]+x} ]] && err_exit '${foo[1]+x} should be empty'
+[[ -v bar ]] || err_exit 'bar should be set'
+[[ -v bar[1] ]] && err_exit 'bar[1] should not be set'
+integer z=( 1 2 4)
+[[ -v z[1] ]] || err_exit 'z[1] should be set'
+unset z[1]
+[[ -v z[1] ]] && err_exit 'z[1] should not be set'
+typeset -si y=( 1 2 4)
+[[ -v y[6] ]] && err_exit 'y[6] should not be set'
+[[ -v y[1] ]] || err_exit 'y[1] should be set'
+unset y[1]
+[[ -v y[1] ]] && err_exit 'y[1] should not be set'
+x=abc
+[[ -v x[0] ]] || err_exit 'x[0] should be set'
+[[ ${x[0]+x} ]] || err_exit print '${x[0]+x} should be x'
+[[ -v x[3] ]] && err_exit 'x[3] should not be set'
+[[ ${x[3]+x} ]] && err_exit '${x[0]+x} should be Empty'
+unset x
+[[ ${x[@]+x} ]] && err_exit '${x[@]+x} should be Empty'
+unset x y z foo bar
+
+{ x=$($SHELL -c '[[ (( $# -eq 0 )) ]] && print ok') 2> /dev/null;}
+[[ $x == ok ]] || err_exit '((...)) inside [[...]] not treated as nested ()'
+
+[[ -e /dev/fd/ ]] || err_exit '/dev/fd/ does not exits'
+[[ -e /dev/tcp/ ]] || err_exit '/dev/tcp/ does not exist'
+[[ -e /dev/udp/ ]] || err_exit '/dev/udp/ does not exist'
+[[ -e /dev/xxx/ ]] && err_exit '/dev/xxx/ exists'
+
+$SHELL 2> /dev/null -c '[[(-n foo)]]' || err_exit '[[(-n foo)]] should not require space in front of ('
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/builtins.sh b/src/cmd/ksh93/tests/builtins.sh
new file mode 100755
index 0000000..6346aff
--- /dev/null
+++ b/src/cmd/ksh93/tests/builtins.sh
@@ -0,0 +1,562 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2012 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+# test shell builtin commands
+builtin getconf
+: ${foo=bar} || err_exit ": failed"
+[[ $foo == bar ]] || err_exit ": side effects failed"
+set -- - foobar
+[[ $# == 2 && $1 == - && $2 == foobar ]] || err_exit "set -- - foobar failed"
+set -- -x foobar
+[[ $# == 2 && $1 == -x && $2 == foobar ]] || err_exit "set -- -x foobar failed"
+getopts :x: foo || err_exit "getopts :x: returns false"
+[[ $foo == x && $OPTARG == foobar ]] || err_exit "getopts :x: failed"
+OPTIND=1
+getopts :r:s var -r
+if [[ $var != : || $OPTARG != r ]]
+then err_exit "'getopts :r:s var -r' not working"
+fi
+OPTIND=1
+getopts :d#u OPT -d 16177
+if [[ $OPT != d || $OPTARG != 16177 ]]
+then err_exit "'getopts :d#u OPT=d OPTARG=16177' failed -- OPT=$OPT OPTARG=$OPTARG"
+fi
+OPTIND=1
+while getopts 'ab' option -a -b
+do [[ $OPTIND == $((OPTIND)) ]] || err_exit "OPTIND optimization bug"
+done
+
+USAGE=$'[-][S:server?Operate on the specified \asubservice\a:]:[subservice:=pmserver]
+ {
+ [p:pmserver]
+ [r:repserver]
+ [11:notifyd]
+ }'
+set pmser p rep r notifyd -11
+while (( $# > 1 ))
+do OPTIND=1
+ getopts "$USAGE" OPT -S $1
+ [[ $OPT == S && $OPTARG == $2 ]] || err_exit "OPT=$OPT OPTARG=$OPTARG -- expected OPT=S OPTARG=$2"
+ shift 2
+done
+
+false ${foo=bar} && err_exit "false failed"
+read <<!
+hello world
+!
+[[ $REPLY == 'hello world' ]] || err_exit "read builtin failed"
+print x:y | IFS=: read a b
+if [[ $a != x ]]
+then err_exit "IFS=: read ... not working"
+fi
+read <<!
+hello \
+world
+!
+[[ $REPLY == 'hello world' ]] || err_exit "read continuation failed"
+read -d x <<!
+hello worldxfoobar
+!
+[[ $REPLY == 'hello world' ]] || err_exit "read builtin failed"
+read <<\!
+hello \
+ world \
+
+!
+[[ $REPLY == 'hello world' ]] || err_exit "read continuation2 failed"
+print "one\ntwo" | { read line
+ print $line | /bin/cat > /dev/null
+ read line
+}
+read <<\!
+\
+a\
+\
+\
+b
+!
+if [[ $REPLY != ab ]]
+then err_exit "read multiple continuation failed"
+fi
+if [[ $line != two ]]
+then err_exit "read from pipeline failed"
+fi
+line=two
+read line < /dev/null
+if [[ $line != "" ]]
+then err_exit "read from /dev/null failed"
+fi
+if [[ $(print -R -) != - ]]
+then err_exit "print -R not working correctly"
+fi
+if [[ $(print -- -) != - ]]
+then err_exit "print -- not working correctly"
+fi
+print -f "hello%nbar\n" size > /dev/null
+if (( size != 5 ))
+then err_exit "%n format of printf not working"
+fi
+print -n -u2 2>&1-
+[[ -w /dev/fd/1 ]] || err_exit "2<&1- with built-ins has side effects"
+x=$0
+if [[ $(eval 'print $0') != $x ]]
+then err_exit '$0 not correct for eval'
+fi
+$SHELL -c 'read x <<< hello' 2> /dev/null || err_exit 'syntax <<< not recognized'
+($SHELL -c 'read x[1] <<< hello') 2> /dev/null || err_exit 'read x[1] not working'
+unset x
+readonly x
+set -- $(readonly)
+if [[ " $@ " != *" x "* ]]
+then err_exit 'unset readonly variables are not displayed'
+fi
+if [[ $( for i in foo bar
+ do print $i
+ continue 10
+ done
+ ) != $'foo\nbar' ]]
+then err_exit 'continue breaks out of loop'
+fi
+(continue bad 2>/dev/null && err_exit 'continue bad should return an error')
+(break bad 2>/dev/null && err_exit 'break bad should return an error')
+(continue 0 2>/dev/null && err_exit 'continue 0 should return an error')
+(break 0 2>/dev/null && err_exit 'break 0 should return an error')
+breakfun() { break;}
+continuefun() { continue;}
+for fun in break continue
+do if [[ $( for i in foo
+ do ${fun}fun
+ print $i
+ done
+ ) != foo ]]
+ then err_exit "$fun call in ${fun}fun breaks out of for loop"
+ fi
+done
+if [[ $(print -f "%b" "\a\n\v\b\r\f\E\03\\oo") != $'\a\n\v\b\r\f\E\03\\oo' ]]
+then err_exit 'print -f "%b" not working'
+fi
+if [[ $(print -f "%P" "[^x].*b\$") != '*[!x]*b' ]]
+then err_exit 'print -f "%P" not working'
+fi
+if [[ $(abc: for i in foo bar;do print $i;break abc;done) != foo ]]
+then err_exit 'break labels not working'
+fi
+if [[ $(command -v if) != if ]]
+then err_exit 'command -v not working'
+fi
+read -r var <<\!
+
+!
+if [[ $var != "" ]]
+then err_exit "read -r of blank line not working"
+fi
+mkdir -p $tmp/a/b/c 2>/dev/null || err_exit "mkdir -p failed"
+$SHELL -c "cd $tmp/a/b; cd c" 2>/dev/null || err_exit "initial script relative cd fails"
+
+trap 'print TERM' TERM
+exp=$'trap -- \'print TERM\' TERM\ntrap -- \'cd /; rm -rf '$tmp$'\' EXIT'
+got=$(trap)
+[[ $got == $exp ]] || err_exit "\$(trap) failed -- expected \"$exp\", got \"$got\""
+exp='print TERM'
+got=$(trap -p TERM)
+[[ $got == $exp ]] || err_exit "\$(trap -p TERM) failed -- expected \"$exp\", got \"$got\""
+
+[[ $($SHELL -c 'trap "print ok" SIGTERM; kill -s SIGTERM $$' 2> /dev/null) == ok ]] || err_exit 'SIGTERM not recognized'
+[[ $($SHELL -c 'trap "print ok" sigterm; kill -s sigterm $$' 2> /dev/null) == ok ]] || err_exit 'SIGTERM not recognized'
+[[ $($SHELL -c '( trap "" TERM);kill $$;print bad' == bad) ]] 2> /dev/null && err_exit 'trap ignored in subshell causes it to be ignored by parent'
+${SHELL} -c 'kill -1 -$$' 2> /dev/null
+[[ $(kill -l $?) == HUP ]] || err_exit 'kill -1 -pid not working'
+${SHELL} -c 'kill -1 -$$' 2> /dev/null
+[[ $(kill -l $?) == HUP ]] || err_exit 'kill -n1 -pid not working'
+${SHELL} -c 'kill -s HUP -$$' 2> /dev/null
+[[ $(kill -l $?) == HUP ]] || err_exit 'kill -HUP -pid not working'
+n=123
+typeset -A base
+base[o]=8#
+base[x]=16#
+base[X]=16#
+for i in d i o u x X
+do if (( $(( ${base[$i]}$(printf "%$i" $n) )) != n ))
+ then err_exit "printf %$i not working"
+ fi
+done
+if [[ $( trap 'print done' EXIT) != done ]]
+then err_exit 'trap on EXIT not working'
+fi
+if [[ $( trap 'print done' EXIT; trap - EXIT) == done ]]
+then err_exit 'trap on EXIT not being cleared'
+fi
+if [[ $(LC_MESSAGES=C type test) != 'test is a shell builtin' ]]
+then err_exit 'whence -v test not a builtin'
+fi
+builtin -d test
+if [[ $(type test) == *builtin* ]]
+then err_exit 'whence -v test after builtin -d incorrect'
+fi
+typeset -Z3 percent=$(printf '%o\n' "'%'")
+forrmat=\\${percent}s
+if [[ $(printf "$forrmat") != %s ]]
+then err_exit "printf $forrmat not working"
+fi
+if (( $(printf 'x\0y' | wc -c) != 3 ))
+then err_exit 'printf \0 not working'
+fi
+if [[ $(printf "%bx%s\n" 'f\to\cbar') != $'f\to' ]]
+then err_exit 'printf %bx%s\n not working'
+fi
+alpha=abcdefghijklmnop
+if [[ $(printf "%10.*s\n" 5 $alpha) != ' abcde' ]]
+then err_exit 'printf %10.%s\n not working'
+fi
+float x2=.0000625
+if [[ $(printf "%10.5E\n" x2) != 6.25000E-05 ]]
+then err_exit 'printf "%10.5E" not normalizing correctly'
+fi
+x2=.000000001
+if [[ $(printf "%g\n" x2 2>/dev/null) != 1e-09 ]]
+then err_exit 'printf "%g" not working correctly'
+fi
+#FIXME#($SHELL read -s foobar <<\!
+#FIXME#testing
+#FIXME#!
+#FIXME#) 2> /dev/null || err_exit ksh read -s var fails
+if [[ $(printf +3 2>/dev/null) != +3 ]]
+then err_exit 'printf is not processing formats beginning with + correctly'
+fi
+if printf "%d %d\n" 123bad 78 >/dev/null 2>/dev/null
+then err_exit "printf not exiting non-zero with conversion errors"
+fi
+if [[ $(trap --version 2> /dev/null;print done) != done ]]
+then err_exit 'trap builtin terminating after --version'
+fi
+if [[ $(set --version 2> /dev/null;print done) != done ]]
+then err_exit 'set builtin terminating after --veresion'
+fi
+unset -f foobar
+function foobar
+{
+ print 'hello world'
+}
+OPTIND=1
+if [[ $(getopts $'[+?X\ffoobar\fX]' v --man 2>&1) != *'Xhello world'X* ]]
+then err_exit '\f...\f not working in getopts usage strings'
+fi
+if [[ $(printf '%H\n' $'<>"& \'\tabc') != '&lt;&gt;&quot;&amp;&nbsp;&apos;&#9;abc' ]]
+then err_exit 'printf %H not working'
+fi
+if [[ $( printf 'foo://ab_c%#H\n' $'<>"& \'\tabc') != 'foo://ab_c%3C%3E%22%26%20%27%09abc' ]]
+then err_exit 'printf %#H not working'
+fi
+if [[ $(printf '%R %R %R %R\n' 'a.b' '*.c' '^' '!(*.*)') != '^a\.b$ \.c$ ^\^$ ^(.*\..*)!$' ]]
+then err_exit 'printf %R not working'
+fi
+if [[ $(printf '%..:c\n' abc) != a:b:c ]]
+then err_exit "printf '%..:c' not working"
+fi
+if [[ $(printf '%..*c\n' : abc) != a:b:c ]]
+then err_exit "printf '%..*c' not working"
+fi
+if [[ $(printf '%..:s\n' abc def ) != abc:def ]]
+then err_exit "printf '%..:s' not working"
+fi
+if [[ $(printf '%..*s\n' : abc def) != abc:def ]]
+then err_exit "printf '%..*s' not working"
+fi
+[[ $(printf '%q\n') == '' ]] || err_exit 'printf "%q" with missing arguments'
+# we won't get hit by the one second boundary twice, right?
+[[ $(printf '%T\n' now) == "$(date)" ]] ||
+[[ $(printf '%T\n' now) == "$(date)" ]] ||
+err_exit 'printf "%T" now'
+behead()
+{
+ read line
+ left=$(cat)
+}
+print $'line1\nline2' | behead
+if [[ $left != line2 ]]
+then err_exit "read reading ahead on a pipe"
+fi
+read -n1 y <<!
+abc
+!
+exp=a
+if [[ $y != $exp ]]
+then err_exit "read -n1 failed -- expected '$exp', got '$y'"
+fi
+print -n $'{ read -r line;print $line;}\nhello' > $tmp/script
+chmod 755 $tmp/script
+if [[ $($SHELL < $tmp/script) != hello ]]
+then err_exit 'read of incomplete line not working correctly'
+fi
+set -f
+set -- *
+if [[ $1 != '*' ]]
+then err_exit 'set -f not working'
+fi
+unset pid1 pid2
+false &
+pid1=$!
+pid2=$(
+ wait $pid1
+ (( $? == 127 )) || err_exit "job known to subshell"
+ print $!
+)
+wait $pid1
+(( $? == 1 )) || err_exit "wait not saving exit value"
+wait $pid2
+(( $? == 127 )) || err_exit "subshell job known to parent"
+env=
+v=$(getconf LIBPATH)
+for v in ${v//,/ }
+do v=${v#*:}
+ v=${v%%:*}
+ eval [[ \$$v ]] && env="$env $v=\"\$$v\""
+done
+if [[ $(foo=bar; eval foo=\$foo $env exec -c \$SHELL -c \'print \$foo\') != bar ]]
+then err_exit '"name=value exec -c ..." not working'
+fi
+$SHELL -c 'OPTIND=-1000000; getopts a opt -a' 2> /dev/null
+[[ $? == 1 ]] || err_exit 'getopts with negative OPTIND not working'
+getopts 'n#num' opt -n 3
+[[ $OPTARG == 3 ]] || err_exit 'getopts with numerical arguments failed'
+if [[ $($SHELL -c $'printf \'%2$s %1$s\n\' world hello') != 'hello world' ]]
+then err_exit 'printf %2$s %1$s not working'
+fi
+val=$(( 'C' ))
+set -- \
+ "'C" $val 0 \
+ "'C'" $val 0 \
+ '"C' $val 0 \
+ '"C"' $val 0 \
+ "'CX" $val 1 \
+ "'CX'" $val 1 \
+ "'C'X" $val 1 \
+ '"CX' $val 1 \
+ '"CX"' $val 1 \
+ '"C"X' $val 1
+while (( $# >= 3 ))
+do arg=$1 val=$2 code=$3
+ shift 3
+ for fmt in '%d' '%g'
+ do out=$(printf "$fmt" "$arg" 2>/dev/null)
+ err=$(printf "$fmt" "$arg" 2>&1 >/dev/null)
+ printf "$fmt" "$arg" >/dev/null 2>&1
+ ret=$?
+ [[ $out == $val ]] || err_exit "printf $fmt $arg failed -- expected '$val', got '$out'"
+ if (( $code ))
+ then [[ $err ]] || err_exit "printf $fmt $arg failed, error message expected"
+ else [[ $err ]] && err_exit "$err: printf $fmt $arg failed, error message not expected -- got '$err'"
+ fi
+ (( $ret == $code )) || err_exit "printf $fmt $arg failed -- expected exit code $code, got $ret"
+ done
+done
+((n=0))
+((n++)); ARGC[$n]=1 ARGV[$n]=""
+((n++)); ARGC[$n]=2 ARGV[$n]="-a"
+((n++)); ARGC[$n]=4 ARGV[$n]="-a -v 2"
+((n++)); ARGC[$n]=4 ARGV[$n]="-a -v 2 x"
+((n++)); ARGC[$n]=4 ARGV[$n]="-a -v 2 x y"
+for ((i=1; i<=n; i++))
+do set -- ${ARGV[$i]}
+ OPTIND=0
+ while getopts -a tst "av:" OPT
+ do :
+ done
+ if [[ $OPTIND != ${ARGC[$i]} ]]
+ then err_exit "\$OPTIND after getopts loop incorrect -- expected ${ARGC[$i]}, got $OPTIND"
+ fi
+done
+options=ab:c
+optarg=foo
+set -- -a -b $optarg -c bar
+while getopts $options opt
+do case $opt in
+ a|c) [[ $OPTARG ]] && err_exit "getopts $options \$OPTARG for flag $opt failed, expected \"\", got \"$OPTARG\"" ;;
+ b) [[ $OPTARG == $optarg ]] || err_exit "getopts $options \$OPTARG failed -- \"$optarg\" expected, got \"$OPTARG\"" ;;
+ *) err_exit "getopts $options failed -- got flag $opt" ;;
+ esac
+done
+
+[[ $($SHELL 2> /dev/null -c 'readonly foo; getopts a: foo -a blah; echo foo') == foo ]] || err_exit 'getopts with readonly variable causes script to abort'
+
+unset a
+{ read -N3 a; read -N1 b;} <<!
+abcdefg
+!
+exp=abc
+[[ $a == $exp ]] || err_exit "read -N3 here-document failed -- expected '$exp', got '$a'"
+exp=d
+[[ $b == $exp ]] || err_exit "read -N1 here-document failed -- expected '$exp', got '$b'"
+read -n3 a <<!
+abcdefg
+!
+exp=abc
+[[ $a == $exp ]] || err_exit "read -n3 here-document failed -- expected '$exp', got '$a'"
+#(print -n a;sleep 1; print -n bcde) | { read -N3 a; read -N1 b;}
+#[[ $a == $exp ]] || err_exit "read -N3 from pipe failed -- expected '$exp', got '$a'"
+#exp=d
+#[[ $b == $exp ]] || err_exit "read -N1 from pipe failed -- expected '$exp', got '$b'"
+#(print -n a;sleep 1; print -n bcde) | read -n3 a
+#exp=a
+#[[ $a == $exp ]] || err_exit "read -n3 from pipe failed -- expected '$exp', got '$a'"
+#rm -f $tmp/fifo
+#if mkfifo $tmp/fifo 2> /dev/null
+#then (print -n a; sleep 1;print -n bcde) > $tmp/fifo &
+# {
+# read -u5 -n3 -t2 a || err_exit 'read -n3 from fifo timedout'
+# read -u5 -n1 -t2 b || err_exit 'read -n1 from fifo timedout'
+# } 5< $tmp/fifo
+# exp=a
+# [[ $a == $exp ]] || err_exit "read -n3 from fifo failed -- expected '$exp', got '$a'"
+# rm -f $tmp/fifo
+# mkfifo $tmp/fifo 2> /dev/null
+# (print -n a; sleep 1;print -n bcde) > $tmp/fifo &
+# {
+# read -u5 -N3 -t2 a || err_exit 'read -N3 from fifo timed out'
+# read -u5 -N1 -t2 b || err_exit 'read -N1 from fifo timedout'
+# } 5< $tmp/fifo
+# exp=abc
+# [[ $a == $exp ]] || err_exit "read -N3 from fifo failed -- expected '$exp', got '$a'"
+# exp=d
+# [[ $b == $exp ]] || err_exit "read -N1 from fifo failed -- expected '$exp', got '$b'"
+#fi
+#rm -f $tmp/fifo
+
+function longline
+{
+ integer i
+ for((i=0; i < $1; i++))
+ do print argument$i
+ done
+}
+# test command -x option
+integer sum=0 n=10000
+if ! ${SHELL:-ksh} -c 'print $#' count $(longline $n) > /dev/null 2>&1
+then for i in $(command command -x ${SHELL:-ksh} -c 'print $#;[[ $1 != argument0 ]]' count $(longline $n) 2> /dev/null)
+ do ((sum += $i))
+ done
+ (( sum == n )) || err_exit "command -x processed only $sum arguments"
+ command -p command -x ${SHELL:-ksh} -c 'print $#;[[ $1 == argument0 ]]' count $(longline $n) > /dev/null 2>&1
+ [[ $? != 1 ]] && err_exit 'incorrect exit status for command -x'
+fi
+# test command -x option with extra arguments
+integer sum=0 n=10000
+if ! ${SHELL:-ksh} -c 'print $#' count $(longline $n) > /dev/null 2>&1
+then for i in $(command command -x ${SHELL:-ksh} -c 'print $#;[[ $1 != argument0 ]]' count $(longline $n) one two three) #2> /dev/null)
+ do ((sum += $i))
+ done
+ (( sum > n )) || err_exit "command -x processed only $sum arguments"
+ (( (sum-n)%3==0 )) || err_exit "command -x processed only $sum arguments"
+ (( sum == n+3)) && err_exit "command -x processed only $sum arguments"
+ command -p command -x ${SHELL:-ksh} -c 'print $#;[[ $1 == argument0 ]]' count $(longline $n) > /dev/null 2>&1
+ [[ $? != 1 ]] && err_exit 'incorrect exit status for command -x'
+fi
+# test for debug trap
+[[ $(typeset -i i=0
+ trap 'print $i' DEBUG
+ while (( i <2))
+ do (( i++))
+ done) == $'0\n0\n1\n1\n2' ]] || err_exit "DEBUG trap not working"
+getconf UNIVERSE - ucb
+[[ $($SHELL -c 'echo -3') == -3 ]] || err_exit "echo -3 not working in ucb universe"
+typeset -F3 start_x=SECONDS total_t delay=0.02
+typeset reps=50 leeway=5
+#sleep $(( 2 * leeway * reps * delay )) |
+#for (( i=0 ; i < reps ; i++ ))
+#do read -N1 -t $delay
+#done
+#(( total_t = SECONDS - start_x ))
+#if (( total_t > leeway * reps * delay ))
+#then err_exit "read -t in pipe taking $total_t secs - $(( reps * delay )) minimum - too long"
+#elif (( total_t < reps * delay ))
+#then err_exit "read -t in pipe taking $total_t secs - $(( reps * delay )) minimum - too fast"
+#fi
+#$SHELL -c 'sleep $(printf "%a" .95)' 2> /dev/null || err_exit "sleep doesn't except %a format constants"
+#$SHELL -c 'test \( ! -e \)' 2> /dev/null ; [[ $? == 1 ]] || err_exit 'test \( ! -e \) not working'
+[[ $(ulimit) == "$(ulimit -fS)" ]] || err_exit 'ulimit is not the same as ulimit -fS'
+tmpfile=$tmp/file.2
+print $'\nprint -r -- "${.sh.file} ${LINENO} ${.sh.lineno}"' > $tmpfile
+[[ $( . "$tmpfile") == "$tmpfile 2 1" ]] || err_exit 'dot command not working'
+print -r -- "'xxx" > $tmpfile
+[[ $($SHELL -c ". $tmpfile"$'\n print ok' 2> /dev/null) == ok ]] || err_exit 'syntax error in dot command affects next command'
+
+#float sec=$SECONDS del=4
+#exec 3>&2 2>/dev/null
+#$SHELL -c "( sleep 1; kill -ALRM \$\$ ) & sleep $del" 2> /dev/null
+#exitval=$?
+#(( sec = SECONDS - sec ))
+#exec 2>&3-
+#(( exitval )) && err_exit "sleep doesn't exit 0 with ALRM interupt"
+#(( sec > (del - 1) )) || err_exit "ALRM signal causes sleep to terminate prematurely -- expected 3 sec, got $sec"
+typeset -r z=3
+y=5
+for i in 123 z %x a.b.c
+do ( unset $i) 2>/dev/null && err_exit "unset $i should fail"
+done
+a=()
+for i in y y y[8] t[abc] y.d a.b a
+do unset $i || print -u2 "err_exit unset $i should not fail"
+done
+[[ $($SHELL -c 'y=3; unset 123 y;print $?$y') == 1 ]] 2> /dev/null || err_exit 'y is not getting unset with unset 123 y'
+[[ $($SHELL -c 'trap foo TERM; (trap;(trap) )') == 'trap -- foo TERM' ]] || err_exit 'traps not getting reset when subshell is last process'
+
+n=$(printf "%b" 'a\0b\0c' | wc -c)
+(( n == 5 )) || err_exit '\0 not working with %b format with printf'
+
+t=$(ulimit -t)
+[[ $($SHELL -c 'ulimit -v 15000 2>/dev/null; ulimit -t') == "$t" ]] || err_exit 'ulimit -v changes ulimit -t'
+
+$SHELL 2> /dev/null -c 'cd ""' && err_exit 'cd "" not producing an error'
+[[ $($SHELL 2> /dev/null -c 'cd "";print hi') != hi ]] && err_exit 'cd "" should not terminate script'
+
+bincat=$(whence -p cat)
+builtin cat
+out=$tmp/seq.out
+seq 11 >$out
+cmp -s <(print -- "$($bincat<( $bincat $out ) )") <(print -- "$(cat <( cat $out ) )") || err_exit "builtin cat differs from $bincat"
+
+[[ $($SHELL -c '{ printf %R "["; print ok;}' 2> /dev/null) == ok ]] || err_exit $'\'printf %R "["\' causes shell to abort'
+
+v=$( $SHELL -c $'
+ trap \'print "usr1"\' USR1
+ trap exit USR2
+ sleep 1 && {
+ kill -USR1 $$ && sleep 1
+ kill -0 $$ 2>/dev/null && kill -USR2 $$
+ } &
+ sleep 2 | read
+ echo done
+' ) 2> /dev/null
+[[ $v == $'usr1\ndone' ]] || err_exit 'read not terminating when receiving USR1 signal'
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/case.sh b/src/cmd/ksh93/tests/case.sh
new file mode 100755
index 0000000..7fe01ea
--- /dev/null
+++ b/src/cmd/ksh93/tests/case.sh
@@ -0,0 +1,85 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+bar=foo2
+bam=foo[3]
+for i in foo1 foo2 foo3 foo4 foo5 foo6
+do foo=0
+ case $i in
+ foo1) foo=1;;
+ $bar) foo=2;;
+ $bam) foo=3;;
+ foo[4]) foo=4;;
+ ${bar%?}5)
+ foo=5;;
+ "${bar%?}6")
+ foo=6;;
+ esac
+ if [[ $i != foo$foo ]]
+ then err_exit "$i not matching correct pattern"
+ fi
+done
+f="[ksh92]"
+case $f in
+\[*\]) ;;
+*) err_exit "$f does not match \[*\]";;
+esac
+
+if [[ $($SHELL -c '
+ x=$(case abc {
+ abc) { print yes;};;
+ *) print no;;
+ }
+ )
+ print -r -- "$x"' 2> /dev/null) != yes ]]
+then err_exit 'case abc {...} not working'
+fi
+[[ $($SHELL -c 'case a in
+a) print -n a > /dev/null ;&
+b) print b;;
+esac') != b ]] && err_exit 'bug in ;& at end of script'
+[[ $(VMDEBUG=1 $SHELL -c '
+ tmp=foo
+ for i in a b
+ do case $i in
+ a) : tmp=$tmp tmp.h=$tmp.h;;
+ b) ( tmp=bar )
+ for j in a
+ do print -r -- $tmp.h
+ done
+ ;;
+ esac
+ done
+') == foo.h ]] || err_exit "optimizer bug"
+
+x=$($SHELL -ec 'case a in a) echo 1; false; echo 2 ;& b) echo 3;; esac')
+[[ $x == 1 ]] || err_exit 'set -e ignored on case fail through'
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/comvar.sh b/src/cmd/ksh93/tests/comvar.sh
new file mode 100755
index 0000000..e08f972
--- /dev/null
+++ b/src/cmd/ksh93/tests/comvar.sh
@@ -0,0 +1,689 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+#test for compound variables
+Command=${0##*/}
+integer Errors=0
+Point=(
+ float x=1. y=0.
+)
+eval p="$Point"
+if (( (p.x*p.x + p.y*p.y) > 1.01 ))
+then err_exit 'compound variable not working'
+fi
+nameref foo=p
+if [[ ${foo.x} != ${Point.x} ]]
+then err_exit 'reference to compound object not working'
+fi
+unset foo
+rec=(
+ name='Joe Blow'
+ born=(
+ month=jan
+ integer day=16
+ year=1980
+ )
+)
+eval newrec="$rec"
+if [[ ${newrec.name} != "${rec.name}" ]]
+then err_exit 'copying a compound object not working'
+fi
+if (( newrec.born.day != 16 ))
+then err_exit 'copying integer field of compound object not working'
+fi
+p_t=(
+ integer z=0
+ typeset -A tokens
+)
+unset x
+typeset -A x
+x=( [foo]=bar )
+if [[ ${x[@]} != bar ]]
+then err_exit 'compound assignemnt of associative arrays not working'
+fi
+unset -n foo x
+unset foo x
+foo=( x=3)
+nameref x=foo
+if [[ ${!x.@} != foo.x ]]
+then err_exit 'name references not expanded on prefix matching'
+fi
+unset x
+unset -n x
+(
+ x=()
+ x.foo.bar=7
+ [[ ${x.foo.bar} == 7 ]] || err_exit '[[ ${x.foo.bar} != 7 ]]'
+ (( x.foo.bar == 7 ))|| err_exit '(( x.foo.bar != 7 ))'
+ [[ ${x.foo} == *bar=7* ]] || err_exit '[[ ${x.foo} != *bar=7* ]]'
+)
+foo=(integer x=3)
+if [[ ${foo} != *x=3* ]]
+then err_exit "compound variable with integer subvariable not working"
+fi
+$SHELL -c $'x=(foo=bar)\n[[ x == x ]]' 2> /dev/null ||
+ err_exit '[[ ... ]] not working after compound assignment'
+unset foo
+[[ ${!foo.@} ]] && err_exit 'unset compound variable leaves subvariables'
+suitable=(
+ label="Table Viewer"
+ langs="ksh"
+ uselang=ksh
+ launch=no
+ groups="default"
+ default=(
+ label="Table Viewer Preferences"
+ entrylist=" \
+ vieworigin viewsize viewcolor viewfontname viewfontsize \
+ showheader header showfooter footer showtitle title showlegends \
+ class_td_lg1_style class_tr_tr1_style \
+ class_th_th1_style class_td_td1_style \
+ fields fieldorder \
+ "
+ entries=(
+ vieworigin=(
+ type=coord var=vieworigin val="0 0" label="Window Position"
+ )
+ viewsize=(
+ type=coord var=viewsize val="400 400" label="Window Size"
+ )
+ viewcolor=(
+ type=2colors var=viewcolor val="gray black"
+ label="Window Colors"
+ )
+ viewfontname=(
+ type=fontname var=viewfontname val="Times-Roman"
+ label="Window Font Name"
+ )
+ viewfontsize=(
+ type=fontsize var=viewfontsize val=14 label="Window Font Size"
+ )
+
+ showheader=(
+ type=yesno var=showheader val=no label="Show Header"
+ )
+ header=(
+ type=text var=header val="" label="Header"
+ )
+
+ showfooter=(
+ type=yesno var=showfooter val=no label="Show Footer"
+ )
+ footer=(
+ type=text var=footer val="" label="Footer"
+ )
+
+ showtitle=(
+ type=yesno var=showtitle val=yes label="Show Title"
+ )
+ title=(
+ type=text var=title val="SWIFTUI - Table View" label="Title"
+ )
+
+ showlegends=(
+ type=yesno var=showlegends val=yes label="Show Legends"
+ )
+
+ class_td_lg1_style=(
+ type=style var=class_td_lg1_style
+ val="color: black; font-family: Times-Roman; font-size: 14pt"
+ label="Legend 1 Style"
+ )
+
+ class_tr_tr1_style=(
+ type=style var=class_tr_tr1_style val="background: black"
+ label="Table Row 1 Style"
+ )
+
+ class_th_th1_style=(
+ type=style var=class_th_th1_style
+ val="color: black; font-family: Times-Roman; font-size: 14pt; text-align: left"
+ label="Table Header 1 Style"
+ )
+
+ class_td_td1_style=(
+ type=style var=class_td_td1_style
+ val="color: black; font-family: Times-Roman; font-size: 14pt; text-align: left"
+ label="Table Cell 1 Style"
+ )
+
+ fields=(
+ type=text var=fields val= label="List of Fields"
+ )
+ fieldorder=(
+ type=text var=fieldorder val= label="Order of Fields"
+ )
+ )
+ )
+)
+[[ "${suitable}" == *entrylist=* ]] || err_exit 'compound variable expansion omitting fields'
+foo=( bar=foo barbar=bar)
+[[ $foo == *bar=foo* ]] || err_exit 'no prefix elements in compound variable output'
+function localvar
+{
+ typeset point=(typeset -i x=3 y=4)
+ (( (point.x*point.x + point.y*point.y) == 25 )) || err_exit "local compound variable not working"
+}
+point=(integer x=6 y=8)
+localvar
+ (( (point.x*point.x + point.y*point.y) == 100 )) || err_exit "global compound variable not preserved"
+[[ $($SHELL -c 'foo=();foo.[x]=(y z); print ${foo.x[@]}') == 'y z' ]] 2> /dev/null || err_exit 'foo=( [x]=(y z) not working'
+function staticvar
+{
+ if [[ $1 ]]
+ then print -r -- "$point"
+ return
+ fi
+ typeset -S point=(typeset -i x=3 y=4)
+ (( (point.x*point.x + point.y*point.y) == 25 )) || err_exit "local compound variable not working"
+ point.y=5
+ point.z=foobar
+}
+staticvar
+ (( (point.x*point.x + point.y*point.y) == 100 )) || err_exit "global compound variable not preserved"
+[[ $(staticvar x) == $'(\n\ttypeset -i x=3\n\ttypeset -i y=5\n\tz=foobar\n)' ]] || err_exit 'static variables in function not working'
+integer x=3
+( typeset -S x=+++)2> /dev/null || err_exit "typeset -S doesn't unset first"
+
+unset z
+( [[ ${z.foo.bar:-abc} == abc ]] 2> /dev/null) || err_exit ':- not working with compound variables'
+stack=()
+typeset -a stack.items=([0]=foo [1]=bar)
+[[ ${stack.items[0]} == foo ]] || err_exit 'typeset -a variable not expanding correctly'
+$SHELL -c 'typeset -a info=( [1]=( passwd=( since=2005-07-20) ))' || err_exit 'problem with embedded index array in compound variable'
+x=(foo=([1]=(y=([2]=(z=4)))))
+[[ $x == *'.y'=* ]] && err_exit 'expansion with bogus leading . in name'
+unset z
+z=1
+function foo
+{
+ z=3
+ [[ ${a.z} == 3 ]] && err_exit "\${a.z} should not be 3"
+ print hi
+}
+a=( b=$(foo) )
+[[ ${a.z} == 3 ]] && err_exit 'a.z should not be set to 3'
+function a.b.get
+{
+ .sh.value=foo
+}
+{ b=( b1=${a.b} ) ;} 2> /dev/null
+[[ ${b.b1} == foo ]] || err_exit '${b.b1} should be foo'
+function dcl1
+{
+ eval 'a=1
+ function a.set
+ { print ${.sh.name}=${.sh.value}; }'
+}
+function dcl2
+{
+ eval 'b=(typeset x=0; typeset y=0 )
+ function b.x.set
+ { print ${.sh.name}=${.sh.value}; }'
+}
+dcl1
+[[ ${ a=123;} == 'a=123' ]] || err_exit 'should be a=123'
+dcl2
+[[ ${ b.x=456;} == 'b.x=456' ]] || err_exit 'should be b.x=456'
+eval 'b=(typeset x=0; typeset y=0 )
+function b.x.set
+{ print ${.sh.name}=${.sh.value}; }' > /dev/null
+[[ ${ b.x=789;} == 'b.x=789' ]] || err_exit 'should be b.x=789'
+unset a b
+function func
+{
+ typeset X
+ X=( bar=2 )
+}
+
+X=( foo=1 )
+func
+[[ $X == $'(\n\tfoo=1\n)' ]] || err_exit 'scoping problem with compound variables'
+unset foo
+typeset -A foo=([a]=aa;[b]=bb;[c]=cc)
+[[ ${foo[c]} == cc ]] || err_exit 'associative array assignment with; not working'
+[[ $({ $SHELL -c 'x=(); typeset -a x.foo; x.foo=bar; print -r -- "$x"' ;} 2> /dev/null) == $'(\n\ttypeset -a foo=bar\n)' ]] || err_exit 'indexed array in compound variable with only element 0 defined fails'
+unset foo
+foo=(typeset -a bar)
+[[ $foo == *'typeset -a bar'* ]] || err_exit 'array attribute -a not preserved in compound variable'
+unset s
+typeset -A s=( [foo]=(y=2 z=3) [bar]=(y=4 z=5))
+[[ ${s[@]} == *z=*z=* ]] || err_exit 'missing elements in compound associative array'
+unset nodes
+typeset -A nodes
+nodes[0]+=( integer x=5)
+[[ ${nodes[0].x} == 5 ]] || err_exit '${nodes[0].x} should be 5'
+unset foo
+typeset -C foo
+foo.bar=abc
+[[ $foo == $'(\n\tbar=abc\n)' ]] || err_exit 'typeset -C not working for foo'
+typeset -C foo=(bar=def)
+[[ $foo == $'(\n\tbar=def\n)' ]] || err_exit 'typeset -C not working when initialized'
+foo=(
+ hello=ok
+ yes=( bam=2 yes=4)
+ typeset -A array=([one]=one [two]=2)
+ last=me
+)
+eval foo2="$foo"
+foo2.hello=notok foo2.yes.yex=no foo2.extra=yes.
+typeset -C bar bam
+{
+ read -Cu3 bar
+ read -Cu3 bam
+ read -ru3
+} 3<<- ++++
+ "$foo"
+ "$foo2"
+ last line
+++++
+[[ $? == 0 ]] || err_exit ' read -C failed'
+[[ $bar == "$foo" ]] || err_exit '$foo != $bar'
+[[ $bam == "$foo2" ]] || err_exit '$foo2 != $bmr'
+[[ $REPLY == 'last line' ]] || err_exit "\$REPLY=$REPLY should be 'last line"
+typeset x=( typeset -a foo=( [1][3]=hello [9][2]="world" ) )
+eval y="(typeset -a foo=$(printf "%B\n" x.foo) )"
+[[ $x == "$y" ]] || err_exit '$x.foo != $y.foo with %B'
+eval y="(typeset -a foo=$(printf "%#B\n" x.foo) )"
+[[ $x == "$y" ]] || err_exit '$x.foo != $y.foo with %#B'
+eval y="$(printf "%B\n" x)"
+[[ $x == "$y" ]] || err_exit '$x != $y with %B'
+eval y="$(printf "%#B\n" x)"
+[[ $x == "$y" ]] || err_exit '$x != $y with %#B'
+y=$(set | grep ^x=) 2> /dev/null
+eval "${y/#x/y}"
+[[ $x == "$y" ]] || err_exit '$x != $y with set | grep'
+unset x y z
+x=( float x=0 y=1; z=([foo]=abc [bar]=def))
+typeset -C y=x
+[[ $x == "$y" ]] || err_exit '$x != $y with typeset -C'
+unset y
+y=()
+y=x
+[[ $x == "$y" ]] || err_exit '$x != $y when x=y and x and y are -C '
+function foobar
+{
+ typeset -C z
+ z=x
+ [[ $x == "$z" ]] || err_exit '$x != $z when x=z and x and z are -C '
+ y=z
+}
+[[ $x == "$y" ]] || err_exit '$x != $y when x=y -C copied in a function '
+z=(foo=abc)
+y+=z
+[[ $y == *foo=abc* ]] || err_exit 'z not appended to y'
+unset y.foo
+[[ $x == "$y" ]] || err_exit '$x != $y when y.foo deleted'
+unset x y
+x=( foo=(z=abc d=ghi) bar=abc; typeset -A r=([x]=3 [y]=4))
+unset x
+x=()
+[[ $x == $'(\n)' ]] || err_exit 'unset compound variable is not empty'
+
+unset z
+z=()
+z.foo=( [one]=hello [two]=(x=3 y=4) [three]=hi)
+z.bar[0]=hello
+z.bar[2]=world
+z.bar[1]=(x=4 y=5)
+exp='(
+ typeset -a bar=(
+ [0]=hello
+ [2]=world
+ [1]=(
+ x=4
+ y=5
+ )
+ )
+ typeset -A foo=(
+ [one]=hello
+ [three]=hi
+ [two]=(
+ x=3
+ y=4
+ )
+ )
+)'
+got=$z
+[[ $got == "$exp" ]] || {
+ exp=$(printf %q "$exp")
+ got=$(printf %q "$got")
+ err_exit "compound indexed array pretty print failed -- expected $exp, got $got"
+}
+
+typeset -A record
+record[a]=(
+ typeset -a x=(
+ [1]=(
+ X=1
+ )
+ )
+)
+exp=$'(\n\ttypeset -a x=(\n\t\t[1]=(\n\t\t\tX=1\n\t\t)\n\t)\n)'
+got=${record[a]}
+[[ $got == "$exp" ]] || {
+ exp=$(printf %q "$exp")
+ got=$(printf %q "$got")
+ err_exit "compound indexed array pretty print failed -- expected $exp, got $got"
+}
+
+unset r
+r=(
+ typeset -a x=(
+ [1]=(
+ X=1
+ )
+ )
+)
+exp=$'(\n\ttypeset -a x=(\n\t\t[1]=(\n\t\t\tX=1\n\t\t)\n\t)\n)'
+got=$r
+[[ $got == "$exp" ]] || {
+ exp=$(printf %q "$exp")
+ got=$(printf %q "$got")
+ err_exit "compound indexed array pretty print failed -- expected $exp, got $got"
+}
+
+# array of compund variables
+typeset -C data=(
+ typeset -a samples
+)
+data.samples+=(
+ type1="greeting1"
+ timestamp1="now1"
+ command1="grrrr1"
+)
+data.samples+=(
+ type2="greeting2"
+ timestamp2="now2"
+ command2="grrrr2"
+)
+
+[[ $data == %(()) ]] || err_exit "unbalanced parenthesis with compound variable containing array of compound variables"
+typeset -C -A hello=( [foo]=bar)
+[[ $(typeset -p hello) == 'typeset -C -A hello=([foo]=bar)' ]] || err_exit 'typeset -A -C with intial assignment not working'
+# this caused a core dump before ksh93t+
+[[ $($SHELL -c 'foo=(x=3 y=4);function bar { typeset z=4;: $z;};bar;print ${!foo.@}') == 'foo.x foo.y' ]] 2> /dev/null || err_exit '${!foo.@} after function not working'
+
+function foo
+{
+ typeset tmp
+ read -C tmp
+ read -C tmp
+}
+foo 2> /dev/null <<- \EOF || err_exit 'deleting compound variable in function failed'
+ (
+ typeset -A myarray3=(
+ [a]=( foo=bar)
+ [b]=( foo=bar)
+ [c d]=( foo=bar)
+ [e]=( foo=bar)
+ [f]=( foo=bar)
+ [g]=( foo=bar)
+ [h]=( foo=bar)
+ [i]=( foo=bar)
+ [j]=( foo=bar)
+ )
+ )
+ hello
+EOF
+
+typeset -C -a mica01
+mica01[4]=( a_string="foo bar" )
+typeset -C more_content=(
+ some_stuff="hello"
+)
+mica01[4]+=more_content
+expected=$'typeset -C -a mica01=([4]=(a_string=\'foo bar\';some_stuff=hello))'
+[[ $(typeset -p mica01) == "$expected" ]] || err_exit 'appened to indexed array compound variable not working'
+
+unset x
+compound x=( integer x ; )
+[[ ! -v x.x ]] && err_exit 'x.x should be set'
+expected=$'(\n\ttypeset -l -i x=0\n)'
+[[ $(print -v x) == "$expected" ]] || err_exit "'print -v x' should be $expected"
+
+typeset -C -A hello19=(
+ [19]=(
+ one="xone 19"
+ two="xtwo 19"
+ )
+ [23]=(
+ one="xone 23"
+ two="xtwo 23"
+ )
+)
+expected="typeset -C -A hello19=([19]=(one='xone 19';two='xtwo 19') [23]=(one='xone 23';two='xtwo 23'))"
+[[ $(typeset -p hello19) == "$expected" ]] || print -u2 'typeset -p hello19 incorrect'
+expected=$'(\n\tone=\'xone 19\'\n\ttwo=\'xtwo 19\'\n) (\n\tone=\'xone 23\'\n\ttwo=\'xtwo 23\'\n)'
+[[ ${hello19[@]} == "$expected" ]] || print -u2 '${hello19[@]} incorrect'
+
+typeset -C -A foo1=( abc="alphabet" ) foo2=( abc="alphabet" )
+function add_one
+{
+ nameref left_op=$1
+ typeset -C info
+ info.hello="world"
+ nameref x=info
+ left_op+=x
+}
+nameref node1="foo1[1234]"
+add_one "node1"
+add_one "foo2[1234]"
+[[ "${foo1[1234]}" == "${foo2[1234]}" ]] || err_exit "test failed\n$(diff -u <( print -r -- "${foo1[1234]}") <(print -r -- "${foo2[1234]}"))."
+
+typeset -C tree
+function f1
+{
+ nameref tr=$1
+ typeset -A tr.subtree
+ typeset -C node
+ node.one="hello"
+ node.two="world"
+
+ # move local note into the array
+ typeset -m tr.subtree["a_node"]=node
+}
+f1 tree
+expected=$'(\n\ttypeset -A subtree=(\n\t\t[a_node]=(\n\t\t\tone=hello\n\t\t\ttwo=world\n\t\t)\n\t)\n)'
+[[ $tree == "$expected" ]] || err_exit 'move of compound local variable to global variable not working'
+
+typeset -C -A array
+float array[12].amount=2.9
+expected='typeset -C -A array=([12]=(typeset -l -E amount=2.9))'
+[[ $(typeset -p array) == "$expected" ]] || err_exit 'typeset with compound variable with compound variable array not working'
+
+typeset -T foo_t=(
+ function diff
+ {
+ print 1.0
+ return 0
+ }
+)
+foo_t sw
+compound output=(
+ integer one=1
+ float mydiff=sw.diff
+ float end=.314
+)
+[[ $output == *end=* ]] || err_exit "The field 'name' end is missing"
+
+compound cpv1=( integer f=2 )
+compound x=(
+ integer a=1
+ compound b=cpv1
+)
+[[ $x == *f=2* ]] || err_exit "The field b containg 'f=2' is missing"
+
+unset x
+compound x=(
+ compound -a nodes=(
+ [4]=( )
+ )
+)
+expected='typeset -C x=(typeset -C -a nodes=([4]=());)'
+[[ $(typeset -p x) == "$expected" ]] || err_exit 'typeset -p with nested compound index array not working'
+
+unset v
+compound v=(
+ integer -A ar=(
+ [aa]=4 [bb]=9
+ )
+)
+expected='typeset -C v=(typeset -A -l -i ar=([aa]=4 [bb]=9);)'
+[[ $(typeset -p v) == "$expected" ]] || err_exit 'attributes for associative arrays embedded in compound variables not working'
+
+unset x
+compound -a x
+x[1]=( a=1 b=2 )
+[[ $(print -v x[1]) == "${x[1]}" ]] || err_exit 'print -v x[1] not working for index array of compound variables'
+
+unset x
+z='typeset -a x=(hello (x=12;y=5) world)'
+{ eval "$z" ;} 2> /dev/null
+[[ $(typeset -p x) == "$z" ]] || err_exit "compound assignment '$z' not working"
+
+expected='typeset -C -A l=([4]=(typeset -a ar=(1 2 3);b=1))'
+typeset -A -C l
+printf "( typeset -a ar=( 1\n2\n3\n) b=1 )\n" | read -C l[4]
+[[ $(typeset -p l) == "$expected" ]] || err_exit 'read -C for associative array of compound variables not working'
+
+unset x
+compound x=( z="a=b c")
+exp=$'typeset -C x=(z=a\\=\'b c\')'
+got=$(typeset -p x)
+[[ $got == "$exp" ]] || err_exit "typeset -p failed -- expected '$exp', got '$got'"
+
+x=(typeset -C -a y;float z=2)
+got=$(print -C x)
+expected='(typeset -C -a y;typeset -l -E z=2)'
+[[ $expected == "$got" ]] || err_exit "print -C x exects '$expected' got '$got'"
+
+unset vx vy
+compound vx=(
+ compound -a va=(
+ [3][17]=(
+ integer -A ar=( [aa]=4 [bb]=9 )
+ )
+ )
+)
+eval "vy=$(print -C vx)"
+[[ $vx == "$vy" ]] || err_exit 'print -C with multi-dimensional array not working'
+eval "vy=$(print -v vx)"
+[[ $vx == "$vy" ]] || err_exit 'print -v with multi-dimensional array not working'
+
+unset x
+typeset -C -A x=( [0]=(a=1) [1]=(b=2) )
+expected=$'(\n\t[0]=(\n\t\ta=1\n\t)\n\t[1]=(\n\t\tb=2\n\t)\n)'
+[[ $(print -v x) == "$expected" ]] || err_exit 'print -v not formatting correctly'
+
+compound -a x=( [0]=(a=1) [1]=(b=2) )
+typeset -m "z=x[1]"
+[[ $(typeset -p z 2>/dev/null) == 'typeset -C z=(b=2)' ]] || err_exit 'typeset -m not working with commpound -a variable'
+
+unset x z
+compound -A x=( [0]=(a=1) [1]=(b=2) )
+typeset -m "z=x[1]"
+[[ $(typeset -p z 2>/dev/null) == 'typeset -C z=(b=2)' ]] || err_exit 'typeset -m not working with commpound -a variable'
+typeset -m "x[1]=x[0]"
+typeset -m "x[0]=z"
+exp='([0]=(b=2) [1]=(a=1))'
+[[ $(print -C x) == "$exp" ]] || err_exit 'typeset -m not working for associative arrays'
+
+unset z r
+z=(a b c)
+r=(x=3 y=4)
+typeset -m z[1]=r
+exp='typeset -a z=(a (x=3;y=4) c)'
+[[ $(typeset -p z) == "$exp" ]] || err_exit 'moving compound variable into indexed array fails'
+
+unset c
+compound c
+compound -a c.a=( [1]=( aa=1 ) )
+compound -a c.b=( [2]=( bb=2 ) )
+typeset -m "c.b[9]=c.a[1]"
+exp='typeset -C c=(typeset -C -a a;typeset -C -a b=( [2]=(bb=2;)[9]=(aa=1));)'
+[[ $(typeset -p c) == "$exp" ]] || err_exit 'moving compound indexed array element to another index fails'
+
+unset c
+compound c
+compound -a c.a=( [1]=( aa=1 ) )
+compound -A c.b=( [2]=( bb=2 ) )
+typeset -m "c.b[9]=c.a[1]"
+exp='typeset -C c=(typeset -C -a a;typeset -C -A b=( [2]=(bb=2;)[9]=(aa=1));)'
+[[ $(typeset -p c) == "$exp" ]] || err_exit 'moving compound indexed array element to a compound associative array element fails'
+
+zzz=(
+ foo=(
+ bar=4
+ )
+)
+[[ $(set | grep "^zzz\.") ]] && err_exit 'set displays compound variables incorrectly'
+
+typeset -A stats
+stats[1]=(a=1 b=2)
+stats[2]=(a=1 b=2)
+stats[1]=(c=3 d=4)
+(( ${#stats[@]} == 2 )) || err_exit "stats[1] should contain 2 element not ${#stats[@]}"
+
+integer i=1
+foo[i++]=(x=3 y=4)
+[[ ${foo[1].x} == 3 ]] || err_exit "\${foo[1].x} should be 3"
+[[ ${foo[1].y} == 4 ]] || err_exit "\${foo[1].y} should be 4"
+
+# ${!x.} caused core dump in ks93u and earlier
+{ $SHELL -c 'compound x=(y=1); : ${!x.}' ; ((!$?));} || err_exit '${!x.} not working'
+
+$SHELL -c 'typeset -A a=([b]=c)' 2> /dev/null || err_exit 'typeset -A a=([b]=c) fails'
+
+compound -a a
+compound c=( name="container1" )
+a[4]=c
+[[ ${a[4]} == $'(\n\tname=container1\n)' ]] || err_exit 'assignment of compound variable to compound array element not working'
+
+unset c
+compound c
+compound -a c.board
+for ((i=2; i < 4; i++))
+do c.board[1][$i]=(foo=bar)
+done
+exp=$'(\n\ttypeset -C -a board=(\n\t\t[1]=(\n\t\t\t[2]=(\n\t\t\t\tfoo=bar\n\t\t\t)\n\t\t\t[3]=(\n\t\t\t\tfoo=bar\n\t\t\t)\n\t\t)\n\t)\n)'
+[[ "$(print -v c)" == "$exp" ]] || err_exit 'compound variable assignment to two dimensional array not working'
+
+unset zz
+zz=()
+zz.[foo]=abc
+zz.[2]=def
+exp='typeset -C zz=([2]=def;foo=abc)'
+[[ $(typeset -p zz) == "$exp" ]] || err_exit 'expansion of compound variables with non-identifiers not working'
+(
+ typeset -i zz.[3]=123
+ exec 2>& 3-
+ exp='typeset -C zz=([2]=def;typeset -i [3]=123;foo=abc)'
+ [[ $(typeset -p zz) == "$exp" ]] || err_exit 'expansion of compound variables with non-identifiers not working in subshells'
+) 3>&2 2> /dev/null || err_exit 'syntax errors expansion of compound variables with non-identifiers'
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/comvario.sh b/src/cmd/ksh93/tests/comvario.sh
new file mode 100644
index 0000000..8ed803a
--- /dev/null
+++ b/src/cmd/ksh93/tests/comvario.sh
@@ -0,0 +1,686 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2012 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2012 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# Roland Mainz <roland.mainz@nrubsig.org> #
+# #
+########################################################################
+
+# test setup
+function err_exit
+{
+ print -u2 -n '\t'
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ (( Errors++ ))
+}
+alias err_exit='err_exit $LINENO'
+
+# "nounset" disabled for now
+#set -o nounset
+Command=${0##*/}
+integer Errors=0 HAVE_signbit=0
+
+if typeset -f .sh.math.signbit >/dev/null && (( signbit(-NaN) ))
+then HAVE_signbit=1
+else print -u2 "$0: warning: -lm does not support signbit(-NaN)"
+fi
+
+compound bracketstat=(
+ integer bopen=0
+ integer bclose=0
+)
+
+function count_brackets
+{
+ typeset x="$1"
+ typeset c
+
+ integer i
+ (( bracketstat.bopen=0 , bracketstat.bclose=0 ))
+
+ for (( i=0 ; i < ${#x} ; i++ )) ; do
+ c="${x:i:1}"
+ [[ "$c" == '(' ]] && (( bracketstat.bopen++ ))
+ [[ "$c" == ')' ]] && (( bracketstat.bclose++ ))
+ done
+
+ (( bracketstat.bopen != bracketstat.bclose )) && return 1
+
+ return 0
+}
+
+# compound variable "cat" nr.1, using $ print "%B\n" ... #
+function cpvcat1
+{
+ set -o errexit
+ compound tmp
+
+ while read -C tmp ; do printf '%B\n' tmp ; done
+ return 0
+}
+
+# compound variable "cat" nr.2, using $ print "%#B\n" ... #
+function cpvcat2
+{
+ set -o errexit
+ compound tmp
+
+ while read -C tmp ; do printf '%#B\n' tmp ; done
+ return 0
+}
+
+# compound variable "cat" nr.3, using $ print -C ... #
+function cpvcat3
+{
+ set -o errexit
+ compound tmp
+
+ while read -C tmp ; do print -C tmp ; done
+ return 0
+}
+
+# compound variable "cat" nr.4, using $ print -v ... #
+function cpvcat4
+{
+ set -o errexit
+ compound tmp
+
+ while read -C tmp ; do print -v tmp ; done
+ return 0
+}
+
+typeset s
+
+# Test 1:
+# Check whether "read -C" leaves the file pointer at the next line
+# (and does not read beyond that point).
+# Data layout is:
+# -- snip --
+# <compound var>
+# hello
+# -- snip --
+# (additionally we test some extra stuff like bracket count)
+s=${
+ compound x=(
+ a=1 b=2
+ typeset -a myarray=( 1 2 3 4 5 6 7 8 9 10 )
+ typeset -A myarray2=( [a]=1 [b]=2 ["c d"]=3 [e]=4 ["f"]=5 [g]=6 [h]=7 [i]=8 [j]=9 [k]=10 )
+ typeset -A myarray3=(
+ [a]=(
+ float m1=0.5
+ float m2=0.6
+ foo="hello"
+ )
+ [b]=(
+ foo="bar"
+ )
+ ["c d"]=(
+ integer at=90
+ )
+ [e]=(
+ compound nested_cpv=(
+ typeset -a myarray=( 1 2 3 4 5 6 7 8 9 10 )
+ typeset str=$'a \'string'
+ )
+ )
+ [f]=(
+ typeset g="f"
+ )
+ [a_nan]=(
+ float my_nan=-nan
+ )
+ [a_hexfloat]=(
+ typeset -X my_hexfloat=1.1
+ )
+ )
+ )
+
+ {
+ printf "%B\n" x
+ print "hello"
+ } | cpvcat1 | cpvcat2 | cpvcat3 | cpvcat4 | {
+ read -C y
+ read s
+ }
+ print "x${s}x"
+} || err_exit "test returned exit code $?"
+
+[[ "${s}" == "xhellox" ]] || err_exit "Expected 'xhellox', got ${s}"
+count_brackets "$y" || err_exit "y: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}"
+count_brackets "$(print -v y)" || err_exit "y: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}"
+count_brackets "$(print -C y)" || err_exit "y: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}"
+
+# cleanup
+unset x y || err_exit "unset failed"
+[[ "$x" == '' ]] || err_exit "cleanup failed for x"
+[[ "$y" == '' ]] || err_exit "cleanup failed for y"
+
+
+# Test 2:
+# Same as test 1 except one more compound var following the "hello"
+# line.
+# Data layout is:
+# -- snip --
+# <compound var>
+# hello
+# <compound var>
+# -- snip --
+s=${
+ compound x=(
+ a=1 b=2
+ typeset -a myarray=( 1 2 3 4 5 6 7 8 9 10 )
+ typeset -A myarray2=( [a]=1 [b]=2 ["c d"]=3 [e]=4 ["f"]=5 [g]=6 [h]=7 [i]=8 [j]=9 [k]=10 )
+ compound -A myarray3=(
+ [a]=(
+ float m1=0.5
+ float m2=0.6
+ foo="hello"
+ )
+ [b]=(
+ foo="bar"
+ )
+ ["c d"]=(
+ integer at=90
+ )
+ [e]=(
+ compound nested_cpv=(
+ typeset -a myarray=( 1 2 3 4 5 6 7 8 9 10 )
+ typeset str=$'a \'string'
+ )
+ )
+ [f]=(
+ typeset g="f"
+ )
+ [a_nan]=(
+ float my_nan=-nan
+ )
+ [a_hexfloat]=(
+ typeset -X my_hexfloat=1.1
+ )
+ )
+ )
+
+ {
+ printf "%B\n" x
+ print "hello"
+ printf "%B\n" x
+ } | cpvcat1 | cpvcat2 | cpvcat3 | cpvcat4 | {
+ read -C y1
+ read s
+ read -C y2
+ }
+
+ print "x${s}x"
+} || err_exit "test returned exit code $?"
+
+[[ "${s}" == "xhellox" ]] || err_exit "Expected 'xhellox', got ${s}."
+[[ "${y1.myarray3[b].foo}" == "bar" ]] || err_exit "y1.myarray3[b].foo != bar"
+[[ "${y2.myarray3[b].foo}" == "bar" ]] || err_exit "y2.myarray3[b].foo != bar"
+[[ "$y1" != "" ]] || err_exit "y1 is empty"
+[[ "$y2" != "" ]] || err_exit "y2 is empty"
+(( ${#y1.myarray3[e].nested_cpv.myarray[@]} == 10 )) || err_exit "Expected 10 elements in y1.myarray3[e].nested_cpv, got ${#y1.myarray3[e].nested_cpv[@]}"
+(( ${#y2.myarray3[e].nested_cpv.myarray[@]} == 10 )) || err_exit "Expected 10 elements in y2.myarray3[e].nested_cpv, got ${#y2.myarray3[e].nested_cpv[@]}"
+(( isnan(y1.myarray3[a_nan].my_nan) )) || err_exit "y1.myarray3[a_nan].my_nan not a NaN"
+(( isnan(y2.myarray3[a_nan].my_nan) )) || err_exit "y2.myarray3[a_nan].my_nan not a NaN"
+if (( HAVE_signbit ))
+then (( signbit(y1.myarray3[a_nan].my_nan) )) || err_exit "y1.myarray3[a_nan].my_nan not negative"
+ (( signbit(y2.myarray3[a_nan].my_nan) )) || err_exit "y2.myarray3[a_nan].my_nan not negative"
+fi
+count_brackets "$y1" || err_exit "y1: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}"
+count_brackets "$(print -v y1)" || err_exit "y1: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}"
+count_brackets "$(print -C y1)" || err_exit "y1: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}"
+count_brackets "$y2" || err_exit "y2: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}"
+count_brackets "$(print -v y2)" || err_exit "y2: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}"
+count_brackets "$(print -C y2)" || err_exit "y2: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}"
+[[ "$y1" == "$y2" ]] || err_exit "Expected $(printf "%q\n" "${y1}") == $(printf "%q\n" "${y2}")."
+[[ "$x" == "$y1" ]] || err_exit "Expected $(printf "%q\n" "${x}") == $(printf "%q\n" "${y}")."
+
+# cleanup
+unset x y1 y2 || err_exit "unset failed"
+[[ "$x" == '' ]] || err_exit "cleanup failed for x"
+[[ "$y1" == '' ]] || err_exit "cleanup failed for y1"
+[[ "$y2" == '' ]] || err_exit "cleanup failed for y2"
+
+
+# Test 3: Test compound variable copy operator vs. "read -C"
+compound x=(
+ a=1 b=2
+ typeset -a myarray=( 1 2 3 4 5 6 7 8 9 10 )
+ typeset -A myarray2=( [a]=1 [b]=2 ["c d"]=3 [e]=4 ["f"]=5 [g]=6 [h]=7 [i]=8 [j]=9 [k]=10 )
+ compound -A myarray3=(
+ [a]=(
+ float m1=0.5
+ float m2=0.6
+ foo="hello"
+ )
+ [b]=(
+ foo="bar"
+ )
+ ["c d"]=(
+ integer at=90
+ )
+ [e]=(
+ compound nested_cpv=(
+ typeset -a myarray=( 1 2 3 4 5 6 7 8 9 10 )
+ typeset str=$'a \'string'
+ )
+ )
+ [f]=(
+ typeset g="f"
+ )
+ [a_nan]=(
+ float my_nan=-nan
+ )
+ [a_hexfloat]=(
+ typeset -X my_hexfloat=1.1
+ )
+ )
+)
+
+compound x_copy=x || err_exit "x_copy copy failed"
+[[ "${x_copy}" != "" ]] || err_exit "x_copy should not be empty"
+count_brackets "${x_copy}" || err_exit "x_copy: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}"
+count_brackets "$(print -v x_copy)" || err_exit "x_copy: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}"
+count_brackets "$(print -C x_copy)" || err_exit "x_copy: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}"
+
+compound nested_cpv_copy
+
+nested_cpv_copy=x.myarray3[e].nested_cpv || err_exit "x.myarray3[e].nested_cpv copy failed"
+(( ${#nested_cpv_copy.myarray[@]} == 10 )) || err_exit "Expected 10 elements in nested_cpv_copy.myarray, got ${#nested_cpv_copy.myarray[@]}"
+
+# unset branch "x.myarray3[e].nested_cpv" of the variable tree "x" ...
+unset x.myarray3[e].nested_cpv || err_exit "unset x.myarray3[e].nested_cpv failed"
+[[ "${x.myarray3[e].nested_cpv}" == "" ]] || err_exit "x.myarray3[e].nested_cpv still has a value"
+
+# ... and restore it from the saved copy
+printf "%B\n" nested_cpv_copy | cpvcat1 | cpvcat2 | cpvcat3 | cpvcat4 | read -C x.myarray3[e].nested_cpv || err_exit "read failed"
+
+# compare copy of the original tree and the modified one
+[[ "${x}" == "${x_copy}" ]] || err_exit "x != x_copy"
+count_brackets "${x}" || err_exit "x: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}"
+count_brackets "$(print -v x)" || err_exit "x: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}"
+count_brackets "$(print -C x)" || err_exit "x: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}"
+(( ${#x.myarray3[e].nested_cpv.myarray[@]} == 10 )) || err_exit "Expected 10 elements in x.myarray3[e].nested_cpv, got ${#x.myarray3[e].nested_cpv[@]}"
+(( isnan(x.myarray3[a_nan].my_nan) )) || err_exit "x.myarray3[a_nan].my_nan not a NaN"
+if (( HAVE_signbit ))
+then (( signbit(x.myarray3[a_nan].my_nan) )) || err_exit "x.myarray3[a_nan].my_nan not negative"
+fi
+
+# cleanup
+unset x x_copy nested_cpv_copy || err_exit "unset failed"
+
+
+# Test 4: Test "read -C" failure for missing bracket at the end
+typeset s
+s=$($SHELL -c 'compound myvar ; print "( unfinished=1" | read -C myvar 2>'/dev/null' || print "error $?"') || err_exit 'shell failed'
+[[ "$s" == 'error 3' ]] || err_exit "compound_read: expected error 3, got ${s}"
+
+
+# Test 5: Test "read -C" failure for missing bracket at the beginning
+typeset s
+s=$($SHELL -c 'compound myvar ; print " unfinished=1 )" | read -C myvar 2>'/dev/null' || print "error $?"') || err_exit 'shell failed'
+[[ "$s" == 'error 3' ]] || err_exit "compound_read: expected error 3, got ${s}"
+
+
+# test6: Derived from the test2 for CR #6944386
+# ("compound v=( integer -A ar=( [aa]=4 [bb]=9 ) ; ) ; print -C v prints trash")
+# which caused compound variables to be corrupted like this:
+# -- snip --
+# ksh93 -c 'compound v=( integer -A ar=( [aa]=4 [bb]=9 ) ; ) ; print -v v'
+# (
+# typeset -A -l -i ar=(
+# [aa]=$'\004'
+# [bb]=$'\t'
+# )
+# )
+# -- snip --
+
+function test6
+{
+ compound out=( typeset stdout stderr ; integer res )
+ compound val
+ integer testid
+
+ compound -r -a tests=(
+ # subtests1:
+ ( cmd='compound v=( integer -A ar=( [aa]=4 [bb]=9 ) ; ) ; print -C v' stdoutpattern=$'~(Alr)(.*\\[bb\\]=9.*)&(.*\\[aa\\]=4.*)' arrefname='ar' )
+ ( cmd='compound v=( float -A ar=( [aa]=4 [bb]=9 ) ; ) ; print -C v' stdoutpattern=$'~(Alr)(.*\\[bb\\]=9.*)&(.*\\[aa\\]=4.*)' arrefname='ar' )
+ ( cmd='compound v=( typeset -A ar=( [aa]=4 [bb]=9 ) ; ) ; print -C v' stdoutpattern=$'~(Alr)(.*\\[bb\\]=["\']*9.*)&(.*\\[aa\\]=["\']*4.*)' arrefname='ar' )
+ ( cmd='compound v=( integer -A ar=( [aa]=4 [bb]=9 ) ; ) ; print -v v' stdoutpattern=$'~(Alr)(.*\\[bb\\]=9.*)&(.*\\[aa\\]=4.*)' arrefname='ar' )
+ ( cmd='compound v=( float -A ar=( [aa]=4 [bb]=9 ) ; ) ; print -v v' stdoutpattern=$'~(Alr)(.*\\[bb\\]=9.*)&(.*\\[aa\\]=4.*)' arrefname='ar' )
+ ( cmd='compound v=( typeset -A ar=( [aa]=4 [bb]=9 ) ; ) ; print -v v' stdoutpattern=$'~(Alr)(.*\\[bb\\]=["\']*9.*)&(.*\\[aa\\]=["\']*4.*)' arrefname='ar' )
+
+ # subtests2: Same as subtests1 but variable "v" is inside "vx"
+ ( cmd='compound vx=( compound v=( integer -A ar=( [aa]=4 [bb]=9 ) ; ) ; ) ; print -C vx' stdoutpattern=$'~(Alr)(.*\\[bb\\]=9.*)&(.*\\[aa\\]=4.*)' arrefname='v.ar' )
+ ( cmd='compound vx=( compound v=( float -A ar=( [aa]=4 [bb]=9 ) ; ) ; ) ; print -C vx' stdoutpattern=$'~(Alr)(.*\\[bb\\]=9.*)&(.*\\[aa\\]=4.*)' arrefname='v.ar' )
+ ( cmd='compound vx=( compound v=( typeset -A ar=( [aa]=4 [bb]=9 ) ; ) ; ) ; print -C vx' stdoutpattern=$'~(Alr)(.*\\[bb\\]=["\']*9.*)&(.*\\[aa\\]=["\']*4.*)' arrefname='v.ar' )
+ ( cmd='compound vx=( compound v=( integer -A ar=( [aa]=4 [bb]=9 ) ; ) ; ) ; print -v vx' stdoutpattern=$'~(Alr)(.*\\[bb\\]=9.*)&(.*\\[aa\\]=4.*)' arrefname='v.ar' )
+ ( cmd='compound vx=( compound v=( float -A ar=( [aa]=4 [bb]=9 ) ; ) ; ) ; print -v vx' stdoutpattern=$'~(Alr)(.*\\[bb\\]=9.*)&(.*\\[aa\\]=4.*)' arrefname='v.ar' )
+ ( cmd='compound vx=( compound v=( typeset -A ar=( [aa]=4 [bb]=9 ) ; ) ; ) ; print -v vx' stdoutpattern=$'~(Alr)(.*\\[bb\\]=["\']*9.*)&(.*\\[aa\\]=["\']*4.*)' arrefname='v.ar' )
+
+ # subtests3: Same as subtests1 but variable "va" is an indexed array
+ ( cmd='compound vx=( compound -a va=( [3]=( integer -A ar=( [aa]=4 [bb]=9 ) ; ) ; ) ; ) ; print -C vx' stdoutpattern=$'~(Alr)(.*\\[bb\\]=9.*)&(.*\\[aa\\]=4.*)' arrefname='va[3].ar' )
+ ( cmd='compound vx=( compound -a va=( [3]=( float -A ar=( [aa]=4 [bb]=9 ) ; ) ; ) ; ) ; print -C vx' stdoutpattern=$'~(Alr)(.*\\[bb\\]=9.*)&(.*\\[aa\\]=4.*)' arrefname='va[3].ar' )
+ ( cmd='compound vx=( compound -a va=( [3]=( typeset -A ar=( [aa]=4 [bb]=9 ) ; ) ; ) ; ) ; print -C vx' stdoutpattern=$'~(Alr)(.*\\[bb\\]=["\']*9.*)&(.*\\[aa\\]=["\']*4.*)' arrefname='va[3].ar' )
+ ( cmd='compound vx=( compound -a va=( [3]=( integer -A ar=( [aa]=4 [bb]=9 ) ; ) ; ) ; ) ; print -v vx' stdoutpattern=$'~(Alr)(.*\\[bb\\]=9.*)&(.*\\[aa\\]=4.*)' arrefname='va[3].ar' )
+ ( cmd='compound vx=( compound -a va=( [3]=( float -A ar=( [aa]=4 [bb]=9 ) ; ) ; ) ; ) ; print -v vx' stdoutpattern=$'~(Alr)(.*\\[bb\\]=9.*)&(.*\\[aa\\]=4.*)' arrefname='va[3].ar' )
+ ( cmd='compound vx=( compound -a va=( [3]=( typeset -A ar=( [aa]=4 [bb]=9 ) ; ) ; ) ; ) ; print -v vx' stdoutpattern=$'~(Alr)(.*\\[bb\\]=["\']*9.*)&(.*\\[aa\\]=["\']*4.*)' arrefname='va[3].ar' )
+
+ # subtests4: Same as subtests1 but variable "va" is an 2d indexed array
+ ( cmd='compound vx=( compound -a va=( [3][17]=( integer -A ar=( [aa]=4 [bb]=9 ) ; ) ; ) ; ) ; print -C vx' stdoutpattern=$'~(Alr)(.*\\[bb\\]=9.*)&(.*\\[aa\\]=4.*)' arrefname='va[3][17].ar' )
+ ( cmd='compound vx=( compound -a va=( [3][17]=( float -A ar=( [aa]=4 [bb]=9 ) ; ) ; ) ; ) ; print -C vx' stdoutpattern=$'~(Alr)(.*\\[bb\\]=9.*)&(.*\\[aa\\]=4.*)' arrefname='va[3][17].ar' )
+ ( cmd='compound vx=( compound -a va=( [3][17]=( typeset -A ar=( [aa]=4 [bb]=9 ) ; ) ; ) ; ) ; print -C vx' stdoutpattern=$'~(Alr)(.*\\[bb\\]=["\']*9.*)&(.*\\[aa\\]=["\']*4.*)' arrefname='va[3][17].ar' )
+ ( cmd='compound vx=( compound -a va=( [3][17]=( integer -A ar=( [aa]=4 [bb]=9 ) ; ) ; ) ; ) ; print -v vx' stdoutpattern=$'~(Alr)(.*\\[bb\\]=9.*)&(.*\\[aa\\]=4.*)' arrefname='va[3][17].ar' )
+ ( cmd='compound vx=( compound -a va=( [3][17]=( float -A ar=( [aa]=4 [bb]=9 ) ; ) ; ) ; ) ; print -v vx' stdoutpattern=$'~(Alr)(.*\\[bb\\]=9.*)&(.*\\[aa\\]=4.*)' arrefname='va[3][17].ar' )
+ ( cmd='compound vx=( compound -a va=( [3][17]=( typeset -A ar=( [aa]=4 [bb]=9 ) ; ) ; ) ; ) ; print -v vx' stdoutpattern=$'~(Alr)(.*\\[bb\\]=["\']*9.*)&(.*\\[aa\\]=["\']*4.*)' arrefname='va[3][17].ar' )
+
+ # subtests5: Same as subtests1 but variable "va" is an associative array
+ ( cmd='compound vx=( compound -A va=( [l]=( integer -A ar=( [aa]=4 [bb]=9 ) ; ) ; ) ; ) ; print -C vx' stdoutpattern=$'~(Alr)(.*\\[bb\\]=9.*)&(.*\\[aa\\]=4.*)' arrefname='va[l].ar' )
+ ( cmd='compound vx=( compound -A va=( [l]=( float -A ar=( [aa]=4 [bb]=9 ) ; ) ; ) ; ) ; print -C vx' stdoutpattern=$'~(Alr)(.*\\[bb\\]=9.*)&(.*\\[aa\\]=4.*)' arrefname='va[l].ar' )
+ ( cmd='compound vx=( compound -A va=( [l]=( typeset -A ar=( [aa]=4 [bb]=9 ) ; ) ; ) ; ) ; print -C vx' stdoutpattern=$'~(Alr)(.*\\[bb\\]=["\']*9.*)&(.*\\[aa\\]=["\']*4.*)' arrefname='va[l].ar' )
+ ( cmd='compound vx=( compound -A va=( [l]=( integer -A ar=( [aa]=4 [bb]=9 ) ; ) ; ) ; ) ; print -v vx' stdoutpattern=$'~(Alr)(.*\\[bb\\]=9.*)&(.*\\[aa\\]=4.*)' arrefname='va[l].ar' )
+ ( cmd='compound vx=( compound -A va=( [l]=( float -A ar=( [aa]=4 [bb]=9 ) ; ) ; ) ; ) ; print -v vx' stdoutpattern=$'~(Alr)(.*\\[bb\\]=9.*)&(.*\\[aa\\]=4.*)' arrefname='va[l].ar' )
+ ( cmd='compound vx=( compound -A va=( [l]=( typeset -A ar=( [aa]=4 [bb]=9 ) ; ) ; ) ; ) ; print -v vx' stdoutpattern=$'~(Alr)(.*\\[bb\\]=["\']*9.*)&(.*\\[aa\\]=["\']*4.*)' arrefname='va[l].ar' )
+ )
+
+ for testid in "${!tests[@]}" ; do
+ nameref test=tests[testid]
+ typeset testname="test2/${testid}"
+
+ out.stderr="${ { out.stdout="${ ${SHELL} -c "${test.cmd}" ; (( out.res=$? )) ; }" ; } 2>&1 ; }"
+
+ (( out.res == 0 )) || err_exit "${testname}: Test shell returned with exit code ${out.res}"
+ [[ "${out.stdout}" == ${test.stdoutpattern} ]] || err_exit "${testname}: Expected match for ${test.stdoutpattern}, got $(printf "%q\n" "${out.stdout}")"
+ [[ "${out.stderr}" == "" ]] || err_exit "${testname}: Expected empty stderr, got $(printf "%q\n" "${out.stderr}")"
+
+ read -C val <<<"${out.stdout}" || err_exit "${testname}: read -C val failed with exit code $?"
+ nameref ar="val.${test.arrefname}"
+ (( ar[aa] == 4 )) || err_exit "${testname}: Expected ar[aa] == 4, got ${ar[aa]}"
+ (( ar[bb] == 9 )) || err_exit "${testname}: Expected ar[bb] == 9, got ${ar[bb]}"
+ done
+
+ return 0
+}
+
+test6
+
+function test_3D_array_read_C
+{
+ compound out=( typeset stdout stderr ; integer res )
+ integer i
+ typeset -r -a tests=(
+ # ast-ksh.2010-03-09 will print "ksh93[1]: read: line 4: 0[0]: invalid variable name" for 3D arrays passed to read -C
+ 'compound c=( typeset -a x ) ; for (( i=0 ; i < 3 ; i++ )) ; do for (( j=0 ; j < 3 ; j++ )) ; do for (( k=0 ; k < 3 ; k++ )) ; do c.x[i][j][k]="$i$j$k" ; done; done; done ; unset c.x[2][0][1] ; print -v c | read -C dummy'
+
+ # same test, 4D, fails with 'ksh[1]: read: line 4: 0: invalid variable name'
+ 'compound c=( typeset -a x ) ; for (( i=0 ; i < 3 ; i++ )) ; do for (( j=0 ; j < 3 ; j++ )) ; do for (( k=0 ; k < 3 ; k++ )) ; do for (( l=0 ; l < 3 ; l++ )) ; do c.x[i][j][k][l]="$i$j$k$l" ; done; done; done ; done ; unset c.x[2][0][1][2] ; print -v c | read -C dummy'
+ )
+
+ for (( i=0 ; i < ${#tests[@]} ; i++ )) ; do
+ out.stderr="${ { out.stdout="${ ${SHELL} -o nounset -c "${tests[i]}" ; (( out.res=$? )) ; }" ; } 2>&1 ; }"
+
+ [[ "${out.stdout}" == '' ]] || err_exit "$0/${i}: Expected empty stdout, got $(printf '%q\n' "${out.stdout}")"
+ [[ "${out.stderr}" == '' ]] || err_exit "$0/${i}: Expected empty stderr, got $(printf '%q\n' "${out.stderr}")"
+ done
+
+ return 0
+}
+
+
+function test_access_2Darray_in_type_in_compound
+{
+ compound out=( typeset stdout stderr ; integer res )
+ integer i
+ typeset -r -a tests=(
+ # ast-ksh.2010-03-09 will print 'ksh: line 1: l.c.x[i][j]=: no parent'
+ 'typeset -T c_t=(typeset -a x) ; compound l=( c_t c ) ; for ((i=0;i<3;i++));do for ((j=0;j<3;j++));do l.c.x[i][j]="" ; done; done; print -v l | read -C dummy'
+ )
+
+ for (( i=0 ; i < ${#tests[@]} ; i++ )) ; do
+ out.stderr="${ { out.stdout="${ ${SHELL} -o nounset -c "${tests[i]}" ; (( out.res=$? )) ; }" ; } 2>&1 ; }"
+
+ [[ "${out.stdout}" == '' ]] || err_exit "$0/${i}: Expected empty stdout, got $(printf '%q\n' "${out.stdout}")"
+ [[ "${out.stderr}" == '' ]] || err_exit "$0/${i}: Expected empty stderr, got $(printf '%q\n' "${out.stderr}")"
+ done
+
+ return 0
+}
+
+function test_read_type_crash
+{
+ compound out=( typeset stdout stderr ; integer res )
+ typeset -r test='
+typeset -T field_t=(
+ typeset -a f
+
+ function reset
+ {
+ integer i j
+
+ for (( i=0 ; i < 3 ; i++ )) ; do
+ for (( j=0 ; j < 3 ; j++ )) ; do
+ _.f[i][j]=""
+ done
+ done
+ return 0
+ }
+
+ function enumerate_empty_fields
+ {
+ integer i j
+
+ for (( i=0 ; i < 3 ; i++ )) ; do
+ for (( j=0 ; j < 3 ; j++ )) ; do
+ [[ "${_.f[i][j]}" == "" ]] && printf "[%d][%d]\n" i j
+ done
+ done
+ return 0
+ }
+
+ function setf
+ {
+ _.f[$1][$2]="$3"
+ }
+)
+
+set -o nounset
+
+compound c1=( field_t x )
+
+c1.x.reset
+
+print -v c1 | read -C c2
+print -v c2
+'
+
+ out.stderr="${ { out.stdout="${ ${SHELL} -o nounset -c "${test}" ; (( out.res=$? )) ; }" ; } 2>&1 ; }"
+
+ [[ "${out.stdout}" != '' ]] || err_exit "$0: Expected nonempty stdout."
+ [[ "${out.stderr}" == '' ]] || err_exit "$0: Expected empty stderr, got $(printf '%q\n' "${out.stderr}")"
+
+ if [[ -f 'core' && -x '/usr/bin/pstack' ]] ; then
+ pstack 'core'
+ rm 'core'
+ fi
+
+ return 0
+}
+
+
+function test_read_C_into_array
+{
+ compound out=( typeset stdout stderr ; integer res )
+ # fixme:
+ # - The tests should cover 3D and 5D indexed arrays and namerefs to sub-dimensions of a 5D indexed array
+ compound -r -a tests=(
+ ( cmd=' typeset -a -C l ; printf "( typeset -a ar=( 1\n2\n3\n) b=1 )\n" | read -C l[4] ; print -v l' typeset -a stdoutpattern=( '~(X)(.+b=1.+)&(.+\[4\].+)' ) )
+ ( cmd=' typeset -a -C l ; nameref l4=l[4] ; printf "( typeset -a ar=( 1\n2\n3\n) b=1 )\n" | read -C l4 ; print -v l' typeset -a stdoutpattern=( '~(X)(.+b=1.+)&(.+\[4\].+)' ) )
+
+ ( cmd=' typeset -a -C l ; printf "( typeset -a ar=( 1\n2\n3\n) b=1 )\n" | read -C l[4][6] ; print -v l' typeset -a stdoutpattern=( '~(X)(.+b=1.+)&(.+\[4\].+)&(.+\[6\].+)' ) )
+ ( cmd=' typeset -a -C l ; nameref l4=l[4][6] ; printf "( typeset -a ar=( 1\n2\n3\n) b=1 )\n" | read -C l4 ; print -v l' typeset -a stdoutpattern=( '~(X)(.+b=1.+)&(.+\[4\].+)&(.+\[6\].+)' ) )
+
+ ( cmd=' typeset -a -C l ; printf "( typeset -a ar=( 1\n2\n3\n) b=1 )\n" | read -C l[4][6][9][11][15] ; print -v l' typeset -a stdoutpattern=( '~(X)(.+b=1.+)&(.+\[4\].+)&(.+\[6\].+)' '~(X)(.+\[9\].+)&(.+\[11\].+)&(.+\[15\].+)' ) )
+ ( cmd=' typeset -a -C l ; nameref l4=l[4][6][9][11][15] ; printf "( typeset -a ar=( 1\n2\n3\n) b=1 )\n" | read -C l4 ; print -v l' typeset -a stdoutpattern=( '~(X)(.+b=1.+)&(.+\[4\].+)&(.+\[6\].+)' '~(X)(.+\[9\].+)&(.+\[11\].+)&(.+\[15\].+)' ) )
+
+ ( cmd=' typeset -A -C l ; printf "( typeset -a ar=( 1\n2\n3\n) b=1 )\n" | read -C l[4] ; print -v l' typeset -a stdoutpattern=( '~(X)(.+b=1.+)&(.+\[4\].+)' ) )
+ ( cmd=' typeset -A -C l ; nameref l4=l[4] ; printf "( typeset -a ar=( 1\n2\n3\n) b=1 )\n" | read -C l4 ; print -v l' typeset -a stdoutpattern=( '~(X)(.+b=1.+)&(.+\[4\].+)' ) )
+ ( cmd='compound c ; typeset -a -C c.l ; printf "( typeset -a ar=( 1\n2\n3\n) b=1 )\n" | read -C c.l[4] ; print -v c' typeset -a stdoutpattern=( '~(X)(.+b=1.+)&(.+\[4\].+)' ) )
+ ( cmd='compound c ; typeset -a -C c.l ; nameref l4=c.l[4] ; printf "( typeset -a ar=( 1\n2\n3\n) b=1 )\n" | read -C l4 ; print -v c' typeset -a stdoutpattern=( '~(X)(.+b=1.+)&(.+\[4\].+)' ) )
+
+ ( cmd='compound c ; typeset -a -C c.l ; printf "( typeset -a ar=( 1\n2\n3\n) b=1 )\n" | read -C c.l[4][6] ; print -v c' typeset -a stdoutpattern=( '~(X)(.+b=1.+)&(.+\[4\].+)&(.+\[6\].+)' ) )
+ ( cmd='compound c ; typeset -a -C c.l ; nameref l4=c.l[4][6] ; printf "( typeset -a ar=( 1\n2\n3\n) b=1 )\n" | read -C l4 ; print -v c' typeset -a stdoutpattern=( '~(X)(.+b=1.+)&(.+\[4\].+)&(.+\[6\].+)' ) )
+
+ ( cmd='compound c ; typeset -a -C c.l ; printf "( typeset -a ar=( 1\n2\n3\n) b=1 )\n" | read -C c.l[4][6][9][11][15] ; print -v c' typeset -a stdoutpattern=( '~(X)(.+b=1.+)&(.+\[4\].+)&(.+\[6\].+)' '~(X)(.+\[9\].+)&(.+\[11\].+)&(.+\[15\].+)' ) )
+ ( cmd='compound c ; typeset -a -C c.l ; nameref l4=c.[4][6][9][11][15] ; printf "( typeset -a ar=( 1\n2\n3\n) b=1 )\n" | read -C l4 ; print -v c' typeset -a stdoutpattern=( '~(X)(.+b=1.+)&(.+\[4\].+)&(.+\[6\].+)' '~(X)(.+\[9\].+)&(.+\[11\].+)&(.+\[15\].+)' ) )
+
+ ( cmd='compound c ; typeset -A -C c.l ; printf "( typeset -a ar=( 1\n2\n3\n) b=1 )\n" | read -C c.l[4] ; print -v c' typeset -a stdoutpattern=( '~(X)(.+b=1.+)&(.+\[4\].+)' ) )
+ ( cmd='compound c ; typeset -A -C c.l ; nameref l4=c.l[4] ; printf "( typeset -a ar=( 1\n2\n3\n) b=1 )\n" | read -C l4 ; print -v c' typeset -a stdoutpattern=( '~(X)(.+b=1.+)&(.+\[4\].+)' ) )
+ )
+ typeset cmd
+ typeset pat
+ integer i
+
+ compound -a test_variants
+
+ # build list of variations of the tests above
+ for (( i=0 ; i < ${#tests[@]} ; i++ )) ; do
+ nameref tst=tests[i]
+
+ # plain test
+ cmd="${tst.cmd}"
+ test_variants+=( testname="${0}/${i}/plain" cmd="$cmd" typeset -a stdoutpattern=( "${tst.stdoutpattern[@]}" ) )
+
+ # test with "read -C" in a function
+ cmd="${tst.cmd/~(E)read[[:space:]]+-C[[:space:]]+([[:alnum:]]+)[[:space:]]+\;/{ function rf { nameref val=\$1 \; read -C val \; } \; rf \1 \; } \; }"
+ test_variants+=( testname="${0}/${i}/read_in_function" cmd="$cmd" typeset -a stdoutpattern=( "${tst.stdoutpattern[@]}" ) )
+
+ # test with "read -C" in a nested function
+ cmd="${tst.cmd/~(E)read[[:space:]]+-C[[:space:]]+([[:alnum:]]+)[[:space:]]+\;/{ function rf2 { nameref val=\$1 \; read -C val \; } \; function rf { nameref val=\$1 \; rf2 val \; } \; rf \1 \; } \; }"
+ test_variants+=( testname="${0}/${i}/read_in_nested_function" cmd="$cmd" typeset -a stdoutpattern=( "${tst.stdoutpattern[@]}" ) )
+
+ # test with "read -C" in a nested function with target variable
+ # being a function-local variable of function "main"
+ cmd='function rf2 { nameref val=$1 ; read -C val ; } ; function rf { nameref val=$1 ; rf2 val ; } ; function main { '
+ cmd+="${tst.cmd/~(E)read[[:space:]]+-C[[:space:]]+([[:alnum:]]+)[[:space:]]+\;/rf \1 \; }"
+ cmd+=' ; } ; main'
+ test_variants+=( testname="${0}/${i}/read_into_localvar_in_nested_function" cmd="$cmd" typeset -a stdoutpattern=( "${tst.stdoutpattern[@]}" ) )
+ done
+
+ # run test variants
+ for (( i=0 ; i < ${#test_variants[@]} ; i++ )) ; do
+ nameref tv=test_variants[i]
+
+ out.stderr="${ { out.stdout="${ ${SHELL} -o nounset -o errexit -c "${tv.cmd}" ; (( out.res=$? )) ; }" ; } 2>&1 ; }"
+
+ for pat in "${tv.stdoutpattern[@]}" ; do
+ [[ "${out.stdout}" == ${pat} ]] || err_exit "${tv.testname}: Expected stdout of $(printf '%q\n' "${tv.cmd}") to match $(printf '%q\n' "${pat}"), got $(printf '%q\n' "${out.stdout}")"
+ done
+ [[ "${out.stderr}" == '' ]] || err_exit "${tv.testname}: Expected empty stderr for $(printf '%q\n' "${tv.cmd}"), got $(printf '%q\n' "${out.stderr}")"
+ (( out.res == 0 )) || err_exit "${tv.testname}: Unexpected exit code ${out.res} for $(printf '%q\n' "${tv.cmd}")"
+ done
+
+ return 0
+}
+
+
+# This test checks whether reading a compound variable value with
+# "read -C var" which contains special shell keywords or aliases
+# like "functions", "alias", "!" etc. in a string array causes the
+# shell to produce errors like this:
+# -- snip --
+# $ ksh93 -c 'print "( compound -A a1=( [4]=( typeset -a x=( alias ) ) ) ;
+# compound -A a2=( [4]=( typeset -a x=( ! ! ! alias ) ) ) )" | read -C c ; print -v c' 1>/dev/null
+# ksh93[1]: alias: c.a1[4].x: compound assignment requires sub-variable name
+# -- snip --
+# A 2nd issue indirectly tested here was that simple indexed string array
+# declarations in a function with the same special keywords did not work
+# either.
+# This happened in ast-ksh.2010-11-12 or older.
+function test_read_C_special_shell_keywords
+{
+ typeset -r -a testcmdpatterns=(
+ # this was the original testcase
+ 'print "( compound -A a1=( [4]=( typeset -a x=( %keyword% ) ) ) ; compound -A a2=( [4]=( typeset -a x=( ! ! ! alias ) ) ) )" | read -C c ; print "X${c.a1[4].x[0]}X"'
+ # same as above but uses indexed arrays instead of associative arrays
+ 'print "( compound -a a1=( [4]=( typeset -a x=( %keyword% ) ) ) ; compound -a a2=( [4]=( typeset -a x=( ! ! ! alias ) ) ) )" | read -C c ; print "X${c.a1[4].x[0]}X"'
+ # same as first testcase but uses a blank in the array index value
+ $'print "( compound -A a1=( [\'hello world\']=( typeset -a x=( %keyword% ) ) ) ; compound -A a2=( [\'hello world\']=( typeset -a x=( ! ! ! alias ) ) ) )" | read -C c ; print "X${c.a1[\'hello world\'].x[0]}X"'
+ )
+ typeset -r -a shell_special_words=(
+ 'alias'
+ 'compound'
+ 'function'
+ 'functions'
+ 'integer'
+ 'local'
+ 'namespace'
+ 'typeset'
+ 'SECONDS'
+ '.sh.version'
+ '!'
+ )
+ integer spwi # shell_special_words index
+ integer tcpi # testcmdpatterns index
+ typeset testcmd
+ typeset testname
+ typeset shkeyword
+ compound out=( typeset stdout stderr ; integer res )
+
+ for (( tcpi=0 ; tcpi < ${#testcmdpatterns[@]} ; tcpi++ )) ; do
+ for (( spwi=0 ; spwi < ${#shell_special_words[@]} ; spwi++ )) ; do
+ shkeyword=${shell_special_words[spwi]}
+ testcmd="${testcmdpatterns[tcpi]//%keyword%/${shkeyword}}"
+ testname="${0}/${tcpi}/${spwi}/"
+
+ out.stderr="${ { out.stdout="${ ${SHELL} -o nounset -o errexit -c "${testcmd}" ; (( out.res=$? )) ; }" ; } 2>&1 ; }"
+
+ [[ "${out.stdout}" == "X${shkeyword}X" ]] || err_exit "${testname}: Expected stdout to match $(printf '%q\n' "X${shkeyword}X"), got $(printf '%q\n' "${out.stdout}")"
+ [[ "${out.stderr}" == '' ]] || err_exit "${testname}: Expected empty stderr, got $(printf '%q\n' "${out.stderr}")"
+ (( out.res == 0 )) || err_exit "${testname}: Unexpected exit code ${out.res}"
+ done
+ done
+
+ return 0
+}
+
+
+test_3D_array_read_C
+test_access_2Darray_in_type_in_compound
+test_read_type_crash
+test_read_C_into_array
+test_read_C_special_shell_keywords
+
+
+# tests done
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/coprocess.sh b/src/cmd/ksh93/tests/coprocess.sh
new file mode 100755
index 0000000..749f691
--- /dev/null
+++ b/src/cmd/ksh93/tests/coprocess.sh
@@ -0,0 +1,360 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2012 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+# test the behavior of co-processes
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+if [[ -d /cygdrive ]]
+then err_exit cygwin detected - coprocess tests disabled - enable at the risk of wedging your system
+ exit $((Errors))
+fi
+
+bintrue=$(whence -p true)
+
+function ping # id
+{
+ integer x=0
+ while ((x++ < 5))
+ do read -r
+ print -r "$1 $REPLY"
+ done
+}
+
+cat |&
+print -p "hello"
+read -p line
+[[ $line == hello ]] || err_exit 'coprocessing fails'
+exec 5>&p 6<&p
+print -u5 'hello again' || err_exit 'write on u5 fails'
+read -u6 line
+[[ $line == 'hello again' ]] || err_exit 'coprocess after moving fds fails'
+exec 5<&- 6<&-
+wait $!
+
+ping three |&
+exec 3>&p
+ping four |&
+exec 4>&p
+ping pipe |&
+
+integer count
+for i in three four pipe four pipe four three pipe pipe three pipe
+do case $i in
+ three) to=-u3;;
+ four) to=-u4;;
+ pipe) to=-p;;
+ esac
+ (( count++ ))
+ print $to $i $count
+done
+
+while ((count > 0))
+do (( count-- ))
+ read -p
+ set -- $REPLY
+ if [[ $1 != $2 ]]
+ then err_exit "$1 does not match $2"
+ fi
+ case $1 in
+ three) ;;
+ four) ;;
+ pipe) ;;
+ *) err_exit "unknown message +|$REPLY|+" ;;
+ esac
+done
+kill $(jobs -p) 2>/dev/null
+
+file=$tmp/regress
+cat > $file <<\!
+/bin/cat |&
+!
+chmod +x $file
+sleep 10 |&
+$file 2> /dev/null || err_exit "parent coprocess prevents script coprocess"
+exec 5<&p 6>&p
+exec 5<&- 6>&-
+kill $(jobs -p) 2>/dev/null
+
+${SHELL-ksh} |&
+cop=$!
+exp=Done
+print -p $'print hello | cat\nprint '$exp
+read -t 5 -p
+read -t 5 -p
+got=$REPLY
+if [[ $got != $exp ]]
+then err_exit "${SHELL-ksh} coprocess io failed -- got '$got', expected '$exp'"
+fi
+exec 5<&p 6>&p
+exec 5<&- 6>&-
+{ sleep 4; kill $cop; } 2>/dev/null &
+spy=$!
+if wait $cop 2>/dev/null
+then kill $spy 2>/dev/null
+else err_exit "coprocess hung after 'exec 5<&p 6>&p; exec 5<&- 6>&-'"
+fi
+wait
+
+{
+echo line1 | grep 'line2'
+echo line2 | grep 'line1'
+} |&
+SECONDS=0 count=0
+while read -p -t 10 line
+do ((count++))
+done
+if (( SECONDS > 8 ))
+then err_exit "read -p hanging (SECONDS=$SECONDS count=$count)"
+fi
+wait $!
+
+( sleep 3 |& sleep 1 && kill $!; sleep 1; sleep 3 |& sleep 1 && kill $! ) ||
+ err_exit "coprocess cleanup not working correctly"
+{ : |& } 2>/dev/null ||
+ err_exit "subshell coprocess lingers in parent"
+wait $!
+
+unset N r e
+integer N=5
+e=12345
+(
+ integer i
+ for ((i = 1; i <= N; i++))
+ do print $i |&
+ read -p r
+ print -n $r
+ wait $!
+ done
+ print
+) 2>/dev/null | read -t 10 r
+[[ $r == $e ]] || err_exit "coprocess timing bug -- expected $e, got '$r'"
+r=
+(
+ integer i
+ for ((i = 1; i <= N; i++))
+ do print $i |&
+ sleep 0.01
+ r=$r$(cat <&p)
+ wait $!
+ done
+ print $r
+) 2>/dev/null | read -t 10 r
+[[ $r == $e ]] || err_exit "coprocess command substitution bug -- expected $e, got '$r'"
+
+(
+ /bin/cat |&
+ sleep 0.01
+ exec 6>&p
+ print -u6 ok
+ exec 6>&-
+ sleep 2
+ kill $! 2> /dev/null
+) && err_exit 'coprocess with subshell would hang'
+for sig in IOT ABRT
+do if ( trap - $sig ) 2> /dev/null
+ then if [[ $( { sig=$sig $SHELL 2> /dev/null <<- '++EOF++'
+ cat |&
+ pid=$!
+ trap "print TRAP" $sig
+ (
+ sleep 2
+ kill -$sig $$
+ sleep 2
+ kill -$sig $$
+ kill $pid
+ sleep 2
+ kill $$
+ ) &
+ while read -p || (($? > 256))
+ do :
+ done
+ ++EOF++
+ } ) != $'TRAP\nTRAP' ]] 2> /dev/null
+ then err_exit 'traps when reading from coprocess not working'
+ fi
+ break
+ fi
+done
+
+trap 'sleep_pid=; kill $pid; err_exit "coprocess 1 hung"' TERM
+{ sleep 5; kill $$; } &
+sleep_pid=$!
+builtin cat
+cat |&
+pid=$!
+exec 5<&p 6>&p
+exp=hi
+print -u6 $exp; read -u5
+[[ $REPLY == "$exp" ]] || err_exit "REPLY failed -- expected '$exp', got '$REPLY'"
+exec 6>&-
+wait $pid
+trap - TERM
+[[ $sleep_pid ]] && kill $sleep_pid
+
+trap 'sleep_pid=; kill $pid; err_exit "coprocess 2 hung"' TERM
+{ sleep 5; kill $$; } &
+sleep_pid=$!
+cat |&
+pid=$!
+print foo >&p 2> /dev/null || err_exit 'first write of foo to coprocess failed'
+print foo >&p 2> /dev/null || err_exit 'second write of foo to coprocess failed'
+kill $pid
+wait $pid 2> /dev/null
+trap - TERM
+[[ $sleep_pid ]] && kill $sleep_pid
+
+trap 'sleep_pid=; kill $pid; err_exit "coprocess 3 hung"' TERM
+{ sleep 5; kill $$; } &
+sleep_pid=$!
+cat |&
+pid=$!
+print -p foo
+print -p bar
+read <&p || err_exit 'first read from coprocess failed'
+[[ $REPLY == foo ]] || err_exit "first REPLY is $REPLY not foo"
+read <&p || err_exit 'second read from coprocess failed'
+[[ $REPLY == bar ]] || err_exit "second REPLY is $REPLY not bar"
+kill $pid
+wait $pid 2> /dev/null
+trap - TERM
+[[ $sleep_pid ]] && kill $sleep_pid
+
+exp=ksh
+got=$(print -r $'#00315
+COATTRIBUTES=\'label=make \'
+# @(#)$Id: libcoshell (AT&T Research) 2008-04-28 $
+_COSHELL_msgfd=5
+{ { (eval \'function fun { trap \":\" 0; return 1; }; trap \"exit 0\" 0; fun; exit 1\') && PATH= print -u$_COSHELL_msgfd ksh; } || { times && echo bsh >&$_COSHELL_msgfd; } || { echo osh >&$_COSHELL_msgfd; }; } >/dev/null 2>&1' | $SHELL 5>&1)
+[[ $got == $exp ]] || err_exit "coshell(3) identification sequence failed -- expected '$exp', got '$got'"
+
+function cop
+{
+ read
+ print ok
+}
+
+exp=ok
+
+cop |&
+pid=$!
+if print -p yo 2>/dev/null
+then read -p got
+else got='no coprocess'
+fi
+[[ $got == $exp ]] || err_exit "main coprocess main query failed -- expected $exp, got '$got'"
+kill $pid 2>/dev/null
+wait
+
+cop |&
+pid=$!
+(
+if print -p yo 2>/dev/null
+then read -p got
+else got='no coprocess'
+fi
+[[ $got == $exp ]] || err_exit "main coprocess subshell query failed -- expected $exp, got '$got'"
+)
+kill $pid 2>/dev/null
+wait
+
+exp='no coprocess'
+
+(
+cop |&
+print $! > $tmp/pid
+)
+pid=$(<$tmp/pid)
+if print -p yo 2>/dev/null
+then read -p got
+else got=$exp
+fi
+[[ $got == $exp ]] || err_exit "subshell coprocess main query failed -- expected $exp, got '$got'"
+kill $pid 2>/dev/null
+wait
+
+(
+cop |&
+print $! > $tmp/pid
+)
+pid=$(<$tmp/pid)
+(
+if print -p yo 2>/dev/null
+then read -p got
+else got=$exp
+fi
+[[ $got == $exp ]] || err_exit "subshell coprocess subshell query failed -- expected $exp, got '$got'"
+kill $pid 2>/dev/null
+wait
+)
+
+function mypipe
+{
+ read; read
+ print -r -- "$REPLY"
+}
+
+mypipe |&
+print -p "hello"
+z="$( $bintrue $($bintrue) )"
+{ print -p "world";} 2> /dev/null
+read -p
+[[ $REPLY == world ]] || err_exit "expected 'world' got '$REPLY'"
+kill $pid 2>/dev/null
+wait
+
+
+function cop
+{
+ read
+ print ok
+}
+exp=ok
+cop |&
+pid=$!
+(
+if print -p yo 2>/dev/null
+then read -p got
+else got='no coprocess'
+fi
+[[ $got == $exp ]] || err_exit "main coprocess subshell query failed -- expected $exp, got '$got'"
+)
+kill $pid 2>/dev/null
+wait
+
+tee=$(whence -p tee)
+ls -l |&
+pid=$!
+$tee -a /dev/null <&p > /dev/null
+wait $pid
+x=$?
+[[ $x == 0 ]] || err_exit "coprocess exitval should be 0, not $x"
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/cubetype.sh b/src/cmd/ksh93/tests/cubetype.sh
new file mode 100755
index 0000000..dbe4e8b
--- /dev/null
+++ b/src/cmd/ksh93/tests/cubetype.sh
@@ -0,0 +1,213 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ (( Errors+=1 ))
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+integer n=2
+
+typeset -T Box_t=(
+ float -h 'height in inches' x=2
+ float -h 'width in inches' y=4
+ comvar=(top=8 bottom=9)
+ integer -S count=0
+ items=(foo bar)
+ colors=([wall]=blue [floor]=red)
+ typeset name=unknown
+ typeset -L6 status=INIT
+ len()
+ {
+ print -r $((sqrt(_.x*_.x + _.y*_.y)))
+ (( _.count++))
+ }
+ typeset -fh 'distance from the origin' len
+ depth()
+ {
+ print 0
+ }
+ float x=3
+)
+
+for ((i=0; i < n; i++))
+do
+Box_t b=(name=box1)
+exp=3 got=${b.x}
+[[ "$got" == "$exp" ]] || err_exit "\${b.x} incorrect for iteration $i -- expected $exp, got '$got'"
+exp=5 got=$(( b.len ))
+(( got == exp )) || err_exit "b.len incorrect for iteration $i -- expected $exp, got '$got = sqrt(${b.x}*${b.x}+${b.y}*${b.y})'"
+exp=5 got=${b.len}
+[[ "$got" == "$exp" ]] || err_exit "\${b.len} incorrect for iteration $i -- expected $exp, got '$got = sqrt(${b.x}*${b.x}+${b.y}*${b.y})'"
+exp=box1 got=${b.name}
+[[ "$got" == "${exp}" ]] || err_exit "\${b.name} incorrect for iteration $i -- expected $exp, got '$got'"
+exp=2 got=$(( b.count ))
+(( got == exp )) || err_exit "b.count incorrect for iteration $i -- expected $exp, got '$got'"
+exp=2 got=${b.count}
+[[ "$got" == "$exp" ]] || err_exit "\${b.ccount} incorrect for iteration $i -- expected $exp, got '$got'"
+b.colors[wall]=green
+b.colors[door]=white
+exp=3 got=${#b.colors[@]}
+[[ "$got" == "$exp" ]] || err_exit "\${#b.colors[@]} incorrect for iteration $i -- expected $exp, got '$got'"
+b.comvar.bottom=11
+b.items[1]=bam
+b.items[2]=extra
+exp=3 got=${#b.items[@]}
+[[ ${#b.items[@]} == 3 ]] || err_exit "\${#b.items[@]} incorrect for iteration $i -- expected $exp, got '$got'"
+Box_t bb=b
+bb.colors[desk]=orange
+exp=4 got=${#b.colors[@]}
+[[ ${#bb.colors[@]} == 4 ]] || err_exit "\${#bb.colors[@]} incorrect for iteration $i -- expected $exp, got '$got'"
+unset b.colors
+exp=2 got=${#b.colors[@]}
+[[ ${#b.colors[@]} == 2 ]] || err_exit "\${#b.colors[@]} incorrect for iteration $i -- expected $exp, got '$got'"
+unset b.items
+exp=2 got=${#b.items[@]}
+[[ ${#b.items[@]} == 2 ]] || err_exit "\${#b.items[@]} incorrect for iteration $i -- expected $exp, got '$got'"
+unset bb.colors
+exp=2 got=${#bb.colors[@]}
+[[ ${#bb.colors[@]} == 2 ]] || err_exit "\${#bb.colors[@]} incorrect for iteration $i -- expected $exp, got '$got'"
+unset bb.items
+exp=2 got=${#bb.items[@]}
+[[ ${#bb.items[@]} == 2 ]] || err_exit "\${#bb.items[@]} incorrect for iteration $i -- expected $exp, got '$got'"
+[[ $b == "$bb" ]] || err_exit "\$b='$b' != \$bb='$bb'"
+b.count=0
+unset b bb
+done
+
+typeset -T Cube_t=(
+ Box_t _=(y=5)
+ float z=1
+ depth()
+ {
+ print -r -- $((_.z))
+ }
+ len()
+ {
+ print -r $((sqrt(_.x*_.x + _.y*_.y + _.z*_.z)))
+ (( _.count++))
+ }
+ float x=8
+ fun()
+ {
+ print 'hello world'
+ }
+)
+
+
+for ((i=0; i < n; i++))
+do
+Box_t b=(name=box2)
+[[ ${b.name} == box2 ]] || err_exit "\${b.name} incorrect -- expected box2, got '${b.name}'"
+(( b.len == 5 )) || err_exit "b.len incorrect for box2 -- expected 5, got '$(( b.len ))'"
+(( b.count == 1 )) || err_exit "b.count incorrect -- expected 1, got '$(( b.count ))'"
+Cube_t c=(name=cube1)
+[[ $c == $'(\n\ttypeset -l -E x=8\n\ttypeset -l -E y=5\n\tcomvar=(\n\t\ttop=8\n\t\tbottom=9\n\t)\n\ttypeset -S -l -i count=1\n\ttypeset -a items=(\n\t\tfoo\n\t\tbar\n\t)\n\ttypeset -A colors=(\n\t\t[floor]=red\n\t\t[wall]=blue\n\t)\n\tname=cube1\n\ttypeset -L 6 status=INIT\n\ttypeset -l -E z=1\n)' ]] || err_exit '$c not correct'
+[[ ${c.x} == 8 ]] || err_exit '${c.x} != 8'
+[[ ${c.depth} == 1 ]] || err_exit '${c.depth} != 1'
+[[ ${c.name} == cube1 ]] || err_exit '${c.name} != cube1 '
+[[ $(c.fun) == 'hello world' ]] || err_exit '$(c.fun) != "hello world"'
+[[ ${c.fun} == 'hello world' ]] || err_exit '${c.fun} != "hello world"'
+(( abs(c.len - sqrt(90)) < 1e-10 )) || err_exit 'c.len != sqrt(90)'
+(( c.count == 2 )) || err_exit 'c.count != 2'
+(( c.count == b.count )) || err_exit 'c.count != b.count'
+c.count=0
+Cube_t d=c
+[[ $d == "$c" ]] || err_exit '$d != $c'
+eval "Cube_t zzz=$c"
+[[ $zzz == "$c" ]] || err_exit '$zzz != $c'
+Cube_t zzz=c
+[[ $zzz == "$c" ]] || err_exit '$zzz != $c without eval'
+xxx=$(typeset -p c)
+eval "${xxx/c=/ccc=}"
+[[ $ccc == "$c" ]] || err_exit '$ccc != $c'
+unset b c d zzz xxx ccc
+done
+for ((i=0; i < n; i++))
+do
+Cube_t cc
+cc[2]=(x=2 y=3 name=two colors+=([table]=white) items+=(pencil) z=6)
+[[ ${cc[0].x} == 8 ]] || err_exit 'cc[0].x !=8'
+[[ ${cc[2].y} == 3 ]] || err_exit '${cc[2].y} != 3'
+(( cc[2].y == 3 )) || err_exit '(( cc[2].y != 3))'
+[[ ${cc[2].colors[table]} == white ]] || err_exit '${cc[2].colors[table]} != white'
+[[ ${cc[2].items[2]} == pencil ]] || err_exit '${cc[2].items[2]} != pencil'
+(( cc[2].len == 7 )) || err_exit '(( cc[2].len != 7 ))'
+[[ $(cc[2].len) == 7 ]] || err_exit '$(cc[2].len) != 7 ))'
+[[ ${cc[2].len} == 7 ]] || err_exit '${cc[2].len} != 7 ))'
+(( cc[2].count == 2 )) || err_exit 'cc[2].count != 2'
+unset cc[2].x cc[2].y cc[2].z
+(( cc[2].len == cc[0].len )) || err_exit 'cc[2].len != cc[0].len'
+(( cc[2].len == cc.len )) || err_exit 'cc[2].len != cc.len'
+(( cc[2].count == 6 )) || err_exit 'cc[2].count != 6'
+unset cc[2].name cc[2].colors cc[2].items
+[[ $cc == "${cc[2]}" ]] || err_exit '$cc != ${cc[2]}'
+cc.count=0
+unset cc
+Cube_t -A cc
+cc[two]=(x=2 y=3 name=two colors+=([table]=white) items+=(pencil) z=6)
+Cube_t cc[one]
+[[ ${#cc[@]} == 2 ]] || err_exit '${#cc[@]} != 2'
+[[ ${cc[two].y} == 3 ]] || err_exit '${cc[two].y} != 3'
+(( cc[two].y == 3 )) || err_exit '(( cc[two].y != 3))'
+[[ ${cc[two].colors[table]} == white ]] || err_exit '${cc[two].colors[table]} != white'
+[[ ${cc[two].items[2]} == pencil ]] || err_exit '${cc[two].items[2]} != pencil'
+(( cc[two].len == 7 )) || err_exit '(( cc[two].len != 7 ))'
+[[ $(cc[two].len) == 7 ]] || err_exit '$(cc[two].len) != 7 ))'
+[[ ${cc[two].len} == 7 ]] || err_exit '${cc[two].len} != 7 ))'
+(( cc[two].count == 2 )) || err_exit 'cc[two].count != 2'
+unset cc[two].x cc[two].y cc[two].z
+(( cc[two].len == cc[one].len )) || err_exit 'cc[two].len != cc[one].len'
+(( cc[two].count == 4 )) || err_exit 'cc[two].count != 4'
+unset cc[two].name unset cc[two].colors cc[two].items
+[[ ${cc[one]} == "${cc[two]}" ]] || err_exit '${cc[one]} != ${cc[two]}'
+cc[two].count=0
+unset cc
+Cube_t cc=(
+ [one]=
+ [two]=(x=2 y=3 name=two colors+=([table]=white) z=6)
+)
+[[ ${#cc[@]} == 2 ]] || err_exit '${#cc[@]} != 2'
+[[ ${cc[two].y} == 3 ]] || err_exit '${cc[two].y} != 3'
+(( cc[two].y == 3 )) || err_exit '(( cc[two].y != 3))'
+[[ ${cc[two].colors[table]} == white ]] || err_exit '${cc[two].colors[table]} != white'
+(( cc[two].len == 7 )) || err_exit '(( cc[two].len != 7 ))'
+[[ $(cc[two].len) == 7 ]] || err_exit '$(cc[two].len) != 7 ))'
+[[ ${cc[two].len} == 7 ]] || err_exit '${cc[two].len} != 7 ))'
+(( cc[two].count == 2 )) || err_exit 'cc[two].count != 2'
+unset cc[two].x cc[two].y cc[two].z
+(( cc[two].len == cc[one].len )) || err_exit 'cc[two].len != cc[one].len'
+(( cc[two].count == 4 )) || err_exit 'cc[two].count != 4'
+cc[three]=cc[two]
+[[ ${cc[two]} == "${cc[three]}" ]] || err_exit "\${cc[two]}='${cc[two]}' != \${cc[three]}='${cc[three]}'"
+[[ $cc[two] == "${cc[three]}" ]] || err_exit "\$cc[two]='${cc[two]}' != \${cc[three]}='${cc[three]}'"
+exp=3
+got=${#cc[@]}
+[[ $got == $exp ]] || err_exit "\${#cc[@]} failed -- expected '$exp', got '$got'"
+unset cc[two].name unset cc[two].colors
+cc[two].count=0
+unset cc
+done
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/enum.sh b/src/cmd/ksh93/tests/enum.sh
new file mode 100755
index 0000000..134a0a3
--- /dev/null
+++ b/src/cmd/ksh93/tests/enum.sh
@@ -0,0 +1,68 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ (( Errors+=1 ))
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+enum Color_t=(red green blue orange yellow)
+enum -i Sex_t=(Male Female)
+for ((i=0; i < 1000; i++))
+do
+Color_t x
+[[ $x == red ]] || err_exit 'Color_t does not default to red'
+x=orange
+[[ $x == orange ]] || err_exit '$x should be orange'
+( x=violet) 2> /dev/null && err_exit 'x=violet should fail'
+x[2]=green
+[[ ${x[2]} == green ]] || err_exit '${x[2]} should be green'
+(( x[2] == 1 )) || err_exit '((x[2]!=1))'
+[[ $((x[2])) == 1 ]] || err_exit '$((x[2]))!=1'
+[[ $x == orange ]] || err_exit '$x is no longer orange'
+Color_t -A y
+y[foo]=yellow
+[[ ${y[foo]} == yellow ]] || err_exit '${y[foo]} != yellow'
+(( y[foo] == 4 )) || err_exit '(( y[foo] != 4))'
+unset y
+typeset -a [Color_t] z
+z[green]=xyz
+[[ ${z[green]} == xyz ]] || err_exit '${z[green]} should be xyz'
+[[ ${z[1]} == xyz ]] || err_exit '${z[1]} should be xyz'
+z[orange]=bam
+[[ ${!z[@]} == 'green orange' ]] || err_exit '${!z[@]} == "green orange"'
+unset x
+Sex_t x
+[[ $x == Male ]] || err_exit 'Sex_t not defaulting to Male'
+x=female
+[[ $x == Female ]] || err_exit 'Sex_t not case sensitive'
+unset x y z
+done
+(
+typeset -T X_t=( typeset name=aha )
+typeset -a[X_t] arr
+) 2> /dev/null
+[[ $? == 1 ]] || err_exit 'typeset -a[X_t] should generate an error message when X-t is not an enumeriation type'
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/exit.sh b/src/cmd/ksh93/tests/exit.sh
new file mode 100755
index 0000000..d2b91b7
--- /dev/null
+++ b/src/cmd/ksh93/tests/exit.sh
@@ -0,0 +1,80 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+function abspath
+{
+ base=$(basename $SHELL)
+ cd ${SHELL%/$base}
+ newdir=$(pwd)
+ cd ~-
+ print $newdir/$base
+}
+#test for proper exit of shell
+builtin getconf
+ABSHELL=$(abspath)
+cd $tmp || { err_exit "cd $tmp failed"; exit 1; }
+print exit 0 >.profile
+${ABSHELL} <<!
+HOME=$PWD \
+PATH=$PATH \
+SHELL=$ABSSHELL \
+$(
+ v=$(getconf LIBPATH)
+ for v in ${v//,/ }
+ do v=${v#*:}
+ v=${v%%:*}
+ eval [[ \$$v ]] && eval print -n \" \"\$v=\"\$$v\"
+ done
+) \
+exec -c -a -ksh ${ABSHELL} -c "exit 1" 1>/dev/null 2>&1
+!
+status=$(echo $?)
+if [[ -o noprivileged && $status != 0 ]]
+then err_exit 'exit in .profile is ignored'
+elif [[ -o privileged && $status == 0 ]]
+then err_exit 'privileged .profile not ignored'
+fi
+if [[ $(trap 'code=$?; echo $code; trap 0; exit $code' 0; exit 123) != 123 ]]
+then err_exit 'exit not setting $?'
+fi
+cat > run.sh <<- "EOF"
+ trap 'code=$?; echo $code; trap 0; exit $code' 0
+ ( trap 0; exit 123 )
+EOF
+if [[ $($SHELL ./run.sh) != 123 ]]
+then err_exit 'subshell trap on exit overwrites parent trap'
+fi
+cd ~- || err_exit "cd back failed"
+$SHELL -c 'builtin -f cmd getconf; getconf --"?-version"; exit 0' >/dev/null 2>&1 || err_exit 'ksh plugin exit failed -- was ksh built with CCFLAGS+=$(CC.EXPORT.DYNAMIC)?'
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/expand.sh b/src/cmd/ksh93/tests/expand.sh
new file mode 100755
index 0000000..2547be8
--- /dev/null
+++ b/src/cmd/ksh93/tests/expand.sh
@@ -0,0 +1,126 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$Line]: "$@"
+ ((Errors++))
+}
+
+integer Errors=0
+Command=${0##*/}
+
+# {...} expansion tests -- ignore if not supported
+
+[[ $(print a{0,1}z) == "a0z a1z" ]] || exit 0
+
+integer Line=$LINENO+1
+set -- \
+ 'ff{c,b,a}' 'ffc ffb ffa' \
+ 'f{d,e,f}g' 'fdg feg ffg' \
+ '{l,n,m}xyz' 'lxyz nxyz mxyz' \
+ '{abc\,def}' '{abc,def}' \
+ '{"abc,def"}' '{abc,def}' \
+ "{'abc,def'}" '{abc,def}' \
+ '{abc}' '{abc}' \
+ '\{a,b,c,d,e}' '{a,b,c,d,e}' \
+ '{x,y,\{a,b,c}}' 'x} y} {a} b} c}' \
+ '{x\,y,\{abc\},trie}' 'x,y {abc} trie' \
+ '/usr/{ucb/{ex,edit},lib/{ex,how_ex}}' '/usr/ucb/ex /usr/ucb/edit /usr/lib/ex /usr/lib/how_ex' \
+ 'XXXX\{a,b,c\}' 'XXXX{a,b,c}' \
+ '{}' '{}' \
+ '{ }' '{ }' \
+ '}' '}' \
+ '{' '{' \
+ 'abcd{efgh' 'abcd{efgh' \
+ 'foo {1,2} bar' 'foo 1 2 bar' \
+ '`print -r -- foo {1,2} bar`' 'foo 1 2 bar' \
+ '$(print -r -- foo {1,2} bar)' 'foo 1 2 bar' \
+ '{1..10}' '1 2 3 4 5 6 7 8 9 10' \
+ '{0..10,braces}' '0..10 braces' \
+ '{{0..10},braces}' '0 1 2 3 4 5 6 7 8 9 10 braces' \
+ 'x{{0..10},braces}y' 'x0y x1y x2y x3y x4y x5y x6y x7y x8y x9y x10y xbracesy' \
+ '{3..3}' '3' \
+ 'x{3..3}y' 'x3y' \
+ '{10..1}' '10 9 8 7 6 5 4 3 2 1' \
+ '{10..1}y' '10y 9y 8y 7y 6y 5y 4y 3y 2y 1y' \
+ 'x{10..1}y' 'x10y x9y x8y x7y x6y x5y x4y x3y x2y x1y' \
+ '{a..f}' 'a b c d e f' \
+ '{f..a}' 'f e d c b a' \
+ '{a..A}' '{a..A}' \
+ '{A..a}' '{A..a}' \
+ '{f..f}' 'f' \
+ '{1..f}' '{1..f}' \
+ '{f..1}' '{f..1}' \
+ '0{1..9} {10..20}' '01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20' \
+ '{-1..-10}' '-1 -2 -3 -4 -5 -6 -7 -8 -9 -10' \
+ '{-19..0}' '-19 -18 -17 -16 -15 -14 -13 -12 -11 -10 -9 -8 -7 -6 -5 -4 -3 -2 -1 0' \
+ '{0..10}' '0 1 2 3 4 5 6 7 8 9 10' \
+ '{0..10..1}' '0 1 2 3 4 5 6 7 8 9 10' \
+ '{0..10..2}' '0 2 4 6 8 10' \
+ '{0..10..3}' '0 3 6 9' \
+ '{0..10..0}' '{0..10..0}' \
+ '{0..10..-1}' '0' \
+ '{10..0}' '10 9 8 7 6 5 4 3 2 1 0' \
+ '{10..0..-1}' '10 9 8 7 6 5 4 3 2 1 0' \
+ '{10..0..-2}' '10 8 6 4 2 0' \
+ '{10..0..-3}' '10 7 4 1' \
+ '{10..0..0}' '{10..0..0}' \
+ '{10..0..1}' '10' \
+ '{a..z..2}' 'a c e g i k m o q s u w y' \
+ '{y..b..-3}' 'y v s p m j g d' \
+ '{0..0x1000..0x200}' '0 512 1024 1536 2048 2560 3072 3584 4096' \
+ '{a,b}{0..2}{z,y}' 'a0z a0y a1z a1y a2z a2y b0z b0y b1z b1y b2z b2y' \
+ '{0..0100..8%03o}' '000 010 020 030 040 050 060 070 100' \
+ '{0..0100..040%020o}' '00000000000000000000 00000000000000000040 00000000000000000100' \
+ '{0..7%03..2u}' '000 001 010 011 100 101 110 111' \
+ '{0..10%llu}' '{0..10%llu}' \
+ '{0..10%s}' '{0..10%s}' \
+ '{0..10%dl}' '{0..10%dl}' \
+ '{a,b}{0..3%02..2u}{y,z}' 'a00y a00z a01y a01z a10y a10z a11y a11z b00y b00z b01y b01z b10y b10z b11y b11z' \
+
+while (($#>1))
+do ((Line++))
+ pattern=$1
+ shift
+ expected=$1
+ shift
+ got=$(eval print -r -- "$pattern")
+ [[ $got == $expected ]] || err_exit "'$pattern' failed -- expected '$expected' got '$got'"
+ #print -r -- " '$pattern' '$got' \\"
+done
+
+# ~(N) no expand glob pattern option
+set -- ~(N)/dev/null
+[[ $# == 1 && $1 == /dev/null ]] || err_exit "~(N)/dev/null not matching /dev/null"
+set -- ~(N)/dev/non_existant_file
+[[ $# == 0 ]] || err_exit "~(N)/dev/nonexistant not empty"
+set -- ""~(N)/dev/non_existant_file
+[[ $# == 1 && ! $1 ]] || err_exit '""~(N)/dev/nonexistant not null argument'
+set -- ~(N)/dev/non_existant_file""
+[[ $# == 1 && ! $1 ]] || err_exit '~(N)/dev/nonexistent"" not null argument'
+for i in ~(N)/dev/non_existent_file
+do err_exit "~(N)/dev/non_existent_file in for loop is $i"
+done
+for i in ""~(N)/dev/non_existent_file
+do [[ ! $i ]] || err_exit '""~(N)/dev/non_existent_file not null'
+done
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/functions.sh b/src/cmd/ksh93/tests/functions.sh
new file mode 100755
index 0000000..fcf3755
--- /dev/null
+++ b/src/cmd/ksh93/tests/functions.sh
@@ -0,0 +1,1157 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2012 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+integer Errors=0
+Command=${0##*/}
+
+ulimit -c 0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+integer foo=33
+bar=bye
+# check for global variables and $0
+function foobar
+{
+ case $1 in
+ 1) print -r - "$foo" "$bar";;
+ 2) print -r - "$0";;
+ 3) typeset foo=foo
+ integer bar=10
+ print -r - "$foo" "$bar";;
+ 4) trap 'foo=36' EXIT
+ typeset foo=20;;
+ esac
+}
+function print
+{
+ command print hi
+}
+if [[ $(print) != hi ]]
+then err_exit "command print not working inside print function"
+fi
+unset -f print
+
+if [[ $(foobar 1) != '33 bye' ]]
+then err_exit 'global variables not correct'
+fi
+
+if [[ $(foobar 2) != 'foobar' ]]
+then err_exit '$0 not correct'
+fi
+
+if [[ $(bar=foo foobar 1) != '33 foo' ]]
+then err_exit 'environment override not correct'
+fi
+if [[ $bar == foo ]]
+then err_exit 'scoping error'
+fi
+
+if [[ $(foobar 3) != 'foo 10' ]]
+then err_exit non-local variables
+fi
+
+foobar 4
+if [[ $foo != 36 ]]
+then err_exit EXIT trap in wrong scope
+fi
+unset -f foobar || err_exit "cannot unset function foobar"
+typeset -f foobar>/dev/null && err_exit "typeset -f has incorrect exit status"
+
+function foobar
+{
+ (return 0)
+}
+> $tmp/test1
+{
+foobar
+if [ -r $tmp/test1 ]
+then rm -r $tmp/test1
+else err_exit 'return within subshell inside function error'
+fi
+}
+abc() print hi
+if [[ $(abc) != hi ]]
+then err_exit 'abc() print hi not working'
+fi
+( unset -f abc )
+if [[ $(abc 2>/dev/null) != hi ]]
+then err_exit 'abc() print hi not working after subshell unset'
+fi
+(
+ function f
+ {
+ exit 1
+ }
+ f
+ err_exit 'exit from function not working'
+)
+unset -f foo
+function foo
+{
+ x=2
+ (
+ x=3
+ cd $tmp
+ print bar
+ )
+ if [[ $x != 2 ]]
+ then err_exit 'value of x not restored after subshell inside function'
+ fi
+}
+x=1
+dir=$PWD
+if [[ $(foo) != bar ]]
+then err_exit 'cd inside nested subshell not working'
+fi
+if [[ $PWD != "$dir" ]]
+then err_exit 'cd inside nested subshell changes $PWD'
+fi
+fun() /bin/echo hello
+if [[ $(fun) != hello ]]
+then err_exit one line functions not working
+fi
+cat > $tmp/script <<-\!
+ print -r -- "$1"
+!
+chmod +x $tmp/script
+function passargs
+{
+ $tmp/script "$@"
+}
+if [[ $(passargs one) != one ]]
+then err_exit 'passing args from functions to scripts not working'
+fi
+cat > $tmp/script <<-\!
+ trap 'exit 0' EXIT
+ function foo
+ {
+ /tmp > /dev/null 2>&1
+ }
+ foo
+!
+if ! $tmp/script
+then err_exit 'exit trap incorrectly triggered'
+fi
+if ! $SHELL -c $tmp/script
+then err_exit 'exit trap incorrectly triggered when invoked with -c'
+fi
+$SHELL -c "trap 'rm $tmp/script' EXIT"
+if [[ -f $tmp/script ]]
+then err_exit 'exit trap not triggered when invoked with -c'
+fi
+cat > $tmp/script <<- \EOF
+ foobar()
+ {
+ return
+ }
+ shift
+ foobar
+ print -r -- "$1"
+EOF
+chmod +x $tmp/script
+if [[ $( $SHELL $tmp/script arg1 arg2) != arg2 ]]
+then err_exit 'arguments not restored by posix functions'
+fi
+function foo
+{
+ print hello
+}
+(
+ function foo
+ {
+ print bar
+ }
+ if [[ $(foo) != bar ]]
+ then err_exit 'function definitions inside subshells not working'
+ fi
+)
+if [[ $(foo) != hello ]]
+then err_exit 'function definitions inside subshells not restored'
+fi
+unset -f foo bar
+function bar
+{
+ print "$y"
+}
+
+function foo
+{
+ typeset x=3
+ y=$x bar
+}
+x=1
+if [[ $(foo) != 3 ]]
+then err_exit 'variable assignment list not using parent scope'
+fi
+unset -f foobar
+cat > $tmp/foobar <<!
+function foobar
+{
+ print foo
+}
+!
+chmod +x $tmp/foobar
+FPATH=$tmp
+autoload foobar
+if [[ $(foobar 2>/dev/null) != foo ]]
+then err_exit 'autoload not working'
+fi
+unset -f foobar
+function foobar
+{
+ typeset -r x=3
+ return 0
+}
+( foobar ) 2> /dev/null || err_exit "cannot unset readonly variable in function"
+if $SHELL -n 2> /dev/null <<-!
+ abc()
+ !
+then err_exit 'abc() without a function body is not a syntax error'
+fi
+function winpath
+{
+ usage='q pathname ...'
+ typeset var format=s
+ while getopts "$usage" var
+ do case $var in
+ q) format=q;;
+ esac
+ done
+ print done
+}
+if [[ $( (winpath --man 2>/dev/null); print ok) != ok ]]
+then err_exit 'getopts --man in functions not working'
+fi
+if [[ $( (winpath -z 2>/dev/null); print ok) != ok ]]
+then err_exit 'getopts with bad option in functions not working'
+fi
+unset -f x
+function x
+{
+ print "$@"
+}
+typeset -ft x
+if [[ $(x x=y 2>/dev/null) != x=y ]]
+then err_exit 'name=value pair args not passed to traced functions'
+fi
+function bad
+{
+ false
+}
+trap 'val=false' ERR
+val=true
+bad
+if [[ $val != false ]]
+then err_exit 'set -e not working for functions'
+fi
+function bad
+{
+ false
+ return 0
+}
+val=true
+bad
+if [[ $val != true ]]
+then err_exit 'set -e not disabled for functions'
+fi
+bad()
+{
+ false
+ return 0
+}
+val=true
+bad
+if [[ $val != false ]]
+then err_exit 'set -e not inherited for posix functions'
+fi
+trap - ERR
+
+function myexport
+{
+ nameref var=$1
+ if (( $# > 1 ))
+ then export $1=$2
+ fi
+ if (( $# > 2 ))
+ then print $(myexport "$1" "$3" )
+ return
+ fi
+ typeset val
+ val=$(export | grep "^$1=")
+ print ${val#"$1="}
+}
+export dgk=base
+val=$(myexport dgk fun)
+if [[ $val != fun ]]
+then err_exit "export inside function not working -- expected 'fun', got '$val'"
+fi
+val=$(export | sed -e '/^dgk=/!d' -e 's/^dgk=//')
+if [[ $val != base ]]
+then err_exit "export not restored after function call -- expected 'base', got '$val'"
+fi
+val=$(myexport dgk fun fun2)
+if [[ $val != fun2 ]]
+then err_exit "export inside function not working with recursive function -- expected 'fun2', got '$val'"
+fi
+val=$(export | sed -e '/^dgk=/!d' -e 's/^dgk=//')
+if [[ $val != base ]]
+then err_exit "export not restored after recursive function call -- expected 'base', got '$val'"
+fi
+val=$(dgk=try3 myexport dgk)
+if [[ $val != try3 ]]
+then err_exit "name=value not added to export list with function call -- expected 'try3', got '$val'"
+fi
+val=$(export | sed -e '/^dgk=/!d' -e 's/^dgk=//')
+if [[ $val != base ]]
+then err_exit "export not restored name=value function call -- expected 'base', got '$val'"
+fi
+unset zzz
+val=$(myexport zzz fun)
+if [[ $val != fun ]]
+then err_exit "export inside function not working -- expected 'fun', got '$val'"
+fi
+val=$(export | sed -e '/^zzz=/!d' -e 's/^zzz=//')
+if [[ $val ]]
+then err_exit "unset varaible exported after function call -- expected '', got '$val'"
+fi
+
+unset zzz
+typeset -u zzz
+function foo
+{
+ zzz=abc
+ print $zzz
+}
+if [[ $(foo)$(foo) != ABCABC ]]
+then err_exit 'attributes on unset variables not saved/restored'
+fi
+function xpd {
+ typeset i j=$1
+ for i
+ do print i=$i j=$j
+ [[ $i == a ]] && xpd b
+ done
+ }
+if [[ $(xpd a c) != $'i=a j=a\ni=b j=b\ni=c j=a' ]]
+then err_exit 'for loop function optimization error'
+fi
+
+typeset -A visited
+integer level=0
+function closure
+{
+ (( $# > 5 )) && return 1
+ ((level < 2)) && ((level++))
+ typeset tmp r=0
+ visited[$1]=1
+
+ for tmp in $level _$level
+ do
+ [[ ${visited[$tmp]} == 1 ]] && continue
+ closure $tmp $* || r=1
+ done
+ return $r
+}
+closure 0 || err_exit -u2 'for loop function optimization bug2'
+dir=$tmp/dir
+mkdir $dir
+cd $dir || { err_exit "cd $dir failed"; exit 1; }
+
+(
+ function a {
+ print a
+ }
+ function b {
+ print 1
+ a
+ print 2
+ } > /dev/null
+ typeset -ft a b
+ PS4=X
+ b
+) > file 2>&1
+[[ $(<file) == *'Xprint 2'* ]] || err_exit 'function trace disabled by function call'
+rm -f file
+
+print 'false' > try
+chmod +x try
+cat > tst <<- EOF
+ function ignore
+ {
+ ./try
+ return 0
+ }
+ trap "print error; exit 1" ERR
+ ignore
+EOF
+if [[ $($SHELL < tst) == error ]]
+then err_exit 'ERR trap not cleared'
+fi
+FPATH=$dir
+print ': This does nothing' > foobar
+chmod +x foobar
+unset -f foobar
+{ foobar; } 2>/dev/null
+got=$?
+exp=126
+if [[ $got != $exp ]]
+then err_exit "function file without function definition processes wrong error -- expected '$exp', got '$got'"
+fi
+print 'set a b c' > dotscript
+[[ $(PATH=$PATH: $SHELL -c '. dotscript;print $#') == 3 ]] || err_exit 'positional parameters not preserved with . script without arguments'
+cd ~- || err_exit "cd back failed"
+function errcheck
+{
+ trap 'print ERR; return 1' ERR
+ false
+ print ok
+}
+err=$(errcheck)
+[[ $err == ERR ]] || err_exit 'trap on ERR not working in a function'
+x="$(
+ function foobar
+ {
+ print ok
+ }
+ typeset -f foobar
+)"
+eval "$x" || err_exit 'typeset -f generates syntax error'
+[[ $(foobar) != ok ]] && err_exit 'typeset -f not generating function'
+unset -f a b c
+a()
+{
+ b
+ b
+ print ${.sh.fun}
+}
+b() { : ;}
+[[ $(a) == a ]] || err_exit '.sh.fun not set correctly in a function'
+print $'a(){\ndate\n}' | $SHELL 2> /dev/null || err_exit 'parser error in a(){;date;}'
+cat > $tmp/data1 << '++EOF'
+ 1 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ 2 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ 3 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ 4 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ 5 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ 6 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ 7 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ 8 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ 9 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ 10 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ 11 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ 12 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ 13 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ 14 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ 15 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ 16 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ 17 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ 18 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ 19 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ 20 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+++EOF
+cat > $tmp/script << '++EOF'
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+
+f()
+{
+cat <<\M
+++EOF
+cat $tmp/data1 >> $tmp/script
+printf 'M\n}\n\nf\n\n' >> $tmp/script
+$SHELL -c $tmp/script > $tmp/data2
+cmp -s $tmp/data[12] || err_exit 'error with long functions'
+v=1
+function f
+{
+ typeset i
+ for i in 0 1
+ do typeset v
+ v=$i
+ [[ $v == $i ]] || return 1
+ done
+}
+f || err_exit "typeset optimization bug"
+function f
+{
+ print -r -- "$foo$bar"
+}
+function g
+{
+ print -r -- $(bar=bam f)
+}
+unset foo bar
+[[ $(foo=hello g) == hellobam ]] || err_exit 'function exports not passed on'
+[[ $(bar=hello g) == bam ]] || err_exit 'function exports not overridden'
+unset -f foo
+function foo
+{
+ typeset line=$1
+ set +n
+ while [[ $line ]]
+ do if [[ ! $varname ]]
+ then varname=${line%% *}
+ line=${line##"$varname"?( )}
+ [[ $line ]] && continue
+ else print ok
+ return
+ fi
+ varname=
+ done
+}
+[[ $(foo 'NUMBERED RECORDSIZE') == ok ]] || err_exit 'optimization error with undefined variable'
+unset x
+x=$(
+ set -e
+ integer count=0
+ function err_f
+ {
+ if ((count++==3))
+ then print failed
+ else false
+ fi
+ }
+ trap 'err_f' ERR
+ false
+)
+[[ $x == failed ]] && err_exit 'ERR trap executed multiple times'
+export environment
+typeset global
+function f
+{
+ typeset i t local
+
+ for i
+ do case $i in
+ [-+]*) set "$@"
+ continue
+ ;;
+ local) local=f
+ t=$(typeset +f $local)
+ ;;
+ global) global=f
+ t=$(typeset +f $global)
+ ;;
+ environment)
+ environment=f
+ t=$(typeset +f $environment)
+ ;;
+ literal)t=$(typeset +f f)
+ ;;
+ positional)
+ set -- f
+ t=$(typeset +f $1)
+ ;;
+ esac
+ [[ $t ]] || err_exit "typeset +f \$$i failed"
+ done
+}
+f local global environment literal positional
+$SHELL -c '
+ print exit 0 > '$tmp'/script
+ chmod +x '$tmp'/script
+ unset var
+ var=( ident=1 )
+ function fun
+ {
+ PATH='$tmp' script
+ }
+ fun
+' || err_exit "compound variable cleanup before script exec failed"
+( $SHELL << \++EOF++
+function main
+{
+ typeset key
+ typeset -A entry
+ entry[a]=( value=aaa )
+}
+main
+++EOF++
+) 2> /dev/null || err_exit 'function main fails'
+optind=$OPTIND
+sub()
+{
+ (
+ OPTIND=1
+ while getopts :abc OPTION "$@"
+ do print OPTIND=$OPTIND
+ done
+ )
+}
+[[ $(sub -a) == OPTIND=2 ]] || err_exit 'OPTIND should be 2'
+[[ $(sub -a) == OPTIND=2 ]] || err_exit 'OPTIND should be 2 again'
+[[ $OPTIND == "$optind" ]] || err_exit 'OPTIND should be 1'
+
+function bar
+{
+ [[ -o nounset ]] && err_exit 'nounset option should not be inherited'
+}
+function foo
+{
+ set -o nounset
+ bar
+}
+set +o nounset
+foo
+function red
+{
+ integer -S d=0
+ printf 'red_one %d\n' d
+ (( d++ ))
+ return 0
+}
+[[ ${ red } != 'red_one 0' ]] && err_exit 'expected red_one 0'
+[[ ${ red } != 'red_one 1' ]] && err_exit 'expected red_one 1'
+xyz=$0
+function traceback
+{
+ integer .level=.sh.level
+ while((--.level>=0))
+ do
+ ((.sh.level = .level))
+ [[ $xyz == "$0" ]] || err_exit "\$xyz=$xyz does not match $0 on level ${.level}"
+ [[ ${.sh.lineno} == "$1" ]] || err_exit "\${.sh.lineno}=${.sh.lineno} does not match $1 on level ${.level}"
+ done
+}
+
+function foo
+{
+ typeset xyz=foo
+ set -- $((LINENO+1))
+ bar $LINENO "$1"
+}
+
+function bar
+{
+ typeset xyz=bar
+ set -- $((LINENO+2))
+ trap 'traceback $LINENO' DEBUG
+ : $LINENO "$1"
+}
+
+set -- $((LINENO+1))
+foo $LINENO
+function .sh.fun.set
+{
+ print -r -- "${.sh.value}"
+}
+function abc
+{
+ :
+}
+def()
+{
+ :
+}
+[[ $(abc) == abc ]] || err_exit '.sh.fun.set not capturing function name'
+[[ $(def) == def ]] || err_exit '.sh.fun.set not capturing name()'
+unset -f .sh.fun.set
+
+# tests for debug functions
+basefile=${.sh.file}
+integer baseline
+cat > $tmp/debug << \+++
+ : line 1
+
+ : line 3
++++
+# Print one line in a call stack
+function _Dbg_print_frame
+{
+ typeset -i pos=$1
+ typeset fn=$2
+ typeset filename="$3"
+ typeset -i line=$4
+ typeset arg=$5
+ shift 5
+ if ((pos==0))
+ then [[ $filename == "$basefile" ]] || err_exit "filename for level 0 is $filename not $basename"
+ [[ $arg == DEBUG ]] && ((baseline++))
+ [[ $line == "$baseline" ]] || err_exit "line number for level 0 is $line not $baseline"
+ elif ((pos==1))
+ then [[ $filename == "$tmp/debug" ]] || err_exit "filename for level 1 is $filename not $tmp/debug"
+ [[ $* == 'foo bar' ]] || err_exit "args are '$*', not 'foo bar'"
+ [[ $line == $arg ]] || err_exit "line number for level 1 is $line not $arg"
+ else err_exit "level should be 0 or 1 but is $pos"
+ fi
+}
+
+function _Dbg_debug_trap_handler
+{
+
+ integer .level=.sh.level .max=.sh.level-1
+ while((--.level>=0))
+ do
+ ((.sh.level = .level))
+ _Dbg_print_frame "${.level}" "$0" "${.sh.file}" "${.sh.lineno}" "${.sh.command##* }" "$@"
+ done
+}
+
+((baseline=LINENO+2))
+trap '_Dbg_debug_trap_handler' DEBUG
+. $tmp/debug foo bar
+trap '' DEBUG
+
+caller() {
+ integer .level=.sh.level .max=.sh.level-1
+ while((--.level>=0))
+ do
+ ((.sh.level = .level))
+ print -r -- "${.sh.lineno}"
+ done
+}
+bar() { caller;}
+set -- $(bar)
+[[ $1 == $2 ]] && err_exit ".sh.inline optimization bug"
+( $SHELL -c ' function foo { typeset x=$1;print $1;};z=();z=($(foo bar)) ') 2> /dev/null || err_exit 'using a function to set an array in a command sub fails'
+
+{
+got=$(
+s=$(ulimit -s)
+if [[ $s == +([[:digit:]]) ]] && (( s < 16384 ))
+then ulimit -s 16384 2>/dev/null
+fi
+$SHELL << \+++
+f()
+{
+ if (($1>1))
+ then x=$(f $(($1-1))) || exit 1
+ fi
+ return 0
+}
+f 257 && print ok
++++
+)
+} 2>/dev/null
+[[ $got == ok ]] || err_exit 'cannot handle comsub depth > 256 in function'
+
+tmp1=$tmp/job.1
+tmp2=$tmp/job.2
+cat > $tmp1 << +++
+#! $SHELL
+print \$\$
++++
+chmod +x $tmp1
+function foo
+{
+ typeset pid
+ $tmp1 > $tmp2 & pid=$!
+ wait $!
+ [[ $(< $tmp2) == $pid ]] || err_exit 'wrong pid for & job in function'
+}
+foo
+# make sure compiled functions work
+[[ $(tmp=$tmp $SHELL <<- \++++
+ cat > $tmp/functions <<- \EOF
+ function bar
+ {
+ print foo
+ }
+ function foobar
+ {
+ bar
+ }
+ EOF
+ ${SHCOMP:-${SHELL%/*}/shcomp} $tmp/functions > $tmp/foobar
+ rm -f "$tmp/functions"
+ chmod +x $tmp/foobar
+ rm $tmp/!(dir|foobar)
+ FPATH=$tmp
+ PATH=$FPATH:$PATH
+ foobar
+++++
+) == foo ]] > /dev/null || err_exit 'functions compiled with shcomp not working'
+# tests for compiled . scripts
+print $'print hello\nprint world' > $tmp/foo
+${SHCOMP:-${SHELL%/*}/shcomp} $tmp/foo > $tmp/foo.sh
+val=$(. $tmp/foo.sh)
+[[ $val == $'hello\nworld' ]] || err_exit "processing compiled dot files not working correctly val=$val"
+# test for functions in shell having side effects.
+unset -f foo foobar bar
+cd "$tmp"
+FPATH=$PWD
+PATH=$FPATH:$PATH
+cat > foo <<- \EOF
+ function bar
+ {
+ print foobar
+ }
+ function foo
+ {
+ bar
+ }
+EOF
+chmod +x foo
+: $(foo)
+[[ $(typeset +f) == *foo* ]] && err_exit 'function in subshell leaving side effect of function foo'
+unset -f foo bar
+: $(foo)
+[[ $(typeset +f) == *foo* ]] && err_exit 'function in subshell leaving side effects of function foo after reload'
+[[ $(typeset +f) == *bar* ]] && err_exit 'function in subshell leaving side effects of function bar after reload'
+
+unset -f foo
+typeset -A bar
+function foo
+{
+ typeset -i bar[$1].x
+ bar[$1].x=5
+}
+foo sub
+[[ ${!bar[@]} == sub ]] || err_exit 'scoping problem with compound array variables'
+
+function A
+{
+ trap "> /dev/null;print TRAP A" EXIT
+ # (( stderr )) && print >&2
+}
+
+function B
+{
+ trap "> /dev/null;print TRAP B" EXIT
+ A
+}
+
+x=$(B)
+[[ $x == $'TRAP A\nTRAP B' ]] || err_exit "trap from functions in subshells fails got" $x
+
+function foo
+{
+ typeset bar=abc
+ unset bar
+# [[ $bar == bam ]] || err_exit 'unsetting local variable does not expose global variable'
+ [[ $bar ]] && err_exit 'unsetting local variable exposes global variable'
+}
+bar=bam
+foo
+
+sleep=$(whence -p sleep)
+function gosleep
+{
+ $sleep 4
+}
+x=$(
+ (sleep 2; pid=; ps | grep sleep | read pid extra; [[ $pid ]] && kill -- $pid) &
+ gosleep 2> /dev/null
+ print ok
+)
+[[ $x == ok ]] || err_exit 'TERM signal sent to last process of function kills the script'
+
+# verify that $0 does not change with functions defined as fun()
+func1()
+{
+ [[ $0 == "$dol0" ]] || err_exit "\$0 changed in func1() to $0"
+}
+function func2
+{
+ [[ $0 == func2 ]] || err_exit "\$0 changed in func2() to $0"
+ dol0=func2
+ func1
+}
+func2
+
+{ $SHELL <<- \EOF
+ function foo
+ {
+ typeset rc=0
+ unset -f foo
+ return $rc;
+ }
+ foo
+EOF
+} 2> /dev/null || err_exit 'problem with unset -f foo within function foo'
+
+val=$($SHELL 2> /dev/null <<- \EOF
+ .sh.fun.set() { set -x; }
+ function f1 { print -n ${.sh.fun}; set -o | grep xtrace;}
+ function f2 { print -n ${.sh.fun}; set -o | grep xtrace;}
+ f1
+ set -o | grep xtrace
+ f2
+EOF)
+[[ $val == f1xtrace*on*off*f2xtrace*on* ]] || err_exit "'.sh.fun.set() { set -x; }' not tracing all functions"
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/glob.sh b/src/cmd/ksh93/tests/glob.sh
new file mode 100755
index 0000000..5b7930e
--- /dev/null
+++ b/src/cmd/ksh93/tests/glob.sh
@@ -0,0 +1,374 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2012 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -r $'\t'"${Command}[$1] ${@:2}"
+ ((Errors++))
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer aware=0 contrary=0 Errors=0 ignorant=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+function test_glob
+{
+ typeset lineno expected drop arg got sep op val add del
+ lineno=$1
+ shift
+ if [[ $1 == --* ]]
+ then del=${1#--}
+ shift
+ fi
+ if [[ $1 == ++* ]]
+ then add=${1#++}
+ shift
+ fi
+ expected=$1
+ shift
+ if (( contrary ))
+ then if [[ $expected == "<Beware> "* ]]
+ then expected=${expected#"<Beware> "}
+ expected="$expected <Beware>"
+ fi
+ if [[ $expected == *"<aXb> <abd>"* ]]
+ then expected=${expected/"<aXb> <abd>"/"<abd> <aXb>"}
+ fi
+ fi
+ for arg
+ do got="$got$sep<$arg>"
+ sep=" "
+ done
+ if (( ignorant && aware ))
+ then if [[ $del ]]
+ then got="<$del> $got"
+ fi
+ if [[ $add ]]
+ then expected="<$add> $expected"
+ fi
+ fi
+ if [[ $got != "$expected" ]]
+ then 'err_exit' $lineno "glob -- expected '$expected', got '$got'"
+ fi
+}
+alias test_glob='test_glob $LINENO'
+
+function test_case
+{
+ typeset lineno expected subject pattern got
+ lineno=$1 expected=$2 subject=$3 pattern=$4
+ eval "
+ case $subject in
+ $pattern) got='<match>' ;;
+ *) got='<nomatch>' ;;
+ esac
+ "
+ if [[ $got != "$expected" ]]
+ then 'err_exit' $lineno "case $subject in $pattern) -- expected '$expected', got '$got'"
+ fi
+}
+alias test_case='test_case $LINENO'
+
+unset undefined
+
+cd $tmp || { err_exit "cd $tmp failed"; exit 1; }
+
+export LC_COLLATE=C
+touch B b
+set -- *
+case $* in
+'b B') contrary=1 ;;
+b|B) ignorant=1 ;;
+esac
+set -- $(LC_ALL=C /bin/sh -c 'echo [a-c]')
+case $* in
+B) aware=1 ;;
+esac
+rm -rf *
+
+touch a b c d abc abd abe bb bcd ca cb dd de Beware
+mkdir bdir
+
+test_glob '<a> <abc> <abd> <abe> <X*>' a* X*
+test_glob '<a> <abc> <abd> <abe>' \a*
+
+if ( set --nullglob ) 2>/dev/null
+then
+ set --nullglob
+
+ test_glob '<a> <abc> <abd> <abe>' a* X*
+
+ set --nonullglob
+fi
+
+if ( set --failglob ) 2>/dev/null
+then
+ set --failglob
+ mkdir tmp
+ touch tmp/l1 tmp/l2 tmp/l3
+
+ test_glob '' tmp/l[12] tmp/*4 tmp/*3
+ test_glob '' tmp/l[12] tmp/*4 tmp/*3
+
+ rm -r tmp
+ set --nofailglob
+fi
+
+test_glob '<bdir/>' b*/
+test_glob '<*>' \*
+test_glob '<a*>' 'a*'
+test_glob '<a*>' a\*
+test_glob '<c> <ca> <cb> <a*> <*q*>' c* a\* *q*
+test_glob '<**>' "*"*
+test_glob '<**>' \**
+test_glob '<\.\./*/>' "\.\./*/"
+test_glob '<s/\..*//>' 's/\..*//'
+test_glob '</^root:/{s/^[!:]*:[!:]*:\([!:]*\).*$/\1/>' "/^root:/{s/^[!:]*:[!:]*:\([!:]*\).*"'$'"/\1/"
+test_glob '<abc> <abd> <abe> <bb> <cb>' [a-c]b*
+test_glob ++Beware '<abd> <abe> <bb> <bcd> <bdir> <ca> <cb> <dd> <de>' [a-y]*[!c]
+test_glob '<abd> <abe>' a*[!c]
+
+touch a-b aXb
+
+test_glob '<a-b> <aXb>' a[X-]b
+
+touch .x .y
+
+test_glob --Beware '<Beware> <d> <dd> <de>' [!a-c]*
+
+if mkdir a\*b 2>/dev/null
+then
+ touch a\*b/ooo
+
+ test_glob '<a*b/ooo>' a\*b/*
+ test_glob '<a*b/ooo>' a\*?/*
+ test_case '<match>' '!7' '*\!*'
+ test_case '<match>' 'r.*' '*.\*'
+ test_glob '<abc>' a[b]c
+ test_glob '<abc>' a["b"]c
+ test_glob '<abc>' a[\b]c
+ test_glob '<abc>' a?c
+ test_case '<match>' 'abc' 'a"b"c'
+ test_case '<match>' 'abc' 'a*c'
+ test_case '<nomatch>' 'abc' '"a?c"'
+ test_case '<nomatch>' 'abc' 'a\*c'
+ test_case '<nomatch>' 'abc' 'a\[b]c'
+ test_case '<match>' '"$undefined"' '""'
+ test_case '<match>' 'abc' 'a["\b"]c'
+
+ rm -rf mkdir a\*b
+fi
+
+mkdir man
+mkdir man/man1
+touch man/man1/sh.1
+
+test_glob '<man/man1/sh.1>' */man*/sh.*
+test_glob '<man/man1/sh.1>' $(echo */man*/sh.*)
+test_glob '<man/man1/sh.1>' "$(echo */man*/sh.*)"
+
+test_case '<match>' 'abc' 'a***c'
+test_case '<match>' 'abc' 'a*****?c'
+test_case '<match>' 'abc' '?*****??'
+test_case '<match>' 'abc' '*****??'
+test_case '<match>' 'abc' '*****??c'
+test_case '<match>' 'abc' '?*****?c'
+test_case '<match>' 'abc' '?***?****c'
+test_case '<match>' 'abc' '?***?****?'
+test_case '<match>' 'abc' '?***?****'
+test_case '<match>' 'abc' '*******c'
+test_case '<match>' 'abc' '*******?'
+test_case '<match>' 'abcdecdhjk' 'a*cd**?**??k'
+test_case '<match>' 'abcdecdhjk' 'a**?**cd**?**??k'
+test_case '<match>' 'abcdecdhjk' 'a**?**cd**?**??k***'
+test_case '<match>' 'abcdecdhjk' 'a**?**cd**?**??***k'
+test_case '<match>' 'abcdecdhjk' 'a**?**cd**?**??***k**'
+test_case '<match>' 'abcdecdhjk' 'a****c**?**??*****'
+test_case '<match>' "'-'" '[-abc]'
+test_case '<match>' "'-'" '[abc-]'
+test_case '<match>' "'\\'" '\\'
+test_case '<match>' "'\\'" '[\\]'
+test_case '<match>' "'\\'" "'\\'"
+test_case '<match>' "'['" '[[]'
+test_case '<match>' '[' '[[]'
+test_case '<match>' "'['" '['
+test_case '<match>' '[' '['
+test_case '<match>' "'[abc'" "'['*"
+test_case '<nomatch>' "'[abc'" '[*'
+test_case '<match>' '[abc' "'['*"
+test_case '<nomatch>' '[abc' '[*'
+test_case '<match>' 'abd' "a[b/c]d"
+test_case '<match>' 'a/d' "a[b/c]d"
+test_case '<match>' 'acd' "a[b/c]d"
+test_case '<match>' "']'" '[]]'
+test_case '<match>' "'-'" '[]-]'
+test_case '<match>' 'p' '[a-\z]'
+test_case '<match>' '"/tmp"' '[/\\]*'
+test_case '<nomatch>' 'abc' '??**********?****?'
+test_case '<nomatch>' 'abc' '??**********?****c'
+test_case '<nomatch>' 'abc' '?************c****?****'
+test_case '<nomatch>' 'abc' '*c*?**'
+test_case '<nomatch>' 'abc' 'a*****c*?**'
+test_case '<nomatch>' 'abc' 'a********???*******'
+test_case '<nomatch>' "'a'" '[]'
+test_case '<nomatch>' 'a' '[]'
+test_case '<nomatch>' "'['" '[abc'
+test_case '<nomatch>' '[' '[abc'
+
+test_glob ++Beware '<b> <bb> <bcd> <bdir>' b*
+test_glob '<Beware> <b> <bb> <bcd> <bdir>' [bB]*
+
+if ( set --nocaseglob ) 2>/dev/null
+then
+ set --nocaseglob
+
+ test_glob '<Beware> <b> <bb> <bcd> <bdir>' b*
+ test_glob '<Beware> <b> <bb> <bcd> <bdir>' [b]*
+ test_glob '<Beware> <b> <bb> <bcd> <bdir>' [bB]*
+
+ set --nonocaseglob
+fi
+
+if ( set -f ) 2>/dev/null
+then
+ set -f
+
+ test_glob '<*>' *
+
+ set +f
+fi
+
+if ( set --noglob ) 2>/dev/null
+then
+ set --noglob
+
+ test_glob '<*>' *
+
+ set --glob
+fi
+
+FIGNORE='@(.*|*)'
+test_glob '<*>' *
+
+FIGNORE='@(.*|*c|*e|?)'
+test_glob '<a-b> <aXb> <abd> <bb> <bcd> <bdir> <ca> <cb> <dd> <man>' *
+
+FIGNORE='@(.*|*b|*d|?)'
+test_glob '<Beware> <abc> <abe> <bdir> <ca> <de> <man>' *
+
+FIGNORE=
+test_glob '<man/man1/sh.1>' */man*/sh.*
+
+unset FIGNORE
+test_glob '<bb> <ca> <cb> <dd> <de>' ??
+test_glob '<man/man1/sh.1>' */man*/sh.*
+
+GLOBIGNORE='.*:*'
+set -- *
+if [[ $1 == '*' ]]
+then
+ GLOBIGNORE='.*:*c:*e:?'
+ test_glob '<>' *
+
+ GLOBIGNORE='.*:*b:*d:?'
+ test_glob '<>' *
+
+ unset GLOBIGNORE
+ test_glob '<>' *
+ test_glob '<man/man1/sh.1>' */man*/sh.*
+
+ GLOBIGNORE=
+ test_glob '<man/man1/sh.1>' */man*/sh.*
+fi
+unset GLOBIGNORE
+
+function test_sub
+{
+ x='${subject'$2'}'
+ eval g=$x
+ if [[ "$g" != "$3" ]]
+ then 'err_exit' $1 subject="'$subject' $x failed, expected '$3', got '$g'"
+ fi
+}
+alias test_sub='test_sub $LINENO'
+
+set --noglob --nobraceexpand
+
+subject='A regular expressions test'
+
+test_sub '/e/#' 'A r#gular expressions test'
+test_sub '//e/#' 'A r#gular #xpr#ssions t#st'
+test_sub '/[^e]/#' '# regular expressions test'
+test_sub '//[^e]/#' '###e######e###e########e##'
+test_sub '/+(e)/#' 'A r#gular expressions test'
+test_sub '//+(e)/#' 'A r#gular #xpr#ssions t#st'
+test_sub '/@-(e)/#' 'A r#gular expressions test'
+test_sub '//@-(e)/#' 'A r#gular #xpr#ssions t#st'
+test_sub '/?(e)/#' '#A regular expressions test'
+test_sub '//?(e)/#' '#A# #r#g#u#l#a#r# #x#p#r#s#s#i#o#n#s# #t#s#t#'
+test_sub '/*(e)/#' '#A regular expressions test'
+test_sub '//*(e)/#' '#A# #r#g#u#l#a#r# #x#p#r#s#s#i#o#n#s# #t#s#t#'
+test_sub '//@(e)/[\1]' 'A r[e]gular [e]xpr[e]ssions t[e]st'
+test_sub '//@-(e)/[\1]' 'A r[e]gular [e]xpr[e]ssions t[e]st'
+test_sub '//+(e)/[\1]' 'A r[e]gular [e]xpr[e]ssions t[e]st'
+test_sub '//+-(e)/[\1]' 'A r[e]gular [e]xpr[e]ssions t[e]st'
+test_sub '//@(+(e))/[\1]' 'A r[e]gular [e]xpr[e]ssions t[e]st'
+test_sub '//@(+-(e))/[\1]' 'A r[e]gular [e]xpr[e]ssions t[e]st'
+test_sub '//-(e)/#' 'A regular expressions test'
+test_sub '//--(e)/#' 'A regular expressions test'
+test_sub '//?(e)/[\1]' '[]A[] []r[e]g[]u[]l[]a[]r[] [e]x[]p[]r[e]s[]s[]i[]o[]n[]s[] []t[e]s[]t[]'
+test_sub '//{0,1}(e)/[\1]' '[]A[] []r[e]g[]u[]l[]a[]r[] [e]x[]p[]r[e]s[]s[]i[]o[]n[]s[] []t[e]s[]t[]'
+test_sub '//*(e)/[\1]' '[]A[] []r[e]g[]u[]l[]a[]r[] [e]x[]p[]r[e]s[]s[]i[]o[]n[]s[] []t[e]s[]t[]'
+test_sub '//{0,}(e)/[\1]' '[]A[] []r[e]g[]u[]l[]a[]r[] [e]x[]p[]r[e]s[]s[]i[]o[]n[]s[] []t[e]s[]t[]'
+test_sub '//@(?(e))/[\1]' '[]A[] []r[e]g[]u[]l[]a[]r[] [e]x[]p[]r[e]s[]s[]i[]o[]n[]s[] []t[e]s[]t[]'
+test_sub '//@({0,1}(e))/[\1]' '[]A[] []r[e]g[]u[]l[]a[]r[] [e]x[]p[]r[e]s[]s[]i[]o[]n[]s[] []t[e]s[]t[]'
+test_sub '//@(*(e))/[\1]' '[]A[] []r[e]g[]u[]l[]a[]r[] [e]x[]p[]r[e]s[]s[]i[]o[]n[]s[] []t[e]s[]t[]'
+test_sub '//@({0,}(e))/[\1]' '[]A[] []r[e]g[]u[]l[]a[]r[] [e]x[]p[]r[e]s[]s[]i[]o[]n[]s[] []t[e]s[]t[]'
+test_sub '/?-(e)/#' '#A regular expressions test'
+test_sub '/@(?-(e))/[\1]' '[]A regular expressions test'
+test_sub '/!(e)/#' '#'
+test_sub '//!(e)/#' '#'
+test_sub '/@(!(e))/[\1]' '[A regular expressions test]'
+test_sub '//@(!(e))/[\1]' '[A regular expressions test]'
+
+subject='e'
+
+test_sub '/!(e)/#' '#e'
+test_sub '//!(e)/#' '#e#'
+test_sub '/!(e)/[\1]' '[]e'
+test_sub '//!(e)/[\1]' '[]e[]'
+test_sub '/@(!(e))/[\1]' '[]e'
+test_sub '//@(!(e))/[\1]' '[]e[]'
+
+subject='a'
+
+test_sub '/@(!(a))/[\1]' '[]a'
+test_sub '//@(!(a))/[\1]' '[]a[]'
+
+subject='aha'
+
+test_sub '/@(!(a))/[\1]' '[aha]'
+test_sub '//@(!(a))/[\1]' '[aha]'
+test_sub '/@(!(aha))/[\1]' '[ah]a'
+test_sub '//@(!(aha))/[\1]' '[ah][a]'
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/grep.sh b/src/cmd/ksh93/tests/grep.sh
new file mode 100755
index 0000000..480f823
--- /dev/null
+++ b/src/cmd/ksh93/tests/grep.sh
@@ -0,0 +1,105 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+function grep
+{
+ #
+ # SHELL VERSION OF GREP
+ #
+ vflag= xflag= cflag= lflag= nflag=
+ set -f
+ while ((1)) # look for grep options
+ do case "$1" in
+ -v*) vflag=1;;
+ -x*) xflag=1;;
+ -c*) cflag=1;;
+ -l*) lflag=1;;
+ -n*) nflag=1;;
+ -b*) print 'b option not supported';;
+ -e*) shift;expr="$1";;
+ -f*) shift;expr=$(< $1);;
+ -*) print $0: 'unknown flag';return 2;;
+ *)
+ if test "$expr" = ''
+ then expr="$1";shift
+ fi
+ test "$xflag" || expr="*${expr}*"
+ break;;
+ esac
+ shift # next argument
+ done
+ noprint=$vflag$cflag$lflag # don't print if these flags are set
+ integer n=0 c=0 tc=0 nargs=$# # initialize counters
+ for i in "$@" # go thru the files
+ do if ((nargs<=1))
+ then fname=''
+ else fname="$i":
+ fi
+ test "$i" && exec 0< $i # open file if necessary
+ while read -r line # read in a line
+ do let n=n+1
+ case "$line" in
+ $expr) # line matches pattern
+ test "$noprint" || print -r -- "$fname${nflag:+$n:}$line"
+ let c=c+1 ;;
+ *) # not a match
+ if test "$vflag"
+ then print -r -- "$fname${nflag:+$n:}$line"
+ fi;;
+ esac
+ done
+ if test "$lflag" && ((c))
+ then print -r -- "$i"
+ fi
+ let tc=tc+c n=0 c=0
+ done
+ test "$cflag" && print $tc # print count if cflag is set
+ let tc # set the return value
+}
+
+cat > $tmp/grep <<\!
+this is a food bar test
+to see how many lines find both foo and bar.
+Some line contain foo only,
+and some lines contain bar only.
+However, many lines contain both foo and also bar.
+A line containing foobar should also be counted.
+There should be six lines with foo and bar.
+There are only two line with out foo but with bar.
+!
+
+if (( $(grep -c 'foo*bar' $tmp/grep ) != 6))
+then err_exit
+fi
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/heredoc.sh b/src/cmd/ksh93/tests/heredoc.sh
new file mode 100755
index 0000000..a8d8a72
--- /dev/null
+++ b/src/cmd/ksh93/tests/heredoc.sh
@@ -0,0 +1,496 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+f=$tmp/here1
+g=$tmp/here2
+cat > $f <<!
+hello world
+!
+if [[ $(<$f) != 'hello world' ]]
+then err_exit "'hello world' here doc not working"
+fi
+cat > $g <<\!
+hello world
+!
+cmp $f $g 2> /dev/null || err_exit "'hello world' quoted here doc not working"
+cat > $g <<- !
+ hello world
+!
+cmp $f $g 2> /dev/null || err_exit "'hello world' tabbed here doc not working"
+cat > $g <<- \!
+ hello world
+!
+cmp $f $g 2> /dev/null || err_exit "'hello world' quoted tabbed here doc not working"
+x=hello
+cat > $g <<!
+$x world
+!
+cmp $f $g 2> /dev/null || err_exit "'$x world' here doc not working"
+cat > $g <<!
+$(print hello) world
+!
+cmp $f $g 2> /dev/null || err_exit "'$(print hello) world' here doc not working"
+cat > $f <<\!!
+!@#$%%^^&*()_+~"::~;'`<>?/.,{}[]
+!!
+if [[ $(<$f) != '!@#$%%^^&*()_+~"::~;'\''`<>?/.,{}[]' ]]
+then err_exit "'hello world' here doc not working"
+fi
+cat > $g <<!!
+!@#\$%%^^&*()_+~"::~;'\`<>?/.,{}[]
+!!
+cmp $f $g 2> /dev/null || err_exit "unquoted here doc not working"
+exec 3<<!
+ foo
+!
+if [[ $(<&3) != ' foo' ]]
+then err_exit "leading tabs stripped with <<!"
+fi
+$SHELL -c "
+eval `echo 'cat <<x'` "|| err_exit "eval `echo 'cat <<x'` core dumps"
+cat > /dev/null <<EOF # comments should not cause core dumps
+abc
+EOF
+cat >$g << :
+:
+:
+cmp /dev/null $g 2> /dev/null || err_exit "empty here doc not working"
+x=$(print $( cat <<HUP
+hello
+HUP
+)
+)
+if [[ $x != hello ]]
+then err_exit "here doc inside command sub not working"
+fi
+y=$(cat <<!
+${x:+${x}}
+!
+)
+if [[ $y != "${x:+${x}}" ]]
+then err_exit '${x:+${x}} not working in here document'
+fi
+$SHELL -c '
+x=0
+while (( x < 100 ))
+do ((x = x+1))
+ cat << EOF
+EOF
+done
+' 2> /dev/null || err_exit '100 empty here docs fails'
+{
+ print 'builtin -d cat
+ cat <<- EOF'
+ for ((i=0; i < 100; i++))
+ do print XXXXXXXXXXXXXXXXXXXX
+ done
+ print ' XXX$(date)XXXX
+ EOF'
+} > $f
+chmod +x "$f"
+$SHELL "$f" > /dev/null || err_exit "large here-doc with command substitution fails"
+x=$(/bin/cat <<!
+$0
+!
+)
+[[ "$x" == "$0" ]] || err_exit '$0 not correct inside here documents'
+$SHELL -c 'x=$(
+cat << EOF
+EOF)' 2> /dev/null || err_exit 'here-doc cannot be terminated by )'
+if [[ $( IFS=:;cat <<-!
+ $IFS$(print hi)$IFS
+ !) != :hi: ]]
+then err_exit '$IFS unset by command substitution in here docs'
+fi
+if x=$($SHELL -c 'cat <<< "hello world"' 2> /dev/null)
+then [[ $x == 'hello world' ]] || err_exit '<<< documents not working'
+ x=$($SHELL -c 'v="hello world";cat <<< $v' 2> /dev/null)
+ [[ $x == 'hello world' ]] || err_exit '<<< documents with $x not working'
+ x=$($SHELL -c 'v="hello world";cat <<< "$v"' 2> /dev/null)
+ [[ $x == 'hello world' ]] || err_exit '<<< documents with $x not working'
+else err_exit '<<< syntax not supported'
+fi
+if [[ $(cat << EOF #testing
+#abc
+abc
+EOF) != $'#abc\nabc' ]]
+then err_exit 'comments not preserved in here-documents'
+fi
+cat > "$f" <<- '!!!!'
+ builtin cat
+ : << EOF
+ $PWD
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ EOF
+ command exec 3>&- 4>&- 5>&- 6>&- 7>&- 8>&- 9>&-
+ x=abc
+ cat << EOF
+ $x
+ EOF
+!!!!
+chmod 755 "$f"
+if [[ $($SHELL "$f") != abc ]]
+then err_exit 'here document descritor was closed'
+fi
+cat > "$f" <<- '!!!!'
+ exec 0<&-
+ foobar()
+ {
+ /bin/cat <<- !
+ foobar
+ !
+ }
+ : << EOF
+ $PWD
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ EOF
+ print -r -- "$(foobar)"
+!!!!
+if [[ $($SHELL "$f") != foobar ]]
+then err_exit 'here document with stdin closed failed'
+fi
+printf $'cat <<# \\!!!\n\thello\n\t\tworld\n!!!' > $f
+[[ $($SHELL "$f") == $'hello\n\tworld' ]] || err_exit "<<# not working for quoted here documents"
+printf $'w=world;cat <<# !!!\n\thello\n\t\t$w\n!!!' > $f
+[[ $($SHELL "$f") == $'hello\n\tworld' ]] || err_exit "<<# not working for non-quoted here documents"
+[[ $( $SHELL <<- \++++
+ S=( typeset a )
+ function S.a.get
+ {
+ .sh.value=$__a
+ }
+ __a=1234
+ cat <<-EOF
+ ${S.a}
+ EOF
+++++
+) == 1234 ]] 2> /dev/null || err_exit 'here document with get discipline failed'
+[[ $($SHELL -c 'g(){ print ok;}; cat <<- EOF
+ ${ g;}
+ EOF
+ ' 2> /dev/null) == ok ]] || err_exit '${ command;} not working in heredoc'
+script=$f
+{
+for ((i=0; i < 406; i++))
+do print ': 23456789012345678'
+done
+print : 123456789123
+cat <<- \EOF
+eval "$(
+ { cat ; } <<MARKER
+ print hello
+ MARKER
+)"
+EOF
+} > $script
+chmod +x $script
+[[ $($SHELL $script) == hello ]] 2> /dev/null || err_exit 'heredoc embeded in command substitution fails at buffer boundary'
+
+got=$( cat << EOF
+\
+abc
+EOF)
+[[ $got == abc ]] || err_exit 'line continuation at start of buffer not working'
+
+tmpfile1=$tmp/file1
+tmpfile2=$tmp/file2
+function gendata
+{
+ typeset -RZ3 i
+ for ((i=0; i < 500; i++))
+ do print -r -- "=====================This is line $i============="
+ done
+}
+
+cat > $tmpfile1 <<- +++
+ function foobar
+ {
+ cat << XXX
+ $(gendata)
+ XXX
+ }
+ cat > $tmpfile2 <<- EOF
+ \$(foobar)
+ $(gendata)
+EOF
++++
+chmod +x $tmpfile1
+$SHELL $tmpfile1
+set -- $(wc < $tmpfile2)
+(( $1 == 1000 )) || err_exit "heredoc $1 lines, should be 1000 lines"
+(( $2 == 4000 )) || err_exit "heredoc $2 words, should be 4000 words"
+
+# comment with here document looses line number count
+integer line=$((LINENO+5))
+function tst
+{
+ [[ $1 == $2 ]] || echo expected $1, got $2
+}
+tst $line $LINENO <<"!" # this comment affects LINENO #
+1
+!
+(( (line+=3) == LINENO )) || err_exit "line number=$LINENO should be $line"
+
+[[ $($SHELL -c 'wc -c <<< ""' 2> /dev/null) == *1 ]] || err_exit '<<< with empty string not working'
+
+mkdir $tmp/functions
+cat > $tmp/functions/t2 <<\!!!
+function t2
+{
+cat <<EOF | sed 's/1234567890/qwertyuiopasdfghj/'
+${1}
+EOF
+}
+!!!
+
+FPATH=$tmp/functions
+foo=${
+cat <<EOF
+1 34567890 $(t2 1234567890 ) 0123456789012345678901234567890123
+111111111111111111111111111111111111111111111111111111111111111
+111111111111111111111111111111111111111111111111111111111111111
+111111111111111111111111111111111111111111111111111111111111111
+111111111111111111111111111111111111111111111111111111111111111
+111111111111111111111111111111111111111111111111111111111111111
+111111111111111111111111111111111111111111111111111111111111111
+111111111111111111111111111111111111111111111111111111111111111
+111111111111111111111111111111111111111111111111111111111111111
+111111111111111111111111111111111111111111111111111111111111111
+111111111111111111111111111111111111111111111111111111111111111
+111111111111111111111111111111111111111111111111111111111111111
+111111111111111111111111111111111111111111111111111111111111111
+111111111111111111111111111111111111111111111111111111111111111
+111111111111111111111111111111111111111111111111111111111111111
+111111111111111111111111111111111111111111111111111111111111 1
+
+2 34567890 $(t2 1234567890 ) 0123456789012345678901234567890123
+222222222222222222222222222222222222222222222222222222222222222
+222222222222222222222222222222222222222222222222222222222222222
+222222222222222222222222222222222222222222222222222222222222222
+222222222222222222222222222222222222222222222222222222222222222
+222222222222222222222222222222222222222222222222222222222222222
+222222222222222222222222222222222222222222222222222222222222222
+222222222222222222222222222222222222222222222222222222222222222
+222222222222222222222222222222222222222222222222222222222222222
+222222222222222222222222222222222222222222222222222222222222222
+222222222222222222222222222222222222222222222222222222222222222
+222222222222222222222222222222222222222222222222222222222222222
+222222222222222222222222222222222222222222222222222222222222222
+222222222222222222222222222222222222222222222222222222222222222
+222222222222222222222222222222222222222222222222222222222222222
+222222222222222222222222222222222222222222222222222222222222 2
+
+3 34567890 $(t2 1234567890 ) 0123456789012345678901234567890123
+333333333333333333333333333333333333333333333333333333333333333
+333333333333333333333333333333333333333333333333333333333333333
+333333333333333333333333333333333333333333333333333333333333333
+333333333333333333333333333333333333333333333333333333333333333
+333333333333333333333333333333333333333333333333333333333333333
+333333333333333333333333333333333333333333333333333333333333333
+333333333333333333333333333333333333333333333333333333333333333
+333333333333333333333333333333333333333333333333333333333333333
+333333333333333333333333333333333333333333333333333333333333333
+333333333333333333333333333333333333333333333333333333333333333
+333333333333333333333333333333333333333333333333333333333333333
+333333333333333333333333333333333333333333333333333333333333333
+333333333333333333333333333333333333333333333333333333333333333
+333333333333333333333333333333333333333333333333333333333333333
+333333333333333333333333333333333333333333333333333333333333 3
+
+4 34567890 $(t2 1234567890 ) 0123456789012345678901234567890123
+444444444444444444444444444444444444444444444444444444444444444
+444444444444444444444444444444444444444444444444444444444444444
+444444444444444444444444444444444444444444444444444444444444444
+444444444444444444444444444444444444444444444444444444444444444
+444444444444444444444444444444444444444444444444444444444444444
+444444444444444444444444444444444444444444444444444444444444444
+444444444444444444444444444444444444444444444444444444444444444
+444444444444444444444444444444444444444444444444444444444444444
+444444444444444444444444444444444444444444444444444444444444444
+444444444444444444444444444444444444444444444444444444444444444
+444444444444444444444444444444444444444444444444444444444444444
+444444444444444444444444444444444444444444444444444444444444444
+444444444444444444444444444444444444444444444444444444444444444
+444444444444444444444444444444444444444444444444444444444444444
+444444444444444444444444444444444444444444444444444444444444 4
+
+5 34567890 $(t2 1234567890 ) 0123456789012345678901234567890123
+555555555555555555555555555555555555555555555555555555555555555
+555555555555555555555555555555555555555555555555555555555555555
+555555555555555555555555555555555555555555555555555555555555555
+555555555555555555555555555555555555555555555555555555555555555
+555555555555555555555555555555555555555555555555555555555555555
+555555555555555555555555555555555555555555555555555555555555555
+555555555555555555555555555555555555555555555555555555555555555
+555555555555555555555555555555555555555555555555555555555555555
+555555555555555555555555555555555555555555555555555555555555555
+555555555555555555555555555555555555555555555555555555555555555
+555555555555555555555555555555555555555555555555555555555555555
+555555555555555555555555555555555555555555555555555555555555555
+555555555555555555555555555555555555555555555555555555555555555
+555555555555555555555555555555555555555555555555555555555555555
+555555555555555555555555555555555555555555555555555555555555 5
+
+6 34567890 $(t2 1234567890 ) 0123456789012345678901234567890123
+666666666666666666666666666666666666666666666666666666666666666
+666666666666666666666666666666666666666666666666666666666666666
+666666666666666666666666666666666666666666666666666666666666666
+666666666666666666666666666666666666666666666666666666666666666
+666666666666666666666666666666666666666666666666666666666666666
+666666666666666666666666666666666666666666666666666666666666666
+666666666666666666666666666666666666666666666666666666666666666
+666666666666666666666666666666666666666666666666666666666666666
+666666666666666666666666666666666666666666666666666666666666666
+666666666666666666666666666666666666666666666666666666666666666
+666666666666666666666666666666666666666666666666666666666666666
+666666666666666666666666666666666666666666666666666666666666666
+666666666666666666666666666666666666666666666666666666666666666
+666666666666666666666666666666666666666666666666666666666666666
+666666666666666666666666666666666666666666666666666666666666 6
+
+7 34567890 $(t2 1234567890 ) 0123456789012345678901234567890123
+777777777777777777777777777777777777777777777777777777777777777
+777777777777777777777777777777777777777777777777777777777777777
+777777777777777777777777777777777777777777777777777777777777777
+777777777777777777777777777777777777777777777777777777777777777
+777777777777777777777777777777777777777777777777777777777777777
+777777777777777777777777777777777777777777777777777777777777777
+777777777777777777777777777777777777777777777777777777777777777
+777777777777777777777777777777777777777777777777777777777777777
+777777777777777777777777777777777777777777777777777777777777777
+777777777777777777777777777777777777777777777777777777777777777
+777777777777777777777777777777777777777777777777777777777777777
+777777777777777777777777777777777777777777777777777777777777777
+777777777777777777777777777777777777777777777777777777777777777
+777777777777777777777777777777777777777777777777777777777777777
+777777777777777777777777777777777777777777777777777777777777 7
+
+8 34567890 $(t2 1234567890 ) 0123456789012345678901234567890123
+888888888888888888888888888888888888888888888888888888888888888
+888888888888888888888888888888888888888888888888888888888888888
+888888888888888888888888888888888888888888888888888888888888888
+888888888888888888888888888888888888888888888888888888888888888
+888888888888888888888888888888888888888888888888888888888888888
+888888888888888888888888888888888888888888888888888888888888888
+888888888888888888888888888888888888888888888888888888888888888
+888888888888888888888888888888888888888888888888888888888888888
+888888888888888888888888888888888888888888888888888888888888888
+888888888888888888888888888888888888888888888888888888888888888
+888888888888888888888888888888888888888888888888888888888888888
+888888888888888888888888888888888888888888888888888888888888888
+888888888888888888888888888888888888888888888888888888888888888
+888888888888888888888888888888888888888888888888888888888888888
+888888888888888888888888888888888888888888888888888888888888 8
+
+9 34567890 $(t2 1234567890 ) 0123456789012345678901234567890123
+999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999 9
+
+10 4567890 $(t2 1234567890 ) 0123456789012345678901234567890123
+101010101010101010101010101010101010101010101010101010101010103
+101010101010101010101010101010101010101010101010101010101010103
+101010101010101010101010101010101010101010101010101010101010103
+101010101010101010101010101010101010101010101010101010101010103
+101010101010101010101010101010101010101010101010101010101010103
+101010101010101010101010101010101010101010101010101010101010103
+101010101010101010101010101010101010101010101010101010101010103
+101010101010101010101010101010101010101010101010101010101010103
+101010101010101010101010101010101010101010101010101010101010103
+101010101010101010101010101010101010101010101010101010101010103
+101010101010101010101010101010101010101010101010101010101010103
+101010101010101010101010101010101010101010101010101010101010103
+101010101010101010101010101010101010101010101010101010101010103
+101010101010101010101010101010101010101010101010101010101010103
+1010101010101010101010101010101010101010101010101010101010 END
+
+EOF
+}
+[[ ${#foo} == 10238 ]] || err_exit 'large here docs containing command subs of dynamically loaded functions fails'
+
+{
+ print $'FOO=1\nBAR=foobarbaz'
+ print -- 'cat <<#EOF'
+ integer i
+ for ((i=0; i < 50000; i++))
+ do print -r -- ' $(($FOO + 1))'
+ print -r -- ' $BAR meep'
+ done
+ print EOF
+} > $f
+$SHELL $f > $g
+[[ $(grep meep $g | grep -v foobar) != '' ]] && err_exit 'here-doc loosing $var expansions on boundaries in rare cases'
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/io.sh b/src/cmd/ksh93/tests/io.sh
new file mode 100755
index 0000000..bed0fd4
--- /dev/null
+++ b/src/cmd/ksh93/tests/io.sh
@@ -0,0 +1,484 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2012 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+unset HISTFILE
+
+function fun
+{
+ while command exec 3>&1
+ do break
+ done 2> /dev/null
+ print -u3 good
+}
+print 'read -r a; print -r -u$1 -- "$a"' > $tmp/mycat
+chmod 755 $tmp/mycat
+for ((i=3; i < 10; i++))
+do
+ eval "a=\$(print foo | $tmp/mycat" $i $i'>&1 > /dev/null |cat)' 2> /dev/null
+ [[ $a == foo ]] || err_exit "bad file descriptor $i in comsub script"
+done
+exec 3> /dev/null
+[[ $(fun) == good ]] || err_exit 'file 3 closed before subshell completes'
+exec 3>&-
+cd $tmp || { err_exit "cd $tmp failed"; exit ; }
+print foo > file1
+print bar >> file1
+if [[ $(<file1) != $'foo\nbar' ]]
+then err_exit 'append (>>) not working'
+fi
+set -o noclobber
+exec 3<> file1
+read -u3 line
+exp=foo
+if [[ $line != $exp ]]
+then err_exit "read on <> fd failed -- expected '$exp', got '$line'"
+fi
+if ( 4> file1 ) 2> /dev/null
+then err_exit 'noclobber not causing exclusive open'
+fi
+set +o noclobber
+
+FDFS=(
+ ( dir=/proc/self/fd semantics='open' )
+ ( dir=/proc/$$/fd semantics='open' )
+ ( dir=/dev/fd semantics='open|dup' )
+ ( dir=/dev/fd semantics='dup' )
+)
+for ((fdfs=0; fdfs<${#FDFS[@]}-1; fdfs++))
+do [[ -e ${FDFS[fdfs].dir} ]] && { command : > ${FDFS[fdfs].dir}/1; } 2>/dev/null >&2 && break
+done
+
+exec 3<> file1
+if command exec 4< ${FDFS[fdfs].dir}/3
+then read -u3 got
+ read -u4 got
+ exp='foo|bar'
+ case $got in
+ foo) semantics='open' ;;
+ bar) semantics='dup' ;;
+ *) semantics='failed' ;;
+ esac
+ [[ $semantics == @(${FDFS[fdfs].semantics}) ]] || err_exit "'4< ${FDFS[fdfs].dir}/3' $semantics semantics instead of ${FDFS[fdfs].semantics} -- expected '$exp', got '$got'"
+fi
+
+# 2004-11-25 ancient /dev/fd/N redirection bug fix
+got=$(
+ {
+ print -n 1
+ print -n 2 > ${FDFS[fdfs].dir}/2
+ print -n 3
+ print -n 4 > ${FDFS[fdfs].dir}/2
+ } 2>&1
+)
+exp='1234|4'
+case $got in
+1234) semantics='dup' ;;
+4) semantics='open' ;;
+*) semantics='failed' ;;
+esac
+[[ $semantics == @(${FDFS[fdfs].semantics}) ]] || err_exit "${FDFS[fdfs].dir}/N $semantics semantics instead of ${FDFS[fdfs].semantics} -- expected '$exp', got '$got'"
+
+cat > close0 <<\!
+exec 0<&-
+echo $(./close1)
+!
+print "echo abc" > close1
+chmod +x close0 close1
+x=$(./close0)
+if [[ $x != "abc" ]]
+then err_exit "picked up file descriptor zero for opening script file"
+fi
+cat > close0 <<\!
+ for ((i=0; i < 1100; i++))
+ do exec 4< /dev/null
+ read -u4
+ done
+ exit 0
+!
+./close0 2> /dev/null || err_exit "multiple exec 4< /dev/null can fail"
+$SHELL -c '
+ trap "rm -f in out" EXIT
+ for ((i = 0; i < 1000; i++))
+ do print -r -- "This is a test"
+ done > in
+ > out
+ exec 1<> out
+ builtin cat
+ print -r -- "$(<in)"
+ cmp -s in out' 2> /dev/null
+[[ $? == 0 ]] || err_exit 'builtin cat truncates files'
+cat >| script <<-\!
+print hello
+( exec 3<&- 4<&-)
+exec 3<&- 4<&-
+print world
+!
+chmod +x script
+[[ $( $SHELL ./script) == $'hello\nworld' ]] || err_exit 'closing 3 & 4 causes script to fail'
+cd ~- || err_exit "cd back failed"
+( exec > '' ) 2> /dev/null && err_exit '> "" does not fail'
+unset x
+( exec > ${x} ) 2> /dev/null && err_exit '> $x, where x null does not fail'
+exec <<!
+foo
+bar
+!
+( exec 0< /dev/null)
+read line
+if [[ $line != foo ]]
+then err_exit 'file descriptor not restored after exec in subshell'
+fi
+exec 3>&- 4>&-
+[[ $( {
+ read -r line; print -r -- "$line"
+ (
+ read -r line; print -r -- "$line"
+ ) & wait
+ while read -r line
+ do print -r -- "$line"
+ done
+ } << !
+line 1
+line 2
+line 3
+!) == $'line 1\nline 2\nline 3' ]] || err_exit 'read error with subshells'
+# 2004-05-11 bug fix
+cat > $tmp/1 <<- ++EOF++
+ script=$tmp/2
+ trap "rm -f \$script" EXIT
+ exec 9> \$script
+ for ((i=3; i<9; i++))
+ do eval "while read -u\$i; do : ; done \$i</dev/null"
+ print -u9 "exec \$i< /dev/null"
+ done
+ for ((i=0; i < 60; i++))
+ do print -u9 -f "%.80c\n" ' '
+ done
+ print -u9 'print ok'
+ exec 9<&-
+ chmod +x \$script
+ \$script
+++EOF++
+chmod +x $tmp/1
+[[ $($SHELL $tmp/1) == ok ]] || err_exit "parent i/o causes child script to fail"
+# 2004-12-20 redirection loss bug fix
+cat > $tmp/1 <<- \++EOF++
+ function a
+ {
+ trap 'print ok' EXIT
+ : > /dev/null
+ }
+ a
+++EOF++
+chmod +x $tmp/1
+[[ $($tmp/1) == ok ]] || err_exit "trap on EXIT loses last command redirection"
+print > /dev/null {n}> $tmp/1
+[[ ! -s $tmp/1 ]] && newio=1
+if [[ $newio && $(print hello | while read -u$n; do print $REPLY; done {n}<&0) != hello ]]
+then err_exit "{n}<&0 not working with for loop"
+fi
+[[ $({ read -r; read -u3 3<&0; print -- "$REPLY" ;} <<!
+hello
+world
+!) == world ]] || err_exit 'I/O not synchronized with <&'
+x="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNSPQRSTUVWXYZ1234567890"
+for ((i=0; i < 62; i++))
+do printf "%.39c\n" ${x:i:1}
+done > $tmp/seek
+if command exec 3<> $tmp/seek
+then (( $(3<#) == 0 )) || err_exit "not at position 0"
+ (( $(3<# ((EOF))) == 40*62 )) || err_exit "not at end-of-file"
+ command exec 3<# ((40*8)) || err_exit "absolute seek fails"
+ read -u3
+ [[ $REPLY == +(i) ]] || err_exit "expected iiii..., got $REPLY"
+ [[ $(3<#) == $(3<# ((CUR)) ) ]] || err_exit '$(3<#)!=$(3<#((CUR)))'
+ command exec 3<# ((CUR+80))
+ read -u3
+ [[ $REPLY == {39}(l) ]] || err_exit "expected lll..., got $REPLY"
+ command exec 3<# ((EOF-80))
+ read -u3
+ [[ $REPLY == +(9) ]] || err_exit "expected 999..., got $REPLY"
+ command exec 3># ((80))
+ print -u3 -f "%.39c\n" @
+ command exec 3># ((80))
+ read -u3
+ [[ $REPLY == +(@) ]] || err_exit "expected @@@..., got $REPLY"
+ read -u3
+ [[ $REPLY == +(d) ]] || err_exit "expected ddd..., got $REPLY"
+ command exec 3># ((EOF))
+ print -u3 -f "%.39c\n" ^
+ (( $(3<# ((CUR-0))) == 40*63 )) || err_exit "not at extended end-of-file"
+ command exec 3<# ((40*62))
+ read -u3
+ [[ $REPLY == +(^) ]] || err_exit "expected ddd..., got $REPLY"
+ command exec 3<# ((0))
+ command exec 3<# *jjjj*
+ read -u3
+ [[ $REPLY == {39}(j) ]] || err_exit "<# pattern failed"
+ [[ $(command exec 3<## *llll*) == {39}(k) ]] || err_exit "<## pattern not saving standard output"
+ read -u3
+ [[ $REPLY == {39}(l) ]] || err_exit "<## pattern failed to position"
+ command exec 3<# *abc*
+ read -u3 && err_exit "not found pattern not positioning at eof"
+ cat $tmp/seek | read -r <# *WWW*
+ [[ $REPLY == *WWWWW* ]] || err_exit '<# not working for pipes'
+ { < $tmp/seek <# ((2358336120)) ;} 2> /dev/null || err_exit 'long seek not working'
+else err_exit "$tmp/seek: cannot open for reading"
+fi
+command exec 3<&- || 'cannot close 3'
+for ((i=0; i < 62; i++))
+do printf "%.39c\n" ${x:i:1}
+done > $tmp/seek
+if command exec {n}<> $tmp/seek
+then { command exec {n}<#((EOF)) ;} 2> /dev/null || err_exit '{n}<# not working'
+ if $SHELL -c '{n}</dev/null' 2> /dev/null
+ then (( $({n}<#) == 40*62)) || err_exit '$({n}<#) not working'
+ else err_exit 'not able to parse {n}</dev/null'
+ fi
+fi
+$SHELL -ic '
+{
+ print -u2 || exit 2
+ print -u3 || exit 3
+ print -u4 || exit 4
+ print -u5 || exit 5
+ print -u6 || exit 6
+ print -u7 || exit 7
+ print -u8 || exit 8
+ print -u9 || exit 9
+} 3> /dev/null 4> /dev/null 5> /dev/null 6> /dev/null 7> /dev/null 8> /dev/null 9> /dev/null' > /dev/null 2>&1
+exitval=$?
+(( exitval )) && err_exit "print to unit $exitval failed"
+$SHELL -c "{ > $tmp/1 ; date;} >&- 2> /dev/null" > $tmp/2
+[[ -s $tmp/1 || -s $tmp/2 ]] && err_exit 'commands with standard output closed produce output'
+$SHELL -c "$SHELL -c ': 3>&1' 1>&- 2>/dev/null" && err_exit 'closed standard output not passed to subshell'
+[[ $(cat <<- \EOF | $SHELL
+ do_it_all()
+ {
+ dd 2>/dev/null # not a ksh93 buildin
+ return $?
+ }
+ do_it_all ; exit $?
+ hello world
+EOF) == 'hello world' ]] || err_exit 'invalid readahead on stdin'
+$SHELL -c 'exec 3>; /dev/null' 2> /dev/null && err_exit '>; with exec should be an error'
+$SHELL -c ': 3>; /dev/null' 2> /dev/null || err_exit '>; not working with at all'
+print hello > $tmp/1
+if ! $SHELL -c "false >; $tmp/1" 2> /dev/null
+then [[ $(<$tmp/1) == hello ]] || err_exit '>; not preserving file on failure'
+fi
+if ! $SHELL -c "sed -e 's/hello/hello world/' $tmp/1" >; $tmp/1 2> /dev/null
+then [[ $(<$tmp/1) == 'hello world' ]] || err_exit '>; not updating file on success'
+fi
+
+$SHELL -c 'exec 3<>; /dev/null' 2> /dev/null && err_exit '<>; with exec should be an error'
+$SHELL -c ': 3<>; /dev/null' 2> /dev/null || err_exit '<>; not working with at all'
+print $'hello\nworld' > $tmp/1
+if ! $SHELL -c "false <>; $tmp/1" 2> /dev/null
+then [[ $(<$tmp/1) == $'hello\nworld' ]] || err_exit '<>; not preserving file on failure'
+fi
+if ! $SHELL -c "head -1 $tmp/1" <>; $tmp/1 2> /dev/null
+then [[ $(<$tmp/1) == hello ]] || err_exit '<>; not truncating file on success of head'
+fi
+print $'hello\nworld' > $tmp/1
+if ! $SHELL -c head < $tmp/1 <#((6)) <>; $tmp/1 2> /dev/null
+then [[ $(<$tmp/1) == world ]] || err_exit '<>; not truncating file on success of behead'
+fi
+
+unset y
+read -n1 y <<!
+abc
+!
+if [[ $y != a ]]
+then err_exit 'read -n1 not working'
+fi
+unset a
+{ read -N3 a; read -N1 b;} <<!
+abcdefg
+!
+[[ $a == abc ]] || err_exit 'read -N3 here-document not working'
+[[ $b == d ]] || err_exit 'read -N1 here-document not working'
+read -n3 a <<!
+abcdefg
+!
+[[ $a == abc ]] || err_exit 'read -n3 here-document not working'
+(print -n a; sleep 1; print -n bcde) | { read -N3 a; read -N1 b;}
+[[ $a == abc ]] || err_exit 'read -N3 from pipe not working'
+[[ $b == d ]] || err_exit 'read -N1 from pipe not working'
+(print -n a; sleep 1; print -n bcde) |read -n3 a
+[[ $a == a ]] || err_exit 'read -n3 from pipe not working'
+if mkfifo $tmp/fifo 2> /dev/null
+then (print -n a; sleep 2; print -n bcde) > $tmp/fifo &
+ {
+ read -u5 -n3 -t3 a || err_exit 'read -n3 from fifo timed out'
+ read -u5 -n1 -t3 b || err_exit 'read -n1 from fifo timed out'
+ } 5< $tmp/fifo
+ exp=a
+ got=$a
+ [[ $got == "$exp" ]] || err_exit "read -n3 from fifo failed -- expected '$exp', got '$got'"
+ exp=b
+ got=$b
+ [[ $got == "$exp" ]] || err_exit "read -n1 from fifo failed -- expected '$exp', got '$got'"
+ rm -f $tmp/fifo
+ wait
+ mkfifo $tmp/fifo 2> /dev/null
+ (print -n a; sleep 2; print -n bcde) > $tmp/fifo &
+ {
+ read -u5 -N3 -t3 a || err_exit 'read -N3 from fifo timed out'
+ read -u5 -N1 -t3 b || err_exit 'read -N1 from fifo timed out'
+ } 5< $tmp/fifo
+ exp=abc
+ got=$a
+ [[ $got == "$exp" ]] || err_exit "read -N3 from fifo failed -- expected '$exp', got '$got'"
+ exp=d
+ got=$b
+ [[ $got == "$exp" ]] || err_exit "read -N1 from fifo failed -- expected '$exp', got '$got'"
+ wait
+fi
+(
+ print -n 'prompt1: '
+ sleep .1
+ print line2
+ sleep .1
+ print -n 'prompt2: '
+ sleep .1
+) | {
+ read -t2 -n 1000 line1
+ read -t2 -n 1000 line2
+ read -t2 -n 1000 line3
+ read -t2 -n 1000 line4
+}
+[[ $? == 0 ]] && err_exit 'should have timed out'
+[[ $line1 == 'prompt1: ' ]] || err_exit "line1 should be 'prompt1: '"
+[[ $line2 == line2 ]] || err_exit "line2 should be line2"
+[[ $line3 == 'prompt2: ' ]] || err_exit "line3 should be 'prompt2: '"
+[[ ! $line4 ]] || err_exit "line4 should be empty"
+
+if $SHELL -c "export LC_ALL=C.UTF-8; c=$'\342\202\254'; [[ \${#c} == 1 ]]" 2>/dev/null
+then lc_utf8=C.UTF-8
+else lc_utf8=''
+fi
+
+typeset -a e o=(-n2 -N2)
+integer i
+set -- \
+ 'a' 'bcd' 'a bcd' 'ab cd' \
+ 'ab' 'cd' 'ab cd' 'ab cd' \
+ 'abc' 'd' 'ab cd' 'ab cd' \
+ 'abcd' '' 'ab cd' 'ab cd'
+while (( $# >= 3 ))
+do a=$1
+ b=$2
+ e[0]=$3
+ e[1]=$4
+ shift 4
+ for ((i = 0; i < 2; i++))
+ do for lc_all in C $lc_utf8
+ do g=$(LC_ALL=$lc_all $SHELL -c "{ print -n '$a'; sleep 0.2; print -n '$b'; sleep 0.2; } | { read ${o[i]} a; print -n \$a; read a; print -n \ \$a; }")
+ [[ $g == "${e[i]}" ]] || err_exit "LC_ALL=$lc_all read ${o[i]} from pipe '$a $b' failed -- expected '${e[i]}', got '$g'"
+ done
+ done
+done
+
+if [[ $lc_utf8 ]]
+then export LC_ALL=$lc_utf8
+ typeset -a c=( '' 'A' $'\303\274' $'\342\202\254' )
+ integer i w
+ typeset o
+ if (( ${#c[2]} == 1 && ${#c[3]} == 1 ))
+ then for i in 1 2 3
+ do for o in n N
+ do for w in 1 2 3
+ do print -nr "${c[w]}" | read -${o}${i} g
+ if [[ $o == N ]] && (( i > 1 ))
+ then e=''
+ else e=${c[w]}
+ fi
+ [[ $g == "$e" ]] || err_exit "read -${o}${i} failed for '${c[w]}' -- expected '$e', got '$g'"
+ done
+ done
+ done
+ fi
+fi
+
+exec 3<&2
+file=$tmp/file
+redirect 5>$file 2>&5
+print -u5 -f 'This is a test\n'
+print -u2 OK
+exec 2<&3
+exp=$'This is a test\nOK'
+got=$(< $file)
+[[ $got == $exp ]] || err_exit "output garbled when stderr is duped -- expected $(printf %q "$exp"), got $(printf %q "$got")"
+print 'hello world' > $file
+1<>; $file 1># ((5))
+(( $(wc -c < $file) == 5 )) || err_exit "$file was not truncate to 5 bytes"
+
+$SHELL -c "PS4=':2:'
+ exec 1> $tmp/21.out 2> $tmp/22.out
+ set -x
+ printf ':1:A:'
+ print \$(:)
+ print :1:Z:" 1> $tmp/11.out 2> $tmp/12.out
+[[ -s $tmp/11.out ]] && err_exit "standard output leaked past redirection"
+[[ -s $tmp/12.out ]] && err_exit "standard error leaked past redirection"
+exp=$':1:A:\n:1:Z:'
+got=$(<$tmp/21.out)
+[[ $exp == "$got" ]] || err_exit "standard output garbled -- expected $(printf %q "$exp"), got $(printf %q "$got")"
+exp=$':2:printf :1:A:\n:2::\n:2:print\n:2:print :1:Z:'
+got=$(<$tmp/22.out)
+[[ $exp == "$got" ]] || err_exit "standard error garbled -- expected $(printf %q "$exp"), got $(printf %q "$got")"
+
+tmp=$tmp $SHELL 2> /dev/null -c 'exec 3<&1 ; exec 1<&- ; exec > $tmp/outfile;print foobar' || err_exit 'exec 1<&- causes failure'
+[[ $(<$tmp/outfile) == foobar ]] || err_exit 'outfile does not contain foobar'
+
+print hello there world > $tmp/foobar
+sed -e 's/there //' $tmp/foobar >; $tmp/foobar
+[[ $(<$tmp/foobar) == 'hello world' ]] || err_exit '>; redirection not working on simple command'
+print hello there world > $tmp/foobar
+{ sed -e 's/there //' $tmp/foobar;print done;} >; $tmp/foobar
+[[ $(<$tmp/foobar) == $'hello world\ndone' ]] || err_exit '>; redirection not working for compound command'
+print hello there world > $tmp/foobar
+$SHELL -c "sed -e 's/there //' $tmp/foobar >; $tmp/foobar"
+[[ $(<$tmp/foobar) == 'hello world' ]] || err_exit '>; redirection not working with -c on a simple command'
+
+rm -f "$tmp/junk"
+for (( i=1; i < 50; i++ ))
+do out=$(/bin/ls "$tmp/junk" 2>/dev/null)
+ if (( $? == 0 ))
+ then err_exit 'wrong error code with redirection'
+ break
+ fi
+done
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/leaks.sh b/src/cmd/ksh93/tests/leaks.sh
new file mode 100755
index 0000000..8d89b05
--- /dev/null
+++ b/src/cmd/ksh93/tests/leaks.sh
@@ -0,0 +1,68 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+builtin vmstate 2>/dev/null || exit 0
+
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+# test for variable reset leak #
+
+function test_reset
+{
+ integer i n=$1
+
+ for ((i = 0; i < n; i++))
+ do u=$i
+ done
+}
+
+n=1000
+
+# one round to get to steady state -- sensitive to -x
+
+test_reset $n
+a=0$(vmstate --format='+%(size)u')
+b=0$(vmstate --format='+%(size)u')
+
+test_reset $n
+a=0$(vmstate --format='+%(size)u')
+test_reset $n
+b=0$(vmstate --format='+%(size)u')
+
+if (( b > a ))
+then err_exit "variable value reset memory leak -- $((b-a)) bytes after $n iterations"
+fi
+
+# buffer boundary tests
+
+for exp in 65535 65536
+do got=$($SHELL -c 'x=$(printf "%.*c" '$exp' x); print ${#x}' 2>&1)
+ [[ $got == $exp ]] || err_exit "large command substitution failed -- expected $exp, got $got"
+done
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/locale.sh b/src/cmd/ksh93/tests/locale.sh
new file mode 100755
index 0000000..60209dc
--- /dev/null
+++ b/src/cmd/ksh93/tests/locale.sh
@@ -0,0 +1,319 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2012 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+unset LANG ${!LC_*}
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+cd $tmp || exit
+
+a=$($SHELL -c '/' 2>&1 | sed -e "s,.*: *,," -e "s, *\[.*,,")
+b=$($SHELL -c '(LC_ALL=debug / 2>/dev/null); /' 2>&1 | sed -e "s,.*: *,," -e "s, *\[.*,,")
+[[ "$b" == "$a" ]] || err_exit "locale not restored after subshell -- expected '$a', got '$b'"
+b=$($SHELL -c '(LC_ALL=debug; / 2>/dev/null); /' 2>&1 | sed -e "s,.*: *,," -e "s, *\[.*,,")
+[[ "$b" == "$a" ]] || err_exit "locale not restored after subshell -- expected '$a', got '$b'"
+
+# test shift-jis \x81\x40 ... \x81\x7E encodings
+# (shift char followed by 7 bit ascii)
+
+typeset -i16 chr
+for locale in $(PATH=/bin:/usr/bin locale -a 2>/dev/null | grep -i jis)
+do export LC_ALL=$locale
+ for ((chr=0x40; chr<=0x7E; chr++))
+ do c=${chr#16#}
+ for s in \\x81\\x$c \\x$c
+ do b="$(printf "$s")"
+ eval n=\$\'$s\'
+ [[ $b == "$n" ]] || err_exit "LC_ALL=$locale printf difference for \"$s\" -- expected '$n', got '$b'"
+ u=$(print -- $b)
+ q=$(print -- "$b")
+ [[ $u == "$q" ]] || err_exit "LC_ALL=$locale quoted print difference for \"$s\" -- $b => '$u' vs \"$b\" => '$q'"
+ done
+ done
+done
+
+# this locale is supported by ast on all platforms
+# EU for { decimal_point="," thousands_sep="." }
+
+locale=C_EU.UTF-8
+
+export LC_ALL=C
+
+# test multibyte value/trace format -- $'\303\274' is UTF-8 u-umlaut
+
+c=$(LC_ALL=C $SHELL -c "printf $':%2s:\n' $'\303\274'")
+u=$(LC_ALL=$locale $SHELL -c "printf $':%2s:\n' $'\303\274'" 2>/dev/null)
+if [[ "$c" != "$u" ]]
+then LC_ALL=$locale
+ x=$'+2+ typeset item.text\
++3+ item.text=\303\274\
++4+ print -- \303\274\
+\303\274\
++5+ eval $\'arr[0]=(\\n\\ttext=\\303\\274\\n)\'
++2+ arr[0].text=ü\
++6+ print -- \303\274\
+ü\
++7+ eval txt=$\'(\\n\\ttext=\\303\\274\\n)\'
++2+ txt.text=\303\274\
++8+ print -- \'(\' text=$\'\\303\\274\' \')\'\
+( text=\303\274 )'
+ u=$(LC_ALL=$locale PS4='+$LINENO+ ' $SHELL -x -c "
+ item=(typeset text)
+ item.text=$'\303\274'
+ print -- \"\${item.text}\"
+ eval \"arr[0]=\$item\"
+ print -- \"\${arr[0].text}\"
+ eval \"txt=\${arr[0]}\"
+ print -- \$txt
+ " 2>&1)
+ [[ "$u" == "$x" ]] || err_exit LC_ALL=$locale multibyte value/trace format failed
+
+ x=$'00fc\n20ac'
+ u=$(LC_ALL=$locale $SHELL -c $'printf "%04x\n" \$\'\"\303\274\"\' \$\'\"\xE2\x82\xAC\"\'')
+ [[ $u == $x ]] || err_exit LC_ALL=$locale multibyte %04x printf format failed
+fi
+
+if (( $($SHELL -c $'export LC_ALL='$locale$'; print -r "\342\202\254\342\202\254\342\202\254\342\202\254w\342\202\254\342\202\254\342\202\254\342\202\254" | wc -m' 2>/dev/null) == 10 ))
+then LC_ALL=$locale $SHELL -c b1=$'"\342\202\254\342\202\254\342\202\254\342\202\254w\342\202\254\342\202\254\342\202\254\342\202\254"; [[ ${b1:4:1} == w ]]' || err_exit 'multibyte ${var:offset:len} not working correctly'
+fi
+
+#$SHELL -c 'export LANG='$locale'; printf "\u[20ac]\u[20ac]" > $tmp/two_euro_chars.txt'
+printf $'\342\202\254\342\202\254' > $tmp/two_euro_chars.txt
+exp="6 2 6"
+set -- $($SHELL -c "
+ unset LC_CTYPE
+ export LANG=$locale
+ export LC_ALL=C
+ command wc -C < $tmp/two_euro_chars.txt
+ unset LC_ALL
+ command wc -C < $tmp/two_euro_chars.txt
+ export LC_ALL=C
+ command wc -C < $tmp/two_euro_chars.txt
+")
+got=$*
+[[ $got == $exp ]] || err_exit "command wc LC_ALL default failed -- expected '$exp', got '$got'"
+set -- $($SHELL -c "
+ if builtin wc 2>/dev/null || builtin -f cmd wc 2>/dev/null
+ then unset LC_CTYPE
+ export LANG=$locale
+ export LC_ALL=C
+ wc -C < $tmp/two_euro_chars.txt
+ unset LC_ALL
+ wc -C < $tmp/two_euro_chars.txt
+ export LC_ALL=C
+ wc -C < $tmp/two_euro_chars.txt
+ fi
+")
+got=$*
+[[ $got == $exp ]] || err_exit "builtin wc LC_ALL default failed -- expected '$exp', got '$got'"
+
+# multibyte char straddling buffer boundary
+
+{
+ unset i
+ integer i
+ for ((i = 0; i < 163; i++))
+ do print "#234567890123456789012345678901234567890123456789"
+ done
+ printf $'%-.*c\n' 15 '#'
+ for ((i = 0; i < 2; i++))
+ do print $': "\xe5\xae\x9f\xe8\xa1\x8c\xe6\xa9\x9f\xe8\x83\xbd\xe3\x82\x92\xe8\xa1\xa8\xe7\xa4\xba\xe3\x81\x97\xe3\x81\xbe\xe3\x81\x99\xe3\x80\x82" :'
+ done
+} > ko.dat
+
+LC_ALL=$locale $SHELL < ko.dat 2> /dev/null || err_exit "script with multibyte char straddling buffer boundary fails"
+
+# exp LC_ALL LC_NUMERIC LANG
+set -- \
+ 2,5 $locale C '' \
+ 2.5 C $locale '' \
+ 2,5 $locale '' C \
+ 2,5 '' $locale C \
+ 2.5 C '' $locale \
+ 2.5 '' C $locale \
+
+unset a b c
+unset LC_ALL LC_NUMERIC LANG
+integer a b c
+while (( $# >= 4 ))
+do exp=$1
+ unset H V
+ typeset -A H
+ typeset -a V
+ [[ $2 ]] && V[0]="export LC_ALL=$2;"
+ [[ $3 ]] && V[1]="export LC_NUMERIC=$3;"
+ [[ $4 ]] && V[2]="export LANG=$4;"
+ for ((a = 0; a < 3; a++))
+ do for ((b = 0; b < 3; b++))
+ do if (( b != a ))
+ then for ((c = 0; c < 3; c++))
+ do if (( c != a && c != b ))
+ then T=${V[$a]}${V[$b]}${V[$c]}
+ if [[ ! ${H[$T]} ]]
+ then H[$T]=1
+ got=$($SHELL -c "${T}print \$(( $exp ))" 2>&1)
+ [[ $got == $exp ]] || err_exit "${T} sequence failed -- expected '$exp', got '$got'"
+ fi
+ fi
+ done
+ fi
+ done
+ done
+ shift 4
+done
+
+# setocale(LC_ALL,"") after setlocale() initialization
+
+printf 'f1\357\274\240f2\n' > input1
+printf 't2\357\274\240f1\n' > input2
+printf '\357\274\240\n' > delim
+print "export LC_ALL=$locale
+join -j1 1 -j2 2 -o 1.1 -t \$(cat delim) input1 input2 > out" > script
+$SHELL -c 'unset LANG ${!LC_*}; $SHELL ./script' ||
+err_exit "join test script failed -- exit code $?"
+exp="f1"
+got="$(<out)"
+[[ $got == "$exp" ]] || err_exit "LC_ALL test script failed -- expected '$exp', got '$got'"
+
+# multibyte identifiers
+
+exp=OK
+got=$(LC_ALL=C.UTF-8 $SHELL -c $'\u[5929]=OK; print ${\u[5929]}' 2>&1)
+[[ $got == "$exp" ]] || err_exit "multibyte variable definition/expansion failed -- expected '$exp', got '$got'"
+got=$(LC_ALL=C.UTF-8 $SHELL -c $'function \u[5929]\n{\nprint OK;\n}; \u[5929]' 2>&1)
+[[ $got == "$exp" ]] || err_exit "multibyte ksh function definition/execution failed -- expected '$exp', got '$got'"
+got=$(LC_ALL=C.UTF-8 $SHELL -c $'\u[5929]()\n{\nprint OK;\n}; \u[5929]' 2>&1)
+[[ $got == "$exp" ]] || err_exit "multibyte posix function definition/execution failed -- expected '$exp', got '$got'"
+
+# this locale is supported by ast on all platforms
+# mainly used to debug multibyte and message translation code
+# however wctype is not supported but that's ok for these tests
+
+locale=debug
+
+if [[ "$(LC_ALL=$locale $SHELL <<- \+EOF+
+ x=a<1z>b<2yx>c
+ print ${#x}
+ +EOF+)" != 5
+ ]]
+then err_exit '${#x} not working with multibyte locales'
+fi
+
+dir=_not_found_
+exp=2
+for cmd in \
+ "cd $dir; export LC_ALL=debug; cd $dir" \
+ "cd $dir; LC_ALL=debug cd $dir" \
+
+do got=$($SHELL -c "$cmd" 2>&1 | sort -u | wc -l)
+ (( ${got:-0} == $exp )) || err_exit "'$cmd' sequence failed -- error message not localized"
+done
+exp=121
+for lc in LANG LC_MESSAGES LC_ALL
+do for cmd in "($lc=$locale;cd $dir)" "$lc=$locale;cd $dir;unset $lc" "function tst { typeset $lc=$locale;cd $dir; }; tst"
+ do tst="$lc=C;cd $dir;$cmd;cd $dir;:"
+ $SHELL -c "unset LANG \${!LC_*}; $SHELL -c '$tst'" > out 2>&1 ||
+ err_exit "'$tst' failed -- exit status $?"
+ integer id=0
+ unset msg
+ typeset -A msg
+ got=
+ while read -r line
+ do line=${line##*:}
+ if [[ ! ${msg[$line]} ]]
+ then msg[$line]=$((++id))
+ fi
+ got+=${msg[$line]}
+ done < out
+ [[ $got == $exp ]] || err_exit "'$tst' failed -- expected '$exp', got '$got'"
+ done
+done
+
+exp=123
+got=$(LC_ALL=debug $SHELL -c "a<2A@>z=$exp; print \$a<2A@>z")
+[[ $got == $exp ]] || err_exit "multibyte debug locale \$a<2A@>z failed -- expected '$exp', got '$got'"
+
+unset LC_ALL LC_MESSAGES
+export LANG=debug
+function message
+{
+ print -r $"An error occurred."
+}
+exp=$'(libshell,3,46)\nAn error occurred.\n(libshell,3,46)'
+alt=$'(debug,message,libshell,An error occurred.)\nAn error occurred.\n(debug,message,libshell,An error occurred.)'
+got=$(message; LANG=C message; message)
+[[ $got == "$exp" || $got == "$alt" ]] || {
+ EXP=$(printf %q "$exp")
+ ALT=$(printf %q "$alt")
+ GOT=$(printf %q "$got")
+ err_exit "LANG change not seen by function -- expected $EXP or $ALT, got $GOT"
+}
+
+a_thing=fish
+got=$(print -r aa$"\\ahello \" /\\${a_thing}/\\"zz)
+exp='aa(debug,'$Command',libshell,\ahello " /\fish/\)zz'
+[[ $got == "$exp" ]] || err_exit "$\"...\" containing expansions fails: expected $exp, got $got"
+
+exp='(debug,'$Command',libshell,This is a string\n)'
+typeset got=$"This is a string\n"
+[[ $got == "$exp" ]] || err_exit "$\"...\" in assignment expansion fails: expected $exp got $got"
+
+unset LANG
+
+LC_ALL=C
+x=$"hello"
+[[ $x == hello ]] || err_exit 'assignment of message strings not working'
+
+# tests for multibyte characteer at buffer boundary
+{
+ print 'cat << \\EOF'
+ for ((i=1; i < 164; i++))
+ do print 123456789+123456789+123456789+123456789+123456789
+ done
+ print $'next character is multibyte<2b|>c<3d|\>foo'
+ for ((i=1; i < 10; i++))
+ do print 123456789+123456789+123456789+123456789+123456789
+ done
+ print EOF
+} > script$$.1
+chmod +x script$$.1
+x=$( LC_ALL=debug $SHELL ./script$$.1)
+[[ ${#x} == 8641 ]] || err_exit 'here doc contains wrong number of chars with multibyte locale'
+[[ $x == *$'next character is multibyte<2b|>c<3d|\>foo'* ]] || err_exit "here_doc doesn't contain line with multibyte chars"
+
+
+x=$(LC_ALL=debug $SHELL -c 'x="a<2b|>c";print -r -- ${#x}')
+(( x == 3 )) || err_exit 'character length of multibyte character should be 3'
+x=$(LC_ALL=debug $SHELL -c 'typeset -R10 x="a<2b|>c";print -r -- "${x}"')
+[[ $x == ' a<2b|>c' ]] || err_exit 'typeset -R10 should begin with three spaces'
+x=$(LC_ALL=debug $SHELL -c 'typeset -L10 x="a<2b|>c";print -r -- "${x}"')
+[[ $x == 'a<2b|>c ' ]] || err_exit 'typeset -L10 should end in three spaces'
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/math.sh b/src/cmd/ksh93/tests/math.sh
new file mode 100644
index 0000000..59884f5
--- /dev/null
+++ b/src/cmd/ksh93/tests/math.sh
@@ -0,0 +1,202 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ (( Errors < 127 && Errors++ ))
+}
+alias err_exit='err_exit $LINENO'
+
+set -o nounset
+Command=${0##*/}
+integer Errors=0
+
+set -o nounset
+
+typeset tmp
+
+# create temporary test directory
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+cd $tmp || exit
+
+function test_arithmetric_expression_accesss_array_element_through_nameref
+{
+ compound out=( typeset stdout stderr ; integer res )
+ compound -r -a tests=(
+ (
+ cmd='@@TYPE@@ -a @@VAR@@ ; @@VAR@@[1]=90 ; function x { nameref nz=$1 ; print " $(( round(nz) ))==$(( round($nz) ))" ; } ; x @@VAR@@[1]' ; stdoutpattern=' 90==90'
+ )
+ (
+ cmd='@@TYPE@@ -a @@VAR@@=( [1]=90 ) ; function x { nameref nz=$1 ; print " $(( round(nz) ))==$(( round($nz) ))" ; } ; x @@VAR@@[1]' ; stdoutpattern=' 90==90'
+ )
+ (
+ cmd='@@TYPE@@ -a @@VAR@@ ; @@VAR@@[1][3]=90 ; function x { nameref nz=$1 ; print " $(( round(nz) ))==$(( round($nz) ))" ; } ; x @@VAR@@[1][3]' ; stdoutpattern=' 90==90'
+ )
+ (
+ cmd='@@TYPE@@ -a @@VAR@@=( [1][3]=90 ) ; function x { nameref nz=$1 ; print " $(( round(nz) ))==$(( round($nz) ))" ; } ; x @@VAR@@[1][3]' ; stdoutpattern=' 90==90'
+ )
+ (
+ cmd='@@TYPE@@ -a @@VAR@@ ; @@VAR@@[1][3][5]=90 ; function x { nameref nz=$1 ; print " $(( round(nz) ))==$(( round($nz) ))" ; } ; x @@VAR@@[1][3][5]' ; stdoutpattern=' 90==90'
+ )
+ (
+ cmd='@@TYPE@@ -a @@VAR@@=( [1][3][5]=90 ) ; function x { nameref nz=$1 ; print " $(( round(nz) ))==$(( round($nz) ))" ; } ; x @@VAR@@[1][3][5]' ; stdoutpattern=' 90==90'
+ )
+ (
+ cmd='@@TYPE@@ -a @@VAR@@ ; @@VAR@@[1][3][5]=90 ; function x { nameref nz=${1}[$2][$3][$4] ; print " $(( round(nz) ))==$(( round($nz) ))" ; } ; x @@VAR@@ 1 3 5' ; stdoutpattern=' 90==90'
+ )
+ (
+ cmd='@@TYPE@@ -A @@VAR@@ ; @@VAR@@[1]=90 ; function x { nameref nz=$1 ; print " $(( round(nz) ))==$(( round($nz) ))" ; } ; x @@VAR@@[1]' ; stdoutpattern=' 90==90'
+ )
+ (
+ cmd='@@TYPE@@ -A @@VAR@@=( [1]=90 ) ; function x { nameref nz=$1 ; print " $(( round(nz) ))==$(( round($nz) ))" ; } ; x @@VAR@@[1]' ; stdoutpattern=' 90==90'
+ )
+ )
+
+ typeset testname
+ integer i
+ typeset mode
+ typeset cmd
+
+ for (( i=0 ; i < ${#tests[@]} ; i++ )) ; do
+ # fixme: This list should include "typeset -lX" and "typeset -X" but ast-ksh.2010-03-09 fails like this:
+ # 'typeset -X -a z ; z[1][3]=90 ; function x { nameref nz=$1 ; print " $(( nz ))==$(( $nz ))" ; } ; x z[1][3]'
+ # + typeset -X -a z
+ # + z[1][3]=90
+ # + x 'z[1][3]'
+ # /home/test001/bin/ksh[1]: x: line 1: x1.68000000000000000000000000000000p: no parent
+ for ty in \
+ 'typeset' \
+ 'integer' \
+ 'float' \
+ 'typeset -i' \
+ 'typeset -si' \
+ 'typeset -li' \
+ 'typeset -E' \
+ 'typeset -F' \
+ 'typeset -X' \
+ 'typeset -lE' \
+ 'typeset -lX' \
+ 'typeset -lF' ; do
+ for mode in \
+ 'plain' \
+ 'in_compound' \
+ 'in_indexed_compound_array' \
+ 'in_2d_indexed_compound_array' \
+ 'in_4d_indexed_compound_array' \
+ 'in_associative_compound_array' \
+ 'in_compound_nameref' \
+ 'in_indexed_compound_array_nameref' \
+ 'in_2d_indexed_compound_array_nameref' \
+ 'in_4d_indexed_compound_array_nameref' \
+ 'in_associative_compound_array_nameref' \
+ ; do
+ nameref tst=tests[i]
+
+ cmd="${tst.cmd//@@TYPE@@/${ty}}"
+
+ case "${mode}" in
+ 'plain')
+ cmd="${cmd//@@VAR@@/z}"
+ ;;
+
+ 'in_compound')
+ cmd="compound c ; ${cmd//@@VAR@@/c.z}"
+ ;;
+ 'in_indexed_compound_array')
+ cmd="compound -a c ; ${cmd//@@VAR@@/c[11].z}"
+ ;;
+ 'in_2d_indexed_compound_array')
+ cmd="compound -a c ; ${cmd//@@VAR@@/c[17][19].z}"
+ ;;
+ 'in_4d_indexed_compound_array')
+ cmd="compound -a c ; ${cmd//@@VAR@@/c[17][19][23][27].z}"
+ ;;
+ 'in_associative_compound_array')
+ cmd="compound -A c ; ${cmd//@@VAR@@/c[info].z}"
+ ;;
+
+ 'in_compound_nameref')
+ cmd="compound c ; nameref ncr=c.z ; ${cmd//@@VAR@@/ncr}"
+ ;;
+ 'in_indexed_compound_array_nameref')
+ cmd="compound -a c ; nameref ncr=c[11].z ; ${cmd//@@VAR@@/ncr}"
+ ;;
+ 'in_2d_indexed_compound_array_nameref')
+ cmd="compound -a c ; nameref ncr=c[17][19].z ; ${cmd//@@VAR@@/ncr}"
+ ;;
+ 'in_4d_indexed_compound_array_nameref')
+ cmd="compound -a c ; nameref ncr=c[17][19][23][27].z ; ${cmd//@@VAR@@/ncr}"
+ ;;
+ 'in_associative_compound_array_nameref')
+ cmd="compound -A c ; nameref ncr=c[info].z ; ${cmd//@@VAR@@/ncr}"
+ ;;
+ *)
+ err_exit "Unexpected mode ${mode}"
+ ;;
+ esac
+
+ testname="${0}/${cmd}"
+#set -x
+ out.stderr="${ { out.stdout="${ ${SHELL} -o nounset -o errexit -c "${cmd}" ; (( out.res=$? )) ; }" ; } 2>&1 ; }"
+#set +x
+
+ [[ "${out.stdout}" == ${tst.stdoutpattern} ]] || err_exit "${testname}: Expected stdout to match $(printf '%q\n' "${tst.stdoutpattern}"), got $(printf '%q\n' "${out.stdout}")"
+ [[ "${out.stderr}" == '' ]] || err_exit "${testname}: Expected empty stderr, got $(printf '%q\n' "${out.stderr}")"
+ (( out.res == 0 )) || err_exit "${testname}: Unexpected exit code ${out.res}"
+ done
+ done
+ done
+
+ return 0
+}
+
+function test_has_iszero
+{
+ typeset str
+ integer i
+
+ typeset -r -a tests=(
+ '(( iszero(0) )) && print "OK"'
+ '(( iszero(0.) )) && print "OK"'
+ '(( iszero(-0) )) && print "OK"'
+ '(( iszero(-0.) )) && print "OK"'
+ 'float n=0. ; (( iszero(n) )) && print "OK"'
+ 'float n=+0. ; (( iszero(n) )) && print "OK"'
+ 'float n=-0. ; (( iszero(n) )) && print "OK"'
+ 'float n=1. ; (( iszero(n) )) || print "OK"'
+ 'float n=1. ; (( iszero(n-1.) )) && print "OK"'
+ 'float n=-1. ; (( iszero(n+1.) )) && print "OK"'
+ )
+
+ for (( i=0 ; i < ${#tests[@]} ; i++ )) ; do
+ str="$( ${SHELL} -o errexit -c "${tests[i]}" 2>&1 )" || err_exit "test $i: returned non-zero exit code $?"
+ [[ "${str}" == 'OK' ]] || err_exit "test $i: expected 'OK', got '${str}'"
+ done
+
+ return 0
+}
+
+# run tests
+test_arithmetric_expression_accesss_array_element_through_nameref
+test_has_iszero
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/nameref.sh b/src/cmd/ksh93/tests/nameref.sh
new file mode 100755
index 0000000..7eb0b21
--- /dev/null
+++ b/src/cmd/ksh93/tests/nameref.sh
@@ -0,0 +1,658 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+function checkref
+{
+ nameref foo=$1 bar=$2
+ if [[ $foo != $bar ]]
+ then err_exit "foo=$foo != bar=$bar"
+ fi
+ foo=hello
+ if [[ $foo != $bar ]]
+ then err_exit "foo=$foo != bar=$bar"
+ fi
+ foo.child=child
+ if [[ ${foo.child} != ${bar.child} ]]
+ then err_exit "foo.child=${foo.child} != bar=${bar.child}"
+ fi
+}
+
+name=first
+checkref name name
+name.child=second
+checkref name name
+.foo=top
+.foo.bar=next
+checkref .foo.bar .foo.bar
+if [[ ${.foo.bar} != hello ]]
+then err_exit ".foo.bar=${.foo.bar} != hello"
+fi
+if [[ ${.foo.bar.child} != child ]]
+then err_exit ".foo.bar.child=${.foo.bar.child} != child"
+fi
+function func1
+{
+ nameref color=$1
+ func2 color
+}
+
+function func2
+{
+ nameref color=$1
+ set -s -- ${!color[@]}
+ print -r -- "$@"
+}
+
+typeset -A color
+color[apple]=red
+color[grape]=purple
+color[banana]=yellow
+if [[ $(func1 color) != 'apple banana grape' ]]
+then err_exit "nameref or nameref not working"
+fi
+nameref x=.foo.bar
+if [[ ${!x} != .foo.bar ]]
+then err_exit "${!x} not working"
+fi
+typeset +n x $(typeset +n)
+unset x
+nameref x=.foo.bar
+function x.set
+{
+ [[ ${.sh.value} ]] && print hello
+}
+if [[ $(.foo.bar.set) != $(x.set) ]]
+then err_exit "function references not working"
+fi
+if [[ $(typeset +n) != x ]]
+then err_exit "typeset +n doesn't list names of reference variables"
+fi
+if [[ $(typeset -n) != x=.foo.bar ]]
+then err_exit "typeset +n doesn't list values of reference variables"
+fi
+file=$tmp/test
+typeset +n foo bar 2> /dev/null
+unset foo bar
+export bar=foo
+nameref foo=bar
+if [[ $foo != foo ]]
+then err_exit "value of nameref foo != $foo"
+fi
+cat > $file <<\!
+print -r -- $foo
+!
+chmod +x "$file"
+y=$( $file)
+if [[ $y != '' ]]
+then err_exit "reference variable not cleared"
+fi
+{
+ command nameref xx=yy
+ command nameref yy=xx
+} 2> /dev/null && err_exit "self reference not detected"
+typeset +n foo bar
+unset foo bar
+set foo
+nameref bar=$1
+foo=hello
+if [[ $bar != hello ]]
+then err_exit 'nameref of positional paramters outside of function not working'
+fi
+unset foo bar
+bar=123
+function foobar
+{
+ typeset -n foo=bar
+ typeset -n foo=bar
+}
+foobar 2> /dev/null || err_exit 'nameref not unsetting previous reference'
+(
+ nameref short=verylong
+ short=( A=a B=b )
+ if [[ ${verylong.A} != a ]]
+ then err_exit 'nameref short to longname compound assignment error'
+ fi
+) 2> /dev/null|| err_exit 'nameref short to longname compound assignment error'
+unset x
+if [[ $(var1=1 var2=2
+ for i in var1 var2
+ do nameref x=$i
+ print $x
+ done) != $'1\n2' ]]
+then err_exit 'for loop nameref optimization error'
+fi
+if [[ $(typeset -A var1 var2
+ var1[sub1]=1 var2[sub2]=1
+ for i in var1 var2
+ do
+ typeset -n array=$i
+ print ${!array[*]}
+ done) != $'sub1\nsub2' ]]
+then err_exit 'for loop nameref optimization test2 error'
+fi
+
+unset -n x foo bar
+if [[ $(nameref x=foo;for x in foo bar;do print ${!x};done) != $'foo\nbar' ]]
+then err_exit 'for loop optimization with namerefs not working'
+fi
+if [[ $(
+ p=(x=(r=3) y=(r=4))
+ for i in x y
+ do nameref x=p.$i
+ print ${x.r}
+ done
+) != $'3\n4' ]]
+then err_exit 'nameref optimization error'
+fi
+[[ $(
+unset x y var
+var=(foo=bar)
+for i in y var
+do typeset -n x=$i
+ if [[ ${!x.@} ]]
+ then print ok
+ fi
+ typeset +n x
+done) != ok ]] && err_exit 'invalid for loop optimization of name references'
+function setval # name value
+{
+ nameref arg=$1
+ nameref var=arg.bar
+ var=$2
+}
+foo=( integer bar=0)
+setval foo 5
+(( foo.bar == 5)) || err_exit 'nested nameref not working'
+function selfref
+{
+ typeset -n ps=$1
+ print -r -- "${ps}"
+}
+ps=(a=1 b=2)
+[[ $(selfref ps) == *a=1* ]] || err_exit 'local nameref cannot reference global variable of the same name'
+function subref
+{
+ typeset -n foo=$1
+ print -r -- ${foo.a}
+}
+[[ $(subref ps) == 1 ]] || err_exit 'local nameref cannot reference global variable child'
+
+function local
+{
+ typeset ps=(typeset -i a=3 b=4)
+ [[ $(subref ps) == 3 ]] || err_exit 'local nameref cannot reference caller compound variable'
+}
+local
+unset -f local
+function local
+{
+ qs=(integer a=3; integer b=4)
+}
+local 2> /dev/null || err_exit 'function local has non-zero exit status'
+[[ ${qs.a} == 3 ]] || err_exit 'function cannot set compound global variable'
+unset fun i
+foo=(x=hi)
+function fun
+{
+ nameref i=$1
+ print -r -- "${i.x}"
+}
+i=foo
+[[ $(fun $i) == hi ]] || err_exit 'nameref for compound variable with in function name of caller fails'
+unset -n foo bar
+typeset -A foo
+foo[x.y]=(x=3 y=4)
+nameref bar=foo[x.y]
+[[ ${bar.x} == 3 ]] || err_exit 'nameref to subscript containing . fails'
+[[ ${!bar} == 'foo[x.y]' ]] || err_exit '${!var} not correct for nameref to an array instance'
+typeset +n bar
+nameref bar=foo
+[[ ${!bar} == foo ]] || err_exit '${!var} not correct for nameref to array variable'
+$SHELL -c 'function bar { nameref x=foo[++];};typeset -A foo;bar' 2> /dev/null ||err_exit 'nameref of associative array tries to evaluate subscript'
+i=$($SHELL -c 'nameref foo=bar; bar[2]=(x=3 y=4); nameref x=foo[2].y;print -r -- $x' 2> /dev/null)
+[[ $i == 4 ]] || err_exit 'creating reference from subscripted variable whose name is a reference failed'
+[[ $($SHELL 2> /dev/null <<- '+++EOF'
+ function bar
+ {
+ nameref x=$1
+ print -r -- "$x"
+ }
+ function foo
+ {
+ typeset var=( foo=hello)
+ bar var
+ }
+ foo
++++EOF
+) == *foo=hello* ]] || err_exit 'unable to display compound variable from name reference of local variable'
+#set -x
+for c in '=' '[' ']' '\' "'" '"' '<' '=' '('
+do [[ $($SHELL 2> /dev/null <<- ++EOF++
+ i=\\$c;typeset -A a; a[\$i]=foo;typeset -n x=a[\$i]; print "\$x"
+ ++EOF++
+) != foo ]] && err_exit 'nameref x=a[$c] '"not working for c=$c"
+done
+for c in '=' '[' ']' '\' "'" '"' '<' '=' '('
+do [[ $($SHELL 2> /dev/null <<- ++EOF++
+ i=\\$c;typeset -A a; a[\$i]=foo;b=a[\$i];typeset -n x=\$b; print "\$x"
+ ++EOF++
+) != foo ]] && err_exit 'nameref x=$b with b=a[$c] '"not working for c=$c"
+done
+
+unset -n foo x
+unset foo x
+typeset -A foo
+nameref x=foo[xyz]
+foo[xyz]=ok
+[[ $x == ok ]] || err_exit 'nameref to unset subscript not working'
+function function2
+{
+ nameref v=$1
+ v.x=19 v.y=20
+}
+function function1
+{
+ typeset compound_var=()
+ function2 compound_var
+ printf "x=%d, y=%d\n" compound_var.x compound_var.y
+}
+x="$(function1)"
+[[ "$x" != 'x=19, y=20' ]] && err_exit "expected 'x=19, y=20', got '${x}'"
+typeset +n bar
+unset foo bar
+[[ $(function a
+{
+ for i in foo bar
+ do typeset -n v=$i
+ print $v
+ done | cat
+}
+foo=1 bar=2;a) == $'1\n2' ]] 2> /dev/null || err_exit 'nameref in pipeline broken'
+function a
+{
+ typeset -n v=vars.data._1
+ print "${v.a} ${v.b}"
+}
+vars=(data=())
+vars.data._1.a=a.1
+vars.data._1.b=b.1
+[[ $(a) == 'a.1 b.1' ]] || err_exit 'nameref choosing wrong scope -- '
+typeset +n bam zip foo
+unset bam zip foo
+typeset -A foo
+foo[2]=bar
+typeset -n bam=foo[2]
+typeset -n zip=bam
+[[ $zip == bar ]] || err_exit 'nameref to another nameref to array element fails'
+[[ -R zip ]] || err_exit '[[ -R zip ]] should detect that zip is a reference'
+[[ -R bam ]] || err_exit '[[ -R bam ]] should detect that bam is a reference'
+[[ -R zip ]] || err_exit '[[ -v zip ]] should detect that zip is set'
+[[ -v bam ]] || err_exit '[[ -v bam ]] should detect that bam is set'
+[[ -R 123 ]] && err_exit '[[ -R 123 ]] should detect that 123 is not a reference'
+[[ -v 123 ]] && err_exit '[[ -v 123 ]] should detect that 123 is not set'
+
+unset ref x
+typeset -n ref
+x=3
+function foobar
+{
+ typeset xxx=3
+ ref=xxx
+ return 0
+}
+foobar 2> /dev/null && err_exit 'invalid reference should cause foobar to fail'
+[[ -v ref ]] && err_exit '$ref should be unset'
+ref=x
+[[ $ref == 3 ]] || err_exit "\$ref is $ref, it should be 3"
+function foobar
+{
+ typeset fvar=()
+ typeset -n ref=fvar.foo
+ ref=ok
+ print -r $ref
+}
+[[ $(foobar) == ok ]] 2> /dev/null || err_exit 'nameref in function not creating variable in proper scope'
+function foobar
+{
+ nameref doc=docs
+ nameref bar=doc.num
+ [[ $bar == 2 ]] || err_exit 'nameref scoping error'
+}
+
+docs=(num=2)
+foobar
+
+typeset +n x y
+unset x y
+typeset -A x
+x[a]=(b=c)
+typeset -n y=x[a]
+[[ ${!y.@} == 'x[a].b' ]] || err_exit 'reference to array element not expanded with ${!y.@}'
+
+typeset +n v
+v=()
+k=a.b.c/d
+command typeset -n n=v.${k//['./']/_} 2> /dev/null || err_exit 'patterns with quotes not handled correctly with name reference assignment'
+
+typeset _n sp
+nameref sp=addrsp
+sp[14]=( size=1 )
+[[ -v sp[19] ]] && err_exit '[[ -v sp[19] ]] where sp is a nameref should not be set'
+
+function fun2
+{
+ nameref var=$1
+ var.foo=bar
+}
+
+function fun1
+{
+ compound -S container
+ fun2 container
+ [[ $container == *foo=bar* ]] || err_exit 'name references to static compound variables in parent scope not working'
+}
+fun1
+
+function fun2
+{
+ nameref var=$1
+ var.foo=bar
+}
+
+typeset -T container_t=(
+ typeset foo
+)
+
+function fun1
+{
+ container_t -S container
+ fun2 container
+ [[ $container == *foo=bar* ]] || err_exit 'name references to static type variables in parent scope not working'
+}
+fun1
+
+function fun2
+{
+ nameref var=$1
+ nameref node=var.foo
+ node=bar
+}
+function fun3
+{
+ fun2 container #2> /dev/null
+}
+compound container
+fun3
+[[ $container == *foo=bar* ]] || err_exit 'name reference to a name reference variable in a function not working'
+
+typeset -A x=( [a]=1 )
+nameref c=x[h]
+[[ -v x[h] ]] && err_exit 'creating reference to non-existant associative array element causes element to get added'
+
+unset a
+function x
+{
+ nameref a=a
+ (( $# > 0 )) && typeset -A a
+ a[a b]=${1-99} # this was cauing a syntax on the second call
+}
+x 7
+x 2> /dev/null
+[[ ${a[a b]} == 99 ]] || err_exit 'nameref not handling subscript correctly'
+
+nameref sizes=baz
+typeset -A -i sizes
+sizes[bar]=1
+[[ ${sizes[*]} == 1 ]] || err_exit 'adding -Ai attribute to name referenced variable not working'
+
+$SHELL 2> /dev/null -c 'nameref foo=bar; typeset -A foo; (( (x=foo[a])==0 ))' || err_exit 'references inside arithmetic expressions not working'
+:
+
+unset ar z
+integer -a ar
+nameref z=ar[0]
+(( z[2]=3))
+[[ ${ar[0][2]} == 3 ]] || err_exit "\${ar[0][2]} is '${ar[0][2]}' but should be 3"
+(( ar[0][2] == 3 )) || err_exit "ar[0][2] is '${ar[0][2]}' but should be 3"
+
+unset c x
+typeset +n c x
+compound c=( typeset -a x )
+nameref x=c.x
+x[4]=1
+[[ ${ typeset -p c.x ;} == *-C* ]] && err_exit 'c.x should not have -C attributes'
+
+{ $SHELL 2> /dev/null <<- \EOF
+ typeset -T xxx_t=(
+ float x=1 y=2
+ typeset name=abc
+ )
+ xxx_t x
+ nameref r=x.y
+ [[ $r == 2 ]] || exit 1
+ unset x
+ [[ ${!r} == .deleted ]] || exit 2
+EOF
+} 2> /dev/null #|| print -u2 bad
+exitval=$?
+if [[ $(kill -l $exitval) == SEGV ]]
+then print -u2 'name reference to unset type instance causes segmentation violation'
+else if((exitval))
+ then print -u2 'name reference to unset type instance not redirected to .deleted'
+ fi
+fi
+
+typeset +n nr
+unset c nr
+compound c
+compound -A c.a
+nameref nr=c.a[hello]
+[[ ${!nr} == "c.a[hello]" ]] || err_exit 'name reference nr to unset associative array instance does not expand ${!nr} correctly.'
+
+typeset +n nr
+compound -a c.b
+nameref nr=c.b[2]
+[[ ${!nr} == "c.b[2]" ]] || err_exit 'name reference nr to unset indexed array instance does not expand ${!nr} correctly.'
+
+typeset +n a b
+unset a b
+typeset -n a=ls[0] b=ls[1]
+read line << \!
+3 4
+!
+set -A ls -- $line
+[[ $a == 3 ]] || err_exit 'name reference to ls[0] when ls is not an array fails'
+
+$SHELL 2> /dev/null <<-\EOF || err_exit 'nameref to array element fails'
+ set -o errexit
+ function bf {
+ nameref treename=$1
+ nodepath="treename" ;
+ nameref x="$nodepath"
+ compound -A x.nodes
+ nameref node=treename.nodes[4]
+ node=()
+ typeset +p node.elements
+ }
+ compound c
+ bf c
+EOF
+
+function add_compound
+{
+ nameref arr=$1
+ arr[34]+=( float val=1.1 )
+}
+compound -a rootcpv
+nameref mycpv=rootcpv[4][8][16][32][64]
+compound -a mycpv.myindexedcompoundarray
+add_compound mycpv.myindexedcompoundarray
+(( mycpv.myindexedcompoundarray[34].val == 1.1 )) || err_exit 'nameref scoping error'
+
+function add_file_to_tree
+{
+ nameref node=$1
+ compound -A node.elements
+ node.elements[/]=(filepath=foobar)
+}
+function main
+{
+ compound filetree
+ add_file_to_tree filetree
+}
+main 2> /dev/null
+[[ $? == 0 ]] || err_exit 'nameref binding to calling function compound variable failed'
+
+unset l
+typeset -a -C l
+printf "( typeset -a ar=( 1\n2\n3\n) b=1 )\n" | read -C l[4][6]
+exp=$(print -v l)
+unset l
+typeset -a -C l
+nameref l4=l[4]
+printf "( typeset -a ar=( 1\n2\n3\n) b=1 )\n" | read -C l4[6]
+[[ $(print -v l) == "$exp" ]] || err_exit 'nameref l4=l[4] not working'
+unset l
+typeset -a -C l
+nameref l46=l[4][6]
+printf "( typeset -a ar=( 1\n2\n3\n) b=1 )\n" | read -C l46
+[[ $(print -v l) == "$exp" ]] || err_exit 'nameref l46=l[4][6] not working'
+
+exp=$'(\n\t[4]=(\n\t\ttypeset -a ar=(\n\t\t\t1\n\t\t\t2\n\t\t)\n\t\tb=1\n\t)\n)'
+unset l
+typeset +n l4
+typeset -a -C l
+nameref l4=l[4]
+printf "( typeset -a ar=( 1\n2\n) b=1 )\n" | read -C l4
+[[ $(print -v l) == "$exp" ]] || err_exit 'nameref l4=l[4] not working with indexed array read'
+
+unset l
+typeset +n l4
+typeset -A -C l
+nameref l4=l[4]
+printf "( typeset -a ar=( 1\n2\n) b=1 )\n" | read -C l4
+[[ $(print -v l) == "$exp" ]] || err_exit 'nameref l4=l[4] not working with associative array read'
+
+exp=$'(\n\t[9]=(\n\t\tfish=4\n\t)\n)'
+function add_eval
+{
+ nameref pos=$1
+ source /dev/stdin <<<"$2"
+ typeset -m pos=addvar
+}
+function do_local_plain
+{
+ compound -A local_tree
+ add_eval local_tree[9].fish "typeset -i addvar=4"
+ [[ $(print -v local_tree) == "$exp" ]] || err_exit 'do_local_plain failed'
+}
+function do_global_throughnameref
+{
+ nameref tr=global_tree
+ add_eval tr[9].fish "typeset -i addvar=4"
+ [[ $(print -v tr) == "$exp" ]] || err_exit 'do_global_throughnameref failed'
+}
+function do_local_throughnameref
+{
+ compound -A local_tree
+ nameref tr=local_tree
+ add_eval tr[9].fish "typeset -i addvar=4"
+ [[ $(print -v tr) == "$exp" ]] || err_exit 'do_local_throughnameref failed'
+}
+compound -A global_tree
+do_global_throughnameref
+do_local_throughnameref
+do_local_plain
+
+unset ar
+compound -a ar
+function read_c
+{
+ nameref v=$1
+ read -C v
+}
+print "( typeset -i x=36 ) " | read_c ar[5][9][2]
+exp=$'(\n\t[5]=(\n\t\t[9]=(\n\t\t\t[2]=(\n\t\t\t\ttypeset -i x=36\n\t\t\t)\n\t\t)\n\t)\n)'
+[[ $(print -v ar) == "$exp" ]] || err_exit 'read into nameref of global array instance from within a function fails'
+
+function read_c
+{
+ nameref v=$1
+ read -C v
+}
+function main
+{
+ compound -a ar
+ nameref nar=ar
+ print "( typeset -i x=36 ) " | read_c nar[5][9][2]
+ exp=$'(\n\t[5]=(\n\t\t[9]=(\n\t\t\t[2]=(\n\t\t\t\ttypeset -i x=36\n\t\t\t)\n\t\t)\n\t)\n)'
+ [[ $(print -v nar) == "$exp" ]] || err_exit 'read from a nameref variable from calling scope fails'
+}
+main
+
+function rf2
+{
+ nameref val=$1
+ read -C val
+}
+function rf
+{
+ nameref val=$1
+ rf2 val
+}
+function main
+{
+ compound c
+ typeset -A -C c.l
+ nameref l4=c.l[4]
+ printf "( typeset -a ar=( 1\n2\n3\n) b=1 )\n" | rf l4
+ exp=$'(\n\ttypeset -C -A l=(\n\t\t[4]=(\n\t\t\ttypeset -a ar=(\n\t\t\t\t1\n\t\t\t\t2\n\t\t\t\t3\n\t\t\t)\n\t\t\tb=1\n\t\t)\n\t)\n)'
+ [[ $(print -v c) == "$exp" ]] || err_exit 'read -C with nameref to array element fails'
+}
+main
+
+# bug reported by ek
+cfg=( alarms=(type=3))
+function a
+{
+ typeset -n y=$1
+ print -- ${y.type}
+}
+function b
+{
+ a $1
+}
+[[ $(a cfg.alarms) == 3 ]] || err_exit "nameref scoping error in function"
+[[ $(b cfg.alarms) == 3 ]] || err_exit "nameref scoping error in nested function"
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/options.sh b/src/cmd/ksh93/tests/options.sh
new file mode 100755
index 0000000..c5b4c2e
--- /dev/null
+++ b/src/cmd/ksh93/tests/options.sh
@@ -0,0 +1,544 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2012 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+unset HISTFILE
+export LC_ALL=C ENV=
+
+ulimit -c 0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+if [[ $( ${SHELL-ksh} -s hello<<-\!
+ print $1
+ !
+ ) != hello ]]
+then err_exit "${SHELL-ksh} -s not working"
+fi
+x=$(
+ set -e
+ false && print bad
+ print good
+)
+if [[ $x != good ]]
+then err_exit 'sh -e not working'
+fi
+[[ $($SHELL -D -c 'print hi; print $"hello"') == '"hello"' ]] || err_exit 'ksh -D not working'
+
+env=$tmp/.env
+print $'(print -u1 aha) &>/dev/null\n(print -u2 aha) &>/dev/null' > $env
+rc=$tmp/.kshrc
+print $'PS1=""\nfunction env_hit\n{\n\tprint OK\n}' > $rc
+
+export ENV=/.$env
+if [[ ! -o privileged ]]
+then
+ got=$($SHELL -E -c : 2>/dev/null)
+ if [[ $g ]]
+ then
+ got=$(printf %q "$got")
+ err_exit "\$ENV file &>/dev/null does not redirect stdout -- expected '', got $got"
+ fi
+ got=$($SHELL -E -c : 2>&1 >/dev/null)
+ if [[ $got != *nonstandard* || $got == *$'\n'* ]]
+ then
+ got=$(printf %q "$got")
+ err_exit "\$ENV file &>/dev/null does not redirect stderr -- expected one diagnostic line, got $got"
+ fi
+fi
+
+export ENV=/.$rc
+if [[ -o privileged ]]
+then
+ [[ $(print env_hit | $SHELL 2>&1) == "OK" ]] &&
+ err_exit 'privileged nointeractive shell reads $ENV file'
+ [[ $(print env_hit | $SHELL -E 2>&1) == "OK" ]] &&
+ err_exit 'privileged -E reads $ENV file'
+ [[ $(print env_hit | $SHELL +E 2>&1) == "OK" ]] &&
+ err_exit 'privileged +E reads $ENV file'
+ [[ $(print env_hit | $SHELL --rc 2>&1) == "OK" ]] &&
+ err_exit 'privileged --rc reads $ENV file'
+ [[ $(print env_hit | $SHELL --norc 2>&1) == "OK" ]] &&
+ err_exit 'privileged --norc reads $ENV file'
+else
+ [[ $(print env_hit | $SHELL 2>&1) == "OK" ]] &&
+ err_exit 'nointeractive shell reads $ENV file'
+ [[ $(print env_hit | $SHELL -E 2>&1) == "OK" ]] ||
+ err_exit '-E ignores $ENV file'
+ [[ $(print env_hit | $SHELL +E 2>&1) == "OK" ]] &&
+ err_exit '+E reads $ENV file'
+ [[ $(print env_hit | $SHELL --rc 2>&1) == "OK" ]] ||
+ err_exit '--rc ignores $ENV file'
+ [[ $(print env_hit | $SHELL --norc 2>&1) == "OK" ]] &&
+ err_exit '--norc reads $ENV file'
+ [[ $(print env_hit | $SHELL -i 2>&1) == "OK" ]] ||
+ err_exit '-i ignores $ENV file'
+fi
+
+export ENV=
+if [[ -o privileged ]]
+then
+ [[ $(print env_hit | HOME=$tmp $SHELL 2>&1) == "OK" ]] &&
+ err_exit 'privileged nointeractive shell reads $HOME/.kshrc file'
+ [[ $(print env_hit | HOME=$tmp $SHELL -E 2>&1) == "OK" ]] &&
+ err_exit 'privileged -E ignores empty $ENV'
+ [[ $(print env_hit | HOME=$tmp $SHELL +E 2>&1) == "OK" ]] &&
+ err_exit 'privileged +E reads $HOME/.kshrc file'
+ [[ $(print env_hit | HOME=$tmp $SHELL --rc 2>&1) == "OK" ]] &&
+ err_exit 'privileged --rc ignores empty $ENV'
+ [[ $(print env_hit | HOME=$tmp $SHELL --norc 2>&1) == "OK" ]] &&
+ err_exit 'privileged --norc reads $HOME/.kshrc file'
+else
+ [[ $(print env_hit | HOME=$tmp $SHELL 2>&1) == "OK" ]] &&
+ err_exit 'nointeractive shell reads $HOME/.kshrc file'
+ [[ $(print env_hit | HOME=$tmp $SHELL -E 2>&1) == "OK" ]] &&
+ err_exit '-E ignores empty $ENV'
+ [[ $(print env_hit | HOME=$tmp $SHELL +E 2>&1) == "OK" ]] &&
+ err_exit '+E reads $HOME/.kshrc file'
+ [[ $(print env_hit | HOME=$tmp $SHELL --rc 2>&1) == "OK" ]] &&
+ err_exit '--rc ignores empty $ENV'
+ [[ $(print env_hit | HOME=$tmp $SHELL --norc 2>&1) == "OK" ]] &&
+ err_exit '--norc reads $HOME/.kshrc file'
+fi
+
+unset ENV
+if [[ -o privileged ]]
+then
+ [[ $(print env_hit | HOME=$tmp $SHELL 2>&1) == "OK" ]] &&
+ err_exit 'privileged nointeractive shell reads $HOME/.kshrc file'
+ [[ $(print env_hit | HOME=$tmp $SHELL -E 2>&1) == "OK" ]] &&
+ err_exit 'privileged -E reads $HOME/.kshrc file'
+ [[ $(print env_hit | HOME=$tmp $SHELL +E 2>&1) == "OK" ]] &&
+ err_exit 'privileged +E reads $HOME/.kshrc file'
+ [[ $(print env_hit | HOME=$tmp $SHELL --rc 2>&1) == "OK" ]] &&
+ err_exit 'privileged --rc reads $HOME/.kshrc file'
+ [[ $(print env_hit | HOME=$tmp $SHELL --norc 2>&1) == "OK" ]] &&
+ err_exit 'privileged --norc reads $HOME/.kshrc file'
+else
+ [[ $(print env_hit | HOME=$tmp $SHELL 2>&1) == "OK" ]] &&
+ err_exit 'nointeractive shell reads $HOME/.kshrc file'
+ [[ $(print env_hit | HOME=$tmp $SHELL -E 2>&1) == "OK" ]] ||
+ err_exit '-E ignores $HOME/.kshrc file'
+ [[ $(print env_hit | HOME=$tmp $SHELL +E 2>&1) == "OK" ]] &&
+ err_exit '+E reads $HOME/.kshrc file'
+ [[ $(print env_hit | HOME=$tmp $SHELL --rc 2>&1) == "OK" ]] ||
+ err_exit '--rc ignores $HOME/.kshrc file'
+ [[ $(print env_hit | HOME=$tmp $SHELL --norc 2>&1) == "OK" ]] &&
+ err_exit '--norc reads $HOME/.kshrc file'
+fi
+
+rm -rf $tmp/.kshrc
+
+if command set -G 2> /dev/null
+then cd $tmp
+ mkdir bar foo
+ > bar.c > bam.c
+ > bar/foo.c > bar/bam.c
+ > foo/bam.c
+ set -- **.c
+ expected='bam.c bar.c'
+ [[ $* == $expected ]] ||
+ err_exit "-G **.c failed -- expected '$expected', got '$*'"
+ set -- **
+ expected='bam.c bar bar.c bar/bam.c bar/foo.c foo foo/bam.c'
+ [[ $* == $expected ]] ||
+ err_exit "-G ** failed -- expected '$expected', got '$*'"
+ set -- **/*.c
+ expected='bam.c bar.c bar/bam.c bar/foo.c foo/bam.c'
+ [[ $* == $expected ]] ||
+ err_exit "-G **/*.c failed -- expected '$expected', got '$*'"
+ set -- **/bam.c
+ expected='bam.c bar/bam.c foo/bam.c'
+ [[ $* == $expected ]] ||
+ err_exit "-G **/bam.c failed -- expected '$expected', got '$*'"
+ cd ~-
+fi
+
+cd $tmp
+t="<$$>.profile.<$$>"
+echo "echo '$t'" > .profile
+cp $SHELL ./-ksh
+if [[ -o privileged ]]
+then
+ [[ $(HOME=$PWD $SHELL -l </dev/null 2>&1) == *$t* ]] &&
+ err_exit 'privileged -l reads .profile'
+ [[ $(HOME=$PWD $SHELL --login </dev/null 2>&1) == *$t* ]] &&
+ err_exit 'privileged --login reads .profile'
+ [[ $(HOME=$PWD $SHELL --login-shell </dev/null 2>&1) == *$t* ]] &&
+ err_exit 'privileged --login-shell reads .profile'
+ [[ $(HOME=$PWD $SHELL --login_shell </dev/null 2>&1) == *$t* ]] &&
+ err_exit 'privileged --login_shell reads .profile'
+ [[ $(HOME=$PWD exec -a -ksh $SHELL </dev/null 2>&1) == *$t* ]] &&
+ err_exit 'privileged exec -a -ksh ksh reads .profile'
+ [[ $(HOME=$PWD ./-ksh -i </dev/null 2>&1) == *$t* ]] &&
+ err_exit 'privileged ./-ksh reads .profile'
+ [[ $(HOME=$PWD ./-ksh -ip </dev/null 2>&1) == *$t* ]] &&
+ err_exit 'privileged ./-ksh -p reads .profile'
+else
+ [[ $(HOME=$PWD $SHELL -l </dev/null 2>&1) == *$t* ]] ||
+ err_exit '-l ignores .profile'
+ [[ $(HOME=$PWD $SHELL --login </dev/null 2>&1) == *$t* ]] ||
+ err_exit '--login ignores .profile'
+ [[ $(HOME=$PWD $SHELL --login-shell </dev/null 2>&1) == *$t* ]] ||
+ err_exit '--login-shell ignores .profile'
+ [[ $(HOME=$PWD $SHELL --login_shell </dev/null 2>&1) == *$t* ]] ||
+ err_exit '--login_shell ignores .profile'
+ [[ $(HOME=$PWD exec -a -ksh $SHELL </dev/null 2>/dev/null) == *$t* ]] ||
+ err_exit 'exec -a -ksh ksh 2>/dev/null ignores .profile'
+ [[ $(HOME=$PWD exec -a -ksh $SHELL </dev/null 2>&1) == *$t* ]] ||
+ err_exit 'exec -a -ksh ksh 2>&1 ignores .profile'
+ [[ $(HOME=$PWD ./-ksh -i </dev/null 2>&1) == *$t* ]] ||
+ err_exit './-ksh ignores .profile'
+ [[ $(HOME=$PWD ./-ksh -ip </dev/null 2>&1) == *$t* ]] &&
+ err_exit './-ksh -p does not ignore .profile'
+fi
+cd ~-
+rm -rf $tmp/.profile
+
+# { exec interactive login_shell restricted xtrace } in the following test
+
+for opt in \
+ allexport all-export all_export \
+ bgnice bg-nice bg_nice \
+ clobber emacs \
+ errexit err-exit err_exit \
+ glob \
+ globstar glob-star glob_star \
+ gmacs \
+ ignoreeof ignore-eof ignore_eof \
+ keyword log markdirs monitor notify \
+ pipefail pipe-fail pipe_fail \
+ trackall track-all track_all \
+ unset verbose vi \
+ viraw vi-raw vi_raw
+do old=$opt
+ if [[ ! -o $opt ]]
+ then old=no$opt
+ fi
+
+ set --$opt || err_exit "set --$opt failed"
+ [[ -o $opt ]] || err_exit "[[ -o $opt ]] failed"
+ [[ -o no$opt ]] && err_exit "[[ -o no$opt ]] failed"
+ [[ -o no-$opt ]] && err_exit "[[ -o no-$opt ]] failed"
+ [[ -o no_$opt ]] && err_exit "[[ -o no_$opt ]] failed"
+ [[ -o ?$opt ]] || err_exit "[[ -o ?$opt ]] failed"
+ [[ -o ?no$opt ]] || err_exit "[[ -o ?no$opt ]] failed"
+ [[ -o ?no-$opt ]] || err_exit "[[ -o ?no-$opt ]] failed"
+ [[ -o ?no_$opt ]] || err_exit "[[ -o ?no_$opt ]] failed"
+
+ set --no$opt || err_exit "set --no$opt failed"
+ [[ -o no$opt ]] || err_exit "[[ -o no$opt ]] failed"
+ [[ -o $opt ]] && err_exit "[[ -o $opt ]] failed"
+
+ set --no-$opt || err_exit "set --no-$opt failed"
+ [[ -o no$opt ]] || err_exit "[[ -o no$opt ]] failed"
+ [[ -o $opt ]] && err_exit "[[ -o $opt ]] failed"
+
+ set --no_$opt || err_exit "set --no_$opt failed"
+ [[ -o no$opt ]] || err_exit "[[ -o no$opt ]] failed"
+ [[ -o $opt ]] && err_exit "[[ -o $opt ]] failed"
+
+ set -o $opt || err_exit "set -o $opt failed"
+ [[ -o $opt ]] || err_exit "[[ -o $opt ]] failed"
+ set -o $opt=1 || err_exit "set -o $opt=1 failed"
+ [[ -o $opt ]] || err_exit "[[ -o $opt ]] failed"
+ set -o no$opt=0 || err_exit "set -o no$opt=0 failed"
+ [[ -o $opt ]] || err_exit "[[ -o $opt ]] failed"
+ set --$opt=1 || err_exit "set --$opt=1 failed"
+ [[ -o $opt ]] || err_exit "[[ -o $opt ]] failed"
+ set --no$opt=0 || err_exit "set --no$opt=0 failed"
+ [[ -o $opt ]] || err_exit "[[ -o $opt ]] failed"
+
+ set -o no$opt || err_exit "set -o no$opt failed"
+ [[ -o no$opt ]] || err_exit "[[ -o no$opt ]] failed"
+ set -o $opt=0 || err_exit "set -o $opt=0 failed"
+ [[ -o no$opt ]] || err_exit "[[ -o no$opt ]] failed"
+ set -o no$opt=1 || err_exit "set -o no$opt=1 failed"
+ [[ -o no$opt ]] || err_exit "[[ -o no$opt ]] failed"
+ set --$opt=0 || err_exit "set --$opt=0 failed"
+ [[ -o no$opt ]] || err_exit "[[ -o no$opt ]] failed"
+ set --no$opt=1 || err_exit "set --no$opt=1 failed"
+ [[ -o no$opt ]] || err_exit "[[ -o no$opt ]] failed"
+
+ set -o no-$opt || err_exit "set -o no-$opt failed"
+ [[ -o no-$opt ]] || err_exit "[[ -o no-$opt ]] failed"
+
+ set -o no_$opt || err_exit "set -o no_$opt failed"
+ [[ -o no_$opt ]] || err_exit "[[ -o no_$opt ]] failed"
+
+ set +o $opt || err_exit "set +o $opt failed"
+ [[ -o no$opt ]] || err_exit "[[ -o no$opt ]] failed"
+
+ set +o no$opt || err_exit "set +o no$opt failed"
+ [[ -o $opt ]] || err_exit "[[ -o $opt ]] failed"
+
+ set +o no-$opt || err_exit "set +o no-$opt failed"
+ [[ -o $opt ]] || err_exit "[[ -o $opt ]] failed"
+
+ set +o no_$opt || err_exit "set +o no_$opt failed"
+ [[ -o $opt ]] || err_exit "[[ -o $opt ]] failed"
+
+ set --$old
+done
+
+for opt in \
+ exec interactive login_shell login-shell logi privileged \
+ rc restricted xtrace
+do [[ -o $opt ]]
+ y=$?
+ [[ -o no$opt ]]
+ n=$?
+ case $y$n in
+ 10|01) ;;
+ *) err_exit "[[ -o $opt ]] == [[ -o no$opt ]]" ;;
+ esac
+done
+
+for opt in \
+ foo foo-bar foo_bar
+do if [[ -o ?$opt ]]
+ then err_exit "[[ -o ?$opt ]] should fail"
+ fi
+ if [[ -o ?no$opt ]]
+ then err_exit "[[ -o ?no$opt ]] should fail"
+ fi
+done
+
+[[ $(set +o) == $(set --state) ]] || err_exit "set --state different from set +o"
+set -- $(set --state)
+[[ $1 == set && $2 == --default ]] || err_exit "set --state failed -- expected 'set --default *', got '$1 $2 *'"
+shift
+restore=$*
+shift
+off=
+for opt
+do case $opt in
+ --not*) opt=${opt/--/--no} ;;
+ --no*) opt=${opt/--no/--} ;;
+ --*) opt=${opt/--/--no} ;;
+ esac
+ off="$off $opt"
+done
+set $off
+state=$(set --state)
+default=$(set --default --state)
+[[ $state == $default ]] || err_exit "set --state for default options failed: expected '$default', got '$state'"
+set $restore
+state=$(set --state)
+[[ $state == "set $restore" ]] || err_exit "set --state after restore failed: expected 'set $restore', got '$state'"
+
+typeset -a pipeline
+pipeline=(
+ ( nopipefail=0 pipefail=1 command='false|true|true' )
+ ( nopipefail=0 pipefail=1 command='true|false|true' )
+ ( nopipefail=1 pipefail=1 command='true|true|false' )
+ ( nopipefail=1 pipefail=1 command='false|false|false' )
+ ( nopipefail=0 pipefail=0 command='true|true|true' )
+ ( nopipefail=0 pipefail=0 command='print hi|(sleep 1;/bin/cat)>/dev/null' )
+)
+set --nopipefail
+for ((i = 0; i < ${#pipeline[@]}; i++ ))
+do eval ${pipeline[i].command}
+ status=$?
+ expected=${pipeline[i].nopipefail}
+ [[ $status == $expected ]] ||
+ err_exit "--nopipefail '${pipeline[i].command}' exit status $status -- expected $expected"
+done
+ftt=0
+set --pipefail
+for ((i = 0; i < ${#pipeline[@]}; i++ ))
+do eval ${pipeline[i].command}
+ status=$?
+ expected=${pipeline[i].pipefail}
+ if [[ $status != $expected ]]
+ then err_exit "--pipefail '${pipeline[i].command}' exit status $status -- expected $expected"
+ (( i == 0 )) && ftt=1
+ fi
+done
+if (( ! ftt ))
+then exp=10
+ got=$(for((n=1;n<exp;n++))do $SHELL --pipefail -c '(sleep 0.1;false)|true|true' && break; done; print $n)
+ [[ $got == $exp ]] || err_exit "--pipefail -c '(sleep 0.1;false)|true|true' fails with exit status 0 (after $got/$exp iterations)"
+fi
+
+echo=$(whence -p echo)
+for ((i=0; i < 20; i++))
+do if ! x=$(true | $echo 123)
+ then err_exit 'command substitution with wrong exit status with pipefai'
+ break
+ fi
+done
+(
+ set -o pipefail
+ false | true
+ (( $? )) || err_exit 'pipe not failing in subshell with pipefail'
+) | wc >/dev/null
+$SHELL -c 'set -o pipefail; false | $(whence -p true);' && err_exit 'pipefail not returning failure with sh -c'
+exp='1212 or 1221'
+got=$(
+ set --pipefail
+ pipe() { date | cat > /dev/null ;}
+ print $'1\n2' |
+ while read i
+ do if pipe $tmp
+ then { print -n $i; sleep 2; print -n $i; } &
+ fi
+ done
+ wait
+)
+[[ $got == @((12|21)(12|21)) ]] || err_exit "& job delayed by --pipefail, expected '$exp', got '$got'"
+$SHELL -c '[[ $- == *c* ]]' || err_exit 'option c not in $-'
+> $tmp/.profile
+for i in i l r s D E a b e f h k n t u v x B C G H
+do HOME=$tmp ENV= $SHELL -$i >/dev/null 2>&1 <<- ++EOF++ || err_exit "option $i not in \$-"
+ [[ \$- == *$i* ]] || exit 1
+ ++EOF++
+done
+letters=ilrabefhknuvxBCGE
+integer j=0
+for i in interactive login restricted allexport notify errexit \
+ noglob trackall keyword noexec nounset verbose xtrace braceexpand \
+ noclobber globstar rc
+do HOME=$tmp ENV= $SHELL -o $i >/dev/null 2>&1 <<- ++EOF++ || err_exit "option $i not equivalent to ${letters:j:1}"
+ [[ \$- == *${letters:j:1}* ]] || exit 1
+ ++EOF++
+ ((j++))
+done
+
+export ENV= PS1="(:$$:)"
+histfile=$tmp/history
+exp=$(HISTFILE=$histfile $SHELL -c $'function foo\n{\ncat\n}\ntype foo')
+for var in HISTSIZE HISTFILE
+do got=$( ( HISTFILE=$histfile $SHELL +E -ic $'unset '$var$'\nfunction foo\n{\ncat\n}\ntype foo\nexit' ) 2>&1 )
+ got=${got##*"$PS1"}
+ [[ $got == "$exp" ]] || err_exit "function definition inside (...) with $var unset fails -- got '$got', expected '$exp'"
+ got=$( { HISTFILE=$histfile $SHELL +E -ic $'unset '$var$'\nfunction foo\n{\ncat\n}\ntype foo\nexit' ;} 2>&1 )
+ got=${got##*"$PS1"}
+ [[ $got == "$exp" ]] || err_exit "function definition inside {...;} with $var unset fails -- got '$got', expected '$exp'"
+done
+( unset HISTFILE; $SHELL -ic "HISTFILE=$histfile" 2>/dev/null ) || err_exit "setting HISTFILE when not in environment fails"
+
+# the next tests loop on all combinations of
+# { SUB PAR CMD ADD }
+
+SUB=(
+ ( BEG='$( ' END=' )' )
+ ( BEG='${ ' END='; }' )
+)
+PAR=(
+ ( BEG='( ' END=' )' )
+ ( BEG='{ ' END='; }' )
+)
+CMD=( command-kill script-kill )
+ADD=( '' '; :' )
+
+cd $tmp
+print $'#!'$SHELL$'\nkill -KILL $$' > command-kill
+print $'kill -KILL $$' > script-kill
+chmod +x command-kill script-kill
+export PATH=.:$PATH
+exp='Killed'
+for ((S=0; S<${#SUB[@]}; S++))
+do for ((P=0; P<${#PAR[@]}; P++))
+ do for ((C=0; C<${#CMD[@]}; C++))
+ do for ((A=0; A<${#ADD[@]}; A++))
+ do cmd="${SUB[S].BEG}${PAR[P].BEG}${CMD[C]}${PAR[P].END} 2>&1${ADD[A]}${SUB[S].END}"
+ eval got="$cmd"
+ got=${got##*': '}
+ got=${got%%'('*}
+ [[ $got == "$exp" ]] || err_exit "$cmd failed -- got '$got', expected '$exp'"
+ done
+ done
+ done
+done
+
+$SHELL 2> /dev/null -c '{; true ;}' || err_exit 'leading ; causes syntax error in brace group'
+$SHELL 2> /dev/null -c '(; true ;)' || err_exit 'leading ; causes syntax error in parenthesis group'
+
+print 'for ((i = 0; i < ${1:-10000}; i++ )); do printf "%.*c\n" 15 x; done' > pipefail
+chmod +x pipefail
+$SHELL --pipefail -c './pipefail 10000 | sed 1q' >/dev/null 2>&1 &
+tst=$!
+{ sleep 4; kill $tst; } 2>/dev/null &
+spy=$!
+wait $tst 2>/dev/null
+status=$?
+if [[ $status == 0 || $(kill -l $status) == PIPE ]]
+then kill $spy 2>/dev/null
+else err_exit "pipefail pipeline bypasses SIGPIPE and hangs"
+fi
+wait
+
+[[ $($SHELL -uc '[[ "${d1.u[z asd].revents}" ]]' 2>&1) == *'d1.u[z asd].revents'* ]] || err_exit 'name of unset parameter not in error message'
+
+[[ $($SHELL 2> /dev/null -xc $'set --showme\nprint 1\n; print 2') == 1 ]] || err_exit 'showme option with xtrace not working correctly'
+
+$SHELL -uc 'var=foo;unset var;: ${var%foo}' >/dev/null 2>&1 && err_exit '${var%foo} should fail with set -u'
+$SHELL -uc 'var=foo;unset var;: ${!var}' >/dev/null 2>&1 && err_exit '${!var} should fail with set -u'
+$SHELL -uc 'var=foo;unset var;: ${#var}' >/dev/null 2>&1 && err_exit '${#var} should fail with set -u'
+$SHELL -uc 'var=foo;unset var;: ${var-OK}' >/dev/null 2>&1 || err_exit '${var-OK} should not fail with set -u'
+$SHELL -uc 'var=foo;nset var;: ${var:-OK}' >/dev/null 2>&1 || err_exit '${var:-OK} should not fail with set -u'
+
+z=$($SHELL 2>&1 -uc 'print ${X23456789012345}')
+[[ $z == *X23456789012345:* ]] || err_exit "error message garbled with set -u got $z"
+
+# pipe hang bug fixed 2011-03-15
+float start=SECONDS toolong=3
+( $SHELL <<-EOF
+ set -o pipefail
+ (sleep $toolong;kill \$\$> /dev/null) &
+ cat $SHELL | for ((i=0; i < 5; i++))
+ do
+ date | wc > /dev/null
+ $SHELL -c 'read -N1'
+ done
+EOF
+) 2> /dev/null
+(( (SECONDS-start) > (toolong-0.5) )) && err_exit "pipefail causes script to hang"
+
+# showme with arithmetic for loops
+$SHELL -n -c $'for((;1;))\ndo ; nothing\ndone' 2>/dev/null || err_exit 'showme commands give syntax error inside arithmetic for loops'
+
+#set -x
+float t1=SECONDS
+set -o pipefail
+print | while read
+do if { date | true;} ; true
+ then sleep 2 &
+ fi
+done
+(( (SECONDS-t1) > .5 )) && err_exit 'pipefail should not wait for background processes'
+
+# process source files from profiles as profile files
+print '. ./dotfile' > envfile
+print $'alias print=:\nprint foobar' > dotfile
+[[ $(ENV=$PWD/envfile $SHELL -i -c : 2>/dev/null) == foobar ]] && err_exit 'files source from profile does not process aliases correctly'
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/path.sh b/src/cmd/ksh93/tests/path.sh
new file mode 100755
index 0000000..3fd16e9
--- /dev/null
+++ b/src/cmd/ksh93/tests/path.sh
@@ -0,0 +1,375 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2012 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+cd $tmp || exit
+type /xxxxxx > out1 2> out2
+[[ -s out1 ]] && err_exit 'type should not write on stdout for not found case'
+[[ -s out2 ]] || err_exit 'type should write on stderr for not found case'
+mkdir dir1 dir2
+cat > dir1/foobar << '+++'
+foobar() { print foobar1;}
+function dir1 { print dir1;}
++++
+cat > dir2/foobar << '+++'
+foobar() { print foobar2;}
+function dir2 { print dir2;}
++++
+chmod +x dir[12]/foobar
+p=$PATH
+FPATH=$PWD/dir1
+PATH=$FPATH:$p
+[[ $( foobar) == foobar1 ]] || err_exit 'foobar should output foobar1'
+FPATH=$PWD/dir2
+PATH=$FPATH:$p
+[[ $(foobar) == foobar2 ]] || err_exit 'foobar should output foobar2'
+FPATH=$PWD/dir1
+PATH=$FPATH:$p
+[[ $(foobar) == foobar1 ]] || err_exit 'foobar should output foobar1 again'
+FPATH=$PWD/dir2
+PATH=$FPATH:$p
+[[ ${ foobar;} == foobar2 ]] || err_exit 'foobar should output foobar2 with ${}'
+[[ ${ dir2;} == dir2 ]] || err_exit 'should be dir2'
+[[ ${ dir1;} == dir1 ]] 2> /dev/null && err_exit 'should not be be dir1'
+FPATH=$PWD/dir1
+PATH=$FPATH:$p
+[[ ${ foobar;} == foobar1 ]] || err_exit 'foobar should output foobar1 with ${}'
+[[ ${ dir1;} == dir1 ]] || err_exit 'should be dir1'
+[[ ${ dir2;} == dir2 ]] 2> /dev/null && err_exit 'should not be be dir2'
+FPATH=$PWD/dir2
+PATH=$FPATH:$p
+[[ ${ foobar;} == foobar2 ]] || err_exit 'foobar should output foobar2 with ${} again'
+PATH=$p
+(PATH="/bin")
+[[ $($SHELL -c 'print -r -- "$PATH"') == "$PATH" ]] || err_exit 'export PATH lost in subshell'
+cat > bug1 <<- EOF
+ print print ok > $tmp/ok
+ /bin/chmod 755 $tmp/ok
+ function a
+ {
+ typeset -x PATH=$tmp
+ ok
+ }
+ path=\$PATH
+ unset PATH
+ a
+ PATH=\$path
+}
+EOF
+[[ $($SHELL ./bug1 2>/dev/null) == ok ]] || err_exit "PATH in function not working"
+cat > bug1 <<- \EOF
+ function lock_unlock
+ {
+ typeset PATH=/usr/bin
+ typeset -x PATH=''
+ }
+
+ PATH=/usr/bin
+ : $(PATH=/usr/bin getconf PATH)
+ typeset -ft lock_unlock
+ lock_unlock
+EOF
+($SHELL ./bug1) 2> /dev/null || err_exit "path_delete bug"
+mkdir tdir
+if $SHELL tdir > /dev/null 2>&1
+then err_exit 'not an error to run ksh on a directory'
+fi
+
+print 'print hi' > ls
+if [[ $($SHELL ls 2> /dev/null) != hi ]]
+then err_exit "$SHELL name not executing version in current directory"
+fi
+if [[ $(ls -d . 2>/dev/null) == . && $(PATH=/bin:/usr/bin:$PATH ls -d . 2>/dev/null) != . ]]
+then err_exit 'PATH export in command substitution not working'
+fi
+pwd=$PWD
+# get rid of leading and trailing : and trailing :.
+PATH=${PATH%.}
+PATH=${PATH%:}
+PATH=${PATH#.}
+PATH=${PATH#:}
+path=$PATH
+var=$(whence date)
+dir=$(basename "$var")
+for i in 1 2 3 4 5 6 7 8 9 0
+do if ! whence notfound$i 2> /dev/null
+ then cmd=notfound$i
+ break
+ fi
+done
+print 'print hello' > date
+chmod +x date
+print 'print notfound' > $cmd
+chmod +x "$cmd"
+> foo
+chmod 755 foo
+for PATH in $path :$path $path: .:$path $path: $path:. $PWD::$path $PWD:.:$path $path:$PWD $path:.:$PWD
+do
+# print path=$PATH $(whence date)
+# print path=$PATH $(whence "$cmd")
+ date
+ "$cmd"
+done > /dev/null 2>&1
+builtin -d date 2> /dev/null
+if [[ $(PATH=:/usr/bin; date) != 'hello' ]]
+then err_exit "leading : in path not working"
+fi
+(
+ PATH=$PWD:
+ builtin chmod
+ print 'print cannot execute' > noexec
+ chmod 644 noexec
+ if [[ ! -x noexec ]]
+ then noexec > /dev/null 2>&1
+ else exit 126
+ fi
+)
+status=$?
+[[ $status == 126 ]] || err_exit "exit status of non-executable is $status -- 126 expected"
+builtin -d rm 2> /dev/null
+chmod=$(whence chmod)
+rm=$(whence rm)
+d=$(dirname "$rm")
+
+chmod=$(whence chmod)
+
+for cmd in date foo
+do exp="$cmd found"
+ print print $exp > $cmd
+ $chmod +x $cmd
+ got=$($SHELL -c "unset FPATH; PATH=/dev/null; $cmd" 2>&1)
+ [[ $got == $exp ]] && err_exit "$cmd as last command should not find ./$cmd with PATH=/dev/null"
+ got=$($SHELL -c "unset FPATH; PATH=/dev/null; $cmd" 2>&1)
+ [[ $got == $exp ]] && err_exit "$cmd should not find ./$cmd with PATH=/dev/null"
+ exp=$PWD/./$cmd
+ got=$(unset FPATH; PATH=/dev/null; whence ./$cmd)
+ [[ $got == $exp ]] || err_exit "whence $cmd should find ./$cmd with PATH=/dev/null"
+ exp=$PWD/$cmd
+ got=$(unset FPATH; PATH=/dev/null; whence $PWD/$cmd)
+ [[ $got == $exp ]] || err_exit "whence \$PWD/$cmd should find ./$cmd with PATH=/dev/null"
+done
+
+exp=''
+got=$($SHELL -c "unset FPATH; PATH=/dev/null; whence ./notfound" 2>&1)
+[[ $got == $exp ]] || err_exit "whence ./$cmd failed -- expected '$exp', got '$got'"
+got=$($SHELL -c "unset FPATH; PATH=/dev/null; whence $PWD/notfound" 2>&1)
+[[ $got == $exp ]] || err_exit "whence \$PWD/$cmd failed -- expected '$exp', got '$got'"
+
+unset FPATH
+PATH=/dev/null
+for cmd in date foo
+do exp="$cmd found"
+ print print $exp > $cmd
+ $chmod +x $cmd
+ got=$($cmd 2>&1)
+ [[ $got == $exp ]] && err_exit "$cmd as last command should not find ./$cmd with PATH=/dev/null"
+ got=$($cmd 2>&1; :)
+ [[ $got == $exp ]] && err_exit "$cmd should not find ./$cmd with PATH=/dev/null"
+ exp=$PWD/./$cmd
+ got=$(whence ./$cmd)
+ [[ $got == $exp ]] || err_exit "whence ./$cmd should find ./$cmd with PATH=/dev/null"
+ exp=$PWD/$cmd
+ got=$(whence $PWD/$cmd)
+ [[ $got == $exp ]] || err_exit "whence \$PWD/$cmd should find ./$cmd with PATH=/dev/null"
+done
+exp=''
+got=$(whence ./notfound)
+[[ $got == $exp ]] || err_exit "whence ./$cmd failed -- expected '$exp', got '$got'"
+got=$(whence $PWD/notfound)
+[[ $got == $exp ]] || err_exit "whence \$PWD/$cmd failed -- expected '$exp', got '$got'"
+
+PATH=$d:
+cp "$rm" kshrm
+if [[ $(whence kshrm) != $PWD/kshrm ]]
+then err_exit 'trailing : in pathname not working'
+fi
+cp "$rm" rm
+PATH=:$d
+if [[ $(whence rm) != $PWD/rm ]]
+then err_exit 'leading : in pathname not working'
+fi
+PATH=$d: whence rm > /dev/null
+if [[ $(whence rm) != $PWD/rm ]]
+then err_exit 'pathname not restored after scoping'
+fi
+mkdir bin
+print 'print ok' > bin/tst
+chmod +x bin/tst
+if [[ $(PATH=$PWD/bin tst 2>/dev/null) != ok ]]
+then err_exit '(PATH=$PWD/bin foo) does not find $PWD/bin/foo'
+fi
+cd /
+if whence ls > /dev/null
+then PATH=
+ if [[ $(whence rm) ]]
+ then err_exit 'setting PATH to Null not working'
+ fi
+ unset PATH
+ if [[ $(whence rm) != /*rm ]]
+ then err_exit 'unsetting path not working'
+ fi
+fi
+PATH=/dev:$tmp
+x=$(whence rm)
+typeset foo=$(PATH=/xyz:/abc :)
+y=$(whence rm)
+[[ $x != "$y" ]] && err_exit 'PATH not restored after command substitution'
+whence getconf > /dev/null && err_exit 'getconf should not be found'
+builtin /bin/getconf
+PATH=/bin
+PATH=$(getconf PATH)
+x=$(whence ls)
+PATH=.:$PWD:${x%/ls}
+[[ $(whence ls) == "$x" ]] || err_exit 'PATH search bug when .:$PWD in path'
+PATH=$PWD:.:${x%/ls}
+[[ $(whence ls) == "$x" ]] || err_exit 'PATH search bug when :$PWD:. in path'
+cd "${x%/ls}"
+[[ $(whence ls) == /* ]] || err_exit 'whence not generating absolute pathname'
+status=$($SHELL -c $'trap \'print $?\' EXIT;/xxx/a/b/c/d/e 2> /dev/null')
+[[ $status == 127 ]] || err_exit "not found command exit status $status -- expected 127"
+status=$($SHELL -c $'trap \'print $?\' EXIT;/dev/null 2> /dev/null')
+[[ $status == 126 ]] || err_exit "non executable command exit status $status -- expected 126"
+status=$($SHELL -c $'trap \'print $?\' ERR;/xxx/a/b/c/d/e 2> /dev/null')
+[[ $status == 127 ]] || err_exit "not found command with ERR trap exit status $status -- expected 127"
+status=$($SHELL -c $'trap \'print $?\' ERR;/dev/null 2> /dev/null')
+[[ $status == 126 ]] || err_exit "non executable command ERR trap exit status $status -- expected 126"
+
+# universe via PATH
+
+builtin getconf
+getconf UNIVERSE - att # override sticky default 'UNIVERSE = foo'
+
+[[ $(PATH=/usr/ucb/bin:/usr/bin echo -n ucb) == 'ucb' ]] || err_exit "ucb universe echo ignores -n option"
+[[ $(PATH=/usr/xpg/bin:/usr/bin echo -n att) == '-n att' ]] || err_exit "att universe echo does not ignore -n option"
+
+PATH=$path
+
+scr=$tmp/script
+exp=126
+
+: > $scr
+chmod a=x $scr
+{ got=$($scr; print $?); } 2>/dev/null
+[[ "$got" == "$exp" ]] || err_exit "unreadable empty script should fail -- expected $exp, got $got"
+{ got=$(command $scr; print $?); } 2>/dev/null
+[[ "$got" == "$exp" ]] || err_exit "command of unreadable empty script should fail -- expected $exp, got $got"
+[[ "$(:; $scr; print $?)" == "$exp" ]] 2>/dev/null || err_exit "unreadable empty script in [[ ... ]] should fail -- expected $exp"
+[[ "$(:; command $scr; print $?)" == "$exp" ]] 2>/dev/null || err_exit "command unreadable empty script in [[ ... ]] should fail -- expected $exp"
+got=$($SHELL -c "$scr; print \$?" 2>/dev/null)
+[[ "$got" == "$exp" ]] || err_exit "\$SHELL -c of unreadable empty script should fail -- expected $exp, got" $got
+got=$($SHELL -c "command $scr; print \$?" 2>/dev/null)
+[[ "$got" == "$exp" ]] || err_exit "\$SHELL -c of command of unreadable empty script should fail -- expected $exp, got" $got
+
+rm -f $scr
+print : > $scr
+chmod a=x $scr
+{ got=$($scr; print $?); } 2>/dev/null
+[[ "$got" == "$exp" ]] || err_exit "unreadable non-empty script should fail -- expected $exp, got $got"
+{ got=$(command $scr; print $?); } 2>/dev/null
+[[ "$got" == "$exp" ]] || err_exit "command of unreadable non-empty script should fail -- expected $exp, got $got"
+[[ "$(:; $scr; print $?)" == "$exp" ]] 2>/dev/null || err_exit "unreadable non-empty script in [[ ... ]] should fail -- expected $exp"
+[[ "$(:; command $scr; print $?)" == "$exp" ]] 2>/dev/null || err_exit "command unreadable non-empty script in [[ ... ]] should fail -- expected $exp"
+got=$($SHELL -c "$scr; print \$?" 2>/dev/null)
+[[ "$got" == "$exp" ]] || err_exit "\$SHELL -c of unreadable non-empty script should fail -- expected $exp, got" $got
+got=$($SHELL -c "command $scr; print \$?" 2>/dev/null)
+[[ "$got" == "$exp" ]] || err_exit "\$SHELL -c of command of unreadable non-empty script should fail -- expected $exp, got" $got
+
+# whence -a bug fix
+cd "$tmp"
+ifs=$IFS
+IFS=$'\n'
+PATH=$PATH:
+> ls
+chmod +x ls
+ok=
+for i in $(whence -a ls)
+do if [[ $i == *"$PWD/ls" ]]
+ then ok=1
+ break;
+ fi
+done
+[[ $ok ]] || err_exit 'whence -a not finding all executables'
+rm -f ls
+PATH=${PATH%:}
+
+#whence -p bug fix
+function foo
+{
+ :
+}
+[[ $(whence -p foo) == foo ]] && err_exit 'whence -p foo should not find function foo'
+
+# whence -q bug fix
+$SHELL -c 'whence -q cat' & pid=$!
+sleep 3
+kill $! 2> /dev/null && err_exit 'whence -q appears to be hung'
+
+FPATH=$PWD
+print 'function foobar { :;}' > foobar
+autoload foobar;
+exec {m}< /dev/null
+for ((i=0; i < 25; i++))
+do ( foobar )
+done
+exec {m}<& -
+exec {n}< /dev/null
+(( n > m )) && err_exit 'autoload function in subshell leaves file open'
+
+# whence -a bug fix
+rmdir=rmdir
+if mkdir "$rmdir"
+then rm=${ whence rm;}
+ cp "$rm" "$rmdir"
+ { PATH=:${rm%/rm} $SHELL -c "cd \"$rmdir\";whence -a rm";} > /dev/null 2>&1
+ exitval=$?
+ (( exitval==0 )) || err_exit "whence -a has exitval $exitval"
+fi
+
+[[ ! -d bin ]] && mkdir bin
+[[ ! -d fun ]] && mkdir fun
+print 'FPATH=../fun' > bin/.paths
+cat <<- \EOF > fun/myfun
+ function myfun
+ {
+ print myfun
+ }
+EOF
+x=$(FPATH= PATH=$PWD/bin $SHELL -c ': $(whence less);myfun') 2> /dev/null
+[[ $x == myfun ]] || err_exit 'function myfun not found'
+
+cp $(whence -p echo) user_to_group_relationship.hdr.query
+FPATH=/foobar:
+PATH=$FPATH:$PATH:.
+[[ $(user_to_group_relationship.hdr.query foobar) == foobar ]] 2> /dev/null || err_exit 'Cannot execute command with . in name when PATH and FPATH end in :.'
+
+exit $((Errors<125?Errors:125))
+
diff --git a/src/cmd/ksh93/tests/pointtype.sh b/src/cmd/ksh93/tests/pointtype.sh
new file mode 100755
index 0000000..b0a5333
--- /dev/null
+++ b/src/cmd/ksh93/tests/pointtype.sh
@@ -0,0 +1,138 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ (( Errors+=1 ))
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+typeset -T Pt_t=(
+ float x=1
+ float y=0
+ len()
+ {
+ print -r $((sqrt(_.x*_.x + _.y*_.y)))
+ }
+)
+
+for ((i=0; i < 100; i++))
+do
+Pt_t p
+[[ ${p.x} == 1 ]] || err_exit '${p[x]} is not 1'
+(( p.x == 1 )) || err_ext 'p[x] is not 1'
+[[ $(p.len) == 1 ]] || err_exit '$(p.len) != 1'
+[[ ${p.len} == 1 ]] || err_exit '${p.len} != 1'
+(( p.len == 1 )) || err_exit '((p.len != 1))'
+Pt_t q=(y=2)
+(( q.x == 1 )) || err_exit 'q.x is not 1'
+(( (q.len - sqrt(5)) < 10e-10 )) || err_exit 'q.len != sqrt(5)'
+q.len()
+{
+ print -r $((abs(_.x)+abs(_.y) ))
+}
+(( q.len == 3 )) || err_exit 'q.len is not 3'
+p=q
+[[ ${p.y} == 2 ]] || err_exit '${p[y]} is not 2'
+[[ ${@p} == Pt_t ]] || err_exit 'type of p is not Pt_t'
+[[ ${@q} == Pt_t ]] || err_exit 'type of q is not Pt_t'
+(( p.len == 3 )) || err_exit 'p.len is not 3'
+unset p q
+Pt_t pp=( ( x=3 y=4) ( x=5 y=12) (y=2) )
+(( pp[0].len == 5 )) || err_exit 'pp[0].len != 5'
+(( pp[1].len == 13 )) || err_exit 'pp[0].len != 12'
+(( (pp[2].len - sqrt(5)) < 10e-10 )) || err_exit 'pp[2].len != sqrt(5)'
+[[ ${pp[1]} == $'(\n\ttypeset -l -E x=5\n\ttypeset -l -E y=12\n)' ]] || err_exit '${pp[1] is not correct'
+[[ ${!pp[@]} == '0 1 2' ]] || err_exit '${pp[@] != "0 1 2"'
+pp+=( x=6 y=8)
+(( pp[3].len == 10 )) || err_exit 'pp[3].len != 10'
+[[ ${!pp[@]} == '0 1 2 3' ]] || err_exit '${pp[@] != "0 1 2 3"'
+pp[4]=pp[1]
+[[ ${pp[4]} == $'(\n\ttypeset -l -E x=5\n\ttypeset -l -E y=12\n)' ]] || err_exit '${pp[4] is not correct'
+unset pp
+Pt_t pp=( [one]=( x=3 y=4) [two]=( x=5 y=12) [three]=(y=2) )
+(( pp[one].len == 5 )) || err_exit 'pp[one].len != 5'
+(( pp[two].len == 13 )) || err_exit 'pp[two].len != 12'
+[[ ${pp[two]} == $'(\n\ttypeset -l -E x=5\n\ttypeset -l -E y=12\n)' ]] || err_exit '${pp[two] is not correct'
+[[ ${!pp[@]} == 'one three two' ]] || err_exit '${pp[@] != "one three two"'
+[[ ${@pp[1]} == Pt_t ]] || err_exit 'type of pp[1] is not Pt_t'
+unset pp
+done
+# redefinition of point
+typeset -T Pt_t=(
+ Pt_t _=(x=3 y=6)
+ float z=2
+ len()
+ {
+ print -r $((sqrt(_.x*_.x + _.y*_.y + _.z*_.z)))
+ }
+)
+Pt_t p
+[[ ${p.y} == 6 ]] || err_exit '${p.y} != 6'
+(( p.len == 7 )) || err_exit '((p.len !=7))'
+
+z=()
+Pt_t -a z.p
+z.p[1]=(y=2)
+z.p[2]=(y=5)
+z.p[3]=(x=6 y=4)
+eval y="$z"
+[[ $y == "$z" ]] || err_exit 'expansion of indexed array of types is incorrect'
+eval "$(typeset -p y)"
+[[ $y == "$z" ]] || err_exit 'typeset -p z for indexed array of types is incorrect'
+unset z y
+z=()
+Pt_t -A z.p
+z.p[1]=(y=2)
+z.p[2]=(y=5)
+z.p[3]=(x=6 y=4)
+eval y="$z"
+[[ $y == "$z" ]] || err_exit 'expansion of associative array of types is incorrect'
+eval "$(typeset -p y)"
+[[ $y == "$z" ]] || err_exit 'typeset -p z for associative of types is incorrect'
+unset z y
+
+typeset -T A_t=(
+ Pt_t -a b
+)
+typeset -T B_t=(
+ Pt_t -A b
+)
+A_t r
+r.b[1]=(y=2)
+r.b[2]=(y=5)
+eval s="$r"
+[[ $r == "$s" ]] || err_exit 'expansion of type containing index array of types is incorrect'
+eval "$(typeset -p s)"
+[[ $y == "$z" ]] || err_exit 'typeset -p z for type containing index of types is incorrect'
+unset r s
+B_t r
+r.b[1]=(y=2)
+r.b[2]=(y=5)
+eval s="$r"
+[[ $r == "$s" ]] || err_exit 'expansion of type containing index array of types is incorrect'
+eval "$(typeset -p s)"
+[[ $y == "$z" ]] || err_exit 'typeset -p z for type containing index of types is incorrect'
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/pty.sh b/src/cmd/ksh93/tests/pty.sh
new file mode 100755
index 0000000..71eaef5
--- /dev/null
+++ b/src/cmd/ksh93/tests/pty.sh
@@ -0,0 +1,442 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2012 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+: : generated by mkptytests from "posix-sh-*-c.pty" : :
+
+# the trickiest part of the tests is avoiding typeahead
+# in the pty dialogue
+
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ (( Errors++ ))
+}
+
+alias err_exit='err_exit $lineno'
+
+Command=${0##*/}
+integer Errors=0 lineno=1
+
+whence -q pty || { lineno=$LINENO; err_exit "pty command not found -- tests skipped"; exit 0; }
+
+bintrue=$(whence -p true)
+
+x=$( $SHELL <<- \EOF
+ trap 'exit 0' EXIT
+ bintrue=$(whence -p true)
+ set -o monitor
+ {
+ eval $'set -o vi\npty $bintrue'
+ } < /dev/null & pid=$!
+ #sleep 1
+ jobs
+ kill $$
+ EOF
+)
+[[ $x == *Stop* ]] && err_exit 'monitor mode enabled incorrectly causes job to stop'
+
+if [[ -o xtrace ]]
+then debug=--debug=1
+else debug=
+fi
+
+function tst
+{
+ integer lineno=$1 offset
+ typeset text
+
+ pty $debug --dialogue --messages='/dev/fd/1' $SHELL |
+ while read -r text
+ do if [[ $text == *debug* ]]
+ then print -u2 -r -- "$text"
+ else offset=${text/*: line +([[:digit:]]):*/\1}
+ err_exit "${text/: line $offset:/: line $(( lineno + offset)):}"
+ fi
+ done
+}
+
+export PS1=':test-!: ' PS2='> ' PS4=': ' ENV= EXINIT= HISTFILE= TERM=dumb VISUAL=vi LC_ALL=C
+
+if ! pty $bintrue < /dev/null
+then err_exit pty command hangs on $bintrue -- tests skipped
+ exit 0
+fi
+
+# err_exit #
+tst $LINENO <<"!"
+L POSIX sh 026(C)
+
+# If the User Portability Utilities Option is supported: When the
+# POSIX locale is specified and a background job is suspended by a
+# SIGTSTP signal then the <state> field in the output message is set to
+# Stopped, Suspended, Stopped(SIGTSTP) or Suspended(SIGTSTP).
+
+I ^\r?\n$
+p :test-1:
+w sleep 60 &
+u [[:digit:]]\r?\n$
+s 100
+p :test-2:
+w kill -TSTP $!
+u (Stopped|Suspended)
+p :test-3:
+w kill -KILL $!
+w wait
+u (Killed|Done)
+!
+
+# err_exit #
+tst $LINENO <<"!"
+L POSIX sh 028(C)
+
+# If the User Portability Utilities Option is supported: When the
+# POSIX locale is specified and a background job is suspended by a
+# SIGTTIN signal then the <state> field in the output message is set to
+# Stopped(SIGTTIN) or Suspended(SIGTTIN).
+
+I ^\r?\n$
+p :test-1:
+w sleep 60 &
+u [[:digit:]]\r?\n$
+s 100
+p :test-2:
+w kill -TTIN $!
+u (Stopped|Suspended) \(SIGTTIN\)
+p :test-3:
+w kill -KILL $!
+w wait
+u (Killed|Done)
+!
+
+# err_exit #
+tst $LINENO <<"!"
+L POSIX sh 029(C)
+
+# If the User Portability Utilities Option is supported: When the
+# POSIX locale is specified and a background job is suspended by a
+# SIGTTOU signal then the <state> field in the output message is set to
+# Stopped(SIGTTOU) or Suspended(SIGTTOU).
+
+I ^\r?\n$
+p :test-1:
+w sleep 60 &
+u [[:digit:]]\r?\n$
+s 100
+p :test-2:
+w kill -TTOU $!
+u (Stopped|Suspended) \(SIGTTOU\)
+p :test-3:
+w kill -KILL $!
+w wait
+u (Killed|Done)
+!
+
+# err_exit #
+tst $LINENO <<"!"
+L POSIX sh 091(C)
+
+# If the User Portability Utilities Option is supported and shell
+# command line editing is supported: When in insert mode an entered
+# character other than <newline>, erase, interrupt, kill, control-V,
+# control-W, backslash \ (followed by erase or kill), end-of-file and
+# <ESC> is inserted in the current command line.
+
+c echo h
+c ell
+w o
+u ^hello\r?\n$
+!
+
+# err_exit #
+tst $LINENO <<"!"
+L POSIX sh 093(C)
+
+# If the User Portability Utilities Option is supported and shell
+# command line editing is supported: After termination of a previous
+# command, sh is entered in insert mode.
+
+w echo hello
+u ^hello\r?\n$
+c echo goo
+c dby
+w e
+u ^goodbye\r?\n$
+!
+
+# err_exit #
+tst $LINENO <<"!"
+L POSIX sh 094(C)
+
+# If the User Portability Utilities Option is supported and shell
+# command line editing is supported: When in insert mode an <ESC>
+# switches sh into command mode.
+
+c echo he\E
+s 400
+w allo
+u ^hello\r?\n$
+!
+
+# err_exit #
+tst $LINENO <<"!"
+L POSIX sh 096(C)
+
+# If the User Portability Utilities Option is supported and shell
+# command line editing is supported: When in command mode the
+# interrupt character causes sh to terminate command line editing on
+# the current command line, re-issue the prompt on the next line of the
+# terminal and to reset the command history so that the command that
+# was interrupted is not entered in the history.
+
+I ^\r?\n$
+p :test-1:
+w echo first
+p :test-2:
+w stty intr ^C
+p :test-3:
+c echo bad\E
+s 400
+c \cC
+w echo scrambled
+p :test-4:
+w history
+u echo first
+r stty intr \^C
+r echo
+r history
+!
+
+# err_exit #
+tst $LINENO <<"!"
+L POSIX sh 097(C)
+
+# If the User Portability Utilities Option is supported and shell
+# command line editing is supported: When in insert mode a <newline>
+# causes the current command line to be executed.
+
+c echo ok\n
+u ^ok\r?\n$
+!
+
+# err_exit #
+tst $LINENO <<"!"
+L POSIX sh 099(C)
+
+# If the User Portability Utilities Option is supported and shell
+# command line editing is supported: When in insert mode the interrupt
+# character causes sh to terminate command line editing on the current
+# command line, re-issue the prompt on the next line of the terminal
+# and to reset the command history so that the command that was
+# interrupted is not entered in the history.
+
+I ^\r?\n$
+p :test-1:
+w echo first
+u ^first
+p :test-2:
+w stty intr ^C
+r
+p :test-3:
+c echo bad\cC
+w echo last
+p :test-4:
+w history
+u echo first
+r stty intr \^C
+r echo last
+r history
+!
+
+# err_exit #
+tst $LINENO <<"!"
+L POSIX sh 100(C)
+
+# If the User Portability Utilities Option is supported and shell
+# command line editing is supported: When in insert mode the kill
+# character clears all the characters from the input line.
+
+p :test-1:
+w stty kill ^X
+p :test-2:
+c echo bad\cX
+w echo ok
+u ^ok\r?\n$
+!
+
+# err_exit #
+tst $LINENO <<"!"
+L POSIX sh 101(C)
+
+# If the User Portability Utilities Option is supported and shell
+# command line editing is supported: When in insert mode a control-V
+# causes the next character to be inserted even in the case that the
+# character is a special insert mode character.
+# Testing Requirements: The assertion must be tested with at least the
+# following set of characters: <newline>, erase, interrupt, kill,
+# control-V, control-W, end-of-file, backslash \ (followed by erase or
+# kill) and <ESC>.
+
+d 10
+p :test-1:
+w stty erase ^H intr ^C kill ^X
+p :test-2:
+w echo erase=:\cV\cH:
+u ^erase=:\r?\n$
+p :test-3:
+w echo kill=:\cV\cX:
+u ^kill=:\cX:\r?\n$
+p :test-4:
+w echo control-V=:\cV\cV:
+u ^control-V=:\cV:\r?\n$
+p :test-5:
+w echo control-W:\cV\cW:
+u ^control-W:\cW:\r?\n$
+p :test-6:
+w echo EOF=:\cV\cD:
+u ^EOF=:\004:\r?\n$
+p :test-7:
+w echo backslash-erase=:\\\cH:
+u ^backslash-erase=:\r?\n$
+p :test-8:
+w echo backslash-kill=:\\\cX:
+u ^backslash-kill=:\cX:\r?\n$
+p :test-9:
+w echo ESC=:\cV\E:
+u ^ESC=:\E:\r?\n$
+p :test-10:
+w echo interrupt=:\cV\cC:
+u ^interrupt=:\cC:\r?\n$
+!
+
+# err_exit #
+tst $LINENO <<"!"
+L POSIX sh 104(C)
+
+# If the User Portability Utilities Option is supported and shell
+# command line editing is supported: When in insert mode an
+# end-of-file at the beginning of an input line is interpreted as the
+# end of input.
+
+p :test-1:
+w trap 'echo done >&2' EXIT
+p :test-2:
+s 100
+c \cD
+u ^done\r?\n$
+!
+
+# err_exit #
+tst $LINENO <<"!"
+L POSIX sh 111(C)
+
+# If the User Portability Utilities Option is supported and shell
+# command line editing is supported: When in command mode, # inserts
+# the character # at the beginning of the command line and causes the
+# line to be treated as a comment and the line is entered in the
+# command history.
+
+p :test-1:
+c echo save\E
+s 400
+c #
+p :test-2:
+w history
+u #echo save
+r history
+!
+
+# err_exit #
+tst $LINENO <<"!"
+L POSIX sh 137(C)
+
+# If the User Portability Utilities Option is supported and shell
+# command line editing is supported: When in command mode, then v
+# invokes the vi editor to edit the current command line in a temporary
+# file. When the editor exits, the commands in the temporary file are
+# executed.
+
+p :test-1:
+c echo hello\E
+s 400
+c v
+u /tmp/
+c A world\E
+s 400
+w :wq
+u ^hello world\r?\n$
+!
+
+# err_exit #
+tst $LINENO <<"!"
+L POSIX sh 251(C)
+
+# If the User Portability Utilities Option is supported and shell
+# command line editing is supported: When in command mode, then the
+# command N repeats the most recent / or ? command, reversing the
+# direction of the search.
+
+p :test-1:
+w echo repeat-1
+u ^repeat-1\r?\n$
+p :test-2:
+w echo repeat-2
+u ^repeat-2\r?\n$
+p :test-3:
+s 100
+c \E
+s 400
+w /rep
+u echo repeat-2
+c n
+r echo repeat-1
+c N
+r echo repeat-2
+w dd
+p :test-3:
+w echo repeat-3
+u ^repeat-3\r?\n$
+p :test-4:
+s 100
+c \E
+s 400
+w ?rep
+r echo repeat-2
+c N
+r echo repeat-1
+c n
+r echo repeat-2
+c n
+r echo repeat-3
+!
+
+# err_exit #
+whence -q less &&
+TERM=vt100 tst $LINENO <<"!"
+L process/terminal group exercise
+
+w m=yes; while true; do echo $m-$m; done | less
+u :$|:\E|lines
+c \cZ
+r Stopped
+w fg
+u yes-yes
+!
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/quoting.sh b/src/cmd/ksh93/tests/quoting.sh
new file mode 100755
index 0000000..01aae0d
--- /dev/null
+++ b/src/cmd/ksh93/tests/quoting.sh
@@ -0,0 +1,369 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ (( Errors++ ))
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+if [[ 'hi there' != "hi there" ]]
+then err_exit "single quotes not the same as double quotes"
+fi
+x='hi there'
+if [[ $x != 'hi there' ]]
+then err_exit "$x not the same as 'hi there'"
+fi
+if [[ $x != "hi there" ]]
+then err_exit "$x not the same as \"hi there \""
+fi
+if [[ \a\b\c\*\|\"\ \\ != 'abc*|" \' ]]
+then err_exit " \\ differs from '' "
+fi
+if [[ "ab\'\"\$(" != 'ab\'\''"$(' ]]
+then err_exit " \"\" differs from '' "
+fi
+if [[ $(print -r - 'abc*|" \') != 'abc*|" \' ]]
+then err_exit "\$(print -r - '') differs from ''"
+fi
+if [[ $(print -r - "abc*|\" \\") != 'abc*|" \' ]]
+then err_exit "\$(print -r - '') differs from ''"
+fi
+if [[ "$(print -r - 'abc*|" \')" != 'abc*|" \' ]]
+then err_exit "\"\$(print -r - '')\" differs from ''"
+fi
+if [[ "$(print -r - "abc*|\" \\")" != 'abc*|" \' ]]
+then err_exit "\"\$(print -r - "")\" differs from ''"
+fi
+if [[ $(print -r - $(print -r - 'abc*|" \')) != 'abc*|" \' ]]
+then err_exit "nested \$(print -r - '') differs from ''"
+fi
+if [[ "$(print -r - $(print -r - 'abc*|" \'))" != 'abc*|" \' ]]
+then err_exit "\"nested \$(print -r - '')\" differs from ''"
+fi
+if [[ $(print -r - "$(print -r - 'abc*|" \')") != 'abc*|" \' ]]
+then err_exit "nested \"\$(print -r - '')\" differs from ''"
+fi
+unset x
+if [[ ${x-$(print -r - "abc*|\" \\")} != 'abc*|" \' ]]
+then err_exit "\${x-\$(print -r - '')} differs from ''"
+fi
+if [[ ${x-$(print -r - "a}c*|\" \\")} != 'a}c*|" \' ]]
+then err_exit "\${x-\$(print -r - '}')} differs from ''"
+fi
+x=$((echo foo)|(cat))
+if [[ $x != foo ]]
+then err_exit "((cmd)|(cmd)) failed"
+fi
+x=$(print -r -- "\"$HOME\"")
+if [[ $x != '"'$HOME'"' ]]
+then err_exit "nested double quotes failed"
+fi
+unset z
+: ${z="a{b}c"}
+if [[ $z != 'a{b}c' ]]
+then err_exit '${z="a{b}c"} not correct'
+fi
+unset z
+: "${z="a{b}c"}"
+if [[ $z != 'a{b}c' ]]
+then err_exit '"${z="a{b}c"}" not correct'
+fi
+if [[ $(print -r -- "a\*b") != 'a\*b' ]]
+then err_exit '$(print -r -- "a\*b") differs from a\*b'
+fi
+unset x
+if [[ $(print -r -- "a\*b$x") != 'a\*b' ]]
+then err_exit '$(print -r -- "a\*b$x") differs from a\*b'
+fi
+x=hello
+set -- ${x+foo bar bam}
+if (( $# !=3 ))
+then err_exit '${x+foo bar bam} does not yield three arguments'
+fi
+set -- ${x+foo "bar bam"}
+if (( $# !=2 ))
+then err_exit '${x+foo "bar bam"} does not yield two arguments'
+fi
+set -- ${x+foo 'bar bam'}
+if (( $# !=2 ))
+then err_exit '${x+foo '\''bar bam'\''} does not yield two arguments'
+fi
+set -- ${x+foo $x bam}
+if (( $# !=3 ))
+then err_exit '${x+foo $x bam} does not yield three arguments'
+fi
+set -- ${x+foo "$x" bam}
+if (( $# !=3 ))
+then err_exit '${x+foo "$x" bam} does not yield three arguments'
+fi
+set -- ${x+"foo $x bam"}
+if (( $# !=1 ))
+then err_exit '${x+"foo $x bam"} does not yield one argument'
+fi
+set -- "${x+foo $x bam}"
+if (( $# !=1 ))
+then err_exit '"${x+foo $x bam}" does not yield one argument'
+fi
+set -- ${x+foo "$x "bam}
+if (( $# !=2 ))
+then err_exit '${x+foo "$x "bam} does not yield two arguments'
+fi
+x="ab$'cd"
+if [[ $x != 'ab$'"'cd" ]]
+then err_exit '$'"' inside double quotes not working"
+fi
+x=`print 'ab$'`
+if [[ $x != 'ab$' ]]
+then err_exit '$'"' inside `` quotes not working"
+fi
+unset a
+x=$(print -r -- "'\
+\
+")
+if [[ $x != "'" ]]
+then err_exit 'line continuation in double strings not working'
+fi
+x=$(print -r -- "'\
+$a\
+")
+if [[ $x != "'" ]]
+then err_exit 'line continuation in expanded double strings not working'
+fi
+x='\*'
+if [[ $(print -r -- $x) != '\*' ]]
+then err_exit 'x="\\*";$x != \*'
+fi
+x=' hello world '
+set -- $x
+if (( $# != 2 ))
+then err_exit 'field splitting error'
+fi
+x=$(print -r -- '1234567890123456789012345678901234567890123456789012345678901234567890 \
+1234567890123456789012345678901234567890123456789012345678901234567890 \
+1234567890123456789012345678901234567890123456789012345678901234567890 \
+1234567890123456789012345678901234567890123456789012345678901234567890 \
+1234567890123456789012345678901234567890123456789012345678901234567890 \
+1234567890123456789012345678901234567890123456789012345678901234567890 \
+1234567890123456789012345678901234567890123456789012345678901234567890 \
+1234567890123456789012345678901234567890123456789012345678901234567890 \
+1234567890123456789012345678901234567890123456789012345678901234567890 \
+1234567890123456789012345678901234567890123456789012345678901234567890 \
+1234567890123456789012345678901234567890123456789012345678901234567890 \
+1234567890123456789012345678901234567890123456789012345678901234567890 \
+1234567890123456789012345678901234567890123456789012345678901234567890 \
+1234567890123456789012345678901234567890123456789012345678901234567890 \
+1234567890123456789012345678901234567890123456789012345678901234567890')
+if (( ${#x} != (15*73-3) ))
+then err_exit "length of x, ${#x}, is incorrect should be $((15*73-3))"
+fi
+x='$hi'
+if [[ $x\$ != '$hi$' ]]
+then err_exit ' $x\$, with x=$hi, does not expand to $hi$'
+fi
+if [[ $x$ != '$hi$' ]]
+then err_exit ' $x$, with x=$hi, does not expand to $hi$'
+fi
+set -- $(/bin/echo foo;sleep 1;/bin/echo bar)
+if [[ $# != 2 ]]
+then err_exit 'word splitting after command substitution not working'
+fi
+unset q
+if [[ "${q:+'}q${q:+'}" != q ]]
+then err_exit 'expansion of "{q:+'\''}" not correct when q unset'
+fi
+q=1
+if [[ "${q:+'}q${q:+'}" != "'q'" ]]
+then err_exit 'expansion of "{q:+'\''}" not correct when q set'
+fi
+x=$'x\' #y'
+if [[ $x != "x' #y" ]]
+then err_exit "$'x\' #y'" not working
+fi
+x=$q$'x\' #y'
+if [[ $x != "1x' #y" ]]
+then err_exit "$q$'x\' #y'" not working
+fi
+IFS=,
+x='a,b\,c,d'
+set -- $x
+if [[ $2 != 'b\' ]]
+then err_exit "field splitting of $x with IFS=$IFS not working"
+fi
+foo=bar
+bar=$(print -r -- ${foo+\\n\ })
+if [[ $bar != '\n ' ]]
+then err_exit '${foo+\\n\ } expansion error'
+fi
+unset bar
+bar=$(print -r -- ${foo+\\n\ $bar})
+if [[ $bar != '\n ' ]]
+then err_exit '${foo+\\n\ $bar} expansion error with bar unset'
+fi
+x='\\(..\\)|&\|\|\\&\\|'
+if [[ $(print -r -- $x) != "$x" ]]
+then err_exit '$x, where x=\\(..\\)|&\|\|\\&\\| not working'
+fi
+x='\\('
+if [[ $(print -r -- a${x}b) != a"${x}"b ]]
+then err_exit 'a${x}b, where x=\\( not working'
+fi
+x=
+if [[ $(print -r -- $x'\\1') != '\\1' ]]
+then err_exit 'backreference inside single quotes broken'
+fi
+set -- ''
+set -- "$@"
+if (( $# != 1 ))
+then err_exit '"$@" not preserving nulls'
+fi
+x=
+if [[ $(print -r s"!\2${x}\1\a!") != 's!\2\1\a!' ]]
+then err_exit 'print -r s"!\2${x}\1\a!" not equal s!\2\1\a!'
+fi
+if [[ $(print -r $'foo\n\n\n') != foo ]]
+then err_exit 'trailing newlines on comsubstitution not removed'
+fi
+unset x
+if [[ ${x:='//'} != '//' ]]
+then err_exit '${x:='//'} != "//"'
+fi
+if [[ $(print -r "\"hi$\"") != '"hi$"' ]]
+then err_exit '$\ not correct inside ""'
+fi
+unset x
+if [[ "${x-a\}b}" != 'a}b' ]]
+then err_exit '"${x-a\}b}" != "a}b"'
+fi
+if [[ "\}\]$x\*\{\[\\" != '\}\]\*\{\[\' ]]
+then err_exit '"\}\]$x\*\{\[\\" != "\}\]\*\{\[\"'
+fi
+foo=yes
+if [[ $(print -r -- {\$foo}) != '{$foo}' ]]
+then err_exit '{\$foo}' not expanded correctly
+fi
+[[ foo == $(
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+print foo) ]] || err_exit "command subsitution with long comments broken"
+subject='some/other/words'
+re='@(?*)/@(?*)/@(?*)'
+[[ ${subject/${re}/\3} != words ]] && err_exit 'string replacement with \3 not working'
+[[ ${subject/${re}/'\3'} != '\3' ]] && err_exit 'string replacement with '"'\3'"' not working'
+[[ ${subject/${re}/"\\3"} != '\3' ]] && err_exit 'string replacement with "\\3" not working'
+[[ ${subject/${re}/"\3"} != '\3' ]] && err_exit 'string replacement with "\3" not working'
+string='\3'
+[[ ${subject/${re}/${string}} != words ]] && err_exit 'string replacement with $string not working with string=\3'
+[[ $(print -r "${subject/${re}/${string}}") != words ]] && err_exit 'string replacement with $string not working with string=\3 using print'
+[[ ${subject/${re}/"${string}"} != '\3' ]] && err_exit 'string replacement with "$string" not working with string=\3'
+[[ $(print -r "${subject/${re}/"${string}"}") != '\3' ]] && err_exit 'string replacement with "$string" not working with string=\3 using print'
+string='\\3'
+[[ ${subject/${re}/${string}} != '\3' ]] && err_exit 'string replacement with $string not working with string=\\3'
+[[ ${subject/${re}/"${string}"} != '\\3' ]] && err_exit 'string replacement with "$string" not working with string=\\3'
+[[ ${subject/${re}/\4} != '\4' ]] && err_exit 'string replacement with \4 not working'
+[[ ${subject/${re}/'\4'} != '\4' ]] && err_exit 'string replacement with '\4' not working'
+string='\4'
+[[ ${subject/${re}/${string}} != '\4' ]] && err_exit 'string replacement with $string not working with string=\4'
+[[ ${subject/${re}/"${string}"} != '\4' ]] && err_exit 'string replacement with "$string" not working with string=\4'
+string='&foo'
+[[ ${subject/${re}/${string}} != '&foo' ]] && err_exit 'string replacement with $string not working with string=&foo'
+[[ ${subject/${re}/"${string}"} != '&foo' ]] && err_exit 'string replacement with "$string" not working with string=&foo'
+{
+x=x
+x=${x:-`id | sed 's/^[^(]*(\([^)]*\)).*/\1/'`}
+} 2> /dev/null || err_exit 'skipping over `` failed'
+[[ $x == x ]] || err_exit 'assignment ${x:=`...`} failed'
+[[ $($SHELL -c 'print a[') == 'a[' ]] || err_exit "unbalanced '[' in command arg fails"
+$SHELL -c $'false && (( `wc -l /dev/null | nawk \'{print $1}\'` > 2 )) && true;:' 2> /dev/null || err_exit 'syntax error with ` in arithmetic expression'
+{ $SHELL -c '(( 1`: "{ }"` ))' ;} 2> /dev/null || err_exit 'problem with ` inside (())'
+varname=foobarx
+x=`print '"\$'${varname}'"'`
+[[ $x == '"$foobarx"' ]] || err_exit $'\\$\' not handled correctly inside ``'
+
+copy1=5 copynum=1
+foo="`eval echo "$"{copy$copynum"-0}"`"
+[[ $foo == "$copy1" ]] || err_exit '$"..." not being ignored inside ``'
+
+[[ $($SHELL -c 'set -- ${1+"$@"}; print $#' cmd '') == 1 ]] || err_exit '${1+"$@"} with one empty argument fails'
+[[ $($SHELL -c 'set -- ${1+"$@"}; print $#' cmd foo '') == 2 ]] || err_exit '${1+"$@"} with one non-empty and on empty argument fails'
+[[ $($SHELL -c 'set -- ${1+"$@"}; print $#' cmd "" '') == 2 ]] || err_exit '${1+"$@"} with two empty arguments fails'
+[[ $($SHELL -c 'set -- ${1+"$@"}; print $#' cmd "" '' '') == 3 ]] || err_exit '${1+"$@"} with three empty arguments fails'
+[[ $($SHELL -c 'set -- "$@"; print $#' cmd '') == 1 ]] || err_exit '"$@" with one empty argument fails'
+[[ $($SHELL -c 'set -- "${@:2}"; print $#' cmd '') == 0 ]] || err_exit '"$@" with one empty argument fails'
+[[ $($SHELL -c 'set -- "$@"; print $#' cmd foo '') == 2 ]] || err_exit '"$@" with one non-empty and on empty argument fails'
+[[ $($SHELL -c 'set -- "$@"; print $#' cmd "" '') == 2 ]] || err_exit '"$@" with two empty arguments fails'
+[[ $($SHELL -c 'set -- "$@"; print $#' cmd "" '' '') == 3 ]] || err_exit '"$@" with three empty arguments fails'
+args=('')
+set -- "${args[@]}"
+[[ $# == 1 ]] || err_exit '"${args[@]}"} with one empty argument fails'
+set -- ${1+"${args[@]}"}
+[[ $# == 1 ]] || err_exit '${1+"${args[@]}"} with one empty argument fails'
+args=(foo '')
+set -- "${args[@]}"
+[[ $# == 2 ]] || err_exit '"${args[@]}"} with one non-empty and one empty argument fails'
+set -- ${1+"${args[@]}"}
+[[ $# == 2 ]] || err_exit '${1+"${args[@]}"} with one non-empty and one empty argument fails'
+
+unset ARGS
+set --
+ARGS=("$@")
+set -- "${ARGS[@]}"
+(( $# )) && err_exit 'set -- "${ARGS[@]}" for empty array should not produce arguments'
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/quoting2.sh b/src/cmd/ksh93/tests/quoting2.sh
new file mode 100755
index 0000000..bc7380d
--- /dev/null
+++ b/src/cmd/ksh93/tests/quoting2.sh
@@ -0,0 +1,215 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+set -o noglob
+if [[ 'hi there' != "hi there" ]]
+then err_exit "single quotes not the same as double quotes"
+fi
+x='hi there'
+if [[ $x != 'hi there' ]]
+then err_exit "$x not the same as 'hi there'"
+fi
+if [[ $x != "hi there" ]]
+then err_exit "$x not the same as \"hi there \""
+fi
+if [[ \a\b\c\*\|\"\ \\ != 'abc*|" \' ]]
+then err_exit " \\ differs from '' "
+fi
+if [[ "ab\'\"\$(" != 'ab\'\''"$(' ]]
+then err_exit " \"\" differs from '' "
+fi
+if [[ $(print -r - 'abc*|" \') != 'abc*|" \' ]]
+then err_exit "\$(print -r - '') differs from ''"
+fi
+if [[ $(print -r - "abc*|\" \\") != 'abc*|" \' ]]
+then err_exit "\$(print -r - '') differs from ''"
+fi
+if [[ "$(print -r - 'abc*|" \')" != 'abc*|" \' ]]
+then err_exit "\"\$(print -r - '')\" differs from ''"
+fi
+if [[ "$(print -r - "abc*|\" \\")" != 'abc*|" \' ]]
+then err_exit "\"\$(print -r - "")\" differs from ''"
+fi
+if [[ $(print -r - "$(print -r - 'abc*|" \')") != 'abc*|" \' ]]
+then err_exit "nested \$(print -r - '') differs from ''"
+fi
+if [[ "$(print -r - $(print -r - 'abc*|" \'))" != 'abc*|" \' ]]
+then err_exit "\"nested \$(print -r - '')\" differs from ''"
+fi
+if [[ $(print -r - "$(print -r - 'abc*|" \')") != 'abc*|" \' ]]
+then err_exit "nested \"\$(print -r - '')\" differs from ''"
+fi
+unset x
+if [[ ${x-$(print -r - "abc*|\" \\")} != 'abc*|" \' ]]
+then err_exit "\${x-\$(print -r - '')} differs from ''"
+fi
+if [[ ${x-$(print -r - "a}c*|\" \\")} != 'a}c*|" \' ]]
+then err_exit "\${x-\$(print -r - '}')} differs from ''"
+fi
+x=$((echo foo)|(cat))
+if [[ $x != foo ]]
+then err_exit "((cmd)|(cmd)) failed"
+fi
+x=$(print -r -- "\"$HOME\"")
+if [[ $x != '"'$HOME'"' ]]
+then err_exit "nested double quotes failed"
+fi
+unset z
+: ${z="a{b}c"}
+if [[ $z != 'a{b}c' ]]
+then err_exit '${z="a{b}c"} not correct'
+fi
+unset z
+: "${z="a{b}c"}"
+if [[ $z != 'a{b}c' ]]
+then err_exit '"${z="a{b}c"}" not correct'
+fi
+if [[ $(print -r -- "a\*b") != 'a\*b' ]]
+then err_exit '$(print -r -- "a\*b") differs from a\*b'
+fi
+unset x
+if [[ $(print -r -- "a\*b$x") != 'a\*b' ]]
+then err_exit '$(print -r -- "a\*b$x") differs from a\*b'
+fi
+x=hello
+set -- ${x+foo bar bam}
+if (( $# !=3 ))
+then err_exit '${x+foo bar bam} does not yield three arguments'
+fi
+set -- ${x+foo "bar bam"}
+if (( $# !=2 ))
+then err_exit '${x+foo "bar bam"} does not yield two arguments'
+fi
+set -- ${x+foo 'bar bam'}
+if (( $# !=2 ))
+then err_exit '${x+foo '\''bar bam'\''} does not yield two arguments'
+fi
+set -- ${x+foo $x bam}
+if (( $# !=3 ))
+then err_exit '${x+foo $x bam} does not yield three arguments'
+fi
+set -- ${x+foo "$x" bam}
+if (( $# !=3 ))
+then err_exit '${x+foo "$x" bam} does not yield three arguments'
+fi
+set -- ${x+"foo $x bam"}
+if (( $# !=1 ))
+then err_exit '${x+"foo $x bam"} does not yield one argument'
+fi
+set -- "${x+foo $x bam}"
+if (( $# !=1 ))
+then err_exit '"${x+foo $x bam}" does not yield one argument'
+fi
+set -- ${x+foo "$x "bam}
+if (( $# !=2 ))
+then err_exit '${x+foo "$x "bam} does not yield two arguments'
+fi
+x="ab$'cd"
+if [[ $x != 'ab$'"'cd" ]]
+then err_exit '$'"' inside double quotes not working"
+fi
+x=`print 'ab$'`
+if [[ $x != 'ab$' ]]
+then err_exit '$'"' inside `` quotes not working"
+fi
+unset a
+x=$(print -r -- "'\
+\
+")
+if [[ $x != "'" ]]
+then err_exit 'line continuation in double strings not working'
+fi
+x=$(print -r -- "'\
+$a\
+")
+if [[ $x != "'" ]]
+then err_exit 'line continuation in expanded double strings not working'
+fi
+x='\*'
+if [[ $(print -r -- $x) != '\*' ]]
+then err_exit 'x="\\*";$x != \*'
+fi
+if [[ $(print -r -- "\}" ) != '\}' ]]
+then err_exit '(print -r -- "\}"' not working
+fi
+if [[ $(print -r -- "\{" ) != '\{' ]]
+then err_exit 'print -r -- "\{"' not working
+fi
+# The following caused a syntax error on earlier versions
+foo=foo x=-
+if [[ `eval print \\${foo$x}` != foo* ]]
+then err_exit '`eval print \\${foo$x}`' not working
+fi
+if [[ "`eval print \\${foo$x}`" != foo* ]]
+then err_exit '"`eval print \\${foo$x}`"' not working
+fi
+if ( [[ $() != '' ]] )
+then err_exit '$() not working'
+fi
+x=a:b:c
+set -- $( IFS=:; print $x)
+if (( $# != 3))
+then err_exit 'IFS not working correctly with command substitution'
+fi
+$SHELL -n 2> /dev/null << \! || err_exit '$(...) bug with ( in comment'
+y=$(
+ # ( this line is a bug fix
+ print hi
+)
+!
+x=
+for j in glob noglob
+do for i in 'a\*b' 'a\ b' 'a\bc' 'a\*b' 'a\"b'
+ do eval [[ '$('print -r -- \'$i\'\$x')' != "'$i'" ]] && err_exit "quoting of $i\$x with $j enabled failed"
+ eval [[ '$('print -r -- \'$i\'\${x%*}')' != "'$i'" ]] && err_exit "quoting of $i\${x%*} with $j enabled failed"
+ if [[ $j == noglob ]]
+ then eval [[ '$('print -r -- \'$i\'\${x:-*}')' != "'$i''*'" ]] && err_exit "quoting of $i\${x:-*} with $j enabled failed"
+ fi
+ done
+ set -f
+done
+foo=foo
+[[ "$" == '$' ]] || err_exit '"$" != $'
+[[ "${foo}$" == 'foo$' ]] || err_exit 'foo=foo;"${foo}$" != foo$'
+[[ "${foo}${foo}$" == 'foofoo$' ]] || err_exit 'foo=foo;"${foo}${foo}$" != foofoo$'
+foo='$ '
+[[ "$foo" == ~(Elr)(\\\$|#)\ ]] || err_exit $'\'$ \' not matching RE \\\\\\$|#\''
+[[ "$foo" == ~(Elr)('\$'|#)\ ]] || err_exit $'\'$ \' not matching RE \'\\$\'|#\''
+foo='# '
+[[ "$foo" == ~(Elr)(\\\$|#)\ ]] || err_exit $'\'# \' not matching RE \\'\$|#\''
+[[ "$foo" == ~(Elr)('\$'|#)\ ]] || err_exit $'\'# \' not matching RE \'\\$\'|#\''
+[[ '\$' == '\$'* ]] || err_exit $'\'\\$\' not matching \'\\$\'*'
+[[ a+a == ~(E)a\+a ]] || err_exit '~(E)a\+a not matching a+a'
+[[ a+a =~ a\+a ]] || err_exit 'RE a\+a not matching a+a'
+
+exp='ac'
+got=$'a\0b'c
+[[ $got == "$exp" ]] || err_exit "\$'a\\0b'c expansion failed -- expected '$exp', got '$got'"
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/readcsv.sh b/src/cmd/ksh93/tests/readcsv.sh
new file mode 100644
index 0000000..9dd6d9c
--- /dev/null
+++ b/src/cmd/ksh93/tests/readcsv.sh
@@ -0,0 +1,65 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2012 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+tmp1=$tmp/tmp1.csv
+tmp2=$tmp/tmp2.csv
+cat > $tmp1 <<- \EOF
+ CAT,"CVE CCODE","NECA OCN",ST,LATA,AP,"New InterState
+ Orig","New Inter""""State
+ Term","New IntraState
+ Orig","New IntraState
+ Term"
+ CLEC,XXXX,AAAA,RB,ABC,comp," 0.2 "," 0.4 "," 0.6 "," 0.8 "
+ CLEC,YYYY,QQQQ,SX,123,mmmm," 0.3 "," 0.5 "," 0.7 "," 0.9 "
+EOF
+integer count=0 nfields
+IFS=${2-,}
+typeset -a arr
+while read -A -S arr
+do ((nfields=${#arr[@]}))
+ if ((++count==1))
+ then ((nfields==10)) || err_exit 'first record should contain 10 fields'
+ [[ ${arr[7]} == $'New Inter""State\nTerm' ]] || err_exit $'7th field of record 1 should contain New Inter""State\nTerm'
+ fi
+ for ((i=0; i < nfields;i++))
+ do delim=$IFS
+ if ((i == nfields-1))
+ then delim=$'\r\n'
+ fi
+ printf "%#q%s" "${arr[i]}" "$delim"
+ done
+done < $tmp1 > $tmp2
+diff "$tmp1" "$tmp2" >/dev/null 2>&1 || err_exit "files $tmp1 and $tmp2 differ"
+
+exit $((Errors<125?Errors:125))
+
diff --git a/src/cmd/ksh93/tests/recttype.sh b/src/cmd/ksh93/tests/recttype.sh
new file mode 100755
index 0000000..9f41d92
--- /dev/null
+++ b/src/cmd/ksh93/tests/recttype.sh
@@ -0,0 +1,70 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ (( Errors+=1 ))
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+typeset -T Pt_t=(
+ float x=1
+ float y=0
+ len()
+ {
+ print -r $((sqrt(_.x*_.x + _.y*_.y)))
+ }
+)
+
+typeset -T Rect_t=(
+ Pt_t ll=(x=0 y=0)
+ Pt_t ur=(x=1 y=1)
+ area()
+ {
+ print -r $(( abs((_.ur.x-_.ll.x)*(_.ur.y-_.ll.y)) ))
+ }
+)
+
+for ((i=0; i < 100; i++))
+do
+Rect_t r
+[[ ${r.area} == 1 ]] || err_exit '${r.area} != 1'
+Rect_t s=(
+ Pt_t ur=(x=9 y=9)
+ Pt_t ll=(x=7 y=7)
+)
+[[ ${s.ur.x} == 9 ]] || err_exit ' ${s.ur.x} != 9'
+(( s.ur.x == 9 ))|| err_exit ' ((s.ur.x)) != 9'
+[[ ${s.ll.y} == 7 ]] || err_exit '${s.ll.y} != 7'
+(( s.area == 4 )) || err_exit 'area of s should be 4'
+[[ ${s.area} == 4 ]] || err_exit '${s.area} != 4'
+unset r s
+done
+Rect_t -A r
+r[one]=(ur=(x=4 y=4))
+(( r[one].area == 16 )) || err_exit 'area of r[one] should be 16'
+[[ ${r[one].area} == 16 ]] || err_exit '${r[one].area} should be 16'
+unset r
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/restricted.sh b/src/cmd/ksh93/tests/restricted.sh
new file mode 100755
index 0000000..5699105
--- /dev/null
+++ b/src/cmd/ksh93/tests/restricted.sh
@@ -0,0 +1,83 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+# test restricted shell
+pwd=$PWD
+case $SHELL in
+/*) ;;
+*/*) SHELL=$pwd/$SHELL;;
+*) SHELL=$(whence "$SHELL");;
+esac
+function check_restricted
+{
+ rm -f out
+ LC_MESSAGES=C rksh -c "$@" 2> out > /dev/null
+ grep restricted out > /dev/null 2>&1
+}
+
+[[ $SHELL != /* ]] && SHELL=$pwd/$SHELL
+cd $tmp || err_exit "cd $tmp failed"
+ln -s $SHELL rksh
+PATH=$PWD:$PATH
+rksh -c '[[ -o restricted ]]' || err_exit 'restricted option not set'
+[[ $(rksh -c 'print hello') == hello ]] || err_exit 'unable to run print'
+check_restricted /bin/echo || err_exit '/bin/echo not resticted'
+check_restricted ./echo || err_exit './echo not resticted'
+check_restricted 'SHELL=ksh' || err_exit 'SHELL asignment not resticted'
+check_restricted 'PATH=/bin' || err_exit 'PATH asignment not resticted'
+check_restricted 'FPATH=/bin' || err_exit 'FPATH asignment not resticted'
+check_restricted 'ENV=/bin' || err_exit 'ENV asignment not resticted'
+check_restricted 'print > file' || err_exit '> file not restricted'
+> empty
+check_restricted 'print <> empty' || err_exit '<> file not restricted'
+print 'echo hello' > script
+chmod +x ./script
+! check_restricted script || err_exit 'script without builtins should run in restricted mode'
+check_restricted ./script || err_exit 'script with / in name should not run in restricted mode'
+print '/bin/echo hello' > script
+! check_restricted script || err_exit 'script with pathnames should run in restricted mode'
+print 'echo hello> file' > script
+! check_restricted script || err_exit 'script with output redirection should run in restricted mode'
+print 'PATH=/bin' > script
+! check_restricted script || err_exit 'script with PATH assignment should run in restricted mode'
+cat > script <<!
+#! $SHELL
+print hello
+!
+! check_restricted 'script;:' || err_exit 'script with #! pathname should run in restricted mode'
+! check_restricted 'script' || err_exit 'script with #! pathname should run in restricted mode even if last command in script'
+for i in PATH ENV FPATH
+do check_restricted "function foo { typeset $i=foobar;};foo" || err_exit "$i can be changed in function by using typeset"
+done
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/return.sh b/src/cmd/ksh93/tests/return.sh
new file mode 100755
index 0000000..8c243f5
--- /dev/null
+++ b/src/cmd/ksh93/tests/return.sh
@@ -0,0 +1,183 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+# test the behavior of return and exit with functions
+
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+unset HISTFILE
+
+foo=NOVAL bar=NOVAL
+file=$tmp/test
+function foo
+{
+ typeset foo=NOEXIT
+ trap "foo=EXIT;rm -f $file" EXIT
+ > $file
+ if (( $1 == 0 ))
+ then return $2
+ elif (( $1 == 1 ))
+ then exit $2
+ else bar "$@"
+ fi
+}
+
+function bar
+{
+ typeset bar=NOEXIT
+ trap 'bar=EXIT' EXIT
+ if (( $1 == 2 ))
+ then return $2
+ elif (( $1 == 3 ))
+ then exit $2
+ fi
+}
+
+function funcheck
+{
+ [[ $foo == EXIT ]] || err_exit "foo "$@" : exit trap not set"
+ if [[ -f $file ]]
+ then rm -r $file
+ err_exit "foo $@: doesn't remove $file"
+ fi
+ foo=NOVAL bar=NOVAL
+}
+
+(exit 0) || err_exit "exit 0 is not zero"
+(return 0) || err_exit "return 0 is not zero"
+(exit) || err_exit "default exit value is not zero"
+(return) || err_exit "default return value is not zero"
+(exit 35)
+ret=$?
+if (( $ret != 35 ))
+then err_exit "exit 35 is $ret not 35"
+fi
+(return 35)
+ret=$?
+if (( $ret != 35 ))
+then err_exit "return 35 is $ret not 35"
+fi
+
+foo 0 0 || err_exit "foo 0 0: incorrect return"
+funcheck 0 0
+foo 0 3
+ret=$?
+if (( $ret != 3 ))
+then err_exit "foo 0 3: return is $ret not 3"
+fi
+funcheck 0 3
+foo 2 0 || err_exit "foo 2 0: incorrect return"
+[[ $bar == EXIT ]] || err_exit "foo 2 0: bar exit trap not set"
+funcheck 2 0
+foo 2 3
+ret=$?
+if (( $ret != 3 ))
+then err_exit "foo 2 3: return is $ret not 3"
+fi
+[[ $bar == EXIT ]] || err_exit "foo 2 3: bar exit trap not set"
+funcheck 2 3
+(foo 3 3)
+ret=$?
+if (( $ret != 3 ))
+then err_exit "foo 3 3: return is $ret not 3"
+fi
+foo=EXIT
+funcheck 3 3
+cat > $file <<!
+return 3
+exit 4
+!
+( . $file )
+ret=$?
+if (( $ret != 3 ))
+then err_exit "return in dot script is $ret should be 3"
+fi
+chmod 755 $file
+( $file )
+ret=$?
+if (( $ret != 3 ))
+then err_exit "return in script is $ret should be 3"
+fi
+cat > $file <<!
+: line 1
+# next line should fail and cause an exit
+: > /
+exit 4
+!
+( . $file ; exit 5 ) 2> /dev/null
+ret=$?
+if (( $ret != 1 ))
+then err_exit "error in dot script is $ret should be 1"
+fi
+( $file; exit 5 ) 2> /dev/null
+ret=$?
+if (( $ret != 5 ))
+then err_exit "error in script is $ret should be 5"
+fi
+cat > $file <<\!
+print -r -- "$0"
+!
+x=$( . $file)
+if [[ $x != $0 ]]
+then err_exit "\$0 in a dot script is $x. Should be $0"
+fi
+x=$($SHELL -i --norc 2> /dev/null <<\!
+typeset -i x=1/0
+print hello
+!
+)
+if [[ $x != hello ]]
+then err_exit "interactive shell terminates with error in bltin"
+fi
+x=$( set -e
+ false
+ print bad
+ )
+if [[ $x != '' ]]
+then err_exit "set -e doesn't terminate script on error"
+fi
+x=$( set -e
+ trap 'exit 0' EXIT
+ false
+ print bad
+ )
+if (( $? != 0 ))
+then err_exit "exit 0 in trap should doesn't set exit value to 0"
+fi
+$SHELL <<\!
+trap 'exit 8' EXIT
+exit 1
+!
+if (( $? != 8 ))
+then err_exit "exit 8 in trap should set exit value to 8"
+fi
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/select.sh b/src/cmd/ksh93/tests/select.sh
new file mode 100755
index 0000000..07d0bde
--- /dev/null
+++ b/src/cmd/ksh93/tests/select.sh
@@ -0,0 +1,67 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+PS3='ABC '
+
+cat > $tmp/1 <<\!
+1) foo
+2) bar
+3) bam
+!
+
+select i in foo bar bam
+do case $i in
+ foo) break;;
+ *) err_exit "select 1 not working"
+ break;;
+ esac
+done 2> /dev/null <<!
+1
+!
+
+unset i
+select i in foo bar bam
+do case $i in
+ foo) err_exit "select foo not working" 2>&3
+ break;;
+ *) if [[ $REPLY != foo ]]
+ then err_exit "select REPLY not correct" 2>&3
+ fi
+ ( set -u; : $i ) || err_exit "select: i not set to null" 2>&3
+ break;;
+ esac
+done 3>&2 2> $tmp/2 <<!
+foo
+!
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/shtests b/src/cmd/ksh93/tests/shtests
new file mode 100755
index 0000000..5815aab
--- /dev/null
+++ b/src/cmd/ksh93/tests/shtests
@@ -0,0 +1,235 @@
+: ksh regression test harness :
+
+USAGE_LICENSE="[-author?David Korn <dgk@research.att.com>][-author?Glenn Fowler <gsf@research.att.com>][-copyright?Copyright (c) 2000-2011 AT&T Intellectual Property][-license?http://www.opensource.org/licenses/cpl1.0.txt]"
+
+command=shtests
+
+setslocale='*@(locale).sh'
+timesensitive='*@(options|sigchld|subshell).sh'
+
+USAGE=$'
+[-s8?
+@(#)$Id: shtests (AT&T Research) 2011-08-08 $
+]
+'$USAGE_LICENSE$'
+[+NAME?shtests - ksh regression test harness]
+[+DESCRIPTION?\bshtests\b is the \bksh\b(1) regression test harness for
+ \b$SHELL\b or \bksh\b if \bSHELL\b is not defined and exported. If
+ none of the \b--posix --utf8 --compile\b options are specified then
+ all three are enabled.]
+[+INPUT FILES?\bshtests\b regression test files are shell scripts that
+ run in an environment controlled by \bshtests\b. An identification
+ message is printed before and after each test on the standard output.
+ The default environment settings are:]
+ {
+ [+unset LANG]
+ [+unset LC_ALL]
+ [+LC_NUMERIC=C?\b.\b radix point assumed by all test scripts.]
+ [+VMALLOC_OPTIONS=abort?\bvmalloc\b(1) arena checking enabled
+ with \babort(2)\b on error.]
+ }
+[c:compile?Run test scripts using \bshcomp\b(1).]
+[d:debug?Enable \bshtests\b execution trace.]
+[l:locale?Disable \b--utf8\b and run the \b--posix\b and \b--compile\b
+ tests, if enabled, in the locale of the caller. This may cause invalid
+ regressions, especially for locales where \b.\b is not the radix
+ point.]
+[p:posix?Run the test scripts in the posix/C locale.]
+[t!:time?Include the current date/time in the test identification
+ messages.]
+[u:utf8?Run the test scripts in the ast-specific C.UTF-8 locale.]
+[v!:vmalloc_options?Run tests with \bVMALLOC_OPTIONS=abort\b. Test
+ script names matching \b'$timesensitive$'\b are run with
+ \bVMALLOC_OPTIONS\b unset.]
+[x:trace?Enable script execution trace.]
+
+[ test.sh ... ] [ name=value ... ]
+
+[+SEE ALSO?\bksh\b(1), \bregress\b(1), \brt\b(1)]
+'
+
+function usage
+{
+ OPTIND=0
+ getopts -a $command "$USAGE" OPT '--??long'
+ exit 2
+}
+
+unset DISPLAY ENV FIGNORE HISTFILE
+trap + PIPE # unadvertized -- set SIGPIPE to SIG_DFL #
+
+integer compile=0 debug=0 locale=0 posix=0 time=1 utf8=0
+typeset vmalloc_options=abort trace=
+vmalloc_options= #XXX# until multi-region vmalloc trace fixed #XXX#
+
+while getopts -a $command "$USAGE" OPT
+do case $OPT in
+ c) if (( $OPTARG ))
+ then compile=2
+ else compile=0
+ fi
+ ;;
+ d) debug=$OPTARG
+ ;;
+ l) locale=$OPTARG
+ ;;
+ p) posix=$OPTARG
+ ;;
+ t) time=$OPTARG
+ ;;
+ u) utf8=$OPTARG
+ ;;
+ v) if (( OPTARG ))
+ then vmalloc_options=abort
+ else vmalloc_options=
+ fi
+ ;;
+ x) trace=-x
+ ;;
+ *) usage
+ ;;
+ esac
+done
+shift $OPTIND-1
+
+if (( debug )) || [[ $trace ]]
+then export PS4=':$LINENO: '
+ if (( debug ))
+ then set -x
+ fi
+fi
+
+while [[ $1 == *=* ]]
+do eval export "$1"
+ shift
+done
+
+if (( !compile && !posix && !utf8 ))
+then compile=1
+ posix=1
+ utf8=1
+fi
+if (( locale ))
+then utf8=0
+ if [[ $LC_ALL ]]
+ then export LANG=$LC_ALL
+ fi
+else unset LANG LC_ALL
+ export LC_NUMERIC=C
+fi
+if [[ $VMALLOC_OPTIONS ]]
+then vmalloc_options=$VMALLOC_OPTIONS
+else VMALLOC_OPTIONS=$vmalloc_options
+fi
+[[ $VMALLOC_OPTIONS ]] || timesensitive=.
+export PATH PWD SHCOMP SHELL VMALLOC_OPTIONS
+PWD=$(pwd)
+SHELL=${SHELL-ksh}
+case $0 in
+/*) d=$(dirname $0);;
+*/*) d=$PWD/$(dirname $0);;
+*) d=$PWD;;
+esac
+case $SHELL in
+/*) ;;
+*/*) SHELL=$d/$SHELL;;
+*) SHELL=$(whence $SHELL);;
+esac
+PATH=/bin:/usr/bin
+if [[ -d /usr/ucb ]]
+then PATH=$PATH:/usr/ucb
+fi
+PATH=$PATH:$d
+if [[ $INSTALLROOT && -r $INSTALLROOT/bin/.paths ]]
+then PATH=$INSTALLROOT/bin:$PATH
+fi
+if [[ ${SHELL%/*} != $INSTALLROOT/bin ]]
+then PATH=${SHELL%/*}:$PATH
+fi
+if [[ ! $SHCOMP ]]
+then s=${SHELL:##*sh}
+ s=${SHELL:%/*}/shcomp$s
+ if [[ -x $s ]]
+ then SHCOMP=$s
+ elif [[ -x ${s%-g} ]]
+ then SHCOMP=${s%-g}
+ else SHCOMP=shcomp
+ fi
+fi
+if (( compile ))
+then if whence $SHCOMP > /dev/null
+ then tmp=$(mktemp -dt) || { echo mktemp -dt failed >&2; exit 1; }
+ trap "cd /; rm -rf $tmp" EXIT
+ elif (( compile > 1 ))
+ then echo $0: --compile: $SHCOMP not found >&2
+ exit 1
+ else compile=0
+ fi
+fi
+typeset -A tests
+for i in ${*-*.sh}
+do if [[ ! -r $i ]]
+ then echo $0: $i: not found >&2
+ continue
+ fi
+ t=$(grep -c err_exit $i)
+ if (( t > 2 ))
+ then (( t = t - 2 ))
+ fi
+ tests[$i]=$t
+ T=test
+ if (( t != 1 ))
+ then T=${T}s
+ fi
+ u=${i##*/}
+ u=${u%.sh}
+ if [[ $i == $timesensitive ]]
+ then VMALLOC_OPTIONS=
+ fi
+ if (( posix || utf8 ))
+ then locales=
+ (( posix )) && locales+=" ${LANG:-C}"
+ [[ $utf8 == 0 || $i == $setslocale ]] || locales+=" C.UTF-8"
+ for lang in $locales
+ do o=$u
+ if [[ $lang == C ]]
+ then lang=
+ else o="$o($lang)"
+ lang=LANG=$lang
+ fi
+ echo test $o begins ${time:+"at $(date +%Y-%m-%d+%H:%M:%S)"}
+ E=error
+ if eval $lang \$SHELL \$trace \$i
+ then echo test $o passed ${time:+"at $(date +%Y-%m-%d+%H:%M:%S)"} "[ $t $T 0 ${E}s ]"
+ else e=$?
+ if (( e != 1 ))
+ then E=${E}s
+ fi
+ echo test $o failed ${time:+"at $(date +%Y-%m-%d+%H:%M:%S)"} with exit code $e "[ $t $T $e $E ]"
+ fi
+ done
+ fi
+ if (( compile ))
+ then c=$tmp/shcomp-$u.ksh
+ o="$u(shcomp)"
+ echo test $o begins ${time:+"at $(date +%Y-%m-%d+%H:%M:%S)"}
+ E=error
+ if $SHCOMP $i > $c
+ then if $SHELL $trace $c
+ then echo test $o passed ${time:+"at $(date +%Y-%m-%d+%H:%M:%S)"} "[ $t $T 0 ${E}s ]"
+ else e=$?
+ if (( e != 1 ))
+ then E=${E}s
+ fi
+ echo test $o failed ${time:+"at $(date +%Y-%m-%d+%H:%M:%S)"} with exit code $e "[ $t $T $e $E ]"
+ fi
+ else e=$?
+ t=1
+ T=test
+ echo test $o failed to compile ${time:+"at $(date +%Y-%m-%d+%H:%M:%S)"} with exit code $e "[ $t $T 1 $E ]"
+ fi
+ if [[ $i == $timesensitive ]]
+ then VMALLOC_OPTIONS=$vmalloc_options
+ fi
+ fi
+done
diff --git a/src/cmd/ksh93/tests/sigchld.sh b/src/cmd/ksh93/tests/sigchld.sh
new file mode 100755
index 0000000..d4dcee6
--- /dev/null
+++ b/src/cmd/ksh93/tests/sigchld.sh
@@ -0,0 +1,160 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2012 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ (( Errors+=1 ))
+}
+
+alias err_exit='err_exit $LINENO'
+
+float DELAY=${1:-0.2}
+integer FOREGROUND=10 BACKGROUND=2 Errors=0
+
+s=$($SHELL -c '
+integer i foreground=0 background=0
+float delay='$DELAY' d=0 s=0
+
+set --errexit
+
+trap "(( background++ ))" CHLD
+
+(( d = delay ))
+for ((i = 0; i < '$BACKGROUND'; i++))
+do sleep $d &
+ (( d *= 4 ))
+ (( s += d ))
+done
+for ((i = 0; i < '$FOREGROUND'; i++))
+do (( foreground++ ))
+ sleep $delay
+ (( s -= delay ))
+ $SHELL -c : > /dev/null # foreground does not generate SIGCHLD
+done
+if (( (s += delay) < 1 ))
+then (( s = 1 ))
+fi
+sleep $s
+wait
+print foreground=$foreground background=$background
+') || err_exit "test loop failed"
+
+eval $s
+
+(( foreground == FOREGROUND )) || err_exit "expected '$FOREGROUND foreground' -- got '$foreground' (DELAY=$DELAY)"
+(( background == BACKGROUND )) || err_exit "expected '$BACKGROUND background' -- got '$background' (DELAY=$DELAY)"
+
+set --noerrexit
+
+if [[ ${.sh.version} == Version?*([[:upper:]])J* ]]
+then
+
+ jobmax=4
+ got=$($SHELL -c '
+ JOBMAX='$jobmax' JOBCOUNT=$(('$jobmax'*2))
+ integer running=0 maxrunning=0
+ trap "((running--))" CHLD
+ for ((i=0; i<JOBCOUNT; i++))
+ do sleep 1 &
+ if ((++running > maxrunning))
+ then ((maxrunning=running))
+ fi
+ done
+ wait
+ print running=$running maxrunning=$maxrunning
+ ')
+ exp='running=0 maxrunning='$jobmax
+ [[ $got == $exp ]] || err_exit "SIGCHLD trap queueing failed -- expected '$exp', got '$got'"
+
+ got=$($SHELL -c '
+ typeset -A proc
+
+ trap "
+ print \${proc[\$!].name} \${proc[\$!].status} \$?
+ unset proc[\$!]
+ " CHLD
+
+ { sleep 3; print a; exit 1; } &
+ proc[$!]=( name=a status=1 )
+
+ { sleep 2; print b; exit 2; } &
+ proc[$!]=( name=b status=2 )
+
+ { sleep 1; print c; exit 3; } &
+ proc[$!]=( name=c status=3 )
+
+ while (( ${#proc[@]} ))
+ do sleep -s
+ done
+ ')
+ exp='c\nc 3 3\nb\nb 2 2\na\na 1 1'
+ [[ $got == $exp ]] || err_exit "SIGCHLD trap queueing failed -- expected $(printf %q "$exp"), got $(printf %q "$got")"
+
+fi
+
+{
+got=$( ( sleep 1;print $'\n') | $SHELL -c 'function handler { : ;}
+ trap handler CHLD; sleep .3 & IFS= read; print good')
+} 2> /dev/null
+[[ $got == good ]] || err_exit 'SIGCLD handler effects read behavior'
+
+set -- $(
+ (
+ $SHELL -xc $'
+ trap \'wait $!; print $! $?\' CHLD
+ { sleep 0.1; exit 9; } &
+ print $!
+ sleep 0.5
+ '
+ ) 2>/dev/null; print $?
+)
+if (( $# != 4 ))
+then err_exit "CHLD trap failed -- expected 4 args, got $#"
+elif (( $4 != 0 ))
+then err_exit "CHLD trap failed -- exit code $4"
+elif (( $1 != $2 ))
+then err_exit "child pid mismatch -- got '$1' != '$2'"
+elif (( $3 != 9 ))
+then err_exit "child status mismatch -- expected '9', got '$3'"
+fi
+
+trap '' CHLD
+integer d
+for ((d=0; d < 2000; d++))
+do if print foo | grep bar
+ then break
+ fi
+done
+(( d==2000 )) || err_exit "trap '' CHLD causes side effects d=$d"
+trap - CHLD
+
+tmp=$(mktemp -dt)
+trap 'rm -rf $tmp' EXIT
+x=$($SHELL 2> /dev/null -ic '/bin/notfound; sleep .5 & sleep 1;jobs')
+[[ $x == *Done* ]] || err_exit 'SIGCHLD blocked after notfound'
+x=$($SHELL 2> /dev/null -ic 'kill -0 12345678901234567876; sleep .5 & sleep 1;jobs')
+[[ $x == *Done* ]] || err_exit 'SIGCHLD blocked after error message'
+print 'set -o monitor;sleep .5 & sleep 1;jobs' > $tmp/foobar
+chmod +x $tmp/foobar
+x=$($SHELL -c "echo | $tmp/foobar")
+[[ $x == *Done* ]] || err_exit 'SIGCHLD blocked for script at end of pipeline'
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/signal.sh b/src/cmd/ksh93/tests/signal.sh
new file mode 100755
index 0000000..c6e150b
--- /dev/null
+++ b/src/cmd/ksh93/tests/signal.sh
@@ -0,0 +1,435 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2012 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ (( Errors++ ))
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+cd $tmp || err_exit "cd $tmp failed"
+
+unset n s t
+typeset -A SIG
+for s in $(kill -l)
+do if ! n=$(kill -l $s 2>/dev/null)
+ then err_exit "'kill -l $s' failed"
+ elif ! t=$(kill -l $n 2>/dev/null)
+ then err_exit "'kill -l $n' failed"
+ elif [[ $s == ?(SIG)$t ]]
+ then SIG[${s#SIG}]=1
+ elif ! m=$(kill -l $t 2>/dev/null)
+ then err_exit "'kill -l $t' failed"
+ elif [[ $m != $n ]]
+ then err_exit "'kill -l $s' => $n, 'kill -l $n' => $t, kill -l $t => $m -- expected $n"
+ fi
+done
+
+(
+ set --pipefail
+ {
+ $SHELL 2> out2 <<- \EOF
+ g=false
+ trap 'print -u2 PIPED; $g && exit 0;g=true' PIPE
+ while :
+ do print hello
+ done
+ EOF
+ } | head > /dev/null
+ (( $? == 0)) || err_exit "SIGPIPE with wrong error code $?"
+ [[ $(<out2) == $'PIPED\nPIPED' ]] || err_exit 'SIGPIPE output on standard error is not correct'
+) &
+cop=$!
+{ sleep 4; kill $cop; } 2>/dev/null &
+spy=$!
+if wait $cop 2>/dev/null
+then kill $spy 2>/dev/null
+else err_exit "pipe with --pipefail PIPE trap hangs"
+fi
+wait
+rm -f out2
+
+[[ $( trap 'print -n got_child' SIGCHLD
+ sleep 2 &
+ for ((i=0; i < 4; i++))
+ do sleep .75
+ print -n $i
+ done) == 01got_child23 ]] || err_exit 'SIGCHLD not working'
+
+# begin standalone SIGINT test generation
+
+cat > tst <<'!'
+# shell trap tests
+#
+# tst control script that calls tst-1, must be run by ksh
+# tst-1 calls tst-2
+# tst-2 calls tst-3
+# tst-3 defaults or handles and discards/propagates SIGINT
+#
+# initial -v option lists script entry and SIGINT delivery
+#
+# three test options
+#
+# d call next script directly, otherwise via $SHELL -c
+# t trap, echo, and kill self on SIGINT, otherwise x or SIGINT default if no x
+# x trap, echo on SIGINT, and tst-3 exit 0, tst-2 exit, otherwise SIGINT default
+# z trap, echo on SIGINT, and tst-3 exit 0, tst-2 exit 0, otherwise SIGINT default
+#
+# Usage: tst [-v] [-options] shell-to-test ...
+
+# "trap + sig" is an unadvertized extension for this test
+# if run from nmake SIGINT is set to SIG_IGN
+# this call sets it back to SIG_DFL
+# semantics w.r.t. function scope must be worked out before
+# making it public
+trap + INT
+
+set -o monitor
+
+function gen
+{
+ typeset o t x d
+ for x in - x z
+ do case $x in
+ [$1]) for t in - t
+ do case $t in
+ [$1]) for d in - d
+ do case $d in
+ [$1]) o="$o $x$t$d"
+ esac
+ done
+ esac
+ done
+ esac
+ done
+ echo '' $o
+}
+
+case $1 in
+-v) v=v; shift ;;
+-*v*) v=v ;;
+*) v= ;;
+esac
+case $1 in
+*' '*) o=$1; shift ;;
+-*) o=$(gen $1); shift ;;
+*) o=$(gen -txd) ;;
+esac
+case $# in
+0) set ksh bash ksh88 pdksh ash zsh ;;
+esac
+for f in $o
+do case $# in
+ 1) ;;
+ *) echo ;;
+ esac
+ for sh
+ do if $sh -c 'exit 0' > /dev/null 2>&1
+ then case $# in
+ 1) printf '%3s ' "$f" ;;
+ *) printf '%16s %3s ' "$sh" "$f" ;;
+ esac
+ $sh tst-1 $v$f $sh > tst.out &
+ wait
+ echo $(cat tst.out)
+ fi
+ done
+done
+case $# in
+1) ;;
+*) echo ;;
+esac
+!
+cat > tst-1 <<'!'
+exec 2>/dev/null
+case $1 in
+*v*) echo 1-main ;;
+esac
+{
+ sleep 2
+ case $1 in
+ *v*) echo "SIGINT" ;;
+ esac
+ kill -s INT 0
+} &
+case $1 in
+*t*) trap '
+ echo 1-intr
+ trap - INT
+ # omitting the self kill exposes shells that deliver
+ # the SIGINT trap but exit 0 for -xt
+ # kill -s INT $$
+ ' INT
+ ;;
+esac
+case $1 in
+*d*) tst-2 $1 $2; status=$? ;;
+*) $2 -c "tst-2 $1 $2"; status=$? ;;
+esac
+printf '1-%04d\n' $status
+sleep 2
+!
+cat > tst-2 <<'!'
+case $1 in
+*z*) trap '
+ echo 2-intr
+ exit 0
+ ' INT
+ ;;
+*x*) trap '
+ echo 2-intr
+ exit
+ ' INT
+ ;;
+*t*) trap '
+ echo 2-intr
+ trap - INT
+ kill -s INT $$
+ ' INT
+ ;;
+esac
+case $1 in
+*v*) echo 2-main ;;
+esac
+case $1 in
+*d*) tst-3 $1 $2; status=$? ;;
+*) $2 -c "tst-3 $1 $2"; status=$? ;;
+esac
+printf '2-%04d\n' $status
+!
+cat > tst-3 <<'!'
+case $1 in
+*[xz]*) trap '
+ sleep 2
+ echo 3-intr
+ exit 0
+ ' INT
+ ;;
+*) trap '
+ sleep 2
+ echo 3-intr
+ trap - INT
+ kill -s INT $$
+ ' INT
+ ;;
+esac
+case $1 in
+*v*) echo 3-main ;;
+esac
+sleep 5
+printf '3-%04d\n' $?
+!
+chmod +x tst tst-?
+
+# end standalone test generation
+
+export PATH=$PATH:
+typeset -A expected
+expected[---]="3-intr"
+expected[--d]="3-intr"
+expected[-t-]="3-intr 2-intr 1-intr 1-0258"
+expected[-td]="3-intr 2-intr 1-intr 1-0258"
+expected[x--]="3-intr 2-intr 1-0000"
+expected[x-d]="3-intr 2-intr 1-0000"
+expected[xt-]="3-intr 2-intr 1-intr 1-0000"
+expected[xtd]="3-intr 2-intr 1-intr 1-0000"
+expected[z--]="3-intr 2-intr 1-0000"
+expected[z-d]="3-intr 2-intr 1-0000"
+expected[zt-]="3-intr 2-intr 1-intr 1-0000"
+expected[ztd]="3-intr 2-intr 1-intr 1-0000"
+
+tst $SHELL > tst.got
+
+while read ops out
+do [[ $out == ${expected[$ops]} ]] || err_exit "interrupt $ops test failed -- expected '${expected[$ops]}', got '$out'"
+done < tst.got
+
+if [[ ${SIG[USR1]} ]]
+then float s=$SECONDS
+ [[ $(LC_ALL=C $SHELL -c 'trap "print SIGUSR1 ; exit 0" USR1; (trap "" USR1 ; exec kill -USR1 $$ & sleep 5); print done') == SIGUSR1 ]] || err_exit 'subshell ignoring signal does not send signal to parent'
+ (( (SECONDS-s) < 4 )) && err_exit 'parent does not wait for child to complete before handling signal'
+ ((s = SECONDS))
+ [[ $(LC_ALL=C $SHELL -c 'trap "print SIGUSR1 ; exit 0" USR1; (trap "exit" USR1 ; exec kill -USR1 $$ & sleep 5); print done') == SIGUSR1 ]] || err_exit 'subshell catching signal does not send signal to parent'
+ (( SECONDS-s < 4 )) && err_exit 'parent completes early'
+fi
+
+yes=$(whence -p yes)
+if [[ $yes ]]
+then for exp in TERM VTALRM PIPE
+ do if [[ ${SIG[$exp]} ]]
+ then {
+ $SHELL <<- EOF
+ foo() { return 0; }
+ trap foo EXIT
+ { sleep 2; kill -$exp \$\$; sleep 3; kill -0 \$\$ && kill -KILL \$\$; } &
+ $yes |
+ while read yes
+ do (/bin/date; sleep .1)
+ done > /dev/null
+ EOF
+ } 2>> /dev/null
+ got=$(kill -l $?)
+ [[ $exp == $got ]] || err_exit "kill -$exp \$\$ failed, required termination by signal '$got'"
+ fi
+ done
+fi
+
+SECONDS=0
+$SHELL 2> /dev/null -c 'sleep 2 && kill $$ & trap "print done; exit 3" EXIT; (sleep 5); print finished' > $tmp/sig
+e=$?
+[[ $e == 3 ]] || err_exit "exit status failed -- expected 3, got $e"
+x=$(<$tmp/sig)
+[[ $x == done ]] || err_exit "output failed -- expected 'done', got '$x'"
+(( SECONDS > 3.5 )) && err_exit "took $SECONDS seconds, expected around 2"
+
+SECONDS=0
+$SHELL 2> /dev/null -c 'sleep 2 && kill $$ & trap "print done; exit 3" EXIT; sleep 5; print finished' > $tmp/sig
+e=$?
+[[ $e == 3 ]] || err_exit "exit status failed -- expected 3, got $e"
+x=$(<$tmp/sig)
+[[ $x == done ]] || err_exit "output failed -- expected 'done', got '$x'"
+(( SECONDS > 3.5 )) && err_exit "took $SECONDS seconds, expected around 2"
+
+SECONDS=0
+{ $SHELL 2> /dev/null -c 'sleep 2 && kill $$ & trap "print done; exit 3" EXIT; (sleep 5); print finished' > $tmp/sig ;} 2> /dev/null
+e=$?
+[[ $e == 3 ]] || err_exit "exit status failed -- expected 3, got $e"
+x=$(<$tmp/sig)
+[[ $x == done ]] || err_exit "output failed -- expected 'done', got '$x'"
+(( SECONDS > 3.5 )) && err_exit "took $SECONDS seconds, expected around 2"
+
+SECONDS=0
+{ $SHELL 2> /dev/null -c 'sleep 2 && kill $$ & trap "print done; exit 3" EXIT; sleep 5; print finished' > $tmp/sig ;} 2> /dev/null
+e=$?
+[[ $e == 3 ]] || err_exit "exit status failed -- expected 3, got $e"
+x=$(<$tmp/sig)
+[[ $x == done ]] || err_exit "output failed -- expected 'done', got '$x'"
+(( SECONDS > 3.5 )) && err_exit "took $SECONDS seconds, expected around 2"
+
+SECONDS=0
+x=$($SHELL 2> /dev/null -c 'sleep 2 && kill $$ & trap "print done; exit 3" EXIT; (sleep 5); print finished')
+e=$?
+[[ $e == 3 ]] || err_exit "exit status failed -- expected 3, got $e"
+[[ $x == done ]] || err_exit "output failed -- expected 'done', got '$x'"
+(( SECONDS > 3.5 )) && err_exit "took $SECONDS seconds, expected around 2"
+
+SECONDS=0
+x=$($SHELL 2> /dev/null -c 'sleep 2 && kill $$ & trap "print done; exit 3" EXIT; sleep 5; print finished')
+e=$?
+[[ $e == 3 ]] || err_exit "exit status failed -- expected 3, got $e"
+[[ $x == done ]] || err_exit "output failed -- expected 'done', got '$x'"
+(( SECONDS > 3.5 )) && err_exit "took $SECONDS seconds, expected around 2"
+
+trap '' SIGBUS
+[[ $($SHELL -c 'trap date SIGBUS; trap -p SIGBUS') ]] && err_exit 'SIGBUS should not have a trap'
+trap -- - SIGBUS
+
+{
+ x=$(
+ $SHELL <<- \++EOF
+ timeout()
+ {
+ trap 'trap - TERM; return' TERM
+ ( sleep $1; kill -TERM $$ ) >/dev/null 2>&1 &
+ sleep 3
+ }
+ timeout 1
+ print ok
+++EOF
+ )
+} 2> /dev/null
+[[ $x == ok ]] || err_exit 'return without arguments in trap not preserving exit status'
+
+x=$(
+ $SHELL <<- \++EOF
+ set -o pipefail
+ foobar()
+ {
+ for ((i=0; i < 10000; i++))
+ do print abcdefghijklmnopqrstuvwxyz
+ done | head > /dev/null
+ }
+ foobar
+ print ok
+ ++EOF
+)
+[[ $x == ok ]] || err_exit 'SIGPIPE exit status causes PIPE signal to be propogaged'
+
+x=$(
+ $SHELL <<- \EOF
+ trap "print GNAW" URG
+ print 1
+ ( sleep 1 ; kill -URG $$ ; sleep 1 ; print S1 ; )
+ print 2
+EOF
+)
+[[ $x == $'1\nS1\nGNAW\n2' ]] || err_exit 'signal ignored in subshell not propagated to parent'
+
+if [[ ${SIG[RTMIN]} ]]
+then {
+ $SHELL <<- \EOF
+ trap : RTMIN
+ for ((i=0 ; i < 3 ; i++))
+ do sleep 1
+ kill -RTMIN $$ 2> /dev/null
+ done &
+ wait
+ EOF
+ } 2> /dev/null
+ [[ $? == 0 ]] && err_exit 'wait interrupted by caught signal should have non-zero exit status'
+ {
+ $SHELL <<- \EOF
+ for ((i=0 ; i < 3 ; i++))
+ do sleep 1
+ kill -RTMIN $$ 2> /dev/null
+ done &
+ wait
+ EOF
+ } 2> /dev/null
+ [[ $(kill -l $?) == RTMIN ]] || err_exit 'wait interrupted by signal not caught should exit with the value of that signal+256'
+fi
+
+function b
+{
+ sleep 3
+ endb=1
+}
+
+function a
+{
+ trap 'print int' TERM
+ b
+ enda=1
+}
+
+{ /bin/sleep 1;kill -s TERM $$;}&
+unset enda endb
+a
+[[ $endb ]] && err_exit 'TERM signal did not kill function b'
+[[ $enda == 1 ]] || err_exit 'TERM signal killed function a'
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/statics.sh b/src/cmd/ksh93/tests/statics.sh
new file mode 100755
index 0000000..7e67279
--- /dev/null
+++ b/src/cmd/ksh93/tests/statics.sh
@@ -0,0 +1,690 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+#
+# Written by Roland Mainz <roland.mainz@nrubsig.org>
+#
+
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ (( Errors < 127 && Errors++ ))
+}
+
+alias err_exit='err_exit $LINENO'
+
+set -o nounset
+Command=${0##*/}
+integer Errors=0
+
+
+
+typeset -T test_t=(
+ typeset name
+ typeset cmd
+ typeset expected_output
+)
+
+function testfunc
+{
+ integer line_number=$1
+ typeset cmd="$2"
+ typeset expected_output="$3"
+ typeset output
+
+ output="$($SHELL -c "${cmd}" 2>&1 )"
+
+ [[ "${output}" == "${expected_output}" ]] || err_exit ${line_number} "${output} != ${expected_output}"
+}
+
+# test1: basic tests
+function test1
+{
+ # string
+ testfunc ${LINENO} '(function l { typeset -S x ; x+="#" ; $1 && print "$x" ; } ; l false ; l false ; l true)' "###"
+ testfunc ${LINENO} 'function l { typeset -S x=">" ; x+="#" ; $1 && print "$x" ; } ; l false ; l false ; l true' ">###"
+ testfunc ${LINENO} 'function l { typeset -S x=">" ; x+="#" ; $1 && print "$x" ; } ; l false ; (l false) ; l true' ">##"
+ testfunc ${LINENO} 'function l { typeset -S x=">" ; x+="#" ; $1 && print "$x" ; } ; l false; ( ulimit -c 0 ; l false) ; l true' ">##"
+
+ # integer
+ # (normal)
+ testfunc ${LINENO} '(function l { integer -S x ; x+=1 ; $1 && print "$x" ; } ; l false ; l false ; l true )' "3"
+ testfunc ${LINENO} '(function l { integer -S x ; x+=1 ; $1 && print "$x" ; } ; l false ; (l false) ; l true )' "2"
+ # (int)
+ testfunc ${LINENO} '(function l { typeset -S -i x ; x+=1 ; $1 && print "$x" ; } ; l false ; l false ; l true )' "3"
+ testfunc ${LINENO} '(function l { typeset -S -i x ; x+=1 ; $1 && print "$x" ; } ; l false ; (l false) ; l true )' "2"
+ # (short)
+ testfunc ${LINENO} '(function l { typeset -S -s -i x ; x+=1 ; $1 && print "$x" ; } ; l false ; l false ; l true )' "3"
+ testfunc ${LINENO} '(function l { typeset -S -s -i x ; x+=1 ; $1 && print "$x" ; } ; l false ; (l false) ; l true )' "2"
+
+ # float
+ testfunc ${LINENO} '(function l { float -S x=0.5 ; (( x+=.5 )) ; $1 && print "$x" ; } ; l false ; l false ; l true )' "2"
+ testfunc ${LINENO} '(function l { float -S x=0.5 ; (( x+=.5 )) ; $1 && print "$x" ; } ; l false ; (l false) ; l true )' "1.5"
+
+ return 0
+}
+
+# test2: test the more complex datatypes
+function test2
+{
+ compound out=( typeset stdout stderr ; integer res )
+ integer i
+
+ test_t -r -a tests=(
+ (
+ name='compound'
+ cmd=$'
+ function l
+ {
+ compound -S s=(
+ integer a=1
+ integer b=2
+ )
+
+ (( s.a++, s.b++ ))
+
+ $1 && printf "a=%d, b=%d\n" s.a s.b
+ }
+ (l false ; l false ; l true ; printf ";")
+ (l false ; l false ; l true ; printf ";")
+ '
+ expected_output=$'a=4, b=5\n;a=4, b=5\n;'
+ )
+ (
+ name='compound_nameref'
+ cmd=$'
+ function l_n
+ {
+ nameref sn=$2
+ (( sn.a++, sn.b++ ))
+
+ $1 && printf "a=%d, b=%d\n" sn.a sn.b
+ }
+ function l
+ {
+ compound -S s=( a=1 b=2 )
+ l_n $1 s
+ }
+ (l false ; l false ; l true ; printf ";")
+ (l false ; l false ; l true ; printf ";")
+ '
+ expected_output=$'a=4, b=5\n;a=4, b=5\n;'
+ )
+
+ (
+ name='type'
+ cmd=$'
+ typeset -T ab_t=(
+ integer a=1
+ integer b=2
+
+ function increment
+ {
+ (( _.a++, _.b++ ))
+ }
+ )
+ function l
+ {
+ ab_t -S s
+
+ s.increment
+
+ $1 && printf "a=%d, b=%d\n" s.a s.b
+ }
+ (l false ; l false ; l true ; printf ";")
+ (l false ; l false ; l true ; printf ";")
+ '
+ expected_output=$'a=4, b=5\n;a=4, b=5\n;'
+ )
+
+ (
+ name='type_nameref'
+ cmd=$'
+ typeset -T ab_t=(
+ integer a=1
+ integer b=2
+
+ function increment
+ {
+ (( _.a++, _.b++ ))
+ }
+ )
+ function l_n
+ {
+ nameref sn=$2
+
+ sn.increment
+
+ $1 && printf "a=%d, b=%d\n" sn.a sn.b
+ }
+ function l
+ {
+ ab_t -S s
+ l_n $1 s
+ }
+ (l false ; l false ; l true ; printf ";")
+ (l false ; l false ; l true ; printf ";")
+ '
+ expected_output=$'a=4, b=5\n;a=4, b=5\n;'
+ )
+
+ (
+ name='indexed_string_array_appendelement'
+ cmd=$'
+ function ar
+ {
+ typeset -a -S s=( "hello" )
+
+ s+=( "an element" )
+
+ $1 && { printf "%s" "${s[@]}" ; printf "\n" ; }
+ }
+ (ar false ; ar false ; ar true ; printf ";")
+ (ar false ; ar false ; ar true ; printf ";")
+ '
+ expected_output=$'helloan elementan elementan element\n;helloan elementan elementan element\n;'
+ )
+
+ (
+ name='indexed_string_array_nameref_appendelement'
+ cmd=$'
+ function ar_n
+ {
+ nameref sn=$2
+ sn+=( "an element" )
+
+ $1 && { printf "%s" "${sn[@]}" ; printf "\n" ; }
+ }
+ function ar
+ {
+ typeset -a -S s=( "hello" )
+ ar_n $1 s
+ }
+ (ar false ; ar false ; ar true ; printf ";")
+ (ar false ; ar false ; ar true ; printf ";")
+ '
+ expected_output=$'helloan elementan elementan element\n;helloan elementan elementan element\n;'
+ )
+
+ (
+ name='associative_string_array_appendelement'
+ cmd=$'
+ function ar
+ {
+ typeset -A -S s=( [0]="hello" )
+
+ s[$(( ${#s[@]} + 1))]="an element"
+
+ $1 && { printf "%s" "${s[@]}" ; printf "\n" ; }
+ }
+ (ar false ; ar false ; ar true ; printf ";")
+ (ar false ; ar false ; ar true ; printf ";")
+ '
+ expected_output=$'helloan elementan elementan element\n;helloan elementan elementan element\n;'
+ )
+
+ (
+ name='associative_string_array_nameref_appendelement'
+ cmd=$'
+ function ar_n
+ {
+ nameref sn=$2
+
+ sn[$(( ${#sn[@]} + 1))]="an element"
+
+ $1 && { printf "%s" "${sn[@]}" ; printf "\n" ; }
+ }
+ function ar
+ {
+ typeset -A -S s=( [0]="hello" )
+ ar_n $1 s
+ }
+ (ar false ; ar false ; ar true ; printf ";")
+ (ar false ; ar false ; ar true ; printf ";")
+ '
+ expected_output=$'helloan elementan elementan element\n;helloan elementan elementan element\n;'
+ )
+
+ (
+ name='indexed_compound_array_editelement'
+ cmd=$'
+ function ar
+ {
+ compound -S -a s=(
+ [5]=(
+ integer a=1
+ integer b=2
+ )
+ )
+
+ (( s[5].a++, s[5].b++ ))
+ $1 && printf "a=%d, b=%d\n" s[5].a s[5].b
+ }
+ (ar false ; ar false ; ar true ; printf ";")
+ (ar false ; ar false ; ar true ; printf ";")
+ '
+ expected_output=$'a=4, b=5\n;a=4, b=5\n;'
+ )
+
+ (
+ name='indexed_compound_array_nameref_editelement'
+ cmd=$'
+ function ar_n
+ {
+ nameref sn=$2
+
+ (( sn.a++, sn.b++ ))
+ $1 && printf "a=%d, b=%d\n" sn.a sn.b
+ }
+ function ar
+ {
+ compound -S -a s=(
+ [5]=(
+ integer a=1
+ integer b=2
+ )
+ )
+
+ ar_n $1 s[5]
+ }
+ (ar false ; ar false ; ar true ; printf ";")
+ (ar false ; ar false ; ar true ; printf ";")
+ '
+ expected_output=$'a=4, b=5\n;a=4, b=5\n;'
+ )
+
+ (
+ name='2d_indexed_compound_array_editelement'
+ cmd=$'
+ function ar
+ {
+ compound -S -a s=(
+ [8][5]=(
+ integer a=1
+ integer b=2
+ )
+ )
+
+ (( s[8][5].a++, s[8][5].b++ ))
+ $1 && printf "a=%d, b=%d\n" s[8][5].a s[8][5].b
+ }
+ (ar false ; ar false ; ar true ; printf ";")
+ (ar false ; ar false ; ar true ; printf ";")
+ '
+ expected_output=$'a=4, b=5\n;a=4, b=5\n;'
+ )
+
+ (
+ name='2d_indexed_compound_array_nameref_editelement'
+ cmd=$'
+ function ar_n
+ {
+ nameref sn=$2
+
+ (( sn.a++, sn.b++ ))
+ $1 && printf "a=%d, b=%d\n" sn.a sn.b
+ }
+ function ar
+ {
+ compound -S -a s=(
+ [8][5]=(
+ integer a=1
+ integer b=2
+ )
+ )
+
+ ar_n $1 s[8][5]
+ }
+ (ar false ; ar false ; ar true ; printf ";")
+ (ar false ; ar false ; ar true ; printf ";")
+ '
+ expected_output=$'a=4, b=5\n;a=4, b=5\n;'
+ )
+ (
+ name='4d_indexed_compound_array_editelement'
+ cmd=$'
+ function ar
+ {
+ compound -S -a s=(
+ [8][5][0][9]=(
+ integer a=1
+ integer b=2
+ )
+ )
+
+ (( s[8][5][0][9].a++, s[8][5][0][9].b++ ))
+ $1 && printf "a=%d, b=%d\n" s[8][5][0][9].a s[8][5][0][9].b
+ }
+ (ar false ; ar false ; ar true ; printf ";")
+ (ar false ; ar false ; ar true ; printf ";")
+ '
+ expected_output=$'a=4, b=5\n;a=4, b=5\n;'
+ )
+
+ (
+ name='4d_indexed_compound_array_nameref_editelement'
+ cmd=$'
+ function ar_n
+ {
+ nameref sn=$2
+
+ (( sn.a++, sn.b++ ))
+ $1 && printf "a=%d, b=%d\n" sn.a sn.b
+ }
+ function ar
+ {
+ compound -S -a s=(
+ [8][5][0][9]=(
+ integer a=1
+ integer b=2
+ )
+ )
+
+ ar_n $1 s[8][5][0][9]
+ }
+ (ar false ; ar false ; ar true ; printf ";")
+ (ar false ; ar false ; ar true ; printf ";")
+ '
+ expected_output=$'a=4, b=5\n;a=4, b=5\n;'
+ )
+
+ (
+ name='associative_compound_array_editelement'
+ cmd=$'
+ function ar
+ {
+ compound -S -A s=(
+ [5]=(
+ integer a=1
+ integer b=2
+ )
+ )
+
+ (( s[5].a++, s[5].b++ ))
+ $1 && printf "a=%d, b=%d\n" s[5].a s[5].b
+ }
+ (ar false ; ar false ; ar true ; printf ";")
+ (ar false ; ar false ; ar true ; printf ";")
+ '
+ expected_output=$'a=4, b=5\n;a=4, b=5\n;'
+ )
+
+ (
+ name='associative_compound_array_nameref_editelement'
+ cmd=$'
+ function ar_n
+ {
+ nameref sn=$2
+
+ (( sn.a++, sn.b++ ))
+ $1 && printf "a=%d, b=%d\n" sn.a sn.b
+ }
+ function ar
+ {
+ compound -S -A s=(
+ [5]=(
+ integer a=1
+ integer b=2
+ )
+ )
+
+ ar_n $1 s[5]
+ }
+ (ar false ; ar false ; ar true ; printf ";")
+ (ar false ; ar false ; ar true ; printf ";")
+ '
+ expected_output=$'a=4, b=5\n;a=4, b=5\n;'
+ )
+
+ (
+ name='indexed_type_array_editelement'
+ cmd=$'
+ typeset -T ab_t=(
+ integer a=1
+ integer b=2
+
+ function increment
+ {
+ (( _.a++, _.b++ ))
+ }
+ )
+
+ function ar
+ {
+ ab_t -S -a s
+ [[ -v s[5] ]] || s[5]=( ) # how do I init an array of types ?
+
+ s[5].increment
+ $1 && printf "a=%d, b=%d\n" s[5].a s[5].b
+ }
+ (ar false ; ar false ; ar true ; printf ";")
+ (ar false ; ar false ; ar true ; printf ";")
+ '
+ expected_output=$'a=4, b=5\n;a=4, b=5\n;'
+ )
+
+ (
+ name='indexed_type_array_nameref_editelement'
+ cmd=$'
+ typeset -T ab_t=(
+ integer a=1
+ integer b=2
+
+ function increment
+ {
+ (( _.a++, _.b++ ))
+ }
+ )
+
+ function ar_n
+ {
+ nameref sn=$2
+
+ sn.increment
+ $1 && printf "a=%d, b=%d\n" sn.a sn.b
+ }
+ function ar
+ {
+ ab_t -S -a s
+ [[ -v s[5] ]] || s[5]=( ) # how do I init an array of types ?
+
+ ar_n $1 s[5]
+ }
+ (ar false ; ar false ; ar true ; printf ";")
+ (ar false ; ar false ; ar true ; printf ";")
+ '
+ expected_output=$'a=4, b=5\n;a=4, b=5\n;'
+ )
+
+ (
+ name='2d_indexed_type_array_editelement'
+ cmd=$'
+ typeset -T ab_t=(
+ integer a=1
+ integer b=2
+
+ function increment
+ {
+ (( _.a++, _.b++ ))
+ }
+ )
+
+ function ar
+ {
+ ab_t -S -a s
+ [[ -v s[9][5] ]] || s[9][5]=( ) # how do I init an array of types ?
+
+ s[9][5].increment
+ $1 && printf "a=%d, b=%d\n" s[9][5].a s[9][5].b
+ }
+ (ar false ; ar false ; ar true ; printf ";")
+ (ar false ; ar false ; ar true ; printf ";")
+ '
+ expected_output=$'a=4, b=5\n;a=4, b=5\n;'
+ )
+
+ (
+ name='2d_indexed_type_array_nameref_editelement'
+ cmd=$'
+ typeset -T ab_t=(
+ integer a=1
+ integer b=2
+
+ function increment
+ {
+ (( _.a++, _.b++ ))
+ }
+ )
+
+ function ar_n
+ {
+ nameref sn=$2
+
+ sn.increment
+ $1 && printf "a=%d, b=%d\n" sn.a sn.b
+ }
+ function ar
+ {
+ ab_t -S -a s
+ [[ -v s[9][5] ]] || s[9][5]=( ) # how do I init an array of types ?
+
+ ar_n $1 s[9][5]
+ }
+ (ar false ; ar false ; ar true ; printf ";")
+ (ar false ; ar false ; ar true ; printf ";")
+ '
+ expected_output=$'a=4, b=5\n;a=4, b=5\n;'
+ )
+
+ (
+ name='associative_type_array_editelement'
+ cmd=$'
+ typeset -T ab_t=(
+ integer a=1
+ integer b=2
+
+ function increment
+ {
+ (( _.a++, _.b++ ))
+ }
+ )
+
+ function ar
+ {
+ ab_t -S -A s
+ [[ -v s[5] ]] || s[5]=( ) # how do I init an array of types ?
+
+ s[5].increment
+ $1 && printf "a=%d, b=%d\n" s[5].a s[5].b
+ }
+ (ar false ; ar false ; ar true ; printf ";")
+ (ar false ; ar false ; ar true ; printf ";")
+ '
+ expected_output=$'a=4, b=5\n;a=4, b=5\n;'
+ )
+
+ (
+ name='associative_type_array_nameref_editelement'
+ cmd=$'
+ typeset -T ab_t=(
+ integer a=1
+ integer b=2
+
+ function increment
+ {
+ (( _.a++, _.b++ ))
+ }
+ )
+
+ function ar_n
+ {
+ nameref sn=$2
+
+ sn.increment
+ $1 && printf "a=%d, b=%d\n" sn.a sn.b
+ }
+ function ar
+ {
+ ab_t -S -A s
+ [[ -v s[5] ]] || s[5]=( ) # how do I init an array of types ?
+
+ ar_n $1 s[5]
+ }
+ (ar false ; ar false ; ar true ; printf ";")
+ (ar false ; ar false ; ar true ; printf ";")
+ '
+ expected_output=$'a=4, b=5\n;a=4, b=5\n;'
+ )
+
+ )
+
+ for (( i=0 ; i < ${#tests[@]} ; i++ )) ; do
+ nameref currtest=tests[i]
+
+#print -u2 -- "${currtest.cmd}"
+ out.stderr="${ { out.stdout="${ ${SHELL} -o nounset -c "${currtest.cmd}" ; (( out.res=$? )) ; }" ; } 2>&1 ; }"
+
+ (( out.res == 0 )) || err_exit "${currtest.name}: Test shell returned with exit code ${out.res}"
+ [[ "${out.stdout}" == "${currtest.expected_output}" ]] || err_exit "${currtest.name}: Expected stdout == $(printf "%q\n" "${currtest.expected_output}"), got $(printf "%q\n" "${out.stdout}")"
+ [[ "${out.stderr}" == '' ]] || err_exit "${currtest.name}: Expected empty stderr, got $(printf "%q\n" "${out.stderr}")"
+ done
+
+ return 0
+}
+
+# run tests
+test1
+test2
+
+
+# Test visibilty of "global" vs. "static" variables. if we have a "static" variable in a
+# function and "unset" it we should see a global variable with the same
+# name, right ?
+integer hx=5
+function test_hx_scope
+{
+ integer -S hx=9
+ $2 && unset hx
+ $1 && printf 'hx=%d\n' hx
+}
+test_hx_scope false false
+test_hx_scope false false
+# first test the "unset" call in a $(...) subshell...
+[[ "$( test_hx_scope true true )" == 'hx=5' ]] || err_exit "can't see global variable hx after unsetting static variable hx"
+# ... end then test whether the value has changed.
+[[ "${ test_hx_scope true false ;}" == 'hx=9' ]] || err_exit "hx variable somehow changed"
+
+out=$(function fun2
+{
+ nameref sn=$1
+ (( sn.a++, sn.b++ ))
+ $2 && printf "a=%d, b=%d\n" sn.a sn.b
+}
+function fun1
+{
+ compound -S s=( a=0 b=0 )
+ fun2 s $1
+}
+(fun1 false ; fun1 false ; fun1 true)
+(fun1 false ; fun1 false ; fun1 true)
+)
+[[ $out == $'a=3, b=3\na=3, b=3' ]] || err_exit 'static variables in functions with initializers not working'
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/subshell.sh b/src/cmd/ksh93/tests/subshell.sh
new file mode 100755
index 0000000..819811a
--- /dev/null
+++ b/src/cmd/ksh93/tests/subshell.sh
@@ -0,0 +1,582 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2012 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u$Error_fd -n "\t"
+ print -u$Error_fd -r ${Command}[$1]: "${@:2}"
+ (( Errors+=1 ))
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0 Error_fd=2
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+bincat=$(PATH=$(getconf PATH) whence -p cat)
+
+z=()
+z.foo=( [one]=hello [two]=(x=3 y=4) [three]=hi)
+z.bar[0]=hello
+z.bar[2]=world
+z.bar[1]=(x=4 y=5)
+val='(
+ typeset -a bar=(
+ [0]=hello
+ [2]=world
+ [1]=(
+ x=4
+ y=5
+ )
+ )
+ typeset -A foo=(
+ [one]=hello
+ [three]=hi
+ [two]=(
+ x=3
+ y=4
+ )
+ )
+)'
+[[ $z == "$val" ]] || err_exit 'compound variable with mixed arrays not working'
+z.bar[1]=yesyes
+[[ ${z.bar[1]} == yesyes ]] || err_exit 'reassign of index array compound variable fails'
+z.bar[1]=(x=12 y=5)
+[[ ${z.bar[1]} == $'(\n\tx=12\n\ty=5\n)' ]] || err_exit 'reassign array simple to compound variable fails'
+eval val="$z"
+(
+ z.foo[three]=good
+ [[ ${z.foo[three]} == good ]] || err_exit 'associative array assignment in subshell not working'
+)
+[[ $z == "$val" ]] || err_exit 'compound variable changes after associative array assignment'
+eval val="$z"
+(
+ z.foo[two]=ok
+ [[ ${z.foo[two]} == ok ]] || err_exit 'associative array assignment to compound variable in subshell not working'
+ z.bar[1]=yes
+ [[ ${z.bar[1]} == yes ]] || err_exit 'index array assignment to compound variable in subshell not working'
+)
+[[ $z == "$val" ]] || err_exit 'compound variable changes after associative array assignment'
+
+x=(
+ foo=( qqq=abc rrr=def)
+ bar=( zzz=no rst=fed)
+)
+eval val="$x"
+(
+ unset x.foo
+ [[ ${x.foo.qqq} ]] && err_exit 'x.foo.qqq should be unset'
+ x.foo=good
+ [[ ${x.foo} == good ]] || err_exit 'x.foo should be good'
+)
+[[ $x == "$val" ]] || err_exit 'compound variable changes after unset leaves'
+unset l
+(
+ l=( a=1 b="BE" )
+)
+[[ ${l+foo} != foo ]] || err_exit 'l should be unset'
+
+Error_fd=9
+eval "exec $Error_fd>&2 2>/dev/null"
+
+TEST_notfound=notfound
+while whence $TEST_notfound >/dev/null 2>&1
+do TEST_notfound=notfound-$RANDOM
+done
+
+
+integer BS=1024 nb=64 ss=60 bs no
+for bs in $BS 1
+do $SHELL -c '
+ {
+ sleep '$ss'
+ kill -KILL $$
+ } &
+ set -- $(printf %.'$(($BS*$nb))'c x | dd bs='$bs')
+ print ${#1}
+ kill $!
+ ' > $tmp/sub 2>/dev/null
+ no=$(<$tmp/sub)
+ (( no == (BS * nb) )) || err_exit "shell hangs on command substitution output size >= $BS*$nb with write size $bs -- expected $((BS*nb)), got ${no:-0}"
+done
+# this time with redirection on the trailing command
+for bs in $BS 1
+do $SHELL -c '
+ {
+ sleep 2
+ sleep '$ss'
+ kill -KILL $$
+ } &
+ set -- $(printf %.'$(($BS*$nb))'c x | dd bs='$bs' 2>/dev/null)
+ print ${#1}
+ kill $!
+ ' > $tmp/sub 2>/dev/null
+ no=$(<$tmp/sub)
+ (( no == (BS * nb) )) || err_exit "shell hangs on command substitution output size >= $BS*$nb with write size $bs and trailing redirection -- expected $((BS*nb)), got ${no:-0}"
+done
+
+# exercise command substitutuion trailing newline logic w.r.t. pipe vs. tmp file io
+
+set -- \
+ 'post-line print' \
+ '$TEST_unset; ($TEST_fork; print 1); print' \
+ 1 \
+ 'pre-line print' \
+ '$TEST_unset; ($TEST_fork; print); print 1' \
+ $'\n1' \
+ 'multiple pre-line print' \
+ '$TEST_unset; ($TEST_fork; print); print; ($TEST_fork; print 1); print' \
+ $'\n\n1' \
+ 'multiple post-line print' \
+ '$TEST_unset; ($TEST_fork; print 1); print; ($TEST_fork; print); print' \
+ 1 \
+ 'intermediate print' \
+ '$TEST_unset; ($TEST_fork; print 1); print; ($TEST_fork; print 2); print' \
+ $'1\n\n2' \
+ 'simple variable' \
+ '$TEST_unset; ($TEST_fork; l=2; print "$l"); print $l' \
+ 2 \
+ 'compound variable' \
+ '$TEST_unset; ($TEST_fork; l=(a=2 b="BE"); print "$l"); print $l' \
+ $'(\n\ta=2\n\tb=BE\n)' \
+
+export TEST_fork TEST_unset
+
+while (( $# >= 3 ))
+do txt=$1
+ cmd=$2
+ exp=$3
+ shift 3
+ for TEST_unset in '' 'unset var'
+ do for TEST_fork in '' 'ulimit -c 0'
+ do for TEST_shell in "eval" "$SHELL -c"
+ do if ! got=$($TEST_shell "$cmd")
+ then err_exit "${TEST_shell/*-c/\$SHELL -c} ${TEST_unset:+unset }${TEST_fork:+fork }$txt print failed"
+ elif [[ "$got" != "$exp" ]]
+ then EXP=$(printf %q "$exp")
+ GOT=$(printf %q "$got")
+ err_exit "${TEST_shell/*-c/\$SHELL -c} ${TEST_unset:+unset }${TEST_fork:+fork }$txt command substitution failed -- expected $EXP, got $GOT"
+ fi
+ done
+ done
+ done
+done
+
+r=$( ($SHELL -c '
+ {
+ sleep 32
+ kill -KILL $$
+ } &
+ for v in $(set | sed "s/=.*//")
+ do command unset $v
+ done
+ typeset -Z5 I
+ for ((I = 0; I < 1024; I++))
+ do eval A$I=1234567890
+ done
+ a=$(set 2>&1)
+ print ok
+ kill -KILL $!
+') 2>/dev/null)
+[[ $r == ok ]] || err_exit "large subshell command substitution hangs"
+
+for TEST_command in '' $TEST_notfound
+do for TEST_exec in '' 'exec'
+ do for TEST_fork in '' 'ulimit -c 0;'
+ do for TEST_redirect in '' '>/dev/null'
+ do for TEST_substitute in '' ': $'
+ do
+
+ TEST_test="$TEST_substitute($TEST_fork $TEST_exec $TEST_command $TEST_redirect)"
+ [[ $TEST_test == '('*([[:space:]])')' ]] && continue
+ r=$($SHELL -c '
+ {
+ sleep 2
+ kill -KILL $$
+ } &
+ '"$TEST_test"'
+ kill $!
+ print ok
+ ')
+ [[ $r == ok ]] || err_exit "shell hangs on $TEST_test"
+
+ done
+ done
+ done
+ done
+done
+
+$SHELL -c '( autoload xxxxx);print -n' || err_exit 'autoloaded functions in subshells can cause failure'
+foo=$($SHELL <<- ++EOF++
+ (trap 'print bar' EXIT;print -n foo)
+ ++EOF++
+)
+[[ $foo == foobar ]] || err_exit 'trap on exit when last commands is subshell is not triggered'
+
+err=$(
+ $SHELL 2>&1 <<- \EOF
+ date=$(whence -p date)
+ function foo
+ {
+ x=$( $date > /dev/null 2>&1 ;:)
+ }
+ # consume almost all fds to push the test to the fd limit #
+ integer max=$(ulimit --nofile)
+ (( max -= 6 ))
+ for ((i=20; i < max; i++))
+ do exec {i}>&1
+ done
+ for ((i=0; i < 20; i++))
+ do y=$(foo)
+ done
+ EOF
+) || {
+ err=${err%%$'\n'*}
+ err=${err#*:}
+ err=${err##[[:space:]]}
+ err_exit "nested command substitution with redirections failed -- $err"
+}
+
+exp=0
+$SHELL -c $'
+ function foobar
+ {
+ print "hello world"
+ }
+ [[ $(getopts \'[+?X\ffoobar\fX]\' v --man 2>&1) == *"Xhello worldX"* ]]
+ exit '$exp$'
+'
+got=$?
+[[ $got == $exp ]] || err_exit "getopts --man runtime callout with nonzero exit terminates shell -- expected '$exp', got '$got'"
+exp=ok
+got=$($SHELL -c $'
+ function foobar
+ {
+ print "hello world"
+ }
+ [[ $(getopts \'[+?X\ffoobar\fX]\' v --man 2>&1) == *"Xhello worldX"* ]]
+ print '$exp$'
+')
+[[ $got == $exp ]] || err_exit "getopts --man runtime callout with nonzero exit terminates shell -- expected '$exp', got '$got'"
+
+# command substitution variations #
+set -- \
+ '$(' ')' \
+ '${ ' '; }' \
+ '$(ulimit -c 0; ' ')' \
+ '$( (' ') )' \
+ '${ (' '); }' \
+ '`' '`' \
+ '`(' ')`' \
+ '`ulimit -c 0; ' '`' \
+ # end of table #
+exp=ok
+testcase[1]='
+ if %sexpr "NOMATCH" : ".*Z" >/dev/null%s
+ then print error
+ else print ok
+ fi
+ exit %s
+'
+testcase[2]='
+ function bar
+ {
+ pipeout=%1$sprintf Ok | tr O o%2$s
+ print $pipeout
+ return 0
+ }
+ foo=%1$sbar%2$s || foo="exit status $?"
+ print $foo
+ exit %3$s
+'
+while (( $# >= 2 ))
+do for ((TEST=1; TEST<=${#testcase[@]}; TEST++))
+ do body=${testcase[TEST]}
+ for code in 0 2
+ do got=${ printf "$body" "$1" "$2" "$code" | $SHELL 2>&1 }
+ status=$?
+ if (( status != code ))
+ then err_exit "test $TEST '$1...$2 exit $code' failed -- exit status $status, expected $code"
+ elif [[ $got != $exp ]]
+ then err_exit "test $TEST '$1...$2 exit $code' failed -- got '$got', expected '$exp'"
+ fi
+ done
+ done
+ shift 2
+done
+
+# the next tests loop on all combinations of
+# { SUB CAT INS TST APP } X { file-sizes }
+# where the file size starts at 1Ki and doubles up to and including 1Mi
+#
+# the tests and timeouts are done in async subshells to prevent
+# the test harness from hanging
+
+SUB=(
+ ( BEG='$( ' END=' )' )
+ ( BEG='${ ' END='; }' )
+)
+CAT=( cat $bincat )
+INS=( "" "builtin cat; " "builtin -d cat $bincat; " ": > /dev/null; " )
+APP=( "" "; :" )
+TST=(
+ ( CMD='print foo | $cat' EXP=3 )
+ ( CMD='$cat < $tmp/lin' )
+ ( CMD='cat $tmp/lin | $cat' )
+ ( CMD='read v < $tmp/buf; print $v' LIM=4*1024 )
+ ( CMD='cat $tmp/buf | read v; print $v' LIM=4*1024 )
+)
+
+if cat /dev/fd/3 3</dev/null >/dev/null 2>&1 || whence mkfifo > /dev/null
+then T=${#TST[@]}
+ TST[T].CMD='$cat <(print foo)'
+ TST[T].EXP=3
+fi
+
+# prime the two data files to 512 bytes each
+# $tmp/lin has newlines every 16 bytes and $tmp/buf has no newlines
+# the outer loop doubles the file size at top
+
+buf=$'1234567890abcdef'
+lin=$'\n1234567890abcde'
+for ((i=0; i<5; i++))
+do buf=$buf$buf
+ lin=$lin$lin
+done
+print -n "$buf" > $tmp/buf
+print -n "$lin" > $tmp/lin
+
+unset SKIP
+for ((n=1024; n<=1024*1024; n*=2))
+do cat $tmp/buf $tmp/buf > $tmp/tmp
+ mv $tmp/tmp $tmp/buf
+ cat $tmp/lin $tmp/lin > $tmp/tmp
+ mv $tmp/tmp $tmp/lin
+ for ((S=0; S<${#SUB[@]}; S++))
+ do for ((C=0; C<${#CAT[@]}; C++))
+ do cat=${CAT[C]}
+ for ((I=0; I<${#INS[@]}; I++))
+ do for ((A=0; A<${#APP[@]}; A++))
+ do for ((T=0; T<${#TST[@]}; T++))
+ do #undent...#
+
+ if [[ ! ${SKIP[S][C][I][A][T]} ]]
+ then eval "{ x=${SUB[S].BEG}${INS[I]}${TST[T].CMD}${APP[A]}${SUB[S].END}; print \${#x}; } >\$tmp/out &"
+ m=$!
+ { sleep 4; kill -9 $m; } &
+ k=$!
+ wait $m
+ h=$?
+ kill -9 $k
+ wait $k
+ got=$(<$tmp/out)
+ if [[ ! $got ]] && (( h ))
+ then got=HUNG
+ fi
+ if [[ ${TST[T].EXP} ]]
+ then exp=${TST[T].EXP}
+ else exp=$n
+ fi
+ if [[ $got != $exp ]]
+ then # on failure skip similar tests on larger files sizes #
+ SKIP[S][C][I][A][T]=1
+ siz=$(printf $'%#i' $exp)
+ cmd=${TST[T].CMD//\$cat/$cat}
+ cmd=${cmd//\$tmp\/buf/$siz.buf}
+ cmd=${cmd//\$tmp\/lin/$siz.lin}
+ err_exit "'x=${SUB[S].BEG}${INS[I]}${cmd}${APP[A]}${SUB[S].END} && print \${#x}' failed -- expected '$exp', got '$got'"
+ elif [[ ${TST[T].EXP} ]] || (( TST[T].LIM >= n ))
+ then SKIP[S][C][I][A][T]=1
+ fi
+ fi
+
+ #...indent#
+ done
+ done
+ done
+ done
+ done
+done
+
+# specifics -- there's more?
+
+{
+ cmd='{ exec 5>/dev/null; print "$(eval ls -d . 2>&1 1>&5)"; } >$tmp/out &'
+ eval $cmd
+ m=$!
+ { sleep 4; kill -9 $m; } &
+ k=$!
+ wait $m
+ h=$?
+ kill -9 $k
+ wait $k
+ got=$(<$tmp/out)
+} 2>/dev/null
+exp=''
+if [[ ! $got ]] && (( h ))
+then got=HUNG
+fi
+if [[ $got != $exp ]]
+then err_exit "eval '$cmd' failed -- expected '$exp', got '$got'"
+fi
+
+float t1=$SECONDS
+sleep=$(whence -p sleep)
+if [[ $sleep ]]
+then
+ $SHELL -c "( $sleep 5 </dev/null >/dev/null 2>&1 & );exit 0" | cat
+ (( (SECONDS-t1) > 4 )) && err_exit '/bin/sleep& in subshell hanging'
+ ((t1=SECONDS))
+fi
+$SHELL -c '( sleep 5 </dev/null >/dev/null 2>&1 & );exit 0' | cat
+(( (SECONDS-t1) > 4 )) && err_exit 'sleep& in subshell hanging'
+
+exp=HOME=$HOME
+( HOME=/bin/sh )
+got=$(env | grep ^HOME=)
+[[ $got == "$exp" ]] || err_exit "( HOME=/bin/sh ) cleanup failed -- expected '$exp', got '$got'"
+
+cmd='echo $((case x in x)echo ok;esac);:)'
+exp=ok
+got=$($SHELL -c "$cmd" 2>&1)
+[[ $got == "$exp" ]] || err_exit "'$cmd' failed -- expected '$exp', got '$got'"
+
+cmd='eval "for i in 1 2; do eval /bin/echo x; done"'
+exp=$'x\nx'
+got=$($SHELL -c "$cmd")
+if [[ $got != "$exp" ]]
+then EXP=$(printf %q "$exp")
+ GOT=$(printf %q "$got")
+ err_exit "'$cmd' failed -- expected $EXP, got $GOT"
+fi
+
+(
+$SHELL -c 'sleep 20 & pid=$!; { x=$( ( seq 60000 ) );kill -9 $pid;}&;wait $pid'
+) 2> /dev/null
+(( $? )) || err_exit 'nested command substitution with large output hangs'
+
+(.sh.foo=foobar)
+[[ ${.sh.foo} == foobar ]] && err_exit '.sh subvariables in subshells remain set'
+[[ $($SHELL -c 'print 1 | : "$(/bin/cat <(/bin/cat))"') ]] && err_exit 'process substitution not working correctly in subshells'
+
+# config hang bug
+integer i
+for ((i=1; i < 1000; i++))
+do typeset foo$i=$i
+done
+{
+ : $( (ac_space=' '; set | grep ac_space) 2>&1)
+} < /dev/null | cat > /dev/null &
+sleep 1.5
+if kill -KILL $! 2> /dev/null
+then err_exit 'process timed out with hung comsub'
+fi
+wait $! 2> /dev/null
+(( $? > 128 )) && err_exit 'incorrect exit status with comsub'
+
+$SHELL 2> /dev/null -c '[[ ${ print foo },${ print bar } == foo,bar ]]' || err_exit '${ print foo },${ print bar } not working'
+$SHELL 2> /dev/null -c '[[ ${ print foo; },${ print bar } == foo,bar ]]' || err_exit '${ print foo; },${ print bar } not working'
+
+src=$'true 2>&1\n: $(true | true)\n: $(true | true)\n: $(true | true)\n'$(whence -p true)
+exp=ok
+got=$( $SHELL -c "(eval '$src'); echo $exp" )
+[[ $got == "$exp" ]] || err_exit 'subshell eval of pipeline clobbers stdout'
+
+x=$( { time $SHELL -c date >| /dev/null;} 2>&1)
+[[ $x == *real*user*sys* ]] || err_exit 'time { ...;} 2>&1 in $(...) fails'
+
+x=$($SHELL -c '( function fx { export X=123; } ; fx; ); echo $X')
+[[ $x == 123 ]] && err_exit 'global variables set from with functions inside a
+subshell can leave side effects in parent shell'
+
+date=$(whence -p date)
+err() { return $1; }
+( err 12 ) & pid=$!
+: $( $date)
+wait $pid
+[[ $? == 12 ]] || err_exit 'exit status from subshells not being preserved'
+
+if cat /dev/fd/3 3</dev/null >/dev/null 2>&1 || whence mkfifo > /dev/null
+then x="$(sed 's/^/Hello /' <(print "Fred" | sort))"
+ [[ $x == 'Hello Fred' ]] || err_exit "process substitution of pipeline in command substitution not working"
+fi
+
+{
+$SHELL <<- \EOF
+ function foo
+ {
+ integer i
+ print -u2 foobar
+ for ((i=0; i < 8000; i++))
+ do print abcdefghijk
+ done
+ print -u2 done
+ }
+ out=$(eval "foo | cat" 2>&1)
+ (( ${#out} == 96011 )) || err_exit "\${#out} is ${#out} should be 96011"
+EOF
+} & pid=$!
+$SHELL -c "{ sleep 2 && kill $pid ;}" 2> /dev/null
+(( $? == 0 )) && err_exit 'process has hung'
+
+{
+x=$( $SHELL <<- \EOF
+ function func1 { typeset IFS; : $(func2); print END ;}
+ function func2 { IFS="BAR"; }
+ func1
+ func1
+EOF
+)
+} 2> /dev/null
+[[ $x == $'END\nEND' ]] || err_exit 'bug in save/restore of IFS in subshell'
+
+true=$(whence -p true)
+date=$(whence -p date)
+tmpf=$tmp/foo
+function fun1
+{
+ $true
+ cd - >/dev/null 2>&1
+ print -u2 -- "$($date) SUCCESS"
+}
+
+print -n $(fun1 2> $tmpf)
+[[ $(< $tmpf) == *SUCCESS ]] || err_exit 'standard error output lost with command substitution'
+
+
+tmpfile=$tmp/foo
+cat > $tmpfile <<-\EOF
+ $SHELL -c 'function g { IFS= ;};function f { typeset IFS;(g);: $V;};f;f'
+ EOF
+$SHELL 2> /dev/null "$tmpfile" || err_exit 'IFS in subshell causes core dump'
+
+unset i
+if [[ -d /dev/fd ]]
+then integer i
+ for ((i=11; i < 29; i++))
+ do if ! [[ -r /dev/fd/$i || -w /dev/fd/$i ]]
+ then a=$($SHELL -c "[[ -r /dev/fd/$i || -w /dev/fd/$i ]]")
+ (( $? )) || err_exit "file descriptor $i not close on exec"
+ fi
+ done
+fi
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/substring.sh b/src/cmd/ksh93/tests/substring.sh
new file mode 100755
index 0000000..e79447f
--- /dev/null
+++ b/src/cmd/ksh93/tests/substring.sh
@@ -0,0 +1,628 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2012 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0 j=4
+base=/home/dgk/foo//bar
+string1=$base/abcabcabc
+if [[ ${string1:0} != "$string1" ]]
+then err_exit "string1:0"
+fi
+if [[ ${string1: -1} != "c" ]]
+then err_exit "string1: -1"
+fi
+if [[ ${string1:0:1000} != "$string1" ]]
+then err_exit "string1:0"
+fi
+if [[ ${string1:1} != "${string1#?}" ]]
+then err_exit "string1:1"
+fi
+if [[ ${string1:1:4} != home ]]
+then err_exit "string1:1:4"
+fi
+if [[ ${string1: -5:4} != bcab ]]
+then err_exit "string1: -5:4"
+fi
+if [[ ${string1:1:j} != home ]]
+then err_exit "string1:1:j"
+fi
+if [[ ${string1:(j?1:0):j} != home ]]
+then err_exit "string1:(j?1:0):j"
+fi
+if [[ ${string1%*zzz*} != "$string1" ]]
+then err_exit "string1%*zzz*"
+fi
+if [[ ${string1%%*zzz*} != "$string1" ]]
+then err_exit "string1%%*zzz*"
+fi
+if [[ ${string1#*zzz*} != "$string1" ]]
+then err_exit "string1#*zzz*"
+fi
+if [[ ${string1##*zzz*} != "$string1" ]]
+then err_exit "string1##*zzz*"
+fi
+if [[ ${string1%+(abc)} != "$base/abcabc" ]]
+then err_exit "string1%+(abc)"
+fi
+if [[ ${string1%%+(abc)} != "$base/" ]]
+then err_exit "string1%%+(abc)"
+fi
+if [[ ${string1%/*} != "$base" ]]
+then err_exit "string1%/*"
+fi
+if [[ "${string1%/*}" != "$base" ]]
+then err_exit '"string1%/*"'
+fi
+if [[ ${string1%"/*"} != "$string1" ]]
+then err_exit 'string1%"/*"'
+fi
+if [[ ${string1%%/*} != "" ]]
+then err_exit "string1%%/*"
+fi
+if [[ ${string1#*/bar} != /abcabcabc ]]
+then err_exit "string1#*bar"
+fi
+if [[ ${string1##*/bar} != /abcabcabc ]]
+then err_exit "string1#*bar"
+fi
+if [[ "${string1#@(*/bar|*/foo)}" != //bar/abcabcabc ]]
+then err_exit "string1#@(*/bar|*/foo)"
+fi
+if [[ ${string1##@(*/bar|*/foo)} != /abcabcabc ]]
+then err_exit "string1##@(*/bar|*/foo)"
+fi
+if [[ ${string1##*/@(bar|foo)} != /abcabcabc ]]
+then err_exit "string1##*/@(bar|foo)"
+fi
+foo=abc
+if [[ ${foo#a[b*} != abc ]]
+then err_exit "abc#a[b*} != abc"
+fi
+if [[ ${foo//[0-9]/bar} != abc ]]
+then err_exit '${foo//[0-9]/bar} not expanding correctly'
+fi
+foo='(abc)'
+if [[ ${foo#'('} != 'abc)' ]]
+then err_exit "(abc)#( != abc)"
+fi
+if [[ ${foo%')'} != '(abc' ]]
+then err_exit "(abc)%) != (abc"
+fi
+foo=a123b456c
+if [[ ${foo/[0-9]?/""} != a3b456c ]]
+then err_exit '${foo/[0-9]?/""} not expanding correctly'
+fi
+if [[ ${foo//[0-9]/""} != abc ]]
+then err_exit '${foo//[0-9]/""} not expanding correctly'
+fi
+if [[ ${foo/#a/b} != b123b456c ]]
+then err_exit '${foo/#a/b} not expanding correctly'
+fi
+if [[ ${foo/#?/b} != b123b456c ]]
+then err_exit '${foo/#?/b} not expanding correctly'
+fi
+if [[ ${foo/%c/b} != a123b456b ]]
+then err_exit '${foo/%c/b} not expanding correctly'
+fi
+if [[ ${foo/%?/b} != a123b456b ]]
+then err_exit '${foo/%?/b} not expanding correctly'
+fi
+while read -r pattern string expected
+do if (( expected ))
+ then if [[ $string != $pattern ]]
+ then err_exit "$pattern does not match $string"
+ fi
+ if [[ ${string##$pattern} != "" ]]
+ then err_exit "\${$string##$pattern} not null"
+ fi
+ if [ "${string##$pattern}" != '' ]
+ then err_exit "\"\${$string##$pattern}\" not null"
+ fi
+ if [[ ${string/$pattern} != "" ]]
+ then err_exit "\${$string/$pattern} not null"
+ fi
+ else if [[ $string == $pattern ]]
+ then err_exit "$pattern matches $string"
+ fi
+ fi
+done <<- \EOF
+ +(a)*+(a) aabca 1
+ !(*.o) foo.o 0
+ !(*.o) foo.c 1
+EOF
+xx=a/b/c/d/e
+yy=${xx#*/}
+if [[ $yy != b/c/d/e ]]
+then err_exit '${xx#*/} != a/b/c/d/e when xx=a/b/c/d/e'
+fi
+if [[ ${xx//\//\\} != 'a\b\c\d\e' ]]
+then err_exit '${xx//\//\\} not working'
+fi
+x=[123]def
+if [[ "${x//\[@(*)\]/\{\1\}}" != {123}def ]]
+then err_exit 'closing brace escape not working'
+fi
+xx=%28text%29
+if [[ ${xx//%28/abc\)} != 'abc)text%29' ]]
+then err_exit '${xx//%28/abc\)} not working'
+fi
+xx='a:b'
+str='(){}[]*?|&^%$#@l'
+for ((i=0 ; i < ${#str}; i++))
+do [[ $(eval print -r -- \"\${xx//:/\\${str:i:1}}\") == "a${str:i:1}b" ]] || err_exit "substitution of \\${str:i:1}} failed"
+ [[ $(eval print -rn -- \"\${xx//:/\'${str:i:1}\'}\") == "a${str:i:1}b" ]] || err_exit "substitution of '${str:i:1}' failed"
+ [[ $(eval print -r -- \"\${xx//:/\"${str:i:1}\"}\") == "a${str:i:1}b" ]] || err_exit "substitution of \"${str:i:1}\" failed"
+done
+[[ ${xx//:/\\n} == 'a\nb' ]] || err_exit "substituion of \\\\n failed"
+[[ ${xx//:/'\n'} == 'a\nb' ]] || err_exit "substituion of '\\n' failed"
+[[ ${xx//:/"\n"} == 'a\nb' ]] || err_exit "substituion of \"\\n\" failed"
+[[ ${xx//:/$'\n'} == $'a\nb' ]] || err_exit "substituion of \$'\\n' failed"
+unset foo
+foo=one/two/three
+if [[ ${foo//'/'/_} != one_two_three ]]
+then err_exit 'single quoting / in replacements failed'
+fi
+if [[ ${foo//"/"/_} != one_two_three ]]
+then err_exit 'double quoting / in replacements failed'
+fi
+if [[ ${foo//\//_} != one_two_three ]]
+then err_exit 'escaping / in replacements failed'
+fi
+function myexport
+{
+ nameref var=$1
+ if (( $# > 1 ))
+ then export $1=$2
+ fi
+ if (( $# > 2 ))
+ then print $(myexport "$1" "$3" )
+ return
+ fi
+ typeset val
+ val=$(export | grep "^$1=")
+ print ${val#"$1="}
+
+}
+export dgk=base
+if [[ $(myexport dgk fun) != fun ]]
+then err_exit 'export inside function not working'
+fi
+val=$(export | grep "^dgk=")
+if [[ ${val#dgk=} != base ]]
+then err_exit 'export not restored after function call'
+fi
+if [[ $(myexport dgk fun fun2) != fun2 ]]
+then err_exit 'export inside function not working with recursive function'
+fi
+val=$(export | grep "^dgk=")
+if [[ ${val#dgk=} != base ]]
+then err_exit 'export not restored after recursive function call'
+fi
+if [[ $(dgk=try3 myexport dgk) != try3 ]]
+then err_exit 'name=value not added to export list with function call'
+fi
+val=$(export | grep "^dgk=")
+if [[ ${val#dgk=} != base ]]
+then err_exit 'export not restored name=value function call'
+fi
+unset zzz
+if [[ $(myexport zzz fun) != fun ]]
+then err_exit 'export inside function not working for zzz'
+fi
+if [[ $(export | grep "zzz=") ]]
+then err_exit 'zzz exported after function call'
+fi
+set -- foo/bar bam/yes last/file/done
+if [[ ${@/*\/@(*)/\1} != 'bar yes done' ]]
+then err_exit '\1 not working with $@'
+fi
+var=(foo/bar bam/yes last/file/done)
+if [[ ${var[@]/*\/@(*)/\1} != 'bar yes done' ]]
+then err_exit '\1 not working with ${var[@]}'
+fi
+var='abc_d2ef.462abc %%'
+if [[ ${var/+(\w)/Q} != 'Q.462abc %%' ]]
+then err_exit '${var/+(\w)/Q} not workding'
+fi
+if [[ ${var//+(\w)/Q} != 'Q.Q %%' ]]
+then err_exit '${var//+(\w)/Q} not workding'
+fi
+if [[ ${var//+(\S)/Q} != 'Q Q' ]]
+then err_exit '${var//+(\S)/Q} not workding'
+fi
+var=$($SHELL -c 'v=/vin:/usr/vin r=vin; : ${v//vin/${r//v/b}};typeset -p .sh.match') 2> /dev/null
+[[ $var == 'typeset -a .sh.match=((vin vin) )' ]] || err_exit '.sh.match not correct when replacement pattern contains a substring match'
+foo='foo+bar+'
+[[ $(print -r -- ${foo//+/'|'}) != 'foo|bar|' ]] && err_exit "\${foobar//+/'|'}"
+[[ $(print -r -- ${foo//+/"|"}) != 'foo|bar|' ]] && err_exit '${foobar//+/"|"}'
+[[ $(print -r -- "${foo//+/'|'}") != 'foo|bar|' ]] && err_exit '"${foobar//+/'"'|'"'}"'
+[[ $(print -r -- "${foo//+/"|"}") != 'foo|bar|' ]] && err_exit '"${foobar//+/"|"}"'
+unset x
+x=abcedfg
+: ${x%@(d)f@(g)}
+[[ ${.sh.match[0]} == dfg ]] || err_exit '.sh.match[0] not dfg'
+[[ ${.sh.match[1]} == d ]] || err_exit '.sh.match[1] not d'
+[[ ${.sh.match[2]} == g ]] || err_exit '.sh.match[2] not g'
+x=abcedddfg
+: ${x%%+(d)f@(g)}
+[[ ${.sh.match[1]} == ddd ]] || err_exit '.sh.match[1] not ddd'
+unset a b
+a='\[abc @(*) def\]'
+b='[abc 123 def]'
+[[ ${b//$a/\1} == 123 ]] || err_exit "\${var/pattern} not working with \[ in pattern"
+unset foo
+foo='(win32.i386) '
+[[ ${foo/'('/'(x11-'} == '(x11-win32.i386) ' ]] || err_exit "\${var/pattern} not working with ' in pattern"
+$SHELL -c $'v=\'$(hello)\'; [[ ${v//\'$(\'/-I\'$(\'} == -I"$v" ]]' 2> /dev/null || err_exit "\${var/pattern} not working with \$( as pattern"
+unset X
+$SHELL -c '[[ ! ${X[@]:0:300} ]]' 2> /dev/null || err_exit '${X[@]:0:300} with X undefined fails'
+$SHELL -c '[[ ${@:0:300} == "$0" ]]' 2> /dev/null || err_exit '${@:0:300} with no arguments fails'
+i=20030704
+[[ ${i#{6}(?)} == 04 ]] || err_exit '${i#{6}(?)} not working'
+[[ ${i#{6,6}(?)} == 04 ]] || err_exit '${i#{6,6}(?)} not working'
+LC_ALL=posix
+i=" ."
+[[ $(printf "<%s>\n" ${i#' '}) == '<.>' ]] || err_exit 'printf "<%s>\n" ${i#' '} failed'
+unset x
+x=foo
+[[ "${x%o}(1)" == "fo(1)" ]] || err_exit 'print ${}() treated as pattern'
+unset i pattern string
+string=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghigklmnopqrstuvwxyz
+integer i
+for((i=0; i < ${#string}; i++))
+do pattern+='@(?)'
+done
+[[ $(string=$string $SHELL -c ": \${string/$pattern/}; print \${.sh.match[26]}") == Z ]] || err_exit -u2 'sh.match[26] not Z'
+: ${string/$pattern/}
+(( ${#.sh.match[@]} == 53 )) || err_exit '.sh.match has wrong number of elements'
+[[ ${.sh.match[@]:2:4} == 'B C D E' ]] || err_exit '${.sh.match[@]:2:4} incorrect'
+
+D=$';' E=$'\\\\' Q=$'"' S=$'\'' M='nested pattern substitution failed'
+
+x='-(-)-'
+[[ ${x/*%(())*/\1} == '(-)' ]] || err_exit $M
+x='-(-)-)-'
+[[ ${x/*%(())*/\1} == '(-)' ]] || err_exit $M
+x='-(-()-)-'
+[[ ${x/*%(())*/\1} == '()' ]] || err_exit $M
+x='-(-\)-)-'
+[[ ${x/*%(())*/\1} == '(-\)' ]] || err_exit $M
+x='-(-\\)-)-'
+[[ ${x/*%(())*/\1} == '(-\\)' ]] || err_exit $M
+x='-(-(-)-'
+[[ ${x/*%(())*/\1} == '(-)' ]] || err_exit $M
+x='-(-(-)-)-'
+[[ ${x/*%(())*/\1} == '(-)' ]] || err_exit $M
+x='-(-[-]-)-'
+[[ ${x/*%(()[])*/\1} == '(-[-]-)' ]] || err_exit $M
+x='-[-(-)-]-'
+[[ ${x/*%(()[])*/\1} == '(-)' ]] || err_exit $M
+x='-(-[-)-]-'
+[[ ${x/*%(()[])*/\1} == '-(-[-)-]-' ]] || err_exit $M
+x='-(-[-]-)-'
+[[ ${x/*%([]())*/\1} == '[-]' ]] || err_exit $M
+x='-[-(-)-]-'
+[[ ${x/*%([]())*/\1} == '[-(-)-]' ]] || err_exit $M
+x='-(-[-)-]-'
+[[ ${x/*%([]())*/\1} == '-(-[-)-]-' ]] || err_exit $M
+
+x='-((-))-'
+[[ ${x/*%(())*/\1} == '(-)' ]] || err_exit $M
+x='-((-))-'
+[[ ${x/~(-g)*%(())*/\1} == '((-))-' ]] || err_exit $M
+x='-((-))-'
+[[ ${x/~(-g:*)*%(())*/\1} == '(-)' ]] || err_exit $M
+x='-((-))-'
+[[ ${x/~(+g)*%(())*/\1} == '(-)' ]] || err_exit $M
+x='-((-))-'
+[[ ${x/~(+g:*)*%(())*/\1} == '(-)' ]] || err_exit $M
+x='-((-))-'
+[[ ${x/*(?)*%(())*(?)*/:\1:\2:\3:} == ':-(:(-):)-:' ]] || err_exit $M
+x='-((-))-'
+[[ ${x/~(-g)*(?)*%(())*(?)*/:\1:\2:\3:} == '::((-))::-' ]] || err_exit $M
+x='-((-))-'
+[[ ${x/~(-g:*(?))*%(())*(?)*/:\1:\2:\3:} == '::(-):)-:' ]] || err_exit $M
+x='-((-))-'
+[[ ${x/~(+g)*(?)*%(())*(?)*/:\1:\2:\3:} == ':-(:(-):)-:' ]] || err_exit $M
+x='-((-))-'
+[[ ${x/~(+g:*(?))*%(())*(?)*/:\1:\2:\3:} == ':-(:(-):)-:' ]] || err_exit $M
+x='call(a+b,x/(c/d),(0));'
+[[ ${x/+([[:alnum:]])*([[:space:]])@(*%(()))*/:\1:\2:\3:} == ':call::(a+b,x/(c/d),(0)):' ]] || err_exit $M
+
+x='-(-;-)-'
+[[ ${x/*%(()D${D})*/\1} == '-(-;-)-' ]] || err_exit $M
+x='-(-);-'
+[[ ${x/*%(()D${D})*/\1} == '(-)' ]] || err_exit $M
+x='-(-)\;-'
+[[ ${x/*%(()D${D})*/\1} == '(-)' ]] || err_exit $M
+x='-(-\;-)-'
+[[ ${x/*%(()D${D}E${E})*/\1} == '(-\;-)' ]] || err_exit $M
+x='-(-)\;-'
+[[ ${x/*%(()D${D}E${E})*/\1} == '(-)' ]] || err_exit $M
+x='-(-(-)\;-)-'
+[[ ${x/*%(()D${D}E${E})*/\1} == '(-)' ]] || err_exit $M
+
+x='-(-")"-)-'
+[[ ${x/*%(()Q${Q})*/\1} == '(-")"-)' ]] || err_exit $M
+x='-(-\")"-)-'
+[[ ${x/*%(()Q${Q})*/\1} == '(-\")"-)' ]] || err_exit $M
+x='-(-\")\"-)-'
+[[ ${x/*%(()Q${Q})*/\1} == '(-\")\"-)' ]] || err_exit $M
+x=$'-(-\\\'")\\\'-)-'
+[[ ${x/*%(()Q${S}Q${Q})*/\1} == $'(-\\\'")\\\'-)' ]] || err_exit $M
+x=$'-(-\\\'")"-)-'
+[[ ${x/*%(()Q${S}Q${Q})*/\1} == $'-(-\\\'")"-)-' ]] || err_exit $M
+x=$'-(-\\\'")"\'-)-'
+[[ ${x/*%(()Q${S}Q${Q})*/\1} == $'(-\\\'")"\'-)' ]] || err_exit $M
+x=$'-(-\\"\')\'\\"-)-'
+[[ ${x/*%(()Q${S}Q${Q})*/\1} == $'(-\\"\')\'\\"-)' ]] || err_exit $M
+x=$'-(-\')\\\'\'-)-'
+[[ ${x/*%(()Q${S}Q${Q})*/\1} == $'-(-\')\\\'\'-)-' ]] || err_exit $M
+x=$'-(-\'")\'-)-'
+[[ ${x/*%(()L${S}Q${Q})*/\1} == $'(-\'")\'-)' ]] || err_exit $M
+x=$'-(-\\\'")"-)-'
+[[ ${x/*%(()L${S}Q${Q})*/\1} == $'-(-\\\'")"-)-' ]] || err_exit $M
+x=$'-(-\\\'")"\'-)-'
+[[ ${x/*%(()L${S}Q${Q})*/\1} == $'(-\\\'")"\'-)' ]] || err_exit $M
+x=$'-(-\\"\')\'\\"-)-'
+[[ ${x/*%(()L${S}Q${Q})*/\1} == $'(-\\"\')\'\\"-)' ]] || err_exit $M
+x=$'-(-\')\\\'\'-)-'
+[[ ${x/*%(()L${S}Q${Q})*/\1} == $'-(-\')\\\'\'-)-' ]] || err_exit $M
+x='-(-")"-)-'
+[[ ${x/*%(()Q${Q})*/\1} == '(-")"-)' ]] || err_exit $M
+x='-(-\")"-)-'
+[[ ${x/*%(()Q${Q})*/\1} == '(-\")"-)' ]] || err_exit $M
+x='-(-\")\"-)-'
+[[ ${x/*%(()Q${Q})*/\1} == '(-\")\"-)' ]] || err_exit $M
+
+x='-(-\)-)-'
+[[ ${x/*%(()E${E})*/\1} == '(-\)-)' ]] || err_exit $M
+x='-(-\\)-)-'
+[[ ${x/*%(()E${E})*/\1} == '(-\\)' ]] || err_exit $M
+x='-(-\")"-)-'
+[[ ${x/*%(()E${E}Q${Q})*/\1} == '(-\")' ]] || err_exit $M
+x='-(-\")\"-)-'
+[[ ${x/*%(()E${E}Q${Q})*/\1} == '(-\")' ]] || err_exit $M
+x=$'-(-\'")"-)-'
+[[ ${x/*%(()E${E}Q${S}Q${Q})*/\1} == $'-(-\'")"-)-' ]] || err_exit $M
+x=$'-(-\\\'")"-)-'
+[[ ${x/*%(()E${E}Q${S}Q${Q})*/\1} == $'(-\\\'")"-)' ]] || err_exit $M
+x=$'-(-\\"\')\'\\"-)-'
+[[ ${x/*%(()E${E}Q${S}Q${Q})*/\1} == $'(-\\"\')\'\\"-)' ]] || err_exit $M
+x=$'-(-\\\'")"-)-'
+[[ ${x/*%(()E${E}L${S}Q${Q})*/\1} == $'(-\\\'")"-)' ]] || err_exit $M
+x=$'-(-\\"\')\'\\"-)-'
+[[ ${x/*%(()E${E}L${S}Q${Q})*/\1} == $'(-\\"\')\'\\"-)' ]] || err_exit $M
+x=$'-(-\\"\')\\\'\\"-)-'
+[[ ${x/*%(()E${E}L${S}Q${Q})*/\1} == $'(-\\"\')\\\'\\"-)' ]] || err_exit $M
+x=$'-(-\\"\')\\\'\\"\'-)-'
+[[ ${x/*%(()E${E}L${S}Q${Q})*/\1} == $'-(-\\"\')\\\'\\"\'-)-' ]] || err_exit $M
+
+x='-(-;-)-'
+[[ ${x/*%(()D\;)*/\1} == '-(-;-)-' ]] || err_exit $M
+x='-(-);-'
+[[ ${x/*%(()D\;)*/\1} == '(-)' ]] || err_exit $M
+x='-(-)\;-'
+[[ ${x/*%(()D\;)*/\1} == '(-)' ]] || err_exit $M
+x='-(-\;-)-'
+[[ ${x/*%(()D\;E\\)*/\1} == '(-\;-)' ]] || err_exit $M
+x='-(-);-'
+[[ ${x/*%(()D\;E\\)*/\1} == '(-)' ]] || err_exit $M
+x='-(-)\;-'
+[[ ${x/*%(()D\;E\\)*/\1} == '(-)' ]] || err_exit $M
+x='-(-(-)\;-)-'
+[[ ${x/*%(()D\;E\\)*/\1} == '(-)' ]] || err_exit $M
+
+x='-(-")"-)-'
+[[ ${x/*%(()Q\")*/\1} == '(-")"-)' ]] || err_exit $M
+x='-(-\")"-)-'
+[[ ${x/*%(()Q\")*/\1} == '(-\")"-)' ]] || err_exit $M
+x='-(-\")\"-)-'
+[[ ${x/*%(()Q\")*/\1} == '(-\")\"-)' ]] || err_exit $M
+x=$'-(-\\\'")\\\'-)-'
+[[ ${x/*%(()Q\'Q\")*/\1} == $'(-\\\'")\\\'-)' ]] || err_exit $M
+x=$'-(-\\\'")"-)-'
+[[ ${x/*%(()Q\'Q\")*/\1} == $'-(-\\\'")"-)-' ]] || err_exit $M
+x=$'-(-\\\'")"\'-)-'
+[[ ${x/*%(()Q\'Q\")*/\1} == $'(-\\\'")"\'-)' ]] || err_exit $M
+x=$'-(-\\"\')\'\\"-)-'
+[[ ${x/*%(()Q\'Q\")*/\1} == $'(-\\"\')\'\\"-)' ]] || err_exit $M
+x=$'-(-\')\\\'\'-)-'
+[[ ${x/*%(()Q\'Q\")*/\1} == $'-(-\')\\\'\'-)-' ]] || err_exit $M
+x=$'-(-\'")\'-)-'
+[[ ${x/*%(()L\'Q\")*/\1} == $'(-\'")\'-)' ]] || err_exit $M
+x=$'-(-\\\'")"-)-'
+[[ ${x/*%(()L\'Q\")*/\1} == $'-(-\\\'")"-)-' ]] || err_exit $M
+x=$'-(-\\\'")"\'-)-'
+[[ ${x/*%(()L\'Q\")*/\1} == $'(-\\\'")"\'-)' ]] || err_exit $M
+x=$'-(-\\"\')\'\\"-)-'
+[[ ${x/*%(()L\'Q\")*/\1} == $'(-\\"\')\'\\"-)' ]] || err_exit $M
+x=$'-(-\')\\\'\'-)-'
+[[ ${x/*%(()L\'Q\")*/\1} == $'-(-\')\\\'\'-)-' ]] || err_exit $M
+x='-(-")"-)-'
+[[ ${x/*%(()Q\")*/\1} == '(-")"-)' ]] || err_exit $M
+x='-(-\")"-)-'
+[[ ${x/*%(()Q\")*/\1} == '(-\")"-)' ]] || err_exit $M
+x='-(-\")\"-)-'
+[[ ${x/*%(()Q\")*/\1} == '(-\")\"-)' ]] || err_exit $M
+
+x='-(-\)-)-'
+[[ ${x/*%(()E\\)*/\1} == '(-\)-)' ]] || err_exit $M
+x='-(-\\)-)-'
+[[ ${x/*%(()E\\)*/\1} == '(-\\)' ]] || err_exit $M
+x='-(-\")"-)-'
+[[ ${x/*%(()E\\Q\")*/\1} == '(-\")' ]] || err_exit $M
+x='-(-\")\"-)-'
+[[ ${x/*%(()E\\Q\")*/\1} == '(-\")' ]] || err_exit $M
+x=$'-(-\'")"-)-'
+[[ ${x/*%(()E\\Q\'Q\")*/\1} == $'-(-\'")"-)-' ]] || err_exit $M
+x=$'-(-\\\'")"-)-'
+[[ ${x/*%(()E\\Q\'Q\")*/\1} == $'(-\\\'")"-)' ]] || err_exit $M
+x=$'-(-\\"\')\'\\"-)-'
+[[ ${x/*%(()E\\Q\'Q\")*/\1} == $'(-\\"\')\'\\"-)' ]] || err_exit $M
+x=$'-(-\\\'")"-)-'
+[[ ${x/*%(()E\\L\'Q\")*/\1} == $'(-\\\'")"-)' ]] || err_exit $M
+x=$'-(-\\"\')\'\\"-)-'
+[[ ${x/*%(()E\\L\'Q\")*/\1} == $'(-\\"\')\'\\"-)' ]] || err_exit $M
+x=$'-(-\\"\')\\\'\\"-)-'
+[[ ${x/*%(()E\\L\'Q\")*/\1} == $'(-\\"\')\\\'\\"-)' ]] || err_exit $M
+x=$'-(-\\"\')\\\'\\"\'-)-'
+[[ ${x/*%(()E\\L\'Q\")*/\1} == $'-(-\\"\')\\\'\\"\'-)-' ]] || err_exit $M
+
+pattern=00
+var=100
+[[ $( print $(( ${var%%00} )) ) == 1 ]] || err_exit "arithmetic with embeddded patterns fails"
+[[ $( print $(( ${var%%$pattern} )) ) == 1 ]] || err_exit "arithmetic with embeddded pattern variables fails"
+if [[ ax == @(a)* ]] && [[ ${.sh.match[1]:0:${#.sh.match[1]}} != a ]]
+then err_exit '${.sh.match[1]:1:${#.sh.match[1]}} not expanding correctly'
+fi
+
+string='foo(d:\nt\box\something)bar'
+expected='d:\nt\box\something'
+[[ ${string/*\(+([!\)])\)*/\1} == "$expected" ]] || err_exit "substring expansion failed '${string/*\(+([!\)])\)*/\1}' returned -- '$expected' expected"
+if [[ $($SHELL -c $'export LC_ALL=C.UTF-8; print -r "\342\202\254\342\202\254\342\202\254\342\202\254w\342\202\254\342\202\254\342\202\254\342\202\254" | wc -m' 2>/dev/null) == 10 ]]
+then LC_ALL=C.UTF-8 $SHELL -c b1=$'"\342\202\254\342\202\254\342\202\254\342\202\254w\342\202\254\342\202\254\342\202\254\342\202\254"; [[ ${b1:4:1} == w ]]' || err_exit 'multibyte ${var:offset:len} not working correctly'
+fi
+{ $SHELL -c 'unset x;[[ ${SHELL:$x} == $SHELL ]]';} 2> /dev/null || err_exit '${var:$x} fails when x is not set'
+{ $SHELL -c 'x=;[[ ${SHELL:$x} == $SHELL ]]';} 2> /dev/null || err_exit '${var:$x} fails when x is null'
+
+# subject mode pattern result #
+set -- \
+ 'a$z' 'E' '[$]|#' 'a($)z' \
+ 'a#z' 'E' '[$]|#' 'a(#)z' \
+ 'a$z' 'Elr' '[$]|#' 'a$z' \
+ 'a#z' 'Elr' '[$]|#' 'a#z' \
+ 'a$' 'E' '[$]|#' 'a($)' \
+ 'a#' 'E' '[$]|#' 'a(#)' \
+ 'a$' 'Elr' '[$]|#' 'a$' \
+ 'a#' 'Elr' '[$]|#' 'a#' \
+ '$z' 'E' '[$]|#' '($)z' \
+ '#z' 'E' '[$]|#' '(#)z' \
+ '$z' 'Elr' '[$]|#' '$z' \
+ '#z' 'Elr' '[$]|#' '#z' \
+ '$' 'E' '[$]|#' '($)' \
+ '#' 'E' '[$]|#' '(#)' \
+ '$' 'Elr' '[$]|#' '($)' \
+ '#' 'Elr' '[$]|#' '(#)' \
+ 'a$z' 'E' '\$|#' 'a$z()' \
+ 'a$z' 'E' '\\$|#' 'a$z' \
+ 'a$z' 'E' '\\\$|#' 'a($)z' \
+ 'a#z' 'E' '\\\$|#' 'a(#)z' \
+ 'a$z' 'Elr' '\\\$|#' 'a$z' \
+ 'a#z' 'Elr' '\\\$|#' 'a#z' \
+ 'a$' 'E' '\\\$|#' 'a($)' \
+ 'a#' 'E' '\\\$|#' 'a(#)' \
+ 'a$' 'Elr' '\\\$|#' 'a$' \
+ 'a#' 'Elr' '\\\$|#' 'a#' \
+ '$z' 'E' '\\\$|#' '($)z' \
+ '#z' 'E' '\\\$|#' '(#)z' \
+ '$z' 'Elr' '\\\$|#' '$z' \
+ '#z' 'Elr' '\\\$|#' '#z' \
+ '$' 'E' '\\\$|#' '($)' \
+ '#' 'E' '\\\$|#' '(#)' \
+ '$' 'Elr' '\\\$|#' '($)' \
+ '#' 'Elr' '\\\$|#' '(#)' \
+# do not delete this line #
+unset i o
+while (( $# >= 4 ))
+do i=$1
+ eval o="\${i/~($2)$3/\\(\\0\\)}"
+ if [[ "$o" != "$4" ]]
+ then err_exit "i='$1'; \${i/~($2)$3/\\(\\0\\)} failed -- expected '$4', got '$o'"
+ fi
+ eval o="\${i/~($2)($3)/\\(\\1\\)}"
+ if [[ "$o" != "$4" ]]
+ then err_exit "i='$1'; \${i/~($2)($3)/\\(\\1\\)} failed -- expected '$4', got '$o'"
+ fi
+ shift 4
+done
+
+#multibyte locale tests
+x='a<2b|>c<3d|\>e' LC_ALL=debug $SHELL -c 'test "${x:0:1}" == a || err_exit ${x:0:1} should be a'
+x='a<2b|>c<3d|\>e' LC_ALL=debug $SHELL -c 'test "${x:1:1}" == "<2b|>" || err_exit ${x:1:1} should be <2b|>'
+x='a<2b|>c<3d|\>e' LC_ALL=debug $SHELL -c 'test "${x:3:1}" == "<3d|\\>" || err_exit ${x:3:1} should be <3d|\>'
+x='a<2b|>c<3d|\>e' LC_ALL=debug $SHELL -c 'test "${x:4:1}" == e || err_exit ${x:4:1} should bee'
+x='a<2b|>c<3d|\>e' LC_ALL=debug $SHELL -c 'test "${x:1}" == "<2b|>c<3d|\\>e" || print -u2 ${x:1}" should be <2b|>c<3d|\>e'
+x='a<2b|>c<3d|\>e' LC_ALL=debug $SHELL -c 'test "${x: -1:1}" == e || err_exit ${x: -1:1} should be e'
+x='a<2b|>c<3d|\>e' LC_ALL=debug $SHELL -c 'test "${x: -2:1}" == "<3d|\\>" || err_exit ${x: -2:1} == <3d|\>'
+x='a<2b|>c<3d|\>e' LC_ALL=debug $SHELL -c 'test "${x:1:3}" == "<2b|>c<3d|\\>" || err_exit ${x:1:3} should be <2b|>c<3d|\>'
+x='a<2b|>c<3d|\>e' LC_ALL=debug $SHELL -c 'test "${x:1:20}" == "<2b|>c<3d|\\>e" || err_exit ${x:1:20} should be <2b|>c<3d|\>e'
+x='a<2b|>c<3d|\>e' LC_ALL=debug $SHELL -c 'test "${x#??}" == "c<3d|\\>e" || err_exit "${x#??} should be c<3d|\>e'
+
+x='a one and a two'
+[[ "${x//~(E)\<.\>/}" == ' one and two' ]] || err_exit "\< and \> not working in with ere's"
+
+{
+$SHELL -c 'typeset x="123" ; integer i=100 ; print -n "${x:i:5}"'
+} 2> /dev/null || err_exit '${x:i:j} fails when i > strlen(x)'
+
+got=$($SHELL -c 'A=""; B="B"; for I in ${A[@]} ${B[@]}; do echo "\"$I\""; done')
+[[ $got == $'"B"' ]] || err_exit '"\"$I\"" fails when $I is empty string'
+
+A='|'
+[[ $A == $A ]] || err_exit 'With A="|", [[ $A == $A ]] does not match'
+
+x="111 222 333 444 555 666"
+[[ $x == ~(E)(...).(...).(...) ]]
+[[ -v .sh.match[0] ]] || err_exit '[[ -v .sh.match[0] ]] should be true'
+[[ -v .sh.match[3] ]] || err_exit '[[ -v .sh.match[3] ]] should be true'
+[[ -v .sh.match[4] ]] && err_exit '[[ -v .sh.match[4] ]] should be false'
+[[ ${#.sh.match[@]} == 4 ]] || err_exit "\${#.sh.match[@]} should be 4, not ${#.sh.match[@]}"
+
+x="foo bar"
+dummy=${x/~(E)(*)/}
+[[ ${ print -v .sh.match;} ]] && err_exit 'print -v should show .sh.match empty when there are no matches'
+
+if $SHELL -c 'set 1 2 3 4 5 6 7 8 9 10 11 12; : ${##[0-9]}' 2>/dev/null
+then set 1 2 3 4 5 6 7 8 9 10 11 12
+ [[ ${##[0-9]} == 2 ]] || err_exit '${##[0-9]} should be 2 with $#==12'
+ [[ ${###[0-9]} == 2 ]] || err_exit '${###[0-9]} should be 2 with $#==12'
+ [[ ${#%[0-9]} == 1 ]] || err_exit '${#%[0-9]} should be 1 with $#==12'
+ [[ ${#%%[0-9]} == 1 ]] || err_exit '${#%%[0-9]} should be 1 with $#==12'
+else err_exit '${##[0-9]} give syntax error'
+fi
+
+{
+ $SHELL -c 'x="a123 456 789z"; : ${x//{3}(\d)/ }' &
+ sleep .5; kill $!; wait $!
+} 2> /dev/null || err_exit $'tokenizer can\'t handle ${var op {..} }'
+
+
+function foo
+{
+ typeset x="123 456 789 abc"
+ typeset dummy="${x/~(E-g)([[:digit:]][[:digit:]])((X)|([[:digit:]]))([[:blank:]])/_}"
+ exp=$'(\n\t[0]=\'123 \'\n\t[1]=12\n\t[2]=3\n\t[4]=3\n\t[5]=\' \'\n)'
+ [[ $(print -v .sh.match) == "$exp" ]] || err_exit '.sh.match not correct with alternations'
+}
+foo
+
+x="a 1 b"
+d=${x/~(E)(([[:digit:]])[[:space:]]*|([[:alpha:]]))/X}
+[[ $(print -v .sh.match) == $'(\n\t[0]=a\n\t[1]=a\n\t[3]=a\n)' ]] || err_exit '.sh.match not sparse'
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/tilde.sh b/src/cmd/ksh93/tests/tilde.sh
new file mode 100755
index 0000000..b044723
--- /dev/null
+++ b/src/cmd/ksh93/tests/tilde.sh
@@ -0,0 +1,101 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2012 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r $Command: "$@"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+if $SHELL -c '[[ ~root == /* ]]'
+then x=$(print -r -- ~root)
+ [[ $x == ~root ]] || err_exit '~user expanded in subshell prevent ~user from working'
+fi
+
+function home # id
+{
+ typeset IFS=: pwd=/etc/passwd
+ set -o noglob
+ if [[ -f $pwd ]] && grep -c "^$1:" $pwd > /dev/null
+ then set -- $(grep "^$1:" $pwd)
+ print -r -- "$6"
+ else print .
+ fi
+}
+
+OLDPWD=/bin
+if [[ ~ != $HOME ]]
+then err_exit '~' not $HOME
+fi
+x=~
+if [[ $x != $HOME ]]
+then err_exit x=~ not $HOME
+fi
+x=x:~
+if [[ $x != x:$HOME ]]
+then err_exit x=x:~ not x:$HOME
+fi
+if [[ ~+ != $PWD ]]
+then err_exit '~' not $PWD
+fi
+x=~+
+if [[ $x != $PWD ]]
+then err_exit x=~+ not $PWD
+fi
+if [[ ~- != $OLDPWD ]]
+then err_exit '~' not $PWD
+fi
+x=~-
+if [[ $x != $OLDPWD ]]
+then err_exit x=~- not $OLDPWD
+fi
+for u in root Administrator
+do h=$(home $u)
+ if [[ $h != . ]]
+ then [[ ~$u -ef $h ]] || err_exit "~$u not $h"
+ x=~$u
+ [[ $x -ef $h ]] || x="~$u not $h"
+ break
+ fi
+done
+x=~g.r.emlin
+if [[ $x != '~g.r.emlin' ]]
+then err_exit "x=~g.r.emlin failed -- expected '~g.r.emlin', got '$x'"
+fi
+x=~:~
+if [[ $x != "$HOME:$HOME" ]]
+then err_exit "x=~:~ failed, expected '$HOME:$HOME', got '$x'"
+fi
+HOME=/
+[[ ~ == / ]] || err_exit '~ should be /'
+[[ ~/foo == /foo ]] || err_exit '~/foo should be /foo when ~==/'
+print $'print ~+\n[[ $1 ]] && $0' > $tmp/tilde
+chmod +x $tmp/tilde
+nl=$'\n'
+[[ $($tmp/tilde foo) == "$PWD$nl$PWD" ]] 2> /dev/null || err_exit 'tilde fails inside a script run by name'
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/timetype.sh b/src/cmd/ksh93/tests/timetype.sh
new file mode 100755
index 0000000..16453c4
--- /dev/null
+++ b/src/cmd/ksh93/tests/timetype.sh
@@ -0,0 +1,81 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ (( Errors+=1 ))
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+typeset -T Time_t=(
+ integer .=-1
+ _='%F+%H:%M'
+ get()
+ {
+ if (( _ < 0 ))
+ then .sh.value=${ printf "%(${_._})T" now ;}
+ else .sh.value=${ printf "%(${_._})T" "#$((_))" ;}
+ fi
+ }
+ set()
+ {
+ .sh.value=${ printf "%(%#)T" "${.sh.value}";}
+ }
+)
+
+d=$(printf "%(%F+%H:%M)T" now)
+integer s=$(printf "%(%#)T" "$d")
+Time_t t=$d
+[[ $t == "$d" ]] || err_exit "printf %T != Time_t -- expected '$d', got '$t'"
+(( t == s )) || err_exit "numeric Time_t failed -- expected '$s', got '$t'"
+t._='%#'
+[[ $t == $s ]] || err_exit "t._='%#' failed -- expected '$s', got '$t'"
+unset t
+Time_t tt=(yesterday today tomorrow)
+tt[3]=2pm
+[[ ${!tt[@]} == '0 1 2 3' ]] || err_exit "indexed array subscript names failed -- expected '0 1 2 3', got '${!tt[@]}'"
+[[ ${tt[0]} == *+00:00 ]] || err_exit "tt[0] failed -- expected 00:00, got '${tt[0]##*+}'"
+[[ ${tt[1]} == *+00:00 ]] || err_exit "tt[1] failed -- expected 00:00, got '${tt[1]##*+}'"
+[[ ${tt[2]} == *+00:00 ]] || err_exit "tt[2] failed -- expected 00:00, got '${tt[2]##*+}'"
+[[ ${tt[3]} == *+14:00 ]] || err_exit "tt[3] failed -- expected 14:00, got '${tt[3]##*+}'"
+unset tt
+Time_t tt=('2008-08-11+00:00:00,yesterday' '2008-08-11+00:00:00,today' '2008-08-11+00:00:00,tomorrow')
+tt[3]=9am
+tt[4]=5pm
+(( (tt[1] - tt[0]) == 24*3600 )) || err_exit "today-yesterday='$((tt[1] - tt[0]))' != 1 day"
+(( (tt[2] - tt[1]) == 24*3600 )) || err_exit "tomorrow-today='$((tt[2] - tt[1]))' != 1 day"
+(( (tt[4] - tt[3]) == 8*3600 )) || err_exit "9am..5pm='$((tt[4] - tt[3]))' != 8 hours"
+unset tt
+Time_t tt=([yesterday]='2008-08-11+00:00:00,yesterday' [today]='2008-08-11+00:00:00,today' [tomorrow]='2008-08-11+00:00:00,tomorrow')
+tt[2pm]='2008-08-11+00:00:00,2pm'
+[[ ${tt[yesterday]} == *+00:00 ]] || err_exit "tt[yesterday] failed -- expected 00:00, got '${tt[yesterday]##*+}'"
+[[ ${tt[today]} == *+00:00 ]] || err_exit "tt[today] failed -- expected 00:00, got '${tt[today]##*+}'"
+[[ ${tt[tomorrow]} == *+00:00 ]] || err_exit "tt[tomorrow] failed -- expected 00:00, got '${tt[tomorrow]##*+}'"
+[[ ${tt[2pm]} == *+14:00 ]] || err_exit "tt[2pm] failed -- expected 14:00, got '${tt[2pm]##*+}'"
+(( (tt[today] - tt[yesterday] ) == 24*3600 )) || err_exit "tt[today]-tt[yesterday] failed -- expected 24*3600, got $(((tt[today]-tt[yesterday])/3600.0))*3600"
+(( (tt[tomorrow] - tt[today] ) == 24*3600 )) || err_exit "tt[tomorrow]-tt[today] failed -- expected 24*3600, got $(((tt[tomorrow]-tt[today])/3600.0))*3600"
+(( (tt[2pm] - tt[today] ) == 14*3600 )) || err_exit "tt[2pm]-tt[today] failed -- expected 14*3600, got $(((tt[2pm]-tt[today])/3600.0))*3600"
+unset tt
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/treemove.sh b/src/cmd/ksh93/tests/treemove.sh
new file mode 100755
index 0000000..8e293c0
--- /dev/null
+++ b/src/cmd/ksh93/tests/treemove.sh
@@ -0,0 +1,163 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# This test checks whether "typeset -m" correctly moves local variables
+# into a global variable tree.
+#
+# This was reported as CR #XXXXXXXX ("XXXX"):
+# -- snip --
+#XXXX
+# -- snip --
+#
+
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ (( Errors+=1 ))
+}
+
+alias err_exit='err_exit $LINENO'
+
+integer Errors=0
+
+## test start
+typeset -C tree1 tree2
+
+# add node to tree which uses "typeset -m" to move a local variable
+# into tree1.subtree["a_node"]
+function f1
+{
+ nameref tr=$1
+ typeset -A tr.subtree
+ typeset -C node
+ node.one="hello"
+ node.two="world"
+ # move local note into the array
+false
+ typeset -m tr.subtree["a_node"]=node
+ return 0
+}
+
+# Alternative version which uses "nameref" instead of "typeset -m"
+function f2
+{
+ nameref tr=$1
+ typeset -A tr.subtree
+ nameref node=tr.subtree["a_node"]
+ node.one="hello"
+ node.two="world"
+ return 0
+}
+
+f1 tree1
+f2 tree2
+
+[[ "${tree1.subtree["a_node"].one}" == "hello" ]] || err_exit "expected tree1.subtree[\"a_node\"].one == 'hello', got ${tree1.subtree["a_node"].one}"
+[[ "${tree1.subtree["a_node"].two}" == "world" ]] || err_exit "expected tree1.subtree[\"a_node\"].two == 'world', got ${tree1.subtree["a_node"].two}"
+[[ "${tree1}" == "${tree2}" ]] || err_exit "tree1 and tree2 differ:$'\n'"
+
+unset c
+compound c
+typeset -C -a c.ar
+c.ar[4]=( a4=1 )
+typeset -m "c.ar[5]=c.ar[4]"
+exp=$'(\n\ttypeset -C -a ar=(\n\t\t[5]=(\n\t\t\ta4=1\n\t\t)\n\t)\n)'
+[[ $(print -v c) == "$exp" ]] || err_exit 'typeset -m "c.ar[5]=c.ar[4]" not working'
+
+typeset -T x_t=( hello=world )
+function m
+{
+ compound c
+ compound -a c.x
+ x_t c.x[4][5][8].field
+ x_t x
+ typeset -m c.x[4][6][9].field=x
+ exp=$'(\n\ttypeset -C -a x=(\n\t\t[4]=(\n\t\t\t[5]=(\n\t\t\t\t[8]=(\n\t\t\t\t\tx_t field=(\n\t\t\t\t\t\thello=world\n\t\t\t\t\t)\n\t\t\t\t)\n\t\t\t)\n\t\t\t[6]=(\n\t\t\t\t[9]=(\n\t\t\t\t\tx_t field=(\n\t\t\t\t\t\thello=world\n\t\t\t\t\t)\n\t\t\t\t)\n\t\t\t)\n\t\t)\n\t)\n)'
+ [[ $(print -v c) == "$exp" ]] || err_exit "typeset -m c.x[4][6][9].field=x where x is a type is not working"
+}
+m
+
+function moveme
+{
+ nameref src=$2 dest=$1
+ typeset -m dest=src
+}
+function main
+{
+ compound a=( aa=1 )
+ compound -a ar
+ moveme ar[4] a 2> /dev/null || err_exit 'function moveme fails'
+ exp=$'(\n\t[4]=(\n\t\taa=1\n\t)\n)'
+ [[ $(print -v ar) == "$exp" ]] || err_exit 'typeset -m dest=src where dest and src are name references fails'
+}
+main
+
+
+{
+$SHELL <<- \EOF
+ function main
+ {
+ compound c=(
+ compound -a board
+ )
+ for ((i=0 ; i < 2 ; i++ )) ; do
+ compound el=(typeset id='pawn')
+ typeset -m "c.board[1][i]=el"
+ done
+ exp=$'(\n\ttypeset -C -a board=(\n\t\t[1]=(\n\t\t\t(\n\t\t\t\tid=pawn\n\t\t\t)\n\t\t\t(\n\t\t\t\tid=pawn\n\t\t\t)\n\t\t)\n\t)\n)'
+ [[ $(print -v c) == "$exp" ]] || exit 1
+ }
+ main
+EOF
+} 2> /dev/null
+if ((exitval=$?))
+then if [[ $(kill -l $exitval) == SEGV ]]
+ then err_exit 'typeset -m "c.board[1][i]=el" core dumps'
+ else err_exit 'typeset -m "c.board[1][i]=el" gives wrong value'
+ fi
+fi
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/types.sh b/src/cmd/ksh93/tests/types.sh
new file mode 100755
index 0000000..e8f82e1
--- /dev/null
+++ b/src/cmd/ksh93/tests/types.sh
@@ -0,0 +1,632 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ (( Errors+=1 ))
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+integer n=2
+
+typeset -T Type_t=(
+ typeset name=foobar
+ typeset x=(hi=ok bar=yes)
+ typeset y=(xa=xx xq=89)
+ typeset -A aa=([one]=abc [two]=def)
+ typeset -a ia=(abc def)
+ typeset -i z=5
+)
+for ((i=0; i < 10; i++))
+do
+ Type_t r s
+ [[ $r == "$s" ]] || err_exit 'r is not equal to s'
+ typeset -C x=r.x
+ y=(xa=bb xq=cc)
+ y2=xyz
+ z2=xyz
+ typeset -C z=y
+ [[ $y == "$z" ]] || err_exit 'y is not equal to z'
+ typeset -C s.y=z
+ [[ $y == "${s.y}" ]] || err_exit 'y is not equal to s.y'
+ .sh.q=$y
+ typeset -C www=.sh.q
+ [[ $www == "$z" ]] || err_exit 'www is not equal to z'
+ typeset -C s.x=r.x
+ [[ ${s.x} == "${r.x}" ]] || err_exit 's.x is not equal to r.x'
+
+ function foo
+ {
+ nameref x=$1 y=$2
+ typeset z=$x
+ y=$x
+ [[ $x == "$y" ]] || err_exit "x is not equal to y with ${!x}"
+ }
+ foo r.y y
+ [[ $y == "${r.y}" ]] || err_exit 'y is not equal to r.y'
+ typeset -C y=z
+ foo y r.y
+ [[ $y == "${r.y}" ]] || err_exit 'y is not equal to r.y again'
+ typeset -C y=z
+ (
+ q=${z}
+ [[ $q == "$z" ]] || err_exit 'q is not equal to z'
+ z=abc
+ )
+ [[ $z == "$y" ]] || err_exit 'value of z not preserved after subshell'
+ unset z y r s x z2 y2 www .sh.q
+done
+typeset -T Frame_t=( typeset file lineno )
+Frame_t frame
+[[ $(typeset -p frame) == 'Frame_t frame=(typeset file;typeset lineno)' ]] || err_exit 'empty fields in type not displayed'
+x=( typeset -a arr=([2]=abc [4]=(x=1 y=def));zz=abc)
+typeset -C y=x
+[[ "$x" == "$y" ]] || print -u2 'y is not equal to x'
+Type_t z=(y=(xa=bb xq=cc))
+typeset -A arr=([foo]=one [bar]=2)
+typeset -A brr=([foo]=one [bar]=2)
+[[ "${arr[@]}" == "${brr[@]}" ]] || err_exit 'arr is not brr'
+for ((i=0; i < 1; i++))
+do typeset -m zzz=x
+ [[ $zzz == "$y" ]] || err_exit 'zzz is not equal to y'
+ typeset -m x=zzz
+ [[ $x == "$y" ]] || err_exit 'x is not equal to y'
+ Type_t t=(y=(xa=bb xq=cc))
+ typeset -m r=t
+ [[ $r == "$z" ]] || err_exit 'r is not equal to z'
+ typeset -m t=r
+ [[ $t == "$z" ]] || err_exit 't is not equal to z'
+ typeset -m crr=arr
+ [[ "${crr[@]}" == "${brr[@]}" ]] || err_exit 'crr is not brr'
+ typeset -m arr=crr
+ [[ "${arr[@]}" == "${brr[@]}" ]] || err_exit 'brr is not arr'
+done
+typeset -m brr[foo]=brr[bar]
+[[ ${brr[foo]} == 2 ]] || err_exit 'move an associative array element fails'
+[[ ${brr[bar]} ]] && err_exit 'brr[bar] should be unset after move'
+unset x y zzz
+x=(a b c)
+typeset -m x[1]=x[2]
+[[ ${x[1]} == c ]] || err_exit 'move an indexed array element fails'
+[[ ${x[2]} ]] && err_exit 'x[2] should be unset after move'
+cat > $tmp/types <<- \+++
+ typeset -T Pt_t=(float x=1. y=0.)
+ Pt_t p=(y=2)
+ print -r -- ${p.y}
++++
+expected=2
+got=$(. $tmp/types) 2>/dev/null
+[[ "$got" == "$expected" ]] || err_exit "typedefs in dot script failed -- expected '$expected', got '$got'"
+typeset -T X_t=(
+ typeset x=foo y=bar
+ typeset s=${_.x}
+ create()
+ {
+ _.y=bam
+ }
+)
+X_t x
+[[ ${x.x} == foo ]] || err_exit 'x.x should be foo'
+[[ ${x.y} == bam ]] || err_exit 'x.y should be bam'
+[[ ${x.s} == ${x.x} ]] || err_exit 'x.s should be x.x'
+typeset -T Y_t=( X_t r )
+Y_t z
+[[ ${z.r.x} == foo ]] || err_exit 'z.r.x should be foo'
+[[ ${z.r.y} == bam ]] || err_exit 'z.r.y should be bam'
+[[ ${z.r.s} == ${z.r.x} ]] || err_exit 'z.r.s should be z.r.x'
+
+unset xx yy
+typeset -T xx=(typeset yy=zz)
+xx=yy
+{ typeset -T xx=(typeset yy=zz) ;} 2>/dev/null && err_exit 'type redefinition should fail'
+$SHELL 2> /dev/null <<- +++ || err_exit 'typedef with only f(){} fails'
+ typeset -T X_t=(
+ f()
+ {
+ print ok
+ }
+ )
++++
+$SHELL 2> /dev/null <<- +++ || err_exit 'unable to redefine f discipline function'
+ typeset -T X_t=(
+ x=1
+ f()
+ {
+ print ok
+ }
+ )
+ X_t z=(
+ function f
+ {
+ print override f
+ }
+ )
++++
+$SHELL 2> /dev/null <<- +++ && err_exit 'invalid discipline name should be an error'
+ typeset -T X_t=(
+ x=1
+ f()
+ {
+ print ok
+ }
+ )
+ X_t z=(
+ function g
+ {
+ print override f
+ }
+ )
++++
+# compound variables containing type variables
+Type_t r
+var=(
+ typeset x=foobar
+ Type_t r
+ integer z=5
+)
+[[ ${var.r} == "$r" ]] || err_exit 'var.r != r'
+(( var.z == 5)) || err_exit 'var.z !=5'
+[[ "$var" == *x=foobar* ]] || err_exit '$var does not contain x=foobar'
+
+typeset -T A_t=(
+ typeset x=aha
+ typeset b=${_.x}
+)
+unset x
+A_t x
+expected=aha
+got=${x.b}
+[[ "$got" == "$expected" ]] || err_exit "type '_' reference failed -- expected '$expected', got '$got'"
+
+typeset -T Tst_t=(
+ function f
+ {
+ A_t a
+ print ${ _.g ${a.x}; }
+ }
+ function g
+ {
+ print foo
+ }
+)
+Tst_t tst
+expected=foo
+got=${ tst.f;}
+[[ "$got" == "$expected" ]] || err_exit "_.g where g is a function in type discipline method failed -- expected '$expected', got '$got'"
+
+typeset -T B_t=(
+ integer -a arr
+ function f
+ {
+ (( _.arr[0] = 0 ))
+ (( _.arr[1] = 1 ))
+ print ${_.arr[*]}
+ }
+)
+unset x
+B_t x
+expected='0 1'
+got=${ x.f;}
+[[ "$got" == "$expected" ]] || err_exit "array assignment of subscripts in type discipline arithmetic failed -- expected '$expected', got '$got'"
+
+typeset -T Fileinfo_t=(
+ size=-1
+ typeset -a text=()
+ integer mtime=-1
+)
+Fileinfo_t -A _Dbg_filenames
+Fileinfo_t finfo
+function bar
+{
+ finfo.text=(line1 line2 line3)
+ finfo.size=${#finfo.text[@]}
+ _Dbg_filenames[foo]=finfo
+}
+bar
+
+expected='Fileinfo_t -A _Dbg_filenames=([foo]=(size=3;typeset -a text=(line1 line2 line3);typeset -l -i mtime=-1))'
+got=$(typeset -p _Dbg_filenames)
+[[ "$got" == "$expected" ]] || {
+ got=$(printf %q "$got")
+ err_exit "copy to associative array of types in function failed -- expected '$expected', got $got"
+}
+
+$SHELL > /dev/null <<- '+++++' || err_exit 'passing _ as nameref arg not working'
+ function f1
+ {
+ typeset -n v=$1
+ print -r -- "$v"
+ }
+ typeset -T A_t=(
+ typeset blah=xxx
+ function f { f1 _ ;}
+ )
+ A_t a
+ [[ ${ a.f ./t1;} == "$a" ]]
++++++
+expected='A_t b.a=(name=one)'
+[[ $( $SHELL << \+++
+ typeset -T A_t=(
+ typeset name=aha
+ )
+ typeset -T B_t=(
+ typeset arr
+ A_t a
+ f()
+ {
+ _.a=(name=one)
+ typeset -p _.a
+ }
+ )
+ B_t b
+ b.f
++++
+) == "$expected" ]] 2> /dev/null || err_exit '_.a=(name=one) not expanding correctly'
+expected='A_t x=(name=xxx)'
+[[ $( $SHELL << \+++
+ typeset -T A_t=(
+ typeset name
+ )
+ A_t x=(name="xxx")
+ typeset -p x
++++
+) == "$expected" ]] || err_exit 'empty field in definition does not expand correctly'
+
+typeset -T Foo_t=(
+ integer x=3
+ integer y=4
+ len() { print -r -- $(( sqrt(_.x**2 + _.y**2))) ;}
+)
+Foo_t foo
+[[ ${foo.len} == 5 ]] || err_exit "discipline function len not working"
+
+typeset -T benchmark_t=(
+ integer num_iterations
+)
+function do_benchmarks
+{
+ nameref tst=b
+ integer num_iterations
+ (( num_iterations= int(tst.num_iterations * 1.0) ))
+ printf "%d\n" num_iterations
+}
+benchmark_t b=(num_iterations=5)
+[[ $(do_benchmarks) == 5 ]] || err_exit 'scoping of nameref of type variables in arithmetic expressions not working'
+
+function cat_content
+{
+ cat <<- EOF
+ (
+ foo_t -a foolist=(
+ ( val=3 )
+ ( val=4 )
+ ( val=5 )
+ )
+ )
+ EOF
+ return 0
+}
+typeset -T foo_t=(
+ integer val=-1
+ function print
+ {
+ print -- ${_.val}
+ }
+)
+function do_something
+{
+ nameref li=$1 # "li" may be an index or associative array
+ li[2].print
+}
+cat_content | read -C x
+[[ $(do_something x.foolist) == 5 ]] || err_exit 'subscripts not honored for arrays of type with disciplines'
+
+typeset -T benchcmd_t=(
+ float x=1
+ float y=2
+)
+unset x
+compound x=(
+ float o
+ benchcmd_t -a m
+ integer h
+)
+expected=$'(\n\ttypeset -l -i h=0\n\tbenchcmd_t -a m\n\ttypeset -l -E o=0\n)'
+[[ $x == "$expected" ]] || err_exit 'compound variable with array of types with no elements not working'
+
+expected=$'Std_file_t db.file[/etc/profile]=(action=preserve;typeset -A sum=([8242e663d6f7bb4c5427a0e58e2925f3]=1);)'
+{
+ got=$($SHELL <<- \EOF
+ MAGIC='stdinstall (at&t research) 2009-08-25'
+ typeset -T Std_file_t=(
+ typeset action
+ typeset -A sum
+ )
+ typeset -T Std_t=(
+ typeset magic=$MAGIC
+ Std_file_t -A file
+ )
+ Std_t db=(magic='stdinstall (at&t research) 2009-08-25';Std_file_t -A file=( [/./home/gsf/.env.sh]=(action=preserve;typeset -A sum=([9b67ab407d01a52b3e73e3945b9a3ee0]=1);)[/etc/profile]=(action=preserve;typeset -A sum=([8242e663d6f7bb4c5427a0e58e2925f3]=1);)[/home/gsf/.profile]=(action=preserve;typeset -A sum=([3ce23137335219672bf2865d003a098e]=1);));)
+ typeset -p db.file[/etc/profile]
+ EOF)
+} 2> /dev/null
+[[ $got == "$expected" ]] || err_exit 'types with arrays of types as members fails'
+
+typeset -T x_t=(
+ integer dummy
+ function set
+ {
+ [[ ${.sh.name} == v ]] || err_exit "name=${.sh.name} should be v"
+ [[ ${.sh.subscript} == 4 ]] || err_exit "subscript=${.sh.subscript} should be 4"
+ [[ ${.sh.value} == hello ]] || err_exit "value=${.sh.value} should be hello"
+ }
+)
+x_t -a v
+v[4]="hello"
+
+typeset -T oset=(
+ typeset -A s
+)
+oset foo bar
+: ${foo.s[a]:=foobar}
+: ${bar.s[d]:=foobar}
+[[ ${bar.s[a]} == foobar ]] && err_exit '${var:=val} for types assigns to type instead of type instance'
+
+typeset -T olist=(
+ typeset -a l
+)
+olist foo
+foo.l[1]=x
+[[ ${!foo.l[*]} == *0* ]] && '0-th elment of foo.l should not be set'
+
+typeset -T oset2=( typeset -A foo )
+oset2 bar
+: ${bar.foo[a]}
+bar.foo[a]=b
+[[ ${#bar.foo[*]} == 1 ]] || err_exit "bar.foo should have 1 element not ${#bar.foo[*]}"
+[[ ${bar.foo[*]} == b ]] || err_exit "bar.foo[*] should be 'b' not ${bar.foo[*]}"
+[[ ${bar.foo[a]} == b ]] || err_exit "bar.foo[a] should be 'b' not ${bar.foo[*]}"
+
+{ x=$( $SHELL 2> /dev/null << \++EOF++
+ typeset -T ab_t=(
+ integer a=1 b=2
+ function increment
+ {
+ (( _.a++, _.b++ ))
+ }
+ )
+ function ar_n
+ {
+ nameref sn=$2
+ sn.increment
+ $1 && printf "a=%d, b=%d\n" sn.a sn.b
+ }
+ function ar
+ {
+ ab_t -S -a s
+ [[ -v s[5] ]] || s[5]=( )
+ ar_n $1 s[5]
+ }
+ x=$(ar false ; ar false ; ar true ; printf ";")
+ y=$(ar false ; ar false ; ar true ; printf ";")
+ print -r -- "\"$x\"" == "\"$y\""
+++EOF++
+) ;} 2> /dev/null
+[[ $x == *a=4*b=5* ]] || err_exit 'static types in a function not working'
+{ eval "[[ $x ]]";} 2> /dev/null || err_exit 'arrays of types leaving side effects in subshells'
+
+typeset -T y_t=(
+ typeset dummy
+ function print_b
+ {
+ print "B"
+ }
+)
+y_t a b=(
+ function print_b
+ {
+ print "1"
+ }
+)
+[[ $(a.print_b) == B ]] || err_exit 'default discipline not working'
+[[ $(b.print_b) == 1 ]] || err_exit 'discipline override not working'
+
+$SHELL 2> /dev/null -c 'true || { typeset -T Type_t=(typeset name=foo);
+ Type_t z=(name=bar) ;}' || err_exit 'unable to parse type command until typeset -T executes'
+
+cd "$tmp"
+FPATH=$PWD
+PATH=$PWD:$PATH
+cat > A_t <<- \EOF
+ typeset -T A_t=(
+ B_t b
+ )
+EOF
+cat > B_t <<- \EOF
+ typeset -T B_t=(
+ integer n=5
+ )
+EOF
+
+unset n
+if n=$(FPATH=$PWD PATH=$PWD:$PATH $SHELL 2> /dev/null -c 'A_t a; print ${a.b.n}')
+then (( n==5 )) || err_exit 'dynamic loading of types gives wrong result'
+else err_exit 'unable to load types dynamically'
+fi
+
+# check that typeset -T reproduces a type.
+if $SHELL > /dev/null 2>&1 -c 'typeset -T'
+then $SHELL > junk1 <<- \+++EOF
+ typeset -T foo_t=(
+ integer x=3 y=4
+ float z=1.2
+ len()
+ {
+ ((.sh.value=sqrt(_.x**2 + _.y**2) ))
+ }
+ function count
+ {
+ print z=$z
+ }
+ )
+ typeset -T
+ print 'typeset -T'
+ +++EOF
+ $SHELL -c '. ./junk1;print "typeset -T"' > junk2
+ diff junk[12] > /dev/null || err_exit 'typeset -T not idempotent'
+ $SHELL -c '. ./junk1;print "typeset +f"' > junk2
+ [[ -s junk2 ]] || err_exit 'non-discipline-method functions found'
+else
+ err_exit 'typeset -T not supported'
+fi
+
+[[ $($SHELL -c 'typeset -T x=( typeset -a h ) ; x j; print -v j.h') ]] && err_exit 'type with indexed array without elements inserts element 0'
+
+[[ $($SHELL -c 'typeset -T x=( integer -a s ) ; compound c ; x c.i ; c.i.s[4]=666 ; print -v c') == *'[0]'* ]] && err_exit 'type with indexed array with non-zero element inserts element 0'
+
+
+{ $SHELL -c '(sleep 3;kill $$)& typeset -T x=( typeset -a s );compound c;x c.i;c.i.s[7][5][3]=hello;x c.j=c.i;[[ ${c.i} == "${c.j}" ]]';} 2> /dev/null
+exitval=$?
+if [[ $(kill -l $exitval) == TERM ]]
+then err_exit 'clone of multi-dimensional array timed out'
+elif ((exitval))
+then err_exit "c.i and c.j are not the same multi-dimensional array"
+fi
+
+typeset -T foobar_t=(
+ float x=1 y=0
+ slen()
+ {
+ print -r -- $((sqrt(_.x**2 + _.y**2)))
+ }
+ typeset -fS slen
+ len()
+ {
+ print -r -- $((sqrt(_.x**2 + _.y**2)))
+ }
+)
+unset z
+foobar_t z=(x=3 y=4)
+(( z.len == 5 )) || err_exit 'z.len should be 5'
+(( z.slen == 1 )) || err_exit 'z.slen should be 1'
+(( .sh.type.foobar_t.slen == 1 )) || err_exit '.sh.type.foobar_t.slen should be 1'
+(( .sh.type.foobar_t.len == 1 )) || err_exit '.sh.type.foobar_t.len should be 1'
+
+typeset -T z_t=( typeset -a ce )
+z_t x1
+x1.ce[3][4]=45
+compound c
+z_t -a c.x2
+c.x2[9]=x1
+got=$(typeset +p "c.x2[9].ce")
+exp='typeset -a c.x2[9].ce'
+[[ $got == "$exp" ]] || err_exit "typeset +p 'c.x2[9].ce' failed -- expected '$exp', got '$got'"
+
+unset b
+typeset -T a_t=(
+ typeset a="hello"
+)
+typeset -T b_t=(
+ a_t b
+)
+compound b
+compound -a b.ca
+b_t b.ca[4].b
+exp='typeset -C b=(typeset -C -a ca=( [4]=(b_t b=(a_t b=(a=hello))));)'
+got=$(typeset -p b)
+[[ $got == "$exp" ]] || err_exit 'typeset -p of nested type not correct'
+
+typeset -T u_t=(
+ integer dummy
+ unset()
+ {
+ print unset
+ }
+)
+unset z
+u_t -a x | read z
+[[ $z == unset ]] && err_exit 'unset discipline called on type creation'
+
+{ z=$($SHELL 2> /dev/null 'typeset -T foo; typeset -T') ;} 2> /dev/null
+[[ $z == 'typeset -T foo' ]] || err_exit '"typeset -T foo; typeset -T" failed'
+
+{ z=$($SHELL 2> /dev/null 'typeset -T foo=bar; typeset -T') ;} 2> /dev/null
+[[ $z ]] && err_exit '"typeset -T foo=bar" should not creates type foo'
+
+{
+$SHELL << \EOF
+ typeset -T board_t=(
+ compound -a board_y
+ function binsert
+ {
+ nameref figure=$1
+ integer y=$2 x=$3
+ typeset -m "_.board_y[y].board_x[x].field=figure"
+ }
+ )
+ function main
+ {
+ compound c=(
+ board_t b
+ )
+ for ((i=0 ; i < 2 ; i++ )) ; do
+ compound p=( hello=world )
+ c.b.binsert p 1 $i
+ done
+ exp='typeset -C c=(board_t b=(typeset -a board_y=( [1]=(typeset -a board_x=( [0]=(field=(hello=world;))[1]=(field=(hello=world)));));))'
+ [[ $(typeset -p c) == "$exp" ]] || exit 1
+ }
+ main
+EOF
+} 2> /dev/null
+if (( exitval=$?))
+then if [[ $(kill -l $exitval) == SEGV ]]
+ then err_exit 'typeset -m in type discipline causes exception'
+ else err_exit 'typeset -m in type discipline gives wrong value'
+ fi
+fi
+
+typeset -T pawn_t=(
+ print_debug()
+ {
+ print 'PAWN'
+ }
+)
+function main
+{
+ compound c=(
+ compound -a board
+ )
+
+ for ((i=2 ; i < 8 ; i++ )) ; do
+ pawn_t c.board[1][$i]
+ done
+
+}
+main 2> /dev/null && err_exit 'type assignment to compound array instance should generate an error'
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/variables.sh b/src/cmd/ksh93/tests/variables.sh
new file mode 100755
index 0000000..be7c308
--- /dev/null
+++ b/src/cmd/ksh93/tests/variables.sh
@@ -0,0 +1,665 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+[[ ${.sh.version} == "$KSH_VERSION" ]] || err_exit '.sh.version != KSH_VERSION'
+unset ss
+[[ ${@ss} ]] && err_exit '${@ss} should be empty string when ss is unset'
+[[ ${!ss} == ss ]] || err_exit '${!ss} should be ss when ss is unset'
+[[ ${#ss} == 0 ]] || err_exit '${#ss} should be 0 when ss is unset'
+# RANDOM
+if (( RANDOM==RANDOM || $RANDOM==$RANDOM ))
+then err_exit RANDOM variable not working
+fi
+# SECONDS
+sleep 3
+if (( SECONDS < 2 ))
+then err_exit SECONDS variable not working
+fi
+# _
+set abc def
+if [[ $_ != def ]]
+then err_exit _ variable not working
+fi
+# ERRNO
+#set abc def
+#rm -f foobar#
+#ERRNO=
+#2> /dev/null < foobar#
+#if (( ERRNO == 0 ))
+#then err_exit ERRNO variable not working
+#fi
+# PWD
+if [[ ! $PWD -ef . ]]
+then err_exit PWD variable failed, not equivalent to .
+fi
+# PPID
+exp=$$
+got=${ $SHELL -c 'print $PPID'; }
+if [[ ${ $SHELL -c 'print $PPID'; } != $$ ]]
+then err_exit "PPID variable failed -- expected '$exp', got '$got'"
+fi
+# OLDPWD
+old=$PWD
+cd /
+if [[ $OLDPWD != $old ]]
+then err_exit "OLDPWD variable failed -- expected '$old', got '$OLDPWD'"
+fi
+cd $old || err_exit cd failed
+# REPLY
+read <<-!
+ foobar
+ !
+if [[ $REPLY != foobar ]]
+then err_exit REPLY variable not working
+fi
+integer save=$LINENO
+# LINENO
+LINENO=10
+#
+# These lines intentionally left blank
+#
+if (( LINENO != 13))
+then err_exit LINENO variable not working
+fi
+LINENO=save+10
+IFS=:
+x=a::b::c
+if [[ $x != a::b::c ]]
+then err_exit "word splitting on constants"
+fi
+set -- $x
+if [[ $# != 5 ]]
+then err_exit ":: doesn't separate null arguments "
+fi
+set x
+if x$1=0 2> /dev/null
+then err_exit "x\$1=value treated as an assignment"
+fi
+# check for attributes across subshells
+typeset -i x=3
+y=1/0
+if ( typeset x=y ) 2> /dev/null
+then err_exit "attributes not passed to subshells"
+fi
+unset x
+function x.set
+{
+ nameref foo=${.sh.name}.save
+ foo=${.sh.value}
+ .sh.value=$0
+}
+x=bar
+if [[ $x != x.set ]]
+then err_exit 'x.set does not override assignment'
+fi
+x.get()
+{
+ nameref foo=${.sh.name}.save
+ .sh.value=$foo
+}
+
+if [[ $x != bar ]]
+then err_exit 'x.get does not work correctly'
+fi
+typeset +n foo
+unset foo
+foo=bar
+(
+ unset foo
+ set +u
+ if [[ $foo != '' ]]
+ then err_exit '$foo not null after unset in subsehll'
+ fi
+)
+if [[ $foo != bar ]]
+then err_exit 'unset foo in subshell produces side effect '
+fi
+unset foo
+if [[ $( { : ${foo?hi there} ; } 2>&1) != *'hi there' ]]
+then err_exit '${foo?hi there} with foo unset does not print hi there on 2'
+fi
+x=$0
+set foobar
+if [[ ${@:0} != "$x foobar" ]]
+then err_exit '${@:0} not expanding correctly'
+fi
+set --
+if [[ ${*:0:1} != "$0" ]]
+then err_exit '${@:0} not expanding correctly'
+fi
+ACCESS=0
+function COUNT.set
+{
+ (( ACCESS++ ))
+}
+COUNT=0
+(( COUNT++ ))
+if (( COUNT != 1 || ACCESS!=2 ))
+then err_exit " set discipline failure COUNT=$COUNT ACCESS=$ACCESS"
+fi
+LANG=C > /dev/null 2>&1
+if [[ $LANG != C ]]
+then err_exit "C locale not working"
+fi
+unset RANDOM
+unset -n foo
+foo=junk
+function foo.get
+{
+ .sh.value=stuff
+ unset -f foo.get
+}
+if [[ $foo != stuff ]]
+then err_exit "foo.get discipline not working"
+fi
+if [[ $foo != junk ]]
+then err_exit "foo.get discipline not working after unset"
+fi
+# special variables
+set -- 1 2 3 4 5 6 7 8 9 10
+sleep 1000 &
+if [[ $(print -r -- ${#10}) != 2 ]]
+then err_exit '${#10}, where ${10}=10 not working'
+fi
+for i in @ '*' ! '#' - '?' '$'
+do false
+ eval foo='$'$i bar='$'{$i}
+ if [[ ${foo} != "${bar}" ]]
+ then err_exit "\$$i not equal to \${$i}"
+ fi
+ command eval bar='$'{$i%?} 2> /dev/null || err_exit "\${$i%?} gives syntax error"
+ if [[ $i != [@*] && ${foo%?} != "$bar" ]]
+ then err_exit "\${$i%?} not correct"
+ fi
+ command eval bar='$'{$i#?} 2> /dev/null || err_exit "\${$i#?} gives syntax error"
+ if [[ $i != [@*] && ${foo#?} != "$bar" ]]
+ then err_exit "\${$i#?} not correct"
+ fi
+ command eval foo='$'{$i} bar='$'{#$i} || err_exit "\${#$i} gives synta
+x error"
+ if [[ $i != @([@*]) && ${#foo} != "$bar" ]]
+ then err_exit "\${#$i} not correct"
+ fi
+done
+kill $!
+unset x
+CDPATH=/
+x=$(cd ${tmp#/})
+if [[ $x != $tmp ]]
+then err_exit 'CDPATH does not display new directory'
+fi
+CDPATH=/:
+x=$(cd ${tmp%/*}; cd ${tmp##*/})
+if [[ $x ]]
+then err_exit 'CDPATH displays new directory when not used'
+fi
+x=$(cd ${tmp#/})
+if [[ $x != $tmp ]]
+then err_exit "CDPATH ${tmp#/} does not display new directory"
+fi
+TMOUT=100
+(TMOUT=20)
+if (( TMOUT !=100 ))
+then err_exit 'setting TMOUT in subshell affects parent'
+fi
+unset y
+function setdisc # var
+{
+ eval function $1.get'
+ {
+ .sh.value=good
+ }
+ '
+}
+y=bad
+setdisc y
+if [[ $y != good ]]
+then err_exit 'setdisc function not working'
+fi
+integer x=$LINENO
+: $'\
+'
+if (( LINENO != x+3 ))
+then err_exit '\<newline> gets linenumber count wrong'
+fi
+set --
+set -- "${@-}"
+if (( $# !=1 ))
+then err_exit '"${@-}" not expanding to null string'
+fi
+for i in : % + / 3b '**' '***' '@@' '{' '[' '}' !! '*a' '$foo'
+do (eval : \${"$i"} 2> /dev/null) && err_exit "\${$i} not an syntax error"
+done
+unset IFS
+( IFS=' ' ; read -r a b c <<-!
+ x y z
+ !
+ if [[ $b ]]
+ then err_exit 'IFS=" " not causing adjacent space to be null string'
+ fi
+)
+read -r a b c <<-!
+x y z
+!
+if [[ $b != y ]]
+then err_exit 'IFS not restored after subshell'
+fi
+
+# The next part generates 3428 IFS set/read tests.
+
+unset IFS x
+function split
+{
+ i=$1 s=$2 r=$3
+ IFS=': '
+ set -- $i
+ IFS=' '
+ g="[$#]"
+ while :
+ do case $# in
+ 0) break ;;
+ esac
+ g="$g($1)"
+ shift
+ done
+ case "$g" in
+ "$s") ;;
+ *) err_exit "IFS=': '; set -- '$i'; expected '$s' got '$g'" ;;
+ esac
+ print "$i" | IFS=": " read arg rem; g="($arg)($rem)"
+ case "$g" in
+ "$r") ;;
+ *) err_exit "IFS=': '; read '$i'; expected '$r' got '$g'" ;;
+ esac
+}
+for str in \
+ '-' \
+ 'a' \
+ '- -' \
+ '- a' \
+ 'a -' \
+ 'a b' \
+ '- - -' \
+ '- - a' \
+ '- a -' \
+ '- a b' \
+ 'a - -' \
+ 'a - b' \
+ 'a b -' \
+ 'a b c'
+do
+ IFS=' '
+ set x $str
+ shift
+ case $# in
+ 0) continue ;;
+ esac
+ f1=$1
+ case $f1 in
+ '-') f1='' ;;
+ esac
+ shift
+ case $# in
+ 0) for d0 in '' ' '
+ do
+ for d1 in '' ' ' ':' ' :' ': ' ' : '
+ do
+ case $f1$d1 in
+ '') split "$d0$f1$d1" "[0]" "()()" ;;
+ ' ') ;;
+ *) split "$d0$f1$d1" "[1]($f1)" "($f1)()" ;;
+ esac
+ done
+ done
+ continue
+ ;;
+ esac
+ f2=$1
+ case $f2 in
+ '-') f2='' ;;
+ esac
+ shift
+ case $# in
+ 0) for d0 in '' ' '
+ do
+ for d1 in ' ' ':' ' :' ': ' ' : '
+ do
+ case ' ' in
+ $f1$d1|$d1$f2) continue ;;
+ esac
+ for d2 in '' ' ' ':' ' :' ': ' ' : '
+ do
+ case $f2$d2 in
+ '') split "$d0$f1$d1$f2$d2" "[1]($f1)" "($f1)()" ;;
+ ' ') ;;
+ *) split "$d0$f1$d1$f2$d2" "[2]($f1)($f2)" "($f1)($f2)" ;;
+ esac
+ done
+ done
+ done
+ continue
+ ;;
+ esac
+ f3=$1
+ case $f3 in
+ '-') f3='' ;;
+ esac
+ shift
+ case $# in
+ 0) for d0 in '' ' '
+ do
+ for d1 in ':' ' :' ': ' ' : '
+ do
+ case ' ' in
+ $f1$d1|$d1$f2) continue ;;
+ esac
+ for d2 in ' ' ':' ' :' ': ' ' : '
+ do
+ case $f2$d2 in
+ ' ') continue ;;
+ esac
+ case ' ' in
+ $f2$d2|$d2$f3) continue ;;
+ esac
+ for d3 in '' ' ' ':' ' :' ': ' ' : '
+ do
+ case $f3$d3 in
+ '') split "$d0$f1$d1$f2$d2$f3$d3" "[2]($f1)($f2)" "($f1)($f2)" ;;
+ ' ') ;;
+ *) x=$f2$d2$f3$d3
+ x=${x#' '}
+ x=${x%' '}
+ split "$d0$f1$d1$f2$d2$f3$d3" "[3]($f1)($f2)($f3)" "($f1)($x)"
+ ;;
+ esac
+ done
+ done
+ done
+ done
+ continue
+ ;;
+ esac
+done
+unset IFS
+
+if [[ $( (print ${12345:?}) 2>&1) != *12345* ]]
+then err_exit 'incorrect error message with ${12345?}'
+fi
+unset foobar
+if [[ $( (print ${foobar:?}) 2>&1) != *foobar* ]]
+then err_exit 'incorrect error message with ${foobar?}'
+fi
+unset bar
+if [[ $( (print ${bar:?bam}) 2>&1) != *bar*bam* ]]
+then err_exit 'incorrect error message with ${foobar?}'
+fi
+{ $SHELL -c '
+function foo
+{
+ typeset SECONDS=0
+ sleep 1.5
+ print $SECONDS
+
+}
+x=$(foo)
+(( x >1 && x < 2 ))
+'
+} 2> /dev/null || err_exit 'SECONDS not working in function'
+cat > $tmp/script <<-\!
+ posixfun()
+ {
+ unset x
+ nameref x=$1
+ print -r -- "$x"
+ }
+ function fun
+ {
+ nameref x=$1
+ print -r -- "$x"
+ }
+ if [[ $1 ]]
+ then file=${.sh.file}
+ else print -r -- "${.sh.file}"
+ fi
+!
+chmod +x $tmp/script
+. $tmp/script 1
+[[ $file == $tmp/script ]] || err_exit ".sh.file not working for dot scripts"
+[[ $($SHELL $tmp/script) == $tmp/script ]] || err_exit ".sh.file not working for scripts"
+[[ $(posixfun .sh.file) == $tmp/script ]] || err_exit ".sh.file not working for posix functions"
+[[ $(fun .sh.file) == $tmp/script ]] || err_exit ".sh.file not working for functions"
+[[ $(posixfun .sh.fun) == posixfun ]] || err_exit ".sh.fun not working for posix functions"
+[[ $(fun .sh.fun) == fun ]] || err_exit ".sh.fun not working for functions"
+[[ $(posixfun .sh.subshell) == 1 ]] || err_exit ".sh.subshell not working for posix functions"
+[[ $(fun .sh.subshell) == 1 ]] || err_exit ".sh.subshell not working for functions"
+(
+ [[ $(posixfun .sh.subshell) == 2 ]] || err_exit ".sh.subshell not working for posix functions in subshells"
+ [[ $(fun .sh.subshell) == 2 ]] || err_exit ".sh.subshell not working for functions in subshells"
+ (( .sh.subshell == 1 )) || err_exit ".sh.subshell not working in a subshell"
+)
+TIMEFORMAT='this is a test'
+[[ $({ { time :;} 2>&1;}) == "$TIMEFORMAT" ]] || err_exit 'TIMEFORMAT not working'
+: ${.sh.version}
+[[ $(alias integer) == *.sh.* ]] && err_exit '.sh. prefixed to alias name'
+: ${.sh.version}
+[[ $(whence rm) == *.sh.* ]] && err_exit '.sh. prefixed to tracked alias name'
+: ${.sh.version}
+[[ $(cd /bin;env | grep PWD=) == *.sh.* ]] && err_exit '.sh. prefixed to PWD'
+# unset discipline bug fix
+dave=dave
+function dave.unset
+{
+ unset dave
+}
+unset dave
+[[ $(typeset +f) == *dave.* ]] && err_exit 'unset discipline not removed'
+
+print 'print ${VAR}' > $tmp/script
+unset VAR
+VAR=new $tmp/script > $tmp/out
+got=$(<$tmp/out)
+[[ $got == new ]] || err_exit "previously unset environment variable not passed to script, expected 'new', got '$got'"
+[[ ! $VAR ]] || err_exit "previously unset environment variable set after script, expected '', got '$VAR'"
+unset VAR
+VAR=old
+VAR=new $tmp/script > $tmp/out
+got=$(<$tmp/out)
+[[ $got == new ]] || err_exit "environment variable covering local variable not passed to script, expected 'new', got '$got'"
+[[ $VAR == old ]] || err_exit "previously set local variable changed after script, expected 'old', got '$VAR'"
+unset VAR
+export VAR=old
+VAR=new $tmp/script > $tmp/out
+got=$(<$tmp/out)
+[[ $got == new ]] || err_exit "environment variable covering environment variable not passed to script, expected 'new', got '$got'"
+[[ $VAR == old ]] || err_exit "previously set environment variable changed after script, expected 'old', got '$VAR'"
+
+(
+ unset dave
+ function dave.append
+ {
+ .sh.value+=$dave
+ dave=
+ }
+ dave=foo; dave+=bar
+ [[ $dave == barfoo ]] || exit 2
+) 2> /dev/null
+case $? in
+0) ;;
+1) err_exit 'append discipline not implemented';;
+*) err_exit 'append discipline not working';;
+esac
+.sh.foobar=hello
+{
+ function .sh.foobar.get
+ {
+ .sh.value=world
+ }
+} 2> /dev/null || err_exit "cannot add get discipline to .sh.foobar"
+[[ ${.sh.foobar} == world ]] || err_exit 'get discipline for .sh.foobar not working'
+x='a|b'
+IFS='|'
+set -- $x
+[[ $2 == b ]] || err_exit '$2 should be b after set'
+exec 3>&2 2> /dev/null
+set -x
+( IFS= ) 2> /dev/null
+set +x
+exec 2>&3-
+set -- $x
+[[ $2 == b ]] || err_exit '$2 should be b after subshell'
+: & pid=$!
+( : & )
+[[ $pid == $! ]] || err_exit '$! value not preserved across subshells'
+unset foo
+typeset -A foo
+function foo.set
+{
+ case ${.sh.subscript} in
+ bar) if ((.sh.value > 1 ))
+ then .sh.value=5
+ foo[barrier_hit]=yes
+ fi
+ ;;
+ barrier_hit)
+ if [[ ${.sh.value} == yes ]]
+ then foo[barrier_not_hit]=no
+ else foo[barrier_not_hit]=yes
+ fi
+ ;;
+ esac
+}
+foo[barrier_hit]=no
+foo[bar]=1
+(( foo[bar] == 1 )) || err_exit 'foo[bar] should be 1'
+[[ ${foo[barrier_hit]} == no ]] || err_exit 'foo[barrier_hit] should be no'
+[[ ${foo[barrier_not_hit]} == yes ]] || err_exit 'foo[barrier_not_hit] should be yes'
+foo[barrier_hit]=no
+foo[bar]=2
+(( foo[bar] == 5 )) || err_exit 'foo[bar] should be 5'
+[[ ${foo[barrier_hit]} == yes ]] || err_exit 'foo[barrier_hit] should be yes'
+[[ ${foo[barrier_not_hit]} == no ]] || err_exit 'foo[barrier_not_hit] should be no'
+unset x
+typeset -i x
+function x.set
+{
+ typeset sub=${.sh.subscript}
+ (( sub > 0 )) && (( x[sub-1]= x[sub-1] + .sh.value ))
+}
+x[0]=0 x[1]=1 x[2]=2 x[3]=3
+[[ ${x[@]} == '12 8 5 3' ]] || err_exit 'set discipline for indexed array not working correctly'
+float seconds
+((SECONDS=3*4))
+seconds=SECONDS
+(( seconds < 12 || seconds > 12.1 )) && err_exit "SECONDS is $seconds and should be close to 12"
+unset a
+function a.set
+{
+ print -r -- "${.sh.name}=${.sh.value}"
+}
+[[ $(a=1) == a=1 ]] || err_exit 'set discipline not working in subshell assignment'
+[[ $(a=1 :) == a=1 ]] || err_exit 'set discipline not working in subshell command'
+
+[[ ${.sh.subshell} == 0 ]] || err_exit '${.sh.subshell} should be 0'
+(
+ [[ ${.sh.subshell} == 1 ]] || err_exit '${.sh.subshell} should be 1'
+ (
+ [[ ${.sh.subshell} == 2 ]] || err_exit '${.sh.subshell} should be 2'
+ )
+)
+
+set -- {1..32768}
+(( $# == 32768 )) || err_exit "\$# failed -- expected 32768, got $#"
+set --
+
+unset r v x
+path=$PATH
+x=foo
+for v in EDITOR VISUAL OPTIND CDPATH FPATH PATH ENV LINENO RANDOM SECONDS _
+do nameref r=$v
+ unset $v
+ if ( $SHELL -c "unset $v; : \$$v" ) 2>/dev/null
+ then [[ $r ]] && err_exit "unset $v failed -- expected '', got '$r'"
+ r=$x
+ [[ $r == $x ]] || err_exit "$v=$x failed -- expected '$x', got '$r'"
+ else err_exit "unset $v; : \$$v failed"
+ fi
+done
+
+x=x
+for v in LC_ALL LC_CTYPE LC_MESSAGES LC_COLLATE LC_NUMERIC
+do nameref r=$v
+ unset $v
+ [[ $r ]] && err_exit "unset $v failed -- expected '', got '$r'"
+ d=$($SHELL -c "$v=$x" 2>&1)
+ [[ $d ]] || err_exit "$v=$x failed -- expected locale diagnostic"
+ { g=$( r=$x; print -- $r ); } 2>/dev/null
+ [[ $g == '' ]] || err_exit "$v=$x failed -- expected '', got '$g'"
+ { g=$( r=C; r=$x; print -- $r ); } 2>/dev/null
+ [[ $g == 'C' ]] || err_exit "$v=C; $v=$x failed -- expected 'C', got '$g'"
+done
+PATH=$path
+
+cd $tmp
+
+print print -n zzz > zzz
+chmod +x zzz
+exp='aaazzz'
+got=$($SHELL -c 'unset SHLVL; print -n aaa; ./zzz' 2>&1) >/dev/null 2>&1
+[[ $got == "$exp" ]] || err_exit "unset SHLVL causes script failure -- expected '$exp', got '$got'"
+
+mkdir glean
+for cmd in date ok
+do exp="$cmd ok"
+ rm -f $cmd
+ print print $exp > glean/$cmd
+ chmod +x glean/$cmd
+ got=$(CDPATH=:.. $SHELL -c "PATH=:/bin:/usr/bin; date > /dev/null; cd glean && ./$cmd" 2>&1)
+ [[ $got == "$exp" ]] || err_exit "cd with CDPATH after PATH change failed -- expected '$exp', got '$got'"
+done
+
+v=LC_CTYPE
+unset $v
+[[ -v $v ]] && err_exit "unset $v; [[ -v $v ]] failed"
+eval $v=C
+[[ -v $v ]] || err_exit "$v=C; [[ -v $v ]] failed"
+
+cmd='set --nounset; unset foo; : ${!foo*}'
+$SHELL -c "$cmd" 2>/dev/null || err_exit "'$cmd' exit status $?, expected 0"
+
+SHLVL=1
+level=$($SHELL -c $'$SHELL -c \'print -r "$SHLVL"\'')
+[[ $level == 3 ]] || err_exit "SHLVL should be 3 not $level"
+
+[[ $($SHELL -c '{ x=1; : ${x.};print ok;}' 2> /dev/null) == ok ]] || err_exit '${x.} where x is a simple variable causes shell to abort'
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/vartree1.sh b/src/cmd/ksh93/tests/vartree1.sh
new file mode 100755
index 0000000..d558dc6
--- /dev/null
+++ b/src/cmd/ksh93/tests/vartree1.sh
@@ -0,0 +1,215 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+#
+# variable tree test #001
+# Propose of this test is whether ksh93 handles global variable trees
+# and function-local variable trees the same way, including "nameref"
+# and "unset" handling.
+#
+
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ (( Errors+=1 ))
+}
+
+alias err_exit='err_exit $LINENO'
+
+function build_tree
+{
+#set -o errexit -o xtrace
+ typeset index
+ typeset s
+ typeset i
+ typeset dummy
+ typeset a b c d e f
+
+ nameref dest_tree="$1" # destination tree
+ nameref srcdata="$2" # source data
+ typeset tree_mode="$3" # mode to define the type of leads
+
+ typeset -A dest_tree.l1
+
+ for index in "${!srcdata.hashnodes[@]}" ; do
+ nameref node=srcdata.hashnodes["${index}"]
+
+ for i in "${node.xlfd[@]}" ; do
+ IFS='-' read dummy a b c d e f <<<"$i"
+
+ if [[ "$a" == "" ]] ; then
+ a="$dummy"
+ fi
+
+ [[ "$a" == "" ]] && a='-'
+ [[ "$b" == "" ]] && b='-'
+ [[ "$c" == "" ]] && c='-'
+
+ if [[ "${dest_tree.l1["$a"]}" == "" ]] ; then
+ #if ! (unset dest_tree.l1["$a"]) ; then
+ typeset -A dest_tree.l1["$a"].l2
+ fi
+
+ if [[ "${dest_tree.l1["$a"].l2["$b"]}" == "" ]] ; then
+ #if ! (unset dest_tree.l1["$a"].l2["$b"]) ; then
+ typeset -A dest_tree.l1["$a"].l2["$b"].l3
+ fi
+
+ if [[ "${!dest_tree.l1["$a"].l2["$b"].l3["$c"].entries[*]}" == "" ]] ; then
+ typeset -A dest_tree.l1["$a"].l2["$b"].l3["$c"].entries
+ fi
+
+ #dest_tree.l1["$a"].l2["$b"].l3["$c"].entries+=( "$index" )
+ typeset new_index
+ if [[ "${tree_mode}" == "leaf_name" ]] ; then
+ new_index=$(( ${#dest_tree.l1["$a"].l2["$b"].l3["$c"].entries[@]}+1 ))
+ else
+ new_index="${node.name}"
+
+ # skip if the leaf node already exists
+ if [[ "${dest_tree.l1["$a"].l2["$b"].l3["$c"].entries[${new_index}]}" != "" ]] ; then
+ continue
+ fi
+ fi
+
+ add_tree_leaf dest_tree.l1["$a"].l2["$b"].l3["$c"].entries[${new_index}] "${index}" "${tree_mode}"
+ done
+ done
+
+ return 0
+}
+
+function add_tree_leaf
+{
+ nameref tree_leafnode="$1"
+ nameref data_node=srcdata.hashnodes["$2"]
+ typeset add_mode="$3"
+
+ case "${add_mode}" in
+ "leaf_name")
+ tree_leafnode="${data_node.name}"
+ return 0
+ ;;
+ "leaf_compound")
+ tree_leafnode=(
+ typeset name="${data_node.name}"
+ typeset -a filenames=( "${data_node.filenames[@]}" )
+ typeset -a comments=( "${data_node.comments[@]}" )
+ typeset -a xlfd=( "${data_node.xlfd[@]}" )
+ )
+ return 0
+ ;;
+ *)
+ print -u2 -f "ERROR: Unknown mode %s in add_tree_leaf\n" "${add_mode}"
+ return 1
+ ;;
+ esac
+
+ # not reached
+ return 1
+}
+
+# "mysrcdata_local" and "mysrcdata_global" must be identical
+typeset mysrcdata_global=(
+ typeset -A hashnodes=(
+ [abcd]=(
+ name='abcd'
+ typeset -a xlfd=(
+ '-urw-itc zapfchancery-medium-i-normal--0-0-0-0-p-0-iso8859-1'
+ '-urw-itc zapfdingbats-medium-r-normal--0-0-0-0-p-0-adobe-fontspecific'
+ '-urw-itc zapfdingbats-medium-r-normal--0-0-0-0-p-0-sun-fontspecific'
+ )
+ typeset -a comments=(
+ 'comment 1'
+ 'comment 2'
+ 'comment 3'
+ )
+ typeset -a filenames=(
+ '/home/foo/abcd_1'
+ '/home/foo/abcd_2'
+ '/home/foo/abcd_3'
+ )
+ )
+ )
+)
+
+mytree_global=()
+
+function main
+{
+ # "mysrcdata_local" and "mysrcdata_global" must be identical
+ typeset mysrcdata_local=(
+ typeset -A hashnodes=(
+ [abcd]=(
+ name='abcd'
+ typeset -a xlfd=(
+ '-urw-itc zapfchancery-medium-i-normal--0-0-0-0-p-0-iso8859-1'
+ '-urw-itc zapfdingbats-medium-r-normal--0-0-0-0-p-0-adobe-fontspecific'
+ '-urw-itc zapfdingbats-medium-r-normal--0-0-0-0-p-0-sun-fontspecific'
+ )
+ typeset -a comments=(
+ 'comment 1'
+ 'comment 2'
+ 'comment 3'
+ )
+ typeset -a filenames=(
+ '/home/foo/abcd_1'
+ '/home/foo/abcd_2'
+ '/home/foo/abcd_3'
+ )
+ )
+ )
+ )
+
+ # build tree using global tree variables
+ build_tree mytree_global mysrcdata_global leaf_compound || \
+ err_exit 'build_tree mytree_global mysrcdata_global leaf_compound returned an error'
+
+ (( $(print -r -- "${mytree_global}" | wc -l) > 10 )) || err_exit "compound tree 'mytree_global' too small"
+
+ # build tree using local tree variables
+ mytree_local=()
+ build_tree mytree_local mysrcdata_local leaf_compound || \
+ err_exit 'build_tree mytree_local mysrcdata_local leaf_compound returned an error'
+
+ (( $(print -r -- "${mytree_local}" | wc -l) > 10 )) || err_exit "compound tree 'mytree_local' too small"
+
+ # Compare trees
+ if [[ "${mytree_global}" != "${mytree_local}" ]] ; then
+ err_exit "compound trees 'mytree_local' and 'mytree_global' not identical"
+ fi
+
+ unset 'mytree_global.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]' ||
+ err_exit "variable 'mytree_global.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]' not found"
+
+ [[ "${mytree_global}" != "${mytree_local}" ]] || err_exit "mytree_global and mytree_local should differ"
+
+ unset 'mytree_local.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]' ||
+ err_exit "variable 'mytree_local.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]' not found"
+
+ # Compare trees (after "unset")
+ if [[ "${mytree_global}" != "${mytree_local}" ]] ; then
+ err_exit "compound trees 'mytree_local' and 'mytree_global' not identical after unset"
+ fi
+}
+
+main
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/vartree2.sh b/src/cmd/ksh93/tests/vartree2.sh
new file mode 100755
index 0000000..e3e4cff
--- /dev/null
+++ b/src/cmd/ksh93/tests/vartree2.sh
@@ -0,0 +1,335 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+#
+# variable tree test #002
+# Propose of this test is whether ksh93 handles global variable trees
+# and function-local variable trees the same way, including "nameref"
+# and "unset" handling.
+#
+
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ (( Errors+=1 ))
+}
+
+alias err_exit='err_exit $LINENO'
+
+# "built_tree1" and "built_tree2" are identical except the way how they test
+# whether a variable exists:
+# - "built_tree1" uses "${varname}" != "", e.g. looking whether the variable
+# as non-zero length content
+# - "built_tree2" uses "! (unset varname)", e.g. "unset" in a subshell
+function build_tree1
+{
+#set -o errexit -o xtrace
+ typeset index
+ typeset s
+ typeset i
+ typeset dummy
+ typeset a b c d e f
+
+ nameref dest_tree="$1" # destination tree
+ nameref srcdata="$2" # source data
+ typeset tree_mode="$3" # mode to define the type of leads
+
+ typeset -A dest_tree.l1
+
+ for index in "${!srcdata.hashnodes[@]}" ; do
+ nameref node=srcdata.hashnodes["${index}"]
+
+ for i in "${node.xlfd[@]}" ; do
+ IFS='-' read dummy a b c d e f <<<"$i"
+
+ if [[ "$a" == "" ]] ; then
+ a="$dummy"
+ fi
+
+ [[ "$a" == "" ]] && a='-'
+ [[ "$b" == "" ]] && b='-'
+ [[ "$c" == "" ]] && c='-'
+
+ if [[ "${dest_tree.l1["$a"]}" == "" ]] ; then
+ #if ! (unset dest_tree.l1["$a"]) ; then
+ typeset -A dest_tree.l1["$a"].l2
+ fi
+
+ if [[ "${dest_tree.l1["$a"].l2["$b"]}" == "" ]] ; then
+ #if ! (unset dest_tree.l1["$a"].l2["$b"]) ; then
+ typeset -A dest_tree.l1["$a"].l2["$b"].l3
+ fi
+
+ if [[ "${!dest_tree.l1["$a"].l2["$b"].l3["$c"].entries[*]}" == "" ]] ; then
+ typeset -A dest_tree.l1["$a"].l2["$b"].l3["$c"].entries
+ fi
+
+ typeset new_index
+ if [[ "${tree_mode}" == "leaf_name" ]] ; then
+ new_index=$(( ${#dest_tree.l1["$a"].l2["$b"].l3["$c"].entries[@]}+1 ))
+ else
+ new_index="${node.name}"
+
+ # skip if the leaf node already exists
+ if [[ "${dest_tree.l1["$a"].l2["$b"].l3["$c"].entries[${new_index}]}" != "" ]] ; then
+ continue
+ fi
+ fi
+
+ add_tree_leaf dest_tree.l1["$a"].l2["$b"].l3["$c"].entries[${new_index}] "${index}" "${tree_mode}"
+ done
+ done
+
+ return 0
+}
+
+# "built_tree1" and "built_tree2" are identical except the way how they test
+# whether a variable exists:
+# - "built_tree1" uses "${varname}" != "", e.g. looking whether the variable
+# as non-zero length content
+# - "built_tree2" uses "! (unset varname)", e.g. "unset" in a subshell
+function build_tree2
+{
+#set -o errexit -o xtrace
+ typeset index
+ typeset s
+ typeset i
+ typeset dummy
+ typeset a b c d e f
+
+ nameref dest_tree="$1" # destination tree
+ nameref srcdata="$2" # source data
+ typeset tree_mode="$3" # mode to define the type of leads
+
+ typeset -A dest_tree.l1
+
+ for index in "${!srcdata.hashnodes[@]}" ; do
+ nameref node=srcdata.hashnodes["${index}"]
+
+ for i in "${node.xlfd[@]}" ; do
+ IFS='-' read dummy a b c d e f <<<"$i"
+
+ if [[ "$a" == "" ]] ; then
+ a="$dummy"
+ fi
+
+ [[ "$a" == "" ]] && a='-'
+ [[ "$b" == "" ]] && b='-'
+ [[ "$c" == "" ]] && c='-'
+
+ #if [[ "${dest_tree.l1["$a"]}" == "" ]] ; then
+ if ! (unset dest_tree.l1["$a"]) ; then
+ typeset -A dest_tree.l1["$a"].l2
+ fi
+
+ #if [[ "${dest_tree.l1["$a"].l2["$b"]}" == "" ]] ; then
+ if ! (unset dest_tree.l1["$a"].l2["$b"]) ; then
+ typeset -A dest_tree.l1["$a"].l2["$b"].l3
+ fi
+
+ if [[ "${!dest_tree.l1["$a"].l2["$b"].l3["$c"].entries[*]}" == "" ]] ; then
+ typeset -A dest_tree.l1["$a"].l2["$b"].l3["$c"].entries
+ fi
+
+ typeset new_index
+ if [[ "${tree_mode}" == "leaf_name" ]] ; then
+ new_index=$(( ${#dest_tree.l1["$a"].l2["$b"].l3["$c"].entries[@]}+1 ))
+ else
+ new_index="${node.name}"
+
+ # skip if the leaf node already exists
+ if [[ "${dest_tree.l1["$a"].l2["$b"].l3["$c"].entries[${new_index}]}" != "" ]] ; then
+ continue
+ fi
+ fi
+
+ add_tree_leaf dest_tree.l1["$a"].l2["$b"].l3["$c"].entries[${new_index}] "${index}" "${tree_mode}"
+ done
+ done
+
+ return 0
+}
+
+
+function add_tree_leaf
+{
+ nameref tree_leafnode="$1"
+ nameref data_node=srcdata.hashnodes["$2"]
+ typeset add_mode="$3"
+
+ case "${add_mode}" in
+ "leaf_name")
+ tree_leafnode="${data_node.name}"
+ return 0
+ ;;
+ "leaf_compound")
+ tree_leafnode=(
+ typeset name="${data_node.name}"
+ typeset -a filenames=( "${data_node.filenames[@]}" )
+ typeset -a comments=( "${data_node.comments[@]}" )
+ typeset -a xlfd=( "${data_node.xlfd[@]}" )
+ )
+ return 0
+ ;;
+ *)
+ print -u2 -f "ERROR: Unknown mode %s in add_tree_leaf\n" "${add_mode}"
+ return 1
+ ;;
+ esac
+
+ # not reached
+ return 1
+}
+
+# "mysrcdata_local" and "mysrcdata_global" must be identical
+typeset mysrcdata_global=(
+ typeset -A hashnodes=(
+ [abcd]=(
+ name='abcd'
+ typeset -a xlfd=(
+ '-urw-itc zapfchancery-medium-i-normal--0-0-0-0-p-0-iso8859-1'
+ '-urw-itc zapfdingbats-medium-r-normal--0-0-0-0-p-0-adobe-fontspecific'
+ '-urw-itc zapfdingbats-medium-r-normal--0-0-0-0-p-0-sun-fontspecific'
+ )
+ typeset -a comments=(
+ 'comment 1'
+ 'comment 2'
+ 'comment 3'
+ )
+ typeset -a filenames=(
+ '/home/foo/abcd_1'
+ '/home/foo/abcd_2'
+ '/home/foo/abcd_3'
+ )
+ )
+ )
+)
+
+mytree_global1=()
+mytree_global2=()
+
+function main
+{
+ # "mysrcdata_local" and "mysrcdata_global" must be identical
+ typeset mysrcdata_local=(
+ typeset -A hashnodes=(
+ [abcd]=(
+ name='abcd'
+ typeset -a xlfd=(
+ '-urw-itc zapfchancery-medium-i-normal--0-0-0-0-p-0-iso8859-1'
+ '-urw-itc zapfdingbats-medium-r-normal--0-0-0-0-p-0-adobe-fontspecific'
+ '-urw-itc zapfdingbats-medium-r-normal--0-0-0-0-p-0-sun-fontspecific'
+ )
+ typeset -a comments=(
+ 'comment 1'
+ 'comment 2'
+ 'comment 3'
+ )
+ typeset -a filenames=(
+ '/home/foo/abcd_1'
+ '/home/foo/abcd_2'
+ '/home/foo/abcd_3'
+ )
+ )
+ )
+ )
+
+ #### Build tree using global tree variables
+ build_tree1 mytree_global1 mysrcdata_global leaf_compound || \
+ err_exit 'build_tree1 mytree_global1 mysrcdata_global leaf_compound returned an error'
+ (( $(print -r -- "${mytree_global1}" | wc -l) > 10 )) || err_exit "compound tree 'mytree_global1' too small"
+
+ build_tree2 mytree_global2 mysrcdata_global leaf_compound || \
+ err_exit 'build_tree2 mytree_global2 mysrcdata_global leaf_compound returned an error'
+ (( $(print -r -- "${mytree_global2}" | wc -l) > 10 )) || err_exit "compound tree 'mytree_global2' too small"
+
+
+ #### build tree using local tree variables
+ mytree_local1=()
+ mytree_local2=()
+
+ build_tree1 mytree_local1 mysrcdata_local leaf_compound || \
+ err_exit 'build_tree1 mytree_local1 mysrcdata_local leaf_compound returned an error'
+ (( $(print -r -- "${mytree_local1}" | wc -l) > 10 )) || err_exit "compound tree 'mytree_local1' too small"
+
+ build_tree2 mytree_local2 mysrcdata_local leaf_compound || \
+ err_exit 'build_tree2 mytree_local2 mysrcdata_local leaf_compound returned an error'
+ (( $(print -r -- "${mytree_local2}" | wc -l) > 10 )) || err_exit "compound tree 'mytree_local2' too small"
+
+
+ #### Compare treess
+ if [[ "${mytree_global1}" != "${mytree_local1}" ]] ; then
+ err_exit "compound trees 'mytree_global1' and 'mytree_local1' not identical"
+ fi
+
+ if [[ "${mytree_global1}" != "${mytree_global2}" ]] ; then
+ err_exit "compound trees 'mytree_global1' and 'mytree_global2' not identical"
+ fi
+
+ if [[ "${mytree_local1}" != "${mytree_local2}" ]] ; then
+ err_exit "compound trees 'mytree_local1' and 'mytree_local2' not identical"
+ fi
+
+
+ #### test "unset" in a subshell
+ ( unset 'mytree_global1.l1[urw].l2[itc zapfdingbats]' ) || \
+ err_exit "try 1: variable 'mytree_global1.l1[urw].l2[itc zapfdingbats]' not found"
+ ( unset 'mytree_global1.l1[urw].l2[itc zapfdingbats]' ) || \
+ err_exit "try 2: variable 'mytree_global1.l1[urw].l2[itc zapfdingbats]' not found"
+
+ # remove parent node (array element) and then check whether the child is gone, too:
+ (
+ unset 'mytree_global1.l1[urw].l2[itc zapfdingbats]'
+ [[ -v 'mytree_global1.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]'} ]]
+ ) && err_exit "global: parent node removed (array element), child still exists"
+ (
+ unset 'mytree_local1.l1[urw].l2[itc zapfdingbats]'
+ [[ -v 'mytree_local1.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]' ]]
+ ) && err_exit "local: parent node removed (array element), child still exists"
+
+ # remove parent node (array variable) and then check whether the child is gone, too:
+ (
+ unset 'mytree_local1.l1[urw].l2'
+ [[ -v 'mytree_local1.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]' ]]
+ ) && err_exit "global: parent node removed (array variable), child still exists"
+ (
+ unset 'mytree_local1.l1[urw].l2'
+ [[ -v 'mytree_local1.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]' ]]
+ ) && err_exit "local: parent node removed (array variable), child still exists"
+
+
+ #### test "unset" and compare trees
+ unset 'mytree_global1.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]' ||
+ err_exit "variable 'mytree_global1.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]' not found"
+
+ [[ "${mytree_global1}" != "${mytree_local1}" ]] || err_exit "mytree_global1 and mytree_local1 should differ"
+
+ unset 'mytree_local1.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]' ||
+ err_exit "variable 'mytree_local1.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]' not found"
+
+ # Compare trees (after "unset")
+ if [[ "${mytree_global1}" != "${mytree_local1}" ]] ; then
+ err_exit "compound trees 'mytree_local1' and 'mytree_global1' not identical after unset"
+ fi
+}
+
+main
+
+exit $((Errors<125?Errors:125))