[ksh93-integration-discuss] Re: [ast-users] Next ksh93 alpha release - when?

Felix Schulte felix.schulte at gmail.com
Wed Sep 13 10:50:14 PDT 2006


On 9/13/06, Glenn Fowler <gsf at research.att.com> wrote:
>
> alpha source posted at
>
>   http://www.research.att.com/sw/download/alpha/INIT.2006-09-12.tgz
>   http://www.research.att.com/sw/download/alpha/ast-ksh.2006-09-12.tgz
>
> run the valgrind tests again
> the stty SIGTTOU and utf-8 vs. emacs editing problems not addressed yet
patch diff from 20060724 to 20060912 attached
-- 
      _        Felix Schulte
    _|_|_     mailto:felix.schulte at gmail.com
    (0 0)
ooO--(_)--Ooo
-------------- next part --------------
diff -r -N -u ksh93_2006_07_24/bin/package ksh93_2006_09_12/bin/package
--- ksh93_2006_07_24/bin/package	2006-07-20 18:35:03.000000000 +0200
+++ ksh93_2006_09_12/bin/package	2006-08-16 16:16:21.000000000 +0200
@@ -40,7 +40,7 @@
 case `(getopts '[-][123:xyz]' opt --xyz; echo 0$opt) 2>/dev/null` in
 0123)	USAGE=$'
 [-?
-@(#)$Id: package (AT&T Research) 2006-07-17 $
+@(#)$Id: package (AT&T Research) 2006-08-16 $
 ]'$USAGE_LICENSE$'
 [+NAME?package - source and binary package control]
 [+DESCRIPTION?The \bpackage\b command controls source and binary
@@ -4645,8 +4645,6 @@
 	flat)	flat=1 # backwards compatibility -- documentation dropped
 		shift
 		;;
-	*)	flat=0
-		;;
 	esac
 	case $# in
 	0)	echo "$command: $action: target directory argument expected" >&2
diff -r -N -u ksh93_2006_07_24/lib/package/ast-ksh.html ksh93_2006_09_12/lib/package/ast-ksh.html
--- ksh93_2006_07_24/lib/package/ast-ksh.html	2006-07-24 18:07:46.000000000 +0200
+++ ksh93_2006_09_12/lib/package/ast-ksh.html	2006-09-13 06:38:20.000000000 +0200
@@ -192,7 +192,23 @@
 <P><HR><CENTER><FONT color=red><FONT face=courier><H3><A name="ksh93 changes">ksh93 changes</A></H3></FONT></FONT></CENTER>
 <PRE>
 
-06-07-21  --- Release ksh93r+  ---
+06-09-08  --- Release ksh93s-  ---
+06-09-97  The -a option was added to typeset for indexed arrays.  This
+	  is only needed when using the (&#0091;subscript&#0093;=value ...) form.
+06-08-16  As a new feature, a leading ~(N) on a pattern has no effect 
+	  except when used for file expansion.  In this case if not
+	  matches are found, the pattern is replaced by nothing rathern
+	  than itself.
+06-08-11  A bug in the expansion of ${.sh.match&#0091;i&#0093;:${#.shmatch&#0091;i&#0093;}} has
+	  been fixed.
+06-08-10  The read builtin options -n and -N have been modified to treat
+          the size as characters rather than bytes unless storing into a
+	  binary (typeset -B) variable.
+06-07-27  When the here document operator &lt;&lt; is followed directly by a #
+	  rather than a -, the first line of the here-document determines
+	  how much whitespace is removed for each line.
+06-07-26  A bug in the C-shell history (enabled with set -H) in which the
+	  history event !$ was not processed has been fixed.
 06-07-21  A bug on some systems in which assigning PATH on a command line
 	  would not take effect has been fixed.
 06-07-20  Add ksh93 and rksh93 as allowable names for ksh binaries.
@@ -1559,6 +1575,25 @@
 <P><HR><CENTER><FONT color=red><FONT face=courier><H3><A name="libast changes">libast changes</A></H3></FONT></FONT></CENTER>
 <PRE>
 
+06-09-12 string/strtoi.h: drop &#0091;cClLqQwW&#0093; multipliers
+06-09-11 misc/optget.c: add numeric arg validity check
+06-09-07 misc/optget.c,tm/tmfix.c: fix uninitialzed var refs
+06-09-05 path/pathprobe.c: add version header verification
+06-08-01 Makefile: handle iffe vs FEATURE/common vs ast_common.h
+06-08-31 Makefile: add ast_map.h to the bootstrap list
+06-08-30 misc/glob.c: fix ~(E)re bug that stripped ~(E) before regcomp
+06-08-30 include/ast.h: add { integralof(x) pointerof(x) }
+06-08-27 string/strelapsed.c: fix off-by-one (too little) parse bug
+06-08-25 misc/optget.c: 0*&lt;n&gt;.* numeric option args =&gt; &lt;n&gt;.*
+06-08-22 misc/glob.c: handle ~(...) pattern options
+06-08-16 string/strelapsed.c: fix off-by-one (too far) parse bug
+06-08-16 regex/regcomp.c: accept but ignore ~(N)
+06-08-14 features/libpath.sh: add solaris LD_LIBRARY_PATH_64 check
+06-08-05 sfio/sfpool.c: pool SF_READ|SF_WRITE loop fix
+06-08-02 misc/fts.c: fix FTS_NOSTAT optimization to check for ..
+06-07-28 include/glob.h: add gl_extra for user globlist_t expansion
+06-07-27 features/common: #include "ast_map.h"
+06-07-26 comp/fnmatch.&#0091;ch&#0093;: allow &lt;ast_map.h&gt; to map fnmatch()
 06-07-22 cdt: snarf from kpv
 06-07-17 string/strperm.c: perm==-1 skips umask(1)
 06-07-17 sfio/sfvprintf.c: handle format invalid mb seq
@@ -2882,6 +2917,15 @@
 <P><HR><CENTER><FONT color=red><FONT face=courier><H3><A name="libcmd changes">libcmd changes</A></H3></FONT></FONT></CENTER>
 <PRE>
 
+06-09-11 tail.c: handle compatibility corner cases
+06-09-08 date.c: add output write error diagnostic
+06-09-04 tail.c: fix initial position for -n0, no args =&gt; no -f
+06-08-28 uniq.c: add -D,--all-repeated
+06-08-25 wc.c,wclib.c: add -L,--longest-line,WC_LONGEST
+06-08-24 wc.c,wclib.c: implement -m and WC_MBYTE
+06-08-24 rmdir.c: -sp applies to every message, add gnu -e
+06-08-23 rmdir.c: add solaris --suppress, -s
+06-08-23 mkdir.c: don't add 0300 to -p final dir mode
 06-07-17 cut.c: handle last line with no newline
 06-07-17 cut.c: --output-delimiter == --line-delimiter
 06-06-25 chmod.c: mask -c output with S_IPERM
@@ -3107,7 +3151,7 @@
 <TR>
 <TD align=left></TD>
 <TD align=center></TD>
-<TD align=right>July 24, 2006</TD>
+<TD align=right>September 13, 2006</TD>
 </TR>
 </TABLE>
 <P>
diff -r -N -u ksh93_2006_07_24/lib/package/ast-ksh.README ksh93_2006_09_12/lib/package/ast-ksh.README
--- ksh93_2006_07_24/lib/package/ast-ksh.README	2006-07-24 18:07:40.000000000 +0200
+++ ksh93_2006_09_12/lib/package/ast-ksh.README	2006-09-13 06:38:14.000000000 +0200
@@ -89,7 +89,23 @@
 
 :::::::: ksh93 ::::::::
 
-06-07-21  --- Release ksh93r+  ---
+06-09-08  --- Release ksh93s-  ---
+06-09-97  The -a option was added to typeset for indexed arrays.  This
+	  is only needed when using the ([subscript]=value ...) form.
+06-08-16  As a new feature, a leading ~(N) on a pattern has no effect 
+	  except when used for file expansion.  In this case if not
+	  matches are found, the pattern is replaced by nothing rathern
+	  than itself.
+06-08-11  A bug in the expansion of ${.sh.match[i]:${#.shmatch[i]}} has
+	  been fixed.
+06-08-10  The read builtin options -n and -N have been modified to treat
+          the size as characters rather than bytes unless storing into a
+	  binary (typeset -B) variable.
+06-07-27  When the here document operator << is followed directly by a #
+	  rather than a -, the first line of the here-document determines
+	  how much whitespace is removed for each line.
+06-07-26  A bug in the C-shell history (enabled with set -H) in which the
+	  history event !$ was not processed has been fixed.
 06-07-21  A bug on some systems in which assigning PATH on a command line
 	  would not take effect has been fixed.
 06-07-20  Add ksh93 and rksh93 as allowable names for ksh binaries.
@@ -1453,6 +1469,25 @@
 
 :::::::: libast ::::::::
 
+06-09-12 string/strtoi.h: drop [cClLqQwW] multipliers
+06-09-11 misc/optget.c: add numeric arg validity check
+06-09-07 misc/optget.c,tm/tmfix.c: fix uninitialzed var refs
+06-09-05 path/pathprobe.c: add version header verification
+06-08-01 Makefile: handle iffe vs FEATURE/common vs ast_common.h
+06-08-31 Makefile: add ast_map.h to the bootstrap list
+06-08-30 misc/glob.c: fix ~(E)re bug that stripped ~(E) before regcomp
+06-08-30 include/ast.h: add { integralof(x) pointerof(x) }
+06-08-27 string/strelapsed.c: fix off-by-one (too little) parse bug
+06-08-25 misc/optget.c: 0*<n>.* numeric option args => <n>.*
+06-08-22 misc/glob.c: handle ~(...) pattern options
+06-08-16 string/strelapsed.c: fix off-by-one (too far) parse bug
+06-08-16 regex/regcomp.c: accept but ignore ~(N)
+06-08-14 features/libpath.sh: add solaris LD_LIBRARY_PATH_64 check
+06-08-05 sfio/sfpool.c: pool SF_READ|SF_WRITE loop fix
+06-08-02 misc/fts.c: fix FTS_NOSTAT optimization to check for ..
+06-07-28 include/glob.h: add gl_extra for user globlist_t expansion
+06-07-27 features/common: #include "ast_map.h"
+06-07-26 comp/fnmatch.[ch]: allow <ast_map.h> to map fnmatch()
 06-07-22 cdt: snarf from kpv
 06-07-17 string/strperm.c: perm==-1 skips umask(1)
 06-07-17 sfio/sfvprintf.c: handle format invalid mb seq
@@ -2773,6 +2808,15 @@
 
 :::::::: libcmd ::::::::
 
+06-09-11 tail.c: handle compatibility corner cases
+06-09-08 date.c: add output write error diagnostic
+06-09-04 tail.c: fix initial position for -n0, no args => no -f
+06-08-28 uniq.c: add -D,--all-repeated
+06-08-25 wc.c,wclib.c: add -L,--longest-line,WC_LONGEST
+06-08-24 wc.c,wclib.c: implement -m and WC_MBYTE
+06-08-24 rmdir.c: -sp applies to every message, add gnu -e
+06-08-23 rmdir.c: add solaris --suppress, -s
+06-08-23 mkdir.c: don't add 0300 to -p final dir mode
 06-07-17 cut.c: handle last line with no newline
 06-07-17 cut.c: --output-delimiter == --line-delimiter
 06-06-25 chmod.c: mask -c output with S_IPERM
diff -r -N -u ksh93_2006_07_24/lib/package/ast-ksh.ver ksh93_2006_09_12/lib/package/ast-ksh.ver
--- ksh93_2006_07_24/lib/package/ast-ksh.ver	2006-07-24 18:07:36.000000000 +0200
+++ ksh93_2006_09_12/lib/package/ast-ksh.ver	2006-09-13 06:38:10.000000000 +0200
@@ -1 +1 @@
-ast-ksh 2006-07-24 2006-07-24 1
+ast-ksh 2006-09-12 2006-09-12 1
diff -r -N -u ksh93_2006_07_24/lib/package/INIT.html ksh93_2006_09_12/lib/package/INIT.html
--- ksh93_2006_07_24/lib/package/INIT.html	2006-07-24 18:07:20.000000000 +0200
+++ ksh93_2006_09_12/lib/package/INIT.html	2006-09-13 06:37:54.000000000 +0200
@@ -48,6 +48,16 @@
 <P><HR><CENTER><FONT color=red><FONT face=courier><H3><A name="INIT changes">INIT changes</A></H3></FONT></FONT></CENTER>
 <PRE>
 
+06-09-08 regress.sh: add PIPE INPUT|OUTPUT for pipe io
+06-09-05 C+probe: add { probe_version version_stamp version_string }
+06-09-05 make.probe: add version stamp comment, CC.VERSION&#0091;.STRING&#0093;
+06-08-27 regress.sh,mktest.sh: add UMASK
+06-08-25 regress.sh: add -b,--ignore-space,IGNORESPACE
+06-08-25 mktest.sh: add IGNORESPACE
+06-08-24 mktest.sh: handle &nbsp;00 in data
+06-08-24 regress.sh: handle -f* for INPUT|OUTPUT|ERROR
+06-08-16 package.sh: fix 'install flat' logic
+06-08-11 rt.sh: handle style=shell %K date format
 06-07-17 ratz.c: fix __MVS__ FAR definition
 06-07-17 iffe.sh: "header x.h" -- deprecate "include x.h" for .SCAN.iffe
 06-07-17 package.sh: differentiate urls vs. assignments
@@ -780,7 +790,7 @@
 <TR>
 <TD align=left></TD>
 <TD align=center></TD>
-<TD align=right>July 24, 2006</TD>
+<TD align=right>September 13, 2006</TD>
 </TR>
 </TABLE>
 <P>
diff -r -N -u ksh93_2006_07_24/lib/package/INIT.README ksh93_2006_09_12/lib/package/INIT.README
--- ksh93_2006_07_24/lib/package/INIT.README	2006-07-24 18:07:16.000000000 +0200
+++ ksh93_2006_09_12/lib/package/INIT.README	2006-09-13 06:37:51.000000000 +0200
@@ -89,6 +89,16 @@
 
 :::::::: INIT ::::::::
 
+06-09-08 regress.sh: add PIPE INPUT|OUTPUT for pipe io
+06-09-05 C+probe: add { probe_version version_stamp version_string }
+06-09-05 make.probe: add version stamp comment, CC.VERSION[.STRING]
+06-08-27 regress.sh,mktest.sh: add UMASK
+06-08-25 regress.sh: add -b,--ignore-space,IGNORESPACE
+06-08-25 mktest.sh: add IGNORESPACE
+06-08-24 mktest.sh: handle \000 in data
+06-08-24 regress.sh: handle -f* for INPUT|OUTPUT|ERROR
+06-08-16 package.sh: fix 'install flat' logic
+06-08-11 rt.sh: handle style=shell %K date format
 06-07-17 ratz.c: fix __MVS__ FAR definition
 06-07-17 iffe.sh: "header x.h" -- deprecate "include x.h" for .SCAN.iffe
 06-07-17 package.sh: differentiate urls vs. assignments
diff -r -N -u ksh93_2006_07_24/lib/package/INIT.ver ksh93_2006_09_12/lib/package/INIT.ver
--- ksh93_2006_07_24/lib/package/INIT.ver	2006-07-24 18:07:14.000000000 +0200
+++ ksh93_2006_09_12/lib/package/INIT.ver	2006-09-13 06:37:48.000000000 +0200
@@ -1 +1 @@
-INIT 2006-07-24 2006-07-24 1
+INIT 2006-09-12 2006-09-12 1
diff -r -N -u ksh93_2006_07_24/src/cmd/INIT/cc.darwin.i386 ksh93_2006_09_12/src/cmd/INIT/cc.darwin.i386
--- ksh93_2006_07_24/src/cmd/INIT/cc.darwin.i386	1970-01-01 01:00:00.000000000 +0100
+++ ksh93_2006_09_12/src/cmd/INIT/cc.darwin.i386	2006-08-30 04:08:39.000000000 +0200
@@ -0,0 +1,80 @@
+: unix wrapper for mac os10 cc : 2006-08-29 :
+
+HOSTTYPE=darwin.i386
+
+case $* in
+-dumpmachine) echo $HOSTTYPE; exit ;;
+esac
+
+CC=/usr/bin/cc
+op=init
+for arg
+do	case $op in
+	init)	op=ld
+		set ''
+		;;
+	esac
+	case $arg in
+	-c)	op=cc
+		;;
+	-E)	op=cpp
+		continue
+		;;
+	-G)	op=dll
+		continue
+		;;
+	-lc)	continue
+		;;
+	-lm)	continue
+		;;
+	esac
+	set "$@" "$arg"
+done
+case $# in
+0)	;;
+*)	shift ;;
+esac
+case $* in
+-v)	$CC "$@"; exit ;;
+esac
+case $op in
+init)	echo "cc: arguments expected" >&2
+	exit 1
+	;;
+cpp)	$CC -E "$@"
+	;;
+cc)	$CC -DCLK_TCK=100 "$@"
+	;;
+dll)	# what a compatibility mess -- surely they can get the apis to play nice
+	tmp=/tmp/cc.$$.err
+	case `MACOSX_DEPLOYMENT_TARGET=10.3 ld -undefined dynamic_lookup -lcc_dynamic 2>&1` in
+	*undefined*dynamic_lookup*)
+		ld -m -flat_namespace -undefined suppress -dylib -dynamic \
+			-ldylib1.o "$@" -lcc_dynamic -framework System >$tmp 2>&1
+		status=$?
+		;;
+	*cc_dynamic*)
+		MACOSX_DEPLOYMENT_TARGET=10.3 ld -undefined dynamic_lookup -m \
+			-dylib -dynamic -ldylib1.o "$@" \
+			`set /Developer/SDKs/MacOSX10.3*/usr/lib/gcc/darwin/*/libcc_dynamic.a; echo $1` \
+			-framework System >$tmp 2>&1
+		status=$?
+		;;
+	*)	MACOSX_DEPLOYMENT_TARGET=10.3 ld -undefined dynamic_lookup -m \
+			-dylib -dynamic -ldylib1.o "$@" -lcc_dynamic \
+			-framework System >$tmp 2>&1
+		status=$?
+		;;
+	esac
+	egrep -v ' (warning .*multiple definitions|definition) of ' $tmp >&2
+	rm -f $tmp
+	exit $status
+	;;
+ld)	tmp=/tmp/cc.$$.err
+	$CC -Wl,-m -DCLK_TCK=100 "$@" >$tmp 2>&1
+	status=$?
+	egrep -v ' (warning .*multiple definitions of|definition of|as lazy binding|not from earlier dynamic) ' $tmp >&2
+	rm -f $tmp
+	exit $status
+	;;
+esac
diff -r -N -u ksh93_2006_07_24/src/cmd/INIT/C+probe ksh93_2006_09_12/src/cmd/INIT/C+probe
--- ksh93_2006_07_24/src/cmd/INIT/C+probe	2006-06-27 15:34:21.000000000 +0200
+++ ksh93_2006_09_12/src/cmd/INIT/C+probe	2006-09-05 16:32:45.000000000 +0200
@@ -2,7 +2,7 @@
 # Glenn Fowler
 # AT&T Research
 #
-# @(#)C probe (AT&T Research) 2006-06-27
+# @(#)C probe (AT&T Research) 2006-09-05
 #
 # probe [ -d ] c-compiler-path [ attributes ]
 #
@@ -29,6 +29,7 @@
 probe_so=".so .sl .dylib"
 probe_symprefix="_"
 probe_verbose="'-v -v' '-# -#' '-d -d' -dryrun '-V -V'"
+probe_version="--version -version -V -v"
 
 #
 # the following are set by the preamble for the tool specific probe
@@ -63,6 +64,9 @@
 fi
 tmpdir=$tmpdir/probe$$
 undef="define defined elif else endif error if ifdef ifndef include line pragma undef __STDC__ __STDPP__ __ARGC__ __BASE__ __BASE_FILE__ __DATE__ __FILE__ __INCLUDE_LEVEL__ __LINE__ __PATH__ __TIME__ __VERSION__"
+version_flags=
+version_stamp=
+version_string=
 
 #
 # constrain the environment
@@ -376,6 +380,17 @@
 	fi
 fi
 
+eval set x $probe_version
+shift
+for o in "$@"
+do	if	$cc $o > version.out 2>&1
+	then	version_flags=$o
+		version_string=`sed -e 1q -e 's/;/ /g' version.out`
+		version_stamp=";VERSION;$o;$version_string;PATH;$cc"
+		break
+	fi
+done
+
 echo 'int main(){return 0;}' > hosted.$src
 $cc -o hosted.$exe hosted.$src && ./hosted.$exe && hosted=1
 
@@ -433,7 +448,6 @@
 stdinclude=$definclude
 case $hosted in
 "")	usrinclude= ;;
-*)	usrinclude=/usr/include ;;
 esac
 cmdinclude=
 while	:
diff -r -N -u ksh93_2006_07_24/src/cmd/INIT/Makefile ksh93_2006_09_12/src/cmd/INIT/Makefile
--- ksh93_2006_07_24/src/cmd/INIT/Makefile	2006-06-14 18:26:59.000000000 +0200
+++ ksh93_2006_09_12/src/cmd/INIT/Makefile	2006-08-30 06:43:33.000000000 +0200
@@ -43,7 +43,7 @@
 
 :: RELEASE hosttype.tst p.c hello.c \
 	cc.specialize cc.pentium4 \
-	cc.darwin.ppc cc.darwin7.ppc \
+	cc.darwin.ppc cc.darwin7.ppc cc.darwin.i386 \
 	cc.hp.pa cc.hp.pa64 cc.ibm.risc \
 	cc.linux.ia64-icc cc.lynxos.i386 cc.lynxos.ppc \
 	cc.mvs.390 cc.next.i386 cc.next.m68k cc.osf.alpha \
diff -r -N -u ksh93_2006_07_24/src/cmd/INIT/make.probe ksh93_2006_09_12/src/cmd/INIT/make.probe
--- ksh93_2006_07_24/src/cmd/INIT/make.probe	2006-06-27 15:33:51.000000000 +0200
+++ ksh93_2006_09_12/src/cmd/INIT/make.probe	2006-09-05 16:32:32.000000000 +0200
@@ -2,7 +2,7 @@
 # Glenn Fowler
 # AT&T Research
 #
-# @(#)make.probe (AT&T Research) 2006-06-27
+# @(#)make.probe (AT&T Research) 2006-09-05
 #
 # C probe for make
 #
@@ -1805,6 +1805,8 @@
 # set up for local override
 #
 
+CC_VERSION_STAMP=$version_stamp
+CC_VERSION_STRING=$version_string
 CC_CC=$cc
 CC_NATIVE=$ccnative
 CC_EXECTYPE=$exectype
@@ -1869,16 +1871,15 @@
 CC_SUFFIX_SHARED=$so
 CC_SUFFIX_SOURCE=.$src
 CC_SUFFIX_STATIC=$sa
+CC_VERSION=$version_flags
 CC_WARN=$warn
 CC_ATTRIBUTES=$ATTRIBUTES
 
 exec >&3
 
-echo CC.CC = $CC_CC
-
 #
 # check for local override
-# all CC_* but CC_CC may be modified
+# all CC_* but { CC_CC CC_VERSION_STAMP CC_VERSION_STRING } may be modified
 # additional CC.* may be printed on stdout
 #
 
@@ -1890,6 +1891,10 @@
 # the payoff
 #
 
+case $version_stamp in
+?*)	echo "# $version_stamp" ;;
+esac
+echo CC.CC = $cc
 echo CC.NATIVE = $CC_NATIVE
 echo CC.EXECTYPE = $CC_EXECTYPE
 echo CC.HOSTTYPE = $CC_HOSTTYPE
@@ -1978,6 +1983,8 @@
 echo CC.SUFFIX.SHARED = $CC_SUFFIX_SHARED
 echo CC.SUFFIX.SOURCE = $CC_SUFFIX_SOURCE
 echo CC.SUFFIX.STATIC = $CC_SUFFIX_STATIC
+echo CC.VERSION = $CC_VERSION
+echo CC.VERSION.STRING = $version_string
 echo CC.WARN = $CC_WARN
 
 for i in $CC_ATTRIBUTES
diff -r -N -u ksh93_2006_07_24/src/cmd/INIT/Mamfile ksh93_2006_09_12/src/cmd/INIT/Mamfile
--- ksh93_2006_07_24/src/cmd/INIT/Mamfile	2006-07-24 18:07:24.000000000 +0200
+++ ksh93_2006_09_12/src/cmd/INIT/Mamfile	2006-09-13 06:37:58.000000000 +0200
@@ -1,4 +1,4 @@
-info mam static 00000 1994-07-17 make (AT&T Research) 5.1 2006-05-21
+info mam static 00000 1994-07-17 make (AT&T Research) 5.1 2006-08-11
 setv INSTALLROOT ../../..
 setv PACKAGEROOT ../../../../..
 setv AR ar
diff -r -N -u ksh93_2006_07_24/src/cmd/INIT/mktest.sh ksh93_2006_09_12/src/cmd/INIT/mktest.sh
--- ksh93_2006_07_24/src/cmd/INIT/mktest.sh	2006-06-27 15:37:48.000000000 +0200
+++ ksh93_2006_09_12/src/cmd/INIT/mktest.sh	2006-08-31 04:34:05.000000000 +0200
@@ -31,7 +31,7 @@
 0123)	ARGV0="-a $command"
 	USAGE=$'
 [-?
-@(#)$Id: mktest (AT&T Labs Research) 2006-06-27 $
+@(#)$Id: mktest (AT&T Labs Research) 2006-08-27 $
 ]
 '$USAGE_LICENSE$'
 [+NAME?mktest - generate a regression test scripts]
@@ -55,7 +55,8 @@
         [+DATA \afile\a [ - | [ options ]] data]]?Create input data
             \afile\a that is empty (-) or contains \adata\a subject to
             \bprint\b(1) \aoptions\a or that is a copy of the DATA command
-            standard input.]
+            standard input. Set \afile\a to \b-\b to name the standard
+            input.]
         [+EXEC [ \aarg\a ... ]]?Run the command under test with
             optional arguments. If the standard input is not specified then
             the standard input of the previous EXEC is used. The standard
@@ -63,7 +64,9 @@
             file.]
         [+EXPORT \aname\a=\avalue\a ...?Export list for subsequent
             commands in the TEST group.]
-        [+KEEP \apattern\a ...?File matych patterns of files to retain
+        [+IGNORESPACE [ 0 | 1 ]
+            ?Ignore space differences when comparing expected output.]
+        [+KEEP \apattern\a ...?File match patterns of files to retain
             between TEST groups.]
         [+NOTE \acomment\a?\acomment\a is added to the current test
             script.]
@@ -71,6 +74,9 @@
             optional arguments.]
         [+TEST [ \anumber\a ]] [ \adescription\a ... ]]?Define a new
             test group with optional \anumber\a and \adescripion\a.]
+        [+UMASK [ \amask\a ]]?Run subsequent tests with \bumask\b(1)
+            \amask\a. If \amask\a is omitted then the original \bumask\b is
+            used.]
         [+UNIT \acommand\a [ \aarg\a ... ]]?Define the command and
             optional default arguments to be tested. \bUNIT\b explicitly
             overrides the default command name derived from the test script
@@ -86,11 +92,11 @@
 	;;
 esac
 
-typeset ARG SCRIPT UNIT TEMP=${TMPDIR:-/tmp}/$command.$$.tmp
+typeset ARG SCRIPT UNIT TEMP=${TMPDIR:-/tmp}/$command.$$.tmp WORK
 typeset IO INPUT OUTPUT ERROR KEEP
 typeset SINGLE= WIDTH=80 quote='%${SINGLE}..${WIDTH}q'
-typeset -A DATA RESET REMOVE
-integer SCRIPT_UNIT=0 TEST=0 CODE=0 EXIT=0 ACCEPT=0 code
+typeset -A DATA RESET REMOVE FORMAT
+integer KEEP_UNIT=0 SCRIPT_UNIT=0 TEST=0 CODE=0 EXIT=0 ACCEPT=0 code
 
 while	getopts $ARGV0 "$USAGE" OPT
 do	case $OPT in
@@ -128,9 +134,13 @@
 (ulimit -c 0) >/dev/null 2>&1 && ulimit -c 0
 if	(( $# ))
 then	set -A UNIT -- "$@"
+	KEEP_UNIT=1
 else	ARG=${SCRIPT##*/}
 	set -A UNIT -- "${ARG%.*}"
 fi
+WORK=${UNIT[0]}.tmp
+rm -rf $WORK
+mkdir $WORK || exit
 
 function LINE
 {
@@ -152,7 +162,7 @@
 
 function UNIT
 {
-	set -A UNIT -- "$@"
+	(( KEEP_UNIT )) || set -A UNIT -- "$@"
 	case $STYLE in
 	regress)LINE
 		print -u$stdout -r -f $'UNIT'
@@ -198,6 +208,7 @@
 		do	unset REMOVE[$i]
 		done
 	fi
+	rm -rf $WORK/*
 	if	[[ $1 == +([0-9]) ]]
 	then	TEST=${1##0}
 		shift
@@ -214,11 +225,14 @@
 	INPUT=
 	OUTPUT=
 	ERROR=
+	UMASK=$UMASK_ORIG
+	UMASK_DONE=$UMASK
+	CODE=0
 }
 
-function prog
+function RUN
 {
-	typeset i n op unit sep output=1 error=1 exitcode=1
+	typeset i n p op unit sep output=1 error=1 exitcode=1
 	integer z
 	op=$1
 	shift
@@ -252,34 +266,58 @@
 			sep=$' '
 		done
 		print -u$stdout
-		[[ /dev/fd/0 -ef /dev/fd/$stdin ]] || cat > $TEMP.in
+		[[ ${DATA[-]} || /dev/fd/0 -ef /dev/fd/$stdin ]] || cat > $TEMP.in
 		IO=$(<$TEMP.in)
 		(( z = $(wc -c < $TEMP.in) ))
 		if	(( z && z == ${#IO} ))
 		then	n=-n
 		else	n=
 		fi
-		if	[[ $op == PROG ]]
-		then	"$unit" "$@" < $TEMP.in > $TEMP.out 2> $TEMP.err
-		else	"${UNIT[@]}" "$@" < $TEMP.in > $TEMP.out 2> $TEMP.err
-		fi
-		code=$?
+		{
+			[[ $UMASK != $UMASK_ORIG ]] && umask $UMASK
+			cd $WORK
+			if	[[ $op == PROG ]]
+			then	"$unit" "$@"
+				code=$?
+			else	"${UNIT[@]}" "$@"
+				code=$?
+			fi
+			cd ..
+			[[ $UMASK != $UMASK_ORIG ]] && umask $UMASK_ORIG
+		} < $TEMP.in > $TEMP.out 2> $TEMP.err
 		if	[[ $IO != "$INPUT" ]]
 		then	INPUT=$IO
-			print -u$stdout -n -r -- $'\t\tINPUT' $n -
-			[[ $IO ]] && print -u$stdout -r -f " $QUOTE" -- "$IO"
+			if	[[ ${FORMAT[-]} ]]
+			then	print -u$stdout -n -r -- $'\t\tINPUT'
+				print -u$stdout -r -f " $QUOTE" -- "${FORMAT[-]}"
+				print -u$stdout -r -f " $QUOTE" -- -
+				unset FORMAT[-]
+			else	print -u$stdout -n -r -- $'\t\tINPUT' $n -
+				[[ $IO ]] && print -u$stdout -r -f " $QUOTE" -- "$IO"
+			fi
 			print -u$stdout
+			unset DATA[-]
 		fi
 		for i in ${!DATA[@]}
-		do	IO=$(<$i)
-			(( z = $(wc -c < $i) ))
-			if	(( z && z == ${#IO} ))
-			then	n=-n
-			else	n=
+		do	if	[[ ${FORMAT[$i]} ]]
+			then	print -u$stdout -n -r -- $'\t\tINPUT'
+				print -u$stdout -r -f " $QUOTE" -- "${FORMAT[$i]}"
+				print -u$stdout -r -f " $QUOTE" -- "$i"
+				unset FORMAT[$i]
+			else	case $i in
+				-)	p=$TEMP.in ;;
+				*)	p=$WORK/$i ;;
+				esac
+				IO=$(<$p)
+				(( z = $(wc -c < $p) ))
+				if	(( z && z == ${#IO} ))
+				then	n=-n
+				else	n=
+				fi
+				print -u$stdout -n -r -- $'\t\tINPUT' $n
+				print -u$stdout -r -f " $QUOTE" -- "$i"
+				[[ $IO ]] && print -u$stdout -r -f " $QUOTE" -- "$IO"
 			fi
-			print -u$stdout -n -r -- $'\t\tINPUT' $n
-			print -u$stdout -r -f " $QUOTE" -- "$i"
-			[[ $IO ]] && print -u$stdout -r -f " $QUOTE" -- "$IO"
 			print -u$stdout
 			unset DATA[$i]
 		done
@@ -292,12 +330,19 @@
 		if	[[ $IO != "$OUTPUT" ]]
 		then	OUTPUT=$IO
 			if	[[ $output ]]
-			then	print -u$stdout -n -r -- $'\t\tOUTPUT' $n -
-				[[ $IO ]] && print -u$stdout -r -f " $QUOTE" -- "$IO"
+			then	if	[[ ! -s $TEMP.out ]]
+				then	print -u$stdout -n -r -- $'\t\tOUTPUT' -
+				elif	cmp -s $TEMP.in $TEMP.out
+				then	OUTPUT=not-$OUTPUT
+					print -u$stdout -n -r -- $'\t\tSAME OUTPUT INPUT'
+				else	print -u$stdout -n -r -- $'\t\tOUTPUT' $n -
+					[[ $IO ]] && print -u$stdout -r -f " $QUOTE" -- "$IO"
+				fi
 				print -u$stdout
 			fi
 		fi
 		IO=$(<$TEMP.err)
+		IO=${IO//$command\[*([0-9])\]:\ .\[*([0-9])\]:\ @(EXEC|PROG)\[*([0-9])\]:\ /}
 		(( z = $(wc -c < $TEMP.err) ))
 		if	(( z && z == ${#IO} ))
 		then	n=-n
@@ -323,6 +368,10 @@
 			print -u$stdout -r -- $'\t\tIGNORE ERROR'
 			;;
 		esac
+		if	[[ $UMASK_DONE != $UMASK ]]
+		then	UMASK_DONE=$UMASK
+			print -u$stdout -r -f $'\t\tUMASK %s\n' $UMASK
+		fi
 		if	(( code != CODE ))
 		then	(( CODE=code ))
 			if	[[ $exitcode ]]
@@ -330,13 +379,15 @@
 			fi
 		fi
 		;;
-	shell)	if	[[ $op == PROG ]]
+	shell)	[[ $UMASK != $UMASK_ORIG ]] && print -u$stdout -r -f "{ umask $UMASK; "
+		if	[[ $op == PROG ]]
 		then	print -u$stdout -r -f $'"'"$unit"$'"'
 		else	print -u$stdout -r -f $'"$@"'
 		fi
 		for ARG in "$@"
 		do	print -u$stdout -r -f " $QUOTE" -- "$ARG"
 		done
+		[[ $UMASK != $UMASK_ORIG ]] && print -u$stdout -r -f "umask $UMASK_ORIG; } "
 		if	[[ ! $output ]]
 		then	print -u$stdout -r -f " >/dev/null"
 		fi
@@ -362,26 +413,35 @@
 
 function EXEC
 {
-	prog EXEC "$@"
+	RUN EXEC "$@"
 }
 
 function DATA
 {
-	typeset f=$1 o=
+	typeset f p o
+	f=$1
 	shift
+	case $f in
+	-)	p=$TEMP.in ;;
+	*)	p=$WORK/$f ;;
+	esac
 	case $1 in
 	'')	cat ;;
 	-)	;;
 	*)	print -r "$@" ;;
-	esac > $f
+	esac > $p
 	DATA[$f]=1
+	if	(( $# == 1 )) && [[ $1 == -?* ]]
+	then	FORMAT[$f]=$1
+	else	FORMAT[$f]=
+	fi
 	if	[[ $f != $KEEP ]]
 	then	REMOVE[$f]=1
 	fi
 	if	[[ $STYLE == shell ]]
 	then	{
 		print -r -f "cat > $QUOTE <<'!TEST-INPUT!'"$'\n' -- "$f"
-		cat "$f"
+		cat "$p"
 		print -r -- !TEST-INPUT!
 		} >&$stdout
 	fi
@@ -418,7 +478,7 @@
 
 function PROG
 {
-	prog PROG "$@"
+	RUN PROG "$@"
 }
 
 function WIDTH
@@ -427,8 +487,24 @@
 	eval QUOTE='"'$quote'"'
 }
 
-trap 'CODE=$?; rm -f $TEMP.*; exit $CODE' 0 1 2 3 15
+function IGNORESPACE
+{
+	IGNORESPACE=-b
+	LINE
+	print -u$stdout -r IGNORESPACE
+}
+
+function UMASK # [ mask ]
+{
+	[[ $UMASK_ORIG ]] || UMASK_ORIG=$(umask)
+	UMASK=$1
+	[[ $UMASK ]] || UMASK=$UMASK_ORIG
+}
+
+trap 'CODE=$?; rm -rf $TEMP.* $WORK; exit $CODE' 0 1 2 3 15
 
+typeset IGNORESPACE UMASK UMASK_ORIG UMASK_DONE
+UMASK_ORIG=$(umask)
 IFS=$IFS$'\n'
 
 print -u$stdout -r "# : : generated from $SCRIPT by $command : : #"
@@ -492,7 +568,7 @@
 	then	echo ${UNIT[0]} tests PASSED
 		rm -f $PREFIX${UNIT[0]}.tmp
 	else	echo ${UNIT[0]} tests FAILED
-		diff $PREFIX${UNIT[0]}.tmp $PREFIX${UNIT[0]}.out
+		diff $IGNORESPACE $PREFIX${UNIT[0]}.tmp $PREFIX${UNIT[0]}.out
 	fi
 	;;
 
diff -r -N -u ksh93_2006_07_24/src/cmd/INIT/package.sh ksh93_2006_09_12/src/cmd/INIT/package.sh
--- ksh93_2006_07_24/src/cmd/INIT/package.sh	2006-07-18 05:48:02.000000000 +0200
+++ ksh93_2006_09_12/src/cmd/INIT/package.sh	2006-08-16 16:15:36.000000000 +0200
@@ -58,7 +58,7 @@
 case `(getopts '[-][123:xyz]' opt --xyz; echo 0$opt) 2>/dev/null` in
 0123)	USAGE=$'
 [-?
-@(#)$Id: package (AT&T Research) 2006-07-17 $
+@(#)$Id: package (AT&T Research) 2006-08-16 $
 ]'$USAGE_LICENSE$'
 [+NAME?package - source and binary package control]
 [+DESCRIPTION?The \bpackage\b command controls source and binary
@@ -4663,8 +4663,6 @@
 	flat)	flat=1 # backwards compatibility -- documentation dropped
 		shift
 		;;
-	*)	flat=0
-		;;
 	esac
 	case $# in
 	0)	echo "$command: $action: target directory argument expected" >&2
diff -r -N -u ksh93_2006_07_24/src/cmd/INIT/ratz.c ksh93_2006_09_12/src/cmd/INIT/ratz.c
--- ksh93_2006_07_24/src/cmd/INIT/ratz.c	2006-07-23 16:39:27.000000000 +0200
+++ ksh93_2006_09_12/src/cmd/INIT/ratz.c	2006-07-25 16:31:11.000000000 +0200
@@ -3635,11 +3635,9 @@
 
 
 local gzFile gz_open      OF((const char *path, const char *mode, FILE* fp));
-local int do_flush        OF((gzFile file, int flush));
 local int    get_byte     OF((gz_stream *s));
 local void   check_header OF((gz_stream *s));
 local int    destroy      OF((gz_stream *s));
-local void   putLong      OF((FILE *file, uLong x));
 local uLong  getLong      OF((gz_stream *s));
 
 /* ===========================================================================
diff -r -N -u ksh93_2006_07_24/src/cmd/INIT/regress.sh ksh93_2006_09_12/src/cmd/INIT/regress.sh
--- ksh93_2006_07_24/src/cmd/INIT/regress.sh	2006-06-27 15:20:57.000000000 +0200
+++ ksh93_2006_09_12/src/cmd/INIT/regress.sh	2006-09-12 18:37:22.000000000 +0200
@@ -23,120 +23,150 @@
 case $(getopts '[-][123:xyz]' opt --xyz 2>/dev/null; echo 0$opt) in
 0123)	USAGE=$'
 [-?
-@(#)$Id: regress (AT&T Labs Research) 2006-06-27 $
+@(#)$Id: regress (AT&T Research) 2006-09-11 $
 ]
 '$USAGE_LICENSE$'
 [+NAME?regress - run regression tests]
-[+DESCRIPTION?\bregress\b runs the tests in \aunit\a, or \aunit\a\b.tst\b
-	if \aunit\a does not exist. If \acommand\a is omitted then it is
-	assumed to be the base name of \aunit\a. All testing is done in the
-	temporary directory \aunit\a\b.tmp\b.]
-[+?Default test output lists the \anumber\a and \adescription\a for each active
-	\bTEST\b group and the \anumber\a:\aline\a for each individual
-	\bEXEC\b test. Each test that fails results in a diagnostic that
-	contains the word \bFAILED\b; no other diagnostics contain this word.]
-[k:keep?Enable \bcore\b dumps, exit after the first test that fails, and do
-	not remove the temporary directory \aunit\a\b.tmp\b.]
+[+DESCRIPTION?\bregress\b runs the tests in \aunit\a, or
+    \aunit\a\b.tst\b if \aunit\a does not exist. If \acommand\a is omitted
+    then it is assumed to be the base name of \aunit\a. All testing is done
+    in the temporary directory \aunit\a\b.tmp\b.]
+[+?Default test output lists the \anumber\a and \adescription\a for
+    each active \bTEST\b group and the \anumber\a:\aline\a for each
+    individual \bEXEC\b test. Each test that fails results in a diagnostic
+    that contains the word \bFAILED\b; no other diagnostics contain this
+    word.]
+[b:ignore-space?Ignore space differences when comparing expected
+    output.]
+[i:pipe-input?Repeat each test with the standard input redirected through a
+    pipe.]
+[k:keep?Enable \bcore\b dumps, exit after the first test that fails,
+    and do not remove the temporary directory \aunit\a\b.tmp\b.]
+[o:pipe-output?Repeat each test with the standard input redirected through
+    a pipe.]
+[p:pipe-io?Repeat each test with the standard input and standard output
+    redirected through pipes.]
 [q:quiet?Output information on \bFAILED\b tests only.]
-[t:test?Run only tests matching \apattern\a. Tests are numbered and consist of
-	at least two digits (0 filled if necessary.) Tests matching \b+(0)\b are
-	always run.]:[pattern]
-[v:verbose?List differences between actual (<) and expected (>) output, errors
-	and exit codes. Also disable long output line truncation.]
+[r!:regular?Run each test with the standard input and standard output
+    redirected through regular files.]
+[t:test?Run only tests matching \apattern\a. Tests are numbered and
+    consist of at least two digits (0 filled if necessary.) Tests matching
+    \b+(0)\b are always run.]:[pattern]
+[v:verbose?List differences between actual (<) and expected (>) output,
+    errors and exit codes. Also disable long output line truncation.]
 [D:debug?Enable debug tracing.]
 
 unit [ command [ arg ... ] ]
 
-[+INPUT FILES?The regression test file \aunit\a\b.tst\b is a \bksh\b(1) script
-	that is executed in an environment with the following functions
-	defined:]{
-	[+BODY { ... }?Defines the test body; used for complex tests.]
-	[+CD \adirectory\a?Create and change to working directory for one test.]
-	[+CLEANUP \astatus\a?Called at exit time to remove the temporary
-		directory \aunit\a\b.tmp\b, list the tests totals via
-		\bTALLY\b, and exit with status \astatus\a.]
-	[+COMMAND \aarg\a ...?Runs the current command under test with
-		\aarg\a ... appended to the default args.]
-	[+COPY \afrom to\a?Copy file \afrom\a to \ato\a. \afrom\a may be
-		a regular file or \bINPUT\b, \bOUTPUT\b or \bERROR\b.
-		Post test comparisons are still done for \afrom\a.]
-	[+DIAGNOSTICS [ \b1\b | \"\" ]]?No argument or an argument of \b1\b
-		declares that diagnostics are to expected for the remainder
-		of the current \bTEST\b; \"\" reverts to the default state
-		that diagnostics are not expected.]
-	[+DO \astatement\a?Defines additional statements to be executed
-		for the current test. \astatement\a may be a { ... } group.]
-	[+EMPTY \bINPUT|OUTPUT|ERROR|SAME?The corresponding file is expected
-		to be empty.]
-	[+ERROR [ \b-n\b ]] \afile\a | - \adata\a ...?The standard error is
-		expected to match either the contents of \afile\a or the line
-		\adata\a. \bERROR -n\b does not append a newline to \adata\a.]
-	[+EXEC [ \aarg\a ... ]]?Runs the command under test with optional
-		arguments. \bINPUT\b, \bOUTPUT\b, \bERROR\b, \bEXIT\b and
-		\bSAME\b calls following this \bEXEC\b up until the next
-		\bEXEC\b or the end of the script provide details for the
-		expected results.]
-	[+EXIT \astatus\a?The command exit status is expected to match the
-		pattern \astatus\a.]
-	[+EXPORT [-]] \aname\a=\avalue\a ...?Export environment variables for
-		one test.]
-	[+FATAL \amessage\a ...?\amessage\a is printed on the standard error
-		and \bregress\b exits with status \b1\b.]
-	[+IGNORE \afile\a ...?\afile\a is ignored for subsequent result
-		comparisons. \afile\a may be \bOUTPUT\b or \bERROR\b.]
-	[+INCLUDE \afile\a ...?One or more \afile\a operands are read
-		via the \bksh\b(1) \b.\b(1) command. \bVIEW\b is used to
-		locate the files.]
-	[+INFO \adescription\a?\adescription\a is printed on the standard
-		error.]
-	[+INITIALIZE?Called by \bregress\b to initialize a each \bTEST\b
-		group.]
-	[+INPUT [ \b-n\b ]] \afile\a | - \adata\a ...?The standard input is
-		set to either the contents of \afile\a or the line
-		\adata\a. \bINPUT -n\b does not append a newline to \adata\a.]
-	[+INTRO?Called by \bregress\b to introduce all \bTEST\b groups.]
-	[+IO \bINPUT|OUTPUT|ERROR\b [ \b-n\b ]] \afile\a | - \adata\a ...?
-		Internal support for the \bINPUT\b, \bOUTPUT\b and \bERROR\b
-		functions.]
-	[+KEEP \apattern\a ...?The temporary directory is cleared for each
-		test. Files matching \apattern\a are retained between tests.]
-	[+MOVE \afrom to\a?Rename file \afrom\a to \ato\a. \afrom\a may be
-		a regular file or \bINPUT\b, \bOUTPUT\b or \bERROR\b.
-		Post test comparisons are ignored for \afrom\a.]
-	[+NOTE \acomment\a?\acomment\a is added to the current test trace
-		output.]
-	[+OUTPUT [ \b-n\b ]] \afile\a | - \adata\a ...?The standard output is
-		expected to match either the contents of \afile\a or the line
-		\adata\a. \bOUTPUT -n\b does not append a newline to \adata\a.]
-	[+PROG \acommand\a [ \aarg\a ... ]]?\acommand\a is run with optional
-		arguments.]
-	[+REMOVE \afile\a ...?\afile\a ... are removed after the current test
-		is done.]
-	[+RUN?Called by \bregress\b to run the current test.]
-	[+SAME \anew old\a?\anew\a is expected to be the same as \aold\a after
-		the current test completes.]
-	[+TALLY?Called by \bregress\b display the \bTEST\b results.]
-	[+TEST \anumber\a [ \adescription\a ... ]]?Define a new test group
-		labelled \anumber\a with optional \adescripion\a.]
-	[+TITLE [+]] \atext\a?Set the \bTEST\b output title to \atext\a. If
-		\b+\b is specified then \atext\a is appended to the default
-		title. The default title is the test file base name, and, if
-		different from the test file base name, the test unit base name.]
-	[+TWD [ \adir\a ... ]]?Set the temporary test dir to \adir\a. The
-		default is \aunit\a\b.tmp\b, where \aunit\a is the test
-		input file sans directory and suffix. If \adir\a matches \b/*\b
-		then it is the directory name; if \adir\a is non-null then the
-		prefix \b${TMPDIR:-/tmp}\b is added; otherwise if \adir\a is
-		omitted then \b${TMPDIR:-/tmp}/tst-\b\aunit\a-$$-$RANDOM.\b\aunit\a
-		is used.]
-	[+UNIT \acommand\a [ \aarg\a ... ]]?Define the command and optional
-		default arguments to be tested. \bUNIT\b explicitly overrides
-		the default command name derived from the test script
-		file name.]
-	[+VIEW \avar\a [ \afile\a ]]?\avar\a is set to the full pathname of
-		\avar\a [ \afile\a ]] in the current \b$VPATH\b view if
-		defined.]
-}
+[+INPUT FILES?The regression test file \aunit\a\b.tst\b is a \bksh\b(1)
+    script that is executed in an environment with the following functions
+    defined:]
+    {
+        [+BODY { ... }?Defines the test body; used for complex tests.]
+        [+CD \adirectory\a?Create and change to working directory for
+            one test.]
+        [+CLEANUP \astatus\a?Called at exit time to remove the
+            temporary directory \aunit\a\b.tmp\b, list the tests totals via
+            \bTALLY\b, and exit with status \astatus\a.]
+        [+COMMAND \aarg\a ...?Runs the current command under test with
+            \aarg\a ... appended to the default args.]
+        [+COPY \afrom to\a?Copy file \afrom\a to \ato\a. \afrom\a may
+            be a regular file or \bINPUT\b, \bOUTPUT\b or \bERROR\b. Post
+            test comparisons are still done for \afrom\a.]
+        [+DIAGNOSTICS [ \b1\b | \"\" ]]?No argument or an argument of
+            \b1\b declares that diagnostics are to expected for the
+            remainder of the current \bTEST\b; \"\" reverts to the default
+            state that diagnostics are not expected.]
+        [+DO \astatement\a?Defines additional statements to be executed
+            for the current test. \astatement\a may be a { ... } group.]
+        [+EMPTY \bINPUT|OUTPUT|ERROR|SAME?The corresponding file is
+            expected to be empty.]
+        [+ERROR [ \b-n\b ]] \afile\a | - \adata\a ...?The standard
+            error is expected to match either the contents of \afile\a or
+            the line \adata\a. \bERROR -n\b does not append a newline to
+            \adata\a.]
+        [+EXEC [ \aarg\a ... ]]?Runs the command under test with
+            optional arguments. \bINPUT\b, \bOUTPUT\b, \bERROR\b, \bEXIT\b
+            and \bSAME\b calls following this \bEXEC\b up until the next
+            \bEXEC\b or the end of the script provide details for the
+            expected results.  If no arguments are specified then the
+	    arguments from the previious \bEXEC\b in the current
+	    \bTEST\b group are used, or no arguments if this is the
+	    first \bEXEC\b in the group.]
+        [+EXIT \astatus\a?The command exit status is expected to match
+            the pattern \astatus\a.]
+        [+EXPORT [-]] \aname\a=\avalue\a ...?Export environment
+            variables for one test.]
+        [+FATAL \amessage\a ...?\amessage\a is printed on the standard
+            error and \bregress\b exits with status \b1\b.]
+        [+IGNORE \afile\a ...?\afile\a is ignored for subsequent result
+            comparisons. \afile\a may be \bOUTPUT\b or \bERROR\b.]
+        [+IGNORESPACE?Ignore space differences when comparing expected
+            output.]
+        [+INCLUDE \afile\a ...?One or more \afile\a operands are read
+            via the \bksh\b(1) \b.\b(1) command. \bVIEW\b is used to locate
+            the files.]
+        [+INFO \adescription\a?\adescription\a is printed on the
+            standard error.]
+        [+INITIALIZE?Called by \bregress\b to initialize a each
+            \bTEST\b group.]
+        [+INPUT [ \b-n\b ]] \afile\a | - \adata\a ...?The standard
+            input is set to either the contents of \afile\a or the line
+            \adata\a. \bINPUT -n\b does not append a newline to \adata\a.]
+        [+INTRO?Called by \bregress\b to introduce all \bTEST\b
+            groups.]
+        [+IO \bINPUT|OUTPUT|ERROR\b [ \b-n\b ]] \afile\a | - \adata\a ...?
+            Internal support for the \bINPUT\b, \bOUTPUT\b and \bERROR\b
+            functions.]
+        [+KEEP \apattern\a ...?The temporary directory is cleared for
+            each test. Files matching \apattern\a are retained between
+            tests.]
+        [+MOVE \afrom to\a?Rename file \afrom\a to \ato\a. \afrom\a may
+            be a regular file or \bINPUT\b, \bOUTPUT\b or \bERROR\b. Post
+            test comparisons are ignored for \afrom\a.]
+        [+NOTE \acomment\a?\acomment\a is added to the current test
+            trace output.]
+        [+OUTPUT [ \b-n\b ]] \afile\a | - \adata\a ...?The standard
+            output is expected to match either the contents of \afile\a or
+            the line \adata\a. \bOUTPUT -n\b does not append a newline to
+            \adata\a.]
+        [+PROG \acommand\a [ \aarg\a ... ]]?\acommand\a is run with
+            optional arguments.]
+        [+REMOVE \afile\a ...?\afile\a ... are removed after the
+            current test is done.]
+        [+RUN?Called by \bregress\b to run the current test.]
+        [+SAME \anew old\a?\anew\a is expected to be the same as
+            \aold\a after the current test completes.]
+	[+SET [\bno\b]]\aname\a[=\avalue\a]]?Set the command line
+	    option --\aname\a.  The setting is in effect for all
+	    tests until the next explicit \bSET\b.]
+        [+TALLY?Called by \bregress\b display the \bTEST\b results.]
+        [+TEST \anumber\a [ \adescription\a ... ]]?Define a new test
+            group labelled \anumber\a with optional \adescripion\a.]
+        [+TITLE [+]] \atext\a?Set the \bTEST\b output title to
+            \atext\a. If \b+\b is specified then \atext\a is appended to
+            the default title. The default title is the test file base
+            name, and, if different from the test file base name, the test
+            unit base name.]
+        [+TWD [ \adir\a ... ]]?Set the temporary test dir to \adir\a.
+            The default is \aunit\a\b.tmp\b, where \aunit\a is the test
+            input file sans directory and suffix. If \adir\a matches \b/*\b
+            then it is the directory name; if \adir\a is non-null then the
+            prefix \b${TMPDIR:-/tmp}\b is added; otherwise if \adir\a is
+            omitted then
+            \b${TMPDIR:-/tmp}/tst-\b\aunit\a-$$-$RANDOM.\b\aunit\a is
+            used.]
+        [+UMASK [ \amask\a ]]?Run subsequent tests with \bumask\b(1)
+            \amask\a. If \amask\a is omitted then the original \bumask\b is
+            used.]
+        [+UNIT \acommand\a [ \aarg\a ... ]]?Define the command and
+            optional default arguments to be tested. \bUNIT\b explicitly
+            overrides the default command name derived from the test script
+            file name.]
+        [+VIEW \avar\a [ \afile\a ]]?\avar\a is set to the full
+            pathname of \avar\a [ \afile\a ]] in the current \b$VPATH\b
+            view if defined.]
+    }
 [+SEE ALSO?\bnmake\b(1), \bksh\b(1)]
 '
 	;;
@@ -189,6 +219,7 @@
 	INPUT=""
 	MOVE=""
 	OUTPUT=""
+	EMPTY PIPE
 	EMPTY SAME
 }
 
@@ -196,8 +227,8 @@
 {
 	typeset base command
 
-	case $quiet in
-	"")	base=${REGRESS##*/}
+	if	[[ ! $TEST_quiet ]]
+	then	base=${REGRESS##*/}
 		base=${base%.tst}
 		command=${COMMAND##*/}
 		command=${command%' '*}
@@ -221,8 +252,7 @@
 			shift
 		done
 		print -u2 "TEST	$TITLE"
-		;;
-	esac
+	fi
 }
 
 function TALLY
@@ -255,7 +285,7 @@
 
 function CLEANUP # status
 {
-	if	[[ ! $keep && $GROUP!=INIT ]]
+	if	[[ ! $TEST_keep && $GROUP!=INIT ]]
 	then	cd $SOURCE
 		RM "$TWD"
 	fi
@@ -265,8 +295,7 @@
 
 function RUN # [ op ]
 {
-	typeset failed i j s
-	typeset $truncate SHOW
+	typeset i
 	case $GROUP in
 	INIT)	RM "$TWD"
 		mkdir "$TWD" || FATAL "$TWD": cannot create directory
@@ -274,7 +303,7 @@
 		TWD=$PWD
 		: > rmu
 		if	rm -u rmu >/dev/null 2>&1
-		then	rmu=-u
+		then	TEST_rmu=-u
 		else	rm rmu
 		fi
 		if	[[ $UNIT ]]
@@ -290,7 +319,8 @@
 		INTRO
 		;;
 	FINI)	;;
-	$select)if	[[ $ITEM == $FLUSHED ]]
+	$TEST_select)
+		if	[[ $ITEM == $FLUSHED ]]
 		then	return
 		fi
 		FLUSHED=$ITEM
@@ -300,40 +330,89 @@
 		else	LASTITEM=$ITEM
 			LABEL=$TEST:$ITEM
 		fi
-		case $quiet in
-		"")	print -nu2 "$LABEL" ;;
-		esac
-		file=""
+		TEST_file=""
 		exec >/dev/null
-		#DEBUG#PS4='+$LINENO+ '; set -x
 		for i in $INPUT
 		do	case " $OUTPUT " in
 			*" $i "*)
 				if	[[ -f $i.sav ]]
 				then	cp $i.sav $i
-					compare="$compare $i"
+					COMPARE="$COMPARE $i"
 				elif	[[ -f $i ]]
 				then	cp $i $i.sav
-					compare="$compare $i"
+					COMPARE="$COMPARE $i"
 				fi
 				;;
 			esac
 		done
 		for i in $OUTPUT
-		do	case " $compare " in
+		do	case " $COMPARE " in
 			*" $i "*)
 				;;
-			*)	compare="$compare $i"
+			*)	COMPARE="$COMPARE $i"
 				;;
 			esac
 		done
 		for i in $INIT
 		do	$i $TEST INIT
 		done
-		case $BODY in
-		"")	COMMAND "${ARGS[@]}" <$TWD/INPUT >$TWD/OUTPUT 2>$TWD/ERROR
-			failed=""
-			ignore=""
+		if	[[ $BODY ]]
+		then	SHOW=$NOTE
+			if	[[ ! $TEST_quiet ]]
+			then	print -r -u2 "	$SHOW"
+			fi
+			for i in $BODY
+			do	$i $TEST BODY
+			done
+		else	SHOW=
+			if	[[ ${PIPE[INPUT]} ]]
+			then	if	[[ ${PIPE[OUTPUT]} ]]
+				then	if	[[ ! $TEST_quiet ]]
+					then	print -nu2 "$LABEL"
+					fi
+					cat <$TWD/INPUT | COMMAND "${ARGS[@]}" 2>$TWD/ERROR | cat >$TWD/OUTPUT
+					RESULTS 'pipe input'
+				else	if	[[ ! $TEST_quiet ]]
+					then	print -nu2 "$LABEL"
+					fi
+					cat <$TWD/INPUT | COMMAND "${ARGS[@]}" >$TWD/OUTPUT 2>$TWD/ERROR
+					RESULTS 'pipe io'
+				fi
+			elif	[[ ${PIPE[OUTPUT]} ]]
+			then	if	[[ ! $TEST_quiet ]]
+				then	print -nu2 "$LABEL"
+				fi
+				COMMAND "${ARGS[@]}" <$TWD/INPUT 2>$TWD/ERROR | cat >$TWD/OUTPUT
+				RESULTS 'pipe output'
+			else	if	[[ $TEST_regular ]]
+				then	if	[[ ! $TEST_quiet ]]
+					then	print -nu2 "$LABEL"
+					fi
+					COMMAND "${ARGS[@]}" <$TWD/INPUT >$TWD/OUTPUT 2>$TWD/ERROR
+					RESULTS
+				fi
+				if	[[ $TEST_pipe_input ]]
+				then	if	[[ ! $TEST_quiet ]]
+					then	print -nu2 "$LABEL"
+					fi
+					cat <$TWD/INPUT | COMMAND "${ARGS[@]}" >$TWD/OUTPUT 2>$TWD/ERROR
+					RESULTS 'pipe input'
+				fi
+				if	[[ $TEST_pipe_output ]]
+				then	if	[[ ! $TEST_quiet ]]
+					then	print -nu2 "$LABEL"
+					fi
+					COMMAND "${ARGS[@]}" <$TWD/INPUT 2>$TWD/ERROR | cat >$TWD/OUTPUT
+					RESULTS 'pipe output'
+				fi
+				if	[[ $TEST_pipe_io ]]
+				then	if	[[ ! $TEST_quiet ]]
+					then	print -nu2 "$LABEL"
+					fi
+					cat <$TWD/INPUT | COMMAND "${ARGS[@]}" 2>$TWD/ERROR | cat >$TWD/OUTPUT
+					RESULTS 'pipe io'
+				fi
+			fi
 			set -- $COPY
 			COPY=""
 			while	:
@@ -345,85 +424,15 @@
 			done
 			set -- $MOVE
 			MOVE=""
-			while	:
-			do	case $# in
-				0|1)	break ;;
-				*)	mv $1 $2; ignore="$ignore $1" ;;
-				esac
+			while	(( $# > 1 ))
+			do	mv $1 $2
 				shift 2
 			done
-			for i in $compare $TWD/OUTPUT $TWD/ERROR
-			do	case " $IGNORE $ignore " in
-				*" $i "*)	continue ;;
-				esac
-				ignore="$ignore $i"
-				j=${SAME[${i##*/}]}
-				if	[[ ! $j ]]
-				then	if	[[ $i == /* ]]
-					then	k=$i
-					else	k=$TWD/$i
-					fi
-					for s in ex sav err
-					do	[[ -f $k.$s ]] && break
-					done
-					j=$k.$s
-				fi
-				case $DIAGNOSTICS:$i in
-				?*:*/ERROR)
-					case $STATUS in
-					0)	[[ ! -s $TWD/ERROR ]] && failed=$failed${failed:+,}DIAGNOSTICS ;;
-					esac
-					continue
-					;;
-				*)	cmp -s $i $j && continue
-					;;
-				esac
-				failed=$failed${failed:+,}${i#$TWD/}
-				case $verbose in
-				?*)	print -u2 "	=== diff ${i#$TWD/} <actual >expected ==="
-					diff $i $j >&2
-					;;
-				esac
-			done
-			case $failed in
-			"")	case $STATUS in
-				$EXIT)	;;
-				*)	failed="exit code $EXIT expected -- got $STATUS" ;;
-				esac
-				;;
-			esac
-			case $failed in
-			"")	SHOW=$NOTE
-				case $quiet in
-				"")	print -r -u2 "	$SHOW" ;;
-				esac
-				;;
-			?*)	((ERRORS++))
-				case $quiet in
-				?*)	print -nu2 "$LABEL" ;;
-				esac
-				SHOW="FAILED [ $failed ] $NOTE"
-				print -r -u2 "	$SHOW"
-				case $keep in
-				?*)	GROUP=FINI; exit ;;
-				esac
-				;;
-			esac
-			;;
-		*)	SHOW=$NOTE
-			case $quiet in
-			"")	print -r -u2 "	$SHOW" ;;
-			esac
-			for i in $BODY
-			do	$i $TEST BODY
-			done
-			;;
-		esac
+		fi
 		for i in $DONE
 		do	$i $TEST DONE $STATUS
 		done
-		compare=""
-		#DEBUG#set +x
+		COMPARE=""
 		;;
 	esac
 	if	[[ $COMMAND_ORIG ]]
@@ -449,7 +458,6 @@
 		case $1 in
 		"")	set -- "$cmd" ;;
 		[-+]*)	set -- "$cmd" "${ARGV[@]}" ;;
-		*)	set -- "${ARGV[@]}"; shift; set -- "$cmd" "$@" ;;
 		esac
 		UNIT=
 	fi
@@ -488,35 +496,29 @@
 	*)		LAST=0${1/[!0123456789]/} TEST=$1 ;;
 	esac
 	NOTE=
-	case $TEST in
-	$select)
-		case $quiet in
-		"")	print -r -u2 "$TEST	$2" ;;
-		esac
-		;;
-	esac
+	if	[[ ! $TEST_quiet && $TEST == $TEST_select ]]
+	then	print -r -u2 "$TEST	$2"
+	fi
 	unset ARGS
 	unset EXPORT
 	EXPORTS=0
-	file=""
-	case $TEST in
-	${GROUP}*)
-		;;
-	*)	GROUP=${TEST%%+([abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ])}
-		case $GROUP in
-		$select)INITIALIZE ;;
-		esac
-		;;
-	esac
+	UMASK=$UMASK_ORIG
+	TEST_file=""
+	if	[[ $TEST != ${GROUP}* ]]
+	then	GROUP=${TEST%%+([abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ])}
+		if	[[ $GROUP == $TEST_select ]]
+		then	INITIALIZE
+		fi
+	fi
 	((SUBTESTS=0))
-	[[ $TEST == $select ]]
+	[[ $TEST == $TEST_select ]]
 }
 
 function EXEC # arg ...
 {
-	case $GROUP in
-	!($select))	return ;;
-	esac
+	if	[[ $GROUP != $TEST_select ]]
+	then	return
+	fi
 	if	((SUBTESTS++))
 	then	RUN
 	fi
@@ -531,18 +533,18 @@
 function CD
 {
 	RUN
-	case $GROUP in
-	$select)	mkdir -p "$@" && cd "$@" || FATAL cannot initialize working directory "$@" ;;
-	esac
+	if	[[ $GROUP == $TEST_select ]]
+	then	mkdir -p "$@" && cd "$@" || FATAL cannot initialize working directory "$@"
+	fi
 }
 
 function EXPORT
 {
 	typeset x
 	RUN
-	case $GROUP in
-	!($select))	return ;;
-	esac
+	if	[[ $GROUP != $TEST_select ]]
+	then	return
+	fi
 	for x
 	do	EXPORT[EXPORTS++]=$x
 	done
@@ -550,9 +552,9 @@
 
 function FLUSH
 {
-	case $GROUP in
-	!($select))	return ;;
-	esac
+	if	[[ $GROUP != $TEST_select ]]
+	then	return
+	fi
 	if	((SUBTESTS++))
 	then	RUN
 	fi
@@ -561,9 +563,9 @@
 function PROG # cmd arg ...
 {
 	typeset command args
-	case $GROUP in
-	!($select))	return ;;
-	esac
+	if	[[ $GROUP != $TEST_select ]]
+	then	return
+	fi
 	ITEM=$LINE
 	NOTE="$(print -r -f '%q ' -- "$@")"
 	COMMAND_ORIG=$COMMAND
@@ -578,20 +580,25 @@
 	NOTE=$*
 }
 
-function IO # INPUT|OUTPUT|ERROR [-f|-n] file|- data ...
+function IO # [ PIPE ] INPUT|OUTPUT|ERROR [-f*|-n] file|- data ...
 {
-	typeset op i v f file x
-	case $GROUP in
-	!($select))	return ;;
-	esac
+	typeset op i v f file pipe x
+	if	[[ $GROUP != $TEST_select ]]
+	then	return
+	fi
+	if	[[ $1 == PIPE ]]
+	then	pipe=1
+		shift
+	fi
 	op=$1
 	shift
+	PIPE[$op]=$pipe
 	file=$TWD/$op
 	case $1 in
 	-x)	x=1; shift ;;
 	esac
 	case $1 in
-	-[fn])	f=$1; shift ;;
+	-f*|-n)	f=$1; shift ;;
 	esac
 	case $# in
 	0)	;;
@@ -639,6 +646,7 @@
 	then	case $#:$f in
 		0:)	: > $file ;;
 		*:-f)	printf -- "$@" > $file ;;
+		*:-f*)	printf -- "${f#-f}""$@" > $file ;;
 		*)	print $f -r -- "$@" > $file ;;
 		esac
 		if	[[ $x ]]
@@ -654,18 +662,18 @@
 
 function COPY # from to
 {
-	case $GROUP in
-	!($select))	return ;;
-	esac
+	if	[[ $GROUP != $TEST_select ]]
+	then	return
+	fi
 	COPY="$COPY $@"
 }
 
 function MOVE # from to
 {
 	typeset f
-	case $GROUP in
-	!($select))	return ;;
-	esac
+	if	[[ $GROUP != $TEST_select ]]
+	then	return
+	fi
 	for f
 	do	case $f in
 		INPUT|OUTPUT|ERROR)
@@ -682,16 +690,16 @@
 function SAME # new old
 {
 	typeset i file v
-	case $GROUP in
-	!($select))	return ;;
-	esac
+	if	[[ $GROUP != $TEST_select ]]
+	then	return
+	fi
 	case $# in
 	2)	case $1 in
 		INPUT)	cat $2 > $1; return ;;
 		esac
 		SAME[$1]=$2
 		file=$1
-		compare="$compare $1"
+		COMPARE="$COMPARE $1"
 		;;
 	3)	SAME[$2]=$3
 		file=$2
@@ -702,7 +710,7 @@
 		*)	eval $1='"$'$1' $2"'
 			;;
 		esac
-		compare="$compare $2"
+		COMPARE="$COMPARE $2"
 		;;
 	esac
 	case " $IGNORE " in
@@ -730,10 +738,10 @@
 
 function RM # rm(1) args
 {
-	if	[[ ! $rmu ]]
+	if	[[ ! $TEST_rmu ]]
 	then	chmod -R u+rwx "$@" >/dev/null 2>&1
 	fi
-	rm $rmu $rmflags "$@"
+	rm $TEST_rmu $TEST_rmflags "$@"
 }
 
 function REMOVE # file ...
@@ -779,6 +787,11 @@
 	EXIT='*'
 }
 
+function IGNORESPACE
+{
+	: ${IGNORESPACE=-b}
+}
+
 function EXIT # status
 {
 	EXIT=$1
@@ -787,13 +800,13 @@
 function INFO # info description
 {
 	typeset -R15 info=$1
-	case $1 in
-	"")	info=no ;;
-	esac
+	if	[[ ! $1 ]]
+	then	info=no
+	fi
 	shift
-	case $quiet in
-	"")	print -r -u2 "$info " "$@" ;;
-	esac
+	if	[[ ! $TEST_quiet ]]
+	then	print -r -u2 "$info " "$@"
+	fi
 }
 
 function COMMAND # arg ...
@@ -806,31 +819,108 @@
 		EXPORT[EXPORTS++]="LC_ALL="
 		;;
 	esac
-	case $keep in
-	?*)	(
+	if	[[ $TEST_keep ]]
+	then	(
 		PS4=''
 		set -x
 		print -r -- "${EXPORT[@]}" $COMMAND "$@"
 		) 2>&1 >/dev/null |
 		sed 's,^print -r -- ,,' >$TWD/COMMAND
 		chmod +x $TWD/COMMAND
-		;; 
-	esac
+	fi
+	[[ $UMASK != $UMASK_ORIG ]] && umask $UMASK
 	eval "${EXPORT[@]}" '$'COMMAND '"$@"'
 	STATUS=$?
+	[[ $UMASK != $UMASK_ORIG ]] && umask $UMASK_ORIG
 	return $STATUS
 }
 
+function RESULTS # pipe*
+{
+	typeset i j k s failed ignore io
+	if	[[ $1 ]]
+	then	io="$1 "
+	fi
+	for i in $COMPARE $TWD/OUTPUT $TWD/ERROR
+	do	case " $IGNORE $ignore $MOVE " in
+		*" $i "*)	continue ;;
+		esac
+		ignore="$ignore $i"
+		j=${SAME[${i##*/}]}
+		if	[[ ! $j ]]
+		then	if	[[ $i == /* ]]
+			then	k=$i
+			else	k=$TWD/$i
+			fi
+			for s in ex sav err
+			do	[[ -f $k.$s ]] && break
+			done
+			j=$k.$s
+		fi
+		if	[[ $DIAGNOSTICS && $i == */ERROR ]]
+		then	if	[[ $STATUS == 0 && ! -s $TWD/ERROR ]]
+			then	failed=$failed${failed:+,}DIAGNOSTICS
+			fi
+			continue
+		fi
+		diff $IGNORESPACE $i $j >$i.diff 2>&1
+		if	[[ -s $i.diff ]]
+		then	failed=$failed${failed:+,}${i#$TWD/}
+			if	[[ $TEST_verbose ]]
+			then	print -u2 "	===" diff $IGNORESPACE ${i#$TWD/} "<actual >expected ==="
+				cat $i.diff >&2
+			fi
+		fi
+	done
+	if	[[ ! $failed && $STATUS != $EXIT ]]
+	then	failed="exit code $EXIT expected -- got $STATUS"
+	fi
+	if	[[ $failed ]]
+	then	((ERRORS++))
+		if	[[ ! $TEST_quiet ]]
+		then	SHOW="FAILED ${io}[ $failed ] $NOTE"
+			print -r -u2 "	$SHOW"
+		fi
+		if	[[ $TEST_keep ]]
+		then	GROUP=FINI
+			exit
+		fi
+	elif	[[ ! $TEST_quiet ]]
+	then	SHOW=$NOTE
+		print -r -u2 "	$SHOW"
+	fi
+}
+
 function SET # [no]name[=value]
 {
-	typeset i
+	typeset i r
+	if	[[ $TEST ]]
+	then	RUN
+	fi
 	for i
-	do	case $i in
-		no?*)	eval ${i#no}='""' ;;
-		*=0)	eval ${i%0}='""' ;;
-		*=*)	eval $i ;;
-		*)	eval $i=1 ;;
-		esac
+	do	if	[[ $i == - ]]
+		then	r=1
+		elif	[[ $i == + ]]
+		then	r=
+		else	if	[[ $i == no?* ]]
+			then	i=${i#no}
+				v=
+			elif	[[ $i == *=* ]]
+			then	v=${i#*=}
+				if	[[ $v == 0 ]]
+				then	v=
+				fi
+				i=${i%%=*}
+			else	v=1
+			fi
+			i=${i//-/_}
+			if	[[ $r ]]
+			then	READONLY[$i]=1
+			elif	[[ ${READONLY[$i]} ]]
+			then	continue
+			fi
+			eval TEST_$i=$v
+		fi
 	done
 }
 
@@ -901,34 +991,61 @@
 	done
 }
 
+function UMASK # [ mask ]
+{
+	if	(( $# ))
+	then	UMASK=$1
+		if	[[ $GROUP == INIT ]]
+		then	UMASK_ORIG=$UMASK
+		fi
+	else	UMASK=$UMASK_ORIG
+	fi
+}
+
+function PIPE # INPUT|OUTPUT|ERROR file|- data ...
+{
+	IO $0 "$@"
+}
+
 # main
 
 integer ERRORS=0 EXPORTS=0 TESTS=0 SUBTESTS=0 LINE=0 ITEM=0 LASTITEM=0 COUNT
 typeset ARGS COMMAND COPY DIAGNOSTICS ERROR EXEC FLUSHED=0 GROUP=INIT
-typeset IGNORE INPUT KEEP OUTPUT TEST SOURCE MOVE NOTE
-typeset ARGS_ORIG COMMAND_ORIG TITLE UNIT ARGV PREFIX OFFSET
-typeset file keep quiet rmflags='-rf --' rmu select trace verbose truncate=-L70
-typeset -A EXPORT SAME VIEWS
+typeset IGNORE INPUT KEEP OUTPUT TEST SOURCE MOVE NOTE UMASK UMASK_ORIG
+typeset ARGS_ORIG COMMAND_ORIG TITLE UNIT ARGV PREFIX OFFSET IGNORESPACE
+typeset COMPARE
+typeset TEST_file TEST_keep TEST_pipe_input TEST_pipe_io TEST_pipe_output
+typeset TEST_quiet TEST_regular=1 TEST_rmflags='-rf --' TEST_rmu TEST_select
+
+typeset -A EXPORT SAME VIEWS PIPE READONLY
 typeset -Z LAST=00
 
 unset FIGNORE
 
 while	getopts -a $command "$USAGE" OPT
 do	case $OPT in
-	k)	SET keep=1
-		(ulimit -c 0) >/dev/null 2>&1 && ulimit -c 0
+	b)	(( $OPTARG )) && IGNORESPACE=-b
 		;;
-	q)	SET quiet=1
+	i)	SET - pipe-input=$OPTARG
 		;;
-	t)	case $select in
-		"")	select="${OPTARG//,/\|}" ;;
-		*)	select="$select|${OPTARG//,/\|}" ;;
-		esac
+	k)	SET - keep=$OPTARG
+		;;
+	o)	SET - pipe-output=$OPTARG
+		;;
+	p)	SET - pipe-io=$OPTARG
+		;;
+	q)	SET - quiet=$OPTARG
+		;;
+	r)	SET - regular=$OPTARG
 		;;
-	v)	SET verbose=1
-		truncate=
+	t)	if	[[ $TEST_select ]]
+		then	TEST_select="$TEST_select|${OPTARG//,/\|}"
+		else	TEST_select="${OPTARG//,/\|}"
+		fi
+		;;
+	v)	SET - verbose=$OPTARG
 		;;
-	D)	SET trace=1
+	D)	SET - trace=$OPTARG
 		;;
 	*)	GROUP=FINI
 		exit 2
@@ -973,23 +1090,30 @@
 fi
 TWD=$PWD/$UNIT.tmp
 PMP=$(/bin/pwd)/$UNIT.tmp
+UMASK_ORIG=$(umask)
 ARGV=("$@")
 trap 'RUN; CLEANUP 0' EXIT
 trap 'CLEANUP $?' HUP INT PIPE TERM
-case $select in
-"")	select="[0123456789]*" ;;
-esac
-select="@($select|+(0))"
-case $trace in
-?*)	PS4='+$LINENO+ '
+if	[[ ! $TEST_select ]]
+then	TEST_select="[0123456789]*"
+fi
+TEST_select="@($TEST_select|+(0))"
+if	[[ $TEST_trace ]]
+then	PS4='+$LINENO+ '
 	set -x
-	;;
-esac
+fi
+if	[[ $TEST_verbose ]]
+then	typeset SHOW
+else	typeset -L70 SHOW
+fi
+if	[[ $TEST_keep ]] && (ulimit -c 0) >/dev/null 2>&1
+then	ulimit -c 0
+fi
 
 # some last minute shenanigans
 
 alias BODY='BODY=BODY; function BODY'
-alias DO='(( $ITEM != $FLUSHED )) && RUN DO; [[ $GROUP == $select ]] &&'
+alias DO='(( $ITEM != $FLUSHED )) && RUN DO; [[ $GROUP == $TEST_select ]] &&'
 alias DONE='DONE=DONE; function DONE'
 alias EXEC='LINE=$LINENO; EXEC'
 alias INIT='INIT=INIT; function INIT'
diff -r -N -u ksh93_2006_07_24/src/cmd/INIT/RELEASE ksh93_2006_09_12/src/cmd/INIT/RELEASE
--- ksh93_2006_07_24/src/cmd/INIT/RELEASE	2006-07-21 21:23:18.000000000 +0200
+++ ksh93_2006_09_12/src/cmd/INIT/RELEASE	2006-09-08 23:26:22.000000000 +0200
@@ -1,3 +1,13 @@
+06-09-08 regress.sh: add PIPE INPUT|OUTPUT for pipe io
+06-09-05 C+probe: add { probe_version version_stamp version_string }
+06-09-05 make.probe: add version stamp comment, CC.VERSION[.STRING]
+06-08-27 regress.sh,mktest.sh: add UMASK
+06-08-25 regress.sh: add -b,--ignore-space,IGNORESPACE
+06-08-25 mktest.sh: add IGNORESPACE
+06-08-24 mktest.sh: handle \000 in data
+06-08-24 regress.sh: handle -f* for INPUT|OUTPUT|ERROR
+06-08-16 package.sh: fix 'install flat' logic
+06-08-11 rt.sh: handle style=shell %K date format
 06-07-17 ratz.c: fix __MVS__ FAR definition
 06-07-17 iffe.sh: "header x.h" -- deprecate "include x.h" for .SCAN.iffe
 06-07-17 package.sh: differentiate urls vs. assignments
diff -r -N -u ksh93_2006_07_24/src/cmd/INIT/rt.sh ksh93_2006_09_12/src/cmd/INIT/rt.sh
--- ksh93_2006_07_24/src/cmd/INIT/rt.sh	2006-06-27 17:08:28.000000000 +0200
+++ ksh93_2006_09_12/src/cmd/INIT/rt.sh	2006-08-13 10:56:01.000000000 +0200
@@ -29,7 +29,7 @@
 0123)	ARGV0="-a $command"
 	USAGE=$'
 [-?
-@(#)$Id: rt (AT&T Research) 2006-06-27 $
+@(#)$Id: rt (AT&T Research) 2006-08-11 $
 ]
 '$USAGE_LICENSE$'
 [+NAME?rt - run "nmake test" and filter output]
@@ -52,7 +52,7 @@
 '
 	;;
 *)	ARGV0=""
-	USAGE="fv"
+	USAGE="fhv"
 	;;
 esac
 
@@ -214,7 +214,7 @@
 		fi
 		continue
 		;;
-	'test '*' begins at '*' '*' '*' '*' '*)
+	'test '*' begins at '????-??-??+??:??:??|'test '*' begins at '*' '*' '*' '*' '*)
 		results $tests $errors
 		unit=${2##*/}
 		unit=${unit%.sh}
@@ -225,7 +225,7 @@
 		style=shell
 		continue
 		;;
-	'test '*' at '*' '*' '*' '*' '*)
+	'test '*' at '????-??-??+??:??:??' [ '*' ]'|'test '*' at '*' '*' '*' '*' '*)
 		case $line in
 		*' [ '*test*error*' ]')
 			while	:
diff -r -N -u ksh93_2006_07_24/src/cmd/ksh93/bltins/getopts.c ksh93_2006_09_12/src/cmd/ksh93/bltins/getopts.c
--- ksh93_2006_07_24/src/cmd/ksh93/bltins/getopts.c	2004-01-06 14:55:06.000000000 +0100
+++ ksh93_2006_09_12/src/cmd/ksh93/bltins/getopts.c	2006-08-11 19:36:23.000000000 +0200
@@ -163,13 +163,20 @@
 	nv_putval(np, options, 0);
 	nv_close(np);
 	np = nv_open(nv_name(OPTARGNOD),shp->var_tree,NV_NOSCOPE);
-	if(opt_info.num != LONG_MIN)
+	if(opt_info.num == LONG_MIN)
+		nv_putval(np, opt_info.arg, NV_RDONLY);
+	else if (opt_info.num > 0 && opt_info.arg && opt_info.arg[0] == (char)opt_info.num)
 	{
-		Sfdouble_t d = opt_info.number;
-		nv_putval(np, (char*)&d, NV_INTEGER|NV_DOUBLE|NV_LONG|NV_RDONLY);
+		key[0] = (char)opt_info.num;
+		key[1] = 0;
+		nv_putval(np, key, NV_RDONLY);
 	}
 	else
-		nv_putval(np, opt_info.arg, NV_RDONLY);
+	{
+		Sfdouble_t d;
+		d = opt_info.number;
+		nv_putval(np, (char*)&d, NV_INTEGER|NV_DOUBLE|NV_LONG|NV_RDONLY);
+	}
 	nv_close(np);
 	sh_popcontext(&buff);
         opt_info.disc = 0;
diff -r -N -u ksh93_2006_07_24/src/cmd/ksh93/bltins/print.c ksh93_2006_09_12/src/cmd/ksh93/bltins/print.c
--- ksh93_2006_07_24/src/cmd/ksh93/bltins/print.c	2006-05-19 17:14:12.000000000 +0200
+++ ksh93_2006_09_12/src/cmd/ksh93/bltins/print.c	2006-08-25 17:39:25.000000000 +0200
@@ -35,7 +35,7 @@
 #include	"history.h"
 #include	"builtins.h"
 #include	"streval.h"
-#include	<tm.h>
+#include	<tmx.h>
 #include	<ctype.h>
 #include	<ccode.h>
 
@@ -384,6 +384,14 @@
 			if(*s==0)
 				break;
                         c = chresc(s - 1, &p);
+                        s = p;
+#if SHOPT_MULTIBYTE
+			if(c>UCHAR_MAX && mbwide())
+			{
+				t += wctomb(t, c);
+				continue;
+			}
+#endif /* SHOPT_MULTIBYTE */
 			if(c=='%')
 				*t++ = '%';
 			else if(c==0)
@@ -391,7 +399,6 @@
 				*t++ = '%';
 				c = 'Z';
 			}
-                        s = p;
                         break;
                     case 0:
                         *t = 0;
@@ -570,7 +577,7 @@
 			break;
 		case 'T':
 			fe->fmt = 'd';
-			value->ll = time(NIL(time_t*));
+			value->ll = tmxgettime();
 			break;
 		default:
 			if(!strchr("DdXxoUu",format))
@@ -702,7 +709,7 @@
 			value->ll = (Sflong_t)strelapsed(*pp->nextarg,&lastchar,1);
 			break;
 		case 'T':
-			value->ll = (Sflong_t)tmdate(*pp->nextarg,&lastchar,NIL(time_t*));
+			value->ll = (Sflong_t)tmxdate(*pp->nextarg,&lastchar,TMX_NOW);
 			break;
 		default:
 			value->ll = 0;
@@ -775,10 +782,10 @@
 		{
 			n = fe->t_str[fe->n_str];
 			fe->t_str[fe->n_str] = 0;
-			value->s = fmttime(fe->t_str, value->ll);
+			value->s = fmttmx(fe->t_str, value->ll);
 			fe->t_str[fe->n_str] = n;
 		}
-		else value->s = fmttime(NIL(char*), value->ll);
+		else value->s = fmttmx(NIL(char*), value->ll);
 		fe->fmt = 's';
 		fe->size = -1;
 		break;
diff -r -N -u ksh93_2006_07_24/src/cmd/ksh93/bltins/read.c ksh93_2006_09_12/src/cmd/ksh93/bltins/read.c
--- ksh93_2006_07_24/src/cmd/ksh93/bltins/read.c	2006-02-09 06:19:06.000000000 +0100
+++ ksh93_2006_09_12/src/cmd/ksh93/bltins/read.c	2006-09-05 23:45:40.000000000 +0200
@@ -63,7 +63,7 @@
 		break;
 	    case 't':
 		sec = sh_strnum(opt_info.arg, (char**)0,1);
-		timeout = 1000*sec+1;
+		timeout = sec ? 1000*sec : 1;
 		break;
 	    case 'd':
 		if(opt_info.arg && *opt_info.arg!='\n')
diff -r -N -u ksh93_2006_07_24/src/cmd/ksh93/bltins/test.c ksh93_2006_09_12/src/cmd/ksh93/bltins/test.c
--- ksh93_2006_07_24/src/cmd/ksh93/bltins/test.c	2005-11-23 17:37:42.000000000 +0100
+++ ksh93_2006_09_12/src/cmd/ksh93/bltins/test.c	2006-07-29 04:20:00.000000000 +0200
@@ -38,14 +38,7 @@
 #include	"builtins.h"
 #include	"FEATURE/externs"
 #include	"FEATURE/poll"
-#include	<tm.h>
-#if TM_VERSION >= 20041201L
 #include	<tmx.h>
-#else
-typedef unsigned long Time_t;
-#define tmxgetatime(s)	((s)->st_atime)
-#define tmxgetmtime(s)	((s)->st_mtime)
-#endif
 
 #ifndef _lib_setregid
 #   undef _lib_setreuid
diff -r -N -u ksh93_2006_07_24/src/cmd/ksh93/bltins/typeset.c ksh93_2006_09_12/src/cmd/ksh93/bltins/typeset.c
--- ksh93_2006_07_24/src/cmd/ksh93/bltins/typeset.c	2006-06-12 21:52:25.000000000 +0200
+++ ksh93_2006_09_12/src/cmd/ksh93/bltins/typeset.c	2006-09-08 23:55:36.000000000 +0200
@@ -200,6 +200,9 @@
 	{
 		switch(n)
 		{
+			case 'a':
+				flag |= NV_IARRAY;
+				break;
 			case 'A':
 				flag |= NV_ARRAY;
 				break;
@@ -414,6 +417,14 @@
 				nv_settype(np,tp->tp,tp->aflag=='-'?0:NV_APPEND);
 				flag = (np->nvflag&NV_NOCHANGE);
 			}
+			if(troot==shp->var_tree && (flag&NV_IARRAY))
+			{
+				flag &= ~NV_IARRAY;
+				if(nv_isnull(np))
+					nv_onattr(np,NV_ARRAY);
+				else
+					nv_putsub(np, (char*)0, 0);
+			}
 			if(troot==shp->var_tree && (nvflags&NV_ARRAY))
 				nv_setarray(np,nv_associative);
 			curflag = np->nvflag;
@@ -569,7 +580,7 @@
 	register char *arg=0, *name;
 	register int n, r=0, flag=0;
 	register Namval_t *np;
-	int dlete=0;
+	long dlete=0;
 	struct tdata tdata;
 	Fptr_t addr;
 	void *library=0;
@@ -647,7 +658,7 @@
 			/* (char*) added for some sgi-mips compilers */ 
 			if(dlete || (addr = (Fptr_t)dlllook(liblist[n],stakptr(flag))))
 			{
-				if(np = sh_addbuiltin(arg, addr,(void*)dlete))
+				if(np = sh_addbuiltin(arg, addr,pointerof(dlete)))
 				{
 					if(dlete || nv_isattr(np,BLT_SPC))
 						errmsg = "restricted name";
diff -r -N -u ksh93_2006_07_24/src/cmd/ksh93/data/builtins.c ksh93_2006_09_12/src/cmd/ksh93/data/builtins.c
--- ksh93_2006_07_24/src/cmd/ksh93/data/builtins.c	2006-06-22 00:06:43.000000000 +0200
+++ ksh93_2006_09_12/src/cmd/ksh93/data/builtins.c	2006-09-05 03:26:57.000000000 +0200
@@ -239,6 +239,8 @@
 			"command to exit with non-zero exit status, or will "
 			"be zero if all commands return zero exit status.]"
 		"[+privileged?Equivalent to \b-p\b.]"
+		"[+showme?Simple commands preceded by a \b;\b will be traced "
+			"as if \b-x\b were enabled but not executed.]"
 		"[+trackall?Equivalent to \b-h\b.]"
 		"[+verbose?Equivalent to \b-v\b.]"
 		"[+vi?Enables/disables \bvi\b editing mode.]"
@@ -1259,8 +1261,10 @@
 "[u]#[fd:=0?Read from file descriptor number \afd\a instead of standard input.]"
 "[t]:[timeout?Specify a timeout \atimeout\a in seconds when reading from "
 	"a terminal or pipe.]"
-"[n]#[nbyte?Read at most \anbyte\a bytes.]"
-"[N]#[nbyte?Read exactly \anbyte\a bytes.]"
+"[n]#[nbyte?Read at most \ansize\a characters.  For binary fields \asize\a "
+	"will be in bytes.]"
+"[N]#[nbyte?Read exactly \ansize\a characters.  For binary fields \asize\a "
+	"will be in bytes.]"
 "\n"
 "\n[var?prompt] [var ...]\n"
 "\n"
@@ -1571,6 +1575,7 @@
 #if SHOPT_BASH
 "[a?Ignored, used for bash compatibility.]"
 #endif
+"[a?Indexed array. this is the default.]"
 "[b?Each \aname\a may contain binary data.  Its value is the mime "
 	"base64 encoding of the data. It can be used with \b-Z\b, "
 	"to specify fixed sized fields.]"
@@ -1820,7 +1825,6 @@
 
 const char e_alrm1[]		= "alarm -r %s +%.3g\n";
 const char e_alrm2[]		= "alarm %s %.3f\n";
-const char e_badfun[]		= "%s: illegal function name";
 const char e_baddisc[]		= "%s: invalid discipline function";
 const char e_nospace[]		= "out of memory";
 const char e_nofork[]		= "cannot fork";
diff -r -N -u ksh93_2006_07_24/src/cmd/ksh93/data/lexstates.c ksh93_2006_09_12/src/cmd/ksh93/data/lexstates.c
--- ksh93_2006_07_24/src/cmd/ksh93/data/lexstates.c	2005-05-20 00:13:04.000000000 +0200
+++ ksh93_2006_09_12/src/cmd/ksh93/data/lexstates.c	2006-08-11 21:00:24.000000000 +0200
@@ -200,10 +200,10 @@
 static const char sh_lexstate5[256] =
 {
 	S_EOF,	0,	0,	0,	0,	0,	0,	0,
-	0,	0,	S_NL,	0,	0,	0,	0,	0,
+	0,	S_BLNK,	S_NL,	0,	0,	0,	0,	0,
 	0,	0,	0,	0,	0,	0,	0,	0,
 	0,	0,	0,	0,	0,	0,	0,	0,
-	0,	0,	S_QUOTE,0,	S_DOL,	0,	S_META,	S_LIT,
+	S_BLNK,	0,	S_QUOTE,0,	S_DOL,	0,	S_META,	S_LIT,
 	S_PUSH,	S_POP,	0,	0,	0,	0,	0,	0,
 	0,	0,	0,	0,	0,	0,	0,	0,
 	0,	0,	0,	S_POP,	S_META,	0,	S_META,	0,
@@ -228,15 +228,15 @@
 	S_ERR,	S_ERR,	S_ERR,	S_ERR,	S_ERR,	S_ERR,	S_ERR,	S_ERR,
 
 	S_ERR,	S_SPC1,	S_ERR,	S_SPC1,	S_SPC2,	S_ERR,	S_ERR,	S_LIT,
-#if SHOPT_OO
-	S_PAR,	S_ERR,	S_SPC2,	S_ERR,	S_ERR,	S_SPC1,	S_ALP,	S_ERR,
-#else
 	S_PAR,	S_ERR,	S_SPC2,	S_ERR,	S_ERR,	S_SPC2,	S_ALP,	S_ERR,
-#endif /* SHOPT_OO */
 	S_DIG,	S_DIG,	S_DIG,	S_DIG,	S_DIG,	S_DIG,	S_DIG,	S_DIG,
 	S_DIG,	S_DIG,	S_ERR,	S_ERR,	S_ERR,	S_ERR,	S_ERR,	S_SPC2,
 
+#if SHOPT_TYPEDEF
+	S_SPC1,	S_ALP,	S_ALP,	S_ALP,	S_ALP,	S_ALP,	S_ALP,	S_ALP,
+#else
 	S_SPC2,	S_ALP,	S_ALP,	S_ALP,	S_ALP,	S_ALP,	S_ALP,	S_ALP,
+#endif
 	S_ALP,	S_ALP,	S_ALP,	S_ALP,	S_ALP,	S_ALP,	S_ALP,	S_ALP,
 	S_ALP,	S_ALP,	S_ALP,	S_ALP,	S_ALP,	S_ALP,	S_ALP,	S_ALP,
 	S_ALP,	S_ALP,	S_ALP,	S_ERR,	S_ERR,	S_ERR,	S_ERR,	S_ALP,
diff -r -N -u ksh93_2006_07_24/src/cmd/ksh93/data/msg.c ksh93_2006_09_12/src/cmd/ksh93/data/msg.c
--- ksh93_2006_07_24/src/cmd/ksh93/data/msg.c	2006-06-21 23:40:08.000000000 +0200
+++ ksh93_2006_09_12/src/cmd/ksh93/data/msg.c	2006-08-16 07:58:01.000000000 +0200
@@ -91,7 +91,7 @@
 const char e_ident[]		= "%s: is not an identifier";
 const char e_badname[]		= "%s: invalid name";
 const char e_varname[]		= "%s: invalid variable name";
-const char e_funname[]		= "%s: invalid function name";
+const char e_badfun[]		= "%s: invalid function name";
 const char e_aliname[]		= "%s: invalid alias name";
 const char e_badexport[]	= "%s: invalid export name";
 const char e_badref[]		= "%s: reference variable cannot be an array";
diff -r -N -u ksh93_2006_07_24/src/cmd/ksh93/data/options.c ksh93_2006_09_12/src/cmd/ksh93/data/options.c
--- ksh93_2006_07_24/src/cmd/ksh93/data/options.c	2006-07-20 22:10:53.000000000 +0200
+++ ksh93_2006_09_12/src/cmd/ksh93/data/options.c	2006-09-07 01:00:31.000000000 +0200
@@ -101,6 +101,7 @@
 	"restricted",			SH_RESTRICTED,
 	bashopt("restricted_shell",	SH_RESTRICTED2|SH_COMMANDLINE)
 	bashopt("shift_verbose",	SH_SHIFT_VERBOSE)
+	"showme",			SH_SHOWME,
 	bashopt("sourcepath",		SH_SOURCEPATH)
 	"trackall",			SH_TRACKALL,
 	"nounset",			SH_NOUNSET,
@@ -132,7 +133,8 @@
 	{"-Lleftjust",	NV_LJUST},
 	{"-Rrightjust",	NV_RJUST},
 	{"-uuppercase",	NV_LTOU},
-	{"-Aarray",	NV_ARRAY},
+	{"-Aassociative array",	NV_ARRAY},
+	{"-aindexed array",	NV_ARRAY},
 	{"++namespace",	NV_TABLE},
 	{"",		0}
 };
diff -r -N -u ksh93_2006_07_24/src/cmd/ksh93/edit/completion.c ksh93_2006_09_12/src/cmd/ksh93/edit/completion.c
--- ksh93_2006_07_24/src/cmd/ksh93/edit/completion.c	2006-06-26 00:46:00.000000000 +0200
+++ ksh93_2006_09_12/src/cmd/ksh93/edit/completion.c	2006-08-14 15:49:19.000000000 +0200
@@ -235,7 +235,7 @@
 		if(*begin=='~' && !strchr(begin,'/'))
 			addstar = 0;
 		stakputc(addstar);
-		stakfreeze(1);
+		ap = (struct argnod*)stakfreeze(1);
 	}
 	if(mode!='*')
 		sh_onoption(SH_MARKDIRS);
@@ -352,8 +352,6 @@
 			out = strcopy(begin,*com++);
 		if(mode=='\\')
 		{
-			if(var!='$' && addstar==0)
-				*out++ = '/';
 			saveout= ++out;
 			while (*com && *begin)
 			{
diff -r -N -u ksh93_2006_07_24/src/cmd/ksh93/edit/edit.c ksh93_2006_09_12/src/cmd/ksh93/edit/edit.c
--- ksh93_2006_07_24/src/cmd/ksh93/edit/edit.c	2006-06-29 04:52:03.000000000 +0200
+++ ksh93_2006_09_12/src/cmd/ksh93/edit/edit.c	2006-09-08 21:52:16.000000000 +0200
@@ -33,6 +33,7 @@
 #include	<ctype.h>
 #include	"FEATURE/options"
 #include	"FEATURE/time"
+#include	"FEATURE/cmds"
 #ifdef _hdr_utime
 #   include	<utime.h>
 #   include	<ls.h>
@@ -50,11 +51,13 @@
 #include	"history.h"
 #include	"edit.h"
 
-static const char CURSOR_UP[] = { ESC, '[', 'A', 0 };
+static char CURSOR_UP[20] = { ESC, '[', 'A', 0 };
 
 #if SHOPT_MULTIBYTE
+#   define is_cntrl(c)	((c<=STRIP) && iscntrl(c))
 #   define is_print(c)	((c&~STRIP) || isprint(c))
 #else
+#   define is_cntrl(c)	iscntrl(c)
 #   define is_print(c)	isprint(c)
 #endif
 
@@ -729,7 +732,22 @@
 	sfwrite(sfstderr,ep->e_outptr,0);
 	ep->e_eol = reedit;
 	if(ep->e_multiline)
+	{
+#ifdef _cmd_infocmp
+		char *term;
+		if(!ep->e_term)
+			ep->e_term = nv_search("TERM",sh.var_tree,0);
+		if(ep->e_term && (term=nv_getval(ep->e_term)) && strlen(term)<sizeof(ep->e_termname) && strcmp(term,ep->e_termname))
+		{
+			sh_trap("eval .sh.subscript=$(infocmp -1C | sed -e '/:up=/!d' -e 's/.*:up=//' -e 's/:\\\\*$//' -e \"s/[']/\\'/g\" -e \"s/.*/$'&'/\")",0);
+			if(pp=nv_getval(SH_SUBSCRNOD))
+				strncpy(CURSOR_UP,pp,sizeof(CURSOR_UP)-1);
+			nv_unset(SH_SUBSCRNOD);
+			strcpy(ep->e_termname,term);
+		}
+#endif
 		ep->e_wsize = MAXLINE - (ep->e_plen-2);
+	}
 }
 
 /*
@@ -1169,10 +1187,9 @@
 	{
 		if(curp == sp)
 			r = dp - phys;
-		d = (is_print(c)?1:-1);
 #if SHOPT_MULTIBYTE
 		d = mbwidth((wchar_t)c);
-		if(d==1 && !is_print(c))
+		if(d==1 && is_cntrl(c))
 			d = -1;
 		if(d>1)
 		{
@@ -1186,6 +1203,8 @@
 			continue;
 		}
 		else
+#else
+		d = (is_cntrl(c)?-1:1);
 #endif	/* SHOPT_MULTIBYTE */
 		if(d<0)
 		{
diff -r -N -u ksh93_2006_07_24/src/cmd/ksh93/edit/hexpand.c ksh93_2006_09_12/src/cmd/ksh93/edit/hexpand.c
--- ksh93_2006_07_24/src/cmd/ksh93/edit/hexpand.c	2005-12-13 22:29:26.000000000 +0100
+++ ksh93_2006_09_12/src/cmd/ksh93/edit/hexpand.c	2006-07-27 04:36:35.000000000 +0200
@@ -268,6 +268,8 @@
 			if(c == '-')
 				n = -n;
 			break;
+		case '$':
+			n = -1;
 		case ':':
 			break;
 		case '?':
diff -r -N -u ksh93_2006_07_24/src/cmd/ksh93/edit/vi.c ksh93_2006_09_12/src/cmd/ksh93/edit/vi.c
--- ksh93_2006_07_24/src/cmd/ksh93/edit/vi.c	2006-06-23 22:56:01.000000000 +0200
+++ ksh93_2006_09_12/src/cmd/ksh93/edit/vi.c	2006-08-14 15:49:19.000000000 +0200
@@ -2324,7 +2324,7 @@
 			--cur_virt;
 			--last_virt;
 			vp->ocur_virt = MAXCHAR;
-			if(c=='=' || (mode>cur_virt && (virtual[cur_virt]==' ' || virtual[cur_virt]=='/')))
+			if(c=='=' || (mode<cur_virt && (virtual[cur_virt]==' ' || virtual[cur_virt]=='/')))
 				vp->ed->e_tabcount = 0;
 			return(APPEND);
 		}
diff -r -N -u ksh93_2006_07_24/src/cmd/ksh93/features/cmds ksh93_2006_09_12/src/cmd/ksh93/features/cmds
--- ksh93_2006_07_24/src/cmd/ksh93/features/cmds	2002-12-04 23:25:52.000000000 +0100
+++ ksh93_2006_09_12/src/cmd/ksh93/features/cmds	2006-08-30 19:10:36.000000000 +0200
@@ -1 +1 @@
-cmd	newgrp,test,id,wc,cut,logname,universe,pfexec
+cmd	newgrp,test,id,wc,cut,logname,universe,pfexec,infocmp
diff -r -N -u ksh93_2006_07_24/src/cmd/ksh93/include/defs.h ksh93_2006_09_12/src/cmd/ksh93/include/defs.h
--- ksh93_2006_07_24/src/cmd/ksh93/include/defs.h	2006-06-21 23:44:07.000000000 +0200
+++ ksh93_2006_09_12/src/cmd/ksh93/include/defs.h	2006-08-30 17:31:36.000000000 +0200
@@ -35,6 +35,10 @@
 #include	"fault.h"
 #include	"argnod.h"
 
+#ifndef pointerof
+#define pointerof(x)		((void*)((char*)0+(x)))
+#endif
+
 #define	env_change()		(++ast.env_serial)
 #if SHOPT_ENV
 #   include	<env.h>
@@ -290,6 +294,7 @@
 extern Sfdouble_t	sh_arith(const char*);
 extern void		*sh_arithcomp(char*);
 extern pid_t 		sh_fork(int,int*);
+extern pid_t		_sh_fork(pid_t, int ,int*);
 extern char 		*sh_mactrim(char*,int);
 extern int 		sh_macexpand(struct argnod*,struct argnod**,int);
 extern void 		sh_machere(Sfio_t*, Sfio_t*, char*);
diff -r -N -u ksh93_2006_07_24/src/cmd/ksh93/include/edit.h ksh93_2006_09_12/src/cmd/ksh93/include/edit.h
--- ksh93_2006_07_24/src/cmd/ksh93/include/edit.h	2006-05-10 17:21:33.000000000 +0200
+++ ksh93_2006_09_12/src/cmd/ksh93/include/edit.h	2006-08-30 18:21:52.000000000 +0200
@@ -148,6 +148,8 @@
 	int	e_multiline;	/* allow multiple lines for editing */
 	int	e_winsz;	/* columns in window */ 
 	Edpos_t	e_curpos;	/* cursor line and column */
+	Namval_t *e_term;	/* TERM variable */
+	char 	e_termname[80];	/* terminal name */
 } Edit_t;
 
 #undef MAXWINDOW
diff -r -N -u ksh93_2006_07_24/src/cmd/ksh93/include/lexstates.h ksh93_2006_09_12/src/cmd/ksh93/include/lexstates.h
--- ksh93_2006_07_24/src/cmd/ksh93/include/lexstates.h	2006-04-26 23:36:56.000000000 +0200
+++ ksh93_2006_09_12/src/cmd/ksh93/include/lexstates.h	2006-08-11 20:59:43.000000000 +0200
@@ -57,12 +57,13 @@
 #define S_SPACE	S_BREAK	/* IFS space characters */
 #define S_DELIM	S_RES	/* IFS delimter characters */
 #define S_MBYTE S_NAME	/* IFS first byte of multi-byte char */
+#define S_BLNK	36	/* space or tab */
 /* The following must be the highest numbered states */
-#define S_QUOTE	36	/* double quote character */
-#define S_GRAVE	37	/* old comsub character */
-#define S_ESC	38	/* escape character */
-#define S_DOL	39	/* $ subsitution character */
-#define S_ESC2	40	/* escape character inside '...' */
+#define S_QUOTE	37	/* double quote character */
+#define S_GRAVE	38	/* old comsub character */
+#define S_ESC	39	/* escape character */
+#define S_DOL	40	/* $ subsitution character */
+#define S_ESC2	41	/* escape character inside '...' */
 
 /* These are the lexical state table names */
 #define ST_BEGIN	0
diff -r -N -u ksh93_2006_07_24/src/cmd/ksh93/include/name.h ksh93_2006_09_12/src/cmd/ksh93/include/name.h
--- ksh93_2006_07_24/src/cmd/ksh93/include/name.h	2006-06-21 23:42:17.000000000 +0200
+++ ksh93_2006_09_12/src/cmd/ksh93/include/name.h	2006-08-16 07:57:23.000000000 +0200
@@ -176,7 +176,6 @@
 extern const char	e_restricted[];
 extern const char	e_ident[];
 extern const char	e_varname[];
-extern const char	e_funname[];
 extern const char	e_noalias[];
 extern const char	e_noarray[];
 extern const char	e_aliname[];
diff -r -N -u ksh93_2006_07_24/src/cmd/ksh93/include/nval.h ksh93_2006_09_12/src/cmd/ksh93/include/nval.h
--- ksh93_2006_07_24/src/cmd/ksh93/include/nval.h	2006-06-21 22:36:13.000000000 +0200
+++ ksh93_2006_09_12/src/cmd/ksh93/include/nval.h	2006-09-08 05:18:52.000000000 +0200
@@ -174,6 +174,7 @@
 #define NV_ASSIGN	NV_NOFREE	/* assignment is possible */
 #define NV_NOASSIGN	0		/* backward compatibility */
 #define NV_NOARRAY	0x200000	/* array name not possible */
+#define NV_IARRAY	0x400000	/* for indexed array */
 #define NV_NOREF	NV_REF		/* don't follow reference */
 #define NV_IDENT	0x80		/* name must be identifier */
 #define NV_VARNAME	0x20000		/* name must be ?(.)id*(.id) */
diff -r -N -u ksh93_2006_07_24/src/cmd/ksh93/include/shell.h ksh93_2006_09_12/src/cmd/ksh93/include/shell.h
--- ksh93_2006_07_24/src/cmd/ksh93/include/shell.h	2006-06-21 22:40:55.000000000 +0200
+++ ksh93_2006_09_12/src/cmd/ksh93/include/shell.h	2006-08-02 18:32:21.000000000 +0200
@@ -88,6 +88,7 @@
 #define SH_GLOBSTARS	33
 #define SH_XARGS	34
 #define SH_RC		35
+#define SH_SHOWME	36
 
 /*
  * passed as flags to builtins in Nambltin_t struct when BLT_OPTIM is on
diff -r -N -u ksh93_2006_07_24/src/cmd/ksh93/include/shlex.h ksh93_2006_09_12/src/cmd/ksh93/include/shlex.h
--- ksh93_2006_07_24/src/cmd/ksh93/include/shlex.h	2006-06-21 22:42:18.000000000 +0200
+++ ksh93_2006_09_12/src/cmd/ksh93/include/shlex.h	2006-08-02 16:54:50.000000000 +0200
@@ -117,6 +117,7 @@
 #define	SH_ASSIGN	020
 #define	SH_FUNDEF	040
 #define SH_ARRAY	0100
+#define SH_SEMI		0200	/* semi-colon after NL ok */
 
 #define SH_COMPASSIGN	010	/* allow compound assignments only */
 
diff -r -N -u ksh93_2006_07_24/src/cmd/ksh93/include/shnodes.h ksh93_2006_09_12/src/cmd/ksh93/include/shnodes.h
--- ksh93_2006_07_24/src/cmd/ksh93/include/shnodes.h	2005-11-22 21:13:45.000000000 +0100
+++ ksh93_2006_09_12/src/cmd/ksh93/include/shnodes.h	2006-08-15 16:18:14.000000000 +0200
@@ -37,6 +37,7 @@
 #define FPOU		(040<<COMBITS)		/* output is a pipe */
 #define FPCL		(0100<<COMBITS)		/* close the pipe */
 #define FCOOP		(0200<<COMBITS)		/* cooperating process */
+#define FSHOWME		(0400<<COMBITS)		/* set for showme commands  */
 #define FPOSIX		(02<<COMBITS)		/* posix semantics function */
 #define FLINENO		(04<<COMBITS)		/* for/case has line number */
 
diff -r -N -u ksh93_2006_07_24/src/cmd/ksh93/include/streval.h ksh93_2006_09_12/src/cmd/ksh93/include/streval.h
--- ksh93_2006_07_24/src/cmd/ksh93/include/streval.h	2006-06-19 23:46:05.000000000 +0200
+++ ksh93_2006_09_12/src/cmd/ksh93/include/streval.h	2006-07-25 16:15:35.000000000 +0200
@@ -45,7 +45,7 @@
 #	ifdef LONGLONG_MAX
 #	   define LDBL_LONGLONG_MAX	((Sfdouble_t)LONGLONG_MAX)
 #	else
-#	   define LDBL_LONGLONG_MAX	((Sfdouble_t)((1LL << (8*sizeof(Sflong_t)-1)) -1 ))
+#	   define LDBL_LONGLONG_MAX	((Sfdouble_t)((((Sflong_t)1) << (8*sizeof(Sflong_t)-1)) -1 ))
 #	endif
 #   endif
 #endif
diff -r -N -u ksh93_2006_07_24/src/cmd/ksh93/include/version.h ksh93_2006_09_12/src/cmd/ksh93/include/version.h
--- ksh93_2006_07_24/src/cmd/ksh93/include/version.h	2006-04-13 18:58:06.000000000 +0200
+++ ksh93_2006_09_12/src/cmd/ksh93/include/version.h	2006-08-21 16:45:02.000000000 +0200
@@ -17,4 +17,4 @@
 *                  David Korn <dgk at research.att.com>                   *
 *                                                                      *
 ***********************************************************************/
-#define SH_RELEASE	"1993-12-28 r+"
+#define SH_RELEASE	"1993-12-28 s-"
diff -r -N -u ksh93_2006_07_24/src/cmd/ksh93/Makefile ksh93_2006_09_12/src/cmd/ksh93/Makefile
--- ksh93_2006_07_24/src/cmd/ksh93/Makefile	2006-07-20 23:33:20.000000000 +0200
+++ ksh93_2006_09_12/src/cmd/ksh93/Makefile	2006-08-21 16:15:23.000000000 +0200
@@ -14,12 +14,10 @@
 
 SHOPT_ACCT ==  			/* accounting */
 SHOPT_ACCTFILE ==  		/* per user accounting info */
-SHOPT_APPEND == 1		/* var+=val string append */
 SHOPT_BASH ==			/* bash compatibility code */
 SHOPT_BRACEPAT == 1		/* C-shell {...,...} expansions (, required) */
 SHOPT_CMDLIB_BLTIN == 0		/* all -lcmd commands builtin */
 SHOPT_CMDLIB_DIR ==		/* SHOPT_CMDLIB_BLTIN prefix SH_CMDLIB_DIR */
-SHOPT_COMPOUND_ARRAY == 1	/* allow compound arrays */
 SHOPT_CRNL ==			/* accept <cr><nl> for <nl> */
 SHOPT_DYNAMIC == 1		/* dynamic loading for builtins */
 SHOPT_ECHOPRINT ==		/* make echo equivalent to print */
diff -r -N -u ksh93_2006_07_24/src/cmd/ksh93/Mamfile ksh93_2006_09_12/src/cmd/ksh93/Mamfile
--- ksh93_2006_07_24/src/cmd/ksh93/Mamfile	2006-07-24 18:07:55.000000000 +0200
+++ ksh93_2006_09_12/src/cmd/ksh93/Mamfile	2006-09-13 06:38:27.000000000 +0200
@@ -1,4 +1,4 @@
-info mam static 00000 1994-07-17 make (AT&T Research) 5.1 2006-05-21
+info mam static 00000 1994-07-17 make (AT&T Research) 5.1 2006-08-11
 setv INSTALLROOT ../../..
 setv PACKAGE_ast_INCLUDE ${INSTALLROOT}/include/ast
 setv PACKAGE_ast_LIB ${INSTALLROOT}/lib
@@ -44,6 +44,8 @@
 make include/nval.h implicit
 make ${PACKAGE_ast_INCLUDE}/cdt.h implicit
 make ${PACKAGE_ast_INCLUDE}/ast_common.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_map.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_map.h dontcare
 done ${PACKAGE_ast_INCLUDE}/ast_common.h dontcare
 make ${PACKAGE_ast_INCLUDE}/ast_std.h implicit
 make ${PACKAGE_ast_INCLUDE}/ast_botch.h implicit
@@ -77,8 +79,7 @@
 done ${PACKAGE_ast_INCLUDE}/ast_fcntl.h dontcare
 make ${PACKAGE_ast_INCLUDE}/ast_types.h implicit
 done ${PACKAGE_ast_INCLUDE}/ast_types.h dontcare
-make ${PACKAGE_ast_INCLUDE}/ast_map.h implicit
-done ${PACKAGE_ast_INCLUDE}/ast_map.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/ast_map.h implicit
 make ${PACKAGE_ast_INCLUDE}/stdio.h implicit
 make ${PACKAGE_ast_INCLUDE}/ast_stdio.h implicit
 make ${PACKAGE_ast_INCLUDE}/sfio_s.h implicit
@@ -452,11 +453,16 @@
 prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
 prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
 done ${PACKAGE_ast_INCLUDE}/ccode.h
+make ${PACKAGE_ast_INCLUDE}/tmx.h implicit
+make ${PACKAGE_ast_INCLUDE}/tv.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+done ${PACKAGE_ast_INCLUDE}/tv.h dontcare
 make ${PACKAGE_ast_INCLUDE}/tm.h implicit
 prev ${PACKAGE_ast_INCLUDE}/times.h implicit
 prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
 prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
-done ${PACKAGE_ast_INCLUDE}/tm.h
+done ${PACKAGE_ast_INCLUDE}/tm.h dontcare
+done ${PACKAGE_ast_INCLUDE}/tmx.h
 make include/streval.h implicit
 make ${PACKAGE_ast_INCLUDE}/ast_float.h implicit
 prev ${PACKAGE_ast_INCLUDE}/ast_common.h implicit
@@ -531,13 +537,7 @@
 done trap.o generated
 make test.o
 make bltins/test.c
-make ${PACKAGE_ast_INCLUDE}/tmx.h implicit
-make ${PACKAGE_ast_INCLUDE}/tv.h implicit
-prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
-done ${PACKAGE_ast_INCLUDE}/tv.h dontcare
-prev ${PACKAGE_ast_INCLUDE}/tm.h implicit
-done ${PACKAGE_ast_INCLUDE}/tmx.h dontcare
-prev ${PACKAGE_ast_INCLUDE}/tm.h implicit
+prev ${PACKAGE_ast_INCLUDE}/tmx.h implicit
 prev FEATURE/poll implicit
 make FEATURE/externs implicit
 meta FEATURE/externs features/%>FEATURE/% features/externs externs
@@ -721,6 +721,7 @@
 prev include/io.h implicit
 prev include/shlex.h implicit
 prev FEATURE/poll implicit
+prev include/edit.h implicit
 prev include/terminal.h implicit
 prev include/builtins.h implicit
 prev include/path.h implicit
@@ -728,7 +729,7 @@
 done sh/args.c
 meta args.o %.c>%.o sh/args.c args
 prev sh/args.c
-exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_OPTIMIZE -DSHOPT_RAWONLY -DSHOPT_HISTEXPAND -DSHOPT_PFSH -D_BLD_shell -DKSHELL -D_PACKAGE_ast -DSHOPT_KIA -DSHOPT_MULTIBYTE -DSHOPT_SUID_EXEC -DSHOPT_BRACEPAT -DSHOPT_DYNAMIC -DSHOPT_ESH -c sh/args.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_OPTIMIZE -DSHOPT_RAWONLY -DSHOPT_HISTEXPAND -DSHOPT_PFSH -D_BLD_shell -DKSHELL -D_PACKAGE_ast -DSHOPT_KIA -DSHOPT_MULTIBYTE -DSHOPT_ESH -DSHOPT_VSH -DSHOPT_SUID_EXEC -DSHOPT_BRACEPAT -DSHOPT_DYNAMIC -c sh/args.c
 done args.o generated
 make array.o
 make sh/array.c
@@ -738,7 +739,7 @@
 done sh/array.c
 meta array.o %.c>%.o sh/array.c array
 prev sh/array.c
-exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_APPEND -D_BLD_shell -D_PACKAGE_ast -DSHOPT_HISTEXPAND -DSHOPT_DYNAMIC -DSHOPT_ESH -DSHOPT_MULTIBYTE -DSHOPT_PFSH -c sh/array.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -D_BLD_shell -D_PACKAGE_ast -DSHOPT_HISTEXPAND -DSHOPT_DYNAMIC -DSHOPT_ESH -DSHOPT_MULTIBYTE -DSHOPT_PFSH -c sh/array.c
 done array.o generated
 make completion.o
 make edit/completion.c
@@ -779,6 +780,18 @@
 prev include/variables.h implicit
 prev include/defs.h implicit
 prev ${PACKAGE_ast_INCLUDE}/ls.h implicit
+make FEATURE/cmds implicit
+meta FEATURE/cmds features/%>FEATURE/% features/cmds cmds
+make features/cmds
+done features/cmds
+prev shell.req
+prev +ljobs
+prev +li
+prev ${mam_libsecdb}
+prev +lintl
+prev ${mam_libdl}
+exec - iffe -v -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS}   ${LDFLAGS} '  ref ${mam_cc_L+-L.} ${mam_cc_L+-L${INSTALLROOT}/lib} -I${PACKAGE_ast_INCLUDE} -I${INSTALLROOT}/include ${mam_libdll} ${mam_libcmd} ${mam_libast} ${mam_libm} ${mam_libast} : run features/cmds
+done FEATURE/cmds generated
 prev FEATURE/time implicit
 prev FEATURE/options implicit
 prev ${PACKAGE_ast_INCLUDE}/ccode.h implicit
@@ -968,7 +981,7 @@
 done sh/macro.c
 meta macro.o %.c>%.o sh/macro.c macro
 prev sh/macro.c
-exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_BRACEPAT -DKSHELL -DSHOPT_COMPOUND_ARRAY -DSHOPT_FILESCAN -DSHOPT_MULTIBYTE -D_PACKAGE_ast -DSHOPT_SUID_EXEC -D_BLD_shell -DSHOPT_PFSH -DSHOPT_KIA -DSHOPT_HISTEXPAND -DSHOPT_DYNAMIC -DSHOPT_ESH -c sh/macro.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_BRACEPAT -DKSHELL -DSHOPT_FILESCAN -DSHOPT_MULTIBYTE -D_PACKAGE_ast -DSHOPT_SUID_EXEC -D_BLD_shell -DSHOPT_PFSH -DSHOPT_KIA -DSHOPT_HISTEXPAND -DSHOPT_DYNAMIC -DSHOPT_ESH -c sh/macro.c
 done macro.o generated
 make name.o
 make sh/name.c
@@ -985,7 +998,7 @@
 done sh/name.c
 meta name.o %.c>%.o sh/name.c name
 prev sh/name.c
-exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_OPTIMIZE -DSHOPT_MULTIBYTE -DSHOPT_COMPOUND_ARRAY -D_BLD_shell -D_PACKAGE_ast -DSHOPT_PFSH -DSHOPT_KIA -DSHOPT_SUID_EXEC -DSHOPT_BRACEPAT -DSHOPT_HISTEXPAND -DSHOPT_DYNAMIC -DSHOPT_ESH -c sh/name.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_OPTIMIZE -DSHOPT_MULTIBYTE -D_BLD_shell -D_PACKAGE_ast -DSHOPT_PFSH -DSHOPT_KIA -DSHOPT_SUID_EXEC -DSHOPT_BRACEPAT -DSHOPT_HISTEXPAND -DSHOPT_DYNAMIC -DSHOPT_ESH -c sh/name.c
 done name.o generated
 make nvtree.o
 make sh/nvtree.c
@@ -995,7 +1008,7 @@
 done sh/nvtree.c
 meta nvtree.o %.c>%.o sh/nvtree.c nvtree
 prev sh/nvtree.c
-exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_COMPOUND_ARRAY -D_PACKAGE_ast -D_BLD_shell -DSHOPT_HISTEXPAND -DSHOPT_DYNAMIC -DSHOPT_ESH -DSHOPT_MULTIBYTE -DSHOPT_PFSH -c sh/nvtree.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -D_PACKAGE_ast -D_BLD_shell -DSHOPT_HISTEXPAND -DSHOPT_DYNAMIC -DSHOPT_ESH -DSHOPT_MULTIBYTE -DSHOPT_PFSH -c sh/nvtree.c
 done nvtree.o generated
 make parse.o
 make sh/parse.c
@@ -1011,7 +1024,7 @@
 done sh/parse.c
 meta parse.o %.c>%.o sh/parse.c parse
 prev sh/parse.c
-exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_NAMESPACE -DSHOPT_COMPOUND_ARRAY -DSHOPT_SUID_EXEC -DSHOPT_BRACEPAT -D_BLD_shell -D_PACKAGE_ast -DSHOPT_MULTIBYTE -DSHOPT_PFSH -DSHOPT_KIA -DSHOPT_ESH -DSHOPT_DYNAMIC -DSHOPT_HISTEXPAND -DKSHELL -c sh/parse.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_NAMESPACE -DSHOPT_SUID_EXEC -DSHOPT_BRACEPAT -D_BLD_shell -D_PACKAGE_ast -DSHOPT_MULTIBYTE -DSHOPT_PFSH -DSHOPT_KIA -DSHOPT_ESH -DSHOPT_DYNAMIC -DSHOPT_HISTEXPAND -DKSHELL -c sh/parse.c
 done parse.o generated
 make path.o
 make sh/path.c
@@ -1265,18 +1278,7 @@
 make ${PACKAGE_ast_INCLUDE}/cmdlist.h implicit
 prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
 done ${PACKAGE_ast_INCLUDE}/cmdlist.h dontcare
-make FEATURE/cmds implicit
-meta FEATURE/cmds features/%>FEATURE/% features/cmds cmds
-make features/cmds
-done features/cmds
-prev shell.req
-prev +ljobs
-prev +li
-prev ${mam_libsecdb}
-prev +lintl
-prev ${mam_libdl}
-exec - iffe -v -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS}   ${LDFLAGS} '  ref ${mam_cc_L+-L.} ${mam_cc_L+-L${INSTALLROOT}/lib} -I${PACKAGE_ast_INCLUDE} -I${INSTALLROOT}/include ${mam_libdll} ${mam_libcmd} ${mam_libast} ${mam_libm} ${mam_libast} : run features/cmds
-done FEATURE/cmds dontcare generated
+prev FEATURE/cmds implicit
 prev include/jobs.h implicit
 prev include/builtins.h implicit
 prev include/version.h implicit
@@ -1389,6 +1391,7 @@
 make suid_exec
 make suid_exec.o
 make sh/suid_exec.c
+prev include/version.h implicit
 prev ${PACKAGE_ast_INCLUDE}/error.h implicit
 prev ${PACKAGE_ast_INCLUDE}/sig.h implicit
 prev ${PACKAGE_ast_INCLUDE}/ls.h implicit
@@ -1399,7 +1402,7 @@
 prev sh/suid_exec.c
 setv CC.DLL -UCC.DLL
 setv _BLD_shell -U_BLD_shell
-exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -D_PACKAGE_ast -c sh/suid_exec.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -D_PACKAGE_ast -c sh/suid_exec.c
 done suid_exec.o generated
 prev +ljobs
 prev +li
diff -r -N -u ksh93_2006_07_24/src/cmd/ksh93/RELEASE ksh93_2006_09_12/src/cmd/ksh93/RELEASE
--- ksh93_2006_07_24/src/cmd/ksh93/RELEASE	2006-07-21 18:18:02.000000000 +0200
+++ ksh93_2006_09_12/src/cmd/ksh93/RELEASE	2006-09-08 18:28:57.000000000 +0200
@@ -1,4 +1,20 @@
-06-07-21  --- Release ksh93r+  ---
+06-09-08  --- Release ksh93s-  ---
+06-09-97  The -a option was added to typeset for indexed arrays.  This
+	  is only needed when using the ([subscript]=value ...) form.
+06-08-16  As a new feature, a leading ~(N) on a pattern has no effect 
+	  except when used for file expansion.  In this case if not
+	  matches are found, the pattern is replaced by nothing rathern
+	  than itself.
+06-08-11  A bug in the expansion of ${.sh.match[i]:${#.shmatch[i]}} has
+	  been fixed.
+06-08-10  The read builtin options -n and -N have been modified to treat
+          the size as characters rather than bytes unless storing into a
+	  binary (typeset -B) variable.
+06-07-27  When the here document operator << is followed directly by a #
+	  rather than a -, the first line of the here-document determines
+	  how much whitespace is removed for each line.
+06-07-26  A bug in the C-shell history (enabled with set -H) in which the
+	  history event !$ was not processed has been fixed.
 06-07-21  A bug on some systems in which assigning PATH on a command line
 	  would not take effect has been fixed.
 06-07-20  Add ksh93 and rksh93 as allowable names for ksh binaries.
diff -r -N -u ksh93_2006_07_24/src/cmd/ksh93/sh/args.c ksh93_2006_09_12/src/cmd/ksh93/sh/args.c
--- ksh93_2006_07_24/src/cmd/ksh93/sh/args.c	2006-06-08 00:18:11.000000000 +0200
+++ ksh93_2006_09_12/src/cmd/ksh93/sh/args.c	2006-08-30 15:45:56.000000000 +0200
@@ -31,6 +31,7 @@
 #include	"path.h"
 #include	"builtins.h"
 #include	"terminal.h"
+#include	"edit.h"
 #include	"FEATURE/poll"
 #if SHOPT_KIA
 #   include	"shlex.h"
diff -r -N -u ksh93_2006_07_24/src/cmd/ksh93/sh/array.c ksh93_2006_09_12/src/cmd/ksh93/sh/array.c
--- ksh93_2006_07_24/src/cmd/ksh93/sh/array.c	2004-11-18 00:19:47.000000000 +0100
+++ ksh93_2006_09_12/src/cmd/ksh93/sh/array.c	2006-09-08 00:53:12.000000000 +0200
@@ -33,15 +33,30 @@
 
 #define NUMSIZE	(4+(ARRAY_MAX>999)+(ARRAY_MAX>9999)+(ARRAY_MAX>99999))
 #define is_associative(ap)	array_assoc((Namarr_t*)(ap))
+#define array_setbit(cp, n)	(cp[(n)/CHAR_BIT] |= 2<<(((n)&(CHAR_BIT-1))))
+#define array_clrbit(cp, n)	(cp[(n)/CHAR_BIT] &= ~(2<<(((n)&(CHAR_BIT-1)))))
+#define array_isbit(cp, n)	(cp[(n)/CHAR_BIT] & 2<<(((n)&(CHAR_BIT-1))))
+#define NV_CHILD		NV_EXPORT
+
+static char Empty[] = "";
 
 struct index_array
 {
         Namarr_t        header;
         int		cur;    /* index of current element */
         int		maxi;   /* maximum index for array */
+	unsigned char	*bits;	/* bit array for child subscripts */
         union Value	val[1]; /* array of value holders */
 };
 
+struct assoc_array
+{
+	Namarr_t	header;
+	Dt_t		*table;
+	Namval_t	*pos;
+	Namval_t	*nextpos;
+	Namval_t	*cur;
+};
 
 /*
  * replace discipline with new one
@@ -83,76 +98,82 @@
 	return(i+1);
 }
 
+static union Value *array_getup(Namval_t *np, Namarr_t *arp)
+{
+	register struct index_array *ap = (struct index_array*)arp;
+	register union Value *up;
+	if(!nv_isarray(np))
+		return(&np->nvalue);
+	if(is_associative(ap))
+		up = (union Value*)((*arp->fun)(np,NIL(char*),0));
+	else
+	{
+		if(ap->cur >= ap->maxi)
+			errormsg(SH_DICT,ERROR_exit(1),e_subscript,nv_name(np));
+		up = &(ap->val[ap->cur]);
+	}
+	return(up);
+}
+
 /*
  * Get the Value pointer for an array.
  * Delete space as necessary if flag is ARRAY_DELETE
  * After the lookup is done the last @ or * subscript is incremented
  */
-static union Value *array_find(Namval_t *np,Namarr_t *arp, int flag)
+static Namval_t *array_find(Namval_t *np,Namarr_t *arp, int flag)
 {
 	register struct index_array *ap = (struct index_array*)arp;
-	register union Value *up;
-	register unsigned dot=0;
+	register union Value	*up;
+	Namval_t		*mp;
 	if(is_associative(ap))
-		up = (union Value*)((*ap->header.fun)(np,NIL(char*),0));
-	else
 	{
-		if((dot=ap->cur) >= ap->maxi)
-			errormsg(SH_DICT,ERROR_exit(1),e_subscript, nv_name(np));
-		up = &(ap->val[dot]);
+		mp = (Namval_t*)((*arp->fun)(np,NIL(char*),NV_ACURRENT));
+		if(!mp)
+			up = (union Value*)&mp;
+		else if(nv_isattr(mp,NV_CHILD))
+			return(mp->nvalue.np);
+		else
+			up =  &mp->nvalue;
 	}
-	if(flag==ARRAY_DELETE)
+	else
 	{
-		if(up->cp)
-		{
-			ap->header.nelem--;
-			if(is_associative(ap))
-			{
-				(*ap->header.fun)(np, NIL(char*), NV_ADELETE);
-				if(!(ap->header.nelem&ARRAY_SCAN))
-					return(up);
-			}
-		}
-		if(array_elem(&ap->header)==0 && ((ap->header.nelem&ARRAY_SCAN) || !is_associative(ap)))
-		{
-			const char *cp = up->cp;
-			if(cp && is_associative(ap))
-				(*ap->header.fun)(np, NIL(char*), NV_AFREE);
-			nv_offattr(np,NV_ARRAY);
-			if(nv_isattr(np,NV_TABLE))
-			{
-				np->nvfun = up->funp;
-				up->cp = 0;
-				up = (union Value*)&np->nvfun;
-			}
-			else
-			{
-				np->nvalue.cp = cp;
-				up->cp = 0;
-				up = &np->nvalue;
-			}
-		}
+		if(ap->cur >= ap->maxi)
+			errormsg(SH_DICT,ERROR_exit(1),e_subscript,nv_name(np));
+		up = &(ap->val[ap->cur]);
+		if(up->np && array_isbit(ap->bits,ap->cur))
+			return(up->np);
 	}
-	else if(!up->cp)
+	np->nvalue.cp = up->cp;
+	if(!up->cp)
 	{
-		if(flag==ARRAY_LOOKUP)
+		if(flag!=ARRAY_ASSIGN)
 			return(0);
 		ap->header.nelem++;
 	}
-	return(up);
+	return(np);
 }
 
 static Namfun_t *array_clone(Namval_t *np, Namval_t *mp, int flags, Namfun_t *fp)
 {
-	Namarr_t *ap = (Namarr_t*)fp;
-	char *name, *sub=0;
-	int nelem = ap->nelem;
+	Namarr_t		*ap = (Namarr_t*)fp;
+	Namval_t		*nq, *mq;
+	char			*name, *sub=0;
+	int			nelem = ap->nelem,offset=staktell();
+	struct index_array	*aq, *ar;
+	if(nelem&ARRAY_NOCLONE)
+		return(0);
 	if(array_assoc(ap))
 		nv_setarray(mp,ap->fun);
 	else
+	{
 		nv_putsub(mp,NIL(char*),ap->nelem);
+		if(aq=(struct index_array*)nv_arrayptr(mp))
+			aq->bits =  (unsigned char*)&aq->val[aq->maxi];
+	}
 	if(!(nelem&(ARRAY_SCAN|ARRAY_UNDEF)) && (sub=nv_getsub(np)))
 		sub = strdup(sub);
+	ar = (struct index_array*)ap;
+	nv_onattr(mp,nv_isattr(np,NV_INTEGER|NV_UTOL|NV_LTOU|NV_LJUST|NV_RJUST|NV_ZFILL|NV_BINARY));
 	nv_putsub(np,NIL(char*),ARRAY_SCAN);
 	do
 	{
@@ -161,7 +182,30 @@
 		else
 			name = nv_getsub(np);
 		nv_putsub(mp,name,ARRAY_ADD);
-		if(nv_isattr(np,NV_INTEGER))
+		if((!array_assoc(ap) &&  array_isbit(ar->bits,ar->cur) && (nq=np)) ||
+			(array_assoc(ap) && (nq = (Namval_t*)((*ap->fun)(np,NIL(char*),NV_ACURRENT))) && nv_isattr(nq, NV_CHILD)))
+		{
+			sfprintf(stkstd,"%s[%s]",nv_name(mp),name);
+			stakputc(0);
+			mq = nv_search(stakptr(offset), sh.var_tree, NV_ADD);
+			stakseek(offset);
+			if(mq)
+			{
+				nv_clone(nq->nvalue.np,mq,0);
+				if(array_assoc(ap))
+				{
+					nq = (Namval_t*)((*ap->fun)(mp,NIL(char*),NV_ACURRENT));
+					nq->nvalue.np = mp;
+					nv_onattr(nq,NV_CHILD);
+				}
+				else
+				{
+					array_setbit(aq->bits,aq->cur);
+					aq->val[aq->cur].np = mq;
+				}
+			}
+		}
+		else if(nv_isattr(np,NV_INTEGER))
 		{
 			Sfdouble_t d= nv_getnum(np);
 			nv_putval(mp,(char*)&d,NV_LONG|NV_DOUBLE|NV_INTEGER);
@@ -185,59 +229,75 @@
 static char *array_getval(Namval_t *np, Namfun_t *disc)
 {
 	register Namarr_t *ap = (Namarr_t*)disc;
-	register union Value *up;
+	register Namval_t *mp;
 	ap = array_check(np,ap,ARRAY_LOOKUP);
-	if(!(up = array_find(np,ap,ARRAY_LOOKUP)))
-		 return (NIL(char*));
-	if(nv_isattr(np,NV_TABLE))
-		np->nvfun = up->funp;
-	else
-		np->nvalue.cp = up->cp;
+	if((mp=array_find(np,ap,ARRAY_LOOKUP))!=np)
+		return(mp?nv_getval(mp):0);
 	return(nv_getv(np,&ap->hdr));
 }
 
 static Sfdouble_t array_getnum(Namval_t *np, Namfun_t *disc)
 {
 	register Namarr_t *ap = (Namarr_t*)disc;
-	register union Value *up;
+	register Namval_t *mp;
 	ap = array_check(np,ap,ARRAY_LOOKUP);
-	if(!(up = array_find(np,ap,ARRAY_LOOKUP)))
-		 return(0);
-	if(nv_isattr(np,NV_TABLE))
-		np->nvfun = up->funp;
-	else
-		np->nvalue.cp = up->cp;
+	if((mp=array_find(np,ap,ARRAY_LOOKUP))!=np)
+		return(mp?nv_getnum(mp):0);
 	return(nv_getn(np,&ap->hdr));
 }
 
 static void array_putval(Namval_t *np, const char *string, int flags, Namfun_t *dp)
 {
-	register Namarr_t *ap = (Namarr_t*)dp;
-	register union Value *up;
+	register Namarr_t	*ap = (Namarr_t*)dp;
+	register union Value	*up;
+	register Namval_t	*mp;
+	register struct index_array *aq = (struct index_array*)ap;
 	ap = array_check(np,ap,string?ARRAY_ASSIGN:ARRAY_DELETE);
 	do
 	{
-		if(!(up = array_find(np,ap,string?ARRAY_ASSIGN:ARRAY_DELETE)))
-			continue;
-		if(nv_isattr(np,NV_TABLE))
-			np->nvfun = up->funp;
-		else
-			np->nvalue.cp = up->cp;
+		mp = array_find(np,ap,string?ARRAY_ASSIGN:ARRAY_DELETE);
+		if(mp && mp!=np)
+			nv_putval(mp, string, flags);
+		if(!string)
+		{
+			if(mp)
+			{
+				if(mp!=np)
+				{
+					dtdelete(sh.var_tree,(void*)mp);
+					free((void*)mp);
+				}
+				if(is_associative(ap))
+					(*ap->fun)(np,NIL(char*),NV_ADELETE);
+				else if(mp!=np)
+				{
+					array_clrbit(aq->bits,aq->cur);
+					aq->val[aq->cur].cp = 0;
+				}
+				ap->nelem--;
+			}
+			if(array_elem(ap)==0 && ((ap->nelem&ARRAY_SCAN) || !is_associative(ap)))
+			{
+				if(is_associative(ap))
+					(*ap->fun)(np, NIL(char*), NV_AFREE);
+				nv_offattr(np,NV_ARRAY);
+			}
+			if(!mp || mp!=np)
+				continue;
+		}
+		/* prevent empty string from being deleted */
+		if(np->nvalue.cp == Empty)
+			np->nvalue.cp = 0;
 		nv_putv(np,string,flags,&ap->hdr);
-		if(nv_isattr(np,NV_TABLE))
-			up->funp = np->nvfun;
-		else
-			up->cp = np->nvalue.cp;
+		up = array_getup(np,ap);
+		up->cp = np->nvalue.cp;
 	}
 	while(!string && nv_nextsub(np));
 	if(!string && !nv_isattr(np,NV_ARRAY))
 	{
 		Namfun_t *nfp;
-		nv_stack(np,(Namfun_t*)ap);
-		nfp = nv_stack(np,0);
-		if(nfp == (Namfun_t*)ap)
-			free((void*)ap);
-		else errormsg(SH_DICT,ERROR_warn(0),"%s: variable discipline not top level",nv_name(np));
+		if(nfp = nv_disc(np,(Namfun_t*)ap,NV_POP))
+			free((void*)nfp);
 	}
 }
 
@@ -266,28 +326,47 @@
 	register int newsize = arsize(maxi+1);
 	if (maxi >= ARRAY_MAX)
 		errormsg(SH_DICT,ERROR_exit(1),e_subscript, fmtbase((long)maxi,10,0));
-	ap = new_of(struct index_array,(newsize-1)*sizeof(union Value*));
+	ap = new_of(struct index_array,(newsize-1)*sizeof(union Value*)+newsize/CHAR_BIT);
 	memset((void*)ap,0,sizeof(*ap));
 	ap->maxi = newsize;
 	ap->cur = maxi;
+	ap->bits =  (unsigned char*)&ap->val[newsize];
+	memset(ap->bits, 0, newsize/CHAR_BIT);
 	if(arp)
 	{
 		ap->header = arp->header;
 		for(;i < arp->maxi;i++)
 			ap->val[i].cp = arp->val[i].cp;
+		memcpy(ap->bits, arp->bits, (arp->maxi/CHAR_BIT));
 		array_setptr(np,arp,ap);
 		free((void*)arp);
 	}
 	else
 	{
 		ap->header.fun = 0;
-		if(nv_isattr(np,NV_TABLE))
+		if((ap->val[0].cp=np->nvalue.cp))
+			i++;
+		else if(np->nvfun)
 		{
-			ap->val[0].funp = np->nvfun;
+			Namval_t *mp;
+			int offset = staktell();
+			sfprintf(stkstd,"%s[0]",nv_name(np));
+			stakputc(0);
+			mp = nv_search(stakptr(offset), sh.var_tree, NV_ADD);
+			stakseek(offset);
+			if(mp && nv_isnull(mp))
+			{
+				nv_clone(np,mp,0);
+				ap->val[0].np = mp;
+				array_setbit(ap->bits,0);
+			}
 			i++;
 		}
-		else if((ap->val[0].cp=np->nvalue.cp))
+		else if(nv_isattr(np,NV_INTEGER))
+		{
+			Sfdouble_t d= nv_getnum(np);
 			i++;
+		}
 		ap->header.nelem = i;
 		ap->header.hdr.nofree = 1;
 		ap->header.hdr.disc = &array_disc;
@@ -376,7 +455,8 @@
 				*--string_index = '0' + (n-10*digit);
 			}
 			nv_putsub(np, string_index, ARRAY_ADD);
-			up=array_find(np,ap,0);
+			up = (union Value*)((*ap->fun)(np,NIL(char*),0));
+			ap->nelem++;
 			up->cp = save_ap->val[dot].cp;
 			save_ap->val[dot].cp = 0;
 		}
@@ -394,17 +474,18 @@
 {
 	register Namarr_t *ap;
 	char *value;
-	if(fun && (ap = nv_arrayptr(np)) && !is_associative(ap))
+	if(fun && (ap = nv_arrayptr(np)))
 	{
 		/*
 		 * if it's already an indexed array, convert to 
 		 * associative structure
 		 */
-		ap = nv_changearray(np, fun);
+		if(!is_associative(ap))
+			ap = nv_changearray(np, fun);
 		return(ap);
 	}
 	value = nv_getval(np);
-	if(fun && !nv_arrayptr(np) && (ap = (Namarr_t*)((*fun)(np, NIL(char*), NV_AINIT))))
+	if(fun && !ap && (ap = (Namarr_t*)((*fun)(np, NIL(char*), NV_AINIT))))
 	{
 		/* check for preexisting initialization and save */
 		ap->nelem = 0;
@@ -421,6 +502,37 @@
 }
 
 /*
+ * move parent subscript into child
+ */
+Namval_t *nv_arraychild(Namval_t *np, Namval_t *nq, int c)
+{
+	register Namarr_t *ap = nv_arrayptr(np);
+	union Value *up;
+	if(!(up = array_getup(np,ap)))
+		return((Namval_t*)0);
+	if(!nq)
+		return(array_find(np,ap, ARRAY_LOOKUP));
+	np->nvalue.cp = up->cp;
+	ap->nelem |= ARRAY_NOCLONE;
+	nv_clone(np, nq, NV_NODISC);
+	if(ap->fun)
+	{
+		up->np = (Namval_t*)((*ap->fun)(np,NIL(char*),NV_ACURRENT));
+		nv_onattr(up->np, NV_CHILD);
+		(up->np)->nvalue.np = nq;
+	}
+	else
+	{
+		struct index_array *aq = (struct index_array*)ap;
+		array_setbit(aq->bits,aq->cur);
+		up->np = nq;
+	}
+	if(c=='.')
+		nv_setvtree(nq);
+	return(nq);
+}
+
+/*
  * This routine sets subscript of <np> to the next element, if any.
  * The return value is zero, if there are no more elements
  * Otherwise, 1 is returned.
@@ -433,8 +545,13 @@
 		return(0);
 	if(is_associative(ap))
 	{
-		if((*ap->header.fun)(np,NIL(char*),NV_ANEXT))
+		struct assoc_array *aq;
+		if(aq=(*ap->header.fun)(np,NIL(char*),NV_ANEXT))
+		{
+			if(nv_isattr(aq->cur,NV_CHILD))
+				nv_putsub(aq->cur->nvalue.np,NIL(char*),ARRAY_UNDEF);
 			return(1);
+		}
 		ap->header.nelem &= ~ ARRAY_SCAN;
 		return(0);
 	}
@@ -443,6 +560,8 @@
 		if(ap->val[dot].cp)
 		{
 			ap->cur = dot;
+			if(array_isbit(ap->bits, dot))
+				nv_putsub(ap->val[dot].np,NIL(char*),ARRAY_UNDEF);
 			return(1);
 		}
 	}
@@ -458,6 +577,9 @@
  *    ARRAY_SCAN, ARRAY_UNDEF, ARRAY_ADD
  * The node pointer is returned which can be NULL if <np> is
  *    not already array and the ARRAY_ADD bit of <mode> is not set.
+ * ARRAY_FILL sets the specified subscript to the empty string when
+ *   ARRAY_ADD is specified and there is no value or sets all
+ * the elements up to the number specified if ARRAY_ADD is not specified
  */
 Namval_t *nv_putsub(Namval_t *np,register char *sp,register long mode)
 {
@@ -474,33 +596,64 @@
 		}
 		if(!ap || size>=ap->maxi)
 		{
-			if(size==0)
+			if(size==0 && !(mode&ARRAY_FILL))
 				return(NIL(Namval_t*));
 			if(sh.subshell)
 				np = sh_assignok(np,1);
 			ap = array_grow(np, ap,size);
 			nv_onattr(np,NV_ARRAY);
 		}
-		ap->header.nelem &= ~(ARRAY_SCAN|ARRAY_UNDEF);
+		ap->header.nelem &= ~ARRAY_UNDEF;
 		ap->header.nelem |= (mode&(ARRAY_SCAN|ARRAY_UNDEF));
 		ap->cur = size;
 		if((mode&ARRAY_SCAN) && !ap->val[size].cp && !nv_nextsub(np))
 			np = 0;
 		if(mode&ARRAY_FILL)
 		{
-			int n;
-			for(n=0; n < size; n++)
-				ap->val[n].cp = "";
-			ap->header.nelem = n|(ap->header.nelem&(ARRAY_SCAN|ARRAY_UNDEF));
-			if(n=ap->maxi-ap->maxi)
-				memset(&ap->val[size],0,n*sizeof(union Value));
+			if(!(mode&ARRAY_ADD))
+			{
+				int n;
+				for(n=0; n < size; n++)
+				{
+					if(!ap->val[n].cp)
+						ap->val[n].cp = Empty;
+				}
+				ap->header.nelem = n|(ap->header.nelem&(ARRAY_SCAN|ARRAY_UNDEF));
+				if(n=ap->maxi-ap->maxi)
+					memset(&ap->val[size],0,n*sizeof(union Value));
+			}
+			else if(!ap->val[size].cp)
+			{
+				if(sh.subshell)
+					np = sh_assignok(np,1);
+				ap->val[size].cp = Empty;
+				ap->header.nelem++;
+			}
+		}
+		else if(!(mode&ARRAY_SCAN))
+		{
+			ap->header.nelem &= ~ARRAY_SCAN;
+			if(array_isbit(ap->bits,size))
+				nv_putsub(ap->val[size].np,NIL(char*),ARRAY_UNDEF);
 		}
 		return((Namval_t*)np);
 	}
-	ap->header.nelem &= ~(ARRAY_SCAN|ARRAY_UNDEF);
+	ap->header.nelem &= ~ARRAY_UNDEF;
+	if(!(mode&ARRAY_FILL))
+		ap->header.nelem &= ~ARRAY_SCAN;
 	ap->header.nelem |= (mode&(ARRAY_SCAN|ARRAY_UNDEF));
 	if(sp)
-		ap = (struct index_array*)(*ap->header.fun)(np, sp, (mode&ARRAY_ADD)?NV_AADD:0);
+	{
+		union Value *up;
+		up = (union Value*)(*ap->header.fun)(np, sp, (mode&ARRAY_ADD)?NV_AADD:0);
+		if(up && !up->cp && (mode&ARRAY_ADD) && (mode&ARRAY_FILL))
+		{
+			if(sh.subshell)
+				np = sh_assignok(np,1);
+			up->cp = Empty;
+			ap->header.nelem++;
+		}
+	}
 	else if(mode&ARRAY_SCAN)
 		(*ap->header.fun)(np,(char*)np,0);
 	else if(mode&ARRAY_UNDEF)
@@ -521,7 +674,7 @@
 	/* first find matching ']' */
 	while(count>0 && (c= *++cp))
 	{
-		if(c=='\\' && (!(mode&NV_SUBQUOTE) || (c=cp[1])=='[' || c==']' || c=='\\'))
+		if(c=='\\' && (!(mode&NV_SUBQUOTE) || (c=cp[1])=='[' || c==']' || c=='\\' || c=='*' || c=='@'))
 		{
 			quoted=1;
 			cp++;
@@ -540,12 +693,10 @@
 		sh_trim(sp=stakptr(count));
 	}
 	if(mode && np)
-		nv_putsub(np, sp, ARRAY_ADD);
+		nv_putsub(np, sp, ARRAY_ADD|(cp[1]?ARRAY_FILL:mode&ARRAY_FILL));
 	if(quoted)
 		stakseek(count);
-	*cp = c;
-	if(*++cp == '[' && np)
-		errormsg(SH_DICT,ERROR_exit(1),e_subscript, nv_name(np));
+	*cp++ = c;
 	return(cp);
 }
 
@@ -591,15 +742,6 @@
 	return(((struct index_array*)(ap))->cur&ARRAY_MASK);
 }
 
-struct assoc_array
-{
-	Namarr_t	header;
-	Dt_t		*table;
-	Namval_t	*pos;
-	Namval_t	*nextpos;
-	Namval_t	*cur;
-};
-
 
 /*
  *  This is the default implementation for associate arrays
@@ -667,8 +809,9 @@
 				ap->cur = 0;
 				return(0);
 			}
-			ap->pos = 0;
-			type = nv_isattr(np,NV_PUBLIC&~NV_ARRAY);
+			else if(!(ap->header.nelem&ARRAY_SCAN))
+				ap->pos = 0;
+			type = nv_isattr(np,NV_PUBLIC&~(NV_ARRAY|NV_CHILD));
 			if((np=nv_search(sp,ap->table,mode?NV_ADD:0)) && nv_isnull(np))
 				nv_onattr(np,type);
 			ap->cur = np;
@@ -693,7 +836,6 @@
 		if(is_associative(ap))
 			errormsg(SH_DICT,ERROR_exit(1),"cannot append index array to associate array %s",nv_name(np));
 	}
-#if SHOPT_APPEND
 	if(append)
 	{
 		if(ap)
@@ -705,7 +847,6 @@
 		else if(!nv_isnull(np))
 			arg0=1;
 	}
-#endif /* SHOPT_APPEND */
 	while(--argc >= 0)
 	{
 		if((argc+arg0)>0  || nv_isattr(np,NV_ARRAY))
diff -r -N -u ksh93_2006_07_24/src/cmd/ksh93/sh/expand.c ksh93_2006_09_12/src/cmd/ksh93/sh/expand.c
--- ksh93_2006_07_24/src/cmd/ksh93/sh/expand.c	2006-06-27 20:37:38.000000000 +0200
+++ ksh93_2006_09_12/src/cmd/ksh93/sh/expand.c	2006-08-16 17:24:33.000000000 +0200
@@ -187,6 +187,8 @@
 		gp->gl_suffix = sufstr;
 	gp->gl_intr = &sh.trapnote; 
 	suflen = 0;
+	if(memcmp(pattern,"~(N",3)==0)
+		flags &= ~GLOB_NOCHECK;
 	glob(pattern, flags, 0, gp);
 #if SHOPT_BASH
 	if(off)
@@ -382,15 +384,19 @@
 			for(; ap; ap=apin)
 			{
 				apin = ap->argchn.ap;
-				if(!sh_isoption(SH_NOGLOB) && (brace = path_expand(ap->argval,arghead)))
-					count += brace;
+				if(!sh_isoption(SH_NOGLOB))
+					brace = (brace=path_expand(ap->argval,arghead));
 				else
 				{
 					ap->argchn.ap = *arghead;
 					*arghead = ap;
-					count++;
+					brace=1;
+				}
+				if(brace)
+				{
+					count += brace;
+					(*arghead)->argflag |= ARG_MAKE;
 				}
-				(*arghead)->argflag |= ARG_MAKE;
 			}
 			return(count);
 	}
diff -r -N -u ksh93_2006_07_24/src/cmd/ksh93/sh/fault.c ksh93_2006_09_12/src/cmd/ksh93/sh/fault.c
--- ksh93_2006_07_24/src/cmd/ksh93/sh/fault.c	2006-06-28 04:07:54.000000000 +0200
+++ ksh93_2006_09_12/src/cmd/ksh93/sh/fault.c	2006-08-05 05:31:04.000000000 +0200
@@ -71,11 +71,12 @@
 	if(sig==SIGWINCH)
 	{
 		int rows=0, cols=0;
+		long v;
 		astwinsize(2,&rows,&cols);
-		if(cols)
-			nv_putval(COLUMNS, (char*)&cols, NV_INTEGER);
-		if(rows)
-			nv_putval(LINES, (char*)&rows, NV_INTEGER);
+		if(v = cols)
+			nv_putval(COLUMNS, (char*)&v, NV_INTEGER);
+		if(v = rows)
+			nv_putval(LINES, (char*)&v, NV_INTEGER);
 	}
 #endif  /* SIGWINCH */
 	if(sh.savesig)
diff -r -N -u ksh93_2006_07_24/src/cmd/ksh93/sh/init.c ksh93_2006_09_12/src/cmd/ksh93/sh/init.c
--- ksh93_2006_07_24/src/cmd/ksh93/sh/init.c	2006-07-21 18:13:42.000000000 +0200
+++ ksh93_2006_09_12/src/cmd/ksh93/sh/init.c	2006-08-11 18:21:34.000000000 +0200
@@ -131,6 +131,7 @@
 	char		*rval;
 	int		vsize;
 	int		nmatch;
+	int		lastsub;
 	int		match[2*(MATCH_MAX+1)];
 };
 
@@ -672,6 +673,7 @@
 		memcpy(mp->val,v,vsize);
 		mp->val[vsize] = 0;
 		nv_putsub(SH_MATCHNOD, NIL(char*), nmatch|ARRAY_FILL);
+		mp->lastsub = -1;
 	}
 } 
 
@@ -682,14 +684,16 @@
 	struct match *mp = (struct match*)fp;
 	int sub,n;
 	char *val;
+	sub = nv_aindex(np);
+	if(sub>=mp->nmatch)
+		return(0);
+	if(sub==mp->lastsub)
+		return(mp->rval);
 	if(mp->rval)
 	{
 		free((void*)mp->rval);
 		mp->rval = 0;
 	}
-	sub = nv_aindex(np);
-	if(sub>=mp->nmatch)
-		return(0);
 	n = mp->match[2*sub+1]-mp->match[2*sub];
 	if(n<=0)
 		return("");
@@ -697,6 +701,7 @@
 	if(mp->val[mp->match[2*sub+1]]==0)
 		return(val);
 	mp->rval = (char*)malloc(n+1);
+	mp->lastsub = sub;
 	memcpy(mp->rval,val,n);
 	mp->rval[n] = 0;
 	return(mp->rval);
diff -r -N -u ksh93_2006_07_24/src/cmd/ksh93/sh/io.c ksh93_2006_09_12/src/cmd/ksh93/sh/io.c
--- ksh93_2006_07_24/src/cmd/ksh93/sh/io.c	2006-06-13 21:00:50.000000000 +0200
+++ ksh93_2006_09_12/src/cmd/ksh93/sh/io.c	2006-08-14 20:37:16.000000000 +0200
@@ -107,7 +107,7 @@
 static ssize_t	subread(Sfio_t*, void*, size_t, Sfdisc_t*);
 static ssize_t	tee_write(Sfio_t*,const void*,size_t,Sfdisc_t*);
 static int	io_prompt(Sfio_t*,int);
-static int	io_heredoc(register struct ionod*, const char*);
+static int	io_heredoc(register struct ionod*, const char*, int);
 static void	sftrack(Sfio_t*,int,int);
 static const Sfdisc_t eval_disc = { NULL, NULL, NULL, eval_exceptf, NULL};
 static Sfdisc_t tee_disc = {NULL,tee_write,NULL,NULL,NULL};
@@ -575,6 +575,7 @@
  * flag = 0 if files are to be restored
  * flag = 2 if files are to be closed on exec
  * flag = 3 when called from $( < ...), just open file and return
+ * flag = SH_SHOWME for trace only
  */
 int	sh_redirect(struct ionod *iop, int flag)
 {
@@ -639,12 +640,11 @@
 			}
 			if(iof&IODOC)
 			{
-				fd = io_heredoc(iop,fname);
 				if(traceon)
-				{
-					io_op[2] = '<';
-					sfputr(sfstderr,io_op,'\n');
-				}
+					sfputr(sfstderr,io_op,'<');
+				fd = io_heredoc(iop,fname,traceon);
+				if(traceon && (flag==SH_SHOWME))
+					sh_close(fd);
 				fname = 0;
 			}
 			else if(iof&IOMOV)
@@ -692,6 +692,8 @@
 					message = e_file;
 					goto fail;
 				}
+				if(flag==SH_SHOWME)
+					goto traceit;
 				if((fd=sh_fcntl(dupfd,F_DUPFD,3))<0)
 					goto fail;
 				sh_iocheckfd(dupfd);
@@ -724,7 +726,11 @@
 				goto openit;
 			}
 			else if(!(iof&IOPUT))
+			{
+				if(flag==SH_SHOWME)
+					goto traceit;
 				fd=sh_chkopen(fname);
+			}
 			else if(sh_isoption(SH_RESTRICTED))
 				errormsg(SH_DICT,ERROR_exit(1),e_restricted,fname);
 			else
@@ -760,12 +766,17 @@
 					}
 				}
 			openit:
-				if((fd=sh_open(fname,o_mode,RW_ALL)) <0)
-					errormsg(SH_DICT,ERROR_system(1),((o_mode&O_CREAT)?e_create:e_open),fname);
+				if(flag!=SH_SHOWME)
+				{
+					if((fd=sh_open(fname,o_mode,RW_ALL)) <0)
+						errormsg(SH_DICT,ERROR_system(1),((o_mode&O_CREAT)?e_create:e_open),fname);
+				}
 			}
 		traceit:
 			if(traceon && fname)
 				sfprintf(sfstderr,"%s %s%s%c",io_op,fname,after,iop->ionxt?' ':'\n');
+			if(flag==SH_SHOWME)
+				return(indx);
 			if(trace && fname)
 			{
 				char *argv[7], **av=argv;
@@ -858,6 +869,7 @@
 			{
 				if(np)
 				{
+					long v;
 					fn = fd;
 					if(fd<10)
 					{
@@ -869,7 +881,8 @@
 					}
 					nv_unset(np);
 					nv_onattr(np,NV_INTEGER);
-					nv_putval(np,(void*)&fn, NV_INTEGER);
+					v = fn;
+					nv_putval(np,(void*)&v, NV_INTEGER);
 					sh_iocheckfd(fd);
 				}
 				else
@@ -897,20 +910,31 @@
 /*
  * Create a tmp file for the here-document
  */
-static int io_heredoc(register struct ionod *iop, const char *name)
+static int io_heredoc(register struct ionod *iop, const char *name, int traceon)
 {
 	register Sfio_t	*infile = 0, *outfile;
-	register char		fd;
+	register int		fd;
 	if(!(iop->iofile&IOSTRG) && (!sh.heredocs || iop->iosize==0))
 		return(sh_open(e_devnull,O_RDONLY));
 	/* create an unnamed temporary file */
 	if(!(outfile=sftmp(0)))
 		errormsg(SH_DICT,ERROR_system(1),e_tmpcreate);
 	if(iop->iofile&IOSTRG)
+	{
+		if(traceon)
+			sfprintf(sfstderr,"< %s\n",name);
 		sfputr(outfile,name,'\n');
+	}
 	else
 	{
 		infile = subopen(sh.heredocs,iop->iooffset,iop->iosize);
+		if(traceon)
+		{
+			char *cp = sh_fmtq(iop->iodelim);
+			fd = (*cp=='$' || *cp=='\'')?' ':'\\';
+			sfprintf(sfstderr," %c%s\n",fd,cp);
+			sfdisc(outfile,&tee_disc);
+		}
 		if(iop->iofile&IOQUOTE)
 		{
 			/* This is a quoted here-document, not expansion */
@@ -920,8 +944,6 @@
 		else
 		{
 			char *lastpath = sh.lastpath;
-			if(sh_isoption(SH_XTRACE))
-				sfdisc(outfile,&tee_disc);
 			sh_machere(infile,outfile,iop->ioname);
 			sh.lastpath = lastpath;
 			if(infile)
@@ -932,6 +954,8 @@
 	fd = sffileno(outfile);
 	sfsetfd(outfile,-1);
 	sfclose(outfile);
+	if(traceon && !(iop->iofile&IOSTRG))
+		sfputr(sfstderr,iop->ioname,'\n');
 	lseek(fd,(off_t)0,SEEK_SET);
 	sh.fdstatus[fd] = IOREAD;
 	return(fd);
diff -r -N -u ksh93_2006_07_24/src/cmd/ksh93/sh/jobs.c ksh93_2006_09_12/src/cmd/ksh93/sh/jobs.c
--- ksh93_2006_07_24/src/cmd/ksh93/sh/jobs.c	2006-03-01 16:26:20.000000000 +0100
+++ ksh93_2006_09_12/src/cmd/ksh93/sh/jobs.c	2006-09-07 21:52:00.000000000 +0200
@@ -229,6 +229,7 @@
 			break;
 		flags |= WNOHANG;
 		job.waitsafe++;
+		jp = 0;
 		if(!(pw=job_bypid(pid)))
 		{
 #ifdef DEBUG
diff -r -N -u ksh93_2006_07_24/src/cmd/ksh93/sh/lex.c ksh93_2006_09_12/src/cmd/ksh93/sh/lex.c
--- ksh93_2006_07_24/src/cmd/ksh93/sh/lex.c	2006-06-21 23:00:11.000000000 +0200
+++ ksh93_2006_09_12/src/cmd/ksh93/sh/lex.c	2006-09-07 22:02:52.000000000 +0200
@@ -45,8 +45,10 @@
 #include	"lexstates.h"
 #include	"io.h"
 
+#define TEST_RE		3
 #define SYNBAD		3	/* exit value for syntax errors */
 #define STACK_ARRAY	3	/* size of depth match stack growth */
+#undef	isblank
 #define isblank(c)	(c==' ' || c=='\t')
 
 /*
@@ -353,10 +355,10 @@
 	}
 	else if(lexd.docword)
 	{
-		if(fcgetc(c)=='-')
+		if(fcgetc(c)=='-' || c=='#')
 		{
 			lexd.docword++;
-			shlex.digits=1;
+			shlex.digits=(c=='#'?3:1);
 		}
 		else if(c=='<')
 		{
@@ -510,6 +512,16 @@
 					lex.comp_assign = 0;
 					return(shlex.token='\n');
 				}
+			case S_BLNK:
+				if(lex.incase<=TEST_RE)
+					continue;
+				/* implicit RPAREN for =~ test operator */
+				if(inlevel+1==lexd.level)
+				{
+					fcseek(-1);
+					c = RPAREN;
+					goto do_pop;
+				}
 				continue;
 			case S_OP:
 				/* return operator token */
@@ -863,9 +875,9 @@
 							poplevel();
 						}
 						break;
-#if SHOPT_OO
-					case '-':
-#endif /* SHOPT_OO */
+#if SHOPT_TYPEDEF
+					case '@':
+#endif /* SHOPT_TYPEDEF */
 					case '!':
 						if(n!=S_ALP)
 							goto dolerr;
@@ -992,6 +1004,7 @@
 				mode = ST_NESTED;
 				continue;
 			case S_POP:
+			do_pop:
 				if(lexd.level <= inlevel)
 					break;
 				n = endchar();
@@ -1139,6 +1152,12 @@
 			epat:
 				if(fcgetc(n)==LPAREN)
 				{
+					if(lex.incase==TEST_RE)
+					{
+						lex.incase++;
+						pushlevel(RPAREN,ST_NORM);
+						mode = ST_NESTED;
+					}
 					wordflags |= ARG_EXP;
 					pushlevel(RPAREN,mode);
 					mode = ST_NESTED;
@@ -1304,6 +1323,8 @@
 					errormsg(SH_DICT,ERROR_warn(0),e_lexobsolete4,shp->inlineno,state);
 				if(c&TEST_PATTERN)
 					lex.incase = 1;
+				else if(c==TEST_REP)
+					lex.incase = TEST_RE;
 				lex.testop2 = 0;
 				shlex.digits = c;
 				shlex.token = TESTBINOP;	
@@ -1570,7 +1591,7 @@
 	register int		c,n;
 	register char		*bufp,*cp;
 	register Sfio_t		*sp=shlex.sh->heredocs, *funlog;
-	int			stripflg, nsave, special=0;
+	int			stripcol=0,stripflg, nsave, special=0;
 	if(funlog=shlex.sh->funlog)
 	{
 		if(fcfill()>0)
@@ -1588,7 +1609,19 @@
 		while(*iop->iodelim=='\t')
 			iop->iodelim++;
 		/* skip over leading tabs in document */
-		while(fcgetc(c)=='\t');
+		if(iop->iofile&IOLSEEK)
+		{
+			iop->iofile &= ~IOLSEEK;
+			while(fcgetc(c)=='\t' || c==' ')
+			{
+				if(c==' ')
+					stripcol++;
+				else
+					stripcol += 8 - stripcol%8;
+			}
+		}
+		else
+			while(fcgetc(c)=='\t');
 		if(c>0)
 			fcseek(-1);
 	}
@@ -1657,7 +1690,7 @@
 		{
 		    case S_NL:
 			shlex.sh->inlineno++;
-			if(stripflg && c=='\t')
+			if((stripcol && c==' ') || (stripflg && c=='\t'))
 			{
 				if(!lexd.dolparen)
 				{
@@ -1667,7 +1700,22 @@
 						iop->iosize += n;
 				}
 				/* skip over tabs */
-				while(c=='\t')
+				if(stripcol)
+				{
+					int col=0;
+					do
+					{
+						fcgetc(c);
+						if(c==' ')
+							col++;
+						else
+							col += 8 - col%8;
+						if(col>stripcol)
+							break;
+					}
+					while (c==' ' || c=='\t');
+				}
+				else while(c=='\t')
 					fcgetc(c);
 				if(c<=0)
 					goto done;
@@ -2012,7 +2060,7 @@
 						dp = sp-1;
 						ep = dp-n;
 					}
-					memcpy(ep,msg,n);
+					memmove(ep,msg,n);
 					*dp++ = '"';
 				}
 				ep = 0;
diff -r -N -u ksh93_2006_07_24/src/cmd/ksh93/sh/macro.c ksh93_2006_09_12/src/cmd/ksh93/sh/macro.c
--- ksh93_2006_07_24/src/cmd/ksh93/sh/macro.c	2006-06-07 05:13:16.000000000 +0200
+++ ksh93_2006_09_12/src/cmd/ksh93/sh/macro.c	2006-08-28 23:57:28.000000000 +0200
@@ -43,7 +43,6 @@
 #include	"national.h"
 #include	"streval.h"
 
-
 #undef STR_GROUP
 #ifndef STR_GROUP
 #   define STR_GROUP	0
@@ -88,7 +87,7 @@
 #define M_SUBNAME	5	/* ${!var[sub]}	*/
 #define M_NAMESCAN	6	/* ${!var*}	*/
 #define M_NAMECOUNT	7	/* ${#var*}	*/
-#define M_CLASS		8	/* ${-var}	*/
+#define M_TYPE		8	/* ${@var}	*/
 
 static int	substring(const char*, const char*, int[], int);
 static void	copyto(Mac_t*, int, int);
@@ -426,7 +425,7 @@
 			ssize_t len;
 			do
 			{
-				switch(len = mbsize(sp))
+				switch(len = mbsize(cp))
 				{
 				    case -1:	/* illegal multi-byte char */
 				    case 0:
@@ -461,6 +460,18 @@
 				c = chresc(cp,&addr);
 				cp = addr;
 				first = fcseek(cp-first);
+#if SHOPT_MULTIBYTE
+				if(c > UCHAR_MAX && mbwide())
+				{
+					int		i;
+					unsigned char	mb[8];
+
+					n = wctomb((char*)mb, c);
+					for(i=0;i<n;i++)
+						stakputc(mb[i]);
+				}
+				else
+#endif /* SHOPT_MULTIBYTE */
 				stakputc(c);
 				if(c==ESCAPE && mp->pattern)
 					stakputc(ESCAPE);
@@ -895,7 +906,6 @@
  */
 static int varsub(Mac_t *mp)
 {
-	static char	idbuff[2];
 	register int	c;
 	register int	type=0; /* M_xxx */
 	register char	*v,*argp=0;
@@ -903,11 +913,12 @@
 	register int 	dolg=0, mode=0;
 	Namarr_t	*ap=0;
 	int		dolmax=0, vsize= -1, offset, nulflg, replen=0, bysub=0;
-	char		*id = idbuff, *pattern=0, *repstr;
-	int		oldpat=mp->pattern,idnum=0;
-	*id = 0;
+	char		idbuff[2], *id = idbuff, *pattern=0, *repstr;
+	int		oldpat=mp->pattern,idnum=0,flag=0,d;
 retry1:
 	mp->zeros = 0;
+	idbuff[0] = 0;
+	idbuff[1] = 0;
 	switch(sh_lexstates[ST_DOL][c=fcget()])
 	{
 	    case S_RBRA:
@@ -924,10 +935,13 @@
 			{
 				if(c=='#')
 					type = M_SIZE;
-#if SHOPT_OO
-				else if(c=='-')
-					type = M_CLASS;
-#endif /* SHOPT_OO */
+#ifdef SHOPT_TYPEDEF
+				else if(c=='@')
+				{
+					type = M_TYPE;
+					goto retry1;
+				}
+#endif /* SHOPT_TYPEDEF */
 				else
 					type = M_VNAME;
 				mode = c;
@@ -1001,61 +1015,59 @@
 		if(c=='.' && type==0)
 			goto nosub;
 		offset = staktell();
-#if SHOPT_COMPOUND_ARRAY
-	    more:
-		np = 0;
-#endif /* SHOPT_COMPOUND_ARRAY */
 		do
-			stakputc(c);
-		while(((c=fcget()),isaname(c))||type && c=='.');
-		if(type && (c==LBRACT||c==RBRACE) && fcpeek(-2)=='.')
 		{
-			if(c==RBRACE)
-			{
-				stakseek(staktell()-1);
-				type = M_TREE;
-			}
-			else
+			np = 0;
+			do
+				stakputc(c);
+			while(((c=fcget()),isaname(c))||type && c=='.');
+			while(c==LBRACT && type)
 			{
-				char *last;
 				sh.argaddr=0;
-				if((type==M_VNAME || type==M_SIZE) && (c=fcget(),isastchar(c)) && fcpeek(0)==RBRACT)
+				if((c=fcget(),isastchar(c)) && fcpeek(0)==RBRACT)
 				{
 					if(type==M_VNAME)
-						type = M_NAMESCAN;
-					else
-						type = M_NAMECOUNT;
+						type = M_SUBNAME;
 					idbuff[0] = mode = c;
-					stakputc(c);
 					fcget();
+					c = fcget();
+					if(c=='.' || c==LBRACT)
+					{