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 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 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 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 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 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 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 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 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 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 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 */ 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 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 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 */ 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 */ 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 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 */ 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 */ 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 */ 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