File ksh93-dttree-crash.dif of Package ksh

--- src/cmd/ksh93/bltins/typeset.c
+++ src/cmd/ksh93/bltins/typeset.c	2013-10-25 13:20:42.799733785 +0000
@@ -579,7 +579,7 @@ static int     setall(char **argv,regist
 						np = sh_fsearch(shp,name,NV_ADD|HASH_NOSCOPE);
 					else
 #endif /* SHOPT_NAMESPACE */
-					np = nv_open(name,sh_subfuntree(1),NV_NOARRAY|NV_IDENT|NV_NOSCOPE);
+					np = nv_open(name,sh_subfuntree(shp,1),NV_NOARRAY|NV_IDENT|NV_NOSCOPE);
 				}
 				else 
 				{
@@ -1168,14 +1168,14 @@ static int unall(int argc, char **argv,
 	{
 		name = sh_optunalias;
 		if(shp->subshell)
-			troot = sh_subaliastree(0);
+			troot = sh_subaliastree(shp,0);
 	}
 	else
 		name = sh_optunset;
 	while(r = optget(argv,name)) switch(r)
 	{
 		case 'f':
-			troot = sh_subfuntree(1);
+			troot = sh_subfuntree(shp,1);
 			break;
 		case 'a':
 			all=1;
--- src/cmd/ksh93/include/defs.h
+++ src/cmd/ksh93/include/defs.h	2013-10-25 13:20:42.799733785 +0000
@@ -423,10 +423,10 @@ extern void		sh_printopts(Shopt_t,int,Sh
 extern int 		sh_readline(Shell_t*,char**,volatile int,int,ssize_t,long);
 extern Sfio_t		*sh_sfeval(char*[]);
 extern void		sh_setmatch(Shell_t*,const char*,int,int,int[],int);
-extern Dt_t		*sh_subaliastree(int);
+extern Dt_t		*sh_subaliastree(Shell_t*,int);
 extern void             sh_scope(Shell_t*, struct argnod*, int);
 extern Namval_t		*sh_scoped(Shell_t*, Namval_t*);
-extern Dt_t		*sh_subfuntree(int);
+extern Dt_t		*sh_subfuntree(Shell_t*,int);
 extern void		sh_subjobcheck(pid_t);
 extern int		sh_subsavefd(int);
 extern void		sh_subtmpfile(Shell_t*);
--- src/cmd/ksh93/sh/arith.c
+++ src/cmd/ksh93/sh/arith.c	2013-10-25 13:20:42.799733785 +0000
@@ -180,7 +180,10 @@ static Namval_t *scope(register Namval_t
 			{
 				ap = nv_arrayptr(np);
 				if(ap && !ap->table)
+				{
 					ap->table = dtopen(&_Nvdisc,Dtoset);
+					dtuserdata(ap->table,shp,1);
+				}
 				if(ap && ap->table && (nq=nv_search(nv_getsub(np),ap->table,NV_ADD)))
 					nq->nvenv = (char*)np;
 				if(nq && nv_isnull(nq))
--- src/cmd/ksh93/sh/array.c
+++ src/cmd/ksh93/sh/array.c	2013-10-25 13:20:42.800733693 +0000
@@ -79,6 +79,7 @@ struct assoc_array
 
 static Namarr_t *array_scope(Namval_t *np, Namarr_t *ap, int flags)
 {
+	Shell_t *shp = sh_getinterp();
 	Namarr_t *aq;
 #if SHOPT_FIXEDARRAY
 	struct fixed_array *fp;
@@ -95,6 +96,7 @@ static Namarr_t *array_scope(Namval_t *n
 	if(is_associative(aq))
 	{
 		aq->scope = (void*)dtopen(&_Nvdisc,Dtoset);
+		dtuserdata(aq->scope,shp,1);
 		dtview((Dt_t*)aq->scope,aq->table);
 		aq->table = (Dt_t*)aq->scope;
 		return(aq);
@@ -271,6 +273,7 @@ int nv_arrayisset(Namval_t *np, Namarr_t
  */
 static Namval_t *array_find(Namval_t *np,Namarr_t *arp, int flag)
 {
+	Shell_t *shp=sh_getinterp();
 	register struct index_array *ap = (struct index_array*)arp;
 	register union Value	*up;
 	Namval_t		*mp;
@@ -373,7 +376,10 @@ static Namval_t *array_find(Namval_t *np
 		{
 			char *cp;
 			if(!ap->header.table)
+			{
 				ap->header.table = dtopen(&_Nvdisc,Dtoset);
+				dtuserdata(ap->header.table,shp,1);
+			}
 			sfprintf(sh.strbuf,"%d",ap->cur);
 			cp = sfstruse(sh.strbuf);
 			mp = nv_search(cp, ap->header.table, NV_ADD);
@@ -402,6 +408,7 @@ static Namval_t *array_find(Namval_t *np
 #if SHOPT_TYPEDEF
 int nv_arraysettype(Namval_t *np, Namval_t *tp, const char *sub, int flags)
 {
+	Shell_t		*shp = sh_getinterp();
 	Namval_t	*nq;
 	char		*av[2];
 	int		rdonly = nv_isattr(np,NV_RDONLY);
@@ -410,7 +417,10 @@ int nv_arraysettype(Namval_t *np, Namval
 	av[1] = 0;
 	sh.last_table = 0;
 	if(!ap->table)
+	{
 		ap->table = dtopen(&_Nvdisc,Dtoset);
+		dtuserdata(ap->table,shp,1);
+	}
 	if(nq = nv_search(sub, ap->table, NV_ADD))
 	{
 		if(!nq->nvfun && nq->nvalue.cp && *nq->nvalue.cp==0)
@@ -485,6 +495,7 @@ static Namfun_t *array_clone(Namval_t *n
 	if(ap->table)
 	{
 		ap->table = dtopen(&_Nvdisc,Dtoset);
+		dtuserdata(ap->table,shp,1);
 		if(ap->scope && !(flags&NV_COMVAR))
 		{
 			ap->scope = ap->table;
@@ -854,7 +865,9 @@ static struct index_array *array_grow(Na
 			np->nvalue.cp=0;
 		if(nv_hasdisc(np,&array_disc) || (nv_type(np) && nv_isvtree(np)))
 		{
+			Shell_t *shp = sh_getinterp();
 			ap->header.table = dtopen(&_Nvdisc,Dtoset);
+			dtuserdata(ap->header.table,shp,1);
 			mp = nv_search("0", ap->header.table,NV_ADD);
 			if(mp && nv_isnull(mp))
 			{
@@ -1169,6 +1182,7 @@ int nv_nextsub(Namval_t *np)
  */
 Namval_t *nv_putsub(Namval_t *np,register char *sp,register long mode)
 {
+	Shell_t *shp = sh_getinterp();
 	register struct index_array *ap = (struct index_array*)nv_arrayptr(np);
 	register int size = (mode&ARRAY_MASK);
 #if SHOPT_FIXEDARRAY
@@ -1180,7 +1194,6 @@ Namval_t *nv_putsub(Namval_t *np,registe
 	{
 		if(sp)
 		{
-			Shell_t	*shp = sh_getinterp();
 			if(ap && ap->xp && !strmatch(sp,"+([0-9])"))
 			{
 				Namval_t *mp = nv_namptr(ap->xp,0);
@@ -1258,7 +1271,10 @@ Namval_t *nv_putsub(Namval_t *np,registe
 					char *cp;
 					Namval_t *mp;
 					if(!ap->header.table)
+					{
 						ap->header.table = dtopen(&_Nvdisc,Dtoset);
+						dtuserdata(ap->header.table,shp,1);
+					}
 					sfprintf(sh.strbuf,"%d",ap->cur);
 					cp = sfstruse(sh.strbuf);
 					mp = nv_search(cp, ap->header.table, NV_ADD);
@@ -1666,6 +1682,7 @@ int nv_aimax(register Namval_t* np)
  */
 void *nv_associative(register Namval_t *np,const char *sp,int mode)
 {
+	Shell_t *shp = sh_getinterp();
 	register struct assoc_array *ap = (struct assoc_array*)nv_arrayptr(np);
 	register int type;
 	switch(mode)
@@ -1674,6 +1691,7 @@ void *nv_associative(register Namval_t *
 		if(ap = (struct assoc_array*)calloc(1,sizeof(struct assoc_array)))
 		{
 			ap->header.table = dtopen(&_Nvdisc,Dtoset);
+			dtuserdata(ap->header.table,shp,1);
 			ap->cur = 0;
 			ap->pos = 0;
 			ap->header.hdr.disc = &array_disc;
@@ -1742,7 +1760,6 @@ void *nv_associative(register Namval_t *
 	    case NV_ANAME:
 		if(ap->cur)
 		{
-			Shell_t *shp = sh_getinterp();
 			if(!shp->instance && nv_isnull(ap->cur))
 				return(NIL(void*));
 			return((void*)ap->cur->nvname);
--- src/cmd/ksh93/sh/init.c
+++ src/cmd/ksh93/sh/init.c	2013-10-25 13:20:42.800733693 +0000
@@ -1909,9 +1909,13 @@ static Init_t *nv_init(Shell_t *shp)
 	(OPTINDNOD)->nvalue.lp = (&shp->st.optindex);
 	/* set up the seconds clock */
 	shp->alias_tree = inittree(shp,shtab_aliases);
+	dtuserdata(shp->alias_tree,shp,1);
 	shp->track_tree = dtopen(&_Nvdisc,Dtset);
+	dtuserdata(shp->track_tree,shp,1);
 	shp->bltin_tree = inittree(shp,(const struct shtable2*)shtab_builtins);
+	dtuserdata(shp->bltin_tree,shp,1);
 	shp->fun_tree = dtopen(&_Nvdisc,Dtoset);
+	dtuserdata(shp->fun_tree,shp,1);
 	dtview(shp->fun_tree,shp->bltin_tree);
 	nv_mount(DOTSHNOD, "type", shp->typedict=dtopen(&_Nvdisc,Dtoset));
 	nv_adddisc(DOTSHNOD, shdiscnames, (Namval_t**)0);
@@ -1954,6 +1958,7 @@ static Dt_t *inittree(Shell_t *shp,const
 		nbltins = n;
 	}
 	base_treep = treep = dtopen(&_Nvdisc,Dtoset);
+	dtuserdata(treep,shp,1);
 	treep->user = (void*)shp;
 	for(tp=name_vals;*tp->sh_name;tp++,np++)
 	{
--- src/cmd/ksh93/sh/macro.c
+++ src/cmd/ksh93/sh/macro.c	2013-10-25 13:20:42.801733601 +0000
@@ -2742,7 +2742,10 @@ static char *sh_tilde(Shell_t *shp,regis
 skip:
 #endif /* _WINIX */
 	if(!logins_tree)
+	{
 		logins_tree = dtopen(&_Nvdisc,Dtbag);
+		dtuserdata(logins_tree,shp,1);
+	}
 	if(np=nv_search(string,logins_tree,NV_ADD))
 	{
 		c = shp->subshell;
--- src/cmd/ksh93/sh/name.c
+++ src/cmd/ksh93/sh/name.c	2013-10-25 13:20:42.802733508 +0000
@@ -821,6 +821,7 @@ Namval_t *nv_create(const char *name,  D
 				{
 					Dt_t *dp = dtview(shp->var_tree,(Dt_t*)0);
 					rp->sdict = dtopen(&_Nvdisc,Dtoset);
+					dtuserdata(rp->sdict,shp,1);
 					dtview(rp->sdict,dp);
 					dtview(shp->var_tree,rp->sdict);
 				}
@@ -1170,7 +1171,10 @@ Namval_t *nv_create(const char *name,  D
 								ap = nv_arrayptr(np);
 							}
 							if(n && ap && !ap->table)
+							{
 								ap->table = dtopen(&_Nvdisc,Dtoset);
+								dtuserdata(ap->table,shp,1);
+							}
 							if(ap && ap->table && (nq=nv_search(sub,ap->table,n)))
 								nq->nvenv = (char*)np;
 							if(nq && nv_isnull(nq))
@@ -1391,7 +1395,7 @@ Namval_t *nv_open(const char *name, Dt_t
 		while((c= *(unsigned char*)cp++) && (c!='=') && (c!='/') &&
 			(c>=0x200 || !(c=sh_lexstates[ST_NORM][c]) || c==S_EPAT || c==S_COLON));
 		if(shp->subshell && c=='=')
-			root = sh_subaliastree(1);
+			root = sh_subaliastree(shp,1);
 		if(c= *--cp)
 			*cp = 0;
 		np = nv_search(name, root, (flags&NV_NOADD)?0:NV_ADD); 
@@ -2350,6 +2354,7 @@ void sh_scope(Shell_t *shp, struct argno
 		newroot = nv_dict(shp->namespace);
 #endif /* SHOPT_NAMESPACE */
 	newscope = dtopen(&_Nvdisc,Dtoset);
+	dtuserdata(newscope,shp,1);
 	if(envlist)
 	{
 		dtview(newscope,(Dt_t*)shp->var_tree);
@@ -3334,7 +3339,10 @@ int nv_rename(register Namval_t *np, int
 		if(ap=nv_arrayptr(np))
 		{
 			if(!ap->table)
+			{
 				ap->table = dtopen(&_Nvdisc,Dtoset);
+				dtuserdata(ap->table,shp,1);
+			}
 			if(ap->table)
 				mp = nv_search(nv_getsub(np),ap->table,NV_ADD);
 			nv_arraychild(np,mp,0);
--- src/cmd/ksh93/sh/nvdisc.c
+++ src/cmd/ksh93/sh/nvdisc.c	2013-10-25 13:20:42.802733508 +0000
@@ -246,6 +246,7 @@ static void chktfree(register Namval_t *
  */
 static void	assign(Namval_t *np,const char* val,int flags,Namfun_t *handle)
 {
+	Shell_t		*shp = sh_getinterp();
 	int		type = (flags&NV_APPEND)?APPEND:ASSIGN;
 	register	struct vardisc *vp = (struct vardisc*)handle;
 	register	Namval_t *nq =  vp->disc[type];
@@ -330,7 +331,7 @@ static void	assign(Namval_t *np,const ch
 	}
 	else if(!nq || !isblocked(bp,type))
 	{
-		Dt_t *root = sh_subfuntree(1);
+		Dt_t *root = sh_subfuntree(shp,1);
 		int n;
 		Namarr_t *ap;
 		block(bp,type);
@@ -1296,6 +1297,7 @@ static Namfun_t *clone_table(Namval_t* n
 	Dt_t		*oroot=tp->dict,*nroot=dtopen(&_Nvdisc,Dtoset);
 	if(!nroot)
 		return(0);
+	dtuserdata(nroot,dtuserdata(oroot,0,0),1);
 	memcpy((void*)ntp,(void*)fp,sizeof(struct table));
 	ntp->dict = nroot;
 	ntp->parent = nv_lastdict();
@@ -1493,6 +1495,6 @@ Namval_t *sh_fsearch(Shell_t *shp, const
 	sfputr(stkp,nv_name(shp->namespace),'.');
 	sfputr(stkp,fname,0);
 	fname = stkptr(stkp,offset);
-	return(nv_search(fname,sh_subfuntree(add&NV_ADD),add));
+	return(nv_search(fname,sh_subfuntree(shp,add&NV_ADD),add));
 }
 #endif /* SHOPT_NAMESPACE */
--- src/cmd/ksh93/sh/path.c
+++ src/cmd/ksh93/sh/path.c	2013-10-25 13:20:42.803733416 +0000
@@ -592,7 +592,7 @@ static void funload(Shell_t *shp,int fno
 	pname = path_fullname(shp,stakptr(PATH_OFFSET));
 	if(shp->fpathdict && (rp = dtmatch(shp->fpathdict,(void*)pname)))
 	{
-		Dt_t	*funtree = sh_subfuntree(1);
+		Dt_t	*funtree = sh_subfuntree(shp,1);
 		while(1)
 		{
 			rpfirst = dtprev(shp->fpathdict,rp);
@@ -868,13 +868,13 @@ Pathcomp_t *path_absolute(Shell_t *shp,r
 		if(isfun && f>=0 && (cp = strrchr(name,'.')))
 		{
 			*cp = 0;
-			if(nv_open(name,sh_subfuntree(1),NV_NOARRAY|NV_IDENT|NV_NOSCOPE))
+			if(nv_open(name,sh_subfuntree(shp,1),NV_NOARRAY|NV_IDENT|NV_NOSCOPE))
 				f = -1;
 			*cp = '.';
 		}
 		if(isfun && f>=0)
 		{
-			nv_onattr(nv_open(name,sh_subfuntree(1),NV_NOARRAY|NV_IDENT|NV_NOSCOPE),NV_LTOU|NV_FUNCTION);
+			nv_onattr(nv_open(name,sh_subfuntree(shp,1),NV_NOARRAY|NV_IDENT|NV_NOSCOPE),NV_LTOU|NV_FUNCTION);
 			funload(shp,f,name);
 			close(f);
 			f = -1;
--- src/cmd/ksh93/sh/subshell.c
+++ src/cmd/ksh93/sh/subshell.c	2013-10-25 13:20:42.803733416 +0000
@@ -379,7 +379,7 @@ static void nv_restore(struct subshell *
  * return pointer to alias tree
  * create new one if in a subshell and one doesn't exist and create is non-zero
  */
-Dt_t *sh_subaliastree(int create)
+Dt_t *sh_subaliastree(Shell_t *shp,int create)
 {
 	register struct subshell *sp = subshell_data;
 	if(!sp || sp->shp->curenv==0)
@@ -387,6 +387,7 @@ Dt_t *sh_subaliastree(int create)
 	if(!sp->salias && create)
 	{
 		sp->salias = dtopen(&_Nvdisc,Dtoset);
+		dtuserdata(sp->salias,shp,1);
 		dtview(sp->salias,sp->shp->alias_tree);
 		sp->shp->alias_tree = sp->salias;
 	}
@@ -397,7 +398,7 @@ Dt_t *sh_subaliastree(int create)
  * return pointer to function tree
  * create new one if in a subshell and one doesn't exist and create is non-zero
  */
-Dt_t *sh_subfuntree(int create)
+Dt_t *sh_subfuntree(Shell_t *shp,int create)
 {
 	register struct subshell *sp = subshell_data;
 	if(!sp || sp->shp->curenv==0)
@@ -405,6 +406,7 @@ Dt_t *sh_subfuntree(int create)
 	if(!sp->sfun && create)
 	{
 		sp->sfun = dtopen(&_Nvdisc,Dtoset);
+		dtuserdata(sp->sfun,shp,1);
 		dtview(sp->sfun,sp->shp->fun_tree);
 		sp->shp->fun_tree = sp->sfun;
 	}
--- src/cmd/ksh93/sh/xec.c
+++ src/cmd/ksh93/sh/xec.c	2013-10-25 13:20:42.804733324 +0000
@@ -2688,6 +2688,7 @@ int sh_exec(register const Shnode_t *t,
 				else
 				{
 					root = dtopen(&_Nvdisc,Dtoset);
+					dtuserdata(root,shp,1);
 					nv_mount(np, (char*)0, root);
 					np->nvalue.cp = Empty;
 					dtview(root,shp->var_base);
@@ -2729,7 +2730,7 @@ int sh_exec(register const Shnode_t *t,
 				np = sh_fsearch(shp,fname,NV_ADD|HASH_NOSCOPE);
 			if(!np)
 #endif /* SHOPT_NAMESPACE */
-			np = nv_open(fname,sh_subfuntree(1),NV_NOASSIGN|NV_NOARRAY|NV_VARNAME|NV_NOSCOPE);
+			np = nv_open(fname,sh_subfuntree(shp,1),NV_NOASSIGN|NV_NOARRAY|NV_VARNAME|NV_NOSCOPE);
 			if(npv)
 			{
 				if(!shp->mktype)
@@ -2743,11 +2744,6 @@ int sh_exec(register const Shnode_t *t,
 				slp = (struct slnod*)np->nvenv;
 				sh_funstaks(slp->slchild,-1);
 				stakdelete(slp->slptr);
-				if(shp->funload)
-				{
-					free((void*)np->nvalue.rp);
-					np->nvalue.rp = 0;
-				}
 				if(rp->sdict)
 				{
 					Namval_t *mp, *nq;
@@ -2761,6 +2757,12 @@ int sh_exec(register const Shnode_t *t,
 					dtclose(rp->sdict);
 					rp->sdict = 0;
 				}
+				if(shp->funload)
+				{
+					if(!shp->fpathdict)
+						free((void*)np->nvalue.rp);
+					np->nvalue.rp = 0;
+				}
 			}
 			if(!np->nvalue.rp)
 			{
@@ -2799,7 +2801,10 @@ int sh_exec(register const Shnode_t *t,
 					if(!shp->fpathdict)
 						shp->fpathdict = dtopen(&_Rpdisc,Dtobag);
 					if(shp->fpathdict)
+					{
+						dtuserdata(shp->fpathdict,shp,1);
 						dtinsert(shp->fpathdict,rp);
+					}
 				}
 			}
 			else
--- src/lib/libast/Mamfile
+++ src/lib/libast/Mamfile	2013-10-25 13:20:42.806733139 +0000
@@ -3969,6 +3969,14 @@ meta dtopen.o %.c>%.o cdt/dtopen.c dtope
 prev cdt/dtopen.c
 exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icdt -Icomp -Iinclude -Istd -I${INSTALLROOT}/include/ast -D_PACKAGE_ast -c cdt/dtopen.c
 done dtopen.o generated
+make dtstat.o
+make cdt/dtstat.c
+prev cdt/dthdr.h implicit
+done cdt/dtstat.c
+meta dtstat.o %.c>%.o cdt/dtstat.c dtstat
+prev cdt/dtstat.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icdt -Icomp -Iinclude -Istd -I${INSTALLROOT}/include/ast -D_PACKAGE_ast -c cdt/dtstat.c
+done dtstat.o generated
 make dtstrhash.o
 make cdt/dtstrhash.c
 prev cdt/dthdr.h implicit
@@ -3985,6 +3993,14 @@ meta dttree.o %.c>%.o cdt/dttree.c dttre
 prev cdt/dttree.c
 exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icdt -Icomp -Iinclude -Istd -I${INSTALLROOT}/include/ast -D_PACKAGE_ast -c cdt/dttree.c
 done dttree.o generated
+make dtuser.o
+make cdt/dtuser.c
+prev cdt/dthdr.h implicit
+done cdt/dtuser.c
+meta dtuser.o %.c>%.o cdt/dtuser.c dtuser
+prev cdt/dtuser.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icdt -Icomp -Iinclude -Istd -I${INSTALLROOT}/include/ast -D_PACKAGE_ast -c cdt/dtuser.c
+done dtuser.o generated
 make dtview.o
 make cdt/dtview.c
 prev cdt/dthdr.h implicit
@@ -6101,7 +6117,7 @@ exec - ${AR} rc libast.a state.o transit
 exec - ${AR} rc libast.a streval.o strexpr.o strmatch.o strcopy.o modei.o modex.o strmode.o strlcat.o strlcpy.o strlook.o strncopy.o strsearch.o strpsearch.o stresc.o stropt.o strtape.o strpcmp.o strnpcmp.o strvcmp.o strnvcmp.o tok.o tokline.o tokscan.o pathaccess.o pathcat.o pathcanon.o pathcheck.o pathpath.o pathexists.o pathfind.o pathkey.o pathprobe.o pathrepl.o pathnative.o pathposix.o pathtemp.o pathtmp.o pathstat.o pathgetlink.o pathsetlink.o pathbin.o pathshell.o pathcd.o pathprog.o fs3d.o ftwalk.o ftwflags.o fts.o astintercept.o conformance.o getenv.o setenviron.o optget.o optjoin.o optesc.o optctx.o strsort.o struniq.o magic.o mime.o mimetype.o signal.o sigflag.o systrace.o error.o errorf.o errormsg.o errorx.o localeconv.o setlocale.o translate.o catopen.o iconv.o lc.o lctab.o mc.o base64.o recfmt.o recstr.o reclen.o fmtrec.o fmtbase.o fmtbuf.o fmtclock.o fmtdev.o fmtelapsed.o fmterror.o fmtesc.o fmtfmt.o fmtfs.o fmtident.o fmtint.o fmtip4.o fmtip6.o fmtls.o fmtmatch.o fmtmode.o fmtnum.o fmtperm.o fmtre.o fmttime.o
 exec - ${AR} rc libast.a fmtuid.o fmtgid.o fmtsignal.o fmtscale.o fmttmx.o fmttv.o fmtversion.o strelapsed.o strperm.o struid.o strgid.o strtoip4.o strtoip6.o stack.o stk.o swapget.o swapmem.o swapop.o swapput.o sigdata.o sigcrit.o sigunblock.o procopen.o procclose.o procrun.o procfree.o tmdate.o tmequiv.o tmfix.o tmfmt.o tmform.o tmgoff.o tminit.o tmleap.o tmlex.o tmlocale.o tmmake.o tmpoff.o tmscan.o tmsleep.o tmtime.o tmtype.o tmweek.o tmword.o tmzone.o tmxdate.o tmxduration.o tmxfmt.o tmxgettime.o tmxleap.o tmxmake.o tmxscan.o tmxsettime.o tmxsleep.o tmxtime.o tmxtouch.o tvcmp.o tvgettime.o tvsettime.o tvsleep.o tvtouch.o cmdarg.o vecargs.o vecfile.o vecfree.o vecload.o vecstring.o univdata.o touch.o mnt.o debug.o memccpy.o memchr.o memcmp.o memcpy.o memdup.o memmove.o memset.o mkdir.o mkfifo.o mknod.o rmdir.o remove.o rename.o link.o unlink.o strdup.o strchr.o strrchr.o strstr.o strtod.o strtold.o strtol.o strtoll.o strtoul.o strtoull.o strton.o strtonll.o strntod.o strntold.o strnton.o
 exec - ${AR} rc libast.a strntonll.o strntol.o strntoll.o strntoul.o strntoull.o strcasecmp.o strncasecmp.o strerror.o mktemp.o tmpnam.o fsync.o execlp.o execve.o execvp.o execvpe.o spawnveg.o vfork.o killpg.o hsearch.o tsearch.o getlogin.o putenv.o setenv.o unsetenv.o lstat.o statvfs.o eaccess.o gross.o omitted.o readlink.o symlink.o getpgrp.o setpgid.o setsid.o waitpid.o creat64.o fcntl.o open.o atexit.o getdents.o getwd.o dup2.o errno.o getpreroot.o ispreroot.o realopen.o setpreroot.o getgroups.o mount.o system.o iblocks.o modedata.o tmdata.o memfatal.o sfkeyprintf.o sfdcdio.o sfdcdos.o sfdcfilter.o sfdcseekable.o sfdcslow.o sfdcsubstr.o sfdctee.o sfdcunion.o sfdcmore.o sfdcprefix.o wc.o wc2utf8.o basename.o closelog.o dirname.o fmtmsglib.o fnmatch.o ftw.o getdate.o getsubopt.o glob.o nftw.o openlog.o re_comp.o resolvepath.o realpath.o regcmp.o regexp.o setlogmask.o strftime.o strptime.o swab.o syslog.o tempnam.o wordexp.o mktime.o regalloc.o regclass.o regcoll.o regcomp.o regcache.o regdecomp.o regerror.o regexec.o regfatal.o reginit.o
-exec - ${AR} rc libast.a regnexec.o regsubcomp.o regsubexec.o regsub.o regrecord.o regrexec.o regstat.o dtclose.o dtdisc.o dthash.o dtlist.o dtmethod.o dtopen.o dtstrhash.o dttree.o dtview.o dtwalk.o dtnew.o dtcomp.o sfclose.o sfclrlock.o sfdisc.o sfdlen.o sfexcept.o sfgetl.o sfgetu.o sfcvt.o sfecvt.o sffcvt.o sfextern.o sffilbuf.o sfflsbuf.o sfprints.o sfgetd.o sfgetr.o sfllen.o sfmode.o sfmove.o sfnew.o sfpkrd.o sfnotify.o sfnputc.o sfopen.o sfpeek.o sfpoll.o sfpool.o sfpopen.o sfprintf.o sfputd.o sfputl.o sfputr.o sfputu.o sfrd.o sfread.o sfreserve.o sfscanf.o sfseek.o sfset.o sfsetbuf.o sfsetfd.o sfsize.o sfsk.o sfstack.o sfstrtod.o sfsync.o sfswap.o sftable.o sftell.o sftmp.o sfungetc.o sfvprintf.o sfvscanf.o sfwr.o sfwrite.o sfpurge.o sfraise.o sfwalk.o sfgetm.o sfmutex.o sfputm.o sfresize.o _sfclrerr.o _sfeof.o _sferror.o _sffileno.o _sfopen.o _sfstacked.o _sfvalue.o _sfgetc.o _sfgetl.o _sfgetl2.o _sfgetu.o _sfgetu2.o _sfdlen.o _sfllen.o _sfslen.o _sfulen.o _sfputc.o _sfputd.o _sfputl.o _sfputm.o
+exec - ${AR} rc libast.a regnexec.o regsubcomp.o regsubexec.o regsub.o regrecord.o regrexec.o regstat.o dtclose.o dtdisc.o dthash.o dtlist.o dtmethod.o dtopen.o dtstat.o dtstrhash.o dttree.o dtuser.o dtview.o dtwalk.o dtnew.o dtcomp.o sfclose.o sfclrlock.o sfdisc.o sfdlen.o sfexcept.o sfgetl.o sfgetu.o sfcvt.o sfecvt.o sffcvt.o sfextern.o sffilbuf.o sfflsbuf.o sfprints.o sfgetd.o sfgetr.o sfllen.o sfmode.o sfmove.o sfnew.o sfpkrd.o sfnotify.o sfnputc.o sfopen.o sfpeek.o sfpoll.o sfpool.o sfpopen.o sfprintf.o sfputd.o sfputl.o sfputr.o sfputu.o sfrd.o sfread.o sfreserve.o sfscanf.o sfseek.o sfset.o sfsetbuf.o sfsetfd.o sfsize.o sfsk.o sfstack.o sfstrtod.o sfsync.o sfswap.o sftable.o sftell.o sftmp.o sfungetc.o sfvprintf.o sfvscanf.o sfwr.o sfwrite.o sfpurge.o sfraise.o sfwalk.o sfgetm.o sfmutex.o sfputm.o sfresize.o _sfclrerr.o _sfeof.o _sferror.o _sffileno.o _sfopen.o _sfstacked.o _sfvalue.o _sfgetc.o _sfgetl.o _sfgetl2.o _sfgetu.o _sfgetu2.o _sfdlen.o _sfllen.o _sfslen.o _sfulen.o _sfputc.o _sfputd.o _sfputl.o _sfputm.o
 exec - ${AR} rc libast.a _sfputu.o clearerr.o fclose.o fdopen.o feof.o ferror.o fflush.o fgetc.o fgetpos.o fgets.o fileno.o fopen.o fprintf.o fpurge.o fputc.o fputs.o fread.o freopen.o fscanf.o fseek.o fseeko.o fsetpos.o ftell.o ftello.o fwrite.o flockfile.o ftrylockfile.o funlockfile.o getc.o getchar.o getw.o pclose.o popen.o printf.o putc.o putchar.o puts.o putw.o rewind.o scanf.o setbuf.o setbuffer.o setlinebuf.o setvbuf.o snprintf.o sprintf.o sscanf.o asprintf.o vasprintf.o tmpfile.o ungetc.o vfprintf.o vfscanf.o vprintf.o vscanf.o vsnprintf.o vsprintf.o vsscanf.o _doprnt.o _doscan.o _filbuf.o _flsbuf.o _stdfun.o _stdopen.o _stdprintf.o _stdscanf.o _stdsprnt.o _stdvbuf.o _stdvsnprnt.o _stdvsprnt.o _stdvsscn.o fgetwc.o fwprintf.o putwchar.o vfwscanf.o wprintf.o fgetws.o fwscanf.o swprintf.o vswprintf.o wscanf.o fputwc.o getwc.o swscanf.o vswscanf.o fputws.o getwchar.o ungetwc.o vwprintf.o fwide.o putwc.o vfwprintf.o vwscanf.o stdio_c99.o fcloseall.o fmemopen.o getdelim.o getline.o frexp.o frexpl.o astcopy.o
 exec - ${AR} rc libast.a astconf.o astdynamic.o astlicense.o astquery.o astwinsize.o conftab.o aststatic.o getopt.o getoptl.o aso.o asolock.o asometh.o asorelax.o aso-sem.o aso-fcntl.o vmbest.o vmclear.o vmclose.o vmdcheap.o vmdebug.o vmdisc.o vmexit.o vmlast.o vmopen.o vmpool.o vmprivate.o vmprofile.o vmregion.o vmsegment.o vmset.o vmstat.o vmstrdup.o vmtrace.o vmwalk.o vmmopen.o malloc.o vmgetmem.o a64l.o acosh.o asinh.o atanh.o cbrt.o crypt.o erf.o err.o exp.o exp__E.o expm1.o gamma.o getpass.o lgamma.o log.o log1p.o log__L.o rand48.o random.o rcmd.o rint.o support.o sfstrtmp.o spawn.o
 exec - (ranlib libast.a) >/dev/null 2>&1 || true
--- src/lib/libast/cdt/cdtlib.h
+++ src/lib/libast/cdt/cdtlib.h	2013-10-25 13:20:42.807733047 +0000
@@ -58,9 +58,9 @@
 /* This struct holds private method data created on DT_OPEN */
 struct _dtdata_s
 {	unsigned int	lock;	/* general dictionary lock	*/
-	Dtuser_t	user;	/* application's data		*/
 	unsigned int	type;	/* method type, control flags	*/
 	ssize_t		size;	/* number of objects		*/
+	Dtuser_t	user;	/* application's data		*/
 	Dt_t		dict;	/* when DT_INDATA is requested	*/
 };
 
@@ -123,7 +123,7 @@ typedef struct _dtlib_s
 #endif /* _BLD_cdt */
 
 /* these macros lock/unlock dictionaries. DTRETURN substitutes for "return" */
-#define DTSETLOCK(dt)		(((dt)->data->type&DT_SHARE) ? asolock(&(dt)->data->lock,1,ASO_SPINLOCK) : 0 )
+#define DTSETLOCK(dt)		(((dt)->data->type&DT_SHARE) ? asolock(&(dt)->data->lock,1,ASO_LOCK) : 0 )
 #define DTCLRLOCK(dt)		(((dt)->data->type&DT_SHARE) ? asolock(&(dt)->data->lock,1,ASO_UNLOCK) : 0 )
 #define DTRETURN(ob,rv)		do { (ob) = (rv); goto dt_return; } while(0)
 #define DTERROR(dt, mesg) 	(!((dt)->disc && (dt)->disc->eventf) ? 0 : \
--- src/lib/libast/cdt/dtcomp.c
+++ src/lib/libast/cdt/dtcomp.c	2013-10-25 13:20:42.807733047 +0000
@@ -52,9 +52,3 @@ extern ssize_t dtsize(Dt_t* d)
 {
 	return (ssize_t)(*(_DT(d)->searchf))((d),(Void_t*)(0),DT_STAT);
 }
-
-#undef dtstat
-extern ssize_t dtstat(Dt_t* d)
-{
-	return (ssize_t)(*(_DT(d)->searchf))((d),(Void_t*)(0),DT_STAT);
-}
--- src/lib/libast/cdt/dthash.c
+++ src/lib/libast/cdt/dthash.c	2013-10-25 13:20:42.807733047 +0000
@@ -52,11 +52,13 @@ static int htable(Dt_t* dt)
 	if((n = hash->tblz) > 0 && (hash->type&H_FIXED) )
 		return 0; /* fixed size table */
 
-	if(n == 0 && disc && disc->eventf) /* let user have input */
+	if(disc && disc->eventf) /* let user have input */
 	{	if((*disc->eventf)(dt, DT_HASHSIZE, &n, disc) > 0 )
 		{	if(n < 0) /* fix table size */
 			{	hash->type |= H_FIXED;
-				n = -n;
+				n = -n; /* desired table size */
+				if(hash->tblz >= n ) /* table size is fixed now */
+					return 0;
 			}
 		}
 	}
@@ -234,12 +236,13 @@ static Void_t* hstat(Dt_t* dt, Dtstat_t*
 
 		for(endt = (t = hash->htbl) + hash->tblz; t < endt; ++t)
 		{	for(n = 0, l = *t; l; l = l->_rght)
+			{	if(n < DT_MAXSIZE)
+					st->lsize[n] += 1;
 				n += 1;
+			}
 			st->mlev = n > st->mlev ? n : st->mlev;
 			if(n < DT_MAXSIZE) /* if chain length is small */
-			{	st->msize = n > st->msize ? n : st->msize;
-				st->lsize[n] += n;
-			}
+				st->msize = n > st->msize ? n : st->msize;
 		}
 	}
 
@@ -310,7 +313,7 @@ int	type;
 	hsh = _DTHSH(dt,key,disc);
 
 	tbl = hash->htbl + (hsh & (hash->tblz-1));
-	pp = ll = NIL(Dtlink_t*);
+	pp = ll = NIL(Dtlink_t*); /* pp is the before, ll is the here */
 	for(p = NIL(Dtlink_t*), l = *tbl; l; p = l, l = l->_rght)
 	{	if(hsh == l->_hash)
 		{	o = _DTOBJ(disc,l); k = _DTKEY(disc,o);
@@ -342,20 +345,41 @@ int	type;
 			_dtfree(dt, ll, type);
 			DTRETURN(obj, _DTOBJ(disc,ll));
 		}
+		else if(type & DT_INSTALL )
+		{	if(dt->meth->type&DT_BAG)
+				goto do_insert;
+			else if(!(lnk = _dtmake(dt, obj, type)) )
+				DTRETURN(obj, NIL(Void_t*) );
+			else /* replace old object with new one */
+			{	if(pp) /* remove old object */
+					pp->_rght = ll->_rght;
+				else	*tbl = ll->_rght;
+				o = _DTOBJ(disc,ll);
+				_dtfree(dt, ll, DT_DELETE);
+				DTANNOUNCE(dt, o, DT_DELETE);
+
+				goto do_insert;
+			}
+		}
 		else
 		{	/**/DEBUG_ASSERT(type&(DT_INSERT|DT_ATTACH|DT_APPEND|DT_RELINK));
-			if(!(dt->meth->type&DT_BAG) )
+			if((dt->meth->type&DT_BAG) )
+				goto do_insert;
+			else
 			{	if(type&(DT_INSERT|DT_APPEND|DT_ATTACH) )
-					type |= DT_SEARCH; /* for announcement */
+					type |= DT_MATCH; /* for announcement */
 				else if(lnk && (type&DT_RELINK) )
+				{	/* remove a duplicate */
+					o = _DTOBJ(disc, lnk);
 					_dtfree(dt, lnk, DT_DELETE);
+					DTANNOUNCE(dt, o, DT_DELETE);
+				}
 				DTRETURN(obj, _DTOBJ(disc,ll));
 			}
-			else	goto do_insert;
 		}
 	}
 	else /* no matching object */
-	{	if(!(type&(DT_INSERT|DT_APPEND|DT_ATTACH|DT_RELINK)) )
+	{	if(!(type&(DT_INSERT|DT_INSTALL|DT_APPEND|DT_ATTACH|DT_RELINK)) )
 			DTRETURN(obj, NIL(Void_t*));
 
 	do_insert: /* inserting a new object */
--- src/lib/libast/cdt/dtlist.c
+++ src/lib/libast/cdt/dtlist.c	2013-10-25 13:20:42.807733047 +0000
@@ -142,9 +142,9 @@ int		type;
 }
 
 #if __STD_C
-static Void_t* liststat(Dt_t* dt, Dtstat_t* st)
+static Void_t* listat(Dt_t* dt, Dtstat_t* st)
 #else
-static Void_t* liststat(dt, st)
+static Void_t* listat(dt, st)
 Dt_t*		dt;
 Dtstat_t*	st;
 #endif
@@ -186,7 +186,7 @@ int	type;
 	else if(type&DT_CLEAR)
 		DTRETURN(obj, lclear(dt));
 	else if(type&DT_STAT )
-		DTRETURN(obj, liststat(dt, (Dtstat_t*)obj));
+		DTRETURN(obj, listat(dt, (Dtstat_t*)obj));
 
 	h = list->here; /* save finger to last search object */
 	list->here = NIL(Dtlink_t*);
@@ -202,8 +202,9 @@ int	type;
 	{	r = (Dtlink_t*)obj;
 		goto do_insert;
 	}
-	else if(type&(DT_INSERT|DT_APPEND|DT_ATTACH))
-	{	if(!(r = _dtmake(dt, obj, type)) )
+	else if(type&(DT_INSERT|DT_INSTALL|DT_APPEND|DT_ATTACH))
+	{ dt_insert:
+		if(!(r = _dtmake(dt, obj, type)) )
 			DTRETURN(obj, NIL(Void_t*));
 		dt->data->size += 1;
 
@@ -290,7 +291,7 @@ int	type;
 		}
 		r = h ? h : r;
 	}
-	if(!r)
+	if(!r) /* not found */
 		DTRETURN(obj, NIL(Void_t*));
 
 	if(type&(DT_DELETE|DT_DETACH|DT_REMOVE))
--- src/lib/libast/cdt/dtopen.c
+++ src/lib/libast/cdt/dtopen.c	2013-10-25 13:20:42.808732955 +0000
@@ -153,25 +153,3 @@ void _dtfree(Dt_t* dt, Dtlink_t* l, int
 	if(disc->link < 0) /* free holder */
 		(void)(*dt->memoryf)(dt, (Void_t*)l, 0, disc);
 }
-
-int dtuserlock(Dt_t* dt, unsigned int key, int type)
-{
-	if(type > 0)
-		return asolock(&dt->data->user.lock, key, ASO_LOCK);
-	else if(type < 0)
-		return asolock(&dt->data->user.lock, key, ASO_UNLOCK);
-	else	return asolock(&dt->data->user.lock, key, ASO_TRYLOCK);
-}
-
-Void_t* dtuserdata(Dt_t* dt, Void_t* data, unsigned int key)
-{
-	if(key == 0)
-		return dt->data->user.data;
-	else if(dtuserlock(dt, key, 1) < 0 )
-		return NIL(Void_t*);
-	else
-	{	dt->data->user.data = data;
-		dtuserlock(dt, key, -1);
-		return data;
-	}
-}
--- src/lib/libast/cdt/dtstat.c
+++ src/lib/libast/cdt/dtstat.c	2013-10-25 13:20:42.808732955 +0000
@@ -0,0 +1,54 @@
+/***********************************************************************
+*                                                                      *
+*               This software is part of the ast package               *
+*          Copyright (c) 1985-2012 AT&T Intellectual Property          *
+*                      and is licensed under the                       *
+*                 Eclipse Public License, Version 1.0                  *
+*                    by AT&T Intellectual Property                     *
+*                                                                      *
+*                A copy of the License is available at                 *
+*          http://www.eclipse.org/org/documents/epl-v10.html           *
+*         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
+*                                                                      *
+*              Information and Software Systems Research               *
+*                            AT&T Research                             *
+*                           Florham Park NJ                            *
+*                                                                      *
+*                 Glenn Fowler <gsf@research.att.com>                  *
+*                  David Korn <dgk@research.att.com>                   *
+*                   Phong Vo <kpv@research.att.com>                    *
+*                                                                      *
+***********************************************************************/
+#include	"dthdr.h"
+
+/* Get statistics for a dictionary
+**
+** Written by Kiem-Phong Vo
+*/
+
+ssize_t dtstat(Dt_t* dt, Dtstat_t* dtst)
+{
+	ssize_t	sz, k, maxk;
+	char	*str;
+	char	*end;
+
+	sz = (ssize_t)(*dt->meth->searchf)(dt, (Void_t*)dtst, DT_STAT);
+
+	str = dtst->mesg;
+	end = &dtst->mesg[sizeof(dtst->mesg)] - 1;
+	str += sfsprintf(str, end - str, "Objects=%d Levels=%d(Largest:", dtst->size, dtst->mlev+1);
+
+	/* print top 3 levels */
+	for(k = maxk = 0; k <= dtst->mlev; ++k)
+		if(dtst->lsize[k] > dtst->lsize[maxk])
+			maxk = k;
+	if(maxk > 0) 
+		maxk -= 1;
+	for(k = 0; k < 3 && maxk <= dtst->mlev; ++k, ++maxk)
+		str += sfsprintf(str, end - str, " lev[%d]=%d", maxk, dtst->lsize[maxk] );
+	if (str < end)
+		*str++ = ')';
+	*str = 0;
+
+	return sz;
+}
--- src/lib/libast/cdt/dtstrhash.c
+++ src/lib/libast/cdt/dtstrhash.c	2013-10-25 13:20:42.808732955 +0000
@@ -22,40 +22,38 @@
 #include	"dthdr.h"
 
 /* Hashing a string into an unsigned integer.
-** The basic method is to continuingly accumulate bytes and multiply
-** with some given prime. The length n of the string is added last.
-** The recurrent equation is like this:
-**	h[k] = (h[k-1] + bytes)*prime	for 0 <= k < n
-**	h[n] = (h[n-1] + n)*prime
-** The prime is chosen to have a good distribution of 1-bits so that
-** the multiplication will distribute the bits in the accumulator well.
-** The below code accumulates 2 bytes at a time for speed.
-**
-** Written by Kiem-Phong Vo (02/28/03)
+** This is the FNV (Fowler-Noll-Vo) hash function.
+** Written by Kiem-Phong Vo (01/10/2012)
 */
 
 #if __STD_C
 uint dtstrhash(uint h, Void_t* args, ssize_t n)
 #else
 uint dtstrhash(h,args,n)
-reg uint	h;
+uint	h;
 Void_t*		args;
 ssize_t		n;
 #endif
 {
 	unsigned char	*s = (unsigned char*)args;
 
-	if(n <= 0)
-	{	for(; *s != 0; s += s[1] ? 2 : 1)
-			h = (h + (s[0]<<8) + s[1])*DT_PRIME;
-		n = s - (unsigned char*)args;
+#if _ast_sizeof_int == 8 /* 64-bit hash */
+#define	FNV_PRIME	((1<<40) + (1<<8) + 0xb3)
+#define FNV_OFFSET	14695981039346656037
+#else /* 32-bit hash */
+#define	FNV_PRIME	((1<<24) + (1<<8) + 0x93)
+#define FNV_OFFSET	2166136261
+#endif
+	h = (h == 0 || h == ~0) ? FNV_OFFSET : h;
+	if(n <= 0) /* see discipline key definition for == 0 */
+	{	for(; *s != 0; ++s )
+			h = (h ^ s[0]) * FNV_PRIME;
 	}
 	else
 	{	unsigned char*	ends;
-		for(ends = s+n-1; s < ends; s += 2)
-			h = (h + (s[0]<<8) + s[1])*DT_PRIME;
-		if(s <= ends)
-			h = (h + (s[0]<<8))*DT_PRIME;
+		for(ends = s+n; s < ends; ++s)
+			h = (h ^ s[0]) * FNV_PRIME;
 	}
-	return (h+n)*DT_PRIME;
+
+	return h;
 }
--- src/lib/libast/cdt/dttree.c
+++ src/lib/libast/cdt/dttree.c	2013-10-25 13:20:42.808732955 +0000
@@ -545,7 +545,14 @@ int		type;
 			}
 			else	goto no_root;
 		}
-		else if(type&DT_REMOVE) /* remove a particular element in the tree */
+		else if(type&(DT_DELETE|DT_DETACH))
+		{ dt_delete: /* remove an object from the dictionary */
+			obj = _DTOBJ(disc,root);
+			_dtfree(dt, root, type);
+			dt->data->size -= 1;
+			goto no_root;
+		}
+		else if(type&DT_REMOVE) /* remove a particular object */
 		{	if(_DTOBJ(disc,root) == obj)
 				goto dt_delete;
 			else
@@ -555,28 +562,32 @@ int		type;
 				DTRETURN(obj, NIL(Void_t*));
 			}
 		}
-		else if(type&(DT_DELETE|DT_DETACH))
-		{ dt_delete: /* remove an object from the dictionary */
-			obj = _DTOBJ(disc,root);
-			_dtfree(dt, root, type);
-			dt->data->size -= 1;
-			goto no_root;
-		}
 		else if(type&(DT_INSERT|DT_APPEND|DT_ATTACH))
 		{	if(dt->meth->type&DT_OSET)
-			{	type |= DT_SEARCH; /* for announcement */
+			{	type |= DT_MATCH; /* for announcement */
 				goto has_root;
 			}
-			else
+			else /* if(dt->meth->type&DT_OBAG) */
 			{	root->_left = NIL(Dtlink_t*);
 				root->_rght = link._left;
 				link._left = root;
 				goto dt_insert;
 			}
 		}
+		else if(type&DT_INSTALL)
+		{	/* remove old object before insert new one */
+			o = _DTOBJ(disc, root);
+			_dtfree(dt, root, DT_DELETE);
+			DTANNOUNCE(dt, o, DT_DELETE);
+			goto dt_insert;
+		}
 		else if(type&DT_RELINK) /* a duplicate */
 		{	if(dt->meth->type&DT_OSET)
+			{	/* remove object */
+				o = _DTOBJ(disc, me);
 				_dtfree(dt, me, DT_DELETE);
+				DTANNOUNCE(dt, o, DT_DELETE);
+			}
 			else
 			{	me->_left = NIL(Dtlink_t*);
 				me->_rght = link._left;
@@ -612,7 +623,7 @@ int		type;
 		{	obj = NIL(Void_t*);
 			goto no_root;
 		}
-		else if(type&(DT_INSERT|DT_APPEND|DT_ATTACH))
+		else if(type&(DT_INSERT|DT_APPEND|DT_ATTACH|DT_INSTALL))
 		{ dt_insert:
 			if(!(root = _dtmake(dt, obj, type)) )
 			{	obj = NIL(Void_t*);
--- src/lib/libast/cdt/dtuser.c
+++ src/lib/libast/cdt/dtuser.c	2013-10-25 13:20:42.808732955 +0000
@@ -0,0 +1,59 @@
+/***********************************************************************
+*                                                                      *
+*               This software is part of the ast package               *
+*          Copyright (c) 1985-2012 AT&T Intellectual Property          *
+*                      and is licensed under the                       *
+*                 Eclipse Public License, Version 1.0                  *
+*                    by AT&T Intellectual Property                     *
+*                                                                      *
+*                A copy of the License is available at                 *
+*          http://www.eclipse.org/org/documents/epl-v10.html           *
+*         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
+*                                                                      *
+*              Information and Software Systems Research               *
+*                            AT&T Research                             *
+*                           Florham Park NJ                            *
+*                                                                      *
+*                 Glenn Fowler <gsf@research.att.com>                  *
+*                  David Korn <dgk@research.att.com>                   *
+*                   Phong Vo <kpv@research.att.com>                    *
+*                                                                      *
+***********************************************************************/
+#include	"dthdr.h"
+
+/* Perform various functions on the user's behalf.
+**
+** Written by Kiem-Phong Vo (01/05/2012)
+*/
+
+/* managing the lock dt->data->user.lock */
+int dtuserlock(Dt_t* dt, unsigned int key, int type)
+{
+	if(key == 0)
+		return -1;
+	else if(type > 0)
+		return asolock(&dt->data->user.lock, key, ASO_LOCK);
+	else if(type < 0)
+		return asolock(&dt->data->user.lock, key, ASO_UNLOCK);
+	else	return asolock(&dt->data->user.lock, key, ASO_TRYLOCK);
+}
+
+/* managing the user data slot dt->data->user.data */
+Void_t* dtuserdata(Dt_t* dt, Void_t* data, int set)
+{
+	if(set == 0) /* just return current value */
+		return asogetptr(&dt->data->user.data);
+	else while(1)
+	{	Void_t	*current = dt->data->user.data;
+		if(asocasptr(&dt->data->user.data, current, data) == current)
+			return	current;
+	}
+}
+
+/* announcing an event on the user's behalf */
+int dtuserevent(Dt_t* dt, int flags, Void_t* data)
+{
+	if(!dt->disc->eventf)
+		return 0;
+	else	return (*dt->disc->eventf)(dt, DT_ANNOUNCE|DT_USER|flags, data, dt->disc);
+}
--- src/lib/libast/include/cdt.h
+++ src/lib/libast/include/cdt.h	2013-10-25 13:20:42.809732863 +0000
@@ -164,6 +164,7 @@ struct _dtstat_s
 	ssize_t		msize;	/* max #defined elts in below arrays	*/
 	ssize_t		lsize[DT_MAXSIZE]; /* #objects by level		*/
 	ssize_t		tsize[DT_MAXSIZE]; /* #tables by level		*/
+	char		mesg[256]; /* digest of top level statistics	*/
 };
 
 /* supported storage methods */
@@ -199,7 +200,8 @@ struct _dtstat_s
 #define DT_ATLEAST	0000040000 /* find the least elt >= object	*/
 #define DT_ATMOST	0000100000 /* find the biggest elt <= object	*/
 #define DT_REMOVE	0002000000 /* remove a specific object		*/
-#define DT_TOANNOUNCE	(DT_INSERT|DT_DELETE|DT_SEARCH|DT_NEXT|DT_PREV|DT_FIRST|DT_LAST|DT_MATCH|DT_ATTACH|DT_DETACH|DT_APPEND|DT_ATLEAST|DT_ATMOST|DT_REMOVE)
+#define DT_INSTALL      0004000000 /* install a new object		*/
+#define DT_TOANNOUNCE	(DT_INSERT|DT_DELETE|DT_SEARCH|DT_NEXT|DT_PREV|DT_FIRST|DT_LAST|DT_MATCH|DT_ATTACH|DT_DETACH|DT_APPEND|DT_ATLEAST|DT_ATMOST|DT_REMOVE|DT_INSTALL)
 
 #define DT_RELINK	0000002000 /* re-inserting (dtdisc,dtmethod...)	*/
 #define DT_FLATTEN	0000000040 /* flatten objects into a list	*/
@@ -216,6 +218,7 @@ struct _dtstat_s
 				   /* the actual event will be this bit */
 				   /* combined with the operation bit	*/
 #define DT_OPTIMIZE	0100000000 /* optimizing data structure		*/
+#define DT_USER		0200000000 /* an announcement on user's behalf	*/
 
 /* events for discipline and method event-handling functions */
 #define DT_OPEN		1	/* a dictionary is being opened		*/
@@ -277,7 +280,8 @@ extern int		dtwalk _ARG_((Dt_t*, int(*)(
 extern int		dtcustomize _ARG_((Dt_t*, int, int));
 extern unsigned int	dtstrhash _ARG_((unsigned int, Void_t*, ssize_t));
 extern int		dtuserlock _ARG_((Dt_t*, unsigned int, int));
-extern Void_t*		dtuserdata _ARG_((Dt_t*, Void_t*, unsigned int));
+extern Void_t*		dtuserdata _ARG_((Dt_t*, Void_t*, int));
+extern int		dtuserevent _ARG_((Dt_t*, int, Void_t*));
 
 /* deal with upward binary compatibility (operation bit translation, etc.) */
 extern Dt_t*		_dtopen _ARG_((Dtdisc_t*, Dtmethod_t*, unsigned long));
@@ -334,6 +338,7 @@ _END_EXTERNS_
 #define dtsearch(d,o)	(*(_DT(d)->searchf))((d),(Void_t*)(o),DT_SEARCH)
 #define dtmatch(d,o)	(*(_DT(d)->searchf))((d),(Void_t*)(o),DT_MATCH)
 #define dtinsert(d,o)	(*(_DT(d)->searchf))((d),(Void_t*)(o),DT_INSERT)
+#define dtinstall(d,o)	(*(_DT(d)->searchf))((d),(Void_t*)(o),DT_INSTALL)
 #define dtappend(d,o)	(*(_DT(d)->searchf))((d),(Void_t*)(o),DT_APPEND)
 #define dtdelete(d,o)	(*(_DT(d)->searchf))((d),(Void_t*)(o),DT_DELETE)
 #define dtremove(d,o)	(*(_DT(d)->searchf))((d),(Void_t*)(o),DT_REMOVE)
@@ -345,7 +350,6 @@ _END_EXTERNS_
 #define dtextract(d)	(Dtlink_t*)(*(_DT(d)->searchf))((d),(Void_t*)(0),DT_EXTRACT)
 #define dtrestore(d,l)	(Dtlink_t*)(*(_DT(d)->searchf))((d),(Void_t*)(l),DT_RESTORE)
 
-#define dtstat(d,s)	(ssize_t)(*(_DT(d)->searchf))((d),(Void_t*)(s),DT_STAT)
 #define dtsize(d)	(ssize_t)(*(_DT(d)->searchf))((d),(Void_t*)(0),DT_STAT)
 
 #define DT_PRIME	17109811 /* 2#00000001 00000101 00010011 00110011 */
openSUSE Build Service is sponsored by