1da2e3ebdSchin /***********************************************************************
2da2e3ebdSchin * *
3da2e3ebdSchin * This software is part of the ast package *
4*3e14f97fSRoger A. Faulkner * Copyright (c) 1982-2010 AT&T Intellectual Property *
5da2e3ebdSchin * and is licensed under the *
6da2e3ebdSchin * Common Public License, Version 1.0 *
77c2fbfb3SApril Chin * by AT&T Intellectual Property *
8da2e3ebdSchin * *
9da2e3ebdSchin * A copy of the License is available at *
10da2e3ebdSchin * http://www.opensource.org/licenses/cpl1.0.txt *
11da2e3ebdSchin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
12da2e3ebdSchin * *
13da2e3ebdSchin * Information and Software Systems Research *
14da2e3ebdSchin * AT&T Research *
15da2e3ebdSchin * Florham Park NJ *
16da2e3ebdSchin * *
17da2e3ebdSchin * David Korn <dgk@research.att.com> *
18da2e3ebdSchin * *
19da2e3ebdSchin ***********************************************************************/
20da2e3ebdSchin #pragma prototyped
21da2e3ebdSchin
22da2e3ebdSchin /*
23da2e3ebdSchin * code for tree nodes and name walking
24da2e3ebdSchin *
25da2e3ebdSchin * David Korn
26da2e3ebdSchin * AT&T Labs
27da2e3ebdSchin *
28da2e3ebdSchin */
29da2e3ebdSchin
30da2e3ebdSchin #include "defs.h"
31da2e3ebdSchin #include "name.h"
32da2e3ebdSchin #include "argnod.h"
337c2fbfb3SApril Chin #include "lexstates.h"
34da2e3ebdSchin
35da2e3ebdSchin struct nvdir
36da2e3ebdSchin {
37da2e3ebdSchin Dt_t *root;
38da2e3ebdSchin Namval_t *hp;
39da2e3ebdSchin Namval_t *table;
407c2fbfb3SApril Chin Namval_t *otable;
41da2e3ebdSchin Namval_t *(*nextnode)(Namval_t*,Dt_t*,Namfun_t*);
42da2e3ebdSchin Namfun_t *fun;
43da2e3ebdSchin struct nvdir *prev;
44da2e3ebdSchin int len;
45da2e3ebdSchin char data[1];
46da2e3ebdSchin };
47da2e3ebdSchin
48da2e3ebdSchin char *nv_getvtree(Namval_t*, Namfun_t *);
49da2e3ebdSchin static void put_tree(Namval_t*, const char*, int,Namfun_t*);
507c2fbfb3SApril Chin static char *walk_tree(Namval_t*, Namval_t*, int);
517c2fbfb3SApril Chin
read_tree(Namval_t * np,Sfio_t * iop,int n,Namfun_t * dp)527c2fbfb3SApril Chin static int read_tree(Namval_t* np, Sfio_t *iop, int n, Namfun_t *dp)
537c2fbfb3SApril Chin {
547c2fbfb3SApril Chin Sfio_t *sp;
557c2fbfb3SApril Chin char *cp;
567c2fbfb3SApril Chin int c;
577c2fbfb3SApril Chin if(n>=0)
587c2fbfb3SApril Chin return(-1);
597c2fbfb3SApril Chin while((c = sfgetc(iop)) && isblank(c));
607c2fbfb3SApril Chin sfungetc(iop,c);
617c2fbfb3SApril Chin sfprintf(sh.strbuf,"%s=%c",nv_name(np),0);
627c2fbfb3SApril Chin cp = sfstruse(sh.strbuf);
637c2fbfb3SApril Chin sp = sfopen((Sfio_t*)0,cp,"s");
647c2fbfb3SApril Chin sfstack(iop,sp);
657c2fbfb3SApril Chin c=sh_eval(iop,SH_READEVAL);
667c2fbfb3SApril Chin return(c);
677c2fbfb3SApril Chin }
68da2e3ebdSchin
create_tree(Namval_t * np,const char * name,int flag,Namfun_t * dp)69da2e3ebdSchin static Namval_t *create_tree(Namval_t *np,const char *name,int flag,Namfun_t *dp)
70da2e3ebdSchin {
71da2e3ebdSchin register Namfun_t *fp=dp;
72*3e14f97fSRoger A. Faulkner fp->dsize = 0;
73da2e3ebdSchin while(fp=fp->next)
74da2e3ebdSchin {
75da2e3ebdSchin if(fp->disc && fp->disc->createf)
76da2e3ebdSchin {
77da2e3ebdSchin if(np=(*fp->disc->createf)(np,name,flag,fp))
78da2e3ebdSchin dp->last = fp->last;
79da2e3ebdSchin return(np);
80da2e3ebdSchin }
81da2e3ebdSchin }
82da2e3ebdSchin return((flag&NV_NOADD)?0:np);
83da2e3ebdSchin }
84da2e3ebdSchin
clone_tree(Namval_t * np,Namval_t * mp,int flags,Namfun_t * fp)857c2fbfb3SApril Chin static Namfun_t *clone_tree(Namval_t *np, Namval_t *mp, int flags, Namfun_t *fp){
867c2fbfb3SApril Chin Namfun_t *dp;
877c2fbfb3SApril Chin if ((flags&NV_MOVE) && nv_type(np))
887c2fbfb3SApril Chin return(fp);
897c2fbfb3SApril Chin dp = nv_clone_disc(fp,flags);
907c2fbfb3SApril Chin if((flags&NV_COMVAR) && !(flags&NV_RAW))
917c2fbfb3SApril Chin {
927c2fbfb3SApril Chin walk_tree(np,mp,flags);
937c2fbfb3SApril Chin if((flags&NV_MOVE) && !(fp->nofree&1))
947c2fbfb3SApril Chin free((void*)fp);
957c2fbfb3SApril Chin }
967c2fbfb3SApril Chin return(dp);
977c2fbfb3SApril Chin }
987c2fbfb3SApril Chin
99da2e3ebdSchin static const Namdisc_t treedisc =
100da2e3ebdSchin {
101da2e3ebdSchin 0,
102da2e3ebdSchin put_tree,
103da2e3ebdSchin nv_getvtree,
104da2e3ebdSchin 0,
105da2e3ebdSchin 0,
1067c2fbfb3SApril Chin create_tree,
1077c2fbfb3SApril Chin clone_tree
1087c2fbfb3SApril Chin ,0,0,0,
1097c2fbfb3SApril Chin read_tree
110da2e3ebdSchin };
111da2e3ebdSchin
nextdot(const char * str)112da2e3ebdSchin static char *nextdot(const char *str)
113da2e3ebdSchin {
114da2e3ebdSchin register char *cp;
1157c2fbfb3SApril Chin register int c;
116da2e3ebdSchin if(*str=='.')
117da2e3ebdSchin str++;
1187c2fbfb3SApril Chin for(cp=(char*)str;c= *cp; cp++)
119da2e3ebdSchin {
1207c2fbfb3SApril Chin if(c=='[')
1217c2fbfb3SApril Chin {
1227c2fbfb3SApril Chin cp = nv_endsubscript((Namval_t*)0,(char*)cp,0);
123da2e3ebdSchin return(*cp=='.'?cp:0);
124da2e3ebdSchin }
1257c2fbfb3SApril Chin if(c=='.')
1267c2fbfb3SApril Chin return(cp);
1277c2fbfb3SApril Chin }
1287c2fbfb3SApril Chin return(0);
129da2e3ebdSchin }
130da2e3ebdSchin
nextdisc(Namval_t * np)131da2e3ebdSchin static Namfun_t *nextdisc(Namval_t *np)
132da2e3ebdSchin {
133da2e3ebdSchin register Namfun_t *fp;
134da2e3ebdSchin if(nv_isref(np))
135da2e3ebdSchin return(0);
136da2e3ebdSchin for(fp=np->nvfun;fp;fp=fp->next)
137da2e3ebdSchin {
138da2e3ebdSchin if(fp && fp->disc && fp->disc->nextf)
139da2e3ebdSchin return(fp);
140da2e3ebdSchin }
141da2e3ebdSchin return(0);
142da2e3ebdSchin }
143da2e3ebdSchin
nv_diropen(Namval_t * np,const char * name)1447c2fbfb3SApril Chin void *nv_diropen(Namval_t *np,const char *name)
145da2e3ebdSchin {
146da2e3ebdSchin char *next,*last;
147da2e3ebdSchin int c,len=strlen(name);
148da2e3ebdSchin struct nvdir *save, *dp = new_of(struct nvdir,len);
1497c2fbfb3SApril Chin Namval_t *nq=0,fake;
1507c2fbfb3SApril Chin Namfun_t *nfp=0;
151da2e3ebdSchin if(!dp)
152da2e3ebdSchin return(0);
153da2e3ebdSchin memset((void*)dp, 0, sizeof(*dp));
154da2e3ebdSchin if(name[len-1]=='*' || name[len-1]=='@')
155da2e3ebdSchin len -= 1;
1567c2fbfb3SApril Chin name = memcpy(dp->data,name,len);
1577c2fbfb3SApril Chin dp->data[len] = 0;
158da2e3ebdSchin dp->len = len;
1597c2fbfb3SApril Chin dp->root = sh.last_root?sh.last_root:sh.var_tree;
1607c2fbfb3SApril Chin #if 1
1617c2fbfb3SApril Chin while(1)
1627c2fbfb3SApril Chin {
163da2e3ebdSchin dp->table = sh.last_table;
1647c2fbfb3SApril Chin sh.last_table = 0;
1657c2fbfb3SApril Chin if(*(last=(char*)name)==0)
1667c2fbfb3SApril Chin break;
1677c2fbfb3SApril Chin if(!(next=nextdot(last)))
1687c2fbfb3SApril Chin break;
1697c2fbfb3SApril Chin *next = 0;
1707c2fbfb3SApril Chin np = nv_open(name, dp->root, NV_NOFAIL);
1717c2fbfb3SApril Chin *next = '.';
1727c2fbfb3SApril Chin if(!np || !nv_istable(np))
1737c2fbfb3SApril Chin break;
1747c2fbfb3SApril Chin dp->root = nv_dict(np);
1757c2fbfb3SApril Chin name = next+1;
1767c2fbfb3SApril Chin }
1777c2fbfb3SApril Chin #else
1787c2fbfb3SApril Chin dp->table = sh.last_table;
1797c2fbfb3SApril Chin sh.last_table = 0;
1807c2fbfb3SApril Chin last = dp->data;
1817c2fbfb3SApril Chin #endif
182da2e3ebdSchin if(*name)
183da2e3ebdSchin {
184da2e3ebdSchin fake.nvname = (char*)name;
1857c2fbfb3SApril Chin if(dp->hp = (Namval_t*)dtprev(dp->root,&fake))
1867c2fbfb3SApril Chin {
1877c2fbfb3SApril Chin char *cp = nv_name(dp->hp);
1887c2fbfb3SApril Chin c = strlen(cp);
1897c2fbfb3SApril Chin if(memcmp(name,cp,c) || name[c]!='[')
190da2e3ebdSchin dp->hp = (Namval_t*)dtnext(dp->root,dp->hp);
1917c2fbfb3SApril Chin else
1927c2fbfb3SApril Chin {
1937c2fbfb3SApril Chin np = dp->hp;
1947c2fbfb3SApril Chin last = 0;
1957c2fbfb3SApril Chin }
1967c2fbfb3SApril Chin }
19734f9b3eeSRoland Mainz else
19834f9b3eeSRoland Mainz dp->hp = (Namval_t*)dtfirst(dp->root);
199da2e3ebdSchin }
200da2e3ebdSchin else
201da2e3ebdSchin dp->hp = (Namval_t*)dtfirst(dp->root);
2027c2fbfb3SApril Chin while(1)
2037c2fbfb3SApril Chin {
2047c2fbfb3SApril Chin if(!last)
2057c2fbfb3SApril Chin next = 0;
2067c2fbfb3SApril Chin else if(next= nextdot(last))
207da2e3ebdSchin {
208da2e3ebdSchin c = *next;
209da2e3ebdSchin *next = 0;
2107c2fbfb3SApril Chin }
2117c2fbfb3SApril Chin if(!np)
2127c2fbfb3SApril Chin {
2137c2fbfb3SApril Chin if(nfp && nfp->disc && nfp->disc->createf)
2147c2fbfb3SApril Chin {
2157c2fbfb3SApril Chin np = (*nfp->disc->createf)(nq,last,0,nfp);
2167c2fbfb3SApril Chin if(*nfp->last == '[')
2177c2fbfb3SApril Chin {
2187c2fbfb3SApril Chin nv_endsubscript(np,nfp->last,NV_NOADD);
2197c2fbfb3SApril Chin if(nq = nv_opensub(np))
2207c2fbfb3SApril Chin np = nq;
2217c2fbfb3SApril Chin }
2227c2fbfb3SApril Chin }
2237c2fbfb3SApril Chin else
224da2e3ebdSchin np = nv_search(last,dp->root,0);
2257c2fbfb3SApril Chin }
2267c2fbfb3SApril Chin if(next)
227da2e3ebdSchin *next = c;
2287c2fbfb3SApril Chin if(np==dp->hp && !next)
2297c2fbfb3SApril Chin dp->hp = (Namval_t*)dtnext(dp->root,dp->hp);
230da2e3ebdSchin if(np && ((nfp=nextdisc(np)) || nv_istable(np)))
231da2e3ebdSchin {
232da2e3ebdSchin if(!(save = new_of(struct nvdir,0)))
233da2e3ebdSchin return(0);
234da2e3ebdSchin *save = *dp;
235da2e3ebdSchin dp->prev = save;
236da2e3ebdSchin if(nv_istable(np))
237da2e3ebdSchin dp->root = nv_dict(np);
238da2e3ebdSchin else
2397c2fbfb3SApril Chin dp->root = (Dt_t*)np;
240da2e3ebdSchin if(nfp)
241da2e3ebdSchin {
242da2e3ebdSchin dp->nextnode = nfp->disc->nextf;
243da2e3ebdSchin dp->table = np;
2447c2fbfb3SApril Chin dp->otable = sh.last_table;
245da2e3ebdSchin dp->fun = nfp;
246da2e3ebdSchin dp->hp = (*dp->nextnode)(np,(Dt_t*)0,nfp);
247da2e3ebdSchin }
248da2e3ebdSchin else
249da2e3ebdSchin dp->nextnode = 0;
250da2e3ebdSchin }
251da2e3ebdSchin else
252da2e3ebdSchin break;
2537c2fbfb3SApril Chin if(!next || next[1]==0)
2547c2fbfb3SApril Chin break;
255da2e3ebdSchin last = next+1;
2567c2fbfb3SApril Chin nq = np;
2577c2fbfb3SApril Chin np = 0;
258da2e3ebdSchin }
259da2e3ebdSchin return((void*)dp);
260da2e3ebdSchin }
261da2e3ebdSchin
262da2e3ebdSchin
nextnode(struct nvdir * dp)263da2e3ebdSchin static Namval_t *nextnode(struct nvdir *dp)
264da2e3ebdSchin {
265da2e3ebdSchin if(dp->nextnode)
266da2e3ebdSchin return((*dp->nextnode)(dp->hp,dp->root,dp->fun));
267da2e3ebdSchin if(dp->len && memcmp(dp->data, dp->hp->nvname, dp->len))
268da2e3ebdSchin return(0);
269da2e3ebdSchin return((Namval_t*)dtnext(dp->root,dp->hp));
270da2e3ebdSchin }
271da2e3ebdSchin
nv_dirnext(void * dir)272da2e3ebdSchin char *nv_dirnext(void *dir)
273da2e3ebdSchin {
274da2e3ebdSchin register struct nvdir *save, *dp = (struct nvdir*)dir;
275da2e3ebdSchin register Namval_t *np, *last_table;
276da2e3ebdSchin register char *cp;
277da2e3ebdSchin Namfun_t *nfp;
2787c2fbfb3SApril Chin Namval_t *nq;
279da2e3ebdSchin while(1)
280da2e3ebdSchin {
281da2e3ebdSchin while(np=dp->hp)
282da2e3ebdSchin {
2837c2fbfb3SApril Chin #if 0
2847c2fbfb3SApril Chin char *sptr;
2857c2fbfb3SApril Chin #endif
2867c2fbfb3SApril Chin if(nv_isarray(np))
2877c2fbfb3SApril Chin nv_putsub(np,(char*)0, ARRAY_UNDEF);
288da2e3ebdSchin dp->hp = nextnode(dp);
28934f9b3eeSRoland Mainz if(nv_isnull(np) && !nv_isarray(np) && !nv_isattr(np,NV_INTEGER))
290da2e3ebdSchin continue;
291da2e3ebdSchin last_table = sh.last_table;
2927c2fbfb3SApril Chin #if 0
2937c2fbfb3SApril Chin if(dp->table && dp->otable && !nv_isattr(dp->table,NV_MINIMAL))
2947c2fbfb3SApril Chin {
2957c2fbfb3SApril Chin sptr = dp->table->nvenv;
2967c2fbfb3SApril Chin dp->table->nvenv = (char*)dp->otable;
2977c2fbfb3SApril Chin }
2987c2fbfb3SApril Chin #endif
299da2e3ebdSchin sh.last_table = dp->table;
300da2e3ebdSchin cp = nv_name(np);
3017c2fbfb3SApril Chin #if 0
3027c2fbfb3SApril Chin if(dp->table && dp->otable && !nv_isattr(dp->table,NV_MINIMAL))
3037c2fbfb3SApril Chin dp->table->nvenv = sptr;
3047c2fbfb3SApril Chin #endif
3057c2fbfb3SApril Chin if(dp->nextnode && !dp->hp && (nq = (Namval_t*)dp->table))
306da2e3ebdSchin {
3077c2fbfb3SApril Chin Namarr_t *ap = nv_arrayptr(nq);
3087c2fbfb3SApril Chin if(ap && (ap->nelem&ARRAY_SCAN) && nv_nextsub(nq))
3097c2fbfb3SApril Chin dp->hp = (*dp->nextnode)(np,(Dt_t*)0,dp->fun);
3107c2fbfb3SApril Chin }
3117c2fbfb3SApril Chin sh.last_table = last_table;
3127c2fbfb3SApril Chin if(!dp->len || memcmp(cp,dp->data,dp->len)==0)
3137c2fbfb3SApril Chin {
3147c2fbfb3SApril Chin if((nfp=nextdisc(np)) && (nfp->disc->getval||nfp->disc->getnum) && nv_isvtree(np) && strcmp(cp,dp->data))
3157c2fbfb3SApril Chin nfp = 0;
3167c2fbfb3SApril Chin if(nfp || nv_istable(np))
317da2e3ebdSchin {
318da2e3ebdSchin Dt_t *root;
319da2e3ebdSchin if(nv_istable(np))
320da2e3ebdSchin root = nv_dict(np);
321da2e3ebdSchin else
3227c2fbfb3SApril Chin root = (Dt_t*)np;
323da2e3ebdSchin /* check for recursive walk */
324da2e3ebdSchin for(save=dp; save; save=save->prev)
325da2e3ebdSchin {
326da2e3ebdSchin if(save->root==root)
327da2e3ebdSchin break;
328da2e3ebdSchin }
329da2e3ebdSchin if(save)
3307c2fbfb3SApril Chin return(cp);
331da2e3ebdSchin if(!(save = new_of(struct nvdir,0)))
332da2e3ebdSchin return(0);
333da2e3ebdSchin *save = *dp;
334da2e3ebdSchin dp->prev = save;
335da2e3ebdSchin dp->root = root;
336da2e3ebdSchin dp->len = 0;
337da2e3ebdSchin if(nfp && np->nvfun)
338da2e3ebdSchin {
3397c2fbfb3SApril Chin #if 0
3407c2fbfb3SApril Chin Namarr_t *ap = nv_arrayptr(np);
3417c2fbfb3SApril Chin if(ap && (ap->nelem&ARRAY_UNDEF))
3427c2fbfb3SApril Chin nv_putsub(np,(char*)0,ARRAY_SCAN);
3437c2fbfb3SApril Chin #endif
344da2e3ebdSchin dp->nextnode = nfp->disc->nextf;
3457c2fbfb3SApril Chin dp->otable = dp->table;
346da2e3ebdSchin dp->table = np;
347da2e3ebdSchin dp->fun = nfp;
348da2e3ebdSchin dp->hp = (*dp->nextnode)(np,(Dt_t*)0,nfp);
349da2e3ebdSchin }
350da2e3ebdSchin else
351da2e3ebdSchin dp->nextnode = 0;
352da2e3ebdSchin }
353da2e3ebdSchin return(cp);
354da2e3ebdSchin }
355da2e3ebdSchin }
356da2e3ebdSchin if(!(save=dp->prev))
357da2e3ebdSchin break;
358da2e3ebdSchin *dp = *save;
359da2e3ebdSchin free((void*)save);
360da2e3ebdSchin }
361da2e3ebdSchin return(0);
362da2e3ebdSchin }
363da2e3ebdSchin
nv_dirclose(void * dir)364da2e3ebdSchin void nv_dirclose(void *dir)
365da2e3ebdSchin {
366da2e3ebdSchin struct nvdir *dp = (struct nvdir*)dir;
367da2e3ebdSchin if(dp->prev)
368da2e3ebdSchin nv_dirclose((void*)dp->prev);
369da2e3ebdSchin free(dir);
370da2e3ebdSchin }
371da2e3ebdSchin
outtype(Namval_t * np,Namfun_t * fp,Sfio_t * out,const char * prefix)372da2e3ebdSchin static void outtype(Namval_t *np, Namfun_t *fp, Sfio_t* out, const char *prefix)
373da2e3ebdSchin {
374da2e3ebdSchin char *type=0;
375da2e3ebdSchin Namval_t *tp = fp->type;
376da2e3ebdSchin if(!tp && fp->disc && fp->disc->typef)
377da2e3ebdSchin tp = (*fp->disc->typef)(np,fp);
378da2e3ebdSchin for(fp=fp->next;fp;fp=fp->next)
379da2e3ebdSchin {
380da2e3ebdSchin if(fp->type || (fp->disc && fp->disc->typef &&(*fp->disc->typef)(np,fp)))
381da2e3ebdSchin {
382da2e3ebdSchin outtype(np,fp,out,prefix);
383da2e3ebdSchin break;
384da2e3ebdSchin }
385da2e3ebdSchin }
386da2e3ebdSchin if(prefix && *prefix=='t')
387da2e3ebdSchin type = "-T";
388da2e3ebdSchin else if(!prefix)
389da2e3ebdSchin type = "type";
390da2e3ebdSchin if(type)
3917c2fbfb3SApril Chin {
3927c2fbfb3SApril Chin char *cp=tp->nvname;
3937c2fbfb3SApril Chin if(cp=strrchr(cp,'.'))
3947c2fbfb3SApril Chin cp++;
3957c2fbfb3SApril Chin else
3967c2fbfb3SApril Chin cp = tp->nvname;
3977c2fbfb3SApril Chin sfprintf(out,"%s %s ",type,cp);
3987c2fbfb3SApril Chin }
399da2e3ebdSchin }
400da2e3ebdSchin
401da2e3ebdSchin /*
402da2e3ebdSchin * print the attributes of name value pair give by <np>
403da2e3ebdSchin */
nv_attribute(register Namval_t * np,Sfio_t * out,char * prefix,int noname)404da2e3ebdSchin void nv_attribute(register Namval_t *np,Sfio_t *out,char *prefix,int noname)
405da2e3ebdSchin {
406da2e3ebdSchin register const Shtable_t *tp;
407da2e3ebdSchin register char *cp;
4087c2fbfb3SApril Chin register unsigned val,mask,attr;
4097c2fbfb3SApril Chin char *ip=0;
410da2e3ebdSchin Namfun_t *fp=0;
4117c2fbfb3SApril Chin Namval_t *typep=0;
412da2e3ebdSchin for(fp=np->nvfun;fp;fp=fp->next)
413da2e3ebdSchin {
4147c2fbfb3SApril Chin if((typep=fp->type) || (fp->disc && fp->disc->typef && (typep=(*fp->disc->typef)(np,fp))))
415da2e3ebdSchin break;
416da2e3ebdSchin }
4177c2fbfb3SApril Chin if(!fp && !nv_isattr(np,~(NV_MINIMAL|NV_NOFREE)))
418da2e3ebdSchin {
4197c2fbfb3SApril Chin if(prefix && *prefix)
4207c2fbfb3SApril Chin {
4217c2fbfb3SApril Chin if(nv_isvtree(np))
4227c2fbfb3SApril Chin sfprintf(out,"%s -C ",prefix);
42334f9b3eeSRoland Mainz else if((!np->nvalue.cp||np->nvalue.cp==Empty) && nv_isattr(np,~NV_NOFREE)==NV_MINIMAL && strcmp(np->nvname,"_"))
4247c2fbfb3SApril Chin sfputr(out,prefix,' ');
4257c2fbfb3SApril Chin }
426da2e3ebdSchin return;
427da2e3ebdSchin }
428da2e3ebdSchin
429da2e3ebdSchin if ((attr=nv_isattr(np,~NV_NOFREE)) || fp)
430da2e3ebdSchin {
4317c2fbfb3SApril Chin if((attr&NV_NOPRINT|NV_INTEGER)==NV_NOPRINT)
432da2e3ebdSchin attr &= ~NV_NOPRINT;
433da2e3ebdSchin if(!attr && !fp)
434da2e3ebdSchin return;
4357c2fbfb3SApril Chin if(fp)
4367c2fbfb3SApril Chin {
4377c2fbfb3SApril Chin prefix = Empty;
4387c2fbfb3SApril Chin attr &= NV_RDONLY|NV_ARRAY;
4397c2fbfb3SApril Chin if(nv_isattr(np,NV_REF|NV_TAGGED)==(NV_REF|NV_TAGGED))
4407c2fbfb3SApril Chin attr |= (NV_REF|NV_TAGGED);
4417c2fbfb3SApril Chin if(typep)
4427c2fbfb3SApril Chin {
4437c2fbfb3SApril Chin char *cp = typep->nvname;
4447c2fbfb3SApril Chin if(cp = strrchr(cp,'.'))
4457c2fbfb3SApril Chin cp++;
4467c2fbfb3SApril Chin else
4477c2fbfb3SApril Chin cp = typep->nvname;
4487c2fbfb3SApril Chin sfputr(out,cp,' ');
4497c2fbfb3SApril Chin fp = 0;
4507c2fbfb3SApril Chin }
4517c2fbfb3SApril Chin }
4527c2fbfb3SApril Chin else if(prefix && *prefix)
453da2e3ebdSchin sfputr(out,prefix,' ');
454da2e3ebdSchin for(tp = shtab_attributes; *tp->sh_name;tp++)
455da2e3ebdSchin {
456da2e3ebdSchin val = tp->sh_number;
457da2e3ebdSchin mask = val;
458da2e3ebdSchin if(fp && (val&NV_INTEGER))
459da2e3ebdSchin break;
460da2e3ebdSchin /*
461da2e3ebdSchin * the following test is needed to prevent variables
462da2e3ebdSchin * with E attribute from being given the F
463da2e3ebdSchin * attribute as well
464da2e3ebdSchin */
4657c2fbfb3SApril Chin if(val==NV_DOUBLE && (attr&(NV_EXPNOTE|NV_HEXFLOAT)))
466da2e3ebdSchin continue;
467da2e3ebdSchin if(val&NV_INTEGER)
468da2e3ebdSchin mask |= NV_DOUBLE;
469da2e3ebdSchin else if(val&NV_HOST)
470da2e3ebdSchin mask = NV_HOST;
471da2e3ebdSchin if((attr&mask)==val)
472da2e3ebdSchin {
473da2e3ebdSchin if(val==NV_ARRAY)
474da2e3ebdSchin {
475da2e3ebdSchin Namarr_t *ap = nv_arrayptr(np);
4767c2fbfb3SApril Chin char **xp=0;
4777c2fbfb3SApril Chin if(ap && array_assoc(ap))
478da2e3ebdSchin {
479da2e3ebdSchin if(tp->sh_name[1]!='A')
480da2e3ebdSchin continue;
481da2e3ebdSchin }
482da2e3ebdSchin else if(tp->sh_name[1]=='A')
483da2e3ebdSchin continue;
48434f9b3eeSRoland Mainz if((ap && (ap->nelem&ARRAY_TREE)) || (!ap && nv_isattr(np,NV_NOFREE)))
4857c2fbfb3SApril Chin {
4867c2fbfb3SApril Chin if(prefix && *prefix)
4877c2fbfb3SApril Chin sfwrite(out,"-C ",3);
4887c2fbfb3SApril Chin }
4897c2fbfb3SApril Chin if(ap && !array_assoc(ap) && (xp=(char**)(ap+1)) && *xp)
4907c2fbfb3SApril Chin ip = nv_namptr(*xp,0)->nvname;
491da2e3ebdSchin }
492da2e3ebdSchin if(prefix)
493da2e3ebdSchin {
494da2e3ebdSchin if(*tp->sh_name=='-')
495da2e3ebdSchin sfprintf(out,"%.2s ",tp->sh_name);
4967c2fbfb3SApril Chin if(ip)
4977c2fbfb3SApril Chin {
4987c2fbfb3SApril Chin sfprintf(out,"[%s] ",ip);
4997c2fbfb3SApril Chin ip = 0;
5007c2fbfb3SApril Chin }
501da2e3ebdSchin }
502da2e3ebdSchin else
503da2e3ebdSchin sfputr(out,tp->sh_name+2,' ');
504da2e3ebdSchin if ((val&(NV_LJUST|NV_RJUST|NV_ZFILL)) && !(val&NV_INTEGER) && val!=NV_HOST)
505da2e3ebdSchin sfprintf(out,"%d ",nv_size(np));
5067c2fbfb3SApril Chin if(val==(NV_REF|NV_TAGGED))
5077c2fbfb3SApril Chin attr &= ~(NV_REF|NV_TAGGED);
508da2e3ebdSchin }
509da2e3ebdSchin if(val==NV_INTEGER && nv_isattr(np,NV_INTEGER))
510da2e3ebdSchin {
511da2e3ebdSchin if(nv_size(np) != 10)
512da2e3ebdSchin {
5137c2fbfb3SApril Chin if(nv_isattr(np, NV_DOUBLE)== NV_DOUBLE)
514da2e3ebdSchin cp = "precision";
515da2e3ebdSchin else
516da2e3ebdSchin cp = "base";
517da2e3ebdSchin if(!prefix)
518da2e3ebdSchin sfputr(out,cp,' ');
519da2e3ebdSchin sfprintf(out,"%d ",nv_size(np));
520da2e3ebdSchin }
521da2e3ebdSchin break;
522da2e3ebdSchin }
523da2e3ebdSchin }
524da2e3ebdSchin if(fp)
525da2e3ebdSchin outtype(np,fp,out,prefix);
526da2e3ebdSchin if(noname)
527da2e3ebdSchin return;
528da2e3ebdSchin sfputr(out,nv_name(np),'\n');
529da2e3ebdSchin }
530da2e3ebdSchin }
531da2e3ebdSchin
532da2e3ebdSchin struct Walk
533da2e3ebdSchin {
534da2e3ebdSchin Sfio_t *out;
535da2e3ebdSchin Dt_t *root;
536da2e3ebdSchin int noscope;
537da2e3ebdSchin int indent;
5387c2fbfb3SApril Chin int nofollow;
5397c2fbfb3SApril Chin int array;
5407c2fbfb3SApril Chin int flags;
541da2e3ebdSchin };
542da2e3ebdSchin
nv_outnode(Namval_t * np,Sfio_t * out,int indent,int special)5437c2fbfb3SApril Chin void nv_outnode(Namval_t *np, Sfio_t* out, int indent, int special)
5447c2fbfb3SApril Chin {
5457c2fbfb3SApril Chin char *fmtq,*ep,*xp;
5467c2fbfb3SApril Chin Namval_t *mp;
5477c2fbfb3SApril Chin Namarr_t *ap = nv_arrayptr(np);
5487c2fbfb3SApril Chin int tabs=0,c,more,associative = 0;
5497c2fbfb3SApril Chin if(ap)
5507c2fbfb3SApril Chin {
5517c2fbfb3SApril Chin if(!(ap->nelem&ARRAY_SCAN))
5527c2fbfb3SApril Chin nv_putsub(np,NIL(char*),ARRAY_SCAN);
5537c2fbfb3SApril Chin sfputc(out,'(');
5547c2fbfb3SApril Chin if(indent>=0)
5557c2fbfb3SApril Chin {
5567c2fbfb3SApril Chin sfputc(out,'\n');
5577c2fbfb3SApril Chin tabs=1;
5587c2fbfb3SApril Chin }
5597c2fbfb3SApril Chin if(!(associative =(array_assoc(ap)!=0)))
5607c2fbfb3SApril Chin {
5617c2fbfb3SApril Chin if(array_elem(ap) < nv_aimax(np)+1)
5627c2fbfb3SApril Chin associative=1;
5637c2fbfb3SApril Chin }
5647c2fbfb3SApril Chin }
5657c2fbfb3SApril Chin mp = nv_opensub(np);
5667c2fbfb3SApril Chin while(1)
5677c2fbfb3SApril Chin {
5687c2fbfb3SApril Chin if(mp && special && nv_isvtree(mp))
5697c2fbfb3SApril Chin {
5707c2fbfb3SApril Chin if(!nv_nextsub(np))
5717c2fbfb3SApril Chin break;
5727c2fbfb3SApril Chin mp = nv_opensub(np);
5737c2fbfb3SApril Chin continue;
5747c2fbfb3SApril Chin }
5757c2fbfb3SApril Chin if(tabs)
5767c2fbfb3SApril Chin sfnputc(out,'\t',++indent);
5777c2fbfb3SApril Chin tabs=0;
5787c2fbfb3SApril Chin if(associative||special)
5797c2fbfb3SApril Chin {
5807c2fbfb3SApril Chin if(!(fmtq = nv_getsub(np)))
5817c2fbfb3SApril Chin break;
5827c2fbfb3SApril Chin sfprintf(out,"[%s]",sh_fmtq(fmtq));
5837c2fbfb3SApril Chin sfputc(out,'=');
5847c2fbfb3SApril Chin }
5857c2fbfb3SApril Chin if(mp && nv_isarray(mp))
5867c2fbfb3SApril Chin {
5877c2fbfb3SApril Chin nv_outnode(mp, out, indent+(indent>=0),0);
5887c2fbfb3SApril Chin if(indent>0)
5897c2fbfb3SApril Chin sfnputc(out,'\t',indent);
5907c2fbfb3SApril Chin sfputc(out,')');
5917c2fbfb3SApril Chin sfputc(out,indent>=0?'\n':' ');
5927c2fbfb3SApril Chin more = nv_nextsub(np);
5937c2fbfb3SApril Chin goto skip;
5947c2fbfb3SApril Chin }
5957c2fbfb3SApril Chin if(mp && nv_isvtree(mp))
5967c2fbfb3SApril Chin nv_onattr(mp,NV_EXPORT);
5977c2fbfb3SApril Chin ep = nv_getval(mp?mp:np);
59834f9b3eeSRoland Mainz if(ep==Empty)
59934f9b3eeSRoland Mainz ep = 0;
6007c2fbfb3SApril Chin xp = 0;
6017c2fbfb3SApril Chin if(!ap && nv_isattr(np,NV_INTEGER|NV_LJUST)==NV_LJUST)
6027c2fbfb3SApril Chin {
6037c2fbfb3SApril Chin xp = ep+nv_size(np);
6047c2fbfb3SApril Chin while(--xp>ep && *xp==' ');
6057c2fbfb3SApril Chin if(xp>ep || *xp!=' ')
6067c2fbfb3SApril Chin xp++;
6077c2fbfb3SApril Chin if(xp < (ep+nv_size(np)))
6087c2fbfb3SApril Chin *xp = 0;
6097c2fbfb3SApril Chin else
6107c2fbfb3SApril Chin xp = 0;
6117c2fbfb3SApril Chin }
6127c2fbfb3SApril Chin if(mp && nv_isvtree(mp))
6137c2fbfb3SApril Chin fmtq = ep;
6147c2fbfb3SApril Chin else if(!(fmtq = sh_fmtq(ep)))
6157c2fbfb3SApril Chin fmtq = "";
6167c2fbfb3SApril Chin else if(!associative && (ep=strchr(fmtq,'=')))
6177c2fbfb3SApril Chin {
6187c2fbfb3SApril Chin char *qp = strchr(fmtq,'\'');
6197c2fbfb3SApril Chin if(!qp || qp>ep)
6207c2fbfb3SApril Chin {
6217c2fbfb3SApril Chin sfwrite(out,fmtq,ep-fmtq);
6227c2fbfb3SApril Chin sfputc(out,'\\');
6237c2fbfb3SApril Chin fmtq = ep;
6247c2fbfb3SApril Chin }
6257c2fbfb3SApril Chin }
6267c2fbfb3SApril Chin more = nv_nextsub(np);
6277c2fbfb3SApril Chin c = '\n';
6287c2fbfb3SApril Chin if(indent<0)
6297c2fbfb3SApril Chin {
6307c2fbfb3SApril Chin c = ';';
6317c2fbfb3SApril Chin if(ap)
6327c2fbfb3SApril Chin c = more?' ':-1;
6337c2fbfb3SApril Chin }
6347c2fbfb3SApril Chin sfputr(out,fmtq,c);
6357c2fbfb3SApril Chin if(xp)
6367c2fbfb3SApril Chin *xp = ' ';
6377c2fbfb3SApril Chin skip:
6387c2fbfb3SApril Chin if(!more)
6397c2fbfb3SApril Chin return;
6407c2fbfb3SApril Chin mp = nv_opensub(np);
6417c2fbfb3SApril Chin if(indent>0 && !(mp && special && nv_isvtree(mp)))
6427c2fbfb3SApril Chin sfnputc(out,'\t',indent);
6437c2fbfb3SApril Chin }
6447c2fbfb3SApril Chin }
6457c2fbfb3SApril Chin
outval(char * name,const char * vname,struct Walk * wp)646da2e3ebdSchin static void outval(char *name, const char *vname, struct Walk *wp)
647da2e3ebdSchin {
648da2e3ebdSchin register Namval_t *np, *nq;
649da2e3ebdSchin register Namfun_t *fp;
6507c2fbfb3SApril Chin int isarray=0, special=0,mode=0;
6517c2fbfb3SApril Chin if(*name!='.' || vname[strlen(vname)-1]==']')
6527c2fbfb3SApril Chin mode = NV_ARRAY;
6537c2fbfb3SApril Chin if(!(np=nv_open(vname,wp->root,mode|NV_VARNAME|NV_NOADD|NV_NOASSIGN|NV_NOFAIL|wp->noscope)))
654da2e3ebdSchin return;
6557c2fbfb3SApril Chin fp = nv_hasdisc(np,&treedisc);
6567c2fbfb3SApril Chin if(*name=='.')
657da2e3ebdSchin {
6587c2fbfb3SApril Chin if(nv_isattr(np,NV_BINARY))
6597c2fbfb3SApril Chin return;
6607c2fbfb3SApril Chin if(fp && np->nvalue.cp && np->nvalue.cp!=Empty)
6617c2fbfb3SApril Chin {
6627c2fbfb3SApril Chin nv_local = 1;
6637c2fbfb3SApril Chin fp = 0;
6647c2fbfb3SApril Chin }
6657c2fbfb3SApril Chin if(fp)
6667c2fbfb3SApril Chin return;
6677c2fbfb3SApril Chin if(nv_isarray(np))
6687c2fbfb3SApril Chin return;
6697c2fbfb3SApril Chin }
6707c2fbfb3SApril Chin if(!special && fp && !nv_isarray(np))
6717c2fbfb3SApril Chin {
6727c2fbfb3SApril Chin Namfun_t *xp;
673da2e3ebdSchin if(!wp->out)
674da2e3ebdSchin {
675da2e3ebdSchin fp = nv_stack(np,fp);
676da2e3ebdSchin if(fp = nv_stack(np,NIL(Namfun_t*)))
677da2e3ebdSchin free((void*)fp);
678da2e3ebdSchin np->nvfun = 0;
679da2e3ebdSchin return;
680da2e3ebdSchin }
6817c2fbfb3SApril Chin for(xp=fp->next; xp; xp = xp->next)
6827c2fbfb3SApril Chin {
6837c2fbfb3SApril Chin if(xp->disc && (xp->disc->getval || xp->disc->getnum))
6847c2fbfb3SApril Chin break;
6857c2fbfb3SApril Chin }
6867c2fbfb3SApril Chin if(!xp)
687da2e3ebdSchin return;
6887c2fbfb3SApril Chin }
68934f9b3eeSRoland Mainz if(nv_isnull(np) && !nv_isarray(np) && !nv_isattr(np,NV_INTEGER))
6907c2fbfb3SApril Chin return;
6917c2fbfb3SApril Chin if(special || (nv_isarray(np) && nv_arrayptr(np)))
692da2e3ebdSchin {
693da2e3ebdSchin isarray=1;
694da2e3ebdSchin if(array_elem(nv_arrayptr(np))==0)
695da2e3ebdSchin isarray=2;
696da2e3ebdSchin else
697da2e3ebdSchin nq = nv_putsub(np,NIL(char*),ARRAY_SCAN|(wp->out?ARRAY_NOCHILD:0));
698da2e3ebdSchin }
699da2e3ebdSchin if(!wp->out)
700da2e3ebdSchin {
701da2e3ebdSchin _nv_unset(np,NV_RDONLY);
702da2e3ebdSchin nv_close(np);
7037c2fbfb3SApril Chin #if 0
7047c2fbfb3SApril Chin if(sh.subshell==0 && !(wp->flags&NV_RDONLY) && !nv_isattr(np,NV_MINIMAL|NV_NOFREE))
7057c2fbfb3SApril Chin nv_delete(np,wp->root,0);
7067c2fbfb3SApril Chin #endif
707da2e3ebdSchin return;
708da2e3ebdSchin }
709da2e3ebdSchin if(isarray==1 && !nq)
7107c2fbfb3SApril Chin {
7117c2fbfb3SApril Chin sfputc(wp->out,'(');
7127c2fbfb3SApril Chin if(wp->indent>=0)
7137c2fbfb3SApril Chin sfputc(wp->out,'\n');
714da2e3ebdSchin return;
715da2e3ebdSchin }
7167c2fbfb3SApril Chin if(isarray==0 && nv_isarray(np) && nv_isnull(np)) /* empty array */
7177c2fbfb3SApril Chin isarray = 2;
7187c2fbfb3SApril Chin special |= wp->nofollow;
7197c2fbfb3SApril Chin if(!wp->array && wp->indent>0)
720da2e3ebdSchin sfnputc(wp->out,'\t',wp->indent);
7217c2fbfb3SApril Chin if(!special)
7227c2fbfb3SApril Chin {
7237c2fbfb3SApril Chin if(*name!='.')
724da2e3ebdSchin nv_attribute(np,wp->out,"typeset",'=');
725da2e3ebdSchin nv_outname(wp->out,name,-1);
72634f9b3eeSRoland Mainz if((np->nvalue.cp && np->nvalue.cp!=Empty) || nv_isattr(np,~(NV_MINIMAL|NV_NOFREE)) || nv_isvtree(np))
727*3e14f97fSRoger A. Faulkner {
728*3e14f97fSRoger A. Faulkner if(wp->indent>=0 || isarray!=2)
729da2e3ebdSchin sfputc(wp->out,(isarray==2?'\n':'='));
730*3e14f97fSRoger A. Faulkner }
731da2e3ebdSchin if(isarray==2)
732da2e3ebdSchin return;
733da2e3ebdSchin }
7347c2fbfb3SApril Chin fp = np->nvfun;
7357c2fbfb3SApril Chin if(*name=='.' && !isarray)
7367c2fbfb3SApril Chin np->nvfun = 0;
7377c2fbfb3SApril Chin nv_outnode(np, wp->out, wp->indent, special);
7387c2fbfb3SApril Chin if(*name=='.' && !isarray)
7397c2fbfb3SApril Chin np->nvfun = fp;
740da2e3ebdSchin if(isarray && !special)
741da2e3ebdSchin {
7427c2fbfb3SApril Chin if(wp->indent>0)
7437c2fbfb3SApril Chin {
7447c2fbfb3SApril Chin sfnputc(wp->out,'\t',wp->indent);
745da2e3ebdSchin sfwrite(wp->out,")\n",2);
746da2e3ebdSchin }
7477c2fbfb3SApril Chin else
7487c2fbfb3SApril Chin sfwrite(wp->out,");",2);
7497c2fbfb3SApril Chin }
750da2e3ebdSchin }
751da2e3ebdSchin
752da2e3ebdSchin /*
753da2e3ebdSchin * format initialization list given a list of assignments <argp>
754da2e3ebdSchin */
genvalue(char ** argv,const char * prefix,int n,struct Walk * wp)755da2e3ebdSchin static char **genvalue(char **argv, const char *prefix, int n, struct Walk *wp)
756da2e3ebdSchin {
757da2e3ebdSchin register char *cp,*nextcp,*arg;
758da2e3ebdSchin register Sfio_t *outfile = wp->out;
7597c2fbfb3SApril Chin register int m,r,l;
760da2e3ebdSchin if(n==0)
761da2e3ebdSchin m = strlen(prefix);
762da2e3ebdSchin else if(cp=nextdot(prefix))
763da2e3ebdSchin m = cp-prefix;
764da2e3ebdSchin else
765da2e3ebdSchin m = strlen(prefix)-1;
766da2e3ebdSchin m++;
7677c2fbfb3SApril Chin if(outfile && !wp->array)
768da2e3ebdSchin {
7697c2fbfb3SApril Chin sfputc(outfile,'(');
7707c2fbfb3SApril Chin if(wp->indent>=0)
7717c2fbfb3SApril Chin {
772da2e3ebdSchin wp->indent++;
7737c2fbfb3SApril Chin sfputc(outfile,'\n');
7747c2fbfb3SApril Chin }
775da2e3ebdSchin }
776da2e3ebdSchin for(; arg= *argv; argv++)
777da2e3ebdSchin {
778da2e3ebdSchin cp = arg + n;
779da2e3ebdSchin if(n==0 && cp[m-1]!='.')
780da2e3ebdSchin continue;
781da2e3ebdSchin if(n && cp[m-1]==0)
782da2e3ebdSchin break;
783da2e3ebdSchin if(n==0 || strncmp(arg,prefix-n,m+n)==0)
784da2e3ebdSchin {
785da2e3ebdSchin cp +=m;
786da2e3ebdSchin r = 0;
787da2e3ebdSchin if(*cp=='.')
788da2e3ebdSchin cp++,r++;
789da2e3ebdSchin if(nextcp=nextdot(cp))
790da2e3ebdSchin {
791da2e3ebdSchin if(outfile)
792da2e3ebdSchin {
7937c2fbfb3SApril Chin Namval_t *np,*tp;
7947c2fbfb3SApril Chin *nextcp = 0;
7957c2fbfb3SApril Chin np=nv_open(arg,wp->root,NV_VARNAME|NV_NOADD|NV_NOASSIGN|NV_NOFAIL|wp->noscope);
7967c2fbfb3SApril Chin if(!np || (nv_isarray(np) && (!(tp=nv_opensub(np)) || !nv_isvtree(tp))))
7977c2fbfb3SApril Chin {
7987c2fbfb3SApril Chin *nextcp = '.';
7997c2fbfb3SApril Chin continue;
8007c2fbfb3SApril Chin }
8017c2fbfb3SApril Chin if(wp->indent>=0)
802da2e3ebdSchin sfnputc(outfile,'\t',wp->indent);
8037c2fbfb3SApril Chin if(*cp!='[' && (tp = nv_type(np)))
8047c2fbfb3SApril Chin {
8057c2fbfb3SApril Chin char *sp;
8067c2fbfb3SApril Chin if(sp = strrchr(tp->nvname,'.'))
8077c2fbfb3SApril Chin sp++;
8087c2fbfb3SApril Chin else
8097c2fbfb3SApril Chin sp = tp->nvname;
8107c2fbfb3SApril Chin sfputr(outfile,sp,' ');
8117c2fbfb3SApril Chin }
812da2e3ebdSchin nv_outname(outfile,cp,nextcp-cp);
813da2e3ebdSchin sfputc(outfile,'=');
8147c2fbfb3SApril Chin *nextcp = '.';
8157c2fbfb3SApril Chin }
8167c2fbfb3SApril Chin else
8177c2fbfb3SApril Chin {
8187c2fbfb3SApril Chin outval(cp,arg,wp);
8197c2fbfb3SApril Chin continue;
820da2e3ebdSchin }
821da2e3ebdSchin argv = genvalue(argv,cp,n+m+r,wp);
8227c2fbfb3SApril Chin if(wp->indent>=0)
823da2e3ebdSchin sfputc(outfile,'\n');
824da2e3ebdSchin if(*argv)
825da2e3ebdSchin continue;
826da2e3ebdSchin break;
827da2e3ebdSchin }
8287c2fbfb3SApril Chin else if(outfile && !wp->nofollow && argv[1] && memcmp(arg,argv[1],l=strlen(arg))==0 && argv[1][l]=='[')
829da2e3ebdSchin {
83034f9b3eeSRoland Mainz int k=1;
83134f9b3eeSRoland Mainz Namarr_t *ap=0;
832da2e3ebdSchin Namval_t *np = nv_open(arg,wp->root,NV_VARNAME|NV_NOADD|NV_NOASSIGN|wp->noscope);
833da2e3ebdSchin if(!np)
834da2e3ebdSchin continue;
83534f9b3eeSRoland Mainz if((wp->array = nv_isarray(np)) && (ap=nv_arrayptr(np)))
83634f9b3eeSRoland Mainz k = array_elem(ap);
83734f9b3eeSRoland Mainz
8387c2fbfb3SApril Chin if(wp->indent>0)
839da2e3ebdSchin sfnputc(outfile,'\t',wp->indent);
840da2e3ebdSchin nv_attribute(np,outfile,"typeset",1);
841da2e3ebdSchin nv_close(np);
84234f9b3eeSRoland Mainz sfputr(outfile,arg+m+r+(n?n:0),(k?'=':'\n'));
84334f9b3eeSRoland Mainz if(!k)
84434f9b3eeSRoland Mainz {
84534f9b3eeSRoland Mainz wp->array=0;
84634f9b3eeSRoland Mainz continue;
84734f9b3eeSRoland Mainz }
8487c2fbfb3SApril Chin wp->nofollow=1;
8497c2fbfb3SApril Chin argv = genvalue(argv,cp,cp-arg ,wp);
8507c2fbfb3SApril Chin sfputc(outfile,wp->indent<0?';':'\n');
851da2e3ebdSchin }
852da2e3ebdSchin else if(outfile && *cp=='[')
853da2e3ebdSchin {
8547c2fbfb3SApril Chin if(wp->indent)
855da2e3ebdSchin sfnputc(outfile,'\t',wp->indent);
856da2e3ebdSchin sfputr(outfile,cp,'=');
857da2e3ebdSchin argv = genvalue(++argv,cp,cp-arg ,wp);
858da2e3ebdSchin sfputc(outfile,'\n');
859da2e3ebdSchin }
860da2e3ebdSchin else
8617c2fbfb3SApril Chin {
862da2e3ebdSchin outval(cp,arg,wp);
8637c2fbfb3SApril Chin if(wp->array)
8647c2fbfb3SApril Chin {
8657c2fbfb3SApril Chin if(wp->indent>=0)
8667c2fbfb3SApril Chin wp->indent++;
8677c2fbfb3SApril Chin else
8687c2fbfb3SApril Chin sfputc(outfile,' ');
8697c2fbfb3SApril Chin wp->array = 0;
8707c2fbfb3SApril Chin }
8717c2fbfb3SApril Chin }
872da2e3ebdSchin }
873da2e3ebdSchin else
874da2e3ebdSchin break;
8757c2fbfb3SApril Chin wp->nofollow = 0;
876da2e3ebdSchin }
8777c2fbfb3SApril Chin wp->array = 0;
878da2e3ebdSchin if(outfile)
879da2e3ebdSchin {
880da2e3ebdSchin int c = prefix[m-1];
881da2e3ebdSchin cp = (char*)prefix;
882da2e3ebdSchin if(c=='.')
883da2e3ebdSchin cp[m-1] = 0;
884da2e3ebdSchin outval(".",prefix-n,wp);
885da2e3ebdSchin if(c=='.')
886da2e3ebdSchin cp[m-1] = c;
8877c2fbfb3SApril Chin if(wp->indent>0)
8887c2fbfb3SApril Chin sfnputc(outfile,'\t',--wp->indent);
889da2e3ebdSchin sfputc(outfile,')');
890da2e3ebdSchin }
891da2e3ebdSchin return(--argv);
892da2e3ebdSchin }
893da2e3ebdSchin
894da2e3ebdSchin /*
895da2e3ebdSchin * walk the virtual tree and print or delete name-value pairs
896da2e3ebdSchin */
walk_tree(register Namval_t * np,Namval_t * xp,int flags)8977c2fbfb3SApril Chin static char *walk_tree(register Namval_t *np, Namval_t *xp, int flags)
898da2e3ebdSchin {
899da2e3ebdSchin static Sfio_t *out;
900da2e3ebdSchin struct Walk walk;
901da2e3ebdSchin Sfio_t *outfile;
9027c2fbfb3SApril Chin int len, savtop = staktell();
903da2e3ebdSchin char *savptr = stakfreeze(0);
904da2e3ebdSchin register struct argnod *ap=0;
905da2e3ebdSchin struct argnod *arglist=0;
906da2e3ebdSchin char *name,*cp, **argv;
907da2e3ebdSchin char *subscript=0;
908da2e3ebdSchin void *dir;
9097c2fbfb3SApril Chin int n=0, noscope=(flags&NV_NOSCOPE);
9107c2fbfb3SApril Chin Namarr_t *arp = nv_arrayptr(np);
9117c2fbfb3SApril Chin Dt_t *save_tree = sh.var_tree;
9127c2fbfb3SApril Chin Namval_t *mp=0;
9137c2fbfb3SApril Chin Shell_t *shp = sh_getinterp();
9147c2fbfb3SApril Chin char *xpname = xp?stakcopy(nv_name(xp)):0;
9157c2fbfb3SApril Chin if(xp)
916da2e3ebdSchin {
9177c2fbfb3SApril Chin shp->last_root = shp->prev_root;
9187c2fbfb3SApril Chin shp->last_table = shp->prev_table;
9197c2fbfb3SApril Chin }
9207c2fbfb3SApril Chin if(shp->last_table)
9217c2fbfb3SApril Chin shp->last_root = nv_dict(shp->last_table);
9227c2fbfb3SApril Chin if(shp->last_root)
9237c2fbfb3SApril Chin shp->var_tree = shp->last_root;
9247c2fbfb3SApril Chin stakputs(nv_name(np));
9257c2fbfb3SApril Chin if(arp && !(arp->nelem&ARRAY_SCAN) && (subscript = nv_getsub(np)))
9267c2fbfb3SApril Chin {
9277c2fbfb3SApril Chin mp = nv_opensub(np);
928da2e3ebdSchin stakputc('[');
929da2e3ebdSchin stakputs(subscript);
930da2e3ebdSchin stakputc(']');
931da2e3ebdSchin stakputc('.');
932da2e3ebdSchin }
9337c2fbfb3SApril Chin else if(*stakptr(staktell()-1) == ']')
9347c2fbfb3SApril Chin mp = np;
935da2e3ebdSchin name = stakfreeze(1);
9367c2fbfb3SApril Chin len = strlen(name);
9377c2fbfb3SApril Chin shp->last_root = 0;
9387c2fbfb3SApril Chin dir = nv_diropen(mp,name);
9397c2fbfb3SApril Chin walk.root = shp->last_root?shp->last_root:shp->var_tree;
940da2e3ebdSchin if(subscript)
941da2e3ebdSchin name[strlen(name)-1] = 0;
942da2e3ebdSchin while(cp = nv_dirnext(dir))
943da2e3ebdSchin {
9447c2fbfb3SApril Chin if(cp[len]!='.')
9457c2fbfb3SApril Chin continue;
9467c2fbfb3SApril Chin if(xp)
9477c2fbfb3SApril Chin {
9487c2fbfb3SApril Chin Dt_t *dp = shp->var_tree;
9497c2fbfb3SApril Chin Namval_t *nq, *mq;
9507c2fbfb3SApril Chin if(strlen(cp)<=len)
9517c2fbfb3SApril Chin continue;
9527c2fbfb3SApril Chin nq = nv_open(cp,walk.root,NV_VARNAME|NV_NOADD|NV_NOASSIGN|NV_NOFAIL);
9537c2fbfb3SApril Chin if(!nq && (flags&NV_MOVE))
9547c2fbfb3SApril Chin nq = nv_search(cp,walk.root,NV_NOADD);
9557c2fbfb3SApril Chin stakseek(0);
9567c2fbfb3SApril Chin stakputs(xpname);
9577c2fbfb3SApril Chin stakputs(cp+len);
9587c2fbfb3SApril Chin stakputc(0);
9597c2fbfb3SApril Chin shp->var_tree = save_tree;
9607c2fbfb3SApril Chin mq = nv_open(stakptr(0),save_tree,NV_VARNAME|NV_NOASSIGN|NV_NOFAIL);
9617c2fbfb3SApril Chin shp->var_tree = dp;
9627c2fbfb3SApril Chin if(nq && mq)
9637c2fbfb3SApril Chin {
9647c2fbfb3SApril Chin nv_clone(nq,mq,flags|NV_RAW);
9657c2fbfb3SApril Chin if(flags&NV_MOVE)
9667c2fbfb3SApril Chin nv_delete(nq,walk.root,0);
9677c2fbfb3SApril Chin }
9687c2fbfb3SApril Chin continue;
9697c2fbfb3SApril Chin }
970da2e3ebdSchin stakseek(ARGVAL);
971da2e3ebdSchin stakputs(cp);
972da2e3ebdSchin ap = (struct argnod*)stakfreeze(1);
973da2e3ebdSchin ap->argflag = ARG_RAW;
974da2e3ebdSchin ap->argchn.ap = arglist;
975da2e3ebdSchin n++;
976da2e3ebdSchin arglist = ap;
977da2e3ebdSchin }
9787c2fbfb3SApril Chin nv_dirclose(dir);
9797c2fbfb3SApril Chin if(xp)
9807c2fbfb3SApril Chin {
9817c2fbfb3SApril Chin shp->var_tree = save_tree;
9827c2fbfb3SApril Chin return((char*)0);
9837c2fbfb3SApril Chin }
984da2e3ebdSchin argv = (char**)stakalloc((n+1)*sizeof(char*));
985da2e3ebdSchin argv += n;
986da2e3ebdSchin *argv = 0;
987da2e3ebdSchin for(; ap; ap=ap->argchn.ap)
988da2e3ebdSchin *--argv = ap->argval;
9897c2fbfb3SApril Chin if(flags&1)
990da2e3ebdSchin outfile = 0;
991da2e3ebdSchin else if(!(outfile=out))
992da2e3ebdSchin outfile = out = sfnew((Sfio_t*)0,(char*)0,-1,-1,SF_WRITE|SF_STRING);
993da2e3ebdSchin else
994da2e3ebdSchin sfseek(outfile,0L,SEEK_SET);
995da2e3ebdSchin walk.out = outfile;
9967c2fbfb3SApril Chin walk.indent = (flags&NV_EXPORT)?-1:0;
9977c2fbfb3SApril Chin walk.nofollow = 0;
998da2e3ebdSchin walk.noscope = noscope;
9997c2fbfb3SApril Chin walk.array = 0;
10007c2fbfb3SApril Chin walk.flags = flags;
1001da2e3ebdSchin genvalue(argv,name,0,&walk);
1002da2e3ebdSchin stakset(savptr,savtop);
10037c2fbfb3SApril Chin shp->var_tree = save_tree;
1004da2e3ebdSchin if(!outfile)
1005da2e3ebdSchin return((char*)0);
1006da2e3ebdSchin sfputc(out,0);
1007da2e3ebdSchin return((char*)out->_data);
1008da2e3ebdSchin }
1009da2e3ebdSchin
nv_isvtree(Namval_t * np)10107c2fbfb3SApril Chin Namfun_t *nv_isvtree(Namval_t *np)
10117c2fbfb3SApril Chin {
10127c2fbfb3SApril Chin if(np)
10137c2fbfb3SApril Chin return(nv_hasdisc(np,&treedisc));
10147c2fbfb3SApril Chin return(0);
10157c2fbfb3SApril Chin }
10167c2fbfb3SApril Chin
1017da2e3ebdSchin /*
1018da2e3ebdSchin * get discipline for compound initializations
1019da2e3ebdSchin */
nv_getvtree(register Namval_t * np,Namfun_t * fp)1020da2e3ebdSchin char *nv_getvtree(register Namval_t *np, Namfun_t *fp)
1021da2e3ebdSchin {
1022*3e14f97fSRoger A. Faulkner int flags=0, dsize=fp->dsize;
10237c2fbfb3SApril Chin for(; fp && fp->next; fp=fp->next)
10247c2fbfb3SApril Chin {
10257c2fbfb3SApril Chin if(fp->next->disc && (fp->next->disc->getnum || fp->next->disc->getval))
1026da2e3ebdSchin return(nv_getv(np,fp));
10277c2fbfb3SApril Chin }
10287c2fbfb3SApril Chin if(nv_isattr(np,NV_BINARY) && !nv_isattr(np,NV_RAW))
1029da2e3ebdSchin return(nv_getv(np,fp));
10307c2fbfb3SApril Chin if(nv_isattr(np,NV_ARRAY) && !nv_type(np) && nv_arraychild(np,(Namval_t*)0,0)==np)
10317c2fbfb3SApril Chin return(nv_getv(np,fp));
10327c2fbfb3SApril Chin if(flags = nv_isattr(np,NV_EXPORT))
10337c2fbfb3SApril Chin nv_offattr(np,NV_EXPORT);
1034*3e14f97fSRoger A. Faulkner if(dsize && (flags&NV_EXPORT))
1035*3e14f97fSRoger A. Faulkner return("()");
10367c2fbfb3SApril Chin return(walk_tree(np,(Namval_t*)0,flags));
1037da2e3ebdSchin }
1038da2e3ebdSchin
1039da2e3ebdSchin /*
1040da2e3ebdSchin * put discipline for compound initializations
1041da2e3ebdSchin */
put_tree(register Namval_t * np,const char * val,int flags,Namfun_t * fp)1042da2e3ebdSchin static void put_tree(register Namval_t *np, const char *val, int flags,Namfun_t *fp)
1043da2e3ebdSchin {
1044da2e3ebdSchin struct Namarray *ap;
1045da2e3ebdSchin int nleft = 0;
10467c2fbfb3SApril Chin if(!val && !fp->next && nv_isattr(np,NV_NOFREE))
10477c2fbfb3SApril Chin return;
10487c2fbfb3SApril Chin if(!nv_isattr(np,(NV_INTEGER|NV_BINARY)))
10497c2fbfb3SApril Chin {
10507c2fbfb3SApril Chin Shell_t *shp = sh_getinterp();
10517c2fbfb3SApril Chin Namval_t *last_table = shp->last_table;
10527c2fbfb3SApril Chin Dt_t *last_root = shp->last_root;
105334f9b3eeSRoland Mainz Namval_t *mp = val?nv_open(val,shp->var_tree,NV_VARNAME|NV_NOADD|NV_NOASSIGN|NV_ARRAY|NV_NOFAIL):0;
10547c2fbfb3SApril Chin if(mp && nv_isvtree(mp))
10557c2fbfb3SApril Chin {
10567c2fbfb3SApril Chin shp->prev_table = shp->last_table;
10577c2fbfb3SApril Chin shp->prev_root = shp->last_root;
10587c2fbfb3SApril Chin shp->last_table = last_table;
10597c2fbfb3SApril Chin shp->last_root = last_root;
10607c2fbfb3SApril Chin if(!(flags&NV_APPEND))
10617c2fbfb3SApril Chin walk_tree(np,(Namval_t*)0,(flags&NV_NOSCOPE)|1);
10627c2fbfb3SApril Chin nv_clone(mp,np,NV_COMVAR);
10637c2fbfb3SApril Chin return;
10647c2fbfb3SApril Chin }
10657c2fbfb3SApril Chin walk_tree(np,(Namval_t*)0,(flags&NV_NOSCOPE)|1);
10667c2fbfb3SApril Chin }
1067da2e3ebdSchin nv_putv(np, val, flags,fp);
10687c2fbfb3SApril Chin if(val && nv_isattr(np,(NV_INTEGER|NV_BINARY)))
1069da2e3ebdSchin return;
1070da2e3ebdSchin if(ap= nv_arrayptr(np))
1071da2e3ebdSchin nleft = array_elem(ap);
1072da2e3ebdSchin if(nleft==0)
1073da2e3ebdSchin {
1074da2e3ebdSchin fp = nv_stack(np,fp);
1075da2e3ebdSchin if(fp = nv_stack(np,NIL(Namfun_t*)))
1076da2e3ebdSchin free((void*)fp);
1077da2e3ebdSchin }
1078da2e3ebdSchin }
1079da2e3ebdSchin
1080da2e3ebdSchin /*
1081da2e3ebdSchin * Insert discipline to cause $x to print current tree
1082da2e3ebdSchin */
nv_setvtree(register Namval_t * np)1083da2e3ebdSchin void nv_setvtree(register Namval_t *np)
1084da2e3ebdSchin {
1085da2e3ebdSchin register Namfun_t *nfp;
10867c2fbfb3SApril Chin if(sh.subshell)
10877c2fbfb3SApril Chin sh_assignok(np,1);
1088da2e3ebdSchin if(nv_hasdisc(np, &treedisc))
1089da2e3ebdSchin return;
1090da2e3ebdSchin nfp = newof(NIL(void*),Namfun_t,1,0);
1091da2e3ebdSchin nfp->disc = &treedisc;
1092*3e14f97fSRoger A. Faulkner nfp->dsize = sizeof(Namfun_t);
1093da2e3ebdSchin nv_stack(np, nfp);
1094da2e3ebdSchin }
1095da2e3ebdSchin
1096