14887Schin /***********************************************************************
24887Schin * *
34887Schin * This software is part of the ast package *
4*12068SRoger.Faulkner@Oracle.COM * Copyright (c) 1982-2010 AT&T Intellectual Property *
54887Schin * and is licensed under the *
64887Schin * Common Public License, Version 1.0 *
78462SApril.Chin@Sun.COM * by AT&T Intellectual Property *
84887Schin * *
94887Schin * A copy of the License is available at *
104887Schin * http://www.opensource.org/licenses/cpl1.0.txt *
114887Schin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
124887Schin * *
134887Schin * Information and Software Systems Research *
144887Schin * AT&T Research *
154887Schin * Florham Park NJ *
164887Schin * *
174887Schin * David Korn <dgk@research.att.com> *
184887Schin * *
194887Schin ***********************************************************************/
204887Schin #pragma prototyped
214887Schin
224887Schin /*
234887Schin * code for tree nodes and name walking
244887Schin *
254887Schin * David Korn
264887Schin * AT&T Labs
274887Schin *
284887Schin */
294887Schin
304887Schin #include "defs.h"
314887Schin #include "name.h"
324887Schin #include "argnod.h"
338462SApril.Chin@Sun.COM #include "lexstates.h"
344887Schin
354887Schin struct nvdir
364887Schin {
374887Schin Dt_t *root;
384887Schin Namval_t *hp;
394887Schin Namval_t *table;
408462SApril.Chin@Sun.COM Namval_t *otable;
414887Schin Namval_t *(*nextnode)(Namval_t*,Dt_t*,Namfun_t*);
424887Schin Namfun_t *fun;
434887Schin struct nvdir *prev;
444887Schin int len;
454887Schin char data[1];
464887Schin };
474887Schin
484887Schin char *nv_getvtree(Namval_t*, Namfun_t *);
494887Schin static void put_tree(Namval_t*, const char*, int,Namfun_t*);
508462SApril.Chin@Sun.COM static char *walk_tree(Namval_t*, Namval_t*, int);
518462SApril.Chin@Sun.COM
read_tree(Namval_t * np,Sfio_t * iop,int n,Namfun_t * dp)528462SApril.Chin@Sun.COM static int read_tree(Namval_t* np, Sfio_t *iop, int n, Namfun_t *dp)
538462SApril.Chin@Sun.COM {
548462SApril.Chin@Sun.COM Sfio_t *sp;
558462SApril.Chin@Sun.COM char *cp;
568462SApril.Chin@Sun.COM int c;
578462SApril.Chin@Sun.COM if(n>=0)
588462SApril.Chin@Sun.COM return(-1);
598462SApril.Chin@Sun.COM while((c = sfgetc(iop)) && isblank(c));
608462SApril.Chin@Sun.COM sfungetc(iop,c);
618462SApril.Chin@Sun.COM sfprintf(sh.strbuf,"%s=%c",nv_name(np),0);
628462SApril.Chin@Sun.COM cp = sfstruse(sh.strbuf);
638462SApril.Chin@Sun.COM sp = sfopen((Sfio_t*)0,cp,"s");
648462SApril.Chin@Sun.COM sfstack(iop,sp);
658462SApril.Chin@Sun.COM c=sh_eval(iop,SH_READEVAL);
668462SApril.Chin@Sun.COM return(c);
678462SApril.Chin@Sun.COM }
684887Schin
create_tree(Namval_t * np,const char * name,int flag,Namfun_t * dp)694887Schin static Namval_t *create_tree(Namval_t *np,const char *name,int flag,Namfun_t *dp)
704887Schin {
714887Schin register Namfun_t *fp=dp;
72*12068SRoger.Faulkner@Oracle.COM fp->dsize = 0;
734887Schin while(fp=fp->next)
744887Schin {
754887Schin if(fp->disc && fp->disc->createf)
764887Schin {
774887Schin if(np=(*fp->disc->createf)(np,name,flag,fp))
784887Schin dp->last = fp->last;
794887Schin return(np);
804887Schin }
814887Schin }
824887Schin return((flag&NV_NOADD)?0:np);
834887Schin }
844887Schin
clone_tree(Namval_t * np,Namval_t * mp,int flags,Namfun_t * fp)858462SApril.Chin@Sun.COM static Namfun_t *clone_tree(Namval_t *np, Namval_t *mp, int flags, Namfun_t *fp){
868462SApril.Chin@Sun.COM Namfun_t *dp;
878462SApril.Chin@Sun.COM if ((flags&NV_MOVE) && nv_type(np))
888462SApril.Chin@Sun.COM return(fp);
898462SApril.Chin@Sun.COM dp = nv_clone_disc(fp,flags);
908462SApril.Chin@Sun.COM if((flags&NV_COMVAR) && !(flags&NV_RAW))
918462SApril.Chin@Sun.COM {
928462SApril.Chin@Sun.COM walk_tree(np,mp,flags);
938462SApril.Chin@Sun.COM if((flags&NV_MOVE) && !(fp->nofree&1))
948462SApril.Chin@Sun.COM free((void*)fp);
958462SApril.Chin@Sun.COM }
968462SApril.Chin@Sun.COM return(dp);
978462SApril.Chin@Sun.COM }
988462SApril.Chin@Sun.COM
994887Schin static const Namdisc_t treedisc =
1004887Schin {
1014887Schin 0,
1024887Schin put_tree,
1034887Schin nv_getvtree,
1044887Schin 0,
1054887Schin 0,
1068462SApril.Chin@Sun.COM create_tree,
1078462SApril.Chin@Sun.COM clone_tree
1088462SApril.Chin@Sun.COM ,0,0,0,
1098462SApril.Chin@Sun.COM read_tree
1104887Schin };
1114887Schin
nextdot(const char * str)1124887Schin static char *nextdot(const char *str)
1134887Schin {
1144887Schin register char *cp;
1158462SApril.Chin@Sun.COM register int c;
1164887Schin if(*str=='.')
1174887Schin str++;
1188462SApril.Chin@Sun.COM for(cp=(char*)str;c= *cp; cp++)
1194887Schin {
1208462SApril.Chin@Sun.COM if(c=='[')
1218462SApril.Chin@Sun.COM {
1228462SApril.Chin@Sun.COM cp = nv_endsubscript((Namval_t*)0,(char*)cp,0);
1238462SApril.Chin@Sun.COM return(*cp=='.'?cp:0);
1248462SApril.Chin@Sun.COM }
1258462SApril.Chin@Sun.COM if(c=='.')
1268462SApril.Chin@Sun.COM return(cp);
1274887Schin }
1288462SApril.Chin@Sun.COM return(0);
1294887Schin }
1304887Schin
nextdisc(Namval_t * np)1314887Schin static Namfun_t *nextdisc(Namval_t *np)
1324887Schin {
1334887Schin register Namfun_t *fp;
1344887Schin if(nv_isref(np))
1354887Schin return(0);
1364887Schin for(fp=np->nvfun;fp;fp=fp->next)
1374887Schin {
1384887Schin if(fp && fp->disc && fp->disc->nextf)
1394887Schin return(fp);
1404887Schin }
1414887Schin return(0);
1424887Schin }
1434887Schin
nv_diropen(Namval_t * np,const char * name)1448462SApril.Chin@Sun.COM void *nv_diropen(Namval_t *np,const char *name)
1454887Schin {
1464887Schin char *next,*last;
1474887Schin int c,len=strlen(name);
1484887Schin struct nvdir *save, *dp = new_of(struct nvdir,len);
1498462SApril.Chin@Sun.COM Namval_t *nq=0,fake;
1508462SApril.Chin@Sun.COM Namfun_t *nfp=0;
1514887Schin if(!dp)
1524887Schin return(0);
1534887Schin memset((void*)dp, 0, sizeof(*dp));
1544887Schin if(name[len-1]=='*' || name[len-1]=='@')
1554887Schin len -= 1;
1568462SApril.Chin@Sun.COM name = memcpy(dp->data,name,len);
1578462SApril.Chin@Sun.COM dp->data[len] = 0;
1584887Schin dp->len = len;
1598462SApril.Chin@Sun.COM dp->root = sh.last_root?sh.last_root:sh.var_tree;
1608462SApril.Chin@Sun.COM #if 1
1618462SApril.Chin@Sun.COM while(1)
1628462SApril.Chin@Sun.COM {
1638462SApril.Chin@Sun.COM dp->table = sh.last_table;
1648462SApril.Chin@Sun.COM sh.last_table = 0;
1658462SApril.Chin@Sun.COM if(*(last=(char*)name)==0)
1668462SApril.Chin@Sun.COM break;
1678462SApril.Chin@Sun.COM if(!(next=nextdot(last)))
1688462SApril.Chin@Sun.COM break;
1698462SApril.Chin@Sun.COM *next = 0;
1708462SApril.Chin@Sun.COM np = nv_open(name, dp->root, NV_NOFAIL);
1718462SApril.Chin@Sun.COM *next = '.';
1728462SApril.Chin@Sun.COM if(!np || !nv_istable(np))
1738462SApril.Chin@Sun.COM break;
1748462SApril.Chin@Sun.COM dp->root = nv_dict(np);
1758462SApril.Chin@Sun.COM name = next+1;
1768462SApril.Chin@Sun.COM }
1778462SApril.Chin@Sun.COM #else
1784887Schin dp->table = sh.last_table;
1798462SApril.Chin@Sun.COM sh.last_table = 0;
1808462SApril.Chin@Sun.COM last = dp->data;
1818462SApril.Chin@Sun.COM #endif
1824887Schin if(*name)
1834887Schin {
1844887Schin fake.nvname = (char*)name;
1858462SApril.Chin@Sun.COM if(dp->hp = (Namval_t*)dtprev(dp->root,&fake))
1868462SApril.Chin@Sun.COM {
1878462SApril.Chin@Sun.COM char *cp = nv_name(dp->hp);
1888462SApril.Chin@Sun.COM c = strlen(cp);
1898462SApril.Chin@Sun.COM if(memcmp(name,cp,c) || name[c]!='[')
1908462SApril.Chin@Sun.COM dp->hp = (Namval_t*)dtnext(dp->root,dp->hp);
1918462SApril.Chin@Sun.COM else
1928462SApril.Chin@Sun.COM {
1938462SApril.Chin@Sun.COM np = dp->hp;
1948462SApril.Chin@Sun.COM last = 0;
1958462SApril.Chin@Sun.COM }
1968462SApril.Chin@Sun.COM }
19710898Sroland.mainz@nrubsig.org else
19810898Sroland.mainz@nrubsig.org dp->hp = (Namval_t*)dtfirst(dp->root);
1994887Schin }
2004887Schin else
2014887Schin dp->hp = (Namval_t*)dtfirst(dp->root);
2028462SApril.Chin@Sun.COM while(1)
2034887Schin {
2048462SApril.Chin@Sun.COM if(!last)
2058462SApril.Chin@Sun.COM next = 0;
2068462SApril.Chin@Sun.COM else if(next= nextdot(last))
2078462SApril.Chin@Sun.COM {
2088462SApril.Chin@Sun.COM c = *next;
2098462SApril.Chin@Sun.COM *next = 0;
2108462SApril.Chin@Sun.COM }
2118462SApril.Chin@Sun.COM if(!np)
2128462SApril.Chin@Sun.COM {
2138462SApril.Chin@Sun.COM if(nfp && nfp->disc && nfp->disc->createf)
2148462SApril.Chin@Sun.COM {
2158462SApril.Chin@Sun.COM np = (*nfp->disc->createf)(nq,last,0,nfp);
2168462SApril.Chin@Sun.COM if(*nfp->last == '[')
2178462SApril.Chin@Sun.COM {
2188462SApril.Chin@Sun.COM nv_endsubscript(np,nfp->last,NV_NOADD);
2198462SApril.Chin@Sun.COM if(nq = nv_opensub(np))
2208462SApril.Chin@Sun.COM np = nq;
2218462SApril.Chin@Sun.COM }
2228462SApril.Chin@Sun.COM }
2238462SApril.Chin@Sun.COM else
2248462SApril.Chin@Sun.COM np = nv_search(last,dp->root,0);
2258462SApril.Chin@Sun.COM }
2268462SApril.Chin@Sun.COM if(next)
2278462SApril.Chin@Sun.COM *next = c;
2288462SApril.Chin@Sun.COM if(np==dp->hp && !next)
2298462SApril.Chin@Sun.COM dp->hp = (Namval_t*)dtnext(dp->root,dp->hp);
2304887Schin if(np && ((nfp=nextdisc(np)) || nv_istable(np)))
2314887Schin {
2324887Schin if(!(save = new_of(struct nvdir,0)))
2334887Schin return(0);
2344887Schin *save = *dp;
2354887Schin dp->prev = save;
2364887Schin if(nv_istable(np))
2374887Schin dp->root = nv_dict(np);
2384887Schin else
2398462SApril.Chin@Sun.COM dp->root = (Dt_t*)np;
2404887Schin if(nfp)
2414887Schin {
2424887Schin dp->nextnode = nfp->disc->nextf;
2434887Schin dp->table = np;
2448462SApril.Chin@Sun.COM dp->otable = sh.last_table;
2454887Schin dp->fun = nfp;
2464887Schin dp->hp = (*dp->nextnode)(np,(Dt_t*)0,nfp);
2474887Schin }
2484887Schin else
2494887Schin dp->nextnode = 0;
2504887Schin }
2514887Schin else
2524887Schin break;
2538462SApril.Chin@Sun.COM if(!next || next[1]==0)
2548462SApril.Chin@Sun.COM break;
2554887Schin last = next+1;
2568462SApril.Chin@Sun.COM nq = np;
2578462SApril.Chin@Sun.COM np = 0;
2584887Schin }
2594887Schin return((void*)dp);
2604887Schin }
2614887Schin
2624887Schin
nextnode(struct nvdir * dp)2634887Schin static Namval_t *nextnode(struct nvdir *dp)
2644887Schin {
2654887Schin if(dp->nextnode)
2664887Schin return((*dp->nextnode)(dp->hp,dp->root,dp->fun));
2674887Schin if(dp->len && memcmp(dp->data, dp->hp->nvname, dp->len))
2684887Schin return(0);
2694887Schin return((Namval_t*)dtnext(dp->root,dp->hp));
2704887Schin }
2714887Schin
nv_dirnext(void * dir)2724887Schin char *nv_dirnext(void *dir)
2734887Schin {
2744887Schin register struct nvdir *save, *dp = (struct nvdir*)dir;
2754887Schin register Namval_t *np, *last_table;
2764887Schin register char *cp;
2774887Schin Namfun_t *nfp;
2788462SApril.Chin@Sun.COM Namval_t *nq;
2794887Schin while(1)
2804887Schin {
2814887Schin while(np=dp->hp)
2824887Schin {
2838462SApril.Chin@Sun.COM #if 0
2848462SApril.Chin@Sun.COM char *sptr;
2858462SApril.Chin@Sun.COM #endif
2868462SApril.Chin@Sun.COM if(nv_isarray(np))
2878462SApril.Chin@Sun.COM nv_putsub(np,(char*)0, ARRAY_UNDEF);
2884887Schin dp->hp = nextnode(dp);
28910898Sroland.mainz@nrubsig.org if(nv_isnull(np) && !nv_isarray(np) && !nv_isattr(np,NV_INTEGER))
2904887Schin continue;
2914887Schin last_table = sh.last_table;
2928462SApril.Chin@Sun.COM #if 0
2938462SApril.Chin@Sun.COM if(dp->table && dp->otable && !nv_isattr(dp->table,NV_MINIMAL))
2948462SApril.Chin@Sun.COM {
2958462SApril.Chin@Sun.COM sptr = dp->table->nvenv;
2968462SApril.Chin@Sun.COM dp->table->nvenv = (char*)dp->otable;
2978462SApril.Chin@Sun.COM }
2988462SApril.Chin@Sun.COM #endif
2994887Schin sh.last_table = dp->table;
3004887Schin cp = nv_name(np);
3018462SApril.Chin@Sun.COM #if 0
3028462SApril.Chin@Sun.COM if(dp->table && dp->otable && !nv_isattr(dp->table,NV_MINIMAL))
3038462SApril.Chin@Sun.COM dp->table->nvenv = sptr;
3048462SApril.Chin@Sun.COM #endif
3058462SApril.Chin@Sun.COM if(dp->nextnode && !dp->hp && (nq = (Namval_t*)dp->table))
3068462SApril.Chin@Sun.COM {
3078462SApril.Chin@Sun.COM Namarr_t *ap = nv_arrayptr(nq);
3088462SApril.Chin@Sun.COM if(ap && (ap->nelem&ARRAY_SCAN) && nv_nextsub(nq))
3098462SApril.Chin@Sun.COM dp->hp = (*dp->nextnode)(np,(Dt_t*)0,dp->fun);
3108462SApril.Chin@Sun.COM }
3114887Schin sh.last_table = last_table;
3128462SApril.Chin@Sun.COM if(!dp->len || memcmp(cp,dp->data,dp->len)==0)
3134887Schin {
3148462SApril.Chin@Sun.COM if((nfp=nextdisc(np)) && (nfp->disc->getval||nfp->disc->getnum) && nv_isvtree(np) && strcmp(cp,dp->data))
3158462SApril.Chin@Sun.COM nfp = 0;
3168462SApril.Chin@Sun.COM if(nfp || nv_istable(np))
3174887Schin {
3184887Schin Dt_t *root;
3194887Schin if(nv_istable(np))
3204887Schin root = nv_dict(np);
3214887Schin else
3228462SApril.Chin@Sun.COM root = (Dt_t*)np;
3234887Schin /* check for recursive walk */
3244887Schin for(save=dp; save; save=save->prev)
3254887Schin {
3264887Schin if(save->root==root)
3274887Schin break;
3284887Schin }
3294887Schin if(save)
3308462SApril.Chin@Sun.COM return(cp);
3314887Schin if(!(save = new_of(struct nvdir,0)))
3324887Schin return(0);
3334887Schin *save = *dp;
3344887Schin dp->prev = save;
3354887Schin dp->root = root;
3364887Schin dp->len = 0;
3374887Schin if(nfp && np->nvfun)
3384887Schin {
3398462SApril.Chin@Sun.COM #if 0
3408462SApril.Chin@Sun.COM Namarr_t *ap = nv_arrayptr(np);
3418462SApril.Chin@Sun.COM if(ap && (ap->nelem&ARRAY_UNDEF))
3428462SApril.Chin@Sun.COM nv_putsub(np,(char*)0,ARRAY_SCAN);
3438462SApril.Chin@Sun.COM #endif
3444887Schin dp->nextnode = nfp->disc->nextf;
3458462SApril.Chin@Sun.COM dp->otable = dp->table;
3464887Schin dp->table = np;
3474887Schin dp->fun = nfp;
3484887Schin dp->hp = (*dp->nextnode)(np,(Dt_t*)0,nfp);
3494887Schin }
3504887Schin else
3514887Schin dp->nextnode = 0;
3524887Schin }
3534887Schin return(cp);
3544887Schin }
3554887Schin }
3564887Schin if(!(save=dp->prev))
3574887Schin break;
3584887Schin *dp = *save;
3594887Schin free((void*)save);
3604887Schin }
3614887Schin return(0);
3624887Schin }
3634887Schin
nv_dirclose(void * dir)3644887Schin void nv_dirclose(void *dir)
3654887Schin {
3664887Schin struct nvdir *dp = (struct nvdir*)dir;
3674887Schin if(dp->prev)
3684887Schin nv_dirclose((void*)dp->prev);
3694887Schin free(dir);
3704887Schin }
3714887Schin
outtype(Namval_t * np,Namfun_t * fp,Sfio_t * out,const char * prefix)3724887Schin static void outtype(Namval_t *np, Namfun_t *fp, Sfio_t* out, const char *prefix)
3734887Schin {
3744887Schin char *type=0;
3754887Schin Namval_t *tp = fp->type;
3764887Schin if(!tp && fp->disc && fp->disc->typef)
3774887Schin tp = (*fp->disc->typef)(np,fp);
3784887Schin for(fp=fp->next;fp;fp=fp->next)
3794887Schin {
3804887Schin if(fp->type || (fp->disc && fp->disc->typef &&(*fp->disc->typef)(np,fp)))
3814887Schin {
3824887Schin outtype(np,fp,out,prefix);
3834887Schin break;
3844887Schin }
3854887Schin }
3864887Schin if(prefix && *prefix=='t')
3874887Schin type = "-T";
3884887Schin else if(!prefix)
3894887Schin type = "type";
3904887Schin if(type)
3918462SApril.Chin@Sun.COM {
3928462SApril.Chin@Sun.COM char *cp=tp->nvname;
3938462SApril.Chin@Sun.COM if(cp=strrchr(cp,'.'))
3948462SApril.Chin@Sun.COM cp++;
3958462SApril.Chin@Sun.COM else
3968462SApril.Chin@Sun.COM cp = tp->nvname;
3978462SApril.Chin@Sun.COM sfprintf(out,"%s %s ",type,cp);
3988462SApril.Chin@Sun.COM }
3994887Schin }
4004887Schin
4014887Schin /*
4024887Schin * print the attributes of name value pair give by <np>
4034887Schin */
nv_attribute(register Namval_t * np,Sfio_t * out,char * prefix,int noname)4044887Schin void nv_attribute(register Namval_t *np,Sfio_t *out,char *prefix,int noname)
4054887Schin {
4064887Schin register const Shtable_t *tp;
4074887Schin register char *cp;
4088462SApril.Chin@Sun.COM register unsigned val,mask,attr;
4098462SApril.Chin@Sun.COM char *ip=0;
4104887Schin Namfun_t *fp=0;
4118462SApril.Chin@Sun.COM Namval_t *typep=0;
4124887Schin for(fp=np->nvfun;fp;fp=fp->next)
4134887Schin {
4148462SApril.Chin@Sun.COM if((typep=fp->type) || (fp->disc && fp->disc->typef && (typep=(*fp->disc->typef)(np,fp))))
4154887Schin break;
4164887Schin }
4178462SApril.Chin@Sun.COM if(!fp && !nv_isattr(np,~(NV_MINIMAL|NV_NOFREE)))
4184887Schin {
4198462SApril.Chin@Sun.COM if(prefix && *prefix)
4208462SApril.Chin@Sun.COM {
4218462SApril.Chin@Sun.COM if(nv_isvtree(np))
4228462SApril.Chin@Sun.COM sfprintf(out,"%s -C ",prefix);
42310898Sroland.mainz@nrubsig.org else if((!np->nvalue.cp||np->nvalue.cp==Empty) && nv_isattr(np,~NV_NOFREE)==NV_MINIMAL && strcmp(np->nvname,"_"))
4248462SApril.Chin@Sun.COM sfputr(out,prefix,' ');
4258462SApril.Chin@Sun.COM }
4268462SApril.Chin@Sun.COM return;
4274887Schin }
4284887Schin
4294887Schin if ((attr=nv_isattr(np,~NV_NOFREE)) || fp)
4304887Schin {
4318462SApril.Chin@Sun.COM if((attr&NV_NOPRINT|NV_INTEGER)==NV_NOPRINT)
4324887Schin attr &= ~NV_NOPRINT;
4334887Schin if(!attr && !fp)
4344887Schin return;
4358462SApril.Chin@Sun.COM if(fp)
4368462SApril.Chin@Sun.COM {
4378462SApril.Chin@Sun.COM prefix = Empty;
4388462SApril.Chin@Sun.COM attr &= NV_RDONLY|NV_ARRAY;
4398462SApril.Chin@Sun.COM if(nv_isattr(np,NV_REF|NV_TAGGED)==(NV_REF|NV_TAGGED))
4408462SApril.Chin@Sun.COM attr |= (NV_REF|NV_TAGGED);
4418462SApril.Chin@Sun.COM if(typep)
4428462SApril.Chin@Sun.COM {
4438462SApril.Chin@Sun.COM char *cp = typep->nvname;
4448462SApril.Chin@Sun.COM if(cp = strrchr(cp,'.'))
4458462SApril.Chin@Sun.COM cp++;
4468462SApril.Chin@Sun.COM else
4478462SApril.Chin@Sun.COM cp = typep->nvname;
4488462SApril.Chin@Sun.COM sfputr(out,cp,' ');
4498462SApril.Chin@Sun.COM fp = 0;
4508462SApril.Chin@Sun.COM }
4518462SApril.Chin@Sun.COM }
4528462SApril.Chin@Sun.COM else if(prefix && *prefix)
4534887Schin sfputr(out,prefix,' ');
4544887Schin for(tp = shtab_attributes; *tp->sh_name;tp++)
4554887Schin {
4564887Schin val = tp->sh_number;
4574887Schin mask = val;
4584887Schin if(fp && (val&NV_INTEGER))
4594887Schin break;
4604887Schin /*
4614887Schin * the following test is needed to prevent variables
4624887Schin * with E attribute from being given the F
4634887Schin * attribute as well
4644887Schin */
4658462SApril.Chin@Sun.COM if(val==NV_DOUBLE && (attr&(NV_EXPNOTE|NV_HEXFLOAT)))
4664887Schin continue;
4674887Schin if(val&NV_INTEGER)
4684887Schin mask |= NV_DOUBLE;
4694887Schin else if(val&NV_HOST)
4704887Schin mask = NV_HOST;
4714887Schin if((attr&mask)==val)
4724887Schin {
4734887Schin if(val==NV_ARRAY)
4744887Schin {
4754887Schin Namarr_t *ap = nv_arrayptr(np);
4768462SApril.Chin@Sun.COM char **xp=0;
4778462SApril.Chin@Sun.COM if(ap && array_assoc(ap))
4784887Schin {
4794887Schin if(tp->sh_name[1]!='A')
4804887Schin continue;
4814887Schin }
4824887Schin else if(tp->sh_name[1]=='A')
4834887Schin continue;
48410898Sroland.mainz@nrubsig.org if((ap && (ap->nelem&ARRAY_TREE)) || (!ap && nv_isattr(np,NV_NOFREE)))
4858462SApril.Chin@Sun.COM {
4868462SApril.Chin@Sun.COM if(prefix && *prefix)
4878462SApril.Chin@Sun.COM sfwrite(out,"-C ",3);
4888462SApril.Chin@Sun.COM }
4898462SApril.Chin@Sun.COM if(ap && !array_assoc(ap) && (xp=(char**)(ap+1)) && *xp)
4908462SApril.Chin@Sun.COM ip = nv_namptr(*xp,0)->nvname;
4914887Schin }
4924887Schin if(prefix)
4934887Schin {
4944887Schin if(*tp->sh_name=='-')
4954887Schin sfprintf(out,"%.2s ",tp->sh_name);
4968462SApril.Chin@Sun.COM if(ip)
4978462SApril.Chin@Sun.COM {
4988462SApril.Chin@Sun.COM sfprintf(out,"[%s] ",ip);
4998462SApril.Chin@Sun.COM ip = 0;
5008462SApril.Chin@Sun.COM }
5014887Schin }
5024887Schin else
5034887Schin sfputr(out,tp->sh_name+2,' ');
5044887Schin if ((val&(NV_LJUST|NV_RJUST|NV_ZFILL)) && !(val&NV_INTEGER) && val!=NV_HOST)
5054887Schin sfprintf(out,"%d ",nv_size(np));
5068462SApril.Chin@Sun.COM if(val==(NV_REF|NV_TAGGED))
5078462SApril.Chin@Sun.COM attr &= ~(NV_REF|NV_TAGGED);
5084887Schin }
5094887Schin if(val==NV_INTEGER && nv_isattr(np,NV_INTEGER))
5104887Schin {
5114887Schin if(nv_size(np) != 10)
5124887Schin {
5138462SApril.Chin@Sun.COM if(nv_isattr(np, NV_DOUBLE)== NV_DOUBLE)
5144887Schin cp = "precision";
5154887Schin else
5164887Schin cp = "base";
5174887Schin if(!prefix)
5184887Schin sfputr(out,cp,' ');
5194887Schin sfprintf(out,"%d ",nv_size(np));
5204887Schin }
5214887Schin break;
5224887Schin }
5234887Schin }
5244887Schin if(fp)
5254887Schin outtype(np,fp,out,prefix);
5264887Schin if(noname)
5274887Schin return;
5284887Schin sfputr(out,nv_name(np),'\n');
5294887Schin }
5304887Schin }
5314887Schin
5324887Schin struct Walk
5334887Schin {
5344887Schin Sfio_t *out;
5354887Schin Dt_t *root;
5364887Schin int noscope;
5374887Schin int indent;
5388462SApril.Chin@Sun.COM int nofollow;
5398462SApril.Chin@Sun.COM int array;
5408462SApril.Chin@Sun.COM int flags;
5414887Schin };
5424887Schin
nv_outnode(Namval_t * np,Sfio_t * out,int indent,int special)5438462SApril.Chin@Sun.COM void nv_outnode(Namval_t *np, Sfio_t* out, int indent, int special)
5448462SApril.Chin@Sun.COM {
5458462SApril.Chin@Sun.COM char *fmtq,*ep,*xp;
5468462SApril.Chin@Sun.COM Namval_t *mp;
5478462SApril.Chin@Sun.COM Namarr_t *ap = nv_arrayptr(np);
5488462SApril.Chin@Sun.COM int tabs=0,c,more,associative = 0;
5498462SApril.Chin@Sun.COM if(ap)
5508462SApril.Chin@Sun.COM {
5518462SApril.Chin@Sun.COM if(!(ap->nelem&ARRAY_SCAN))
5528462SApril.Chin@Sun.COM nv_putsub(np,NIL(char*),ARRAY_SCAN);
5538462SApril.Chin@Sun.COM sfputc(out,'(');
5548462SApril.Chin@Sun.COM if(indent>=0)
5558462SApril.Chin@Sun.COM {
5568462SApril.Chin@Sun.COM sfputc(out,'\n');
5578462SApril.Chin@Sun.COM tabs=1;
5588462SApril.Chin@Sun.COM }
5598462SApril.Chin@Sun.COM if(!(associative =(array_assoc(ap)!=0)))
5608462SApril.Chin@Sun.COM {
5618462SApril.Chin@Sun.COM if(array_elem(ap) < nv_aimax(np)+1)
5628462SApril.Chin@Sun.COM associative=1;
5638462SApril.Chin@Sun.COM }
5648462SApril.Chin@Sun.COM }
5658462SApril.Chin@Sun.COM mp = nv_opensub(np);
5668462SApril.Chin@Sun.COM while(1)
5678462SApril.Chin@Sun.COM {
5688462SApril.Chin@Sun.COM if(mp && special && nv_isvtree(mp))
5698462SApril.Chin@Sun.COM {
5708462SApril.Chin@Sun.COM if(!nv_nextsub(np))
5718462SApril.Chin@Sun.COM break;
5728462SApril.Chin@Sun.COM mp = nv_opensub(np);
5738462SApril.Chin@Sun.COM continue;
5748462SApril.Chin@Sun.COM }
5758462SApril.Chin@Sun.COM if(tabs)
5768462SApril.Chin@Sun.COM sfnputc(out,'\t',++indent);
5778462SApril.Chin@Sun.COM tabs=0;
5788462SApril.Chin@Sun.COM if(associative||special)
5798462SApril.Chin@Sun.COM {
5808462SApril.Chin@Sun.COM if(!(fmtq = nv_getsub(np)))
5818462SApril.Chin@Sun.COM break;
5828462SApril.Chin@Sun.COM sfprintf(out,"[%s]",sh_fmtq(fmtq));
5838462SApril.Chin@Sun.COM sfputc(out,'=');
5848462SApril.Chin@Sun.COM }
5858462SApril.Chin@Sun.COM if(mp && nv_isarray(mp))
5868462SApril.Chin@Sun.COM {
5878462SApril.Chin@Sun.COM nv_outnode(mp, out, indent+(indent>=0),0);
5888462SApril.Chin@Sun.COM if(indent>0)
5898462SApril.Chin@Sun.COM sfnputc(out,'\t',indent);
5908462SApril.Chin@Sun.COM sfputc(out,')');
5918462SApril.Chin@Sun.COM sfputc(out,indent>=0?'\n':' ');
5928462SApril.Chin@Sun.COM more = nv_nextsub(np);
5938462SApril.Chin@Sun.COM goto skip;
5948462SApril.Chin@Sun.COM }
5958462SApril.Chin@Sun.COM if(mp && nv_isvtree(mp))
5968462SApril.Chin@Sun.COM nv_onattr(mp,NV_EXPORT);
5978462SApril.Chin@Sun.COM ep = nv_getval(mp?mp:np);
59810898Sroland.mainz@nrubsig.org if(ep==Empty)
59910898Sroland.mainz@nrubsig.org ep = 0;
6008462SApril.Chin@Sun.COM xp = 0;
6018462SApril.Chin@Sun.COM if(!ap && nv_isattr(np,NV_INTEGER|NV_LJUST)==NV_LJUST)
6028462SApril.Chin@Sun.COM {
6038462SApril.Chin@Sun.COM xp = ep+nv_size(np);
6048462SApril.Chin@Sun.COM while(--xp>ep && *xp==' ');
6058462SApril.Chin@Sun.COM if(xp>ep || *xp!=' ')
6068462SApril.Chin@Sun.COM xp++;
6078462SApril.Chin@Sun.COM if(xp < (ep+nv_size(np)))
6088462SApril.Chin@Sun.COM *xp = 0;
6098462SApril.Chin@Sun.COM else
6108462SApril.Chin@Sun.COM xp = 0;
6118462SApril.Chin@Sun.COM }
6128462SApril.Chin@Sun.COM if(mp && nv_isvtree(mp))
6138462SApril.Chin@Sun.COM fmtq = ep;
6148462SApril.Chin@Sun.COM else if(!(fmtq = sh_fmtq(ep)))
6158462SApril.Chin@Sun.COM fmtq = "";
6168462SApril.Chin@Sun.COM else if(!associative && (ep=strchr(fmtq,'=')))
6178462SApril.Chin@Sun.COM {
6188462SApril.Chin@Sun.COM char *qp = strchr(fmtq,'\'');
6198462SApril.Chin@Sun.COM if(!qp || qp>ep)
6208462SApril.Chin@Sun.COM {
6218462SApril.Chin@Sun.COM sfwrite(out,fmtq,ep-fmtq);
6228462SApril.Chin@Sun.COM sfputc(out,'\\');
6238462SApril.Chin@Sun.COM fmtq = ep;
6248462SApril.Chin@Sun.COM }
6258462SApril.Chin@Sun.COM }
6268462SApril.Chin@Sun.COM more = nv_nextsub(np);
6278462SApril.Chin@Sun.COM c = '\n';
6288462SApril.Chin@Sun.COM if(indent<0)
6298462SApril.Chin@Sun.COM {
6308462SApril.Chin@Sun.COM c = ';';
6318462SApril.Chin@Sun.COM if(ap)
6328462SApril.Chin@Sun.COM c = more?' ':-1;
6338462SApril.Chin@Sun.COM }
6348462SApril.Chin@Sun.COM sfputr(out,fmtq,c);
6358462SApril.Chin@Sun.COM if(xp)
6368462SApril.Chin@Sun.COM *xp = ' ';
6378462SApril.Chin@Sun.COM skip:
6388462SApril.Chin@Sun.COM if(!more)
6398462SApril.Chin@Sun.COM return;
6408462SApril.Chin@Sun.COM mp = nv_opensub(np);
6418462SApril.Chin@Sun.COM if(indent>0 && !(mp && special && nv_isvtree(mp)))
6428462SApril.Chin@Sun.COM sfnputc(out,'\t',indent);
6438462SApril.Chin@Sun.COM }
6448462SApril.Chin@Sun.COM }
6458462SApril.Chin@Sun.COM
outval(char * name,const char * vname,struct Walk * wp)6464887Schin static void outval(char *name, const char *vname, struct Walk *wp)
6474887Schin {
6484887Schin register Namval_t *np, *nq;
6494887Schin register Namfun_t *fp;
6508462SApril.Chin@Sun.COM int isarray=0, special=0,mode=0;
6518462SApril.Chin@Sun.COM if(*name!='.' || vname[strlen(vname)-1]==']')
6528462SApril.Chin@Sun.COM mode = NV_ARRAY;
6538462SApril.Chin@Sun.COM if(!(np=nv_open(vname,wp->root,mode|NV_VARNAME|NV_NOADD|NV_NOASSIGN|NV_NOFAIL|wp->noscope)))
6544887Schin return;
6558462SApril.Chin@Sun.COM fp = nv_hasdisc(np,&treedisc);
6568462SApril.Chin@Sun.COM if(*name=='.')
6574887Schin {
6588462SApril.Chin@Sun.COM if(nv_isattr(np,NV_BINARY))
6598462SApril.Chin@Sun.COM return;
6608462SApril.Chin@Sun.COM if(fp && np->nvalue.cp && np->nvalue.cp!=Empty)
6618462SApril.Chin@Sun.COM {
6628462SApril.Chin@Sun.COM nv_local = 1;
6638462SApril.Chin@Sun.COM fp = 0;
6648462SApril.Chin@Sun.COM }
6658462SApril.Chin@Sun.COM if(fp)
6668462SApril.Chin@Sun.COM return;
6678462SApril.Chin@Sun.COM if(nv_isarray(np))
6688462SApril.Chin@Sun.COM return;
6698462SApril.Chin@Sun.COM }
6708462SApril.Chin@Sun.COM if(!special && fp && !nv_isarray(np))
6718462SApril.Chin@Sun.COM {
6728462SApril.Chin@Sun.COM Namfun_t *xp;
6734887Schin if(!wp->out)
6744887Schin {
6754887Schin fp = nv_stack(np,fp);
6764887Schin if(fp = nv_stack(np,NIL(Namfun_t*)))
6774887Schin free((void*)fp);
6784887Schin np->nvfun = 0;
6798462SApril.Chin@Sun.COM return;
6804887Schin }
6818462SApril.Chin@Sun.COM for(xp=fp->next; xp; xp = xp->next)
6828462SApril.Chin@Sun.COM {
6838462SApril.Chin@Sun.COM if(xp->disc && (xp->disc->getval || xp->disc->getnum))
6848462SApril.Chin@Sun.COM break;
6858462SApril.Chin@Sun.COM }
6868462SApril.Chin@Sun.COM if(!xp)
6878462SApril.Chin@Sun.COM return;
6884887Schin }
68910898Sroland.mainz@nrubsig.org if(nv_isnull(np) && !nv_isarray(np) && !nv_isattr(np,NV_INTEGER))
6904887Schin return;
6918462SApril.Chin@Sun.COM if(special || (nv_isarray(np) && nv_arrayptr(np)))
6924887Schin {
6934887Schin isarray=1;
6944887Schin if(array_elem(nv_arrayptr(np))==0)
6954887Schin isarray=2;
6964887Schin else
6974887Schin nq = nv_putsub(np,NIL(char*),ARRAY_SCAN|(wp->out?ARRAY_NOCHILD:0));
6984887Schin }
6994887Schin if(!wp->out)
7004887Schin {
7014887Schin _nv_unset(np,NV_RDONLY);
7024887Schin nv_close(np);
7038462SApril.Chin@Sun.COM #if 0
7048462SApril.Chin@Sun.COM if(sh.subshell==0 && !(wp->flags&NV_RDONLY) && !nv_isattr(np,NV_MINIMAL|NV_NOFREE))
7058462SApril.Chin@Sun.COM nv_delete(np,wp->root,0);
7068462SApril.Chin@Sun.COM #endif
7074887Schin return;
7084887Schin }
7094887Schin if(isarray==1 && !nq)
7108462SApril.Chin@Sun.COM {
7118462SApril.Chin@Sun.COM sfputc(wp->out,'(');
7128462SApril.Chin@Sun.COM if(wp->indent>=0)
7138462SApril.Chin@Sun.COM sfputc(wp->out,'\n');
7144887Schin return;
7154887Schin }
7168462SApril.Chin@Sun.COM if(isarray==0 && nv_isarray(np) && nv_isnull(np)) /* empty array */
7178462SApril.Chin@Sun.COM isarray = 2;
7188462SApril.Chin@Sun.COM special |= wp->nofollow;
7198462SApril.Chin@Sun.COM if(!wp->array && wp->indent>0)
7204887Schin sfnputc(wp->out,'\t',wp->indent);
7218462SApril.Chin@Sun.COM if(!special)
7224887Schin {
7238462SApril.Chin@Sun.COM if(*name!='.')
7248462SApril.Chin@Sun.COM nv_attribute(np,wp->out,"typeset",'=');
7258462SApril.Chin@Sun.COM nv_outname(wp->out,name,-1);
72610898Sroland.mainz@nrubsig.org if((np->nvalue.cp && np->nvalue.cp!=Empty) || nv_isattr(np,~(NV_MINIMAL|NV_NOFREE)) || nv_isvtree(np))
727*12068SRoger.Faulkner@Oracle.COM {
728*12068SRoger.Faulkner@Oracle.COM if(wp->indent>=0 || isarray!=2)
729*12068SRoger.Faulkner@Oracle.COM sfputc(wp->out,(isarray==2?'\n':'='));
730*12068SRoger.Faulkner@Oracle.COM }
7318462SApril.Chin@Sun.COM if(isarray==2)
7328462SApril.Chin@Sun.COM return;
7334887Schin }
7348462SApril.Chin@Sun.COM fp = np->nvfun;
7358462SApril.Chin@Sun.COM if(*name=='.' && !isarray)
7368462SApril.Chin@Sun.COM np->nvfun = 0;
7378462SApril.Chin@Sun.COM nv_outnode(np, wp->out, wp->indent, special);
7388462SApril.Chin@Sun.COM if(*name=='.' && !isarray)
7398462SApril.Chin@Sun.COM np->nvfun = fp;
7404887Schin if(isarray && !special)
7414887Schin {
7428462SApril.Chin@Sun.COM if(wp->indent>0)
7438462SApril.Chin@Sun.COM {
7448462SApril.Chin@Sun.COM sfnputc(wp->out,'\t',wp->indent);
7458462SApril.Chin@Sun.COM sfwrite(wp->out,")\n",2);
7468462SApril.Chin@Sun.COM }
7478462SApril.Chin@Sun.COM else
7488462SApril.Chin@Sun.COM sfwrite(wp->out,");",2);
7494887Schin }
7504887Schin }
7514887Schin
7524887Schin /*
7534887Schin * format initialization list given a list of assignments <argp>
7544887Schin */
genvalue(char ** argv,const char * prefix,int n,struct Walk * wp)7554887Schin static char **genvalue(char **argv, const char *prefix, int n, struct Walk *wp)
7564887Schin {
7574887Schin register char *cp,*nextcp,*arg;
7584887Schin register Sfio_t *outfile = wp->out;
7598462SApril.Chin@Sun.COM register int m,r,l;
7604887Schin if(n==0)
7614887Schin m = strlen(prefix);
7624887Schin else if(cp=nextdot(prefix))
7634887Schin m = cp-prefix;
7644887Schin else
7654887Schin m = strlen(prefix)-1;
7664887Schin m++;
7678462SApril.Chin@Sun.COM if(outfile && !wp->array)
7684887Schin {
7698462SApril.Chin@Sun.COM sfputc(outfile,'(');
7708462SApril.Chin@Sun.COM if(wp->indent>=0)
7718462SApril.Chin@Sun.COM {
7728462SApril.Chin@Sun.COM wp->indent++;
7738462SApril.Chin@Sun.COM sfputc(outfile,'\n');
7748462SApril.Chin@Sun.COM }
7754887Schin }
7764887Schin for(; arg= *argv; argv++)
7774887Schin {
7784887Schin cp = arg + n;
7794887Schin if(n==0 && cp[m-1]!='.')
7804887Schin continue;
7814887Schin if(n && cp[m-1]==0)
7824887Schin break;
7834887Schin if(n==0 || strncmp(arg,prefix-n,m+n)==0)
7844887Schin {
7854887Schin cp +=m;
7864887Schin r = 0;
7874887Schin if(*cp=='.')
7884887Schin cp++,r++;
7894887Schin if(nextcp=nextdot(cp))
7904887Schin {
7914887Schin if(outfile)
7924887Schin {
7938462SApril.Chin@Sun.COM Namval_t *np,*tp;
7948462SApril.Chin@Sun.COM *nextcp = 0;
7958462SApril.Chin@Sun.COM np=nv_open(arg,wp->root,NV_VARNAME|NV_NOADD|NV_NOASSIGN|NV_NOFAIL|wp->noscope);
7968462SApril.Chin@Sun.COM if(!np || (nv_isarray(np) && (!(tp=nv_opensub(np)) || !nv_isvtree(tp))))
7978462SApril.Chin@Sun.COM {
7988462SApril.Chin@Sun.COM *nextcp = '.';
7998462SApril.Chin@Sun.COM continue;
8008462SApril.Chin@Sun.COM }
8018462SApril.Chin@Sun.COM if(wp->indent>=0)
8028462SApril.Chin@Sun.COM sfnputc(outfile,'\t',wp->indent);
8038462SApril.Chin@Sun.COM if(*cp!='[' && (tp = nv_type(np)))
8048462SApril.Chin@Sun.COM {
8058462SApril.Chin@Sun.COM char *sp;
8068462SApril.Chin@Sun.COM if(sp = strrchr(tp->nvname,'.'))
8078462SApril.Chin@Sun.COM sp++;
8088462SApril.Chin@Sun.COM else
8098462SApril.Chin@Sun.COM sp = tp->nvname;
8108462SApril.Chin@Sun.COM sfputr(outfile,sp,' ');
8118462SApril.Chin@Sun.COM }
8124887Schin nv_outname(outfile,cp,nextcp-cp);
8134887Schin sfputc(outfile,'=');
8148462SApril.Chin@Sun.COM *nextcp = '.';
8158462SApril.Chin@Sun.COM }
8168462SApril.Chin@Sun.COM else
8178462SApril.Chin@Sun.COM {
8188462SApril.Chin@Sun.COM outval(cp,arg,wp);
8198462SApril.Chin@Sun.COM continue;
8204887Schin }
8214887Schin argv = genvalue(argv,cp,n+m+r,wp);
8228462SApril.Chin@Sun.COM if(wp->indent>=0)
8234887Schin sfputc(outfile,'\n');
8244887Schin if(*argv)
8254887Schin continue;
8264887Schin break;
8274887Schin }
8288462SApril.Chin@Sun.COM else if(outfile && !wp->nofollow && argv[1] && memcmp(arg,argv[1],l=strlen(arg))==0 && argv[1][l]=='[')
8294887Schin {
83010898Sroland.mainz@nrubsig.org int k=1;
83110898Sroland.mainz@nrubsig.org Namarr_t *ap=0;
8324887Schin Namval_t *np = nv_open(arg,wp->root,NV_VARNAME|NV_NOADD|NV_NOASSIGN|wp->noscope);
8334887Schin if(!np)
8344887Schin continue;
83510898Sroland.mainz@nrubsig.org if((wp->array = nv_isarray(np)) && (ap=nv_arrayptr(np)))
83610898Sroland.mainz@nrubsig.org k = array_elem(ap);
83710898Sroland.mainz@nrubsig.org
8388462SApril.Chin@Sun.COM if(wp->indent>0)
8398462SApril.Chin@Sun.COM sfnputc(outfile,'\t',wp->indent);
8404887Schin nv_attribute(np,outfile,"typeset",1);
8414887Schin nv_close(np);
84210898Sroland.mainz@nrubsig.org sfputr(outfile,arg+m+r+(n?n:0),(k?'=':'\n'));
84310898Sroland.mainz@nrubsig.org if(!k)
84410898Sroland.mainz@nrubsig.org {
84510898Sroland.mainz@nrubsig.org wp->array=0;
84610898Sroland.mainz@nrubsig.org continue;
84710898Sroland.mainz@nrubsig.org }
8488462SApril.Chin@Sun.COM wp->nofollow=1;
8498462SApril.Chin@Sun.COM argv = genvalue(argv,cp,cp-arg ,wp);
8508462SApril.Chin@Sun.COM sfputc(outfile,wp->indent<0?';':'\n');
8514887Schin }
8524887Schin else if(outfile && *cp=='[')
8534887Schin {
8548462SApril.Chin@Sun.COM if(wp->indent)
8558462SApril.Chin@Sun.COM sfnputc(outfile,'\t',wp->indent);
8564887Schin sfputr(outfile,cp,'=');
8574887Schin argv = genvalue(++argv,cp,cp-arg ,wp);
8584887Schin sfputc(outfile,'\n');
8594887Schin }
8604887Schin else
8618462SApril.Chin@Sun.COM {
8624887Schin outval(cp,arg,wp);
8638462SApril.Chin@Sun.COM if(wp->array)
8648462SApril.Chin@Sun.COM {
8658462SApril.Chin@Sun.COM if(wp->indent>=0)
8668462SApril.Chin@Sun.COM wp->indent++;
8678462SApril.Chin@Sun.COM else
8688462SApril.Chin@Sun.COM sfputc(outfile,' ');
8698462SApril.Chin@Sun.COM wp->array = 0;
8708462SApril.Chin@Sun.COM }
8718462SApril.Chin@Sun.COM }
8724887Schin }
8734887Schin else
8744887Schin break;
8758462SApril.Chin@Sun.COM wp->nofollow = 0;
8764887Schin }
8778462SApril.Chin@Sun.COM wp->array = 0;
8784887Schin if(outfile)
8794887Schin {
8804887Schin int c = prefix[m-1];
8814887Schin cp = (char*)prefix;
8824887Schin if(c=='.')
8834887Schin cp[m-1] = 0;
8844887Schin outval(".",prefix-n,wp);
8854887Schin if(c=='.')
8864887Schin cp[m-1] = c;
8878462SApril.Chin@Sun.COM if(wp->indent>0)
8888462SApril.Chin@Sun.COM sfnputc(outfile,'\t',--wp->indent);
8894887Schin sfputc(outfile,')');
8904887Schin }
8914887Schin return(--argv);
8924887Schin }
8934887Schin
8944887Schin /*
8954887Schin * walk the virtual tree and print or delete name-value pairs
8964887Schin */
walk_tree(register Namval_t * np,Namval_t * xp,int flags)8978462SApril.Chin@Sun.COM static char *walk_tree(register Namval_t *np, Namval_t *xp, int flags)
8984887Schin {
8994887Schin static Sfio_t *out;
9004887Schin struct Walk walk;
9014887Schin Sfio_t *outfile;
9028462SApril.Chin@Sun.COM int len, savtop = staktell();
9034887Schin char *savptr = stakfreeze(0);
9044887Schin register struct argnod *ap=0;
9054887Schin struct argnod *arglist=0;
9064887Schin char *name,*cp, **argv;
9074887Schin char *subscript=0;
9084887Schin void *dir;
9098462SApril.Chin@Sun.COM int n=0, noscope=(flags&NV_NOSCOPE);
9108462SApril.Chin@Sun.COM Namarr_t *arp = nv_arrayptr(np);
9118462SApril.Chin@Sun.COM Dt_t *save_tree = sh.var_tree;
9128462SApril.Chin@Sun.COM Namval_t *mp=0;
9138462SApril.Chin@Sun.COM Shell_t *shp = sh_getinterp();
9148462SApril.Chin@Sun.COM char *xpname = xp?stakcopy(nv_name(xp)):0;
9158462SApril.Chin@Sun.COM if(xp)
9168462SApril.Chin@Sun.COM {
9178462SApril.Chin@Sun.COM shp->last_root = shp->prev_root;
9188462SApril.Chin@Sun.COM shp->last_table = shp->prev_table;
9198462SApril.Chin@Sun.COM }
9208462SApril.Chin@Sun.COM if(shp->last_table)
9218462SApril.Chin@Sun.COM shp->last_root = nv_dict(shp->last_table);
9228462SApril.Chin@Sun.COM if(shp->last_root)
9238462SApril.Chin@Sun.COM shp->var_tree = shp->last_root;
9244887Schin stakputs(nv_name(np));
9258462SApril.Chin@Sun.COM if(arp && !(arp->nelem&ARRAY_SCAN) && (subscript = nv_getsub(np)))
9264887Schin {
9278462SApril.Chin@Sun.COM mp = nv_opensub(np);
9284887Schin stakputc('[');
9294887Schin stakputs(subscript);
9304887Schin stakputc(']');
9314887Schin stakputc('.');
9324887Schin }
9338462SApril.Chin@Sun.COM else if(*stakptr(staktell()-1) == ']')
9348462SApril.Chin@Sun.COM mp = np;
9354887Schin name = stakfreeze(1);
9368462SApril.Chin@Sun.COM len = strlen(name);
9378462SApril.Chin@Sun.COM shp->last_root = 0;
9388462SApril.Chin@Sun.COM dir = nv_diropen(mp,name);
9398462SApril.Chin@Sun.COM walk.root = shp->last_root?shp->last_root:shp->var_tree;
9404887Schin if(subscript)
9414887Schin name[strlen(name)-1] = 0;
9424887Schin while(cp = nv_dirnext(dir))
9434887Schin {
9448462SApril.Chin@Sun.COM if(cp[len]!='.')
9458462SApril.Chin@Sun.COM continue;
9468462SApril.Chin@Sun.COM if(xp)
9478462SApril.Chin@Sun.COM {
9488462SApril.Chin@Sun.COM Dt_t *dp = shp->var_tree;
9498462SApril.Chin@Sun.COM Namval_t *nq, *mq;
9508462SApril.Chin@Sun.COM if(strlen(cp)<=len)
9518462SApril.Chin@Sun.COM continue;
9528462SApril.Chin@Sun.COM nq = nv_open(cp,walk.root,NV_VARNAME|NV_NOADD|NV_NOASSIGN|NV_NOFAIL);
9538462SApril.Chin@Sun.COM if(!nq && (flags&NV_MOVE))
9548462SApril.Chin@Sun.COM nq = nv_search(cp,walk.root,NV_NOADD);
9558462SApril.Chin@Sun.COM stakseek(0);
9568462SApril.Chin@Sun.COM stakputs(xpname);
9578462SApril.Chin@Sun.COM stakputs(cp+len);
9588462SApril.Chin@Sun.COM stakputc(0);
9598462SApril.Chin@Sun.COM shp->var_tree = save_tree;
9608462SApril.Chin@Sun.COM mq = nv_open(stakptr(0),save_tree,NV_VARNAME|NV_NOASSIGN|NV_NOFAIL);
9618462SApril.Chin@Sun.COM shp->var_tree = dp;
9628462SApril.Chin@Sun.COM if(nq && mq)
9638462SApril.Chin@Sun.COM {
9648462SApril.Chin@Sun.COM nv_clone(nq,mq,flags|NV_RAW);
9658462SApril.Chin@Sun.COM if(flags&NV_MOVE)
9668462SApril.Chin@Sun.COM nv_delete(nq,walk.root,0);
9678462SApril.Chin@Sun.COM }
9688462SApril.Chin@Sun.COM continue;
9698462SApril.Chin@Sun.COM }
9704887Schin stakseek(ARGVAL);
9714887Schin stakputs(cp);
9724887Schin ap = (struct argnod*)stakfreeze(1);
9734887Schin ap->argflag = ARG_RAW;
9744887Schin ap->argchn.ap = arglist;
9754887Schin n++;
9764887Schin arglist = ap;
9774887Schin }
9788462SApril.Chin@Sun.COM nv_dirclose(dir);
9798462SApril.Chin@Sun.COM if(xp)
9808462SApril.Chin@Sun.COM {
9818462SApril.Chin@Sun.COM shp->var_tree = save_tree;
9828462SApril.Chin@Sun.COM return((char*)0);
9838462SApril.Chin@Sun.COM }
9844887Schin argv = (char**)stakalloc((n+1)*sizeof(char*));
9854887Schin argv += n;
9864887Schin *argv = 0;
9874887Schin for(; ap; ap=ap->argchn.ap)
9884887Schin *--argv = ap->argval;
9898462SApril.Chin@Sun.COM if(flags&1)
9904887Schin outfile = 0;
9914887Schin else if(!(outfile=out))
9924887Schin outfile = out = sfnew((Sfio_t*)0,(char*)0,-1,-1,SF_WRITE|SF_STRING);
9934887Schin else
9944887Schin sfseek(outfile,0L,SEEK_SET);
9954887Schin walk.out = outfile;
9968462SApril.Chin@Sun.COM walk.indent = (flags&NV_EXPORT)?-1:0;
9978462SApril.Chin@Sun.COM walk.nofollow = 0;
9984887Schin walk.noscope = noscope;
9998462SApril.Chin@Sun.COM walk.array = 0;
10008462SApril.Chin@Sun.COM walk.flags = flags;
10014887Schin genvalue(argv,name,0,&walk);
10024887Schin stakset(savptr,savtop);
10038462SApril.Chin@Sun.COM shp->var_tree = save_tree;
10044887Schin if(!outfile)
10054887Schin return((char*)0);
10064887Schin sfputc(out,0);
10074887Schin return((char*)out->_data);
10084887Schin }
10094887Schin
nv_isvtree(Namval_t * np)10108462SApril.Chin@Sun.COM Namfun_t *nv_isvtree(Namval_t *np)
10118462SApril.Chin@Sun.COM {
10128462SApril.Chin@Sun.COM if(np)
10138462SApril.Chin@Sun.COM return(nv_hasdisc(np,&treedisc));
10148462SApril.Chin@Sun.COM return(0);
10158462SApril.Chin@Sun.COM }
10168462SApril.Chin@Sun.COM
10174887Schin /*
10184887Schin * get discipline for compound initializations
10194887Schin */
nv_getvtree(register Namval_t * np,Namfun_t * fp)10204887Schin char *nv_getvtree(register Namval_t *np, Namfun_t *fp)
10214887Schin {
1022*12068SRoger.Faulkner@Oracle.COM int flags=0, dsize=fp->dsize;
10238462SApril.Chin@Sun.COM for(; fp && fp->next; fp=fp->next)
10248462SApril.Chin@Sun.COM {
10258462SApril.Chin@Sun.COM if(fp->next->disc && (fp->next->disc->getnum || fp->next->disc->getval))
10268462SApril.Chin@Sun.COM return(nv_getv(np,fp));
10278462SApril.Chin@Sun.COM }
10288462SApril.Chin@Sun.COM if(nv_isattr(np,NV_BINARY) && !nv_isattr(np,NV_RAW))
10294887Schin return(nv_getv(np,fp));
10308462SApril.Chin@Sun.COM if(nv_isattr(np,NV_ARRAY) && !nv_type(np) && nv_arraychild(np,(Namval_t*)0,0)==np)
10314887Schin return(nv_getv(np,fp));
10328462SApril.Chin@Sun.COM if(flags = nv_isattr(np,NV_EXPORT))
10338462SApril.Chin@Sun.COM nv_offattr(np,NV_EXPORT);
1034*12068SRoger.Faulkner@Oracle.COM if(dsize && (flags&NV_EXPORT))
1035*12068SRoger.Faulkner@Oracle.COM return("()");
10368462SApril.Chin@Sun.COM return(walk_tree(np,(Namval_t*)0,flags));
10374887Schin }
10384887Schin
10394887Schin /*
10404887Schin * put discipline for compound initializations
10414887Schin */
put_tree(register Namval_t * np,const char * val,int flags,Namfun_t * fp)10424887Schin static void put_tree(register Namval_t *np, const char *val, int flags,Namfun_t *fp)
10434887Schin {
10444887Schin struct Namarray *ap;
10454887Schin int nleft = 0;
10468462SApril.Chin@Sun.COM if(!val && !fp->next && nv_isattr(np,NV_NOFREE))
10478462SApril.Chin@Sun.COM return;
10488462SApril.Chin@Sun.COM if(!nv_isattr(np,(NV_INTEGER|NV_BINARY)))
10498462SApril.Chin@Sun.COM {
10508462SApril.Chin@Sun.COM Shell_t *shp = sh_getinterp();
10518462SApril.Chin@Sun.COM Namval_t *last_table = shp->last_table;
10528462SApril.Chin@Sun.COM Dt_t *last_root = shp->last_root;
105310898Sroland.mainz@nrubsig.org Namval_t *mp = val?nv_open(val,shp->var_tree,NV_VARNAME|NV_NOADD|NV_NOASSIGN|NV_ARRAY|NV_NOFAIL):0;
10548462SApril.Chin@Sun.COM if(mp && nv_isvtree(mp))
10558462SApril.Chin@Sun.COM {
10568462SApril.Chin@Sun.COM shp->prev_table = shp->last_table;
10578462SApril.Chin@Sun.COM shp->prev_root = shp->last_root;
10588462SApril.Chin@Sun.COM shp->last_table = last_table;
10598462SApril.Chin@Sun.COM shp->last_root = last_root;
10608462SApril.Chin@Sun.COM if(!(flags&NV_APPEND))
10618462SApril.Chin@Sun.COM walk_tree(np,(Namval_t*)0,(flags&NV_NOSCOPE)|1);
10628462SApril.Chin@Sun.COM nv_clone(mp,np,NV_COMVAR);
10638462SApril.Chin@Sun.COM return;
10648462SApril.Chin@Sun.COM }
10658462SApril.Chin@Sun.COM walk_tree(np,(Namval_t*)0,(flags&NV_NOSCOPE)|1);
10668462SApril.Chin@Sun.COM }
10674887Schin nv_putv(np, val, flags,fp);
10688462SApril.Chin@Sun.COM if(val && nv_isattr(np,(NV_INTEGER|NV_BINARY)))
10694887Schin return;
10704887Schin if(ap= nv_arrayptr(np))
10714887Schin nleft = array_elem(ap);
10724887Schin if(nleft==0)
10734887Schin {
10744887Schin fp = nv_stack(np,fp);
10754887Schin if(fp = nv_stack(np,NIL(Namfun_t*)))
10764887Schin free((void*)fp);
10774887Schin }
10784887Schin }
10794887Schin
10804887Schin /*
10814887Schin * Insert discipline to cause $x to print current tree
10824887Schin */
nv_setvtree(register Namval_t * np)10834887Schin void nv_setvtree(register Namval_t *np)
10844887Schin {
10854887Schin register Namfun_t *nfp;
10868462SApril.Chin@Sun.COM if(sh.subshell)
10878462SApril.Chin@Sun.COM sh_assignok(np,1);
10884887Schin if(nv_hasdisc(np, &treedisc))
10894887Schin return;
10904887Schin nfp = newof(NIL(void*),Namfun_t,1,0);
10914887Schin nfp->disc = &treedisc;
1092*12068SRoger.Faulkner@Oracle.COM nfp->dsize = sizeof(Namfun_t);
10934887Schin nv_stack(np, nfp);
10944887Schin }
10954887Schin
1096