1da2e3ebdSchin /***********************************************************************
2da2e3ebdSchin * *
3da2e3ebdSchin * This software is part of the ast package *
4b30d1939SAndy Fiddaman * Copyright (c) 1982-2012 AT&T Intellectual Property *
5da2e3ebdSchin * and is licensed under the *
6b30d1939SAndy Fiddaman * Eclipse Public License, Version 1.0 *
77c2fbfb3SApril Chin * by AT&T Intellectual Property *
8da2e3ebdSchin * *
9da2e3ebdSchin * 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) *
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 * AT&T Labs
23da2e3ebdSchin *
24da2e3ebdSchin */
25da2e3ebdSchin
26da2e3ebdSchin #include "defs.h"
27da2e3ebdSchin #include "variables.h"
28da2e3ebdSchin #include "builtins.h"
29da2e3ebdSchin #include "path.h"
30da2e3ebdSchin
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)33da2e3ebdSchin int nv_compare(Dt_t* dict, Void_t *sp, Void_t *dp, Dtdisc_t *disc)
34da2e3ebdSchin {
35da2e3ebdSchin if(sp==dp)
36da2e3ebdSchin return(0);
37da2e3ebdSchin return(strcmp((char*)sp,(char*)dp));
38da2e3ebdSchin }
39da2e3ebdSchin
40da2e3ebdSchin /*
41da2e3ebdSchin * call the next getval function in the chain
42da2e3ebdSchin */
nv_getv(Namval_t * np,register Namfun_t * nfp)43da2e3ebdSchin char *nv_getv(Namval_t *np, register Namfun_t *nfp)
44da2e3ebdSchin {
45da2e3ebdSchin register Namfun_t *fp;
46da2e3ebdSchin register char *cp;
47da2e3ebdSchin if((fp = nfp) != NIL(Namfun_t*) && !nv_local)
48da2e3ebdSchin fp = nfp = nfp->next;
49da2e3ebdSchin nv_local=0;
50da2e3ebdSchin for(; fp; fp=fp->next)
51da2e3ebdSchin {
52da2e3ebdSchin if(!fp->disc || (!fp->disc->getnum && !fp->disc->getval))
53da2e3ebdSchin continue;
54da2e3ebdSchin if(!nv_isattr(np,NV_NODISC) || fp==(Namfun_t*)nv_arrayptr(np))
55da2e3ebdSchin break;
56da2e3ebdSchin }
57da2e3ebdSchin if(fp && fp->disc->getval)
58da2e3ebdSchin cp = (*fp->disc->getval)(np,fp);
59da2e3ebdSchin else if(fp && fp->disc->getnum)
60da2e3ebdSchin {
61da2e3ebdSchin sfprintf(sh.strbuf,"%.*Lg",12,(*fp->disc->getnum)(np,fp));
62da2e3ebdSchin cp = sfstruse(sh.strbuf);
63da2e3ebdSchin }
64da2e3ebdSchin else
65da2e3ebdSchin {
66da2e3ebdSchin nv_local=1;
67da2e3ebdSchin cp = nv_getval(np);
68da2e3ebdSchin }
69da2e3ebdSchin return(cp);
70da2e3ebdSchin }
71da2e3ebdSchin
72da2e3ebdSchin /*
73da2e3ebdSchin * call the next getnum function in the chain
74da2e3ebdSchin */
nv_getn(Namval_t * np,register Namfun_t * nfp)75da2e3ebdSchin Sfdouble_t nv_getn(Namval_t *np, register Namfun_t *nfp)
76da2e3ebdSchin {
77da2e3ebdSchin register Namfun_t *fp;
78da2e3ebdSchin register Sfdouble_t d=0;
79b30d1939SAndy Fiddaman Shell_t *shp = sh_getinterp();
80da2e3ebdSchin char *str;
81da2e3ebdSchin if((fp = nfp) != NIL(Namfun_t*) && !nv_local)
82da2e3ebdSchin fp = nfp = nfp->next;
83da2e3ebdSchin nv_local=0;
84da2e3ebdSchin for(; fp; fp=fp->next)
85da2e3ebdSchin {
867c2fbfb3SApril Chin if(!fp->disc || (!fp->disc->getnum && !fp->disc->getval))
87da2e3ebdSchin continue;
88da2e3ebdSchin if(!fp->disc->getnum && nv_isattr(np,NV_INTEGER))
89da2e3ebdSchin continue;
90da2e3ebdSchin if(!nv_isattr(np,NV_NODISC) || fp==(Namfun_t*)nv_arrayptr(np))
91da2e3ebdSchin break;
92da2e3ebdSchin }
937c2fbfb3SApril Chin if(fp && fp->disc && fp->disc->getnum)
94da2e3ebdSchin d = (*fp->disc->getnum)(np,fp);
95da2e3ebdSchin else if(nv_isattr(np,NV_INTEGER))
96da2e3ebdSchin {
97da2e3ebdSchin nv_local = 1;
98da2e3ebdSchin d = nv_getnum(np);
99da2e3ebdSchin }
100da2e3ebdSchin else
101da2e3ebdSchin {
1027c2fbfb3SApril Chin if(fp && fp->disc && fp->disc->getval)
103da2e3ebdSchin str = (*fp->disc->getval)(np,fp);
104da2e3ebdSchin else
105da2e3ebdSchin str = nv_getv(np,fp?fp:nfp);
106da2e3ebdSchin if(str && *str)
107da2e3ebdSchin {
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);
114da2e3ebdSchin }
115da2e3ebdSchin }
116da2e3ebdSchin return(d);
117da2e3ebdSchin }
118da2e3ebdSchin
119da2e3ebdSchin /*
120da2e3ebdSchin * call the next assign function in the chain
121da2e3ebdSchin */
nv_putv(Namval_t * np,const char * value,int flags,register Namfun_t * nfp)122da2e3ebdSchin void nv_putv(Namval_t *np, const char *value, int flags, register Namfun_t *nfp)
123da2e3ebdSchin {
124da2e3ebdSchin register Namfun_t *fp, *fpnext;
125b30d1939SAndy Fiddaman Namarr_t *ap;
126da2e3ebdSchin if((fp=nfp) != NIL(Namfun_t*) && !nv_local)
127da2e3ebdSchin fp = nfp = nfp->next;
128da2e3ebdSchin nv_local=0;
1297c2fbfb3SApril Chin if(flags&NV_NODISC)
1307c2fbfb3SApril Chin fp = 0;
131da2e3ebdSchin for(; fp; fp=fpnext)
132da2e3ebdSchin {
133da2e3ebdSchin fpnext = fp->next;
1347c2fbfb3SApril Chin if(!fp->disc || !fp->disc->putval)
135da2e3ebdSchin {
136b30d1939SAndy Fiddaman if(!value && (!(ap=nv_arrayptr(np)) || ap->nelem==0))
137da2e3ebdSchin {
1387c2fbfb3SApril Chin if(fp->disc || !(fp->nofree&1))
1397c2fbfb3SApril Chin nv_disc(np,fp,NV_POP);
1407c2fbfb3SApril Chin if(!(fp->nofree&1))
141da2e3ebdSchin free((void*)fp);
142da2e3ebdSchin }
143da2e3ebdSchin continue;
144da2e3ebdSchin }
145da2e3ebdSchin if(!nv_isattr(np,NV_NODISC) || fp==(Namfun_t*)nv_arrayptr(np))
146da2e3ebdSchin break;
147da2e3ebdSchin }
148b30d1939SAndy Fiddaman if(!value && (flags&NV_TYPE) && fp && fp->disc->putval==assign)
149b30d1939SAndy Fiddaman fp = 0;
150da2e3ebdSchin if(fp && fp->disc->putval)
151da2e3ebdSchin (*fp->disc->putval)(np,value, flags, fp);
152da2e3ebdSchin else
153da2e3ebdSchin {
154da2e3ebdSchin nv_local=1;
155da2e3ebdSchin if(value)
156da2e3ebdSchin nv_putval(np, value, flags);
157da2e3ebdSchin else
1587c2fbfb3SApril Chin _nv_unset(np, flags&(NV_RDONLY|NV_EXPORT));
159da2e3ebdSchin }
160da2e3ebdSchin }
161da2e3ebdSchin
16234f9b3eeSRoland Mainz #define LOOKUPS 0
163da2e3ebdSchin #define ASSIGN 1
164da2e3ebdSchin #define APPEND 2
165da2e3ebdSchin #define UNASSIGN 3
16634f9b3eeSRoland Mainz #define LOOKUPN 4
167da2e3ebdSchin #define BLOCKED ((Namval_t*)&nv_local)
168da2e3ebdSchin
169da2e3ebdSchin struct vardisc
170da2e3ebdSchin {
171da2e3ebdSchin Namfun_t fun;
17234f9b3eeSRoland Mainz Namval_t *disc[5];
173da2e3ebdSchin };
174da2e3ebdSchin
175da2e3ebdSchin struct blocked
176da2e3ebdSchin {
177da2e3ebdSchin struct blocked *next;
178da2e3ebdSchin Namval_t *np;
179da2e3ebdSchin int flags;
180da2e3ebdSchin void *sub;
181da2e3ebdSchin int isub;
182da2e3ebdSchin };
183da2e3ebdSchin
184da2e3ebdSchin static struct blocked *blist;
185da2e3ebdSchin
186da2e3ebdSchin #define isblocked(bp,type) ((bp)->flags & (1<<(type)))
187da2e3ebdSchin #define block(bp,type) ((bp)->flags |= (1<<(type)))
188da2e3ebdSchin #define unblock(bp,type) ((bp)->flags &= ~(1<<(type)))
189da2e3ebdSchin
190da2e3ebdSchin /*
191da2e3ebdSchin * returns pointer to blocking structure
192da2e3ebdSchin */
block_info(Namval_t * np,struct blocked * pp)193da2e3ebdSchin static struct blocked *block_info(Namval_t *np, struct blocked *pp)
194da2e3ebdSchin {
195da2e3ebdSchin register struct blocked *bp;
196da2e3ebdSchin void *sub=0;
197da2e3ebdSchin int isub=0;
198da2e3ebdSchin if(nv_isarray(np) && (isub=nv_aindex(np)) < 0)
199da2e3ebdSchin sub = nv_associative(np,(const char*)0,NV_ACURRENT);
200da2e3ebdSchin for(bp=blist ; bp; bp=bp->next)
201da2e3ebdSchin {
202da2e3ebdSchin if(bp->np==np && bp->sub==sub && bp->isub==isub)
203da2e3ebdSchin return(bp);
204da2e3ebdSchin }
205da2e3ebdSchin if(pp)
206da2e3ebdSchin {
207da2e3ebdSchin pp->np = np;
208da2e3ebdSchin pp->flags = 0;
209da2e3ebdSchin pp->isub = isub;
210da2e3ebdSchin pp->sub = sub;
211da2e3ebdSchin pp->next = blist;
212da2e3ebdSchin blist = pp;
213da2e3ebdSchin }
214da2e3ebdSchin return(pp);
215da2e3ebdSchin }
216da2e3ebdSchin
block_done(struct blocked * bp)217da2e3ebdSchin static void block_done(struct blocked *bp)
218da2e3ebdSchin {
219da2e3ebdSchin blist = bp = bp->next;
220da2e3ebdSchin if(bp && (bp->isub>=0 || bp->sub))
221da2e3ebdSchin nv_putsub(bp->np, bp->sub,(bp->isub<0?0:bp->isub)|ARRAY_SETSUB);
222da2e3ebdSchin }
223da2e3ebdSchin
224da2e3ebdSchin /*
225da2e3ebdSchin * free discipline if no more discipline functions
226da2e3ebdSchin */
chktfree(register Namval_t * np,register struct vardisc * vp)227da2e3ebdSchin static void chktfree(register Namval_t *np, register struct vardisc *vp)
228da2e3ebdSchin {
229da2e3ebdSchin register int n;
230da2e3ebdSchin for(n=0; n< sizeof(vp->disc)/sizeof(*vp->disc); n++)
231da2e3ebdSchin {
232da2e3ebdSchin if(vp->disc[n])
233da2e3ebdSchin break;
234da2e3ebdSchin }
235da2e3ebdSchin if(n>=sizeof(vp->disc)/sizeof(*vp->disc))
236da2e3ebdSchin {
237da2e3ebdSchin /* no disc left so pop */
238da2e3ebdSchin Namfun_t *fp;
2397c2fbfb3SApril Chin if((fp=nv_stack(np, NIL(Namfun_t*))) && !(fp->nofree&1))
240da2e3ebdSchin free((void*)fp);
241da2e3ebdSchin }
242da2e3ebdSchin }
243da2e3ebdSchin
244da2e3ebdSchin /*
245da2e3ebdSchin * This function performs an assignment disc on the given node <np>
246da2e3ebdSchin */
assign(Namval_t * np,const char * val,int flags,Namfun_t * handle)247da2e3ebdSchin static void assign(Namval_t *np,const char* val,int flags,Namfun_t *handle)
248da2e3ebdSchin {
249da2e3ebdSchin int type = (flags&NV_APPEND)?APPEND:ASSIGN;
250da2e3ebdSchin register struct vardisc *vp = (struct vardisc*)handle;
251da2e3ebdSchin register Namval_t *nq = vp->disc[type];
252da2e3ebdSchin struct blocked block, *bp = block_info(np, &block);
253da2e3ebdSchin Namval_t node;
2547c2fbfb3SApril Chin union Value *up = np->nvalue.up;
2557c2fbfb3SApril Chin #if SHOPT_TYPEDEF
2567c2fbfb3SApril Chin Namval_t *tp, *nr;
2577c2fbfb3SApril Chin 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))
2587c2fbfb3SApril Chin {
2597c2fbfb3SApril Chin char *sub = nv_getsub(np);
260b30d1939SAndy Fiddaman _nv_unset(np,0);
2617c2fbfb3SApril Chin if(sub)
2627c2fbfb3SApril Chin {
2637c2fbfb3SApril Chin nv_putsub(np, sub, ARRAY_ADD);
2647c2fbfb3SApril Chin nv_putval(np,nv_getval(nr), 0);
2657c2fbfb3SApril Chin }
2667c2fbfb3SApril Chin else
2677c2fbfb3SApril Chin nv_clone(nr,np,0);
2687c2fbfb3SApril Chin goto done;
2697c2fbfb3SApril Chin }
2707c2fbfb3SApril Chin #endif /* SHOPT_TYPEDEF */
271da2e3ebdSchin if(val || isblocked(bp,type))
272da2e3ebdSchin {
273da2e3ebdSchin if(!nq || isblocked(bp,type))
274da2e3ebdSchin {
275da2e3ebdSchin nv_putv(np,val,flags,handle);
276da2e3ebdSchin goto done;
277da2e3ebdSchin }
278da2e3ebdSchin node = *SH_VALNOD;
279da2e3ebdSchin if(!nv_isnull(SH_VALNOD))
280da2e3ebdSchin {
281da2e3ebdSchin nv_onattr(SH_VALNOD,NV_NOFREE);
282b30d1939SAndy Fiddaman _nv_unset(SH_VALNOD,0);
283da2e3ebdSchin }
284da2e3ebdSchin if(flags&NV_INTEGER)
2857c2fbfb3SApril Chin nv_onattr(SH_VALNOD,(flags&(NV_LONG|NV_DOUBLE|NV_EXPNOTE|NV_HEXFLOAT|NV_SHORT)));
286da2e3ebdSchin nv_putval(SH_VALNOD, val, (flags&NV_INTEGER)?flags:NV_NOFREE);
287da2e3ebdSchin }
288da2e3ebdSchin else
289da2e3ebdSchin nq = vp->disc[type=UNASSIGN];
290da2e3ebdSchin if(nq && !isblocked(bp,type))
291da2e3ebdSchin {
292b30d1939SAndy Fiddaman int bflag=0;
293da2e3ebdSchin block(bp,type);
29434f9b3eeSRoland Mainz if (type==APPEND && (bflag= !isblocked(bp,LOOKUPS)))
29534f9b3eeSRoland Mainz block(bp,LOOKUPS);
296da2e3ebdSchin sh_fun(nq,np,(char**)0);
297da2e3ebdSchin unblock(bp,type);
298da2e3ebdSchin if(bflag)
29934f9b3eeSRoland Mainz unblock(bp,LOOKUPS);
300da2e3ebdSchin if(!vp->disc[type])
301da2e3ebdSchin chktfree(np,vp);
302da2e3ebdSchin }
3037c2fbfb3SApril Chin if(nv_isarray(np))
3047c2fbfb3SApril Chin np->nvalue.up = up;
305da2e3ebdSchin if(val)
306da2e3ebdSchin {
307da2e3ebdSchin register char *cp;
308da2e3ebdSchin Sfdouble_t d;
309da2e3ebdSchin if(nv_isnull(SH_VALNOD))
310da2e3ebdSchin cp=0;
311da2e3ebdSchin else if(flags&NV_INTEGER)
312da2e3ebdSchin {
313da2e3ebdSchin d = nv_getnum(SH_VALNOD);
314da2e3ebdSchin cp = (char*)(&d);
315da2e3ebdSchin flags |= (NV_LONG|NV_DOUBLE);
316da2e3ebdSchin flags &= ~NV_SHORT;
317da2e3ebdSchin }
318da2e3ebdSchin else
319da2e3ebdSchin cp = nv_getval(SH_VALNOD);
320da2e3ebdSchin if(cp)
321da2e3ebdSchin nv_putv(np,cp,flags|NV_RDONLY,handle);
322b30d1939SAndy Fiddaman _nv_unset(SH_VALNOD,0);
323da2e3ebdSchin /* restore everything but the nvlink field */
324da2e3ebdSchin memcpy(&SH_VALNOD->nvname, &node.nvname, sizeof(node)-sizeof(node.nvlink));
325da2e3ebdSchin }
326b30d1939SAndy Fiddaman else if(sh_isstate(SH_INIT) || np==SH_FUNNAMENOD)
327da2e3ebdSchin {
328da2e3ebdSchin /* don't free functions during reinitialization */
329da2e3ebdSchin nv_putv(np,val,flags,handle);
330da2e3ebdSchin }
331da2e3ebdSchin else if(!nq || !isblocked(bp,type))
332da2e3ebdSchin {
333da2e3ebdSchin Dt_t *root = sh_subfuntree(1);
334da2e3ebdSchin int n;
335da2e3ebdSchin Namarr_t *ap;
336da2e3ebdSchin block(bp,type);
337b30d1939SAndy Fiddaman nv_disc(np,handle,NV_POP);
338da2e3ebdSchin nv_putv(np, val, flags, handle);
3397c2fbfb3SApril Chin if(sh.subshell)
3407c2fbfb3SApril Chin goto done;
341da2e3ebdSchin if(nv_isarray(np) && (ap=nv_arrayptr(np)) && ap->nelem>0)
342da2e3ebdSchin goto done;
343da2e3ebdSchin for(n=0; n < sizeof(vp->disc)/sizeof(*vp->disc); n++)
344da2e3ebdSchin {
345da2e3ebdSchin if((nq=vp->disc[n]) && !nv_isattr(nq,NV_NOFREE))
346da2e3ebdSchin {
347b30d1939SAndy Fiddaman _nv_unset(nq,0);
348da2e3ebdSchin dtdelete(root,nq);
349da2e3ebdSchin }
350da2e3ebdSchin }
351da2e3ebdSchin unblock(bp,type);
3527c2fbfb3SApril Chin if(!(handle->nofree&1))
353da2e3ebdSchin free(handle);
354da2e3ebdSchin }
355da2e3ebdSchin done:
356da2e3ebdSchin if(bp== &block)
357da2e3ebdSchin 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 }
363da2e3ebdSchin }
364da2e3ebdSchin
365da2e3ebdSchin /*
366da2e3ebdSchin * This function executes a lookup disc and then performs
367da2e3ebdSchin * the lookup on the given node <np>
368da2e3ebdSchin */
lookup(Namval_t * np,int type,Sfdouble_t * dp,Namfun_t * handle)36934f9b3eeSRoland Mainz static char* lookup(Namval_t *np, int type, Sfdouble_t *dp,Namfun_t *handle)
370da2e3ebdSchin {
371da2e3ebdSchin register struct vardisc *vp = (struct vardisc*)handle;
372da2e3ebdSchin struct blocked block, *bp = block_info(np, &block);
37334f9b3eeSRoland Mainz register Namval_t *nq = vp->disc[type];
374da2e3ebdSchin register char *cp=0;
375da2e3ebdSchin Namval_t node;
3767c2fbfb3SApril Chin union Value *up = np->nvalue.up;
37734f9b3eeSRoland Mainz if(nq && !isblocked(bp,type))
378da2e3ebdSchin {
379da2e3ebdSchin node = *SH_VALNOD;
380da2e3ebdSchin if(!nv_isnull(SH_VALNOD))
381da2e3ebdSchin {
382da2e3ebdSchin nv_onattr(SH_VALNOD,NV_NOFREE);
383b30d1939SAndy Fiddaman _nv_unset(SH_VALNOD,0);
384da2e3ebdSchin }
38534f9b3eeSRoland Mainz if(type==LOOKUPN)
38634f9b3eeSRoland Mainz {
38734f9b3eeSRoland Mainz nv_onattr(SH_VALNOD,NV_DOUBLE|NV_INTEGER);
38834f9b3eeSRoland Mainz nv_setsize(SH_VALNOD,10);
38934f9b3eeSRoland Mainz }
39034f9b3eeSRoland Mainz block(bp,type);
391da2e3ebdSchin sh_fun(nq,np,(char**)0);
39234f9b3eeSRoland Mainz unblock(bp,type);
39334f9b3eeSRoland Mainz if(!vp->disc[type])
394da2e3ebdSchin chktfree(np,vp);
39534f9b3eeSRoland Mainz if(type==LOOKUPN)
3967c2fbfb3SApril Chin {
39734f9b3eeSRoland Mainz cp = (char*)(SH_VALNOD->nvalue.cp);
39834f9b3eeSRoland Mainz *dp = nv_getnum(SH_VALNOD);
3997c2fbfb3SApril Chin }
40034f9b3eeSRoland Mainz else if(cp = nv_getval(SH_VALNOD))
40134f9b3eeSRoland Mainz cp = stkcopy(stkstd,cp);
40234f9b3eeSRoland Mainz _nv_unset(SH_VALNOD,NV_RDONLY);
403da2e3ebdSchin if(!nv_isnull(&node))
404da2e3ebdSchin {
405da2e3ebdSchin /* restore everything but the nvlink field */
406da2e3ebdSchin memcpy(&SH_VALNOD->nvname, &node.nvname, sizeof(node)-sizeof(node.nvlink));
407da2e3ebdSchin }
408da2e3ebdSchin }
4097c2fbfb3SApril Chin if(nv_isarray(np))
4107c2fbfb3SApril Chin np->nvalue.up = up;
411da2e3ebdSchin if(!cp)
41234f9b3eeSRoland Mainz {
41334f9b3eeSRoland Mainz if(type==LOOKUPS)
41434f9b3eeSRoland Mainz cp = nv_getv(np,handle);
41534f9b3eeSRoland Mainz else
41634f9b3eeSRoland Mainz *dp = nv_getn(np,handle);
41734f9b3eeSRoland Mainz }
418da2e3ebdSchin if(bp== &block)
419da2e3ebdSchin 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 }
425da2e3ebdSchin return(cp);
426da2e3ebdSchin }
427da2e3ebdSchin
lookups(Namval_t * np,Namfun_t * handle)42834f9b3eeSRoland Mainz static char* lookups(Namval_t *np, Namfun_t *handle)
42934f9b3eeSRoland Mainz {
43034f9b3eeSRoland Mainz return(lookup(np,LOOKUPS,(Sfdouble_t*)0,handle));
43134f9b3eeSRoland Mainz }
4327c2fbfb3SApril Chin
lookupn(Namval_t * np,Namfun_t * handle)43334f9b3eeSRoland Mainz static Sfdouble_t lookupn(Namval_t *np, Namfun_t *handle)
434da2e3ebdSchin {
43534f9b3eeSRoland Mainz Sfdouble_t d;
43634f9b3eeSRoland Mainz lookup(np,LOOKUPN, &d ,handle);
43734f9b3eeSRoland Mainz return(d);
43834f9b3eeSRoland Mainz }
43934f9b3eeSRoland Mainz
440da2e3ebdSchin
441da2e3ebdSchin /*
442da2e3ebdSchin * Set disc on given <event> to <action>
443da2e3ebdSchin * If action==np, the current disc is returned
444da2e3ebdSchin * A null return value indicates that no <event> is known for <np>
445da2e3ebdSchin * If <event> is NULL, then return the event name after <action>
446da2e3ebdSchin * If <event> is NULL, and <action> is NULL, return the first event
447da2e3ebdSchin */
nv_setdisc(register Namval_t * np,register const char * event,Namval_t * action,register Namfun_t * fp)448da2e3ebdSchin char *nv_setdisc(register Namval_t* np,register const char *event,Namval_t *action,register Namfun_t *fp)
449da2e3ebdSchin {
450da2e3ebdSchin register struct vardisc *vp = (struct vardisc*)np->nvfun;
451da2e3ebdSchin register int type;
452da2e3ebdSchin char *empty = "";
4533e14f97fSRoger A. Faulkner while(vp)
4543e14f97fSRoger A. Faulkner {
4553e14f97fSRoger A. Faulkner if(vp->fun.disc && (vp->fun.disc->setdisc || vp->fun.disc->putval == assign))
4563e14f97fSRoger A. Faulkner break;
4573e14f97fSRoger A. Faulkner vp = (struct vardisc*)vp->fun.next;
4583e14f97fSRoger A. Faulkner }
4597c2fbfb3SApril Chin if(vp && !vp->fun.disc)
4607c2fbfb3SApril Chin vp = 0;
461da2e3ebdSchin if(np == (Namval_t*)fp)
462da2e3ebdSchin {
463da2e3ebdSchin register const char *name;
464da2e3ebdSchin register int getname=0;
465da2e3ebdSchin /* top level call, check for get/set */
466da2e3ebdSchin if(!event)
467da2e3ebdSchin {
468da2e3ebdSchin if(!action)
4697c2fbfb3SApril Chin return((char*)nv_discnames[0]);
470da2e3ebdSchin getname=1;
471da2e3ebdSchin event = (char*)action;
472da2e3ebdSchin }
4737c2fbfb3SApril Chin for(type=0; name=nv_discnames[type]; type++)
474da2e3ebdSchin {
475da2e3ebdSchin if(strcmp(event,name)==0)
476da2e3ebdSchin break;
477da2e3ebdSchin }
478da2e3ebdSchin if(getname)
479da2e3ebdSchin {
480da2e3ebdSchin event = 0;
4817c2fbfb3SApril Chin if(name && !(name = nv_discnames[++type]))
482da2e3ebdSchin action = 0;
483da2e3ebdSchin }
484da2e3ebdSchin if(!name)
485da2e3ebdSchin {
4867c2fbfb3SApril Chin for(fp=(Namfun_t*)vp; fp; fp=fp->next)
4877c2fbfb3SApril Chin {
4887c2fbfb3SApril Chin if(fp->disc && fp->disc->setdisc)
4897c2fbfb3SApril Chin return((*fp->disc->setdisc)(np,event,action,fp));
4907c2fbfb3SApril Chin }
491da2e3ebdSchin }
492da2e3ebdSchin else if(getname)
493da2e3ebdSchin return((char*)name);
494da2e3ebdSchin }
495da2e3ebdSchin if(!fp)
496da2e3ebdSchin return(NIL(char*));
497da2e3ebdSchin if(np != (Namval_t*)fp)
498da2e3ebdSchin {
499da2e3ebdSchin /* not the top level */
500da2e3ebdSchin while(fp = fp->next)
501da2e3ebdSchin {
5027c2fbfb3SApril Chin if(fp->disc && fp->disc->setdisc)
503da2e3ebdSchin return((*fp->disc->setdisc)(np,event,action,fp));
504da2e3ebdSchin }
505da2e3ebdSchin return(NIL(char*));
506da2e3ebdSchin }
507da2e3ebdSchin /* Handle GET/SET/APPEND/UNSET disc */
508da2e3ebdSchin if(vp && vp->fun.disc->putval!=assign)
509da2e3ebdSchin vp = 0;
510da2e3ebdSchin if(!vp)
511da2e3ebdSchin {
51234f9b3eeSRoland Mainz Namdisc_t *dp;
513da2e3ebdSchin if(action==np)
514da2e3ebdSchin return((char*)action);
51534f9b3eeSRoland Mainz if(!(vp = newof(NIL(struct vardisc*),struct vardisc,1,sizeof(Namdisc_t))))
516da2e3ebdSchin return(0);
51734f9b3eeSRoland Mainz dp = (Namdisc_t*)(vp+1);
51834f9b3eeSRoland Mainz vp->fun.disc = dp;
51934f9b3eeSRoland Mainz memset(dp,0,sizeof(*dp));
52034f9b3eeSRoland Mainz dp->dsize = sizeof(struct vardisc);
52134f9b3eeSRoland Mainz dp->putval = assign;
5223e14f97fSRoger A. Faulkner if(nv_isarray(np) && !nv_arrayptr(np))
5233e14f97fSRoger A. Faulkner nv_putsub(np,(char*)0, 1);
524da2e3ebdSchin nv_stack(np, (Namfun_t*)vp);
525da2e3ebdSchin }
526da2e3ebdSchin if(action==np)
527da2e3ebdSchin {
528da2e3ebdSchin action = vp->disc[type];
529da2e3ebdSchin empty = 0;
530da2e3ebdSchin }
531da2e3ebdSchin else if(action)
53234f9b3eeSRoland Mainz {
53334f9b3eeSRoland Mainz Namdisc_t *dp = (Namdisc_t*)vp->fun.disc;
53434f9b3eeSRoland Mainz if(type==LOOKUPS)
53534f9b3eeSRoland Mainz dp->getval = lookups;
53634f9b3eeSRoland Mainz else if(type==LOOKUPN)
53734f9b3eeSRoland Mainz dp->getnum = lookupn;
538da2e3ebdSchin vp->disc[type] = action;
53934f9b3eeSRoland Mainz }
540da2e3ebdSchin else
541da2e3ebdSchin {
542da2e3ebdSchin struct blocked *bp;
543da2e3ebdSchin action = vp->disc[type];
544da2e3ebdSchin vp->disc[type] = 0;
545da2e3ebdSchin if(!(bp=block_info(np,(struct blocked*)0)) || !isblocked(bp,UNASSIGN))
546da2e3ebdSchin chktfree(np,vp);
547da2e3ebdSchin }
548da2e3ebdSchin return(action?(char*)action:empty);
549da2e3ebdSchin }
550da2e3ebdSchin
551da2e3ebdSchin /*
552da2e3ebdSchin * Set disc on given <event> to <action>
553da2e3ebdSchin * If action==np, the current disc is returned
554da2e3ebdSchin * A null return value indicates that no <event> is known for <np>
555da2e3ebdSchin * If <event> is NULL, then return the event name after <action>
556da2e3ebdSchin * If <event> is NULL, and <action> is NULL, return the first event
557da2e3ebdSchin */
setdisc(register Namval_t * np,register const char * event,Namval_t * action,register Namfun_t * fp)558da2e3ebdSchin static char *setdisc(register Namval_t* np,register const char *event,Namval_t *action,register Namfun_t *fp)
559da2e3ebdSchin {
560da2e3ebdSchin register Nambfun_t *vp = (Nambfun_t*)fp;
561da2e3ebdSchin register int type,getname=0;
562da2e3ebdSchin register const char *name;
563da2e3ebdSchin const char **discnames = vp->bnames;
564da2e3ebdSchin /* top level call, check for discipline match */
565da2e3ebdSchin if(!event)
566da2e3ebdSchin {
567da2e3ebdSchin if(!action)
568da2e3ebdSchin return((char*)discnames[0]);
569da2e3ebdSchin getname=1;
570da2e3ebdSchin event = (char*)action;
571da2e3ebdSchin }
572da2e3ebdSchin for(type=0; name=discnames[type]; type++)
573da2e3ebdSchin {
574da2e3ebdSchin if(strcmp(event,name)==0)
575da2e3ebdSchin break;
576da2e3ebdSchin }
577da2e3ebdSchin if(getname)
578da2e3ebdSchin {
579da2e3ebdSchin event = 0;
580da2e3ebdSchin if(name && !(name = discnames[++type]))
581da2e3ebdSchin action = 0;
582da2e3ebdSchin }
583da2e3ebdSchin if(!name)
584da2e3ebdSchin return(nv_setdisc(np,event,action,fp));
585da2e3ebdSchin else if(getname)
586da2e3ebdSchin return((char*)name);
587da2e3ebdSchin /* Handle the disciplines */
588da2e3ebdSchin if(action==np)
589da2e3ebdSchin action = vp->bltins[type];
590da2e3ebdSchin 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);
595da2e3ebdSchin vp->bltins[type] = action;
596b30d1939SAndy Fiddaman }
597da2e3ebdSchin else
598da2e3ebdSchin {
599da2e3ebdSchin action = vp->bltins[type];
600da2e3ebdSchin vp->bltins[type] = 0;
601da2e3ebdSchin }
602b30d1939SAndy Fiddaman return((char*)action);
603da2e3ebdSchin }
604da2e3ebdSchin
putdisc(Namval_t * np,const char * val,int flag,Namfun_t * fp)605da2e3ebdSchin static void putdisc(Namval_t* np, const char* val, int flag, Namfun_t* fp)
606da2e3ebdSchin {
607da2e3ebdSchin nv_putv(np,val,flag,fp);
6087c2fbfb3SApril Chin if(!val && !(flag&NV_NOFREE))
609da2e3ebdSchin {
610da2e3ebdSchin register Nambfun_t *vp = (Nambfun_t*)fp;
611da2e3ebdSchin register int i;
612da2e3ebdSchin for(i=0; vp->bnames[i]; i++)
613da2e3ebdSchin {
614da2e3ebdSchin register Namval_t *mp;
615da2e3ebdSchin if((mp=vp->bltins[i]) && !nv_isattr(mp,NV_NOFREE))
616da2e3ebdSchin {
617da2e3ebdSchin if(is_abuiltin(mp))
618da2e3ebdSchin {
619da2e3ebdSchin if(mp->nvfun && !nv_isattr(mp,NV_NOFREE))
620da2e3ebdSchin free((void*)mp->nvfun);
621da2e3ebdSchin dtdelete(sh.bltin_tree,mp);
622da2e3ebdSchin free((void*)mp);
623da2e3ebdSchin }
624da2e3ebdSchin }
625da2e3ebdSchin }
626da2e3ebdSchin nv_disc(np,fp,NV_POP);
6277c2fbfb3SApril Chin if(!(fp->nofree&1))
628da2e3ebdSchin free((void*)fp);
629da2e3ebdSchin
630da2e3ebdSchin }
631da2e3ebdSchin }
632da2e3ebdSchin
633da2e3ebdSchin static const Namdisc_t Nv_bdisc = { 0, putdisc, 0, 0, setdisc };
634da2e3ebdSchin
nv_clone_disc(register Namfun_t * fp,int flags)6357c2fbfb3SApril Chin Namfun_t *nv_clone_disc(register Namfun_t *fp, int flags)
636da2e3ebdSchin {
637da2e3ebdSchin register Namfun_t *nfp;
638da2e3ebdSchin register int size;
63934f9b3eeSRoland Mainz if(!fp->disc && !fp->next && (fp->nofree&1))
64034f9b3eeSRoland Mainz return(fp);
641da2e3ebdSchin if(!(size=fp->dsize) && (!fp->disc || !(size=fp->disc->dsize)))
642da2e3ebdSchin size = sizeof(Namfun_t);
643da2e3ebdSchin if(!(nfp=newof(NIL(Namfun_t*),Namfun_t,1,size-sizeof(Namfun_t))))
644da2e3ebdSchin return(0);
645da2e3ebdSchin memcpy(nfp,fp,size);
64634f9b3eeSRoland Mainz nfp->nofree &= ~1;
6477c2fbfb3SApril Chin nfp->nofree |= (flags&NV_RDONLY)?1:0;
648da2e3ebdSchin return(nfp);
649da2e3ebdSchin }
650da2e3ebdSchin
nv_adddisc(Namval_t * np,const char ** names,Namval_t ** funs)651da2e3ebdSchin int nv_adddisc(Namval_t *np, const char **names, Namval_t **funs)
652da2e3ebdSchin {
653da2e3ebdSchin register Nambfun_t *vp;
654da2e3ebdSchin register int n=0;
655da2e3ebdSchin register const char **av=names;
656da2e3ebdSchin if(av)
657da2e3ebdSchin {
658da2e3ebdSchin while(*av++)
659da2e3ebdSchin n++;
660da2e3ebdSchin }
661da2e3ebdSchin if(!(vp = newof(NIL(Nambfun_t*),Nambfun_t,1,n*sizeof(Namval_t*))))
662da2e3ebdSchin return(0);
663da2e3ebdSchin vp->fun.dsize = sizeof(Nambfun_t)+n*sizeof(Namval_t*);
6647c2fbfb3SApril Chin vp->fun.nofree |= 2;
6657c2fbfb3SApril Chin vp->num = n;
666da2e3ebdSchin if(funs)
667da2e3ebdSchin memcpy((void*)vp->bltins, (void*)funs,n*sizeof(Namval_t*));
668da2e3ebdSchin else while(n>=0)
669da2e3ebdSchin vp->bltins[n--] = 0;
670da2e3ebdSchin vp->fun.disc = &Nv_bdisc;
671da2e3ebdSchin vp->bnames = names;
672da2e3ebdSchin nv_stack(np,&vp->fun);
673da2e3ebdSchin return(1);
674da2e3ebdSchin }
675da2e3ebdSchin
676da2e3ebdSchin /*
6777c2fbfb3SApril Chin * push, pop, clne, or reorder disciplines onto node <np>
678da2e3ebdSchin * mode can be one of
679da2e3ebdSchin * NV_FIRST: Move or push <fp> to top of the stack or delete top
680da2e3ebdSchin * NV_LAST: Move or push <fp> to bottom of stack or delete last
681da2e3ebdSchin * NV_POP: Delete <fp> from top of the stack
682da2e3ebdSchin * NV_CLONE: Replace fp with a copy created my malloc() and return it
683da2e3ebdSchin */
nv_disc(register Namval_t * np,register Namfun_t * fp,int mode)684da2e3ebdSchin Namfun_t *nv_disc(register Namval_t *np, register Namfun_t* fp, int mode)
685da2e3ebdSchin {
686da2e3ebdSchin Namfun_t *lp, **lpp;
687da2e3ebdSchin if(nv_isref(np))
688da2e3ebdSchin return(0);
689da2e3ebdSchin if(mode==NV_CLONE && !fp)
690da2e3ebdSchin return(0);
691da2e3ebdSchin if(fp)
692da2e3ebdSchin {
6937c2fbfb3SApril Chin fp->subshell = sh.subshell;
694da2e3ebdSchin if((lp=np->nvfun)==fp)
695da2e3ebdSchin {
696da2e3ebdSchin if(mode==NV_CLONE)
697da2e3ebdSchin {
6987c2fbfb3SApril Chin lp = nv_clone_disc(fp,0);
699da2e3ebdSchin return(np->nvfun=lp);
700da2e3ebdSchin }
701da2e3ebdSchin if(mode==NV_FIRST || mode==0)
702da2e3ebdSchin return(fp);
703da2e3ebdSchin np->nvfun = lp->next;
704da2e3ebdSchin if(mode==NV_POP)
705da2e3ebdSchin return(fp);
7067c2fbfb3SApril Chin if(mode==NV_LAST && (lp->next==0 || lp->next->disc==0))
7077c2fbfb3SApril Chin return(fp);
708da2e3ebdSchin }
709da2e3ebdSchin /* see if <fp> is on the list already */
710da2e3ebdSchin lpp = &np->nvfun;
711da2e3ebdSchin if(lp)
712da2e3ebdSchin {
7137c2fbfb3SApril Chin while(lp->next && lp->next->disc)
714da2e3ebdSchin {
715da2e3ebdSchin if(lp->next==fp)
716da2e3ebdSchin {
7177c2fbfb3SApril Chin if(mode==NV_LAST && fp->next==0)
7187c2fbfb3SApril Chin return(fp);
719da2e3ebdSchin if(mode==NV_CLONE)
720da2e3ebdSchin {
7217c2fbfb3SApril Chin fp = nv_clone_disc(fp,0);
722da2e3ebdSchin lp->next = fp;
723da2e3ebdSchin return(fp);
724da2e3ebdSchin }
725da2e3ebdSchin lp->next = fp->next;
726da2e3ebdSchin if(mode==NV_POP)
727da2e3ebdSchin return(fp);
728da2e3ebdSchin if(mode!=NV_LAST)
729da2e3ebdSchin break;
730da2e3ebdSchin }
731da2e3ebdSchin lp = lp->next;
732da2e3ebdSchin }
733b30d1939SAndy Fiddaman if(mode==NV_LAST && lp->disc)
734da2e3ebdSchin lpp = &lp->next;
735da2e3ebdSchin }
736da2e3ebdSchin if(mode==NV_POP)
737da2e3ebdSchin return(0);
738da2e3ebdSchin /* push */
739da2e3ebdSchin nv_offattr(np,NV_NODISC);
740da2e3ebdSchin 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 }
747da2e3ebdSchin else
748da2e3ebdSchin {
7497c2fbfb3SApril Chin if((fp->nofree&1) && *lpp)
7507c2fbfb3SApril Chin fp = nv_clone_disc(fp,0);
751da2e3ebdSchin fp->next = *lpp;
752da2e3ebdSchin }
753da2e3ebdSchin *lpp = fp;
754da2e3ebdSchin }
755da2e3ebdSchin else
756da2e3ebdSchin {
757da2e3ebdSchin if(mode==NV_FIRST)
758da2e3ebdSchin return(np->nvfun);
759da2e3ebdSchin else if(mode==NV_LAST)
760da2e3ebdSchin for(lp=np->nvfun; lp; fp=lp,lp=lp->next);
761da2e3ebdSchin else if(fp = np->nvfun)
762da2e3ebdSchin np->nvfun = fp->next;
763da2e3ebdSchin }
764da2e3ebdSchin return(fp);
765da2e3ebdSchin }
766da2e3ebdSchin
767da2e3ebdSchin /*
768da2e3ebdSchin * returns discipline pointer if discipline with specified functions
769da2e3ebdSchin * is on the discipline stack
770da2e3ebdSchin */
nv_hasdisc(Namval_t * np,const Namdisc_t * dp)771da2e3ebdSchin Namfun_t *nv_hasdisc(Namval_t *np, const Namdisc_t *dp)
772da2e3ebdSchin {
773da2e3ebdSchin register Namfun_t *fp;
774da2e3ebdSchin for(fp=np->nvfun; fp; fp = fp->next)
775da2e3ebdSchin {
776da2e3ebdSchin if(fp->disc== dp)
777da2e3ebdSchin return(fp);
778da2e3ebdSchin }
779da2e3ebdSchin return(0);
780da2e3ebdSchin }
781da2e3ebdSchin
782da2e3ebdSchin struct notify
783da2e3ebdSchin {
784da2e3ebdSchin Namfun_t hdr;
785da2e3ebdSchin char **ptr;
786da2e3ebdSchin };
787da2e3ebdSchin
put_notify(Namval_t * np,const char * val,int flags,Namfun_t * fp)788da2e3ebdSchin static void put_notify(Namval_t* np,const char *val,int flags,Namfun_t *fp)
789da2e3ebdSchin {
790da2e3ebdSchin struct notify *pp = (struct notify*)fp;
791da2e3ebdSchin nv_putv(np,val,flags,fp);
792da2e3ebdSchin nv_stack(np,fp);
793da2e3ebdSchin nv_stack(np,(Namfun_t*)0);
794da2e3ebdSchin *pp->ptr = 0;
7957c2fbfb3SApril Chin if(!(fp->nofree&1))
796da2e3ebdSchin free((void*)fp);
797da2e3ebdSchin }
798da2e3ebdSchin
799da2e3ebdSchin static const Namdisc_t notify_disc = { 0, put_notify };
800da2e3ebdSchin
nv_unsetnotify(Namval_t * np,char ** addr)801da2e3ebdSchin int nv_unsetnotify(Namval_t *np, char **addr)
802da2e3ebdSchin {
803da2e3ebdSchin register Namfun_t *fp;
804da2e3ebdSchin for(fp=np->nvfun;fp;fp=fp->next)
805da2e3ebdSchin {
806da2e3ebdSchin if(fp->disc->putval==put_notify && ((struct notify*)fp)->ptr==addr)
807da2e3ebdSchin {
808da2e3ebdSchin nv_stack(np,fp);
809da2e3ebdSchin nv_stack(np,(Namfun_t*)0);
8107c2fbfb3SApril Chin if(!(fp->nofree&1))
811da2e3ebdSchin free((void*)fp);
812da2e3ebdSchin return(1);
813da2e3ebdSchin }
814da2e3ebdSchin }
815da2e3ebdSchin return(0);
816da2e3ebdSchin }
817da2e3ebdSchin
nv_setnotify(Namval_t * np,char ** addr)818da2e3ebdSchin int nv_setnotify(Namval_t *np, char **addr)
819da2e3ebdSchin {
820da2e3ebdSchin struct notify *pp = newof(0,struct notify, 1,0);
821da2e3ebdSchin if(!pp)
822da2e3ebdSchin return(0);
823da2e3ebdSchin pp->ptr = addr;
824da2e3ebdSchin pp->hdr.disc = ¬ify_disc;
825da2e3ebdSchin nv_stack(np,&pp->hdr);
826da2e3ebdSchin return(1);
827da2e3ebdSchin }
828da2e3ebdSchin
newnode(const char * name)829da2e3ebdSchin static void *newnode(const char *name)
830da2e3ebdSchin {
831da2e3ebdSchin register int s;
832da2e3ebdSchin register Namval_t *np = newof(0,Namval_t,1,s=strlen(name)+1);
833da2e3ebdSchin if(np)
834da2e3ebdSchin {
835da2e3ebdSchin np->nvname = (char*)np+sizeof(Namval_t);
836da2e3ebdSchin memcpy(np->nvname,name,s);
837da2e3ebdSchin }
838da2e3ebdSchin return((void*)np);
839da2e3ebdSchin }
840da2e3ebdSchin
841da2e3ebdSchin /*
842da2e3ebdSchin * clone a numeric value
843da2e3ebdSchin */
num_clone(register Namval_t * np,void * val)844da2e3ebdSchin static void *num_clone(register Namval_t *np, void *val)
845da2e3ebdSchin {
846da2e3ebdSchin register int size;
847da2e3ebdSchin void *nval;
848da2e3ebdSchin if(!val)
849da2e3ebdSchin return(0);
8507c2fbfb3SApril Chin if(nv_isattr(np,NV_DOUBLE)==NV_DOUBLE)
851da2e3ebdSchin {
852da2e3ebdSchin if(nv_isattr(np,NV_LONG))
853da2e3ebdSchin size = sizeof(Sfdouble_t);
854da2e3ebdSchin else if(nv_isattr(np,NV_SHORT))
855da2e3ebdSchin size = sizeof(float);
856da2e3ebdSchin else
857da2e3ebdSchin size = sizeof(double);
858da2e3ebdSchin }
859da2e3ebdSchin else
860da2e3ebdSchin {
861da2e3ebdSchin if(nv_isattr(np,NV_LONG))
862da2e3ebdSchin size = sizeof(Sflong_t);
863da2e3ebdSchin else if(nv_isattr(np,NV_SHORT))
8647c2fbfb3SApril Chin {
8657c2fbfb3SApril Chin if(nv_isattr(np,NV_INT16P)==NV_INT16P)
8667c2fbfb3SApril Chin size = sizeof(short);
8677c2fbfb3SApril Chin else
8687c2fbfb3SApril Chin return((void*)np->nvalue.ip);
8697c2fbfb3SApril Chin }
870da2e3ebdSchin else
871da2e3ebdSchin size = sizeof(int32_t);
872da2e3ebdSchin }
873da2e3ebdSchin if(!(nval = malloc(size)))
874da2e3ebdSchin return(0);
875da2e3ebdSchin memcpy(nval,val,size);
876da2e3ebdSchin return(nval);
877da2e3ebdSchin }
878da2e3ebdSchin
clone_all_disc(Namval_t * np,Namval_t * mp,int flags)8797c2fbfb3SApril Chin void clone_all_disc( Namval_t *np, Namval_t *mp, int flags)
880da2e3ebdSchin {
8817c2fbfb3SApril Chin register Namfun_t *fp, **mfp = &mp->nvfun, *nfp, *fpnext;
8827c2fbfb3SApril Chin for(fp=np->nvfun; fp;fp=fpnext)
883da2e3ebdSchin {
8847c2fbfb3SApril Chin fpnext = fp->next;
8857c2fbfb3SApril Chin if(!fpnext && (flags&NV_COMVAR) && fp->disc && fp->disc->namef)
8867c2fbfb3SApril Chin return;
8877c2fbfb3SApril Chin if((fp->nofree&2) && (flags&NV_NODISC))
888da2e3ebdSchin nfp = 0;
889da2e3ebdSchin if(fp->disc && fp->disc->clonef)
890da2e3ebdSchin nfp = (*fp->disc->clonef)(np,mp,flags,fp);
8917c2fbfb3SApril Chin else if(flags&NV_MOVE)
8927c2fbfb3SApril Chin nfp = fp;
893da2e3ebdSchin else
8947c2fbfb3SApril Chin nfp = nv_clone_disc(fp,flags);
895da2e3ebdSchin if(!nfp)
896da2e3ebdSchin continue;
897da2e3ebdSchin nfp->next = 0;
898da2e3ebdSchin *mfp = nfp;
899da2e3ebdSchin mfp = &nfp->next;
900da2e3ebdSchin }
901da2e3ebdSchin }
902da2e3ebdSchin
903da2e3ebdSchin /*
904da2e3ebdSchin * clone <mp> from <np> flags can be one of the following
905da2e3ebdSchin * NV_APPEND - append <np> onto <mp>
906da2e3ebdSchin * NV_MOVE - move <np> to <mp>
907da2e3ebdSchin * NV_NOFREE - mark the new node as nofree
908da2e3ebdSchin * NV_NODISC - discplines with funs non-zero will not be copied
9097c2fbfb3SApril Chin * NV_COMVAR - cloning a compound variable
910da2e3ebdSchin */
nv_clone(Namval_t * np,Namval_t * mp,int flags)911da2e3ebdSchin int nv_clone(Namval_t *np, Namval_t *mp, int flags)
912da2e3ebdSchin {
9137c2fbfb3SApril Chin Namfun_t *fp, *fpnext;
9147c2fbfb3SApril Chin const char *val = mp->nvalue.cp;
9157c2fbfb3SApril Chin unsigned short flag = mp->nvflag;
9167c2fbfb3SApril Chin unsigned short size = mp->nvsize;
9177c2fbfb3SApril Chin for(fp=mp->nvfun; fp; fp=fpnext)
9187c2fbfb3SApril Chin {
9197c2fbfb3SApril Chin fpnext = fp->next;
9207c2fbfb3SApril Chin if(!fpnext && (flags&NV_COMVAR) && fp->disc && fp->disc->namef)
9217c2fbfb3SApril Chin break;
9227c2fbfb3SApril Chin if(!(fp->nofree&1))
9237c2fbfb3SApril Chin free((void*)fp);
9247c2fbfb3SApril Chin }
9257c2fbfb3SApril Chin mp->nvfun = fp;
926da2e3ebdSchin if(fp=np->nvfun)
927da2e3ebdSchin {
9287c2fbfb3SApril Chin if(nv_isattr(mp,NV_EXPORT|NV_MINIMAL) == (NV_EXPORT|NV_MINIMAL))
929da2e3ebdSchin {
9307c2fbfb3SApril Chin mp->nvenv = 0;
9317c2fbfb3SApril Chin nv_offattr(mp,NV_MINIMAL);
932da2e3ebdSchin }
9337c2fbfb3SApril Chin if(!(flags&NV_COMVAR) && !nv_isattr(np,NV_MINIMAL) && np->nvenv && !(nv_isattr(mp,NV_MINIMAL)))
9347c2fbfb3SApril Chin mp->nvenv = np->nvenv;
9357c2fbfb3SApril Chin mp->nvflag &= NV_MINIMAL;
9367c2fbfb3SApril Chin mp->nvflag |= np->nvflag&~(NV_ARRAY|NV_MINIMAL|NV_NOFREE);
9377c2fbfb3SApril Chin flag = mp->nvflag;
938da2e3ebdSchin clone_all_disc(np, mp, flags);
939da2e3ebdSchin }
940da2e3ebdSchin if(flags&NV_APPEND)
941da2e3ebdSchin return(1);
9427c2fbfb3SApril Chin if(mp->nvsize == size)
9437c2fbfb3SApril Chin nv_setsize(mp,nv_size(np));
9447c2fbfb3SApril Chin if(mp->nvflag == flag)
9457c2fbfb3SApril Chin mp->nvflag = (np->nvflag&~(NV_MINIMAL))|(mp->nvflag&NV_MINIMAL);
9460d56f5dfSToomas Soome if(nv_isattr(np,NV_EXPORT))
9470d56f5dfSToomas Soome mp->nvflag |= (np->nvflag&NV_MINIMAL);
9487c2fbfb3SApril Chin if(mp->nvalue.cp==val && !nv_isattr(np,NV_INTEGER))
9497c2fbfb3SApril Chin {
9507c2fbfb3SApril Chin if(np->nvalue.cp && np->nvalue.cp!=Empty && (flags&NV_COMVAR) && !(flags&NV_MOVE))
9517c2fbfb3SApril Chin {
9527c2fbfb3SApril Chin if(size)
9537c2fbfb3SApril Chin mp->nvalue.cp = (char*)memdup(np->nvalue.cp,size);
9547c2fbfb3SApril Chin else
9557c2fbfb3SApril Chin mp->nvalue.cp = strdup(np->nvalue.cp);
9567c2fbfb3SApril Chin nv_offattr(mp,NV_NOFREE);
9577c2fbfb3SApril Chin }
958b30d1939SAndy Fiddaman else if((np->nvfun || !nv_isattr(np,NV_ARRAY)) && !(mp->nvalue.cp = np->nvalue.cp))
9597c2fbfb3SApril Chin nv_offattr(mp,NV_NOFREE);
9607c2fbfb3SApril Chin }
961da2e3ebdSchin if(flags&NV_MOVE)
962da2e3ebdSchin {
9637c2fbfb3SApril Chin if(nv_isattr(np,NV_INTEGER))
9647c2fbfb3SApril Chin mp->nvalue.ip = np->nvalue.ip;
965da2e3ebdSchin np->nvfun = 0;
966da2e3ebdSchin np->nvalue.cp = 0;
967da2e3ebdSchin if(!nv_isattr(np,NV_MINIMAL) || nv_isattr(mp,NV_EXPORT))
9683e14f97fSRoger A. Faulkner {
9693e14f97fSRoger A. Faulkner 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;
9773e14f97fSRoger A. Faulkner }
9783e14f97fSRoger A. Faulkner else
9793e14f97fSRoger A. Faulkner np->nvflag &= NV_MINIMAL;
980da2e3ebdSchin nv_setsize(np,0);
981da2e3ebdSchin return(1);
982da2e3ebdSchin }
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)
98634f9b3eeSRoland Mainz {
987da2e3ebdSchin mp->nvalue.ip = (int*)num_clone(np,(void*)np->nvalue.ip);
98834f9b3eeSRoland Mainz nv_offattr(mp,NV_NOFREE);
98934f9b3eeSRoland Mainz }
990b30d1939SAndy Fiddaman else if((flags&NV_NOFREE) && !nv_arrayptr(np))
991da2e3ebdSchin nv_onattr(np,NV_NOFREE);
992da2e3ebdSchin return(1);
993da2e3ebdSchin }
994da2e3ebdSchin
995da2e3ebdSchin /*
996da2e3ebdSchin * The following discipline is for copy-on-write semantics
997da2e3ebdSchin */
clone_getv(Namval_t * np,Namfun_t * handle)998da2e3ebdSchin static char* clone_getv(Namval_t *np, Namfun_t *handle)
999da2e3ebdSchin {
1000da2e3ebdSchin return(np->nvalue.np?nv_getval(np->nvalue.np):0);
1001da2e3ebdSchin }
1002da2e3ebdSchin
clone_getn(Namval_t * np,Namfun_t * handle)1003da2e3ebdSchin static Sfdouble_t clone_getn(Namval_t *np, Namfun_t *handle)
1004da2e3ebdSchin {
1005da2e3ebdSchin return(np->nvalue.np?nv_getnum(np->nvalue.np):0);
1006da2e3ebdSchin }
1007da2e3ebdSchin
clone_putv(Namval_t * np,const char * val,int flags,Namfun_t * handle)1008da2e3ebdSchin static void clone_putv(Namval_t *np,const char* val,int flags,Namfun_t *handle)
1009da2e3ebdSchin {
1010da2e3ebdSchin Namfun_t *dp = nv_stack(np,(Namfun_t*)0);
1011da2e3ebdSchin Namval_t *mp = np->nvalue.np;
1012da2e3ebdSchin if(!sh.subshell)
1013da2e3ebdSchin free((void*)dp);
1014da2e3ebdSchin if(val)
1015da2e3ebdSchin nv_clone(mp,np,NV_NOFREE);
1016da2e3ebdSchin np->nvalue.cp = 0;
1017da2e3ebdSchin nv_putval(np,val,flags);
1018da2e3ebdSchin }
1019da2e3ebdSchin
1020da2e3ebdSchin static const Namdisc_t clone_disc =
1021da2e3ebdSchin {
1022da2e3ebdSchin 0,
1023da2e3ebdSchin clone_putv,
1024da2e3ebdSchin clone_getv,
1025da2e3ebdSchin clone_getn
1026da2e3ebdSchin };
1027da2e3ebdSchin
nv_mkclone(Namval_t * mp)1028da2e3ebdSchin Namval_t *nv_mkclone(Namval_t *mp)
1029da2e3ebdSchin {
1030da2e3ebdSchin Namval_t *np;
1031da2e3ebdSchin Namfun_t *dp;
1032da2e3ebdSchin np = newof(0,Namval_t,1,0);
1033da2e3ebdSchin np->nvflag = mp->nvflag;
1034da2e3ebdSchin np->nvsize = mp->nvsize;
1035da2e3ebdSchin np->nvname = mp->nvname;
1036da2e3ebdSchin np->nvalue.np = mp;
1037da2e3ebdSchin np->nvflag = mp->nvflag;
1038da2e3ebdSchin dp = newof(0,Namfun_t,1,0);
1039da2e3ebdSchin dp->disc = &clone_disc;
1040da2e3ebdSchin nv_stack(np,dp);
1041da2e3ebdSchin dtinsert(nv_dict(sh.namespace),np);
1042da2e3ebdSchin return(np);
1043da2e3ebdSchin }
1044da2e3ebdSchin
nv_search(const char * name,Dt_t * root,int mode)1045da2e3ebdSchin Namval_t *nv_search(const char *name, Dt_t *root, int mode)
1046da2e3ebdSchin {
1047da2e3ebdSchin register Namval_t *np;
1048da2e3ebdSchin register Dt_t *dp = 0;
1049da2e3ebdSchin if(mode&HASH_NOSCOPE)
1050da2e3ebdSchin dp = dtview(root,0);
1051da2e3ebdSchin if(mode&HASH_BUCKET)
1052da2e3ebdSchin {
1053da2e3ebdSchin Namval_t *mp = (void*)name;
1054da2e3ebdSchin if(!(np = dtsearch(root,mp)) && (mode&NV_ADD))
1055da2e3ebdSchin name = nv_name(mp);
1056da2e3ebdSchin }
1057da2e3ebdSchin else
1058da2e3ebdSchin {
105934f9b3eeSRoland Mainz if(*name=='.' && root==sh.var_tree && !dp)
1060da2e3ebdSchin root = sh.var_base;
1061da2e3ebdSchin np = dtmatch(root,(void*)name);
1062da2e3ebdSchin }
1063b30d1939SAndy Fiddaman #if SHOPT_COSHELL
1064b30d1939SAndy Fiddaman if(sh.inpool)
1065b30d1939SAndy Fiddaman mode |= HASH_NOSCOPE;
1066b30d1939SAndy Fiddaman #endif /* SHOPT_COSHELL */
1067da2e3ebdSchin if(!np && (mode&NV_ADD))
1068da2e3ebdSchin {
1069da2e3ebdSchin if(sh.namespace && !(mode&HASH_NOSCOPE) && root==sh.var_tree)
1070da2e3ebdSchin root = nv_dict(sh.namespace);
1071da2e3ebdSchin else if(!dp && !(mode&HASH_NOSCOPE))
1072da2e3ebdSchin {
1073da2e3ebdSchin register Dt_t *next;
1074da2e3ebdSchin while(next=dtvnext(root))
1075da2e3ebdSchin root = next;
1076da2e3ebdSchin }
1077da2e3ebdSchin np = (Namval_t*)dtinsert(root,newnode(name));
1078da2e3ebdSchin }
1079da2e3ebdSchin if(dp)
1080da2e3ebdSchin dtview(root,dp);
1081da2e3ebdSchin return(np);
1082da2e3ebdSchin }
1083da2e3ebdSchin
1084da2e3ebdSchin /*
1085da2e3ebdSchin * finds function or builtin for given name and the discipline variable
1086da2e3ebdSchin * if var!=0 the variable pointer is returned and the built-in name
1087da2e3ebdSchin * is put onto the stack at the current offset.
1088da2e3ebdSchin * otherwise, a pointer to the builtin (variable or type) is returned
1089da2e3ebdSchin * and var contains the poiner to the variable
1090da2e3ebdSchin * if last==0 and first component of name is a reference, nv_bfsearch()
1091da2e3ebdSchin will return 0.
1092da2e3ebdSchin */
nv_bfsearch(const char * name,Dt_t * root,Namval_t ** var,char ** last)1093da2e3ebdSchin Namval_t *nv_bfsearch(const char *name, Dt_t *root, Namval_t **var, char **last)
1094da2e3ebdSchin {
1095b30d1939SAndy Fiddaman Shell_t *shp = sh_getinterp();
10967c2fbfb3SApril Chin int c,offset = staktell();
1097da2e3ebdSchin register char *sp, *cp=0;
1098da2e3ebdSchin Namval_t *np, *nq;
10997c2fbfb3SApril Chin char *dname=0;
1100da2e3ebdSchin if(var)
1101da2e3ebdSchin *var = 0;
1102da2e3ebdSchin /* check for . in the name before = */
1103da2e3ebdSchin for(sp=(char*)name+1; *sp; sp++)
1104da2e3ebdSchin {
1105da2e3ebdSchin if(*sp=='=')
1106da2e3ebdSchin return(0);
11077c2fbfb3SApril Chin if(*sp=='[')
11087c2fbfb3SApril Chin {
11097c2fbfb3SApril Chin while(*sp=='[')
11107c2fbfb3SApril Chin {
11117c2fbfb3SApril Chin sp = nv_endsubscript((Namval_t*)0,(char*)sp,0);
11127c2fbfb3SApril Chin if(sp[-1]!=']')
11137c2fbfb3SApril Chin return(0);
11147c2fbfb3SApril Chin }
11157c2fbfb3SApril Chin if(*sp==0)
11167c2fbfb3SApril Chin break;
11177c2fbfb3SApril Chin if(*sp!='.')
11187c2fbfb3SApril Chin return(0);
1119b30d1939SAndy Fiddaman cp = sp;
11207c2fbfb3SApril Chin }
11217c2fbfb3SApril Chin else if(*sp=='.')
1122da2e3ebdSchin cp = sp;
1123da2e3ebdSchin }
1124da2e3ebdSchin if(!cp)
1125da2e3ebdSchin return(var?nv_search(name,root,0):0);
1126da2e3ebdSchin stakputs(name);
1127da2e3ebdSchin stakputc(0);
1128b30d1939SAndy Fiddaman dname = cp+1;
1129da2e3ebdSchin cp = stakptr(offset) + (cp-name);
1130da2e3ebdSchin if(last)
1131da2e3ebdSchin *last = cp;
11327c2fbfb3SApril Chin c = *cp;
1133da2e3ebdSchin *cp = 0;
1134b30d1939SAndy Fiddaman nq=nv_open(stakptr(offset),0,NV_VARNAME|NV_NOASSIGN|NV_NOADD|NV_NOFAIL);
11357c2fbfb3SApril Chin *cp = c;
1136da2e3ebdSchin if(!nq)
1137da2e3ebdSchin {
1138da2e3ebdSchin np = 0;
1139da2e3ebdSchin goto done;
1140da2e3ebdSchin }
1141da2e3ebdSchin if(!var)
1142da2e3ebdSchin {
1143da2e3ebdSchin np = nq;
1144da2e3ebdSchin goto done;
1145da2e3ebdSchin }
1146da2e3ebdSchin *var = nq;
11477c2fbfb3SApril Chin if(c=='[')
11487c2fbfb3SApril Chin 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;
11687c2fbfb3SApril Chin return((Namval_t*)nv_setdisc(nq,dname,nq,(Namfun_t*)nq));
1169da2e3ebdSchin done:
1170da2e3ebdSchin stakseek(offset);
1171da2e3ebdSchin return(np);
1172da2e3ebdSchin }
1173da2e3ebdSchin
1174da2e3ebdSchin /*
11757c2fbfb3SApril Chin * add or replace built-in version of command corresponding to <path>
1176da2e3ebdSchin * The <bltin> argument is a pointer to the built-in
1177da2e3ebdSchin * if <extra>==1, the built-in will be deleted
1178da2e3ebdSchin * Special builtins cannot be added or deleted return failure
1179da2e3ebdSchin * The return value for adding builtins is a pointer to the node or NULL on
1180da2e3ebdSchin * failure. For delete NULL means success and the node that cannot be
1181da2e3ebdSchin * deleted is returned on failure.
1182da2e3ebdSchin */
sh_addbuiltin(const char * path,Shbltin_f bltin,void * extra)1183b30d1939SAndy Fiddaman Namval_t *sh_addbuiltin(const char *path, Shbltin_f bltin, void *extra)
1184da2e3ebdSchin {
1185b30d1939SAndy Fiddaman register const char *name;
11867c2fbfb3SApril Chin char *cp;
11877c2fbfb3SApril Chin register Namval_t *np, *nq=0;
11887c2fbfb3SApril Chin 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)))
1192da2e3ebdSchin 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))
1201da2e3ebdSchin {
1202da2e3ebdSchin /* exists without a path */
1203b30d1939SAndy Fiddaman stakseek(offset);
1204da2e3ebdSchin if(extra == (void*)1)
1205da2e3ebdSchin {
1206da2e3ebdSchin if(np->nvfun && !nv_isattr(np,NV_NOFREE))
1207da2e3ebdSchin free((void*)np->nvfun);
1208da2e3ebdSchin dtdelete(sh.bltin_tree,np);
1209da2e3ebdSchin return(0);
1210da2e3ebdSchin }
1211da2e3ebdSchin if(!bltin)
1212da2e3ebdSchin return(np);
1213da2e3ebdSchin }
1214da2e3ebdSchin else for(np=(Namval_t*)dtfirst(sh.bltin_tree);np;np=(Namval_t*)dtnext(sh.bltin_tree,np))
1215da2e3ebdSchin {
1216da2e3ebdSchin if(strcmp(name,path_basename(nv_name(np))))
1217da2e3ebdSchin continue;
1218da2e3ebdSchin /* exists probably with different path so delete it */
1219da2e3ebdSchin if(strcmp(path,nv_name(np)))
1220da2e3ebdSchin {
1221da2e3ebdSchin if(nv_isattr(np,BLT_SPC))
1222da2e3ebdSchin return(np);
1223da2e3ebdSchin if(!bltin)
1224b30d1939SAndy Fiddaman bltin = (Shbltin_f)np->nvalue.bfp;
1225da2e3ebdSchin if(np->nvenv)
1226da2e3ebdSchin dtdelete(sh.bltin_tree,np);
1227da2e3ebdSchin if(extra == (void*)1)
1228da2e3ebdSchin return(0);
1229da2e3ebdSchin np = 0;
1230da2e3ebdSchin }
1231da2e3ebdSchin break;
1232da2e3ebdSchin }
1233da2e3ebdSchin if(!np && !(np = nv_search(path,sh.bltin_tree,bltin?NV_ADD:0)))
1234da2e3ebdSchin return(0);
1235b30d1939SAndy Fiddaman stakseek(offset);
1236da2e3ebdSchin if(nv_isattr(np,BLT_SPC))
12377c2fbfb3SApril Chin {
12387c2fbfb3SApril Chin if(extra)
12397c2fbfb3SApril Chin np->nvfun = (Namfun_t*)extra;
1240da2e3ebdSchin return(np);
12417c2fbfb3SApril Chin }
1242da2e3ebdSchin np->nvenv = 0;
1243da2e3ebdSchin np->nvfun = 0;
1244da2e3ebdSchin if(bltin)
1245da2e3ebdSchin {
1246b30d1939SAndy Fiddaman np->nvalue.bfp = (Nambfp_f)bltin;
1247da2e3ebdSchin nv_onattr(np,NV_BLTIN|NV_NOFREE);
1248da2e3ebdSchin np->nvfun = (Namfun_t*)extra;
1249da2e3ebdSchin }
1250da2e3ebdSchin if(nq)
1251da2e3ebdSchin {
1252da2e3ebdSchin cp=nv_setdisc(nq,cp+1,np,(Namfun_t*)nq);
1253da2e3ebdSchin nv_close(nq);
1254da2e3ebdSchin if(!cp)
1255da2e3ebdSchin errormsg(SH_DICT,ERROR_exit(1),e_baddisc,name);
1256da2e3ebdSchin }
1257da2e3ebdSchin if(extra == (void*)1)
1258da2e3ebdSchin return(0);
1259da2e3ebdSchin return(np);
1260da2e3ebdSchin }
1261da2e3ebdSchin
1262da2e3ebdSchin #undef nv_stack
nv_stack(register Namval_t * np,register Namfun_t * fp)1263da2e3ebdSchin extern Namfun_t *nv_stack(register Namval_t *np, register Namfun_t* fp)
1264da2e3ebdSchin {
1265da2e3ebdSchin return(nv_disc(np,fp,0));
1266da2e3ebdSchin }
1267da2e3ebdSchin
1268da2e3ebdSchin struct table
1269da2e3ebdSchin {
1270da2e3ebdSchin Namfun_t fun;
1271da2e3ebdSchin Namval_t *parent;
1272da2e3ebdSchin Shell_t *shp;
1273da2e3ebdSchin Dt_t *dict;
1274da2e3ebdSchin };
1275da2e3ebdSchin
next_table(register Namval_t * np,Dt_t * root,Namfun_t * fp)1276da2e3ebdSchin static Namval_t *next_table(register Namval_t* np, Dt_t *root,Namfun_t *fp)
1277da2e3ebdSchin {
1278da2e3ebdSchin struct table *tp = (struct table *)fp;
1279da2e3ebdSchin if(root)
1280da2e3ebdSchin return((Namval_t*)dtnext(root,np));
1281da2e3ebdSchin else
1282da2e3ebdSchin return((Namval_t*)dtfirst(tp->dict));
1283da2e3ebdSchin }
1284da2e3ebdSchin
create_table(Namval_t * np,const char * name,int flags,Namfun_t * fp)1285da2e3ebdSchin static Namval_t *create_table(Namval_t *np,const char *name,int flags,Namfun_t *fp)
1286da2e3ebdSchin {
1287da2e3ebdSchin struct table *tp = (struct table *)fp;
1288da2e3ebdSchin tp->shp->last_table = np;
1289da2e3ebdSchin return(nv_create(name, tp->dict, flags, fp));
1290da2e3ebdSchin }
1291da2e3ebdSchin
clone_table(Namval_t * np,Namval_t * mp,int flags,Namfun_t * fp)1292da2e3ebdSchin static Namfun_t *clone_table(Namval_t* np, Namval_t *mp, int flags, Namfun_t *fp)
1293da2e3ebdSchin {
1294da2e3ebdSchin struct table *tp = (struct table*)fp;
12957c2fbfb3SApril Chin struct table *ntp = (struct table*)nv_clone_disc(fp,0);
1296da2e3ebdSchin Dt_t *oroot=tp->dict,*nroot=dtopen(&_Nvdisc,Dtoset);
1297da2e3ebdSchin if(!nroot)
1298da2e3ebdSchin return(0);
1299da2e3ebdSchin memcpy((void*)ntp,(void*)fp,sizeof(struct table));
1300da2e3ebdSchin ntp->dict = nroot;
1301da2e3ebdSchin ntp->parent = nv_lastdict();
1302da2e3ebdSchin for(np=(Namval_t*)dtfirst(oroot);np;np=(Namval_t*)dtnext(oroot,np))
1303da2e3ebdSchin {
1304da2e3ebdSchin mp = (Namval_t*)dtinsert(nroot,newnode(np->nvname));
1305da2e3ebdSchin nv_clone(np,mp,flags);
1306da2e3ebdSchin }
1307da2e3ebdSchin return(&ntp->fun);
1308da2e3ebdSchin }
1309da2e3ebdSchin
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)1326da2e3ebdSchin static void put_table(register Namval_t* np, const char* val, int flags, Namfun_t* fp)
1327da2e3ebdSchin {
1328da2e3ebdSchin register Dt_t *root = ((struct table*)fp)->dict;
1329da2e3ebdSchin register Namval_t *nq, *mp;
1330da2e3ebdSchin Namarr_t *ap;
1331b30d1939SAndy Fiddaman struct adata data;
1332da2e3ebdSchin if(val)
1333b30d1939SAndy Fiddaman {
1334b30d1939SAndy Fiddaman nv_putv(np,val,flags,fp);
1335da2e3ebdSchin return;
1336b30d1939SAndy Fiddaman }
1337da2e3ebdSchin if(nv_isarray(np) && (ap=nv_arrayptr(np)) && array_elem(ap))
1338da2e3ebdSchin 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);
1344da2e3ebdSchin for(mp=(Namval_t*)dtfirst(root);mp;mp=nq)
1345da2e3ebdSchin {
1346da2e3ebdSchin _nv_unset(mp,flags);
1347da2e3ebdSchin nq = (Namval_t*)dtnext(root,mp);
1348da2e3ebdSchin dtdelete(root,mp);
1349da2e3ebdSchin free((void*)mp);
1350da2e3ebdSchin }
1351da2e3ebdSchin dtclose(root);
13527c2fbfb3SApril Chin if(!(fp->nofree&1))
1353da2e3ebdSchin free((void*)fp);
1354b30d1939SAndy Fiddaman np->nvfun = 0;
1355da2e3ebdSchin }
1356da2e3ebdSchin
1357da2e3ebdSchin /*
1358da2e3ebdSchin * return space separated list of names of variables in given tree
1359da2e3ebdSchin */
get_table(Namval_t * np,Namfun_t * fp)1360da2e3ebdSchin static char *get_table(Namval_t *np, Namfun_t *fp)
1361da2e3ebdSchin {
1362da2e3ebdSchin register Dt_t *root = ((struct table*)fp)->dict;
1363da2e3ebdSchin static Sfio_t *out;
1364da2e3ebdSchin register int first=1;
1365da2e3ebdSchin register Dt_t *base = dtview(root,0);
1366da2e3ebdSchin if(out)
1367da2e3ebdSchin sfseek(out,(Sfoff_t)0,SEEK_SET);
1368da2e3ebdSchin else
1369da2e3ebdSchin out = sfnew((Sfio_t*)0,(char*)0,-1,-1,SF_WRITE|SF_STRING);
1370da2e3ebdSchin for(np=(Namval_t*)dtfirst(root);np;np=(Namval_t*)dtnext(root,np))
1371da2e3ebdSchin {
1372da2e3ebdSchin if(!nv_isnull(np) || np->nvfun || nv_isattr(np,~NV_NOFREE))
1373da2e3ebdSchin {
1374da2e3ebdSchin if(!first)
1375da2e3ebdSchin sfputc(out,' ');
1376da2e3ebdSchin else
1377da2e3ebdSchin first = 0;
1378da2e3ebdSchin sfputr(out,np->nvname,-1);
1379da2e3ebdSchin }
1380da2e3ebdSchin }
1381da2e3ebdSchin sfputc(out,0);
1382da2e3ebdSchin if(base)
1383da2e3ebdSchin dtview(root,base);
1384da2e3ebdSchin return((char*)out->_data);
1385da2e3ebdSchin }
1386da2e3ebdSchin
1387da2e3ebdSchin static const Namdisc_t table_disc =
1388da2e3ebdSchin {
1389da2e3ebdSchin sizeof(struct table),
1390da2e3ebdSchin put_table,
1391da2e3ebdSchin get_table,
1392da2e3ebdSchin 0,
1393da2e3ebdSchin 0,
1394da2e3ebdSchin create_table,
1395da2e3ebdSchin clone_table,
1396da2e3ebdSchin 0,
1397da2e3ebdSchin next_table,
1398da2e3ebdSchin };
1399da2e3ebdSchin
nv_parent(Namval_t * np)14007c2fbfb3SApril Chin Namval_t *nv_parent(Namval_t *np)
14017c2fbfb3SApril Chin {
14027c2fbfb3SApril Chin struct table *tp = (struct table *)nv_hasdisc(np,&table_disc);
14037c2fbfb3SApril Chin if(tp)
14047c2fbfb3SApril Chin return(tp->parent);
14057c2fbfb3SApril Chin return(0);
14067c2fbfb3SApril Chin }
14077c2fbfb3SApril Chin
nv_dict(Namval_t * np)1408da2e3ebdSchin Dt_t *nv_dict(Namval_t* np)
1409da2e3ebdSchin {
1410b30d1939SAndy Fiddaman Shell_t *shp=sh_getinterp();
1411da2e3ebdSchin struct table *tp = (struct table*)nv_hasdisc(np,&table_disc);
1412da2e3ebdSchin if(tp)
1413da2e3ebdSchin return(tp->dict);
1414b30d1939SAndy Fiddaman np = shp->last_table;
1415da2e3ebdSchin while(np)
1416da2e3ebdSchin {
1417da2e3ebdSchin if(tp = (struct table*)nv_hasdisc(np,&table_disc))
1418da2e3ebdSchin return(tp->dict);
1419da2e3ebdSchin #if 0
1420da2e3ebdSchin np = nv_create(np,(const char*)0, NV_FIRST, (Namfun_t*)0);
14217c2fbfb3SApril Chin #else
14227c2fbfb3SApril Chin break;
1423da2e3ebdSchin #endif
1424da2e3ebdSchin }
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);
1431da2e3ebdSchin }
1432da2e3ebdSchin
1433da2e3ebdSchin /*
1434da2e3ebdSchin * create a mountable name-value pair tree
1435da2e3ebdSchin */
nv_mount(Namval_t * np,const char * name,Dt_t * dict)1436da2e3ebdSchin Namval_t *nv_mount(Namval_t *np, const char *name, Dt_t *dict)
1437da2e3ebdSchin {
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();
1444da2e3ebdSchin if(!(tp = newof((struct table*)0, struct table,1,0)))
1445da2e3ebdSchin return(0);
1446da2e3ebdSchin if(name)
1447da2e3ebdSchin {
1448da2e3ebdSchin Namfun_t *fp = pp->nvfun;
1449da2e3ebdSchin mp = (*fp->disc->createf)(pp,name,0,fp);
1450da2e3ebdSchin }
1451da2e3ebdSchin else
1452da2e3ebdSchin mp = np;
1453b30d1939SAndy Fiddaman nv_offattr(mp,NV_TABLE);
1454da2e3ebdSchin if(!nv_isnull(mp))
1455b30d1939SAndy Fiddaman _nv_unset(mp,NV_RDONLY);
1456da2e3ebdSchin tp->shp = sh_getinterp();
1457da2e3ebdSchin tp->dict = dict;
1458da2e3ebdSchin tp->parent = pp;
1459da2e3ebdSchin tp->fun.disc = &table_disc;
14607c2fbfb3SApril Chin nv_disc(mp, &tp->fun, NV_FIRST);
1461da2e3ebdSchin return(mp);
1462da2e3ebdSchin }
1463da2e3ebdSchin
nv_discfun(int which)1464da2e3ebdSchin const Namdisc_t *nv_discfun(int which)
1465da2e3ebdSchin {
1466da2e3ebdSchin switch(which)
1467da2e3ebdSchin {
1468da2e3ebdSchin case NV_DCADD:
1469da2e3ebdSchin return(&Nv_bdisc);
1470da2e3ebdSchin case NV_DCRESTRICT:
1471da2e3ebdSchin return(&RESTRICTED_disc);
1472da2e3ebdSchin }
1473da2e3ebdSchin return(0);
1474da2e3ebdSchin }
1475da2e3ebdSchin
nv_hasget(Namval_t * np)14763e14f97fSRoger A. Faulkner int nv_hasget(Namval_t *np)
14773e14f97fSRoger A. Faulkner {
14783e14f97fSRoger A. Faulkner register Namfun_t *fp;
14793e14f97fSRoger A. Faulkner for(fp=np->nvfun; fp; fp=fp->next)
14803e14f97fSRoger A. Faulkner {
14813e14f97fSRoger A. Faulkner if(!fp->disc || (!fp->disc->getnum && !fp->disc->getval))
14823e14f97fSRoger A. Faulkner continue;
14833e14f97fSRoger A. Faulkner return(1);
14843e14f97fSRoger A. Faulkner }
14853e14f97fSRoger A. Faulkner return(0);
14863e14f97fSRoger A. Faulkner }
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