1da2e3ebdSchin /***********************************************************************
2da2e3ebdSchin *                                                                      *
3da2e3ebdSchin *               This software is part of the ast package               *
4*b30d1939SAndy Fiddaman *          Copyright (c) 1982-2012 AT&T Intellectual Property          *
5da2e3ebdSchin *                      and is licensed under the                       *
6*b30d1939SAndy Fiddaman *                 Eclipse Public License, Version 1.0                  *
77c2fbfb3SApril Chin *                    by AT&T Intellectual Property                     *
8da2e3ebdSchin *                                                                      *
9da2e3ebdSchin *                A copy of the License is available at                 *
10*b30d1939SAndy Fiddaman *          http://www.eclipse.org/org/documents/epl-v10.html           *
11*b30d1939SAndy Fiddaman *         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
12da2e3ebdSchin *                                                                      *
13da2e3ebdSchin *              Information and Software Systems Research               *
14da2e3ebdSchin *                            AT&T Research                             *
15da2e3ebdSchin *                           Florham Park NJ                            *
16da2e3ebdSchin *                                                                      *
17da2e3ebdSchin *                  David Korn <dgk@research.att.com>                   *
18da2e3ebdSchin *                                                                      *
19da2e3ebdSchin ***********************************************************************/
20da2e3ebdSchin #pragma prototyped
21da2e3ebdSchin 
22da2e3ebdSchin /*
23da2e3ebdSchin  * code for tree nodes and name walking
24da2e3ebdSchin  *
25da2e3ebdSchin  *   David Korn
26da2e3ebdSchin  *   AT&T Labs
27da2e3ebdSchin  *
28da2e3ebdSchin  */
29da2e3ebdSchin 
30da2e3ebdSchin #include	"defs.h"
31da2e3ebdSchin #include	"name.h"
32da2e3ebdSchin #include	"argnod.h"
337c2fbfb3SApril Chin #include	"lexstates.h"
34da2e3ebdSchin 
35da2e3ebdSchin struct nvdir
36da2e3ebdSchin {
37da2e3ebdSchin 	Dt_t		*root;
38da2e3ebdSchin 	Namval_t	*hp;
39da2e3ebdSchin 	Namval_t	*table;
407c2fbfb3SApril Chin 	Namval_t	*otable;
41da2e3ebdSchin 	Namval_t	*(*nextnode)(Namval_t*,Dt_t*,Namfun_t*);
42da2e3ebdSchin 	Namfun_t	*fun;
43da2e3ebdSchin 	struct nvdir	*prev;
44da2e3ebdSchin 	int		len;
45*b30d1939SAndy Fiddaman 	char		*data;
46da2e3ebdSchin };
47da2e3ebdSchin 
48*b30d1939SAndy Fiddaman static int	Indent;
49da2e3ebdSchin char *nv_getvtree(Namval_t*, Namfun_t *);
50da2e3ebdSchin static void put_tree(Namval_t*, const char*, int,Namfun_t*);
517c2fbfb3SApril Chin static char *walk_tree(Namval_t*, Namval_t*, int);
527c2fbfb3SApril Chin 
read_tree(Namval_t * np,Sfio_t * iop,int n,Namfun_t * dp)537c2fbfb3SApril Chin static int read_tree(Namval_t* np, Sfio_t *iop, int n, Namfun_t *dp)
547c2fbfb3SApril Chin {
557c2fbfb3SApril Chin 	Sfio_t	*sp;
567c2fbfb3SApril Chin 	char	*cp;
577c2fbfb3SApril Chin 	int	c;
587c2fbfb3SApril Chin 	if(n>=0)
597c2fbfb3SApril Chin 		return(-1);
607c2fbfb3SApril Chin 	while((c = sfgetc(iop)) &&  isblank(c));
617c2fbfb3SApril Chin 	sfungetc(iop,c);
627c2fbfb3SApril Chin 	sfprintf(sh.strbuf,"%s=%c",nv_name(np),0);
637c2fbfb3SApril Chin 	cp = sfstruse(sh.strbuf);
647c2fbfb3SApril Chin 	sp = sfopen((Sfio_t*)0,cp,"s");
657c2fbfb3SApril Chin 	sfstack(iop,sp);
667c2fbfb3SApril Chin 	c=sh_eval(iop,SH_READEVAL);
677c2fbfb3SApril Chin 	return(c);
687c2fbfb3SApril Chin }
69da2e3ebdSchin 
create_tree(Namval_t * np,const char * name,int flag,Namfun_t * dp)70da2e3ebdSchin static Namval_t *create_tree(Namval_t *np,const char *name,int flag,Namfun_t *dp)
71da2e3ebdSchin {
72da2e3ebdSchin 	register Namfun_t *fp=dp;
733e14f97fSRoger A. Faulkner 	fp->dsize = 0;
74da2e3ebdSchin 	while(fp=fp->next)
75da2e3ebdSchin 	{
76da2e3ebdSchin 		if(fp->disc && fp->disc->createf)
77da2e3ebdSchin 		{
78da2e3ebdSchin 			if(np=(*fp->disc->createf)(np,name,flag,fp))
79da2e3ebdSchin 				dp->last = fp->last;
80da2e3ebdSchin 			return(np);
81da2e3ebdSchin 		}
82da2e3ebdSchin 	}
83da2e3ebdSchin 	return((flag&NV_NOADD)?0:np);
84da2e3ebdSchin }
85da2e3ebdSchin 
clone_tree(Namval_t * np,Namval_t * mp,int flags,Namfun_t * fp)867c2fbfb3SApril Chin static Namfun_t *clone_tree(Namval_t *np, Namval_t *mp, int flags, Namfun_t *fp){
877c2fbfb3SApril Chin 	Namfun_t	*dp;
887c2fbfb3SApril Chin 	if ((flags&NV_MOVE) && nv_type(np))
897c2fbfb3SApril Chin 		return(fp);
907c2fbfb3SApril Chin 	dp = nv_clone_disc(fp,flags);
917c2fbfb3SApril Chin 	if((flags&NV_COMVAR) && !(flags&NV_RAW))
927c2fbfb3SApril Chin 	{
937c2fbfb3SApril Chin 		walk_tree(np,mp,flags);
947c2fbfb3SApril Chin 		if((flags&NV_MOVE) && !(fp->nofree&1))
957c2fbfb3SApril Chin 			free((void*)fp);
967c2fbfb3SApril Chin 	}
977c2fbfb3SApril Chin 	return(dp);
987c2fbfb3SApril Chin }
997c2fbfb3SApril Chin 
100da2e3ebdSchin static const Namdisc_t treedisc =
101da2e3ebdSchin {
102da2e3ebdSchin 	0,
103da2e3ebdSchin 	put_tree,
104da2e3ebdSchin 	nv_getvtree,
105da2e3ebdSchin 	0,
106da2e3ebdSchin 	0,
1077c2fbfb3SApril Chin 	create_tree,
1087c2fbfb3SApril Chin 	clone_tree
1097c2fbfb3SApril Chin 	,0,0,0,
1107c2fbfb3SApril Chin 	read_tree
111da2e3ebdSchin };
112da2e3ebdSchin 
nextdot(const char * str)113da2e3ebdSchin static char *nextdot(const char *str)
114da2e3ebdSchin {
115da2e3ebdSchin 	register char *cp;
1167c2fbfb3SApril Chin 	register int c;
117da2e3ebdSchin 	if(*str=='.')
118da2e3ebdSchin 		str++;
1197c2fbfb3SApril Chin 	for(cp=(char*)str;c= *cp; cp++)
120da2e3ebdSchin 	{
1217c2fbfb3SApril Chin 		if(c=='[')
1227c2fbfb3SApril Chin 		{
1237c2fbfb3SApril Chin 			cp = nv_endsubscript((Namval_t*)0,(char*)cp,0);
1247c2fbfb3SApril Chin 			return(*cp=='.'?cp:0);
1257c2fbfb3SApril Chin 		}
1267c2fbfb3SApril Chin 		if(c=='.')
1277c2fbfb3SApril Chin 			return(cp);
128da2e3ebdSchin 	}
1297c2fbfb3SApril Chin 	return(0);
130da2e3ebdSchin }
131da2e3ebdSchin 
nextdisc(Namval_t * np)132da2e3ebdSchin static  Namfun_t *nextdisc(Namval_t *np)
133da2e3ebdSchin {
134da2e3ebdSchin 	register Namfun_t *fp;
135da2e3ebdSchin 	if(nv_isref(np))
136da2e3ebdSchin 		return(0);
137da2e3ebdSchin         for(fp=np->nvfun;fp;fp=fp->next)
138da2e3ebdSchin 	{
139da2e3ebdSchin 		if(fp && fp->disc && fp->disc->nextf)
140da2e3ebdSchin 			return(fp);
141da2e3ebdSchin 	}
142da2e3ebdSchin 	return(0);
143da2e3ebdSchin }
144da2e3ebdSchin 
nv_diropen(Namval_t * np,const char * name)1457c2fbfb3SApril Chin void *nv_diropen(Namval_t *np,const char *name)
146da2e3ebdSchin {
147da2e3ebdSchin 	char *next,*last;
148da2e3ebdSchin 	int c,len=strlen(name);
149*b30d1939SAndy Fiddaman 	struct nvdir *save, *dp = new_of(struct nvdir,len+1);
1507c2fbfb3SApril Chin 	Namval_t *nq=0,fake;
1517c2fbfb3SApril Chin 	Namfun_t *nfp=0;
152da2e3ebdSchin 	if(!dp)
153da2e3ebdSchin 		return(0);
154da2e3ebdSchin 	memset((void*)dp, 0, sizeof(*dp));
155*b30d1939SAndy Fiddaman 	dp->data = (char*)(dp+1);
156da2e3ebdSchin 	if(name[len-1]=='*' || name[len-1]=='@')
157da2e3ebdSchin 		len -= 1;
1587c2fbfb3SApril Chin 	name = memcpy(dp->data,name,len);
1597c2fbfb3SApril Chin 	dp->data[len] = 0;
160da2e3ebdSchin 	dp->len = len;
1617c2fbfb3SApril Chin 	dp->root = sh.last_root?sh.last_root:sh.var_tree;
1627c2fbfb3SApril Chin #if 1
1637c2fbfb3SApril Chin 	while(1)
1647c2fbfb3SApril Chin 	{
1657c2fbfb3SApril Chin 		dp->table = sh.last_table;
1667c2fbfb3SApril Chin 		sh.last_table = 0;
1677c2fbfb3SApril Chin 		if(*(last=(char*)name)==0)
1687c2fbfb3SApril Chin 			break;
1697c2fbfb3SApril Chin 		if(!(next=nextdot(last)))
1707c2fbfb3SApril Chin 			break;
1717c2fbfb3SApril Chin 		*next = 0;
1727c2fbfb3SApril Chin 		np = nv_open(name, dp->root, NV_NOFAIL);
1737c2fbfb3SApril Chin 		*next = '.';
1747c2fbfb3SApril Chin 		if(!np || !nv_istable(np))
1757c2fbfb3SApril Chin 			break;
1767c2fbfb3SApril Chin 		dp->root = nv_dict(np);
1777c2fbfb3SApril Chin 		name = next+1;
1787c2fbfb3SApril Chin 	}
1797c2fbfb3SApril Chin #else
180da2e3ebdSchin 	dp->table = sh.last_table;
1817c2fbfb3SApril Chin 	sh.last_table = 0;
1827c2fbfb3SApril Chin 	last = dp->data;
1837c2fbfb3SApril Chin #endif
184da2e3ebdSchin 	if(*name)
185da2e3ebdSchin 	{
186da2e3ebdSchin 		fake.nvname = (char*)name;
1877c2fbfb3SApril Chin 		if(dp->hp = (Namval_t*)dtprev(dp->root,&fake))
1887c2fbfb3SApril Chin 		{
1897c2fbfb3SApril Chin 			char *cp = nv_name(dp->hp);
1907c2fbfb3SApril Chin 			c = strlen(cp);
1917c2fbfb3SApril Chin 			if(memcmp(name,cp,c) || name[c]!='[')
1927c2fbfb3SApril Chin 				dp->hp = (Namval_t*)dtnext(dp->root,dp->hp);
1937c2fbfb3SApril Chin 			else
1947c2fbfb3SApril Chin 			{
1957c2fbfb3SApril Chin 				np = dp->hp;
1967c2fbfb3SApril Chin 				last = 0;
1977c2fbfb3SApril Chin 			}
1987c2fbfb3SApril Chin 		}
19934f9b3eeSRoland Mainz 		else
20034f9b3eeSRoland Mainz 			dp->hp = (Namval_t*)dtfirst(dp->root);
201da2e3ebdSchin 	}
202da2e3ebdSchin 	else
203da2e3ebdSchin 		dp->hp = (Namval_t*)dtfirst(dp->root);
2047c2fbfb3SApril Chin 	while(1)
205da2e3ebdSchin 	{
2067c2fbfb3SApril Chin 		if(!last)
2077c2fbfb3SApril Chin 			next = 0;
2087c2fbfb3SApril Chin 		else if(next= nextdot(last))
2097c2fbfb3SApril Chin 		{
2107c2fbfb3SApril Chin 			c = *next;
2117c2fbfb3SApril Chin 			*next = 0;
2127c2fbfb3SApril Chin 		}
2137c2fbfb3SApril Chin 		if(!np)
2147c2fbfb3SApril Chin 		{
2157c2fbfb3SApril Chin 			if(nfp && nfp->disc && nfp->disc->createf)
2167c2fbfb3SApril Chin 			{
2177c2fbfb3SApril Chin 				np =  (*nfp->disc->createf)(nq,last,0,nfp);
2187c2fbfb3SApril Chin 				if(*nfp->last == '[')
2197c2fbfb3SApril Chin 				{
2207c2fbfb3SApril Chin 					nv_endsubscript(np,nfp->last,NV_NOADD);
2217c2fbfb3SApril Chin 					if(nq = nv_opensub(np))
2227c2fbfb3SApril Chin 						np = nq;
2237c2fbfb3SApril Chin 				}
2247c2fbfb3SApril Chin 			}
2257c2fbfb3SApril Chin 			else
2267c2fbfb3SApril Chin 				np = nv_search(last,dp->root,0);
2277c2fbfb3SApril Chin 		}
2287c2fbfb3SApril Chin 		if(next)
2297c2fbfb3SApril Chin 			*next = c;
2307c2fbfb3SApril Chin 		if(np==dp->hp && !next)
2317c2fbfb3SApril Chin 			dp->hp = (Namval_t*)dtnext(dp->root,dp->hp);
232da2e3ebdSchin 		if(np && ((nfp=nextdisc(np)) || nv_istable(np)))
233da2e3ebdSchin 		{
234da2e3ebdSchin 			if(!(save = new_of(struct nvdir,0)))
235da2e3ebdSchin 				return(0);
236da2e3ebdSchin 			*save = *dp;
237da2e3ebdSchin 			dp->prev = save;
238da2e3ebdSchin 			if(nv_istable(np))
239da2e3ebdSchin 				dp->root = nv_dict(np);
240da2e3ebdSchin 			else
2417c2fbfb3SApril Chin 				dp->root = (Dt_t*)np;
242da2e3ebdSchin 			if(nfp)
243da2e3ebdSchin 			{
244da2e3ebdSchin 				dp->nextnode = nfp->disc->nextf;
245da2e3ebdSchin 				dp->table = np;
2467c2fbfb3SApril Chin 				dp->otable = sh.last_table;
247da2e3ebdSchin 				dp->fun = nfp;
248da2e3ebdSchin 				dp->hp = (*dp->nextnode)(np,(Dt_t*)0,nfp);
249da2e3ebdSchin 			}
250da2e3ebdSchin 			else
251da2e3ebdSchin 				dp->nextnode = 0;
252da2e3ebdSchin 		}
253da2e3ebdSchin 		else
254da2e3ebdSchin 			break;
2557c2fbfb3SApril Chin 		if(!next || next[1]==0)
2567c2fbfb3SApril Chin 			break;
257da2e3ebdSchin 		last = next+1;
2587c2fbfb3SApril Chin 		nq = np;
2597c2fbfb3SApril Chin 		np = 0;
260da2e3ebdSchin 	}
261da2e3ebdSchin 	return((void*)dp);
262da2e3ebdSchin }
263da2e3ebdSchin 
264da2e3ebdSchin 
nextnode(struct nvdir * dp)265da2e3ebdSchin static Namval_t *nextnode(struct nvdir *dp)
266da2e3ebdSchin {
267da2e3ebdSchin 	if(dp->nextnode)
268da2e3ebdSchin 		return((*dp->nextnode)(dp->hp,dp->root,dp->fun));
269da2e3ebdSchin 	if(dp->len && memcmp(dp->data, dp->hp->nvname, dp->len))
270da2e3ebdSchin 		return(0);
271da2e3ebdSchin 	return((Namval_t*)dtnext(dp->root,dp->hp));
272da2e3ebdSchin }
273da2e3ebdSchin 
nv_dirnext(void * dir)274da2e3ebdSchin char *nv_dirnext(void *dir)
275da2e3ebdSchin {
276da2e3ebdSchin 	register struct nvdir *save, *dp = (struct nvdir*)dir;
277da2e3ebdSchin 	register Namval_t *np, *last_table;
278da2e3ebdSchin 	register char *cp;
279da2e3ebdSchin 	Namfun_t *nfp;
2807c2fbfb3SApril Chin 	Namval_t *nq;
281da2e3ebdSchin 	while(1)
282da2e3ebdSchin 	{
283da2e3ebdSchin 		while(np=dp->hp)
284da2e3ebdSchin 		{
2857c2fbfb3SApril Chin #if 0
2867c2fbfb3SApril Chin 			char *sptr;
2877c2fbfb3SApril Chin #endif
2887c2fbfb3SApril Chin 			if(nv_isarray(np))
2897c2fbfb3SApril Chin 				nv_putsub(np,(char*)0, ARRAY_UNDEF);
290da2e3ebdSchin 			dp->hp = nextnode(dp);
29134f9b3eeSRoland Mainz 			if(nv_isnull(np) && !nv_isarray(np) && !nv_isattr(np,NV_INTEGER))
292da2e3ebdSchin 				continue;
293da2e3ebdSchin 			last_table = sh.last_table;
2947c2fbfb3SApril Chin #if 0
2957c2fbfb3SApril Chin 			if(dp->table && dp->otable && !nv_isattr(dp->table,NV_MINIMAL))
2967c2fbfb3SApril Chin 			{
2977c2fbfb3SApril Chin 				sptr = dp->table->nvenv;
2987c2fbfb3SApril Chin 				dp->table->nvenv = (char*)dp->otable;
2997c2fbfb3SApril Chin 			}
3007c2fbfb3SApril Chin #endif
301da2e3ebdSchin 			sh.last_table = dp->table;
302da2e3ebdSchin 			cp = nv_name(np);
3037c2fbfb3SApril Chin #if 0
3047c2fbfb3SApril Chin 			if(dp->table && dp->otable && !nv_isattr(dp->table,NV_MINIMAL))
3057c2fbfb3SApril Chin 				dp->table->nvenv = sptr;
3067c2fbfb3SApril Chin #endif
3077c2fbfb3SApril Chin 			if(dp->nextnode && !dp->hp && (nq = (Namval_t*)dp->table))
3087c2fbfb3SApril Chin 			{
3097c2fbfb3SApril Chin 				Namarr_t  *ap = nv_arrayptr(nq);
3107c2fbfb3SApril Chin 				if(ap && (ap->nelem&ARRAY_SCAN) && nv_nextsub(nq))
3117c2fbfb3SApril Chin 					dp->hp = (*dp->nextnode)(np,(Dt_t*)0,dp->fun);
3127c2fbfb3SApril Chin 			}
313da2e3ebdSchin 			sh.last_table = last_table;
3147c2fbfb3SApril Chin 			if(!dp->len || memcmp(cp,dp->data,dp->len)==0)
315da2e3ebdSchin 			{
3167c2fbfb3SApril Chin 				if((nfp=nextdisc(np)) && (nfp->disc->getval||nfp->disc->getnum) && nv_isvtree(np) && strcmp(cp,dp->data))
3177c2fbfb3SApril Chin 					nfp = 0;
3187c2fbfb3SApril Chin 				if(nfp || nv_istable(np))
319da2e3ebdSchin 				{
320da2e3ebdSchin 					Dt_t *root;
321*b30d1939SAndy Fiddaman 					int len;
322da2e3ebdSchin 					if(nv_istable(np))
323da2e3ebdSchin 						root = nv_dict(np);
324da2e3ebdSchin 					else
3257c2fbfb3SApril Chin 						root = (Dt_t*)np;
326da2e3ebdSchin 					/* check for recursive walk */
327da2e3ebdSchin 					for(save=dp; save;  save=save->prev)
328da2e3ebdSchin 					{
329da2e3ebdSchin 						if(save->root==root)
330da2e3ebdSchin 							break;
331da2e3ebdSchin 					}
332da2e3ebdSchin 					if(save)
3337c2fbfb3SApril Chin 						return(cp);
334*b30d1939SAndy Fiddaman 					len = strlen(cp);
335*b30d1939SAndy Fiddaman 					if(!(save = new_of(struct nvdir,len+1)))
336da2e3ebdSchin 						return(0);
337da2e3ebdSchin 					*save = *dp;
338da2e3ebdSchin 					dp->prev = save;
339da2e3ebdSchin 					dp->root = root;
340*b30d1939SAndy Fiddaman 					dp->len = len-1;
341*b30d1939SAndy Fiddaman 					dp->data = (char*)(save+1);
342*b30d1939SAndy Fiddaman 					memcpy(dp->data,cp,len+1);
343da2e3ebdSchin 					if(nfp && np->nvfun)
344da2e3ebdSchin 					{
3457c2fbfb3SApril Chin #if 0
3467c2fbfb3SApril Chin 				                Namarr_t *ap = nv_arrayptr(np);
3477c2fbfb3SApril Chin 				                if(ap && (ap->nelem&ARRAY_UNDEF))
3487c2fbfb3SApril Chin 				                        nv_putsub(np,(char*)0,ARRAY_SCAN);
3497c2fbfb3SApril Chin #endif
350da2e3ebdSchin 						dp->nextnode = nfp->disc->nextf;
3517c2fbfb3SApril Chin 						dp->otable = dp->table;
352da2e3ebdSchin 						dp->table = np;
353da2e3ebdSchin 						dp->fun = nfp;
354da2e3ebdSchin 						dp->hp = (*dp->nextnode)(np,(Dt_t*)0,nfp);
355da2e3ebdSchin 					}
356da2e3ebdSchin 					else
357da2e3ebdSchin 						dp->nextnode = 0;
358da2e3ebdSchin 				}
359da2e3ebdSchin 				return(cp);
360da2e3ebdSchin 			}
361da2e3ebdSchin 		}
362da2e3ebdSchin 		if(!(save=dp->prev))
363da2e3ebdSchin 			break;
364da2e3ebdSchin 		*dp = *save;
365da2e3ebdSchin 		free((void*)save);
366da2e3ebdSchin 	}
367da2e3ebdSchin 	return(0);
368da2e3ebdSchin }
369da2e3ebdSchin 
nv_dirclose(void * dir)370da2e3ebdSchin void nv_dirclose(void *dir)
371da2e3ebdSchin {
372da2e3ebdSchin 	struct nvdir *dp = (struct nvdir*)dir;
373da2e3ebdSchin 	if(dp->prev)
374da2e3ebdSchin 		nv_dirclose((void*)dp->prev);
375da2e3ebdSchin 	free(dir);
376da2e3ebdSchin }
377da2e3ebdSchin 
outtype(Namval_t * np,Namfun_t * fp,Sfio_t * out,const char * prefix)378da2e3ebdSchin static void outtype(Namval_t *np, Namfun_t *fp, Sfio_t* out, const char *prefix)
379da2e3ebdSchin {
380da2e3ebdSchin 	char *type=0;
381da2e3ebdSchin 	Namval_t *tp = fp->type;
382da2e3ebdSchin 	if(!tp && fp->disc && fp->disc->typef)
383da2e3ebdSchin 		tp = (*fp->disc->typef)(np,fp);
384da2e3ebdSchin 	for(fp=fp->next;fp;fp=fp->next)
385da2e3ebdSchin 	{
386da2e3ebdSchin 		if(fp->type || (fp->disc && fp->disc->typef &&(*fp->disc->typef)(np,fp)))
387da2e3ebdSchin 		{
388da2e3ebdSchin 			outtype(np,fp,out,prefix);
389da2e3ebdSchin 			break;
390da2e3ebdSchin 		}
391da2e3ebdSchin 	}
392da2e3ebdSchin 	if(prefix && *prefix=='t')
393da2e3ebdSchin 		type = "-T";
394da2e3ebdSchin 	else if(!prefix)
395da2e3ebdSchin 		type = "type";
396da2e3ebdSchin 	if(type)
3977c2fbfb3SApril Chin 	{
3987c2fbfb3SApril Chin 		char *cp=tp->nvname;
3997c2fbfb3SApril Chin 		if(cp=strrchr(cp,'.'))
4007c2fbfb3SApril Chin 			cp++;
4017c2fbfb3SApril Chin 		else
4027c2fbfb3SApril Chin 			cp = tp->nvname;
4037c2fbfb3SApril Chin 		sfprintf(out,"%s %s ",type,cp);
4047c2fbfb3SApril Chin 	}
405da2e3ebdSchin }
406da2e3ebdSchin 
407da2e3ebdSchin /*
408da2e3ebdSchin  * print the attributes of name value pair give by <np>
409da2e3ebdSchin  */
nv_attribute(register Namval_t * np,Sfio_t * out,char * prefix,int noname)410da2e3ebdSchin void nv_attribute(register Namval_t *np,Sfio_t *out,char *prefix,int noname)
411da2e3ebdSchin {
412da2e3ebdSchin 	register const Shtable_t *tp;
413da2e3ebdSchin 	register char *cp;
4147c2fbfb3SApril Chin 	register unsigned val,mask,attr;
4157c2fbfb3SApril Chin 	char *ip=0;
416da2e3ebdSchin 	Namfun_t *fp=0;
4177c2fbfb3SApril Chin 	Namval_t *typep=0;
418*b30d1939SAndy Fiddaman #if SHOPT_FIXEDARRAY
419*b30d1939SAndy Fiddaman 	int fixed=0;
420*b30d1939SAndy Fiddaman #endif /* SHOPT_FIXEDARRAY */
421da2e3ebdSchin 	for(fp=np->nvfun;fp;fp=fp->next)
422da2e3ebdSchin 	{
4237c2fbfb3SApril Chin 		if((typep=fp->type) || (fp->disc && fp->disc->typef && (typep=(*fp->disc->typef)(np,fp))))
424da2e3ebdSchin 			break;
425da2e3ebdSchin 	}
426*b30d1939SAndy Fiddaman 	if(np==typep)
427*b30d1939SAndy Fiddaman 	{
428*b30d1939SAndy Fiddaman 
429*b30d1939SAndy Fiddaman 		fp = 0;
430*b30d1939SAndy Fiddaman 		typep = 0;
431*b30d1939SAndy Fiddaman 	}
4327c2fbfb3SApril Chin 	if(!fp  && !nv_isattr(np,~(NV_MINIMAL|NV_NOFREE)))
433da2e3ebdSchin 	{
4347c2fbfb3SApril Chin 		if(prefix && *prefix)
4357c2fbfb3SApril Chin 		{
4367c2fbfb3SApril Chin 			if(nv_isvtree(np))
4377c2fbfb3SApril Chin 				sfprintf(out,"%s -C ",prefix);
43834f9b3eeSRoland Mainz 			else if((!np->nvalue.cp||np->nvalue.cp==Empty) && nv_isattr(np,~NV_NOFREE)==NV_MINIMAL && strcmp(np->nvname,"_"))
4397c2fbfb3SApril Chin 				sfputr(out,prefix,' ');
4407c2fbfb3SApril Chin 		}
441da2e3ebdSchin 		return;
4427c2fbfb3SApril Chin 	}
443da2e3ebdSchin 
444da2e3ebdSchin 	if ((attr=nv_isattr(np,~NV_NOFREE)) || fp)
445da2e3ebdSchin 	{
446c4fc965cSToomas Soome 		if((attr&(NV_NOPRINT|NV_INTEGER))==NV_NOPRINT)
447da2e3ebdSchin 			attr &= ~NV_NOPRINT;
448da2e3ebdSchin 		if(!attr && !fp)
449da2e3ebdSchin 			return;
4507c2fbfb3SApril Chin 		if(fp)
4517c2fbfb3SApril Chin 		{
4527c2fbfb3SApril Chin 			prefix = Empty;
4537c2fbfb3SApril Chin 			attr &= NV_RDONLY|NV_ARRAY;
4547c2fbfb3SApril Chin 			if(nv_isattr(np,NV_REF|NV_TAGGED)==(NV_REF|NV_TAGGED))
4557c2fbfb3SApril Chin 				attr |= (NV_REF|NV_TAGGED);
4567c2fbfb3SApril Chin 			if(typep)
4577c2fbfb3SApril Chin 			{
4587c2fbfb3SApril Chin 				char *cp = typep->nvname;
4597c2fbfb3SApril Chin 				if(cp = strrchr(cp,'.'))
4607c2fbfb3SApril Chin 					cp++;
4617c2fbfb3SApril Chin 				else
4627c2fbfb3SApril Chin 					cp = typep->nvname;
4637c2fbfb3SApril Chin 				sfputr(out,cp,' ');
4647c2fbfb3SApril Chin 				fp = 0;
4657c2fbfb3SApril Chin 			}
4667c2fbfb3SApril Chin 		}
4677c2fbfb3SApril Chin 		else if(prefix && *prefix)
468da2e3ebdSchin 			sfputr(out,prefix,' ');
469da2e3ebdSchin 		for(tp = shtab_attributes; *tp->sh_name;tp++)
470da2e3ebdSchin 		{
471da2e3ebdSchin 			val = tp->sh_number;
472da2e3ebdSchin 			mask = val;
473da2e3ebdSchin 			if(fp && (val&NV_INTEGER))
474da2e3ebdSchin 				break;
475da2e3ebdSchin 			/*
476da2e3ebdSchin 			 * the following test is needed to prevent variables
477da2e3ebdSchin 			 * with E attribute from being given the F
478da2e3ebdSchin 			 * attribute as well
479da2e3ebdSchin 			*/
4807c2fbfb3SApril Chin 			if(val==NV_DOUBLE && (attr&(NV_EXPNOTE|NV_HEXFLOAT)))
481da2e3ebdSchin 				continue;
482da2e3ebdSchin 			if(val&NV_INTEGER)
483da2e3ebdSchin 				mask |= NV_DOUBLE;
484da2e3ebdSchin 			else if(val&NV_HOST)
485da2e3ebdSchin 				mask = NV_HOST;
486da2e3ebdSchin 			if((attr&mask)==val)
487da2e3ebdSchin 			{
488da2e3ebdSchin 				if(val==NV_ARRAY)
489da2e3ebdSchin 				{
490da2e3ebdSchin 					Namarr_t *ap = nv_arrayptr(np);
4917c2fbfb3SApril Chin 					char **xp=0;
4927c2fbfb3SApril Chin 					if(ap && array_assoc(ap))
493da2e3ebdSchin 					{
494da2e3ebdSchin 						if(tp->sh_name[1]!='A')
495da2e3ebdSchin 							continue;
496da2e3ebdSchin 					}
497da2e3ebdSchin 					else if(tp->sh_name[1]=='A')
498da2e3ebdSchin 						continue;
49934f9b3eeSRoland Mainz 					if((ap && (ap->nelem&ARRAY_TREE)) || (!ap && nv_isattr(np,NV_NOFREE)))
5007c2fbfb3SApril Chin 					{
5017c2fbfb3SApril Chin 						if(prefix && *prefix)
5027c2fbfb3SApril Chin 							sfwrite(out,"-C ",3);
5037c2fbfb3SApril Chin 					}
504*b30d1939SAndy Fiddaman #if SHOPT_FIXEDARRAY
505*b30d1939SAndy Fiddaman 					if(ap && ap->fixed)
506*b30d1939SAndy Fiddaman 						fixed++;
507*b30d1939SAndy Fiddaman 					else
508*b30d1939SAndy Fiddaman #endif /* SHOPT_FIXEDARRAY */
5097c2fbfb3SApril Chin 					if(ap && !array_assoc(ap) && (xp=(char**)(ap+1)) && *xp)
5107c2fbfb3SApril Chin 						ip = nv_namptr(*xp,0)->nvname;
511da2e3ebdSchin 				}
512*b30d1939SAndy Fiddaman 				if(val==NV_UTOL || val==NV_LTOU)
513*b30d1939SAndy Fiddaman 				{
514*b30d1939SAndy Fiddaman 					if((cp = (char*)nv_mapchar(np,0)) && strcmp(cp,tp->sh_name+2))
515*b30d1939SAndy Fiddaman 					{
516*b30d1939SAndy Fiddaman 						sfprintf(out,"-M %s ",cp);
517*b30d1939SAndy Fiddaman 						continue;
518*b30d1939SAndy Fiddaman 					}
519*b30d1939SAndy Fiddaman 				}
520da2e3ebdSchin 				if(prefix)
521da2e3ebdSchin 				{
522da2e3ebdSchin 					if(*tp->sh_name=='-')
523da2e3ebdSchin 						sfprintf(out,"%.2s ",tp->sh_name);
5247c2fbfb3SApril Chin 					if(ip)
5257c2fbfb3SApril Chin 					{
5267c2fbfb3SApril Chin 						sfprintf(out,"[%s] ",ip);
5277c2fbfb3SApril Chin 						ip = 0;
5287c2fbfb3SApril Chin 					}
529da2e3ebdSchin 				}
530da2e3ebdSchin 				else
531da2e3ebdSchin 					sfputr(out,tp->sh_name+2,' ');
532da2e3ebdSchin 		                if ((val&(NV_LJUST|NV_RJUST|NV_ZFILL)) && !(val&NV_INTEGER) && val!=NV_HOST)
533da2e3ebdSchin 					sfprintf(out,"%d ",nv_size(np));
5347c2fbfb3SApril Chin 				if(val==(NV_REF|NV_TAGGED))
5357c2fbfb3SApril Chin 					attr &= ~(NV_REF|NV_TAGGED);
536da2e3ebdSchin 			}
537da2e3ebdSchin 		        if(val==NV_INTEGER && nv_isattr(np,NV_INTEGER))
538da2e3ebdSchin 			{
539da2e3ebdSchin 				if(nv_size(np) != 10)
540da2e3ebdSchin 				{
5417c2fbfb3SApril Chin 					if(nv_isattr(np, NV_DOUBLE)== NV_DOUBLE)
542da2e3ebdSchin 						cp = "precision";
543da2e3ebdSchin 					else
544da2e3ebdSchin 						cp = "base";
545da2e3ebdSchin 					if(!prefix)
546da2e3ebdSchin 						sfputr(out,cp,' ');
547da2e3ebdSchin 					sfprintf(out,"%d ",nv_size(np));
548da2e3ebdSchin 				}
549da2e3ebdSchin 				break;
550da2e3ebdSchin 			}
551da2e3ebdSchin 		}
552*b30d1939SAndy Fiddaman #if SHOPT_FIXEDARRAY
553da2e3ebdSchin 		if(fp)
554da2e3ebdSchin 			outtype(np,fp,out,prefix);
555da2e3ebdSchin 		if(noname)
556da2e3ebdSchin 			return;
557*b30d1939SAndy Fiddaman 		if(fixed)
558*b30d1939SAndy Fiddaman 		{
559*b30d1939SAndy Fiddaman 			sfprintf(out,"%s",nv_name(np));
560*b30d1939SAndy Fiddaman 			nv_arrfixed(np,out,0,(char*)0);
561*b30d1939SAndy Fiddaman 			sfputc(out,';');
562*b30d1939SAndy Fiddaman 		}
563*b30d1939SAndy Fiddaman #endif /* SHOPT_FIXEDARRAY */
564da2e3ebdSchin 		sfputr(out,nv_name(np),'\n');
565da2e3ebdSchin 	}
566da2e3ebdSchin }
567da2e3ebdSchin 
568da2e3ebdSchin struct Walk
569da2e3ebdSchin {
570*b30d1939SAndy Fiddaman 	Shell_t	*shp;
571da2e3ebdSchin 	Sfio_t	*out;
572da2e3ebdSchin 	Dt_t	*root;
573da2e3ebdSchin 	int	noscope;
574da2e3ebdSchin 	int	indent;
5757c2fbfb3SApril Chin 	int	nofollow;
5767c2fbfb3SApril Chin 	int	array;
5777c2fbfb3SApril Chin 	int	flags;
578da2e3ebdSchin };
579da2e3ebdSchin 
nv_outnode(Namval_t * np,Sfio_t * out,int indent,int special)5807c2fbfb3SApril Chin void nv_outnode(Namval_t *np, Sfio_t* out, int indent, int special)
5817c2fbfb3SApril Chin {
5827c2fbfb3SApril Chin 	char		*fmtq,*ep,*xp;
5837c2fbfb3SApril Chin 	Namval_t	*mp;
5847c2fbfb3SApril Chin 	Namarr_t	*ap = nv_arrayptr(np);
585*b30d1939SAndy Fiddaman 	int		scan,tabs=0,c,more,associative = 0;
586*b30d1939SAndy Fiddaman 	int		saveI = Indent;
587*b30d1939SAndy Fiddaman 	Indent = indent;
5887c2fbfb3SApril Chin 	if(ap)
5897c2fbfb3SApril Chin 	{
5907c2fbfb3SApril Chin 		if(!(ap->nelem&ARRAY_SCAN))
5917c2fbfb3SApril Chin 			nv_putsub(np,NIL(char*),ARRAY_SCAN);
5927c2fbfb3SApril Chin 		sfputc(out,'(');
5937c2fbfb3SApril Chin 		if(indent>=0)
5947c2fbfb3SApril Chin 		{
5957c2fbfb3SApril Chin 			sfputc(out,'\n');
5967c2fbfb3SApril Chin 			tabs=1;
5977c2fbfb3SApril Chin 		}
5987c2fbfb3SApril Chin 		if(!(associative =(array_assoc(ap)!=0)))
5997c2fbfb3SApril Chin 		{
6007c2fbfb3SApril Chin 			if(array_elem(ap) < nv_aimax(np)+1)
6017c2fbfb3SApril Chin 				associative=1;
6027c2fbfb3SApril Chin 		}
6037c2fbfb3SApril Chin 	}
6047c2fbfb3SApril Chin 	mp = nv_opensub(np);
6057c2fbfb3SApril Chin 	while(1)
6067c2fbfb3SApril Chin 	{
607*b30d1939SAndy Fiddaman 		if(mp && special && nv_isvtree(mp) && !nv_isarray(mp))
6087c2fbfb3SApril Chin 		{
6097c2fbfb3SApril Chin 			if(!nv_nextsub(np))
6107c2fbfb3SApril Chin 				break;
6117c2fbfb3SApril Chin 			mp = nv_opensub(np);
6127c2fbfb3SApril Chin 			continue;
6137c2fbfb3SApril Chin 		}
6147c2fbfb3SApril Chin 		if(tabs)
615*b30d1939SAndy Fiddaman 			sfnputc(out,'\t',Indent = ++indent);
6167c2fbfb3SApril Chin 		tabs=0;
6177c2fbfb3SApril Chin 		if(associative||special)
6187c2fbfb3SApril Chin 		{
6197c2fbfb3SApril Chin 			if(!(fmtq = nv_getsub(np)))
6207c2fbfb3SApril Chin 				break;
6217c2fbfb3SApril Chin 			sfprintf(out,"[%s]",sh_fmtq(fmtq));
6227c2fbfb3SApril Chin 			sfputc(out,'=');
6237c2fbfb3SApril Chin 		}
624*b30d1939SAndy Fiddaman 		if(ap && !array_assoc(ap))
625*b30d1939SAndy Fiddaman 			scan = ap->nelem&ARRAY_SCAN;
6267c2fbfb3SApril Chin 		if(mp && nv_isarray(mp))
6277c2fbfb3SApril Chin 		{
628*b30d1939SAndy Fiddaman 			nv_outnode(mp, out, indent,0);
6297c2fbfb3SApril Chin 			if(indent>0)
6307c2fbfb3SApril Chin 				sfnputc(out,'\t',indent);
6317c2fbfb3SApril Chin 			sfputc(out,')');
6327c2fbfb3SApril Chin 			sfputc(out,indent>=0?'\n':' ');
633*b30d1939SAndy Fiddaman 			if(ap && !array_assoc(ap))
634*b30d1939SAndy Fiddaman 				ap->nelem |= scan;
6357c2fbfb3SApril Chin 			more = nv_nextsub(np);
6367c2fbfb3SApril Chin 			goto skip;
6377c2fbfb3SApril Chin 		}
6387c2fbfb3SApril Chin 		if(mp && nv_isvtree(mp))
639*b30d1939SAndy Fiddaman 		{
640*b30d1939SAndy Fiddaman 			if(indent<0)
641*b30d1939SAndy Fiddaman 				nv_onattr(mp,NV_EXPORT);
642*b30d1939SAndy Fiddaman 			nv_onattr(mp,NV_TABLE);
643*b30d1939SAndy Fiddaman 		}
6447c2fbfb3SApril Chin 		ep = nv_getval(mp?mp:np);
645*b30d1939SAndy Fiddaman 		if(ep==Empty && !(ap && ap->fixed))
64634f9b3eeSRoland Mainz 			ep = 0;
6477c2fbfb3SApril Chin 		xp = 0;
6487c2fbfb3SApril Chin 		if(!ap && nv_isattr(np,NV_INTEGER|NV_LJUST)==NV_LJUST)
6497c2fbfb3SApril Chin 		{
6507c2fbfb3SApril Chin 			xp = ep+nv_size(np);
6517c2fbfb3SApril Chin 			while(--xp>ep && *xp==' ');
6527c2fbfb3SApril Chin 			if(xp>ep || *xp!=' ')
6537c2fbfb3SApril Chin 				xp++;
6547c2fbfb3SApril Chin 			if(xp < (ep+nv_size(np)))
6557c2fbfb3SApril Chin 				*xp = 0;
6567c2fbfb3SApril Chin 			else
6577c2fbfb3SApril Chin 				xp = 0;
6587c2fbfb3SApril Chin 		}
6597c2fbfb3SApril Chin 		if(mp && nv_isvtree(mp))
6607c2fbfb3SApril Chin 			fmtq = ep;
6617c2fbfb3SApril Chin 		else if(!(fmtq = sh_fmtq(ep)))
6627c2fbfb3SApril Chin 			fmtq = "";
6637c2fbfb3SApril Chin 		else if(!associative && (ep=strchr(fmtq,'=')))
6647c2fbfb3SApril Chin 		{
6657c2fbfb3SApril Chin 			char *qp = strchr(fmtq,'\'');
6667c2fbfb3SApril Chin 			if(!qp || qp>ep)
6677c2fbfb3SApril Chin 			{
6687c2fbfb3SApril Chin 				sfwrite(out,fmtq,ep-fmtq);
6697c2fbfb3SApril Chin 				sfputc(out,'\\');
6707c2fbfb3SApril Chin 				fmtq = ep;
6717c2fbfb3SApril Chin 			}
6727c2fbfb3SApril Chin 		}
673*b30d1939SAndy Fiddaman 		if(ap && !array_assoc(ap))
674*b30d1939SAndy Fiddaman 			ap->nelem |= scan;
6757c2fbfb3SApril Chin 		more = nv_nextsub(np);
6767c2fbfb3SApril Chin 		c = '\n';
6777c2fbfb3SApril Chin 		if(indent<0)
6787c2fbfb3SApril Chin 		{
679*b30d1939SAndy Fiddaman 			c = indent < -1?-1:';';
6807c2fbfb3SApril Chin 			if(ap)
6817c2fbfb3SApril Chin 				c = more?' ':-1;
6827c2fbfb3SApril Chin 		}
6837c2fbfb3SApril Chin 		sfputr(out,fmtq,c);
6847c2fbfb3SApril Chin 		if(xp)
6857c2fbfb3SApril Chin 			*xp = ' ';
6867c2fbfb3SApril Chin 	skip:
6877c2fbfb3SApril Chin 		if(!more)
688*b30d1939SAndy Fiddaman 			break;
6897c2fbfb3SApril Chin 		mp = nv_opensub(np);
6907c2fbfb3SApril Chin 		if(indent>0 && !(mp && special && nv_isvtree(mp)))
6917c2fbfb3SApril Chin 			sfnputc(out,'\t',indent);
6927c2fbfb3SApril Chin 	}
693*b30d1939SAndy Fiddaman 	Indent = saveI;
6947c2fbfb3SApril Chin }
6957c2fbfb3SApril Chin 
outval(char * name,const char * vname,struct Walk * wp)696da2e3ebdSchin static void outval(char *name, const char *vname, struct Walk *wp)
697da2e3ebdSchin {
698*b30d1939SAndy Fiddaman 	register Namval_t *np, *nq, *last_table=wp->shp->last_table;
699da2e3ebdSchin         register Namfun_t *fp;
7007c2fbfb3SApril Chin 	int isarray=0, special=0,mode=0;
7017c2fbfb3SApril Chin 	if(*name!='.' || vname[strlen(vname)-1]==']')
7027c2fbfb3SApril Chin 		mode = NV_ARRAY;
7037c2fbfb3SApril Chin 	if(!(np=nv_open(vname,wp->root,mode|NV_VARNAME|NV_NOADD|NV_NOASSIGN|NV_NOFAIL|wp->noscope)))
704*b30d1939SAndy Fiddaman 	{
705*b30d1939SAndy Fiddaman 		wp->shp->last_table = last_table;
706da2e3ebdSchin 		return;
707*b30d1939SAndy Fiddaman 	}
708*b30d1939SAndy Fiddaman 	if(!wp->out)
709*b30d1939SAndy Fiddaman 		wp->shp->last_table = last_table;
7107c2fbfb3SApril Chin 	fp = nv_hasdisc(np,&treedisc);
7117c2fbfb3SApril Chin 	if(*name=='.')
712da2e3ebdSchin 	{
7137c2fbfb3SApril Chin 		if(nv_isattr(np,NV_BINARY))
7147c2fbfb3SApril Chin 			return;
7157c2fbfb3SApril Chin 		if(fp && np->nvalue.cp && np->nvalue.cp!=Empty)
7167c2fbfb3SApril Chin 		{
7177c2fbfb3SApril Chin 			nv_local = 1;
7187c2fbfb3SApril Chin 			fp = 0;
7197c2fbfb3SApril Chin 		}
7207c2fbfb3SApril Chin 		if(fp)
7217c2fbfb3SApril Chin 			return;
7227c2fbfb3SApril Chin 		if(nv_isarray(np))
7237c2fbfb3SApril Chin 			return;
7247c2fbfb3SApril Chin 	}
7257c2fbfb3SApril Chin 	if(!special && fp && !nv_isarray(np))
7267c2fbfb3SApril Chin 	{
7277c2fbfb3SApril Chin 		Namfun_t *xp;
728da2e3ebdSchin 		if(!wp->out)
729da2e3ebdSchin 		{
730da2e3ebdSchin 			fp = nv_stack(np,fp);
731da2e3ebdSchin 			if(fp = nv_stack(np,NIL(Namfun_t*)))
732da2e3ebdSchin 				free((void*)fp);
733da2e3ebdSchin 			np->nvfun = 0;
7347c2fbfb3SApril Chin 			return;
735da2e3ebdSchin 		}
7367c2fbfb3SApril Chin 		for(xp=fp->next; xp; xp = xp->next)
7377c2fbfb3SApril Chin 		{
7387c2fbfb3SApril Chin 			if(xp->disc && (xp->disc->getval || xp->disc->getnum))
7397c2fbfb3SApril Chin 				break;
7407c2fbfb3SApril Chin 		}
7417c2fbfb3SApril Chin 		if(!xp)
7427c2fbfb3SApril Chin 			return;
743da2e3ebdSchin 	}
74434f9b3eeSRoland Mainz 	if(nv_isnull(np) && !nv_isarray(np) && !nv_isattr(np,NV_INTEGER))
745da2e3ebdSchin 		return;
7467c2fbfb3SApril Chin 	if(special || (nv_isarray(np) && nv_arrayptr(np)))
747da2e3ebdSchin 	{
748da2e3ebdSchin 		isarray=1;
749da2e3ebdSchin 		if(array_elem(nv_arrayptr(np))==0)
750da2e3ebdSchin 			isarray=2;
751da2e3ebdSchin 		else
752da2e3ebdSchin 			nq = nv_putsub(np,NIL(char*),ARRAY_SCAN|(wp->out?ARRAY_NOCHILD:0));
753da2e3ebdSchin 	}
754da2e3ebdSchin 	if(!wp->out)
755da2e3ebdSchin 	{
756da2e3ebdSchin 		_nv_unset(np,NV_RDONLY);
757*b30d1939SAndy Fiddaman 		if(sh.subshell || (wp->flags!=NV_RDONLY) || nv_isattr(np,NV_MINIMAL|NV_NOFREE))
758*b30d1939SAndy Fiddaman 			wp->root = 0;
759*b30d1939SAndy Fiddaman 		nv_delete(np,wp->root,nv_isattr(np,NV_MINIMAL)?NV_NOFREE:0);
760da2e3ebdSchin 		return;
761da2e3ebdSchin 	}
762da2e3ebdSchin 	if(isarray==1 && !nq)
763da2e3ebdSchin 	{
7647c2fbfb3SApril Chin 		sfputc(wp->out,'(');
7657c2fbfb3SApril Chin 		if(wp->indent>=0)
7667c2fbfb3SApril Chin 			sfputc(wp->out,'\n');
7677c2fbfb3SApril Chin 		return;
768da2e3ebdSchin 	}
769*b30d1939SAndy Fiddaman 	if(isarray==0 && nv_isarray(np) && (nv_isnull(np)||np->nvalue.cp==Empty))  /* empty array */
7707c2fbfb3SApril Chin 		isarray = 2;
7717c2fbfb3SApril Chin 	special |= wp->nofollow;
7727c2fbfb3SApril Chin 	if(!wp->array && wp->indent>0)
773da2e3ebdSchin 		sfnputc(wp->out,'\t',wp->indent);
7747c2fbfb3SApril Chin 	if(!special)
7757c2fbfb3SApril Chin 	{
7767c2fbfb3SApril Chin 		if(*name!='.')
777*b30d1939SAndy Fiddaman 		{
778*b30d1939SAndy Fiddaman 			Namarr_t *ap;
7797c2fbfb3SApril Chin 			nv_attribute(np,wp->out,"typeset",'=');
780*b30d1939SAndy Fiddaman 			if((ap=nv_arrayptr(np)) && ap->fixed)
781*b30d1939SAndy Fiddaman 			{
782*b30d1939SAndy Fiddaman 				sfprintf(wp->out,"%s",name);
783*b30d1939SAndy Fiddaman 				nv_arrfixed(np,wp->out,0,(char*)0);
784*b30d1939SAndy Fiddaman 				sfputc(wp->out,';');
785*b30d1939SAndy Fiddaman 			}
786*b30d1939SAndy Fiddaman 		}
787da2e3ebdSchin 		nv_outname(wp->out,name,-1);
78834f9b3eeSRoland Mainz 		if((np->nvalue.cp && np->nvalue.cp!=Empty) || nv_isattr(np,~(NV_MINIMAL|NV_NOFREE)) || nv_isvtree(np))
789*b30d1939SAndy Fiddaman 			sfputc(wp->out,(isarray==2?(wp->indent>=0?'\n':';'):'='));
7907c2fbfb3SApril Chin 		if(isarray==2)
7917c2fbfb3SApril Chin 			return;
792da2e3ebdSchin 	}
7937c2fbfb3SApril Chin 	fp = np->nvfun;
7947c2fbfb3SApril Chin 	if(*name=='.' && !isarray)
7957c2fbfb3SApril Chin 		np->nvfun = 0;
7967c2fbfb3SApril Chin 	nv_outnode(np, wp->out, wp->indent, special);
7977c2fbfb3SApril Chin 	if(*name=='.' && !isarray)
7987c2fbfb3SApril Chin 		np->nvfun = fp;
7997c2fbfb3SApril Chin 	if(isarray && !special)
800da2e3ebdSchin 	{
8017c2fbfb3SApril Chin 		if(wp->indent>0)
802da2e3ebdSchin 		{
8037c2fbfb3SApril Chin 			sfnputc(wp->out,'\t',wp->indent);
8047c2fbfb3SApril Chin 			sfwrite(wp->out,")\n",2);
805da2e3ebdSchin 		}
806da2e3ebdSchin 		else
8077c2fbfb3SApril Chin 			sfwrite(wp->out,");",2);
808da2e3ebdSchin 	}
809da2e3ebdSchin }
810da2e3ebdSchin 
811da2e3ebdSchin /*
812da2e3ebdSchin  * format initialization list given a list of assignments <argp>
813da2e3ebdSchin  */
genvalue(char ** argv,const char * prefix,int n,struct Walk * wp)814da2e3ebdSchin static char **genvalue(char **argv, const char *prefix, int n, struct Walk *wp)
815da2e3ebdSchin {
816da2e3ebdSchin 	register char *cp,*nextcp,*arg;
817da2e3ebdSchin 	register Sfio_t *outfile = wp->out;
8187c2fbfb3SApril Chin 	register int m,r,l;
819da2e3ebdSchin 	if(n==0)
820da2e3ebdSchin 		m = strlen(prefix);
821da2e3ebdSchin 	else if(cp=nextdot(prefix))
822da2e3ebdSchin 		m = cp-prefix;
823da2e3ebdSchin 	else
824da2e3ebdSchin 		m = strlen(prefix)-1;
825da2e3ebdSchin 	m++;
8267c2fbfb3SApril Chin 	if(outfile && !wp->array)
827da2e3ebdSchin 	{
8287c2fbfb3SApril Chin 		sfputc(outfile,'(');
8297c2fbfb3SApril Chin 		if(wp->indent>=0)
8307c2fbfb3SApril Chin 		{
8317c2fbfb3SApril Chin 			wp->indent++;
8327c2fbfb3SApril Chin 			sfputc(outfile,'\n');
8337c2fbfb3SApril Chin 		}
834da2e3ebdSchin 	}
835da2e3ebdSchin 	for(; arg= *argv; argv++)
836da2e3ebdSchin 	{
837da2e3ebdSchin 		cp = arg + n;
838da2e3ebdSchin 		if(n==0 && cp[m-1]!='.')
839da2e3ebdSchin 			continue;
840da2e3ebdSchin 		if(n && cp[m-1]==0)
841da2e3ebdSchin 			break;
842da2e3ebdSchin 		if(n==0 || strncmp(arg,prefix-n,m+n)==0)
843da2e3ebdSchin 		{
844da2e3ebdSchin 			cp +=m;
845da2e3ebdSchin 			r = 0;
846da2e3ebdSchin 			if(*cp=='.')
847da2e3ebdSchin 				cp++,r++;
848*b30d1939SAndy Fiddaman 			if(wp->indent < 0 && argv[1]==0)
849*b30d1939SAndy Fiddaman 				wp->indent--;
850da2e3ebdSchin 			if(nextcp=nextdot(cp))
851da2e3ebdSchin 			{
852da2e3ebdSchin 				if(outfile)
853da2e3ebdSchin 				{
8547c2fbfb3SApril Chin 					Namval_t *np,*tp;
8557c2fbfb3SApril Chin 					*nextcp = 0;
8567c2fbfb3SApril Chin 					np=nv_open(arg,wp->root,NV_VARNAME|NV_NOADD|NV_NOASSIGN|NV_NOFAIL|wp->noscope);
8577c2fbfb3SApril Chin 					if(!np || (nv_isarray(np) && (!(tp=nv_opensub(np)) || !nv_isvtree(tp))))
8587c2fbfb3SApril Chin 					{
8597c2fbfb3SApril Chin 						*nextcp = '.';
8607c2fbfb3SApril Chin 						continue;
8617c2fbfb3SApril Chin 					}
8627c2fbfb3SApril Chin 					if(wp->indent>=0)
8637c2fbfb3SApril Chin 						sfnputc(outfile,'\t',wp->indent);
8647c2fbfb3SApril Chin 					if(*cp!='[' && (tp = nv_type(np)))
8657c2fbfb3SApril Chin 					{
8667c2fbfb3SApril Chin 						char *sp;
8677c2fbfb3SApril Chin 						if(sp = strrchr(tp->nvname,'.'))
8687c2fbfb3SApril Chin 							sp++;
8697c2fbfb3SApril Chin 						else
8707c2fbfb3SApril Chin 							sp = tp->nvname;
8717c2fbfb3SApril Chin 						sfputr(outfile,sp,' ');
8727c2fbfb3SApril Chin 					}
873da2e3ebdSchin 					nv_outname(outfile,cp,nextcp-cp);
874da2e3ebdSchin 					sfputc(outfile,'=');
8757c2fbfb3SApril Chin 					*nextcp = '.';
8767c2fbfb3SApril Chin 				}
8777c2fbfb3SApril Chin 				else
8787c2fbfb3SApril Chin 				{
8797c2fbfb3SApril Chin 					outval(cp,arg,wp);
8807c2fbfb3SApril Chin 					continue;
881da2e3ebdSchin 				}
882da2e3ebdSchin 				argv = genvalue(argv,cp,n+m+r,wp);
8837c2fbfb3SApril Chin 				if(wp->indent>=0)
884da2e3ebdSchin 					sfputc(outfile,'\n');
885da2e3ebdSchin 				if(*argv)
886da2e3ebdSchin 					continue;
887da2e3ebdSchin 				break;
888da2e3ebdSchin 			}
8897c2fbfb3SApril Chin 			else if(outfile && !wp->nofollow && argv[1] && memcmp(arg,argv[1],l=strlen(arg))==0 && argv[1][l]=='[')
890da2e3ebdSchin 			{
89134f9b3eeSRoland Mainz 				int	k=1;
89234f9b3eeSRoland Mainz 				Namarr_t *ap=0;
893da2e3ebdSchin 				Namval_t *np = nv_open(arg,wp->root,NV_VARNAME|NV_NOADD|NV_NOASSIGN|wp->noscope);
894da2e3ebdSchin 				if(!np)
895da2e3ebdSchin 					continue;
89634f9b3eeSRoland Mainz 				if((wp->array = nv_isarray(np)) && (ap=nv_arrayptr(np)))
89734f9b3eeSRoland Mainz 					k = array_elem(ap);
89834f9b3eeSRoland Mainz 
8997c2fbfb3SApril Chin 				if(wp->indent>0)
9007c2fbfb3SApril Chin 					sfnputc(outfile,'\t',wp->indent);
901da2e3ebdSchin 				nv_attribute(np,outfile,"typeset",1);
902da2e3ebdSchin 				nv_close(np);
90334f9b3eeSRoland Mainz 				sfputr(outfile,arg+m+r+(n?n:0),(k?'=':'\n'));
90434f9b3eeSRoland Mainz 				if(!k)
90534f9b3eeSRoland Mainz 				{
90634f9b3eeSRoland Mainz 					wp->array=0;
90734f9b3eeSRoland Mainz 					continue;
90834f9b3eeSRoland Mainz 				}
9097c2fbfb3SApril Chin 				wp->nofollow=1;
9107c2fbfb3SApril Chin 				argv = genvalue(argv,cp,cp-arg ,wp);
9117c2fbfb3SApril Chin 				sfputc(outfile,wp->indent<0?';':'\n');
912da2e3ebdSchin 			}
913*b30d1939SAndy Fiddaman 			else if(outfile && *cp=='[' && cp[-1]!='.')
914da2e3ebdSchin 			{
915*b30d1939SAndy Fiddaman 				/* skip multi-dimensional arrays */
916*b30d1939SAndy Fiddaman 				if(*nv_endsubscript((Namval_t*)0,cp,0)=='[')
917*b30d1939SAndy Fiddaman 					continue;
918*b30d1939SAndy Fiddaman 				if(wp->indent>0)
9197c2fbfb3SApril Chin 					sfnputc(outfile,'\t',wp->indent);
920*b30d1939SAndy Fiddaman 				if(cp[-1]=='.')
921*b30d1939SAndy Fiddaman 					cp--;
922da2e3ebdSchin 				sfputr(outfile,cp,'=');
923*b30d1939SAndy Fiddaman 				if(*cp=='.')
924*b30d1939SAndy Fiddaman 					cp++;
925da2e3ebdSchin 				argv = genvalue(++argv,cp,cp-arg ,wp);
926*b30d1939SAndy Fiddaman 				sfputc(outfile,wp->indent>0?'\n':';');
927da2e3ebdSchin 			}
928da2e3ebdSchin 			else
9297c2fbfb3SApril Chin 			{
930da2e3ebdSchin 				outval(cp,arg,wp);
9317c2fbfb3SApril Chin 				if(wp->array)
9327c2fbfb3SApril Chin 				{
9337c2fbfb3SApril Chin 					if(wp->indent>=0)
9347c2fbfb3SApril Chin 						wp->indent++;
9357c2fbfb3SApril Chin 					else
9367c2fbfb3SApril Chin 						sfputc(outfile,' ');
9377c2fbfb3SApril Chin 					wp->array = 0;
9387c2fbfb3SApril Chin 				}
9397c2fbfb3SApril Chin 			}
940da2e3ebdSchin 		}
941da2e3ebdSchin 		else
942da2e3ebdSchin 			break;
9437c2fbfb3SApril Chin 		wp->nofollow = 0;
944da2e3ebdSchin 	}
9457c2fbfb3SApril Chin 	wp->array = 0;
946da2e3ebdSchin 	if(outfile)
947da2e3ebdSchin 	{
948da2e3ebdSchin 		int c = prefix[m-1];
949da2e3ebdSchin 		cp = (char*)prefix;
950da2e3ebdSchin 		if(c=='.')
951da2e3ebdSchin 			cp[m-1] = 0;
952da2e3ebdSchin 		outval(".",prefix-n,wp);
953da2e3ebdSchin 		if(c=='.')
954da2e3ebdSchin 			cp[m-1] = c;
9557c2fbfb3SApril Chin 		if(wp->indent>0)
9567c2fbfb3SApril Chin 			sfnputc(outfile,'\t',--wp->indent);
957da2e3ebdSchin 		sfputc(outfile,')');
958da2e3ebdSchin 	}
959da2e3ebdSchin 	return(--argv);
960da2e3ebdSchin }
961da2e3ebdSchin 
962da2e3ebdSchin /*
963da2e3ebdSchin  * walk the virtual tree and print or delete name-value pairs
964da2e3ebdSchin  */
walk_tree(register Namval_t * np,Namval_t * xp,int flags)9657c2fbfb3SApril Chin static char *walk_tree(register Namval_t *np, Namval_t *xp, int flags)
966da2e3ebdSchin {
967da2e3ebdSchin 	static Sfio_t *out;
968da2e3ebdSchin 	struct Walk walk;
969da2e3ebdSchin 	Sfio_t *outfile;
970*b30d1939SAndy Fiddaman 	Sfoff_t	off = 0;
9717c2fbfb3SApril Chin 	int len, savtop = staktell();
972da2e3ebdSchin 	char *savptr = stakfreeze(0);
973da2e3ebdSchin 	register struct argnod *ap=0;
974da2e3ebdSchin 	struct argnod *arglist=0;
975da2e3ebdSchin 	char *name,*cp, **argv;
976da2e3ebdSchin 	char *subscript=0;
977da2e3ebdSchin 	void *dir;
9787c2fbfb3SApril Chin 	int n=0, noscope=(flags&NV_NOSCOPE);
9797c2fbfb3SApril Chin 	Namarr_t *arp = nv_arrayptr(np);
9807c2fbfb3SApril Chin 	Dt_t	*save_tree = sh.var_tree;
9817c2fbfb3SApril Chin 	Namval_t	*mp=0;
9827c2fbfb3SApril Chin 	Shell_t		*shp = sh_getinterp();
9837c2fbfb3SApril Chin 	char		*xpname = xp?stakcopy(nv_name(xp)):0;
984*b30d1939SAndy Fiddaman 	walk.shp = shp;
9857c2fbfb3SApril Chin 	if(xp)
9867c2fbfb3SApril Chin 	{
9877c2fbfb3SApril Chin 		shp->last_root = shp->prev_root;
9887c2fbfb3SApril Chin 		shp->last_table = shp->prev_table;
9897c2fbfb3SApril Chin 	}
9907c2fbfb3SApril Chin 	if(shp->last_table)
9917c2fbfb3SApril Chin 		shp->last_root = nv_dict(shp->last_table);
9927c2fbfb3SApril Chin 	if(shp->last_root)
9937c2fbfb3SApril Chin 		shp->var_tree = shp->last_root;
994da2e3ebdSchin 	stakputs(nv_name(np));
9957c2fbfb3SApril Chin 	if(arp && !(arp->nelem&ARRAY_SCAN) && (subscript = nv_getsub(np)))
996da2e3ebdSchin 	{
9977c2fbfb3SApril Chin 		mp = nv_opensub(np);
998da2e3ebdSchin 		stakputc('[');
999da2e3ebdSchin 		stakputs(subscript);
1000da2e3ebdSchin 		stakputc(']');
1001da2e3ebdSchin 		stakputc('.');
1002da2e3ebdSchin 	}
10037c2fbfb3SApril Chin 	else if(*stakptr(staktell()-1) == ']')
10047c2fbfb3SApril Chin 		mp = np;
1005da2e3ebdSchin 	name = stakfreeze(1);
10067c2fbfb3SApril Chin 	len = strlen(name);
10077c2fbfb3SApril Chin 	shp->last_root = 0;
10087c2fbfb3SApril Chin 	dir = nv_diropen(mp,name);
10097c2fbfb3SApril Chin 	walk.root = shp->last_root?shp->last_root:shp->var_tree;
1010da2e3ebdSchin 	if(subscript)
1011da2e3ebdSchin 		name[strlen(name)-1] = 0;
1012da2e3ebdSchin 	while(cp = nv_dirnext(dir))
1013da2e3ebdSchin 	{
10147c2fbfb3SApril Chin 		if(cp[len]!='.')
10157c2fbfb3SApril Chin 			continue;
10167c2fbfb3SApril Chin 		if(xp)
10177c2fbfb3SApril Chin 		{
10187c2fbfb3SApril Chin 			Dt_t		*dp = shp->var_tree;
10197c2fbfb3SApril Chin 			Namval_t	*nq, *mq;
10207c2fbfb3SApril Chin 			if(strlen(cp)<=len)
10217c2fbfb3SApril Chin 				continue;
10227c2fbfb3SApril Chin 			nq = nv_open(cp,walk.root,NV_VARNAME|NV_NOADD|NV_NOASSIGN|NV_NOFAIL);
10237c2fbfb3SApril Chin 			if(!nq && (flags&NV_MOVE))
10247c2fbfb3SApril Chin 				nq = nv_search(cp,walk.root,NV_NOADD);
10257c2fbfb3SApril Chin 			stakseek(0);
10267c2fbfb3SApril Chin 			stakputs(xpname);
10277c2fbfb3SApril Chin 			stakputs(cp+len);
10287c2fbfb3SApril Chin 			stakputc(0);
10297c2fbfb3SApril Chin 			shp->var_tree = save_tree;
1030*b30d1939SAndy Fiddaman 			mq = nv_open(stakptr(0),shp->prev_root,NV_VARNAME|NV_NOASSIGN|NV_NOFAIL);
10317c2fbfb3SApril Chin 			shp->var_tree = dp;
10327c2fbfb3SApril Chin 			if(nq && mq)
10337c2fbfb3SApril Chin 			{
10347c2fbfb3SApril Chin 				nv_clone(nq,mq,flags|NV_RAW);
10357c2fbfb3SApril Chin 				if(flags&NV_MOVE)
10367c2fbfb3SApril Chin 					nv_delete(nq,walk.root,0);
10377c2fbfb3SApril Chin 			}
10387c2fbfb3SApril Chin 			continue;
10397c2fbfb3SApril Chin 		}
1040da2e3ebdSchin 		stakseek(ARGVAL);
1041da2e3ebdSchin 		stakputs(cp);
1042da2e3ebdSchin 		ap = (struct argnod*)stakfreeze(1);
1043da2e3ebdSchin 		ap->argflag = ARG_RAW;
1044da2e3ebdSchin 		ap->argchn.ap = arglist;
1045da2e3ebdSchin 		n++;
1046da2e3ebdSchin 		arglist = ap;
1047da2e3ebdSchin 	}
10487c2fbfb3SApril Chin 	nv_dirclose(dir);
10497c2fbfb3SApril Chin 	if(xp)
10507c2fbfb3SApril Chin 	{
10517c2fbfb3SApril Chin 		shp->var_tree = save_tree;
10527c2fbfb3SApril Chin 		return((char*)0);
10537c2fbfb3SApril Chin 	}
1054da2e3ebdSchin 	argv = (char**)stakalloc((n+1)*sizeof(char*));
1055da2e3ebdSchin 	argv += n;
1056da2e3ebdSchin 	*argv = 0;
1057da2e3ebdSchin 	for(; ap; ap=ap->argchn.ap)
1058da2e3ebdSchin 		*--argv = ap->argval;
10597c2fbfb3SApril Chin 	if(flags&1)
1060da2e3ebdSchin 		outfile = 0;
1061da2e3ebdSchin 	else if(!(outfile=out))
1062da2e3ebdSchin 		outfile = out =  sfnew((Sfio_t*)0,(char*)0,-1,-1,SF_WRITE|SF_STRING);
1063*b30d1939SAndy Fiddaman 	else if(flags&NV_TABLE)
1064*b30d1939SAndy Fiddaman 		off = sftell(outfile);
1065da2e3ebdSchin 	else
1066da2e3ebdSchin 		sfseek(outfile,0L,SEEK_SET);
1067da2e3ebdSchin 	walk.out = outfile;
1068*b30d1939SAndy Fiddaman 	walk.indent = (flags&NV_EXPORT)?-1:Indent;
10697c2fbfb3SApril Chin 	walk.nofollow = 0;
1070da2e3ebdSchin 	walk.noscope = noscope;
10717c2fbfb3SApril Chin 	walk.array = 0;
10727c2fbfb3SApril Chin 	walk.flags = flags;
1073da2e3ebdSchin 	genvalue(argv,name,0,&walk);
1074da2e3ebdSchin 	stakset(savptr,savtop);
10757c2fbfb3SApril Chin 	shp->var_tree = save_tree;
1076da2e3ebdSchin 	if(!outfile)
1077da2e3ebdSchin 		return((char*)0);
1078da2e3ebdSchin 	sfputc(out,0);
1079*b30d1939SAndy Fiddaman 	sfseek(out,off,SEEK_SET);
1080*b30d1939SAndy Fiddaman 	return((char*)out->_data+off);
1081da2e3ebdSchin }
1082da2e3ebdSchin 
nv_isvtree(Namval_t * np)10837c2fbfb3SApril Chin Namfun_t *nv_isvtree(Namval_t *np)
10847c2fbfb3SApril Chin {
10857c2fbfb3SApril Chin 	if(np)
10867c2fbfb3SApril Chin 		return(nv_hasdisc(np,&treedisc));
10877c2fbfb3SApril Chin 	return(0);
10887c2fbfb3SApril Chin }
10897c2fbfb3SApril Chin 
1090da2e3ebdSchin /*
1091da2e3ebdSchin  * get discipline for compound initializations
1092da2e3ebdSchin  */
nv_getvtree(register Namval_t * np,Namfun_t * fp)1093da2e3ebdSchin char *nv_getvtree(register Namval_t *np, Namfun_t *fp)
1094da2e3ebdSchin {
1095*b30d1939SAndy Fiddaman 	int flags=0, dsize=fp?fp->dsize:0;
10967c2fbfb3SApril Chin 	for(; fp && fp->next; fp=fp->next)
10977c2fbfb3SApril Chin 	{
10987c2fbfb3SApril Chin 		if(fp->next->disc && (fp->next->disc->getnum || fp->next->disc->getval))
10997c2fbfb3SApril Chin 			return(nv_getv(np,fp));
11007c2fbfb3SApril Chin 	}
11017c2fbfb3SApril Chin 	if(nv_isattr(np,NV_BINARY) &&  !nv_isattr(np,NV_RAW))
1102da2e3ebdSchin 		return(nv_getv(np,fp));
11037c2fbfb3SApril Chin 	if(nv_isattr(np,NV_ARRAY) && !nv_type(np) && nv_arraychild(np,(Namval_t*)0,0)==np)
1104da2e3ebdSchin 		return(nv_getv(np,fp));
11057c2fbfb3SApril Chin 	if(flags = nv_isattr(np,NV_EXPORT))
11067c2fbfb3SApril Chin 		nv_offattr(np,NV_EXPORT);
1107*b30d1939SAndy Fiddaman 	if(flags |= nv_isattr(np,NV_TABLE))
1108*b30d1939SAndy Fiddaman 		nv_offattr(np,NV_TABLE);
11093e14f97fSRoger A. Faulkner 	if(dsize && (flags&NV_EXPORT))
11103e14f97fSRoger A. Faulkner 		return("()");
11117c2fbfb3SApril Chin 	return(walk_tree(np,(Namval_t*)0,flags));
1112da2e3ebdSchin }
1113da2e3ebdSchin 
1114da2e3ebdSchin /*
1115da2e3ebdSchin  * put discipline for compound initializations
1116da2e3ebdSchin  */
put_tree(register Namval_t * np,const char * val,int flags,Namfun_t * fp)1117da2e3ebdSchin static void put_tree(register Namval_t *np, const char *val, int flags,Namfun_t *fp)
1118da2e3ebdSchin {
1119da2e3ebdSchin 	struct Namarray *ap;
1120da2e3ebdSchin 	int nleft = 0;
11217c2fbfb3SApril Chin 	if(!val && !fp->next && nv_isattr(np,NV_NOFREE))
11227c2fbfb3SApril Chin 		return;
11237c2fbfb3SApril Chin 	if(!nv_isattr(np,(NV_INTEGER|NV_BINARY)))
11247c2fbfb3SApril Chin 	{
11257c2fbfb3SApril Chin 		Shell_t		*shp = sh_getinterp();
11267c2fbfb3SApril Chin 		Namval_t	*last_table = shp->last_table;
11277c2fbfb3SApril Chin 		Dt_t		*last_root = shp->last_root;
112834f9b3eeSRoland Mainz 		Namval_t 	*mp = val?nv_open(val,shp->var_tree,NV_VARNAME|NV_NOADD|NV_NOASSIGN|NV_ARRAY|NV_NOFAIL):0;
11297c2fbfb3SApril Chin 		if(mp && nv_isvtree(mp))
11307c2fbfb3SApril Chin 		{
11317c2fbfb3SApril Chin 			shp->prev_table = shp->last_table;
11327c2fbfb3SApril Chin 			shp->prev_root = shp->last_root;
11337c2fbfb3SApril Chin 			shp->last_table = last_table;
11347c2fbfb3SApril Chin 			shp->last_root = last_root;
11357c2fbfb3SApril Chin 			if(!(flags&NV_APPEND))
11367c2fbfb3SApril Chin 				walk_tree(np,(Namval_t*)0,(flags&NV_NOSCOPE)|1);
11377c2fbfb3SApril Chin 			nv_clone(mp,np,NV_COMVAR);
11387c2fbfb3SApril Chin 			return;
11397c2fbfb3SApril Chin 		}
11407c2fbfb3SApril Chin 		walk_tree(np,(Namval_t*)0,(flags&NV_NOSCOPE)|1);
11417c2fbfb3SApril Chin 	}
1142da2e3ebdSchin 	nv_putv(np, val, flags,fp);
11437c2fbfb3SApril Chin 	if(val && nv_isattr(np,(NV_INTEGER|NV_BINARY)))
1144da2e3ebdSchin 		return;
1145da2e3ebdSchin 	if(ap= nv_arrayptr(np))
1146da2e3ebdSchin 		nleft = array_elem(ap);
1147da2e3ebdSchin 	if(nleft==0)
1148da2e3ebdSchin 	{
1149da2e3ebdSchin 		fp = nv_stack(np,fp);
1150da2e3ebdSchin 		if(fp = nv_stack(np,NIL(Namfun_t*)))
1151da2e3ebdSchin 			free((void*)fp);
1152da2e3ebdSchin 	}
1153da2e3ebdSchin }
1154da2e3ebdSchin 
1155da2e3ebdSchin /*
1156da2e3ebdSchin  * Insert discipline to cause $x to print current tree
1157da2e3ebdSchin  */
nv_setvtree(register Namval_t * np)1158da2e3ebdSchin void nv_setvtree(register Namval_t *np)
1159da2e3ebdSchin {
1160da2e3ebdSchin 	register Namfun_t *nfp;
11617c2fbfb3SApril Chin 	if(sh.subshell)
11627c2fbfb3SApril Chin 		sh_assignok(np,1);
1163da2e3ebdSchin 	if(nv_hasdisc(np, &treedisc))
1164da2e3ebdSchin 		return;
1165da2e3ebdSchin 	nfp = newof(NIL(void*),Namfun_t,1,0);
1166da2e3ebdSchin 	nfp->disc = &treedisc;
11673e14f97fSRoger A. Faulkner 	nfp->dsize = sizeof(Namfun_t);
1168da2e3ebdSchin 	nv_stack(np, nfp);
1169da2e3ebdSchin }
1170da2e3ebdSchin 
1171