xref: /illumos-gate/usr/src/contrib/ast/src/cmd/ksh93/sh/nvdisc.c (revision 5b8dd251e631f58e50129eeb313228a0646df3fe)
1b30d1939SAndy Fiddaman /***********************************************************************
2b30d1939SAndy Fiddaman *                                                                      *
3b30d1939SAndy Fiddaman *               This software is part of the ast package               *
4b30d1939SAndy Fiddaman *          Copyright (c) 1982-2012 AT&T Intellectual Property          *
5b30d1939SAndy Fiddaman *                      and is licensed under the                       *
6b30d1939SAndy Fiddaman *                 Eclipse Public License, Version 1.0                  *
7b30d1939SAndy Fiddaman *                    by AT&T Intellectual Property                     *
8b30d1939SAndy Fiddaman *                                                                      *
9b30d1939SAndy Fiddaman *                A copy of the License is available at                 *
10b30d1939SAndy Fiddaman *          http://www.eclipse.org/org/documents/epl-v10.html           *
11b30d1939SAndy Fiddaman *         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
12b30d1939SAndy Fiddaman *                                                                      *
13b30d1939SAndy Fiddaman *              Information and Software Systems Research               *
14b30d1939SAndy Fiddaman *                            AT&T Research                             *
15b30d1939SAndy Fiddaman *                           Florham Park NJ                            *
16b30d1939SAndy Fiddaman *                                                                      *
17b30d1939SAndy Fiddaman *                  David Korn <dgk@research.att.com>                   *
18b30d1939SAndy Fiddaman *                                                                      *
19b30d1939SAndy Fiddaman ***********************************************************************/
20b30d1939SAndy Fiddaman #pragma prototyped
21b30d1939SAndy Fiddaman /*
22b30d1939SAndy Fiddaman  * AT&T Labs
23b30d1939SAndy Fiddaman  *
24b30d1939SAndy Fiddaman  */
25b30d1939SAndy Fiddaman 
26b30d1939SAndy Fiddaman #include        "defs.h"
27b30d1939SAndy Fiddaman #include        "variables.h"
28b30d1939SAndy Fiddaman #include        "builtins.h"
29b30d1939SAndy Fiddaman #include        "path.h"
30b30d1939SAndy Fiddaman 
31b30d1939SAndy Fiddaman static void assign(Namval_t*,const char*,int,Namfun_t*);
32b30d1939SAndy Fiddaman 
nv_compare(Dt_t * dict,Void_t * sp,Void_t * dp,Dtdisc_t * disc)33b30d1939SAndy Fiddaman int nv_compare(Dt_t* dict, Void_t *sp, Void_t *dp, Dtdisc_t *disc)
34b30d1939SAndy Fiddaman {
35b30d1939SAndy Fiddaman 	if(sp==dp)
36b30d1939SAndy Fiddaman 		return(0);
37b30d1939SAndy Fiddaman 	return(strcmp((char*)sp,(char*)dp));
38b30d1939SAndy Fiddaman }
39b30d1939SAndy Fiddaman 
40b30d1939SAndy Fiddaman /*
41b30d1939SAndy Fiddaman  * call the next getval function in the chain
42b30d1939SAndy Fiddaman  */
nv_getv(Namval_t * np,register Namfun_t * nfp)43b30d1939SAndy Fiddaman char *nv_getv(Namval_t *np, register Namfun_t *nfp)
44b30d1939SAndy Fiddaman {
45b30d1939SAndy Fiddaman 	register Namfun_t	*fp;
46b30d1939SAndy Fiddaman 	register char *cp;
47b30d1939SAndy Fiddaman 	if((fp = nfp) != NIL(Namfun_t*) && !nv_local)
48b30d1939SAndy Fiddaman 		fp = nfp = nfp->next;
49b30d1939SAndy Fiddaman 	nv_local=0;
50b30d1939SAndy Fiddaman 	for(; fp; fp=fp->next)
51b30d1939SAndy Fiddaman 	{
52b30d1939SAndy Fiddaman 		if(!fp->disc || (!fp->disc->getnum && !fp->disc->getval))
53b30d1939SAndy Fiddaman 			continue;
54b30d1939SAndy Fiddaman 		if(!nv_isattr(np,NV_NODISC) || fp==(Namfun_t*)nv_arrayptr(np))
55b30d1939SAndy Fiddaman 			break;
56b30d1939SAndy Fiddaman 	}
57b30d1939SAndy Fiddaman 	if(fp && fp->disc->getval)
58b30d1939SAndy Fiddaman 		cp = (*fp->disc->getval)(np,fp);
59b30d1939SAndy Fiddaman 	else if(fp && fp->disc->getnum)
60b30d1939SAndy Fiddaman 	{
61b30d1939SAndy Fiddaman 		sfprintf(sh.strbuf,"%.*Lg",12,(*fp->disc->getnum)(np,fp));
62b30d1939SAndy Fiddaman 		cp = sfstruse(sh.strbuf);
63b30d1939SAndy Fiddaman 	}
64b30d1939SAndy Fiddaman 	else
65b30d1939SAndy Fiddaman 	{
66b30d1939SAndy Fiddaman 		nv_local=1;
67b30d1939SAndy Fiddaman 		cp = nv_getval(np);
68b30d1939SAndy Fiddaman 	}
69b30d1939SAndy Fiddaman 	return(cp);
70b30d1939SAndy Fiddaman }
71b30d1939SAndy Fiddaman 
72b30d1939SAndy Fiddaman /*
73b30d1939SAndy Fiddaman  * call the next getnum function in the chain
74b30d1939SAndy Fiddaman  */
nv_getn(Namval_t * np,register Namfun_t * nfp)75b30d1939SAndy Fiddaman Sfdouble_t nv_getn(Namval_t *np, register Namfun_t *nfp)
76b30d1939SAndy Fiddaman {
77b30d1939SAndy Fiddaman 	register Namfun_t	*fp;
78b30d1939SAndy Fiddaman 	register Sfdouble_t	d=0;
79b30d1939SAndy Fiddaman 	Shell_t			*shp = sh_getinterp();
80b30d1939SAndy Fiddaman 	char *str;
81b30d1939SAndy Fiddaman 	if((fp = nfp) != NIL(Namfun_t*) && !nv_local)
82b30d1939SAndy Fiddaman 		fp = nfp = nfp->next;
83b30d1939SAndy Fiddaman 	nv_local=0;
84b30d1939SAndy Fiddaman 	for(; fp; fp=fp->next)
85b30d1939SAndy Fiddaman 	{
86b30d1939SAndy Fiddaman 		if(!fp->disc || (!fp->disc->getnum && !fp->disc->getval))
87b30d1939SAndy Fiddaman 			continue;
88b30d1939SAndy Fiddaman 		if(!fp->disc->getnum && nv_isattr(np,NV_INTEGER))
89b30d1939SAndy Fiddaman 			continue;
90b30d1939SAndy Fiddaman 		if(!nv_isattr(np,NV_NODISC) || fp==(Namfun_t*)nv_arrayptr(np))
91b30d1939SAndy Fiddaman 			break;
92b30d1939SAndy Fiddaman 	}
93b30d1939SAndy Fiddaman 	if(fp && fp->disc && fp->disc->getnum)
94b30d1939SAndy Fiddaman 		d = (*fp->disc->getnum)(np,fp);
95b30d1939SAndy Fiddaman 	else if(nv_isattr(np,NV_INTEGER))
96b30d1939SAndy Fiddaman 	{
97b30d1939SAndy Fiddaman 		nv_local = 1;
98b30d1939SAndy Fiddaman 		d =  nv_getnum(np);
99b30d1939SAndy Fiddaman 	}
100b30d1939SAndy Fiddaman 	else
101b30d1939SAndy Fiddaman 	{
102b30d1939SAndy Fiddaman 		if(fp && fp->disc && fp->disc->getval)
103b30d1939SAndy Fiddaman 			str = (*fp->disc->getval)(np,fp);
104b30d1939SAndy Fiddaman 		else
105b30d1939SAndy Fiddaman 			str = nv_getv(np,fp?fp:nfp);
106b30d1939SAndy Fiddaman 		if(str && *str)
107b30d1939SAndy Fiddaman 		{
108b30d1939SAndy Fiddaman 			if(nv_isattr(np,NV_LJUST|NV_RJUST) || (*str=='0' && !(str[1]=='x'||str[1]=='X')))
109b30d1939SAndy Fiddaman 			{
110b30d1939SAndy Fiddaman 				while(*str=='0')
111b30d1939SAndy Fiddaman 					str++;
112b30d1939SAndy Fiddaman 			}
113b30d1939SAndy Fiddaman 			d = sh_arith(shp,str);
114b30d1939SAndy Fiddaman 		}
115b30d1939SAndy Fiddaman 	}
116b30d1939SAndy Fiddaman 	return(d);
117b30d1939SAndy Fiddaman }
118b30d1939SAndy Fiddaman 
119b30d1939SAndy Fiddaman /*
120b30d1939SAndy Fiddaman  * call the next assign function in the chain
121b30d1939SAndy Fiddaman  */
nv_putv(Namval_t * np,const char * value,int flags,register Namfun_t * nfp)122b30d1939SAndy Fiddaman void nv_putv(Namval_t *np, const char *value, int flags, register Namfun_t *nfp)
123b30d1939SAndy Fiddaman {
124b30d1939SAndy Fiddaman 	register Namfun_t	*fp, *fpnext;
125b30d1939SAndy Fiddaman 	Namarr_t		*ap;
126b30d1939SAndy Fiddaman 	if((fp=nfp) != NIL(Namfun_t*) && !nv_local)
127b30d1939SAndy Fiddaman 		fp = nfp = nfp->next;
128b30d1939SAndy Fiddaman 	nv_local=0;
129b30d1939SAndy Fiddaman 	if(flags&NV_NODISC)
130b30d1939SAndy Fiddaman 		fp = 0;
131b30d1939SAndy Fiddaman 	for(; fp; fp=fpnext)
132b30d1939SAndy Fiddaman 	{
133b30d1939SAndy Fiddaman 		fpnext = fp->next;
134b30d1939SAndy Fiddaman 		if(!fp->disc || !fp->disc->putval)
135b30d1939SAndy Fiddaman 		{
136b30d1939SAndy Fiddaman 			if(!value && (!(ap=nv_arrayptr(np)) || ap->nelem==0))
137b30d1939SAndy Fiddaman 			{
138b30d1939SAndy Fiddaman 				if(fp->disc || !(fp->nofree&1))
139b30d1939SAndy Fiddaman 					nv_disc(np,fp,NV_POP);
140b30d1939SAndy Fiddaman 				if(!(fp->nofree&1))
141b30d1939SAndy Fiddaman 					free((void*)fp);
142b30d1939SAndy Fiddaman 			}
143b30d1939SAndy Fiddaman 			continue;
144b30d1939SAndy Fiddaman 		}
145b30d1939SAndy Fiddaman 		if(!nv_isattr(np,NV_NODISC) || fp==(Namfun_t*)nv_arrayptr(np))
146b30d1939SAndy Fiddaman 			break;
147b30d1939SAndy Fiddaman 	}
148b30d1939SAndy Fiddaman 	if(!value && (flags&NV_TYPE) && fp && fp->disc->putval==assign)
149b30d1939SAndy Fiddaman 		fp = 0;
150b30d1939SAndy Fiddaman 	if(fp && fp->disc->putval)
151b30d1939SAndy Fiddaman 		(*fp->disc->putval)(np,value, flags, fp);
152b30d1939SAndy Fiddaman 	else
153b30d1939SAndy Fiddaman 	{
154b30d1939SAndy Fiddaman 		nv_local=1;
155b30d1939SAndy Fiddaman 		if(value)
156b30d1939SAndy Fiddaman 			nv_putval(np, value, flags);
157b30d1939SAndy Fiddaman 		else
158b30d1939SAndy Fiddaman 			_nv_unset(np, flags&(NV_RDONLY|NV_EXPORT));
159b30d1939SAndy Fiddaman 	}
160b30d1939SAndy Fiddaman }
161b30d1939SAndy Fiddaman 
162b30d1939SAndy Fiddaman #define	LOOKUPS		0
163b30d1939SAndy Fiddaman #define	ASSIGN		1
164b30d1939SAndy Fiddaman #define	APPEND		2
165b30d1939SAndy Fiddaman #define	UNASSIGN	3
166b30d1939SAndy Fiddaman #define	LOOKUPN		4
167b30d1939SAndy Fiddaman #define BLOCKED		((Namval_t*)&nv_local)
168b30d1939SAndy Fiddaman 
169b30d1939SAndy Fiddaman struct	vardisc
170b30d1939SAndy Fiddaman {
171b30d1939SAndy Fiddaman 	Namfun_t	fun;
172b30d1939SAndy Fiddaman 	Namval_t	*disc[5];
173b30d1939SAndy Fiddaman };
174b30d1939SAndy Fiddaman 
175b30d1939SAndy Fiddaman struct blocked
176b30d1939SAndy Fiddaman {
177b30d1939SAndy Fiddaman 	struct blocked	*next;
178b30d1939SAndy Fiddaman 	Namval_t	*np;
179b30d1939SAndy Fiddaman 	int		flags;
180b30d1939SAndy Fiddaman 	void		*sub;
181b30d1939SAndy Fiddaman 	int		isub;
182b30d1939SAndy Fiddaman };
183b30d1939SAndy Fiddaman 
184b30d1939SAndy Fiddaman static struct blocked	*blist;
185b30d1939SAndy Fiddaman 
186b30d1939SAndy Fiddaman #define isblocked(bp,type)	((bp)->flags & (1<<(type)))
187b30d1939SAndy Fiddaman #define block(bp,type)		((bp)->flags |= (1<<(type)))
188b30d1939SAndy Fiddaman #define unblock(bp,type)	((bp)->flags &= ~(1<<(type)))
189b30d1939SAndy Fiddaman 
190b30d1939SAndy Fiddaman /*
191b30d1939SAndy Fiddaman  * returns pointer to blocking structure
192b30d1939SAndy Fiddaman  */
block_info(Namval_t * np,struct blocked * pp)193b30d1939SAndy Fiddaman static struct blocked *block_info(Namval_t *np, struct blocked *pp)
194b30d1939SAndy Fiddaman {
195b30d1939SAndy Fiddaman 	register struct blocked	*bp;
196b30d1939SAndy Fiddaman 	void			*sub=0;
197b30d1939SAndy Fiddaman 	int			isub=0;
198b30d1939SAndy Fiddaman 	if(nv_isarray(np) && (isub=nv_aindex(np)) < 0)
199b30d1939SAndy Fiddaman 		sub = nv_associative(np,(const char*)0,NV_ACURRENT);
200b30d1939SAndy Fiddaman 	for(bp=blist ; bp; bp=bp->next)
201b30d1939SAndy Fiddaman 	{
202b30d1939SAndy Fiddaman 		if(bp->np==np && bp->sub==sub && bp->isub==isub)
203b30d1939SAndy Fiddaman 			return(bp);
204b30d1939SAndy Fiddaman 	}
205b30d1939SAndy Fiddaman 	if(pp)
206b30d1939SAndy Fiddaman 	{
207b30d1939SAndy Fiddaman 		pp->np = np;
208b30d1939SAndy Fiddaman 		pp->flags = 0;
209b30d1939SAndy Fiddaman 		pp->isub = isub;
210b30d1939SAndy Fiddaman 		pp->sub = sub;
211b30d1939SAndy Fiddaman 		pp->next = blist;
212b30d1939SAndy Fiddaman 		blist = pp;
213b30d1939SAndy Fiddaman 	}
214b30d1939SAndy Fiddaman 	return(pp);
215b30d1939SAndy Fiddaman }
216b30d1939SAndy Fiddaman 
block_done(struct blocked * bp)217b30d1939SAndy Fiddaman static void block_done(struct blocked *bp)
218b30d1939SAndy Fiddaman {
219b30d1939SAndy Fiddaman 	blist = bp = bp->next;
220b30d1939SAndy Fiddaman 	if(bp && (bp->isub>=0 || bp->sub))
221b30d1939SAndy Fiddaman 		nv_putsub(bp->np, bp->sub,(bp->isub<0?0:bp->isub)|ARRAY_SETSUB);
222b30d1939SAndy Fiddaman }
223b30d1939SAndy Fiddaman 
224b30d1939SAndy Fiddaman /*
225b30d1939SAndy Fiddaman  * free discipline if no more discipline functions
226b30d1939SAndy Fiddaman  */
chktfree(register Namval_t * np,register struct vardisc * vp)227b30d1939SAndy Fiddaman static void chktfree(register Namval_t *np, register struct vardisc *vp)
228b30d1939SAndy Fiddaman {
229b30d1939SAndy Fiddaman 	register int n;
230b30d1939SAndy Fiddaman 	for(n=0; n< sizeof(vp->disc)/sizeof(*vp->disc); n++)
231b30d1939SAndy Fiddaman 	{
232b30d1939SAndy Fiddaman 		if(vp->disc[n])
233b30d1939SAndy Fiddaman 			break;
234b30d1939SAndy Fiddaman 	}
235b30d1939SAndy Fiddaman 	if(n>=sizeof(vp->disc)/sizeof(*vp->disc))
236b30d1939SAndy Fiddaman 	{
237b30d1939SAndy Fiddaman 		/* no disc left so pop */
238b30d1939SAndy Fiddaman 		Namfun_t *fp;
239b30d1939SAndy Fiddaman 		if((fp=nv_stack(np, NIL(Namfun_t*))) && !(fp->nofree&1))
240b30d1939SAndy Fiddaman 			free((void*)fp);
241b30d1939SAndy Fiddaman 	}
242b30d1939SAndy Fiddaman }
243b30d1939SAndy Fiddaman 
244b30d1939SAndy Fiddaman /*
245b30d1939SAndy Fiddaman  * This function performs an assignment disc on the given node <np>
246b30d1939SAndy Fiddaman  */
assign(Namval_t * np,const char * val,int flags,Namfun_t * handle)247b30d1939SAndy Fiddaman static void	assign(Namval_t *np,const char* val,int flags,Namfun_t *handle)
248b30d1939SAndy Fiddaman {
249b30d1939SAndy Fiddaman 	int		type = (flags&NV_APPEND)?APPEND:ASSIGN;
250b30d1939SAndy Fiddaman 	register	struct vardisc *vp = (struct vardisc*)handle;
251b30d1939SAndy Fiddaman 	register	Namval_t *nq =  vp->disc[type];
252b30d1939SAndy Fiddaman 	struct blocked	block, *bp = block_info(np, &block);
253b30d1939SAndy Fiddaman 	Namval_t	node;
254b30d1939SAndy Fiddaman 	union Value	*up = np->nvalue.up;
255b30d1939SAndy Fiddaman #if SHOPT_TYPEDEF
256b30d1939SAndy Fiddaman 	Namval_t	*tp, *nr;
257b30d1939SAndy Fiddaman 	if(val && (tp=nv_type(np)) && (nr=nv_open(val,sh.var_tree,NV_VARNAME|NV_ARRAY|NV_NOADD|NV_NOFAIL)) && tp==nv_type(nr))
258b30d1939SAndy Fiddaman 	{
259b30d1939SAndy Fiddaman 		char *sub = nv_getsub(np);
260b30d1939SAndy Fiddaman 		_nv_unset(np,0);
261b30d1939SAndy Fiddaman 		if(sub)
262b30d1939SAndy Fiddaman 		{
263b30d1939SAndy Fiddaman 			nv_putsub(np, sub, ARRAY_ADD);
264b30d1939SAndy Fiddaman 			nv_putval(np,nv_getval(nr), 0);
265b30d1939SAndy Fiddaman 		}
266b30d1939SAndy Fiddaman 		else
267b30d1939SAndy Fiddaman 			nv_clone(nr,np,0);
268b30d1939SAndy Fiddaman 		goto done;
269b30d1939SAndy Fiddaman 	}
270b30d1939SAndy Fiddaman #endif /* SHOPT_TYPEDEF */
271b30d1939SAndy Fiddaman 	if(val || isblocked(bp,type))
272b30d1939SAndy Fiddaman 	{
273b30d1939SAndy Fiddaman 		if(!nq || isblocked(bp,type))
274b30d1939SAndy Fiddaman 		{
275b30d1939SAndy Fiddaman 			nv_putv(np,val,flags,handle);
276b30d1939SAndy Fiddaman 			goto done;
277b30d1939SAndy Fiddaman 		}
278b30d1939SAndy Fiddaman 		node = *SH_VALNOD;
279b30d1939SAndy Fiddaman 		if(!nv_isnull(SH_VALNOD))
280b30d1939SAndy Fiddaman 		{
281b30d1939SAndy Fiddaman 			nv_onattr(SH_VALNOD,NV_NOFREE);
282b30d1939SAndy Fiddaman 			_nv_unset(SH_VALNOD,0);
283b30d1939SAndy Fiddaman 		}
284b30d1939SAndy Fiddaman 		if(flags&NV_INTEGER)
285b30d1939SAndy Fiddaman 			nv_onattr(SH_VALNOD,(flags&(NV_LONG|NV_DOUBLE|NV_EXPNOTE|NV_HEXFLOAT|NV_SHORT)));
286b30d1939SAndy Fiddaman 		nv_putval(SH_VALNOD, val, (flags&NV_INTEGER)?flags:NV_NOFREE);
287b30d1939SAndy Fiddaman 	}
288b30d1939SAndy Fiddaman 	else
289b30d1939SAndy Fiddaman 		nq =  vp->disc[type=UNASSIGN];
290b30d1939SAndy Fiddaman 	if(nq && !isblocked(bp,type))
291b30d1939SAndy Fiddaman 	{
292b30d1939SAndy Fiddaman 		int bflag=0;
293b30d1939SAndy Fiddaman 		block(bp,type);
294b30d1939SAndy Fiddaman 		if (type==APPEND && (bflag= !isblocked(bp,LOOKUPS)))
295b30d1939SAndy Fiddaman 			block(bp,LOOKUPS);
296b30d1939SAndy Fiddaman 		sh_fun(nq,np,(char**)0);
297b30d1939SAndy Fiddaman 		unblock(bp,type);
298b30d1939SAndy Fiddaman 		if(bflag)
299b30d1939SAndy Fiddaman 			unblock(bp,LOOKUPS);
300b30d1939SAndy Fiddaman 		if(!vp->disc[type])
301b30d1939SAndy Fiddaman 			chktfree(np,vp);
302b30d1939SAndy Fiddaman 	}
303b30d1939SAndy Fiddaman 	if(nv_isarray(np))
304b30d1939SAndy Fiddaman 		np->nvalue.up = up;
305b30d1939SAndy Fiddaman 	if(val)
306b30d1939SAndy Fiddaman 	{
307b30d1939SAndy Fiddaman 		register char *cp;
308b30d1939SAndy Fiddaman 		Sfdouble_t d;
309b30d1939SAndy Fiddaman 		if(nv_isnull(SH_VALNOD))
310b30d1939SAndy Fiddaman 			cp=0;
311b30d1939SAndy Fiddaman 		else if(flags&NV_INTEGER)
312b30d1939SAndy Fiddaman 		{
313b30d1939SAndy Fiddaman 			d = nv_getnum(SH_VALNOD);
314b30d1939SAndy Fiddaman 			cp = (char*)(&d);
315b30d1939SAndy Fiddaman 			flags |= (NV_LONG|NV_DOUBLE);
316b30d1939SAndy Fiddaman 			flags &= ~NV_SHORT;
317b30d1939SAndy Fiddaman 		}
318b30d1939SAndy Fiddaman 		else
319b30d1939SAndy Fiddaman 			cp = nv_getval(SH_VALNOD);
320b30d1939SAndy Fiddaman 		if(cp)
321b30d1939SAndy Fiddaman 			nv_putv(np,cp,flags|NV_RDONLY,handle);
322b30d1939SAndy Fiddaman 		_nv_unset(SH_VALNOD,0);
323b30d1939SAndy Fiddaman 		/* restore everything but the nvlink field */
324b30d1939SAndy Fiddaman 		memcpy(&SH_VALNOD->nvname,  &node.nvname, sizeof(node)-sizeof(node.nvlink));
325b30d1939SAndy Fiddaman 	}
326b30d1939SAndy Fiddaman 	else if(sh_isstate(SH_INIT) || np==SH_FUNNAMENOD)
327b30d1939SAndy Fiddaman 	{
328b30d1939SAndy Fiddaman 		/* don't free functions during reinitialization */
329b30d1939SAndy Fiddaman 		nv_putv(np,val,flags,handle);
330b30d1939SAndy Fiddaman 	}
331b30d1939SAndy Fiddaman 	else if(!nq || !isblocked(bp,type))
332b30d1939SAndy Fiddaman 	{
333b30d1939SAndy Fiddaman 		Dt_t *root = sh_subfuntree(1);
334b30d1939SAndy Fiddaman 		int n;
335b30d1939SAndy Fiddaman 		Namarr_t *ap;
336b30d1939SAndy Fiddaman 		block(bp,type);
337b30d1939SAndy Fiddaman 		nv_disc(np,handle,NV_POP);
338b30d1939SAndy Fiddaman 		nv_putv(np, val, flags, handle);
339b30d1939SAndy Fiddaman 		if(sh.subshell)
340b30d1939SAndy Fiddaman 			goto done;
341b30d1939SAndy Fiddaman 		if(nv_isarray(np) && (ap=nv_arrayptr(np)) && ap->nelem>0)
342b30d1939SAndy Fiddaman 			goto done;
343b30d1939SAndy Fiddaman 		for(n=0; n < sizeof(vp->disc)/sizeof(*vp->disc); n++)
344b30d1939SAndy Fiddaman 		{
345b30d1939SAndy Fiddaman 			if((nq=vp->disc[n]) && !nv_isattr(nq,NV_NOFREE))
346b30d1939SAndy Fiddaman 			{
347b30d1939SAndy Fiddaman 				_nv_unset(nq,0);
348b30d1939SAndy Fiddaman 				dtdelete(root,nq);
349b30d1939SAndy Fiddaman 			}
350b30d1939SAndy Fiddaman 		}
351b30d1939SAndy Fiddaman 		unblock(bp,type);
352b30d1939SAndy Fiddaman 		if(!(handle->nofree&1))
353b30d1939SAndy Fiddaman 			free(handle);
354b30d1939SAndy Fiddaman 	}
355b30d1939SAndy Fiddaman done:
356b30d1939SAndy Fiddaman 	if(bp== &block)
357b30d1939SAndy Fiddaman 		block_done(bp);
358b30d1939SAndy Fiddaman 	if(nq && nq->nvalue.rp->running==1)
359b30d1939SAndy Fiddaman 	{
360b30d1939SAndy Fiddaman 		nq->nvalue.rp->running=0;
361b30d1939SAndy Fiddaman 		_nv_unset(nq,0);
362b30d1939SAndy Fiddaman 	}
363b30d1939SAndy Fiddaman }
364b30d1939SAndy Fiddaman 
365b30d1939SAndy Fiddaman /*
366b30d1939SAndy Fiddaman  * This function executes a lookup disc and then performs
367b30d1939SAndy Fiddaman  * the lookup on the given node <np>
368b30d1939SAndy Fiddaman  */
lookup(Namval_t * np,int type,Sfdouble_t * dp,Namfun_t * handle)369b30d1939SAndy Fiddaman static char*	lookup(Namval_t *np, int type, Sfdouble_t *dp,Namfun_t *handle)
370b30d1939SAndy Fiddaman {
371b30d1939SAndy Fiddaman 	register struct vardisc	*vp = (struct vardisc*)handle;
372b30d1939SAndy Fiddaman 	struct blocked		block, *bp = block_info(np, &block);
373b30d1939SAndy Fiddaman 	register Namval_t	*nq = vp->disc[type];
374b30d1939SAndy Fiddaman 	register char		*cp=0;
375b30d1939SAndy Fiddaman 	Namval_t		node;
376b30d1939SAndy Fiddaman 	union Value		*up = np->nvalue.up;
377b30d1939SAndy Fiddaman 	if(nq && !isblocked(bp,type))
378b30d1939SAndy Fiddaman 	{
379b30d1939SAndy Fiddaman 		node = *SH_VALNOD;
380b30d1939SAndy Fiddaman 		if(!nv_isnull(SH_VALNOD))
381b30d1939SAndy Fiddaman 		{
382b30d1939SAndy Fiddaman 			nv_onattr(SH_VALNOD,NV_NOFREE);
383b30d1939SAndy Fiddaman 			_nv_unset(SH_VALNOD,0);
384b30d1939SAndy Fiddaman 		}
385b30d1939SAndy Fiddaman 		if(type==LOOKUPN)
386b30d1939SAndy Fiddaman 		{
387b30d1939SAndy Fiddaman 			nv_onattr(SH_VALNOD,NV_DOUBLE|NV_INTEGER);
388b30d1939SAndy Fiddaman 			nv_setsize(SH_VALNOD,10);
389b30d1939SAndy Fiddaman 		}
390b30d1939SAndy Fiddaman 		block(bp,type);
391b30d1939SAndy Fiddaman 		sh_fun(nq,np,(char**)0);
392b30d1939SAndy Fiddaman 		unblock(bp,type);
393b30d1939SAndy Fiddaman 		if(!vp->disc[type])
394b30d1939SAndy Fiddaman 			chktfree(np,vp);
395b30d1939SAndy Fiddaman 		if(type==LOOKUPN)
396b30d1939SAndy Fiddaman 		{
397b30d1939SAndy Fiddaman 			cp = (char*)(SH_VALNOD->nvalue.cp);
398b30d1939SAndy Fiddaman 			*dp = nv_getnum(SH_VALNOD);
399b30d1939SAndy Fiddaman 		}
400b30d1939SAndy Fiddaman 		else if(cp = nv_getval(SH_VALNOD))
401b30d1939SAndy Fiddaman 			cp = stkcopy(stkstd,cp);
402b30d1939SAndy Fiddaman 		_nv_unset(SH_VALNOD,NV_RDONLY);
403b30d1939SAndy Fiddaman 		if(!nv_isnull(&node))
404b30d1939SAndy Fiddaman 		{
405b30d1939SAndy Fiddaman 			/* restore everything but the nvlink field */
406b30d1939SAndy Fiddaman 			memcpy(&SH_VALNOD->nvname,  &node.nvname, sizeof(node)-sizeof(node.nvlink));
407b30d1939SAndy Fiddaman 		}
408b30d1939SAndy Fiddaman 	}
409b30d1939SAndy Fiddaman 	if(nv_isarray(np))
410b30d1939SAndy Fiddaman 		np->nvalue.up = up;
411b30d1939SAndy Fiddaman 	if(!cp)
412b30d1939SAndy Fiddaman 	{
413b30d1939SAndy Fiddaman 		if(type==LOOKUPS)
414b30d1939SAndy Fiddaman 			cp = nv_getv(np,handle);
415b30d1939SAndy Fiddaman 		else
416b30d1939SAndy Fiddaman 			*dp = nv_getn(np,handle);
417b30d1939SAndy Fiddaman 	}
418b30d1939SAndy Fiddaman 	if(bp== &block)
419b30d1939SAndy Fiddaman 		block_done(bp);
420b30d1939SAndy Fiddaman 	if(nq && nq->nvalue.rp->running==1)
421b30d1939SAndy Fiddaman 	{
422b30d1939SAndy Fiddaman 		nq->nvalue.rp->running=0;
423b30d1939SAndy Fiddaman 		_nv_unset(nq,0);
424b30d1939SAndy Fiddaman 	}
425b30d1939SAndy Fiddaman 	return(cp);
426b30d1939SAndy Fiddaman }
427b30d1939SAndy Fiddaman 
lookups(Namval_t * np,Namfun_t * handle)428b30d1939SAndy Fiddaman static char*	lookups(Namval_t *np, Namfun_t *handle)
429b30d1939SAndy Fiddaman {
430b30d1939SAndy Fiddaman 	return(lookup(np,LOOKUPS,(Sfdouble_t*)0,handle));
431b30d1939SAndy Fiddaman }
432b30d1939SAndy Fiddaman 
lookupn(Namval_t * np,Namfun_t * handle)433b30d1939SAndy Fiddaman static Sfdouble_t lookupn(Namval_t *np, Namfun_t *handle)
434b30d1939SAndy Fiddaman {
435b30d1939SAndy Fiddaman 	Sfdouble_t	d;
436b30d1939SAndy Fiddaman 	lookup(np,LOOKUPN, &d ,handle);
437b30d1939SAndy Fiddaman 	return(d);
438b30d1939SAndy Fiddaman }
439b30d1939SAndy Fiddaman 
440b30d1939SAndy Fiddaman 
441b30d1939SAndy Fiddaman /*
442b30d1939SAndy Fiddaman  * Set disc on given <event> to <action>
443b30d1939SAndy Fiddaman  * If action==np, the current disc is returned
444b30d1939SAndy Fiddaman  * A null return value indicates that no <event> is known for <np>
445b30d1939SAndy Fiddaman  * If <event> is NULL, then return the event name after <action>
446b30d1939SAndy Fiddaman  * If <event> is NULL, and <action> is NULL, return the first event
447b30d1939SAndy Fiddaman  */
nv_setdisc(register Namval_t * np,register const char * event,Namval_t * action,register Namfun_t * fp)448b30d1939SAndy Fiddaman char *nv_setdisc(register Namval_t* np,register const char *event,Namval_t *action,register Namfun_t *fp)
449b30d1939SAndy Fiddaman {
450b30d1939SAndy Fiddaman 	register struct vardisc *vp = (struct vardisc*)np->nvfun;
451b30d1939SAndy Fiddaman 	register int type;
452b30d1939SAndy Fiddaman 	char *empty = "";
453b30d1939SAndy Fiddaman 	while(vp)
454b30d1939SAndy Fiddaman 	{
455b30d1939SAndy Fiddaman 		if(vp->fun.disc && (vp->fun.disc->setdisc || vp->fun.disc->putval == assign))
456b30d1939SAndy Fiddaman 			break;
457b30d1939SAndy Fiddaman 		vp = (struct vardisc*)vp->fun.next;
458b30d1939SAndy Fiddaman 	}
459b30d1939SAndy Fiddaman 	if(vp && !vp->fun.disc)
460b30d1939SAndy Fiddaman 		vp = 0;
461b30d1939SAndy Fiddaman 	if(np == (Namval_t*)fp)
462b30d1939SAndy Fiddaman 	{
463b30d1939SAndy Fiddaman 		register const char *name;
464b30d1939SAndy Fiddaman 		register int getname=0;
465b30d1939SAndy Fiddaman 		/* top level call, check for get/set */
466b30d1939SAndy Fiddaman 		if(!event)
467b30d1939SAndy Fiddaman 		{
468b30d1939SAndy Fiddaman 			if(!action)
469b30d1939SAndy Fiddaman 				return((char*)nv_discnames[0]);
470b30d1939SAndy Fiddaman 			getname=1;
471b30d1939SAndy Fiddaman 			event = (char*)action;
472b30d1939SAndy Fiddaman 		}
473b30d1939SAndy Fiddaman 		for(type=0; name=nv_discnames[type]; type++)
474b30d1939SAndy Fiddaman 		{
475b30d1939SAndy Fiddaman 			if(strcmp(event,name)==0)
476b30d1939SAndy Fiddaman 				break;
477b30d1939SAndy Fiddaman 		}
478b30d1939SAndy Fiddaman 		if(getname)
479b30d1939SAndy Fiddaman 		{
480b30d1939SAndy Fiddaman 			event = 0;
481b30d1939SAndy Fiddaman 			if(name && !(name = nv_discnames[++type]))
482b30d1939SAndy Fiddaman 				action = 0;
483b30d1939SAndy Fiddaman 		}
484b30d1939SAndy Fiddaman 		if(!name)
485b30d1939SAndy Fiddaman 		{
486b30d1939SAndy Fiddaman 			for(fp=(Namfun_t*)vp; fp; fp=fp->next)
487b30d1939SAndy Fiddaman 			{
488b30d1939SAndy Fiddaman 				if(fp->disc && fp->disc->setdisc)
489b30d1939SAndy Fiddaman 					return((*fp->disc->setdisc)(np,event,action,fp));
490b30d1939SAndy Fiddaman 			}
491b30d1939SAndy Fiddaman 		}
492b30d1939SAndy Fiddaman 		else if(getname)
493b30d1939SAndy Fiddaman 			return((char*)name);
494b30d1939SAndy Fiddaman 	}
495b30d1939SAndy Fiddaman 	if(!fp)
496b30d1939SAndy Fiddaman 		return(NIL(char*));
497b30d1939SAndy Fiddaman 	if(np != (Namval_t*)fp)
498b30d1939SAndy Fiddaman 	{
499b30d1939SAndy Fiddaman 		/* not the top level */
500b30d1939SAndy Fiddaman 		while(fp = fp->next)
501b30d1939SAndy Fiddaman 		{
502b30d1939SAndy Fiddaman 			if(fp->disc && fp->disc->setdisc)
503b30d1939SAndy Fiddaman 				return((*fp->disc->setdisc)(np,event,action,fp));
504b30d1939SAndy Fiddaman 		}
505b30d1939SAndy Fiddaman 		return(NIL(char*));
506b30d1939SAndy Fiddaman 	}
507b30d1939SAndy Fiddaman 	/* Handle GET/SET/APPEND/UNSET disc */
508b30d1939SAndy Fiddaman 	if(vp && vp->fun.disc->putval!=assign)
509b30d1939SAndy Fiddaman 		vp = 0;
510b30d1939SAndy Fiddaman 	if(!vp)
511b30d1939SAndy Fiddaman 	{
512b30d1939SAndy Fiddaman 		Namdisc_t	*dp;
513b30d1939SAndy Fiddaman 		if(action==np)
514b30d1939SAndy Fiddaman 			return((char*)action);
515b30d1939SAndy Fiddaman 		if(!(vp = newof(NIL(struct vardisc*),struct vardisc,1,sizeof(Namdisc_t))))
516b30d1939SAndy Fiddaman 			return(0);
517b30d1939SAndy Fiddaman 		dp = (Namdisc_t*)(vp+1);
518b30d1939SAndy Fiddaman 		vp->fun.disc = dp;
519b30d1939SAndy Fiddaman 		memset(dp,0,sizeof(*dp));
520b30d1939SAndy Fiddaman 		dp->dsize = sizeof(struct vardisc);
521b30d1939SAndy Fiddaman 		dp->putval = assign;
522b30d1939SAndy Fiddaman 		if(nv_isarray(np) && !nv_arrayptr(np))
523b30d1939SAndy Fiddaman 			nv_putsub(np,(char*)0, 1);
524b30d1939SAndy Fiddaman 		nv_stack(np, (Namfun_t*)vp);
525b30d1939SAndy Fiddaman 	}
526b30d1939SAndy Fiddaman 	if(action==np)
527b30d1939SAndy Fiddaman 	{
528b30d1939SAndy Fiddaman 		action = vp->disc[type];
529b30d1939SAndy Fiddaman 		empty = 0;
530b30d1939SAndy Fiddaman 	}
531b30d1939SAndy Fiddaman 	else if(action)
532b30d1939SAndy Fiddaman 	{
533b30d1939SAndy Fiddaman 		Namdisc_t *dp = (Namdisc_t*)vp->fun.disc;
534b30d1939SAndy Fiddaman 		if(type==LOOKUPS)
535b30d1939SAndy Fiddaman 			dp->getval = lookups;
536b30d1939SAndy Fiddaman 		else if(type==LOOKUPN)
537b30d1939SAndy Fiddaman 			dp->getnum = lookupn;
538b30d1939SAndy Fiddaman 		vp->disc[type] = action;
539b30d1939SAndy Fiddaman 	}
540b30d1939SAndy Fiddaman 	else
541b30d1939SAndy Fiddaman 	{
542b30d1939SAndy Fiddaman 		struct blocked *bp;
543b30d1939SAndy Fiddaman 		action = vp->disc[type];
544b30d1939SAndy Fiddaman 		vp->disc[type] = 0;
545b30d1939SAndy Fiddaman 		if(!(bp=block_info(np,(struct blocked*)0)) || !isblocked(bp,UNASSIGN))
546b30d1939SAndy Fiddaman 			chktfree(np,vp);
547b30d1939SAndy Fiddaman 	}
548b30d1939SAndy Fiddaman 	return(action?(char*)action:empty);
549b30d1939SAndy Fiddaman }
550b30d1939SAndy Fiddaman 
551b30d1939SAndy Fiddaman /*
552b30d1939SAndy Fiddaman  * Set disc on given <event> to <action>
553b30d1939SAndy Fiddaman  * If action==np, the current disc is returned
554b30d1939SAndy Fiddaman  * A null return value indicates that no <event> is known for <np>
555b30d1939SAndy Fiddaman  * If <event> is NULL, then return the event name after <action>
556b30d1939SAndy Fiddaman  * If <event> is NULL, and <action> is NULL, return the first event
557b30d1939SAndy Fiddaman  */
setdisc(register Namval_t * np,register const char * event,Namval_t * action,register Namfun_t * fp)558b30d1939SAndy Fiddaman static char *setdisc(register Namval_t* np,register const char *event,Namval_t *action,register Namfun_t *fp)
559b30d1939SAndy Fiddaman {
560b30d1939SAndy Fiddaman 	register Nambfun_t *vp = (Nambfun_t*)fp;
561b30d1939SAndy Fiddaman 	register int type,getname=0;
562b30d1939SAndy Fiddaman 	register const char *name;
563b30d1939SAndy Fiddaman 	const char **discnames = vp->bnames;
564b30d1939SAndy Fiddaman 	/* top level call, check for discipline match */
565b30d1939SAndy Fiddaman 	if(!event)
566b30d1939SAndy Fiddaman 	{
567b30d1939SAndy Fiddaman 		if(!action)
568b30d1939SAndy Fiddaman 			return((char*)discnames[0]);
569b30d1939SAndy Fiddaman 		getname=1;
570b30d1939SAndy Fiddaman 		event = (char*)action;
571b30d1939SAndy Fiddaman 	}
572b30d1939SAndy Fiddaman 	for(type=0; name=discnames[type]; type++)
573b30d1939SAndy Fiddaman 	{
574b30d1939SAndy Fiddaman 		if(strcmp(event,name)==0)
575b30d1939SAndy Fiddaman 			break;
576b30d1939SAndy Fiddaman 	}
577b30d1939SAndy Fiddaman 	if(getname)
578b30d1939SAndy Fiddaman 	{
579b30d1939SAndy Fiddaman 		event = 0;
580b30d1939SAndy Fiddaman 		if(name && !(name = discnames[++type]))
581b30d1939SAndy Fiddaman 			action = 0;
582b30d1939SAndy Fiddaman 	}
583b30d1939SAndy Fiddaman 	if(!name)
584b30d1939SAndy Fiddaman 		return(nv_setdisc(np,event,action,fp));
585b30d1939SAndy Fiddaman 	else if(getname)
586b30d1939SAndy Fiddaman 		return((char*)name);
587b30d1939SAndy Fiddaman 	/* Handle the disciplines */
588b30d1939SAndy Fiddaman 	if(action==np)
589b30d1939SAndy Fiddaman 		action = vp->bltins[type];
590b30d1939SAndy Fiddaman 	else if(action)
591b30d1939SAndy Fiddaman 	{
592b30d1939SAndy Fiddaman 		Namval_t *tp = nv_type(np);
593b30d1939SAndy Fiddaman 		if(tp && (np = (Namval_t*)vp->bltins[type]) && nv_isattr(np,NV_STATICF))
594b30d1939SAndy Fiddaman 			errormsg(SH_DICT,ERROR_exit(1),e_staticfun,name,tp->nvname);
595b30d1939SAndy Fiddaman 		vp->bltins[type] = action;
596b30d1939SAndy Fiddaman 	}
597b30d1939SAndy Fiddaman 	else
598b30d1939SAndy Fiddaman 	{
599b30d1939SAndy Fiddaman 		action = vp->bltins[type];
600b30d1939SAndy Fiddaman 		vp->bltins[type] = 0;
601b30d1939SAndy Fiddaman 	}
602b30d1939SAndy Fiddaman 	return((char*)action);
603b30d1939SAndy Fiddaman }
604b30d1939SAndy Fiddaman 
putdisc(Namval_t * np,const char * val,int flag,Namfun_t * fp)605b30d1939SAndy Fiddaman static void putdisc(Namval_t* np, const char* val, int flag, Namfun_t* fp)
606b30d1939SAndy Fiddaman {
607b30d1939SAndy Fiddaman 	nv_putv(np,val,flag,fp);
608b30d1939SAndy Fiddaman 	if(!val && !(flag&NV_NOFREE))
609b30d1939SAndy Fiddaman 	{
610b30d1939SAndy Fiddaman 		register Nambfun_t *vp = (Nambfun_t*)fp;
611b30d1939SAndy Fiddaman 		register int i;
612b30d1939SAndy Fiddaman 		for(i=0; vp->bnames[i]; i++)
613b30d1939SAndy Fiddaman 		{
614b30d1939SAndy Fiddaman 			register Namval_t *mp;
615b30d1939SAndy Fiddaman 			if((mp=vp->bltins[i]) && !nv_isattr(mp,NV_NOFREE))
616b30d1939SAndy Fiddaman 			{
617b30d1939SAndy Fiddaman 				if(is_abuiltin(mp))
618b30d1939SAndy Fiddaman 				{
619b30d1939SAndy Fiddaman 					if(mp->nvfun && !nv_isattr(mp,NV_NOFREE))
620b30d1939SAndy Fiddaman 						free((void*)mp->nvfun);
621b30d1939SAndy Fiddaman 					dtdelete(sh.bltin_tree,mp);
622b30d1939SAndy Fiddaman 					free((void*)mp);
623b30d1939SAndy Fiddaman 				}
624b30d1939SAndy Fiddaman 			}
625b30d1939SAndy Fiddaman 		}
626b30d1939SAndy Fiddaman 		nv_disc(np,fp,NV_POP);
627b30d1939SAndy Fiddaman 		if(!(fp->nofree&1))
628b30d1939SAndy Fiddaman 			free((void*)fp);
629b30d1939SAndy Fiddaman 
630b30d1939SAndy Fiddaman 	}
631b30d1939SAndy Fiddaman }
632b30d1939SAndy Fiddaman 
633b30d1939SAndy Fiddaman static const Namdisc_t Nv_bdisc	= {   0, putdisc, 0, 0, setdisc };
634b30d1939SAndy Fiddaman 
nv_clone_disc(register Namfun_t * fp,int flags)635b30d1939SAndy Fiddaman Namfun_t *nv_clone_disc(register Namfun_t *fp, int flags)
636b30d1939SAndy Fiddaman {
637b30d1939SAndy Fiddaman 	register Namfun_t	*nfp;
638b30d1939SAndy Fiddaman 	register int		size;
639b30d1939SAndy Fiddaman 	if(!fp->disc && !fp->next && (fp->nofree&1))
640b30d1939SAndy Fiddaman 		return(fp);
641b30d1939SAndy Fiddaman 	if(!(size=fp->dsize) && (!fp->disc || !(size=fp->disc->dsize)))
642b30d1939SAndy Fiddaman 		size = sizeof(Namfun_t);
643b30d1939SAndy Fiddaman 	if(!(nfp=newof(NIL(Namfun_t*),Namfun_t,1,size-sizeof(Namfun_t))))
644b30d1939SAndy Fiddaman 		return(0);
645b30d1939SAndy Fiddaman 	memcpy(nfp,fp,size);
646b30d1939SAndy Fiddaman 	nfp->nofree &= ~1;
647b30d1939SAndy Fiddaman 	nfp->nofree |= (flags&NV_RDONLY)?1:0;
648b30d1939SAndy Fiddaman 	return(nfp);
649b30d1939SAndy Fiddaman }
650b30d1939SAndy Fiddaman 
nv_adddisc(Namval_t * np,const char ** names,Namval_t ** funs)651b30d1939SAndy Fiddaman int nv_adddisc(Namval_t *np, const char **names, Namval_t **funs)
652b30d1939SAndy Fiddaman {
653b30d1939SAndy Fiddaman 	register Nambfun_t *vp;
654b30d1939SAndy Fiddaman 	register int n=0;
655b30d1939SAndy Fiddaman 	register const char **av=names;
656b30d1939SAndy Fiddaman 	if(av)
657b30d1939SAndy Fiddaman 	{
658b30d1939SAndy Fiddaman 		while(*av++)
659b30d1939SAndy Fiddaman 			n++;
660b30d1939SAndy Fiddaman 	}
661b30d1939SAndy Fiddaman 	if(!(vp = newof(NIL(Nambfun_t*),Nambfun_t,1,n*sizeof(Namval_t*))))
662b30d1939SAndy Fiddaman 		return(0);
663b30d1939SAndy Fiddaman 	vp->fun.dsize = sizeof(Nambfun_t)+n*sizeof(Namval_t*);
664b30d1939SAndy Fiddaman 	vp->fun.nofree |= 2;
665b30d1939SAndy Fiddaman 	vp->num = n;
666b30d1939SAndy Fiddaman 	if(funs)
667b30d1939SAndy Fiddaman 		memcpy((void*)vp->bltins, (void*)funs,n*sizeof(Namval_t*));
668b30d1939SAndy Fiddaman 	else while(n>=0)
669b30d1939SAndy Fiddaman 		vp->bltins[n--] = 0;
670b30d1939SAndy Fiddaman 	vp->fun.disc = &Nv_bdisc;
671b30d1939SAndy Fiddaman 	vp->bnames = names;
672b30d1939SAndy Fiddaman 	nv_stack(np,&vp->fun);
673b30d1939SAndy Fiddaman 	return(1);
674b30d1939SAndy Fiddaman }
675b30d1939SAndy Fiddaman 
676b30d1939SAndy Fiddaman /*
677b30d1939SAndy Fiddaman  * push, pop, clne, or reorder disciplines onto node <np>
678b30d1939SAndy Fiddaman  * mode can be one of
679b30d1939SAndy Fiddaman  *    NV_FIRST:  Move or push <fp> to top of the stack or delete top
680b30d1939SAndy Fiddaman  *    NV_LAST:	 Move or push <fp> to bottom of stack or delete last
681b30d1939SAndy Fiddaman  *    NV_POP:	 Delete <fp> from top of the stack
682b30d1939SAndy Fiddaman  *    NV_CLONE:  Replace fp with a copy created my malloc() and return it
683b30d1939SAndy Fiddaman  */
nv_disc(register Namval_t * np,register Namfun_t * fp,int mode)684b30d1939SAndy Fiddaman Namfun_t *nv_disc(register Namval_t *np, register Namfun_t* fp, int mode)
685b30d1939SAndy Fiddaman {
686b30d1939SAndy Fiddaman 	Namfun_t *lp, **lpp;
687b30d1939SAndy Fiddaman 	if(nv_isref(np))
688b30d1939SAndy Fiddaman 		return(0);
689b30d1939SAndy Fiddaman 	if(mode==NV_CLONE && !fp)
690b30d1939SAndy Fiddaman 		return(0);
691b30d1939SAndy Fiddaman 	if(fp)
692b30d1939SAndy Fiddaman 	{
693b30d1939SAndy Fiddaman 		fp->subshell = sh.subshell;
694b30d1939SAndy Fiddaman 		if((lp=np->nvfun)==fp)
695b30d1939SAndy Fiddaman 		{
696b30d1939SAndy Fiddaman 			if(mode==NV_CLONE)
697b30d1939SAndy Fiddaman 			{
698b30d1939SAndy Fiddaman 				lp = nv_clone_disc(fp,0);
699b30d1939SAndy Fiddaman 				return(np->nvfun=lp);
700b30d1939SAndy Fiddaman 			}
701b30d1939SAndy Fiddaman 			if(mode==NV_FIRST || mode==0)
702b30d1939SAndy Fiddaman 				return(fp);
703b30d1939SAndy Fiddaman 			np->nvfun = lp->next;
704b30d1939SAndy Fiddaman 			if(mode==NV_POP)
705b30d1939SAndy Fiddaman 				return(fp);
706b30d1939SAndy Fiddaman 			if(mode==NV_LAST && (lp->next==0 || lp->next->disc==0))
707b30d1939SAndy Fiddaman 				return(fp);
708b30d1939SAndy Fiddaman 		}
709b30d1939SAndy Fiddaman 		/* see if <fp> is on the list already */
710b30d1939SAndy Fiddaman 		lpp = &np->nvfun;
711b30d1939SAndy Fiddaman 		if(lp)
712b30d1939SAndy Fiddaman 		{
713b30d1939SAndy Fiddaman 			while(lp->next && lp->next->disc)
714b30d1939SAndy Fiddaman 			{
715b30d1939SAndy Fiddaman 				if(lp->next==fp)
716b30d1939SAndy Fiddaman 				{
717b30d1939SAndy Fiddaman 					if(mode==NV_LAST && fp->next==0)
718b30d1939SAndy Fiddaman 						return(fp);
719b30d1939SAndy Fiddaman 					if(mode==NV_CLONE)
720b30d1939SAndy Fiddaman 					{
721b30d1939SAndy Fiddaman 						fp = nv_clone_disc(fp,0);
722b30d1939SAndy Fiddaman 						lp->next = fp;
723b30d1939SAndy Fiddaman 						return(fp);
724b30d1939SAndy Fiddaman 					}
725b30d1939SAndy Fiddaman 					lp->next = fp->next;
726b30d1939SAndy Fiddaman 					if(mode==NV_POP)
727b30d1939SAndy Fiddaman 						return(fp);
728b30d1939SAndy Fiddaman 					if(mode!=NV_LAST)
729b30d1939SAndy Fiddaman 						break;
730b30d1939SAndy Fiddaman 				}
731b30d1939SAndy Fiddaman 				lp = lp->next;
732b30d1939SAndy Fiddaman 			}
733b30d1939SAndy Fiddaman 			if(mode==NV_LAST && lp->disc)
734b30d1939SAndy Fiddaman 				lpp = &lp->next;
735b30d1939SAndy Fiddaman 		}
736b30d1939SAndy Fiddaman 		if(mode==NV_POP)
737b30d1939SAndy Fiddaman 			return(0);
738b30d1939SAndy Fiddaman 		/* push */
739b30d1939SAndy Fiddaman 		nv_offattr(np,NV_NODISC);
740b30d1939SAndy Fiddaman 		if(mode==NV_LAST)
741b30d1939SAndy Fiddaman 		{
742b30d1939SAndy Fiddaman 			if(lp && !lp->disc)
743b30d1939SAndy Fiddaman 				fp->next = lp;
744b30d1939SAndy Fiddaman 			else
745*5b8dd251SAndy Fiddaman 				fp->next = *lpp;
746b30d1939SAndy Fiddaman 		}
747b30d1939SAndy Fiddaman 		else
748b30d1939SAndy Fiddaman 		{
749b30d1939SAndy Fiddaman 			if((fp->nofree&1) && *lpp)
750b30d1939SAndy Fiddaman 				fp = nv_clone_disc(fp,0);
751b30d1939SAndy Fiddaman 			fp->next = *lpp;
752b30d1939SAndy Fiddaman 		}
753b30d1939SAndy Fiddaman 		*lpp = fp;
754b30d1939SAndy Fiddaman 	}
755b30d1939SAndy Fiddaman 	else
756b30d1939SAndy Fiddaman 	{
757b30d1939SAndy Fiddaman 		if(mode==NV_FIRST)
758b30d1939SAndy Fiddaman 			return(np->nvfun);
759b30d1939SAndy Fiddaman 		else if(mode==NV_LAST)
760b30d1939SAndy Fiddaman 			for(lp=np->nvfun; lp; fp=lp,lp=lp->next);
761b30d1939SAndy Fiddaman 		else if(fp = np->nvfun)
762b30d1939SAndy Fiddaman 			np->nvfun = fp->next;
763b30d1939SAndy Fiddaman 	}
764b30d1939SAndy Fiddaman 	return(fp);
765b30d1939SAndy Fiddaman }
766b30d1939SAndy Fiddaman 
767b30d1939SAndy Fiddaman /*
768b30d1939SAndy Fiddaman  * returns discipline pointer if discipline with specified functions
769b30d1939SAndy Fiddaman  * is on the discipline stack
770b30d1939SAndy Fiddaman  */
nv_hasdisc(Namval_t * np,const Namdisc_t * dp)771b30d1939SAndy Fiddaman Namfun_t *nv_hasdisc(Namval_t *np, const Namdisc_t *dp)
772b30d1939SAndy Fiddaman {
773b30d1939SAndy Fiddaman 	register Namfun_t *fp;
774b30d1939SAndy Fiddaman 	for(fp=np->nvfun; fp; fp = fp->next)
775b30d1939SAndy Fiddaman 	{
776b30d1939SAndy Fiddaman 		if(fp->disc== dp)
777b30d1939SAndy Fiddaman 			return(fp);
778b30d1939SAndy Fiddaman 	}
779b30d1939SAndy Fiddaman 	return(0);
780b30d1939SAndy Fiddaman }
781b30d1939SAndy Fiddaman 
782b30d1939SAndy Fiddaman struct notify
783b30d1939SAndy Fiddaman {
784b30d1939SAndy Fiddaman 	Namfun_t	hdr;
785b30d1939SAndy Fiddaman 	char		**ptr;
786b30d1939SAndy Fiddaman };
787b30d1939SAndy Fiddaman 
put_notify(Namval_t * np,const char * val,int flags,Namfun_t * fp)788b30d1939SAndy Fiddaman static void put_notify(Namval_t* np,const char *val,int flags,Namfun_t *fp)
789b30d1939SAndy Fiddaman {
790b30d1939SAndy Fiddaman 	struct notify *pp = (struct notify*)fp;
791b30d1939SAndy Fiddaman 	nv_putv(np,val,flags,fp);
792b30d1939SAndy Fiddaman 	nv_stack(np,fp);
793b30d1939SAndy Fiddaman 	nv_stack(np,(Namfun_t*)0);
794b30d1939SAndy Fiddaman 	*pp->ptr = 0;
795b30d1939SAndy Fiddaman 	if(!(fp->nofree&1))
796b30d1939SAndy Fiddaman 		free((void*)fp);
797b30d1939SAndy Fiddaman }
798b30d1939SAndy Fiddaman 
799b30d1939SAndy Fiddaman static const Namdisc_t notify_disc  = {  0, put_notify };
800b30d1939SAndy Fiddaman 
nv_unsetnotify(Namval_t * np,char ** addr)801b30d1939SAndy Fiddaman int nv_unsetnotify(Namval_t *np, char **addr)
802b30d1939SAndy Fiddaman {
803b30d1939SAndy Fiddaman 	register Namfun_t *fp;
804b30d1939SAndy Fiddaman 	for(fp=np->nvfun;fp;fp=fp->next)
805b30d1939SAndy Fiddaman 	{
806b30d1939SAndy Fiddaman 		if(fp->disc->putval==put_notify && ((struct notify*)fp)->ptr==addr)
807b30d1939SAndy Fiddaman 		{
808b30d1939SAndy Fiddaman 			nv_stack(np,fp);
809b30d1939SAndy Fiddaman 			nv_stack(np,(Namfun_t*)0);
810b30d1939SAndy Fiddaman 			if(!(fp->nofree&1))
811b30d1939SAndy Fiddaman 				free((void*)fp);
812b30d1939SAndy Fiddaman 			return(1);
813b30d1939SAndy Fiddaman 		}
814b30d1939SAndy Fiddaman 	}
815b30d1939SAndy Fiddaman 	return(0);
816b30d1939SAndy Fiddaman }
817b30d1939SAndy Fiddaman 
nv_setnotify(Namval_t * np,char ** addr)818b30d1939SAndy Fiddaman int nv_setnotify(Namval_t *np, char **addr)
819b30d1939SAndy Fiddaman {
820b30d1939SAndy Fiddaman 	struct notify *pp = newof(0,struct notify, 1,0);
821b30d1939SAndy Fiddaman 	if(!pp)
822b30d1939SAndy Fiddaman 		return(0);
823b30d1939SAndy Fiddaman 	pp->ptr = addr;
824b30d1939SAndy Fiddaman 	pp->hdr.disc = &notify_disc;
825b30d1939SAndy Fiddaman 	nv_stack(np,&pp->hdr);
826b30d1939SAndy Fiddaman 	return(1);
827b30d1939SAndy Fiddaman }
828b30d1939SAndy Fiddaman 
newnode(const char * name)829b30d1939SAndy Fiddaman static void *newnode(const char *name)
830b30d1939SAndy Fiddaman {
831b30d1939SAndy Fiddaman 	register int s;
832b30d1939SAndy Fiddaman 	register Namval_t *np = newof(0,Namval_t,1,s=strlen(name)+1);
833b30d1939SAndy Fiddaman 	if(np)
834b30d1939SAndy Fiddaman 	{
835b30d1939SAndy Fiddaman 		np->nvname = (char*)np+sizeof(Namval_t);
836b30d1939SAndy Fiddaman 		memcpy(np->nvname,name,s);
837b30d1939SAndy Fiddaman 	}
838b30d1939SAndy Fiddaman 	return((void*)np);
839b30d1939SAndy Fiddaman }
840b30d1939SAndy Fiddaman 
841b30d1939SAndy Fiddaman /*
842b30d1939SAndy Fiddaman  * clone a numeric value
843b30d1939SAndy Fiddaman  */
num_clone(register Namval_t * np,void * val)844b30d1939SAndy Fiddaman static void *num_clone(register Namval_t *np, void *val)
845b30d1939SAndy Fiddaman {
846b30d1939SAndy Fiddaman 	register int size;
847b30d1939SAndy Fiddaman 	void *nval;
848b30d1939SAndy Fiddaman 	if(!val)
849b30d1939SAndy Fiddaman 		return(0);
850b30d1939SAndy Fiddaman 	if(nv_isattr(np,NV_DOUBLE)==NV_DOUBLE)
851b30d1939SAndy Fiddaman 	{
852b30d1939SAndy Fiddaman 		if(nv_isattr(np,NV_LONG))
853b30d1939SAndy Fiddaman 			size = sizeof(Sfdouble_t);
854b30d1939SAndy Fiddaman 		else if(nv_isattr(np,NV_SHORT))
855b30d1939SAndy Fiddaman 			size = sizeof(float);
856b30d1939SAndy Fiddaman 		else
857b30d1939SAndy Fiddaman 			size = sizeof(double);
858b30d1939SAndy Fiddaman 	}
859b30d1939SAndy Fiddaman 	else
860b30d1939SAndy Fiddaman 	{
861b30d1939SAndy Fiddaman 		if(nv_isattr(np,NV_LONG))
862b30d1939SAndy Fiddaman 			size = sizeof(Sflong_t);
863b30d1939SAndy Fiddaman 		else if(nv_isattr(np,NV_SHORT))
864b30d1939SAndy Fiddaman 		{
865b30d1939SAndy Fiddaman 			if(nv_isattr(np,NV_INT16P)==NV_INT16P)
866b30d1939SAndy Fiddaman 				size = sizeof(short);
867b30d1939SAndy Fiddaman 			else
868b30d1939SAndy Fiddaman 				return((void*)np->nvalue.ip);
869b30d1939SAndy Fiddaman 		}
870b30d1939SAndy Fiddaman 		else
871b30d1939SAndy Fiddaman 			size = sizeof(int32_t);
872b30d1939SAndy Fiddaman 	}
873b30d1939SAndy Fiddaman 	if(!(nval = malloc(size)))
874b30d1939SAndy Fiddaman 		return(0);
875b30d1939SAndy Fiddaman 	memcpy(nval,val,size);
876b30d1939SAndy Fiddaman 	return(nval);
877b30d1939SAndy Fiddaman }
878b30d1939SAndy Fiddaman 
clone_all_disc(Namval_t * np,Namval_t * mp,int flags)879b30d1939SAndy Fiddaman void clone_all_disc( Namval_t *np, Namval_t *mp, int flags)
880b30d1939SAndy Fiddaman {
881b30d1939SAndy Fiddaman 	register Namfun_t *fp, **mfp = &mp->nvfun, *nfp, *fpnext;
882b30d1939SAndy Fiddaman 	for(fp=np->nvfun; fp;fp=fpnext)
883b30d1939SAndy Fiddaman 	{
884b30d1939SAndy Fiddaman 		fpnext = fp->next;
885b30d1939SAndy Fiddaman 		if(!fpnext && (flags&NV_COMVAR) && fp->disc && fp->disc->namef)
886b30d1939SAndy Fiddaman 			return;
887b30d1939SAndy Fiddaman 		if((fp->nofree&2) && (flags&NV_NODISC))
888b30d1939SAndy Fiddaman 			nfp = 0;
889b30d1939SAndy Fiddaman 		if(fp->disc && fp->disc->clonef)
890b30d1939SAndy Fiddaman 			nfp = (*fp->disc->clonef)(np,mp,flags,fp);
891b30d1939SAndy Fiddaman 		else	if(flags&NV_MOVE)
892b30d1939SAndy Fiddaman 			nfp = fp;
893b30d1939SAndy Fiddaman 		else
894b30d1939SAndy Fiddaman 			nfp = nv_clone_disc(fp,flags);
895b30d1939SAndy Fiddaman 		if(!nfp)
896b30d1939SAndy Fiddaman 			continue;
897b30d1939SAndy Fiddaman 		nfp->next = 0;
898b30d1939SAndy Fiddaman 		*mfp = nfp;
899b30d1939SAndy Fiddaman 		mfp = &nfp->next;
900b30d1939SAndy Fiddaman 	}
901b30d1939SAndy Fiddaman }
902b30d1939SAndy Fiddaman 
903b30d1939SAndy Fiddaman /*
904b30d1939SAndy Fiddaman  * clone <mp> from <np> flags can be one of the following
905b30d1939SAndy Fiddaman  * NV_APPEND - append <np> onto <mp>
906b30d1939SAndy Fiddaman  * NV_MOVE - move <np> to <mp>
907b30d1939SAndy Fiddaman  * NV_NOFREE - mark the new node as nofree
908b30d1939SAndy Fiddaman  * NV_NODISC - discplines with funs non-zero will not be copied
909b30d1939SAndy Fiddaman  * NV_COMVAR - cloning a compound variable
910b30d1939SAndy Fiddaman  */
nv_clone(Namval_t * np,Namval_t * mp,int flags)911b30d1939SAndy Fiddaman int nv_clone(Namval_t *np, Namval_t *mp, int flags)
912b30d1939SAndy Fiddaman {
913b30d1939SAndy Fiddaman 	Namfun_t	*fp, *fpnext;
914b30d1939SAndy Fiddaman 	const char	*val = mp->nvalue.cp;
915b30d1939SAndy Fiddaman 	unsigned short	flag = mp->nvflag;
916b30d1939SAndy Fiddaman 	unsigned short	size = mp->nvsize;
917b30d1939SAndy Fiddaman 	for(fp=mp->nvfun; fp; fp=fpnext)
918b30d1939SAndy Fiddaman 	{
919b30d1939SAndy Fiddaman 		fpnext = fp->next;
920b30d1939SAndy Fiddaman 		if(!fpnext && (flags&NV_COMVAR) && fp->disc && fp->disc->namef)
921b30d1939SAndy Fiddaman 			break;
922b30d1939SAndy Fiddaman 		if(!(fp->nofree&1))
923b30d1939SAndy Fiddaman 			free((void*)fp);
924b30d1939SAndy Fiddaman 	}
925b30d1939SAndy Fiddaman 	mp->nvfun = fp;
926b30d1939SAndy Fiddaman 	if(fp=np->nvfun)
927b30d1939SAndy Fiddaman 	{
928b30d1939SAndy Fiddaman 		if(nv_isattr(mp,NV_EXPORT|NV_MINIMAL) == (NV_EXPORT|NV_MINIMAL))
929b30d1939SAndy Fiddaman 		{
930b30d1939SAndy Fiddaman 			mp->nvenv = 0;
931b30d1939SAndy Fiddaman 			nv_offattr(mp,NV_MINIMAL);
932b30d1939SAndy Fiddaman 		}
933b30d1939SAndy Fiddaman 		if(!(flags&NV_COMVAR) && !nv_isattr(np,NV_MINIMAL) && np->nvenv && !(nv_isattr(mp,NV_MINIMAL)))
934b30d1939SAndy Fiddaman 			mp->nvenv = np->nvenv;
935b30d1939SAndy Fiddaman 		mp->nvflag &= NV_MINIMAL;
936b30d1939SAndy Fiddaman 	        mp->nvflag |= np->nvflag&~(NV_ARRAY|NV_MINIMAL|NV_NOFREE);
937b30d1939SAndy Fiddaman 		flag = mp->nvflag;
938b30d1939SAndy Fiddaman 		clone_all_disc(np, mp, flags);
939b30d1939SAndy Fiddaman 	}
940b30d1939SAndy Fiddaman 	if(flags&NV_APPEND)
941b30d1939SAndy Fiddaman 		return(1);
942b30d1939SAndy Fiddaman 	if(mp->nvsize == size)
943b30d1939SAndy Fiddaman 	        nv_setsize(mp,nv_size(np));
944b30d1939SAndy Fiddaman 	if(mp->nvflag == flag)
945b30d1939SAndy Fiddaman 	        mp->nvflag = (np->nvflag&~(NV_MINIMAL))|(mp->nvflag&NV_MINIMAL);
946b30d1939SAndy Fiddaman 	if(nv_isattr(np,NV_EXPORT))
947b30d1939SAndy Fiddaman 		mp->nvflag |= (np->nvflag&NV_MINIMAL);
948b30d1939SAndy Fiddaman 	if(mp->nvalue.cp==val && !nv_isattr(np,NV_INTEGER))
949b30d1939SAndy Fiddaman 	{
950b30d1939SAndy Fiddaman 		if(np->nvalue.cp && np->nvalue.cp!=Empty && (flags&NV_COMVAR) && !(flags&NV_MOVE))
951b30d1939SAndy Fiddaman 		{
952b30d1939SAndy Fiddaman 			if(size)
953b30d1939SAndy Fiddaman 				mp->nvalue.cp = (char*)memdup(np->nvalue.cp,size);
954b30d1939SAndy Fiddaman 			else
955b30d1939SAndy Fiddaman 			        mp->nvalue.cp = strdup(np->nvalue.cp);
956b30d1939SAndy Fiddaman 			nv_offattr(mp,NV_NOFREE);
957b30d1939SAndy Fiddaman 		}
958b30d1939SAndy Fiddaman 		else if((np->nvfun || !nv_isattr(np,NV_ARRAY)) && !(mp->nvalue.cp = np->nvalue.cp))
959b30d1939SAndy Fiddaman 			nv_offattr(mp,NV_NOFREE);
960b30d1939SAndy Fiddaman 	}
961b30d1939SAndy Fiddaman 	if(flags&NV_MOVE)
962b30d1939SAndy Fiddaman 	{
963b30d1939SAndy Fiddaman 		if(nv_isattr(np,NV_INTEGER))
964b30d1939SAndy Fiddaman 			mp->nvalue.ip = np->nvalue.ip;
965b30d1939SAndy Fiddaman 		np->nvfun = 0;
966b30d1939SAndy Fiddaman 		np->nvalue.cp = 0;
967b30d1939SAndy Fiddaman 		if(!nv_isattr(np,NV_MINIMAL) || nv_isattr(mp,NV_EXPORT))
968b30d1939SAndy Fiddaman 		{
969b30d1939SAndy Fiddaman 			mp->nvenv = np->nvenv;
970b30d1939SAndy Fiddaman 			if(nv_isattr(np,NV_MINIMAL))
971b30d1939SAndy Fiddaman 			{
972b30d1939SAndy Fiddaman 				np->nvenv = 0;
973b30d1939SAndy Fiddaman 				np->nvflag = NV_EXPORT;
974b30d1939SAndy Fiddaman 			}
975b30d1939SAndy Fiddaman 			else
976b30d1939SAndy Fiddaman 				np->nvflag = 0;
977b30d1939SAndy Fiddaman 		}
978b30d1939SAndy Fiddaman 		else
979b30d1939SAndy Fiddaman 			np->nvflag &= NV_MINIMAL;
980b30d1939SAndy Fiddaman 	        nv_setsize(np,0);
981b30d1939SAndy Fiddaman 		return(1);
982b30d1939SAndy Fiddaman 	}
983b30d1939SAndy Fiddaman 	else if((flags&NV_ARRAY) && !nv_isattr(np,NV_MINIMAL))
984b30d1939SAndy Fiddaman 		mp->nvenv = np->nvenv;
985b30d1939SAndy Fiddaman 	if(nv_isattr(np,NV_INTEGER) && mp->nvalue.ip!=np->nvalue.ip && np->nvalue.cp!=Empty)
986b30d1939SAndy Fiddaman 	{
987b30d1939SAndy Fiddaman 		mp->nvalue.ip = (int*)num_clone(np,(void*)np->nvalue.ip);
988b30d1939SAndy Fiddaman 		nv_offattr(mp,NV_NOFREE);
989b30d1939SAndy Fiddaman 	}
990b30d1939SAndy Fiddaman 	else if((flags&NV_NOFREE) && !nv_arrayptr(np))
991b30d1939SAndy Fiddaman 	        nv_onattr(np,NV_NOFREE);
992b30d1939SAndy Fiddaman 	return(1);
993b30d1939SAndy Fiddaman }
994b30d1939SAndy Fiddaman 
995b30d1939SAndy Fiddaman /*
996b30d1939SAndy Fiddaman  *  The following discipline is for copy-on-write semantics
997b30d1939SAndy Fiddaman  */
clone_getv(Namval_t * np,Namfun_t * handle)998b30d1939SAndy Fiddaman static char* clone_getv(Namval_t *np, Namfun_t *handle)
999b30d1939SAndy Fiddaman {
1000b30d1939SAndy Fiddaman 	return(np->nvalue.np?nv_getval(np->nvalue.np):0);
1001b30d1939SAndy Fiddaman }
1002b30d1939SAndy Fiddaman 
clone_getn(Namval_t * np,Namfun_t * handle)1003b30d1939SAndy Fiddaman static Sfdouble_t clone_getn(Namval_t *np, Namfun_t *handle)
1004b30d1939SAndy Fiddaman {
1005b30d1939SAndy Fiddaman 	return(np->nvalue.np?nv_getnum(np->nvalue.np):0);
1006b30d1939SAndy Fiddaman }
1007b30d1939SAndy Fiddaman 
clone_putv(Namval_t * np,const char * val,int flags,Namfun_t * handle)1008b30d1939SAndy Fiddaman static void clone_putv(Namval_t *np,const char* val,int flags,Namfun_t *handle)
1009b30d1939SAndy Fiddaman {
1010b30d1939SAndy Fiddaman 	Namfun_t *dp = nv_stack(np,(Namfun_t*)0);
1011b30d1939SAndy Fiddaman 	Namval_t *mp = np->nvalue.np;
1012b30d1939SAndy Fiddaman 	if(!sh.subshell)
1013b30d1939SAndy Fiddaman 		free((void*)dp);
1014b30d1939SAndy Fiddaman 	if(val)
1015b30d1939SAndy Fiddaman 		nv_clone(mp,np,NV_NOFREE);
1016b30d1939SAndy Fiddaman 	np->nvalue.cp = 0;
1017b30d1939SAndy Fiddaman 	nv_putval(np,val,flags);
1018b30d1939SAndy Fiddaman }
1019b30d1939SAndy Fiddaman 
1020b30d1939SAndy Fiddaman static const Namdisc_t clone_disc =
1021b30d1939SAndy Fiddaman {
1022b30d1939SAndy Fiddaman 	0,
1023b30d1939SAndy Fiddaman 	clone_putv,
1024b30d1939SAndy Fiddaman 	clone_getv,
1025b30d1939SAndy Fiddaman 	clone_getn
1026b30d1939SAndy Fiddaman };
1027b30d1939SAndy Fiddaman 
nv_mkclone(Namval_t * mp)1028b30d1939SAndy Fiddaman Namval_t *nv_mkclone(Namval_t *mp)
1029b30d1939SAndy Fiddaman {
1030b30d1939SAndy Fiddaman 	Namval_t *np;
1031b30d1939SAndy Fiddaman 	Namfun_t *dp;
1032b30d1939SAndy Fiddaman 	np = newof(0,Namval_t,1,0);
1033b30d1939SAndy Fiddaman 	np->nvflag = mp->nvflag;
1034b30d1939SAndy Fiddaman 	np->nvsize = mp->nvsize;
1035b30d1939SAndy Fiddaman 	np->nvname = mp->nvname;
1036b30d1939SAndy Fiddaman 	np->nvalue.np = mp;
1037b30d1939SAndy Fiddaman 	np->nvflag = mp->nvflag;
1038b30d1939SAndy Fiddaman 	dp = newof(0,Namfun_t,1,0);
1039b30d1939SAndy Fiddaman 	dp->disc = &clone_disc;
1040b30d1939SAndy Fiddaman 	nv_stack(np,dp);
1041b30d1939SAndy Fiddaman 	dtinsert(nv_dict(sh.namespace),np);
1042b30d1939SAndy Fiddaman 	return(np);
1043b30d1939SAndy Fiddaman }
1044b30d1939SAndy Fiddaman 
nv_search(const char * name,Dt_t * root,int mode)1045b30d1939SAndy Fiddaman Namval_t *nv_search(const char *name, Dt_t *root, int mode)
1046b30d1939SAndy Fiddaman {
1047b30d1939SAndy Fiddaman 	register Namval_t *np;
1048b30d1939SAndy Fiddaman 	register Dt_t *dp = 0;
1049b30d1939SAndy Fiddaman 	if(mode&HASH_NOSCOPE)
1050b30d1939SAndy Fiddaman 		dp = dtview(root,0);
1051b30d1939SAndy Fiddaman 	if(mode&HASH_BUCKET)
1052b30d1939SAndy Fiddaman 	{
1053b30d1939SAndy Fiddaman 		Namval_t *mp = (void*)name;
1054b30d1939SAndy Fiddaman 		if(!(np = dtsearch(root,mp)) && (mode&NV_ADD))
1055b30d1939SAndy Fiddaman 			name = nv_name(mp);
1056b30d1939SAndy Fiddaman 	}
1057b30d1939SAndy Fiddaman 	else
1058b30d1939SAndy Fiddaman 	{
1059b30d1939SAndy Fiddaman 		if(*name=='.' && root==sh.var_tree && !dp)
1060b30d1939SAndy Fiddaman 			root = sh.var_base;
1061b30d1939SAndy Fiddaman 		np = dtmatch(root,(void*)name);
1062b30d1939SAndy Fiddaman 	}
1063b30d1939SAndy Fiddaman #if SHOPT_COSHELL
1064b30d1939SAndy Fiddaman 	if(sh.inpool)
1065b30d1939SAndy Fiddaman 		mode |= HASH_NOSCOPE;
1066b30d1939SAndy Fiddaman #endif /* SHOPT_COSHELL */
1067b30d1939SAndy Fiddaman 	if(!np && (mode&NV_ADD))
1068b30d1939SAndy Fiddaman 	{
1069b30d1939SAndy Fiddaman 		if(sh.namespace && !(mode&HASH_NOSCOPE) && root==sh.var_tree)
1070b30d1939SAndy Fiddaman 			root = nv_dict(sh.namespace);
1071b30d1939SAndy Fiddaman 		else if(!dp && !(mode&HASH_NOSCOPE))
1072b30d1939SAndy Fiddaman 		{
1073b30d1939SAndy Fiddaman 			register Dt_t *next;
1074b30d1939SAndy Fiddaman 			while(next=dtvnext(root))
1075b30d1939SAndy Fiddaman 				root = next;
1076b30d1939SAndy Fiddaman 		}
1077b30d1939SAndy Fiddaman 		np = (Namval_t*)dtinsert(root,newnode(name));
1078b30d1939SAndy Fiddaman 	}
1079b30d1939SAndy Fiddaman 	if(dp)
1080b30d1939SAndy Fiddaman 		dtview(root,dp);
1081b30d1939SAndy Fiddaman 	return(np);
1082b30d1939SAndy Fiddaman }
1083b30d1939SAndy Fiddaman 
1084b30d1939SAndy Fiddaman /*
1085b30d1939SAndy Fiddaman  * finds function or builtin for given name and the discipline variable
1086b30d1939SAndy Fiddaman  * if var!=0 the variable pointer is returned and the built-in name
1087b30d1939SAndy Fiddaman  *    is put onto the stack at the current offset.
1088b30d1939SAndy Fiddaman  * otherwise, a pointer to the builtin (variable or type) is returned
1089b30d1939SAndy Fiddaman  * and var contains the poiner to the variable
1090b30d1939SAndy Fiddaman  * if last==0 and first component of name is a reference, nv_bfsearch()
1091b30d1939SAndy Fiddaman 	will return 0.
1092b30d1939SAndy Fiddaman  */
nv_bfsearch(const char * name,Dt_t * root,Namval_t ** var,char ** last)1093b30d1939SAndy Fiddaman Namval_t *nv_bfsearch(const char *name, Dt_t *root, Namval_t **var, char **last)
1094b30d1939SAndy Fiddaman {
1095b30d1939SAndy Fiddaman 	Shell_t		*shp = sh_getinterp();
1096b30d1939SAndy Fiddaman 	int		c,offset = staktell();
1097b30d1939SAndy Fiddaman 	register char	*sp, *cp=0;
1098b30d1939SAndy Fiddaman 	Namval_t	*np, *nq;
1099b30d1939SAndy Fiddaman 	char		*dname=0;
1100b30d1939SAndy Fiddaman 	if(var)
1101b30d1939SAndy Fiddaman 		*var = 0;
1102b30d1939SAndy Fiddaman 	/* check for . in the name before = */
1103b30d1939SAndy Fiddaman 	for(sp=(char*)name+1; *sp; sp++)
1104b30d1939SAndy Fiddaman 	{
1105b30d1939SAndy Fiddaman 		if(*sp=='=')
1106b30d1939SAndy Fiddaman 			return(0);
1107b30d1939SAndy Fiddaman 		if(*sp=='[')
1108b30d1939SAndy Fiddaman 		{
1109b30d1939SAndy Fiddaman 			while(*sp=='[')
1110b30d1939SAndy Fiddaman 			{
1111b30d1939SAndy Fiddaman 				sp = nv_endsubscript((Namval_t*)0,(char*)sp,0);
1112b30d1939SAndy Fiddaman 				if(sp[-1]!=']')
1113b30d1939SAndy Fiddaman 					return(0);
1114b30d1939SAndy Fiddaman 			}
1115b30d1939SAndy Fiddaman 			if(*sp==0)
1116b30d1939SAndy Fiddaman 				break;
1117b30d1939SAndy Fiddaman 			if(*sp!='.')
1118b30d1939SAndy Fiddaman 				return(0);
1119b30d1939SAndy Fiddaman 			cp = sp;
1120b30d1939SAndy Fiddaman 		}
1121b30d1939SAndy Fiddaman 		else if(*sp=='.')
1122b30d1939SAndy Fiddaman 			cp = sp;
1123b30d1939SAndy Fiddaman 	}
1124b30d1939SAndy Fiddaman 	if(!cp)
1125b30d1939SAndy Fiddaman 		return(var?nv_search(name,root,0):0);
1126b30d1939SAndy Fiddaman 	stakputs(name);
1127b30d1939SAndy Fiddaman 	stakputc(0);
1128b30d1939SAndy Fiddaman 	dname = cp+1;
1129b30d1939SAndy Fiddaman 	cp = stakptr(offset) + (cp-name);
1130b30d1939SAndy Fiddaman 	if(last)
1131b30d1939SAndy Fiddaman 		*last = cp;
1132b30d1939SAndy Fiddaman 	c = *cp;
1133b30d1939SAndy Fiddaman 	*cp = 0;
1134b30d1939SAndy Fiddaman 	nq=nv_open(stakptr(offset),0,NV_VARNAME|NV_NOASSIGN|NV_NOADD|NV_NOFAIL);
1135b30d1939SAndy Fiddaman 	*cp = c;
1136b30d1939SAndy Fiddaman 	if(!nq)
1137b30d1939SAndy Fiddaman 	{
1138b30d1939SAndy Fiddaman 		np = 0;
1139b30d1939SAndy Fiddaman 		goto done;
1140b30d1939SAndy Fiddaman 	}
1141b30d1939SAndy Fiddaman 	if(!var)
1142b30d1939SAndy Fiddaman 	{
1143b30d1939SAndy Fiddaman 		np = nq;
1144b30d1939SAndy Fiddaman 		goto done;
1145b30d1939SAndy Fiddaman 	}
1146b30d1939SAndy Fiddaman 	*var = nq;
1147b30d1939SAndy Fiddaman 	if(c=='[')
1148b30d1939SAndy Fiddaman 		nv_endsubscript(nq, cp,NV_NOADD);
1149b30d1939SAndy Fiddaman 	stakseek(offset);
1150b30d1939SAndy Fiddaman #if SHOPT_NAMESPACE
1151b30d1939SAndy Fiddaman 	if(nv_istable(nq))
1152b30d1939SAndy Fiddaman 	{
1153b30d1939SAndy Fiddaman 		Namval_t *nsp = shp->namespace;
1154b30d1939SAndy Fiddaman 		if(last==0)
1155b30d1939SAndy Fiddaman 			return(nv_search(name,root,0));
1156b30d1939SAndy Fiddaman 		shp->namespace = 0;
1157b30d1939SAndy Fiddaman 		stakputs(nv_name(nq));
1158b30d1939SAndy Fiddaman 		shp->namespace = nsp;
1159b30d1939SAndy Fiddaman 		stakputs(dname-1);
1160b30d1939SAndy Fiddaman 		stakputc(0);
1161b30d1939SAndy Fiddaman 		np = nv_search(stakptr(offset),root,0);
1162b30d1939SAndy Fiddaman 		stakseek(offset);
1163b30d1939SAndy Fiddaman 		return(np);
1164b30d1939SAndy Fiddaman 	}
1165b30d1939SAndy Fiddaman #endif /* SHOPT_NAMESPACE */
1166b30d1939SAndy Fiddaman 	while(nv_isarray(nq) && !nv_isattr(nq,NV_MINIMAL|NV_EXPORT) && nq->nvenv && nv_isarray((Namval_t*)nq->nvenv))
1167b30d1939SAndy Fiddaman 		nq = (Namval_t*)nq->nvenv;
1168b30d1939SAndy Fiddaman 	return((Namval_t*)nv_setdisc(nq,dname,nq,(Namfun_t*)nq));
1169b30d1939SAndy Fiddaman done:
1170b30d1939SAndy Fiddaman 	stakseek(offset);
1171b30d1939SAndy Fiddaman 	return(np);
1172b30d1939SAndy Fiddaman }
1173b30d1939SAndy Fiddaman 
1174b30d1939SAndy Fiddaman /*
1175b30d1939SAndy Fiddaman  * add or replace built-in version of command corresponding to <path>
1176b30d1939SAndy Fiddaman  * The <bltin> argument is a pointer to the built-in
1177b30d1939SAndy Fiddaman  * if <extra>==1, the built-in will be deleted
1178b30d1939SAndy Fiddaman  * Special builtins cannot be added or deleted return failure
1179b30d1939SAndy Fiddaman  * The return value for adding builtins is a pointer to the node or NULL on
1180b30d1939SAndy Fiddaman  *   failure.  For delete NULL means success and the node that cannot be
1181b30d1939SAndy Fiddaman  *   deleted is returned on failure.
1182b30d1939SAndy Fiddaman  */
sh_addbuiltin(const char * path,Shbltin_f bltin,void * extra)1183b30d1939SAndy Fiddaman Namval_t *sh_addbuiltin(const char *path, Shbltin_f bltin, void *extra)
1184b30d1939SAndy Fiddaman {
1185b30d1939SAndy Fiddaman 	register const char	*name;
1186b30d1939SAndy Fiddaman 	char			*cp;
1187b30d1939SAndy Fiddaman 	register Namval_t	*np, *nq=0;
1188b30d1939SAndy Fiddaman 	int			offset=staktell();
1189b30d1939SAndy Fiddaman 	if(extra==(void*)1)
1190b30d1939SAndy Fiddaman 		name = path;
1191b30d1939SAndy Fiddaman 	else if((name = path_basename(path))==path && bltin!=(Shbltin_f)SYSTYPESET->nvalue.bfp && (nq=nv_bfsearch(name,sh.bltin_tree,(Namval_t**)0,&cp)))
1192b30d1939SAndy Fiddaman 		path = name = stakptr(offset);
1193b30d1939SAndy Fiddaman 	else if(sh.bltin_dir && extra!=(void*)1)
1194b30d1939SAndy Fiddaman 	{
1195b30d1939SAndy Fiddaman 		stakputs(sh.bltin_dir);
1196b30d1939SAndy Fiddaman 		stakputc('/');
1197b30d1939SAndy Fiddaman 		stakputs(name);
1198b30d1939SAndy Fiddaman 		path = stakptr(offset);
1199b30d1939SAndy Fiddaman 	}
1200b30d1939SAndy Fiddaman 	if(np = nv_search(name,sh.bltin_tree,0))
1201b30d1939SAndy Fiddaman 	{
1202b30d1939SAndy Fiddaman 		/* exists without a path */
1203b30d1939SAndy Fiddaman 		stakseek(offset);
1204b30d1939SAndy Fiddaman 		if(extra == (void*)1)
1205b30d1939SAndy Fiddaman 		{
1206b30d1939SAndy Fiddaman 			if(np->nvfun && !nv_isattr(np,NV_NOFREE))
1207b30d1939SAndy Fiddaman 				free((void*)np->nvfun);
1208b30d1939SAndy Fiddaman 			dtdelete(sh.bltin_tree,np);
1209b30d1939SAndy Fiddaman 			return(0);
1210b30d1939SAndy Fiddaman 		}
1211b30d1939SAndy Fiddaman 		if(!bltin)
1212b30d1939SAndy Fiddaman 			return(np);
1213b30d1939SAndy Fiddaman 	}
1214b30d1939SAndy Fiddaman 	else for(np=(Namval_t*)dtfirst(sh.bltin_tree);np;np=(Namval_t*)dtnext(sh.bltin_tree,np))
1215b30d1939SAndy Fiddaman 	{
1216b30d1939SAndy Fiddaman 		if(strcmp(name,path_basename(nv_name(np))))
1217b30d1939SAndy Fiddaman 			continue;
1218b30d1939SAndy Fiddaman 		/* exists probably with different path so delete it */
1219b30d1939SAndy Fiddaman 		if(strcmp(path,nv_name(np)))
1220b30d1939SAndy Fiddaman 		{
1221b30d1939SAndy Fiddaman 			if(nv_isattr(np,BLT_SPC))
1222b30d1939SAndy Fiddaman 				return(np);
1223b30d1939SAndy Fiddaman 			if(!bltin)
1224b30d1939SAndy Fiddaman 				bltin = (Shbltin_f)np->nvalue.bfp;
1225b30d1939SAndy Fiddaman 			if(np->nvenv)
1226b30d1939SAndy Fiddaman 				dtdelete(sh.bltin_tree,np);
1227b30d1939SAndy Fiddaman 			if(extra == (void*)1)
1228b30d1939SAndy Fiddaman 				return(0);
1229b30d1939SAndy Fiddaman 			np = 0;
1230b30d1939SAndy Fiddaman 		}
1231b30d1939SAndy Fiddaman 		break;
1232b30d1939SAndy Fiddaman 	}
1233b30d1939SAndy Fiddaman 	if(!np && !(np = nv_search(path,sh.bltin_tree,bltin?NV_ADD:0)))
1234b30d1939SAndy Fiddaman 		return(0);
1235b30d1939SAndy Fiddaman 	stakseek(offset);
1236b30d1939SAndy Fiddaman 	if(nv_isattr(np,BLT_SPC))
1237b30d1939SAndy Fiddaman 	{
1238b30d1939SAndy Fiddaman 		if(extra)
1239b30d1939SAndy Fiddaman 			np->nvfun = (Namfun_t*)extra;
1240b30d1939SAndy Fiddaman 		return(np);
1241b30d1939SAndy Fiddaman 	}
1242b30d1939SAndy Fiddaman 	np->nvenv = 0;
1243b30d1939SAndy Fiddaman 	np->nvfun = 0;
1244b30d1939SAndy Fiddaman 	if(bltin)
1245b30d1939SAndy Fiddaman 	{
1246b30d1939SAndy Fiddaman 		np->nvalue.bfp = (Nambfp_f)bltin;
1247b30d1939SAndy Fiddaman 		nv_onattr(np,NV_BLTIN|NV_NOFREE);
1248b30d1939SAndy Fiddaman 		np->nvfun = (Namfun_t*)extra;
1249b30d1939SAndy Fiddaman 	}
1250b30d1939SAndy Fiddaman 	if(nq)
1251b30d1939SAndy Fiddaman 	{
1252b30d1939SAndy Fiddaman 		cp=nv_setdisc(nq,cp+1,np,(Namfun_t*)nq);
1253b30d1939SAndy Fiddaman 		nv_close(nq);
1254b30d1939SAndy Fiddaman 		if(!cp)
1255b30d1939SAndy Fiddaman 			errormsg(SH_DICT,ERROR_exit(1),e_baddisc,name);
1256b30d1939SAndy Fiddaman 	}
1257b30d1939SAndy Fiddaman 	if(extra == (void*)1)
1258b30d1939SAndy Fiddaman 		return(0);
1259b30d1939SAndy Fiddaman 	return(np);
1260b30d1939SAndy Fiddaman }
1261b30d1939SAndy Fiddaman 
1262b30d1939SAndy Fiddaman #undef nv_stack
nv_stack(register Namval_t * np,register Namfun_t * fp)1263b30d1939SAndy Fiddaman extern Namfun_t *nv_stack(register Namval_t *np, register Namfun_t* fp)
1264b30d1939SAndy Fiddaman {
1265b30d1939SAndy Fiddaman 	return(nv_disc(np,fp,0));
1266b30d1939SAndy Fiddaman }
1267b30d1939SAndy Fiddaman 
1268b30d1939SAndy Fiddaman struct table
1269b30d1939SAndy Fiddaman {
1270b30d1939SAndy Fiddaman 	Namfun_t	fun;
1271b30d1939SAndy Fiddaman 	Namval_t	*parent;
1272b30d1939SAndy Fiddaman 	Shell_t		*shp;
1273b30d1939SAndy Fiddaman 	Dt_t		*dict;
1274b30d1939SAndy Fiddaman };
1275b30d1939SAndy Fiddaman 
next_table(register Namval_t * np,Dt_t * root,Namfun_t * fp)1276b30d1939SAndy Fiddaman static Namval_t *next_table(register Namval_t* np, Dt_t *root,Namfun_t *fp)
1277b30d1939SAndy Fiddaman {
1278b30d1939SAndy Fiddaman 	struct table *tp = (struct table *)fp;
1279b30d1939SAndy Fiddaman 	if(root)
1280b30d1939SAndy Fiddaman 		return((Namval_t*)dtnext(root,np));
1281b30d1939SAndy Fiddaman 	else
1282b30d1939SAndy Fiddaman 		return((Namval_t*)dtfirst(tp->dict));
1283b30d1939SAndy Fiddaman }
1284b30d1939SAndy Fiddaman 
create_table(Namval_t * np,const char * name,int flags,Namfun_t * fp)1285b30d1939SAndy Fiddaman static Namval_t *create_table(Namval_t *np,const char *name,int flags,Namfun_t *fp)
1286b30d1939SAndy Fiddaman {
1287b30d1939SAndy Fiddaman 	struct table *tp = (struct table *)fp;
1288b30d1939SAndy Fiddaman 	tp->shp->last_table = np;
1289b30d1939SAndy Fiddaman 	return(nv_create(name, tp->dict, flags, fp));
1290b30d1939SAndy Fiddaman }
1291b30d1939SAndy Fiddaman 
clone_table(Namval_t * np,Namval_t * mp,int flags,Namfun_t * fp)1292b30d1939SAndy Fiddaman static Namfun_t *clone_table(Namval_t* np, Namval_t *mp, int flags, Namfun_t *fp)
1293b30d1939SAndy Fiddaman {
1294b30d1939SAndy Fiddaman 	struct table	*tp = (struct table*)fp;
1295b30d1939SAndy Fiddaman 	struct table	*ntp = (struct table*)nv_clone_disc(fp,0);
1296b30d1939SAndy Fiddaman 	Dt_t		*oroot=tp->dict,*nroot=dtopen(&_Nvdisc,Dtoset);
1297b30d1939SAndy Fiddaman 	if(!nroot)
1298b30d1939SAndy Fiddaman 		return(0);
1299b30d1939SAndy Fiddaman 	memcpy((void*)ntp,(void*)fp,sizeof(struct table));
1300b30d1939SAndy Fiddaman 	ntp->dict = nroot;
1301b30d1939SAndy Fiddaman 	ntp->parent = nv_lastdict();
1302b30d1939SAndy Fiddaman 	for(np=(Namval_t*)dtfirst(oroot);np;np=(Namval_t*)dtnext(oroot,np))
1303b30d1939SAndy Fiddaman 	{
1304b30d1939SAndy Fiddaman 		mp = (Namval_t*)dtinsert(nroot,newnode(np->nvname));
1305b30d1939SAndy Fiddaman 		nv_clone(np,mp,flags);
1306b30d1939SAndy Fiddaman 	}
1307b30d1939SAndy Fiddaman 	return(&ntp->fun);
1308b30d1939SAndy Fiddaman }
1309b30d1939SAndy Fiddaman 
1310b30d1939SAndy Fiddaman struct adata
1311b30d1939SAndy Fiddaman {
1312b30d1939SAndy Fiddaman 	Shell_t		*sh;
1313b30d1939SAndy Fiddaman 	Namval_t	*tp;
1314b30d1939SAndy Fiddaman 	char		*mapname;
1315b30d1939SAndy Fiddaman 	char		**argnam;
1316b30d1939SAndy Fiddaman 	int		attsize;
1317b30d1939SAndy Fiddaman 	char		*attval;
1318b30d1939SAndy Fiddaman };
1319b30d1939SAndy Fiddaman 
delete_fun(Namval_t * np,void * data)1320b30d1939SAndy Fiddaman static void delete_fun(Namval_t *np, void *data)
1321b30d1939SAndy Fiddaman {
1322b30d1939SAndy Fiddaman 	Shell_t *shp = ((struct adata*)data)->sh;
1323b30d1939SAndy Fiddaman 	nv_delete(np,shp->fun_tree,NV_NOFREE);
1324b30d1939SAndy Fiddaman }
1325b30d1939SAndy Fiddaman 
put_table(register Namval_t * np,const char * val,int flags,Namfun_t * fp)1326b30d1939SAndy Fiddaman static void put_table(register Namval_t* np, const char* val, int flags, Namfun_t* fp)
1327b30d1939SAndy Fiddaman {
1328b30d1939SAndy Fiddaman 	register Dt_t		*root = ((struct table*)fp)->dict;
1329b30d1939SAndy Fiddaman 	register Namval_t	*nq, *mp;
1330b30d1939SAndy Fiddaman 	Namarr_t		*ap;
1331b30d1939SAndy Fiddaman 	struct adata		data;
1332b30d1939SAndy Fiddaman 	if(val)
1333b30d1939SAndy Fiddaman 	{
1334b30d1939SAndy Fiddaman 		nv_putv(np,val,flags,fp);
1335b30d1939SAndy Fiddaman 		return;
1336b30d1939SAndy Fiddaman 	}
1337b30d1939SAndy Fiddaman 	if(nv_isarray(np) && (ap=nv_arrayptr(np)) && array_elem(ap))
1338b30d1939SAndy Fiddaman 		return;
1339b30d1939SAndy Fiddaman 	memset(&data,0,sizeof(data));
1340b30d1939SAndy Fiddaman 	data.mapname = nv_name(np);
1341b30d1939SAndy Fiddaman 	data.sh = ((struct table*)fp)->shp;
1342b30d1939SAndy Fiddaman 	nv_scan(data.sh->fun_tree,delete_fun,(void*)&data,NV_FUNCTION,NV_FUNCTION|NV_NOSCOPE);
1343b30d1939SAndy Fiddaman 	dtview(root,0);
1344b30d1939SAndy Fiddaman 	for(mp=(Namval_t*)dtfirst(root);mp;mp=nq)
1345b30d1939SAndy Fiddaman 	{
1346b30d1939SAndy Fiddaman 		_nv_unset(mp,flags);
1347b30d1939SAndy Fiddaman 		nq = (Namval_t*)dtnext(root,mp);
1348b30d1939SAndy Fiddaman 		dtdelete(root,mp);
1349b30d1939SAndy Fiddaman 		free((void*)mp);
1350b30d1939SAndy Fiddaman 	}
1351b30d1939SAndy Fiddaman 	dtclose(root);
1352b30d1939SAndy Fiddaman 	if(!(fp->nofree&1))
1353b30d1939SAndy Fiddaman 		free((void*)fp);
1354b30d1939SAndy Fiddaman 	np->nvfun = 0;
1355b30d1939SAndy Fiddaman }
1356b30d1939SAndy Fiddaman 
1357b30d1939SAndy Fiddaman /*
1358b30d1939SAndy Fiddaman  * return space separated list of names of variables in given tree
1359b30d1939SAndy Fiddaman  */
get_table(Namval_t * np,Namfun_t * fp)1360b30d1939SAndy Fiddaman static char *get_table(Namval_t *np, Namfun_t *fp)
1361b30d1939SAndy Fiddaman {
1362b30d1939SAndy Fiddaman 	register Dt_t *root = ((struct table*)fp)->dict;
1363b30d1939SAndy Fiddaman 	static Sfio_t *out;
1364b30d1939SAndy Fiddaman 	register int first=1;
1365b30d1939SAndy Fiddaman 	register Dt_t *base = dtview(root,0);
1366b30d1939SAndy Fiddaman         if(out)
1367b30d1939SAndy Fiddaman                 sfseek(out,(Sfoff_t)0,SEEK_SET);
1368b30d1939SAndy Fiddaman         else
1369b30d1939SAndy Fiddaman                 out =  sfnew((Sfio_t*)0,(char*)0,-1,-1,SF_WRITE|SF_STRING);
1370b30d1939SAndy Fiddaman 	for(np=(Namval_t*)dtfirst(root);np;np=(Namval_t*)dtnext(root,np))
1371b30d1939SAndy Fiddaman 	{
1372b30d1939SAndy Fiddaman                 if(!nv_isnull(np) || np->nvfun || nv_isattr(np,~NV_NOFREE))
1373b30d1939SAndy Fiddaman 		{
1374b30d1939SAndy Fiddaman 			if(!first)
1375b30d1939SAndy Fiddaman 				sfputc(out,' ');
1376b30d1939SAndy Fiddaman 			else
1377b30d1939SAndy Fiddaman 				first = 0;
1378b30d1939SAndy Fiddaman 			sfputr(out,np->nvname,-1);
1379b30d1939SAndy Fiddaman 		}
1380b30d1939SAndy Fiddaman 	}
1381b30d1939SAndy Fiddaman 	sfputc(out,0);
1382b30d1939SAndy Fiddaman 	if(base)
1383b30d1939SAndy Fiddaman 		dtview(root,base);
1384b30d1939SAndy Fiddaman 	return((char*)out->_data);
1385b30d1939SAndy Fiddaman }
1386b30d1939SAndy Fiddaman 
1387b30d1939SAndy Fiddaman static const Namdisc_t table_disc =
1388b30d1939SAndy Fiddaman {
1389b30d1939SAndy Fiddaman         sizeof(struct table),
1390b30d1939SAndy Fiddaman         put_table,
1391b30d1939SAndy Fiddaman         get_table,
1392b30d1939SAndy Fiddaman         0,
1393b30d1939SAndy Fiddaman         0,
1394b30d1939SAndy Fiddaman         create_table,
1395b30d1939SAndy Fiddaman         clone_table,
1396b30d1939SAndy Fiddaman         0,
1397b30d1939SAndy Fiddaman         next_table,
1398b30d1939SAndy Fiddaman };
1399b30d1939SAndy Fiddaman 
nv_parent(Namval_t * np)1400b30d1939SAndy Fiddaman Namval_t *nv_parent(Namval_t *np)
1401b30d1939SAndy Fiddaman {
1402b30d1939SAndy Fiddaman 	struct table *tp = (struct table *)nv_hasdisc(np,&table_disc);
1403b30d1939SAndy Fiddaman 	if(tp)
1404b30d1939SAndy Fiddaman 		return(tp->parent);
1405b30d1939SAndy Fiddaman 	return(0);
1406b30d1939SAndy Fiddaman }
1407b30d1939SAndy Fiddaman 
nv_dict(Namval_t * np)1408b30d1939SAndy Fiddaman Dt_t *nv_dict(Namval_t* np)
1409b30d1939SAndy Fiddaman {
1410b30d1939SAndy Fiddaman 	Shell_t 	*shp=sh_getinterp();
1411b30d1939SAndy Fiddaman 	struct table *tp = (struct table*)nv_hasdisc(np,&table_disc);
1412b30d1939SAndy Fiddaman 	if(tp)
1413b30d1939SAndy Fiddaman 		return(tp->dict);
1414b30d1939SAndy Fiddaman 	np = shp->last_table;
1415b30d1939SAndy Fiddaman 	while(np)
1416b30d1939SAndy Fiddaman 	{
1417b30d1939SAndy Fiddaman 		if(tp = (struct table*)nv_hasdisc(np,&table_disc))
1418b30d1939SAndy Fiddaman 			return(tp->dict);
1419b30d1939SAndy Fiddaman #if 0
1420b30d1939SAndy Fiddaman 		np = nv_create(np,(const char*)0, NV_FIRST, (Namfun_t*)0);
1421b30d1939SAndy Fiddaman #else
1422b30d1939SAndy Fiddaman 		break;
1423b30d1939SAndy Fiddaman #endif
1424b30d1939SAndy Fiddaman 	}
1425b30d1939SAndy Fiddaman 	return(shp->var_tree);
1426b30d1939SAndy Fiddaman }
1427b30d1939SAndy Fiddaman 
nv_istable(Namval_t * np)1428b30d1939SAndy Fiddaman int nv_istable(Namval_t *np)
1429b30d1939SAndy Fiddaman {
1430b30d1939SAndy Fiddaman 	return(nv_hasdisc(np,&table_disc)!=0);
1431b30d1939SAndy Fiddaman }
1432b30d1939SAndy Fiddaman 
1433b30d1939SAndy Fiddaman /*
1434b30d1939SAndy Fiddaman  * create a mountable name-value pair tree
1435b30d1939SAndy Fiddaman  */
nv_mount(Namval_t * np,const char * name,Dt_t * dict)1436b30d1939SAndy Fiddaman Namval_t *nv_mount(Namval_t *np, const char *name, Dt_t *dict)
1437b30d1939SAndy Fiddaman {
1438b30d1939SAndy Fiddaman 	Namval_t *mp, *pp;
1439b30d1939SAndy Fiddaman 	struct table *tp;
1440b30d1939SAndy Fiddaman 	if(nv_hasdisc(np,&table_disc))
1441b30d1939SAndy Fiddaman 		pp = np;
1442b30d1939SAndy Fiddaman 	else
1443b30d1939SAndy Fiddaman 		pp = nv_lastdict();
1444b30d1939SAndy Fiddaman 	if(!(tp = newof((struct table*)0, struct table,1,0)))
1445b30d1939SAndy Fiddaman 		return(0);
1446b30d1939SAndy Fiddaman 	if(name)
1447b30d1939SAndy Fiddaman 	{
1448b30d1939SAndy Fiddaman 		Namfun_t *fp = pp->nvfun;
1449b30d1939SAndy Fiddaman 		mp = (*fp->disc->createf)(pp,name,0,fp);
1450b30d1939SAndy Fiddaman 	}
1451b30d1939SAndy Fiddaman 	else
1452b30d1939SAndy Fiddaman 		mp = np;
1453b30d1939SAndy Fiddaman 	nv_offattr(mp,NV_TABLE);
1454b30d1939SAndy Fiddaman 	if(!nv_isnull(mp))
1455b30d1939SAndy Fiddaman 		_nv_unset(mp,NV_RDONLY);
1456b30d1939SAndy Fiddaman 	tp->shp = sh_getinterp();
1457b30d1939SAndy Fiddaman 	tp->dict = dict;
1458b30d1939SAndy Fiddaman 	tp->parent = pp;
1459b30d1939SAndy Fiddaman 	tp->fun.disc = &table_disc;
1460b30d1939SAndy Fiddaman 	nv_disc(mp, &tp->fun, NV_FIRST);
1461b30d1939SAndy Fiddaman 	return(mp);
1462b30d1939SAndy Fiddaman }
1463b30d1939SAndy Fiddaman 
nv_discfun(int which)1464b30d1939SAndy Fiddaman const Namdisc_t *nv_discfun(int which)
1465b30d1939SAndy Fiddaman {
1466b30d1939SAndy Fiddaman 	switch(which)
1467b30d1939SAndy Fiddaman 	{
1468b30d1939SAndy Fiddaman 	    case NV_DCADD:
1469b30d1939SAndy Fiddaman 		return(&Nv_bdisc);
1470b30d1939SAndy Fiddaman 	    case NV_DCRESTRICT:
1471b30d1939SAndy Fiddaman 		return(&RESTRICTED_disc);
1472b30d1939SAndy Fiddaman 	}
1473b30d1939SAndy Fiddaman 	return(0);
1474b30d1939SAndy Fiddaman }
1475b30d1939SAndy Fiddaman 
nv_hasget(Namval_t * np)1476b30d1939SAndy Fiddaman int nv_hasget(Namval_t *np)
1477b30d1939SAndy Fiddaman {
1478b30d1939SAndy Fiddaman 	register Namfun_t	*fp;
1479b30d1939SAndy Fiddaman 	for(fp=np->nvfun; fp; fp=fp->next)
1480b30d1939SAndy Fiddaman 	{
1481b30d1939SAndy Fiddaman 		if(!fp->disc || (!fp->disc->getnum && !fp->disc->getval))
1482b30d1939SAndy Fiddaman 			continue;
1483b30d1939SAndy Fiddaman 		return(1);
1484b30d1939SAndy Fiddaman 	}
1485b30d1939SAndy Fiddaman 	return(0);
1486b30d1939SAndy Fiddaman }
1487b30d1939SAndy Fiddaman 
1488b30d1939SAndy Fiddaman #if SHOPT_NAMESPACE
sh_fsearch(Shell_t * shp,const char * fname,int add)1489b30d1939SAndy Fiddaman Namval_t *sh_fsearch(Shell_t *shp, const char *fname, int add)
1490b30d1939SAndy Fiddaman {
1491b30d1939SAndy Fiddaman 	Stk_t	*stkp = shp->stk;
1492b30d1939SAndy Fiddaman 	int	offset = stktell(stkp);
1493b30d1939SAndy Fiddaman 	sfputr(stkp,nv_name(shp->namespace),'.');
1494b30d1939SAndy Fiddaman 	sfputr(stkp,fname,0);
1495b30d1939SAndy Fiddaman 	fname = stkptr(stkp,offset);
1496b30d1939SAndy Fiddaman 	return(nv_search(fname,sh_subfuntree(add&NV_ADD),add));
1497b30d1939SAndy Fiddaman }
1498b30d1939SAndy Fiddaman #endif /* SHOPT_NAMESPACE */
1499