14887Schin /*********************************************************************** 24887Schin * * 34887Schin * This software is part of the ast package * 4*8462SApril.Chin@Sun.COM * Copyright (c) 1982-2008 AT&T Intellectual Property * 54887Schin * and is licensed under the * 64887Schin * Common Public License, Version 1.0 * 7*8462SApril.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" 33*8462SApril.Chin@Sun.COM #include "lexstates.h" 344887Schin 354887Schin struct nvdir 364887Schin { 374887Schin Dt_t *root; 384887Schin Namval_t *hp; 394887Schin Namval_t *table; 40*8462SApril.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*); 50*8462SApril.Chin@Sun.COM static char *walk_tree(Namval_t*, Namval_t*, int); 51*8462SApril.Chin@Sun.COM 52*8462SApril.Chin@Sun.COM static int read_tree(Namval_t* np, Sfio_t *iop, int n, Namfun_t *dp) 53*8462SApril.Chin@Sun.COM { 54*8462SApril.Chin@Sun.COM Sfio_t *sp; 55*8462SApril.Chin@Sun.COM char *cp; 56*8462SApril.Chin@Sun.COM int c; 57*8462SApril.Chin@Sun.COM if(n>=0) 58*8462SApril.Chin@Sun.COM return(-1); 59*8462SApril.Chin@Sun.COM while((c = sfgetc(iop)) && isblank(c)); 60*8462SApril.Chin@Sun.COM sfungetc(iop,c); 61*8462SApril.Chin@Sun.COM sfprintf(sh.strbuf,"%s=%c",nv_name(np),0); 62*8462SApril.Chin@Sun.COM cp = sfstruse(sh.strbuf); 63*8462SApril.Chin@Sun.COM sp = sfopen((Sfio_t*)0,cp,"s"); 64*8462SApril.Chin@Sun.COM sfstack(iop,sp); 65*8462SApril.Chin@Sun.COM c=sh_eval(iop,SH_READEVAL); 66*8462SApril.Chin@Sun.COM return(c); 67*8462SApril.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; 724887Schin while(fp=fp->next) 734887Schin { 744887Schin if(fp->disc && fp->disc->createf) 754887Schin { 764887Schin if(np=(*fp->disc->createf)(np,name,flag,fp)) 774887Schin dp->last = fp->last; 784887Schin return(np); 794887Schin } 804887Schin } 814887Schin return((flag&NV_NOADD)?0:np); 824887Schin } 834887Schin 84*8462SApril.Chin@Sun.COM static Namfun_t *clone_tree(Namval_t *np, Namval_t *mp, int flags, Namfun_t *fp){ 85*8462SApril.Chin@Sun.COM Namfun_t *dp; 86*8462SApril.Chin@Sun.COM if ((flags&NV_MOVE) && nv_type(np)) 87*8462SApril.Chin@Sun.COM return(fp); 88*8462SApril.Chin@Sun.COM dp = nv_clone_disc(fp,flags); 89*8462SApril.Chin@Sun.COM if((flags&NV_COMVAR) && !(flags&NV_RAW)) 90*8462SApril.Chin@Sun.COM { 91*8462SApril.Chin@Sun.COM walk_tree(np,mp,flags); 92*8462SApril.Chin@Sun.COM if((flags&NV_MOVE) && !(fp->nofree&1)) 93*8462SApril.Chin@Sun.COM free((void*)fp); 94*8462SApril.Chin@Sun.COM } 95*8462SApril.Chin@Sun.COM return(dp); 96*8462SApril.Chin@Sun.COM } 97*8462SApril.Chin@Sun.COM 984887Schin static const Namdisc_t treedisc = 994887Schin { 1004887Schin 0, 1014887Schin put_tree, 1024887Schin nv_getvtree, 1034887Schin 0, 1044887Schin 0, 105*8462SApril.Chin@Sun.COM create_tree, 106*8462SApril.Chin@Sun.COM clone_tree 107*8462SApril.Chin@Sun.COM ,0,0,0, 108*8462SApril.Chin@Sun.COM read_tree 1094887Schin }; 1104887Schin 1114887Schin static char *nextdot(const char *str) 1124887Schin { 1134887Schin register char *cp; 114*8462SApril.Chin@Sun.COM register int c; 1154887Schin if(*str=='.') 1164887Schin str++; 117*8462SApril.Chin@Sun.COM for(cp=(char*)str;c= *cp; cp++) 1184887Schin { 119*8462SApril.Chin@Sun.COM if(c=='[') 120*8462SApril.Chin@Sun.COM { 121*8462SApril.Chin@Sun.COM cp = nv_endsubscript((Namval_t*)0,(char*)cp,0); 122*8462SApril.Chin@Sun.COM return(*cp=='.'?cp:0); 123*8462SApril.Chin@Sun.COM } 124*8462SApril.Chin@Sun.COM if(c=='.') 125*8462SApril.Chin@Sun.COM return(cp); 1264887Schin } 127*8462SApril.Chin@Sun.COM return(0); 1284887Schin } 1294887Schin 1304887Schin static Namfun_t *nextdisc(Namval_t *np) 1314887Schin { 1324887Schin register Namfun_t *fp; 1334887Schin if(nv_isref(np)) 1344887Schin return(0); 1354887Schin for(fp=np->nvfun;fp;fp=fp->next) 1364887Schin { 1374887Schin if(fp && fp->disc && fp->disc->nextf) 1384887Schin return(fp); 1394887Schin } 1404887Schin return(0); 1414887Schin } 1424887Schin 143*8462SApril.Chin@Sun.COM void *nv_diropen(Namval_t *np,const char *name) 1444887Schin { 1454887Schin char *next,*last; 1464887Schin int c,len=strlen(name); 1474887Schin struct nvdir *save, *dp = new_of(struct nvdir,len); 148*8462SApril.Chin@Sun.COM Namval_t *nq=0,fake; 149*8462SApril.Chin@Sun.COM Namfun_t *nfp=0; 1504887Schin if(!dp) 1514887Schin return(0); 1524887Schin memset((void*)dp, 0, sizeof(*dp)); 1534887Schin if(name[len-1]=='*' || name[len-1]=='@') 1544887Schin len -= 1; 155*8462SApril.Chin@Sun.COM name = memcpy(dp->data,name,len); 156*8462SApril.Chin@Sun.COM dp->data[len] = 0; 1574887Schin dp->len = len; 158*8462SApril.Chin@Sun.COM dp->root = sh.last_root?sh.last_root:sh.var_tree; 159*8462SApril.Chin@Sun.COM #if 1 160*8462SApril.Chin@Sun.COM while(1) 161*8462SApril.Chin@Sun.COM { 162*8462SApril.Chin@Sun.COM dp->table = sh.last_table; 163*8462SApril.Chin@Sun.COM sh.last_table = 0; 164*8462SApril.Chin@Sun.COM if(*(last=(char*)name)==0) 165*8462SApril.Chin@Sun.COM break; 166*8462SApril.Chin@Sun.COM if(!(next=nextdot(last))) 167*8462SApril.Chin@Sun.COM break; 168*8462SApril.Chin@Sun.COM *next = 0; 169*8462SApril.Chin@Sun.COM np = nv_open(name, dp->root, NV_NOFAIL); 170*8462SApril.Chin@Sun.COM *next = '.'; 171*8462SApril.Chin@Sun.COM if(!np || !nv_istable(np)) 172*8462SApril.Chin@Sun.COM break; 173*8462SApril.Chin@Sun.COM dp->root = nv_dict(np); 174*8462SApril.Chin@Sun.COM name = next+1; 175*8462SApril.Chin@Sun.COM } 176*8462SApril.Chin@Sun.COM #else 1774887Schin dp->table = sh.last_table; 178*8462SApril.Chin@Sun.COM sh.last_table = 0; 179*8462SApril.Chin@Sun.COM last = dp->data; 180*8462SApril.Chin@Sun.COM #endif 1814887Schin if(*name) 1824887Schin { 1834887Schin fake.nvname = (char*)name; 184*8462SApril.Chin@Sun.COM if(dp->hp = (Namval_t*)dtprev(dp->root,&fake)) 185*8462SApril.Chin@Sun.COM { 186*8462SApril.Chin@Sun.COM char *cp = nv_name(dp->hp); 187*8462SApril.Chin@Sun.COM c = strlen(cp); 188*8462SApril.Chin@Sun.COM if(memcmp(name,cp,c) || name[c]!='[') 189*8462SApril.Chin@Sun.COM dp->hp = (Namval_t*)dtnext(dp->root,dp->hp); 190*8462SApril.Chin@Sun.COM else 191*8462SApril.Chin@Sun.COM { 192*8462SApril.Chin@Sun.COM np = dp->hp; 193*8462SApril.Chin@Sun.COM last = 0; 194*8462SApril.Chin@Sun.COM } 195*8462SApril.Chin@Sun.COM } 1964887Schin } 1974887Schin else 1984887Schin dp->hp = (Namval_t*)dtfirst(dp->root); 199*8462SApril.Chin@Sun.COM while(1) 2004887Schin { 201*8462SApril.Chin@Sun.COM if(!last) 202*8462SApril.Chin@Sun.COM next = 0; 203*8462SApril.Chin@Sun.COM else if(next= nextdot(last)) 204*8462SApril.Chin@Sun.COM { 205*8462SApril.Chin@Sun.COM c = *next; 206*8462SApril.Chin@Sun.COM *next = 0; 207*8462SApril.Chin@Sun.COM } 208*8462SApril.Chin@Sun.COM if(!np) 209*8462SApril.Chin@Sun.COM { 210*8462SApril.Chin@Sun.COM if(nfp && nfp->disc && nfp->disc->createf) 211*8462SApril.Chin@Sun.COM { 212*8462SApril.Chin@Sun.COM np = (*nfp->disc->createf)(nq,last,0,nfp); 213*8462SApril.Chin@Sun.COM if(*nfp->last == '[') 214*8462SApril.Chin@Sun.COM { 215*8462SApril.Chin@Sun.COM nv_endsubscript(np,nfp->last,NV_NOADD); 216*8462SApril.Chin@Sun.COM if(nq = nv_opensub(np)) 217*8462SApril.Chin@Sun.COM np = nq; 218*8462SApril.Chin@Sun.COM } 219*8462SApril.Chin@Sun.COM } 220*8462SApril.Chin@Sun.COM else 221*8462SApril.Chin@Sun.COM np = nv_search(last,dp->root,0); 222*8462SApril.Chin@Sun.COM } 223*8462SApril.Chin@Sun.COM if(next) 224*8462SApril.Chin@Sun.COM *next = c; 225*8462SApril.Chin@Sun.COM if(np==dp->hp && !next) 226*8462SApril.Chin@Sun.COM dp->hp = (Namval_t*)dtnext(dp->root,dp->hp); 2274887Schin if(np && ((nfp=nextdisc(np)) || nv_istable(np))) 2284887Schin { 2294887Schin if(!(save = new_of(struct nvdir,0))) 2304887Schin return(0); 2314887Schin *save = *dp; 2324887Schin dp->prev = save; 2334887Schin if(nv_istable(np)) 2344887Schin dp->root = nv_dict(np); 2354887Schin else 236*8462SApril.Chin@Sun.COM dp->root = (Dt_t*)np; 2374887Schin if(nfp) 2384887Schin { 2394887Schin dp->nextnode = nfp->disc->nextf; 2404887Schin dp->table = np; 241*8462SApril.Chin@Sun.COM dp->otable = sh.last_table; 2424887Schin dp->fun = nfp; 2434887Schin dp->hp = (*dp->nextnode)(np,(Dt_t*)0,nfp); 2444887Schin } 2454887Schin else 2464887Schin dp->nextnode = 0; 2474887Schin } 2484887Schin else 2494887Schin break; 250*8462SApril.Chin@Sun.COM if(!next || next[1]==0) 251*8462SApril.Chin@Sun.COM break; 2524887Schin last = next+1; 253*8462SApril.Chin@Sun.COM nq = np; 254*8462SApril.Chin@Sun.COM np = 0; 2554887Schin } 2564887Schin return((void*)dp); 2574887Schin } 2584887Schin 2594887Schin 2604887Schin static Namval_t *nextnode(struct nvdir *dp) 2614887Schin { 2624887Schin if(dp->nextnode) 2634887Schin return((*dp->nextnode)(dp->hp,dp->root,dp->fun)); 2644887Schin if(dp->len && memcmp(dp->data, dp->hp->nvname, dp->len)) 2654887Schin return(0); 2664887Schin return((Namval_t*)dtnext(dp->root,dp->hp)); 2674887Schin } 2684887Schin 2694887Schin char *nv_dirnext(void *dir) 2704887Schin { 2714887Schin register struct nvdir *save, *dp = (struct nvdir*)dir; 2724887Schin register Namval_t *np, *last_table; 2734887Schin register char *cp; 2744887Schin Namfun_t *nfp; 275*8462SApril.Chin@Sun.COM Namval_t *nq; 2764887Schin while(1) 2774887Schin { 2784887Schin while(np=dp->hp) 2794887Schin { 280*8462SApril.Chin@Sun.COM #if 0 281*8462SApril.Chin@Sun.COM char *sptr; 282*8462SApril.Chin@Sun.COM #endif 283*8462SApril.Chin@Sun.COM if(nv_isarray(np)) 284*8462SApril.Chin@Sun.COM nv_putsub(np,(char*)0, ARRAY_UNDEF); 2854887Schin dp->hp = nextnode(dp); 286*8462SApril.Chin@Sun.COM if(nv_isnull(np) && !nv_isarray(np)) 2874887Schin continue; 2884887Schin last_table = sh.last_table; 289*8462SApril.Chin@Sun.COM #if 0 290*8462SApril.Chin@Sun.COM if(dp->table && dp->otable && !nv_isattr(dp->table,NV_MINIMAL)) 291*8462SApril.Chin@Sun.COM { 292*8462SApril.Chin@Sun.COM sptr = dp->table->nvenv; 293*8462SApril.Chin@Sun.COM dp->table->nvenv = (char*)dp->otable; 294*8462SApril.Chin@Sun.COM } 295*8462SApril.Chin@Sun.COM #endif 2964887Schin sh.last_table = dp->table; 2974887Schin cp = nv_name(np); 298*8462SApril.Chin@Sun.COM #if 0 299*8462SApril.Chin@Sun.COM if(dp->table && dp->otable && !nv_isattr(dp->table,NV_MINIMAL)) 300*8462SApril.Chin@Sun.COM dp->table->nvenv = sptr; 301*8462SApril.Chin@Sun.COM #endif 302*8462SApril.Chin@Sun.COM if(dp->nextnode && !dp->hp && (nq = (Namval_t*)dp->table)) 303*8462SApril.Chin@Sun.COM { 304*8462SApril.Chin@Sun.COM Namarr_t *ap = nv_arrayptr(nq); 305*8462SApril.Chin@Sun.COM if(ap && (ap->nelem&ARRAY_SCAN) && nv_nextsub(nq)) 306*8462SApril.Chin@Sun.COM dp->hp = (*dp->nextnode)(np,(Dt_t*)0,dp->fun); 307*8462SApril.Chin@Sun.COM } 3084887Schin sh.last_table = last_table; 309*8462SApril.Chin@Sun.COM if(!dp->len || memcmp(cp,dp->data,dp->len)==0) 3104887Schin { 311*8462SApril.Chin@Sun.COM if((nfp=nextdisc(np)) && (nfp->disc->getval||nfp->disc->getnum) && nv_isvtree(np) && strcmp(cp,dp->data)) 312*8462SApril.Chin@Sun.COM nfp = 0; 313*8462SApril.Chin@Sun.COM if(nfp || nv_istable(np)) 3144887Schin { 3154887Schin Dt_t *root; 3164887Schin if(nv_istable(np)) 3174887Schin root = nv_dict(np); 3184887Schin else 319*8462SApril.Chin@Sun.COM root = (Dt_t*)np; 3204887Schin /* check for recursive walk */ 3214887Schin for(save=dp; save; save=save->prev) 3224887Schin { 3234887Schin if(save->root==root) 3244887Schin break; 3254887Schin } 3264887Schin if(save) 327*8462SApril.Chin@Sun.COM return(cp); 3284887Schin if(!(save = new_of(struct nvdir,0))) 3294887Schin return(0); 3304887Schin *save = *dp; 3314887Schin dp->prev = save; 3324887Schin dp->root = root; 3334887Schin dp->len = 0; 3344887Schin if(nfp && np->nvfun) 3354887Schin { 336*8462SApril.Chin@Sun.COM #if 0 337*8462SApril.Chin@Sun.COM Namarr_t *ap = nv_arrayptr(np); 338*8462SApril.Chin@Sun.COM if(ap && (ap->nelem&ARRAY_UNDEF)) 339*8462SApril.Chin@Sun.COM nv_putsub(np,(char*)0,ARRAY_SCAN); 340*8462SApril.Chin@Sun.COM #endif 3414887Schin dp->nextnode = nfp->disc->nextf; 342*8462SApril.Chin@Sun.COM dp->otable = dp->table; 3434887Schin dp->table = np; 3444887Schin dp->fun = nfp; 3454887Schin dp->hp = (*dp->nextnode)(np,(Dt_t*)0,nfp); 3464887Schin } 3474887Schin else 3484887Schin dp->nextnode = 0; 3494887Schin } 3504887Schin return(cp); 3514887Schin } 3524887Schin } 3534887Schin if(!(save=dp->prev)) 3544887Schin break; 3554887Schin *dp = *save; 3564887Schin free((void*)save); 3574887Schin } 3584887Schin return(0); 3594887Schin } 3604887Schin 3614887Schin void nv_dirclose(void *dir) 3624887Schin { 3634887Schin struct nvdir *dp = (struct nvdir*)dir; 3644887Schin if(dp->prev) 3654887Schin nv_dirclose((void*)dp->prev); 3664887Schin free(dir); 3674887Schin } 3684887Schin 3694887Schin static void outtype(Namval_t *np, Namfun_t *fp, Sfio_t* out, const char *prefix) 3704887Schin { 3714887Schin char *type=0; 3724887Schin Namval_t *tp = fp->type; 3734887Schin if(!tp && fp->disc && fp->disc->typef) 3744887Schin tp = (*fp->disc->typef)(np,fp); 3754887Schin for(fp=fp->next;fp;fp=fp->next) 3764887Schin { 3774887Schin if(fp->type || (fp->disc && fp->disc->typef &&(*fp->disc->typef)(np,fp))) 3784887Schin { 3794887Schin outtype(np,fp,out,prefix); 3804887Schin break; 3814887Schin } 3824887Schin } 3834887Schin if(prefix && *prefix=='t') 3844887Schin type = "-T"; 3854887Schin else if(!prefix) 3864887Schin type = "type"; 3874887Schin if(type) 388*8462SApril.Chin@Sun.COM { 389*8462SApril.Chin@Sun.COM char *cp=tp->nvname; 390*8462SApril.Chin@Sun.COM if(cp=strrchr(cp,'.')) 391*8462SApril.Chin@Sun.COM cp++; 392*8462SApril.Chin@Sun.COM else 393*8462SApril.Chin@Sun.COM cp = tp->nvname; 394*8462SApril.Chin@Sun.COM sfprintf(out,"%s %s ",type,cp); 395*8462SApril.Chin@Sun.COM } 3964887Schin } 3974887Schin 3984887Schin /* 3994887Schin * print the attributes of name value pair give by <np> 4004887Schin */ 4014887Schin void nv_attribute(register Namval_t *np,Sfio_t *out,char *prefix,int noname) 4024887Schin { 4034887Schin register const Shtable_t *tp; 4044887Schin register char *cp; 405*8462SApril.Chin@Sun.COM register unsigned val,mask,attr; 406*8462SApril.Chin@Sun.COM char *ip=0; 4074887Schin Namfun_t *fp=0; 408*8462SApril.Chin@Sun.COM Namval_t *typep=0; 4094887Schin for(fp=np->nvfun;fp;fp=fp->next) 4104887Schin { 411*8462SApril.Chin@Sun.COM if((typep=fp->type) || (fp->disc && fp->disc->typef && (typep=(*fp->disc->typef)(np,fp)))) 4124887Schin break; 4134887Schin } 414*8462SApril.Chin@Sun.COM if(!fp && !nv_isattr(np,~(NV_MINIMAL|NV_NOFREE))) 4154887Schin { 416*8462SApril.Chin@Sun.COM if(prefix && *prefix) 417*8462SApril.Chin@Sun.COM { 418*8462SApril.Chin@Sun.COM if(nv_isvtree(np)) 419*8462SApril.Chin@Sun.COM sfprintf(out,"%s -C ",prefix); 420*8462SApril.Chin@Sun.COM else if(!np->nvalue.cp && nv_isattr(np,~NV_NOFREE)==NV_MINIMAL && strcmp(np->nvname,"_")) 421*8462SApril.Chin@Sun.COM sfputr(out,prefix,' '); 422*8462SApril.Chin@Sun.COM } 423*8462SApril.Chin@Sun.COM return; 4244887Schin } 4254887Schin 4264887Schin if ((attr=nv_isattr(np,~NV_NOFREE)) || fp) 4274887Schin { 428*8462SApril.Chin@Sun.COM if((attr&NV_NOPRINT|NV_INTEGER)==NV_NOPRINT) 4294887Schin attr &= ~NV_NOPRINT; 4304887Schin if(!attr && !fp) 4314887Schin return; 432*8462SApril.Chin@Sun.COM if(fp) 433*8462SApril.Chin@Sun.COM { 434*8462SApril.Chin@Sun.COM prefix = Empty; 435*8462SApril.Chin@Sun.COM attr &= NV_RDONLY|NV_ARRAY; 436*8462SApril.Chin@Sun.COM if(nv_isattr(np,NV_REF|NV_TAGGED)==(NV_REF|NV_TAGGED)) 437*8462SApril.Chin@Sun.COM attr |= (NV_REF|NV_TAGGED); 438*8462SApril.Chin@Sun.COM if(typep) 439*8462SApril.Chin@Sun.COM { 440*8462SApril.Chin@Sun.COM char *cp = typep->nvname; 441*8462SApril.Chin@Sun.COM if(cp = strrchr(cp,'.')) 442*8462SApril.Chin@Sun.COM cp++; 443*8462SApril.Chin@Sun.COM else 444*8462SApril.Chin@Sun.COM cp = typep->nvname; 445*8462SApril.Chin@Sun.COM sfputr(out,cp,' '); 446*8462SApril.Chin@Sun.COM fp = 0; 447*8462SApril.Chin@Sun.COM } 448*8462SApril.Chin@Sun.COM } 449*8462SApril.Chin@Sun.COM else if(prefix && *prefix) 4504887Schin sfputr(out,prefix,' '); 4514887Schin for(tp = shtab_attributes; *tp->sh_name;tp++) 4524887Schin { 4534887Schin val = tp->sh_number; 4544887Schin mask = val; 4554887Schin if(fp && (val&NV_INTEGER)) 4564887Schin break; 4574887Schin /* 4584887Schin * the following test is needed to prevent variables 4594887Schin * with E attribute from being given the F 4604887Schin * attribute as well 4614887Schin */ 462*8462SApril.Chin@Sun.COM if(val==NV_DOUBLE && (attr&(NV_EXPNOTE|NV_HEXFLOAT))) 4634887Schin continue; 4644887Schin if(val&NV_INTEGER) 4654887Schin mask |= NV_DOUBLE; 4664887Schin else if(val&NV_HOST) 4674887Schin mask = NV_HOST; 4684887Schin if((attr&mask)==val) 4694887Schin { 4704887Schin if(val==NV_ARRAY) 4714887Schin { 4724887Schin Namarr_t *ap = nv_arrayptr(np); 473*8462SApril.Chin@Sun.COM char **xp=0; 474*8462SApril.Chin@Sun.COM if(ap && array_assoc(ap)) 4754887Schin { 4764887Schin if(tp->sh_name[1]!='A') 4774887Schin continue; 4784887Schin } 4794887Schin else if(tp->sh_name[1]=='A') 4804887Schin continue; 481*8462SApril.Chin@Sun.COM if(ap && (ap->nelem&ARRAY_TREE)) 482*8462SApril.Chin@Sun.COM { 483*8462SApril.Chin@Sun.COM if(prefix && *prefix) 484*8462SApril.Chin@Sun.COM sfwrite(out,"-C ",3); 485*8462SApril.Chin@Sun.COM } 486*8462SApril.Chin@Sun.COM if(ap && !array_assoc(ap) && (xp=(char**)(ap+1)) && *xp) 487*8462SApril.Chin@Sun.COM ip = nv_namptr(*xp,0)->nvname; 4884887Schin } 4894887Schin if(prefix) 4904887Schin { 4914887Schin if(*tp->sh_name=='-') 4924887Schin sfprintf(out,"%.2s ",tp->sh_name); 493*8462SApril.Chin@Sun.COM if(ip) 494*8462SApril.Chin@Sun.COM { 495*8462SApril.Chin@Sun.COM sfprintf(out,"[%s] ",ip); 496*8462SApril.Chin@Sun.COM ip = 0; 497*8462SApril.Chin@Sun.COM } 4984887Schin } 4994887Schin else 5004887Schin sfputr(out,tp->sh_name+2,' '); 5014887Schin if ((val&(NV_LJUST|NV_RJUST|NV_ZFILL)) && !(val&NV_INTEGER) && val!=NV_HOST) 5024887Schin sfprintf(out,"%d ",nv_size(np)); 503*8462SApril.Chin@Sun.COM if(val==(NV_REF|NV_TAGGED)) 504*8462SApril.Chin@Sun.COM attr &= ~(NV_REF|NV_TAGGED); 5054887Schin } 5064887Schin if(val==NV_INTEGER && nv_isattr(np,NV_INTEGER)) 5074887Schin { 5084887Schin if(nv_size(np) != 10) 5094887Schin { 510*8462SApril.Chin@Sun.COM if(nv_isattr(np, NV_DOUBLE)== NV_DOUBLE) 5114887Schin cp = "precision"; 5124887Schin else 5134887Schin cp = "base"; 5144887Schin if(!prefix) 5154887Schin sfputr(out,cp,' '); 5164887Schin sfprintf(out,"%d ",nv_size(np)); 5174887Schin } 5184887Schin break; 5194887Schin } 5204887Schin } 5214887Schin if(fp) 5224887Schin outtype(np,fp,out,prefix); 5234887Schin if(noname) 5244887Schin return; 5254887Schin sfputr(out,nv_name(np),'\n'); 5264887Schin } 5274887Schin } 5284887Schin 5294887Schin struct Walk 5304887Schin { 5314887Schin Sfio_t *out; 5324887Schin Dt_t *root; 5334887Schin int noscope; 5344887Schin int indent; 535*8462SApril.Chin@Sun.COM int nofollow; 536*8462SApril.Chin@Sun.COM int array; 537*8462SApril.Chin@Sun.COM int flags; 5384887Schin }; 5394887Schin 540*8462SApril.Chin@Sun.COM void nv_outnode(Namval_t *np, Sfio_t* out, int indent, int special) 541*8462SApril.Chin@Sun.COM { 542*8462SApril.Chin@Sun.COM char *fmtq,*ep,*xp; 543*8462SApril.Chin@Sun.COM Namval_t *mp; 544*8462SApril.Chin@Sun.COM Namarr_t *ap = nv_arrayptr(np); 545*8462SApril.Chin@Sun.COM int tabs=0,c,more,associative = 0; 546*8462SApril.Chin@Sun.COM if(ap) 547*8462SApril.Chin@Sun.COM { 548*8462SApril.Chin@Sun.COM if(!(ap->nelem&ARRAY_SCAN)) 549*8462SApril.Chin@Sun.COM nv_putsub(np,NIL(char*),ARRAY_SCAN); 550*8462SApril.Chin@Sun.COM sfputc(out,'('); 551*8462SApril.Chin@Sun.COM if(indent>=0) 552*8462SApril.Chin@Sun.COM { 553*8462SApril.Chin@Sun.COM sfputc(out,'\n'); 554*8462SApril.Chin@Sun.COM tabs=1; 555*8462SApril.Chin@Sun.COM } 556*8462SApril.Chin@Sun.COM if(!(associative =(array_assoc(ap)!=0))) 557*8462SApril.Chin@Sun.COM { 558*8462SApril.Chin@Sun.COM if(array_elem(ap) < nv_aimax(np)+1) 559*8462SApril.Chin@Sun.COM associative=1; 560*8462SApril.Chin@Sun.COM } 561*8462SApril.Chin@Sun.COM } 562*8462SApril.Chin@Sun.COM mp = nv_opensub(np); 563*8462SApril.Chin@Sun.COM while(1) 564*8462SApril.Chin@Sun.COM { 565*8462SApril.Chin@Sun.COM if(mp && special && nv_isvtree(mp)) 566*8462SApril.Chin@Sun.COM { 567*8462SApril.Chin@Sun.COM if(!nv_nextsub(np)) 568*8462SApril.Chin@Sun.COM break; 569*8462SApril.Chin@Sun.COM mp = nv_opensub(np); 570*8462SApril.Chin@Sun.COM continue; 571*8462SApril.Chin@Sun.COM } 572*8462SApril.Chin@Sun.COM if(tabs) 573*8462SApril.Chin@Sun.COM sfnputc(out,'\t',++indent); 574*8462SApril.Chin@Sun.COM tabs=0; 575*8462SApril.Chin@Sun.COM if(associative||special) 576*8462SApril.Chin@Sun.COM { 577*8462SApril.Chin@Sun.COM if(!(fmtq = nv_getsub(np))) 578*8462SApril.Chin@Sun.COM break; 579*8462SApril.Chin@Sun.COM sfprintf(out,"[%s]",sh_fmtq(fmtq)); 580*8462SApril.Chin@Sun.COM sfputc(out,'='); 581*8462SApril.Chin@Sun.COM } 582*8462SApril.Chin@Sun.COM if(mp && nv_isarray(mp)) 583*8462SApril.Chin@Sun.COM { 584*8462SApril.Chin@Sun.COM nv_outnode(mp, out, indent+(indent>=0),0); 585*8462SApril.Chin@Sun.COM if(indent>0) 586*8462SApril.Chin@Sun.COM sfnputc(out,'\t',indent); 587*8462SApril.Chin@Sun.COM sfputc(out,')'); 588*8462SApril.Chin@Sun.COM sfputc(out,indent>=0?'\n':' '); 589*8462SApril.Chin@Sun.COM more = nv_nextsub(np); 590*8462SApril.Chin@Sun.COM goto skip; 591*8462SApril.Chin@Sun.COM } 592*8462SApril.Chin@Sun.COM if(mp && nv_isvtree(mp)) 593*8462SApril.Chin@Sun.COM nv_onattr(mp,NV_EXPORT); 594*8462SApril.Chin@Sun.COM ep = nv_getval(mp?mp:np); 595*8462SApril.Chin@Sun.COM xp = 0; 596*8462SApril.Chin@Sun.COM if(!ap && nv_isattr(np,NV_INTEGER|NV_LJUST)==NV_LJUST) 597*8462SApril.Chin@Sun.COM { 598*8462SApril.Chin@Sun.COM xp = ep+nv_size(np); 599*8462SApril.Chin@Sun.COM while(--xp>ep && *xp==' '); 600*8462SApril.Chin@Sun.COM if(xp>ep || *xp!=' ') 601*8462SApril.Chin@Sun.COM xp++; 602*8462SApril.Chin@Sun.COM if(xp < (ep+nv_size(np))) 603*8462SApril.Chin@Sun.COM *xp = 0; 604*8462SApril.Chin@Sun.COM else 605*8462SApril.Chin@Sun.COM xp = 0; 606*8462SApril.Chin@Sun.COM } 607*8462SApril.Chin@Sun.COM if(mp && nv_isvtree(mp)) 608*8462SApril.Chin@Sun.COM fmtq = ep; 609*8462SApril.Chin@Sun.COM else if(!(fmtq = sh_fmtq(ep))) 610*8462SApril.Chin@Sun.COM fmtq = ""; 611*8462SApril.Chin@Sun.COM else if(!associative && (ep=strchr(fmtq,'='))) 612*8462SApril.Chin@Sun.COM { 613*8462SApril.Chin@Sun.COM char *qp = strchr(fmtq,'\''); 614*8462SApril.Chin@Sun.COM if(!qp || qp>ep) 615*8462SApril.Chin@Sun.COM { 616*8462SApril.Chin@Sun.COM sfwrite(out,fmtq,ep-fmtq); 617*8462SApril.Chin@Sun.COM sfputc(out,'\\'); 618*8462SApril.Chin@Sun.COM fmtq = ep; 619*8462SApril.Chin@Sun.COM } 620*8462SApril.Chin@Sun.COM } 621*8462SApril.Chin@Sun.COM more = nv_nextsub(np); 622*8462SApril.Chin@Sun.COM c = '\n'; 623*8462SApril.Chin@Sun.COM if(indent<0) 624*8462SApril.Chin@Sun.COM { 625*8462SApril.Chin@Sun.COM c = ';'; 626*8462SApril.Chin@Sun.COM if(ap) 627*8462SApril.Chin@Sun.COM c = more?' ':-1; 628*8462SApril.Chin@Sun.COM } 629*8462SApril.Chin@Sun.COM sfputr(out,fmtq,c); 630*8462SApril.Chin@Sun.COM if(xp) 631*8462SApril.Chin@Sun.COM *xp = ' '; 632*8462SApril.Chin@Sun.COM skip: 633*8462SApril.Chin@Sun.COM if(!more) 634*8462SApril.Chin@Sun.COM return; 635*8462SApril.Chin@Sun.COM mp = nv_opensub(np); 636*8462SApril.Chin@Sun.COM if(indent>0 && !(mp && special && nv_isvtree(mp))) 637*8462SApril.Chin@Sun.COM sfnputc(out,'\t',indent); 638*8462SApril.Chin@Sun.COM } 639*8462SApril.Chin@Sun.COM } 640*8462SApril.Chin@Sun.COM 6414887Schin static void outval(char *name, const char *vname, struct Walk *wp) 6424887Schin { 6434887Schin register Namval_t *np, *nq; 6444887Schin register Namfun_t *fp; 645*8462SApril.Chin@Sun.COM int isarray=0, special=0,mode=0; 646*8462SApril.Chin@Sun.COM if(*name!='.' || vname[strlen(vname)-1]==']') 647*8462SApril.Chin@Sun.COM mode = NV_ARRAY; 648*8462SApril.Chin@Sun.COM if(!(np=nv_open(vname,wp->root,mode|NV_VARNAME|NV_NOADD|NV_NOASSIGN|NV_NOFAIL|wp->noscope))) 6494887Schin return; 650*8462SApril.Chin@Sun.COM fp = nv_hasdisc(np,&treedisc); 651*8462SApril.Chin@Sun.COM if(*name=='.') 6524887Schin { 653*8462SApril.Chin@Sun.COM if(nv_isattr(np,NV_BINARY)) 654*8462SApril.Chin@Sun.COM return; 655*8462SApril.Chin@Sun.COM if(fp && np->nvalue.cp && np->nvalue.cp!=Empty) 656*8462SApril.Chin@Sun.COM { 657*8462SApril.Chin@Sun.COM nv_local = 1; 658*8462SApril.Chin@Sun.COM fp = 0; 659*8462SApril.Chin@Sun.COM } 660*8462SApril.Chin@Sun.COM if(fp) 661*8462SApril.Chin@Sun.COM return; 662*8462SApril.Chin@Sun.COM if(nv_isarray(np)) 663*8462SApril.Chin@Sun.COM return; 664*8462SApril.Chin@Sun.COM } 665*8462SApril.Chin@Sun.COM if(!special && fp && !nv_isarray(np)) 666*8462SApril.Chin@Sun.COM { 667*8462SApril.Chin@Sun.COM Namfun_t *xp; 6684887Schin if(!wp->out) 6694887Schin { 6704887Schin fp = nv_stack(np,fp); 6714887Schin if(fp = nv_stack(np,NIL(Namfun_t*))) 6724887Schin free((void*)fp); 6734887Schin np->nvfun = 0; 674*8462SApril.Chin@Sun.COM return; 6754887Schin } 676*8462SApril.Chin@Sun.COM for(xp=fp->next; xp; xp = xp->next) 677*8462SApril.Chin@Sun.COM { 678*8462SApril.Chin@Sun.COM if(xp->disc && (xp->disc->getval || xp->disc->getnum)) 679*8462SApril.Chin@Sun.COM break; 680*8462SApril.Chin@Sun.COM } 681*8462SApril.Chin@Sun.COM if(!xp) 682*8462SApril.Chin@Sun.COM return; 6834887Schin } 684*8462SApril.Chin@Sun.COM if((nv_isnull(np) || np->nvalue.cp==Empty) && !nv_isarray(np)) 6854887Schin return; 686*8462SApril.Chin@Sun.COM if(special || (nv_isarray(np) && nv_arrayptr(np))) 6874887Schin { 6884887Schin isarray=1; 6894887Schin if(array_elem(nv_arrayptr(np))==0) 6904887Schin isarray=2; 6914887Schin else 6924887Schin nq = nv_putsub(np,NIL(char*),ARRAY_SCAN|(wp->out?ARRAY_NOCHILD:0)); 6934887Schin } 6944887Schin if(!wp->out) 6954887Schin { 6964887Schin _nv_unset(np,NV_RDONLY); 6974887Schin nv_close(np); 698*8462SApril.Chin@Sun.COM #if 0 699*8462SApril.Chin@Sun.COM if(sh.subshell==0 && !(wp->flags&NV_RDONLY) && !nv_isattr(np,NV_MINIMAL|NV_NOFREE)) 700*8462SApril.Chin@Sun.COM nv_delete(np,wp->root,0); 701*8462SApril.Chin@Sun.COM #endif 7024887Schin return; 7034887Schin } 7044887Schin if(isarray==1 && !nq) 705*8462SApril.Chin@Sun.COM { 706*8462SApril.Chin@Sun.COM sfputc(wp->out,'('); 707*8462SApril.Chin@Sun.COM if(wp->indent>=0) 708*8462SApril.Chin@Sun.COM sfputc(wp->out,'\n'); 7094887Schin return; 7104887Schin } 711*8462SApril.Chin@Sun.COM if(isarray==0 && nv_isarray(np) && nv_isnull(np)) /* empty array */ 712*8462SApril.Chin@Sun.COM isarray = 2; 713*8462SApril.Chin@Sun.COM special |= wp->nofollow; 714*8462SApril.Chin@Sun.COM if(!wp->array && wp->indent>0) 7154887Schin sfnputc(wp->out,'\t',wp->indent); 716*8462SApril.Chin@Sun.COM if(!special) 7174887Schin { 718*8462SApril.Chin@Sun.COM if(*name!='.') 719*8462SApril.Chin@Sun.COM nv_attribute(np,wp->out,"typeset",'='); 720*8462SApril.Chin@Sun.COM nv_outname(wp->out,name,-1); 721*8462SApril.Chin@Sun.COM if(np->nvalue.cp || nv_isattr(np,~(NV_MINIMAL|NV_NOFREE)) || nv_isvtree(np)) 722*8462SApril.Chin@Sun.COM sfputc(wp->out,(isarray==2?'\n':'=')); 723*8462SApril.Chin@Sun.COM if(isarray==2) 724*8462SApril.Chin@Sun.COM return; 7254887Schin } 726*8462SApril.Chin@Sun.COM fp = np->nvfun; 727*8462SApril.Chin@Sun.COM if(*name=='.' && !isarray) 728*8462SApril.Chin@Sun.COM np->nvfun = 0; 729*8462SApril.Chin@Sun.COM nv_outnode(np, wp->out, wp->indent, special); 730*8462SApril.Chin@Sun.COM if(*name=='.' && !isarray) 731*8462SApril.Chin@Sun.COM np->nvfun = fp; 7324887Schin if(isarray && !special) 7334887Schin { 734*8462SApril.Chin@Sun.COM if(wp->indent>0) 735*8462SApril.Chin@Sun.COM { 736*8462SApril.Chin@Sun.COM sfnputc(wp->out,'\t',wp->indent); 737*8462SApril.Chin@Sun.COM sfwrite(wp->out,")\n",2); 738*8462SApril.Chin@Sun.COM } 739*8462SApril.Chin@Sun.COM else 740*8462SApril.Chin@Sun.COM sfwrite(wp->out,");",2); 7414887Schin } 7424887Schin } 7434887Schin 7444887Schin /* 7454887Schin * format initialization list given a list of assignments <argp> 7464887Schin */ 7474887Schin static char **genvalue(char **argv, const char *prefix, int n, struct Walk *wp) 7484887Schin { 7494887Schin register char *cp,*nextcp,*arg; 7504887Schin register Sfio_t *outfile = wp->out; 751*8462SApril.Chin@Sun.COM register int m,r,l; 7524887Schin if(n==0) 7534887Schin m = strlen(prefix); 7544887Schin else if(cp=nextdot(prefix)) 7554887Schin m = cp-prefix; 7564887Schin else 7574887Schin m = strlen(prefix)-1; 7584887Schin m++; 759*8462SApril.Chin@Sun.COM if(outfile && !wp->array) 7604887Schin { 761*8462SApril.Chin@Sun.COM sfputc(outfile,'('); 762*8462SApril.Chin@Sun.COM if(wp->indent>=0) 763*8462SApril.Chin@Sun.COM { 764*8462SApril.Chin@Sun.COM wp->indent++; 765*8462SApril.Chin@Sun.COM sfputc(outfile,'\n'); 766*8462SApril.Chin@Sun.COM } 7674887Schin } 7684887Schin for(; arg= *argv; argv++) 7694887Schin { 7704887Schin cp = arg + n; 7714887Schin if(n==0 && cp[m-1]!='.') 7724887Schin continue; 7734887Schin if(n && cp[m-1]==0) 7744887Schin break; 7754887Schin if(n==0 || strncmp(arg,prefix-n,m+n)==0) 7764887Schin { 7774887Schin cp +=m; 7784887Schin r = 0; 7794887Schin if(*cp=='.') 7804887Schin cp++,r++; 7814887Schin if(nextcp=nextdot(cp)) 7824887Schin { 7834887Schin if(outfile) 7844887Schin { 785*8462SApril.Chin@Sun.COM Namval_t *np,*tp; 786*8462SApril.Chin@Sun.COM *nextcp = 0; 787*8462SApril.Chin@Sun.COM np=nv_open(arg,wp->root,NV_VARNAME|NV_NOADD|NV_NOASSIGN|NV_NOFAIL|wp->noscope); 788*8462SApril.Chin@Sun.COM if(!np || (nv_isarray(np) && (!(tp=nv_opensub(np)) || !nv_isvtree(tp)))) 789*8462SApril.Chin@Sun.COM { 790*8462SApril.Chin@Sun.COM *nextcp = '.'; 791*8462SApril.Chin@Sun.COM continue; 792*8462SApril.Chin@Sun.COM } 793*8462SApril.Chin@Sun.COM if(wp->indent>=0) 794*8462SApril.Chin@Sun.COM sfnputc(outfile,'\t',wp->indent); 795*8462SApril.Chin@Sun.COM if(*cp!='[' && (tp = nv_type(np))) 796*8462SApril.Chin@Sun.COM { 797*8462SApril.Chin@Sun.COM char *sp; 798*8462SApril.Chin@Sun.COM if(sp = strrchr(tp->nvname,'.')) 799*8462SApril.Chin@Sun.COM sp++; 800*8462SApril.Chin@Sun.COM else 801*8462SApril.Chin@Sun.COM sp = tp->nvname; 802*8462SApril.Chin@Sun.COM sfputr(outfile,sp,' '); 803*8462SApril.Chin@Sun.COM } 8044887Schin nv_outname(outfile,cp,nextcp-cp); 8054887Schin sfputc(outfile,'='); 806*8462SApril.Chin@Sun.COM *nextcp = '.'; 807*8462SApril.Chin@Sun.COM } 808*8462SApril.Chin@Sun.COM else 809*8462SApril.Chin@Sun.COM { 810*8462SApril.Chin@Sun.COM outval(cp,arg,wp); 811*8462SApril.Chin@Sun.COM continue; 8124887Schin } 8134887Schin argv = genvalue(argv,cp,n+m+r,wp); 814*8462SApril.Chin@Sun.COM if(wp->indent>=0) 8154887Schin sfputc(outfile,'\n'); 8164887Schin if(*argv) 8174887Schin continue; 8184887Schin break; 8194887Schin } 820*8462SApril.Chin@Sun.COM else if(outfile && !wp->nofollow && argv[1] && memcmp(arg,argv[1],l=strlen(arg))==0 && argv[1][l]=='[') 8214887Schin { 8224887Schin Namval_t *np = nv_open(arg,wp->root,NV_VARNAME|NV_NOADD|NV_NOASSIGN|wp->noscope); 8234887Schin if(!np) 8244887Schin continue; 825*8462SApril.Chin@Sun.COM wp->array = nv_isarray(np); 826*8462SApril.Chin@Sun.COM if(wp->indent>0) 827*8462SApril.Chin@Sun.COM sfnputc(outfile,'\t',wp->indent); 8284887Schin nv_attribute(np,outfile,"typeset",1); 8294887Schin nv_close(np); 830*8462SApril.Chin@Sun.COM sfputr(outfile,arg+m+r+(n?n:0),'='); 831*8462SApril.Chin@Sun.COM wp->nofollow=1; 832*8462SApril.Chin@Sun.COM argv = genvalue(argv,cp,cp-arg ,wp); 833*8462SApril.Chin@Sun.COM sfputc(outfile,wp->indent<0?';':'\n'); 8344887Schin } 8354887Schin else if(outfile && *cp=='[') 8364887Schin { 837*8462SApril.Chin@Sun.COM if(wp->indent) 838*8462SApril.Chin@Sun.COM sfnputc(outfile,'\t',wp->indent); 8394887Schin sfputr(outfile,cp,'='); 8404887Schin argv = genvalue(++argv,cp,cp-arg ,wp); 8414887Schin sfputc(outfile,'\n'); 8424887Schin } 8434887Schin else 844*8462SApril.Chin@Sun.COM { 8454887Schin outval(cp,arg,wp); 846*8462SApril.Chin@Sun.COM if(wp->array) 847*8462SApril.Chin@Sun.COM { 848*8462SApril.Chin@Sun.COM if(wp->indent>=0) 849*8462SApril.Chin@Sun.COM wp->indent++; 850*8462SApril.Chin@Sun.COM else 851*8462SApril.Chin@Sun.COM sfputc(outfile,' '); 852*8462SApril.Chin@Sun.COM wp->array = 0; 853*8462SApril.Chin@Sun.COM } 854*8462SApril.Chin@Sun.COM } 8554887Schin } 8564887Schin else 8574887Schin break; 858*8462SApril.Chin@Sun.COM wp->nofollow = 0; 8594887Schin } 860*8462SApril.Chin@Sun.COM wp->array = 0; 8614887Schin if(outfile) 8624887Schin { 8634887Schin int c = prefix[m-1]; 8644887Schin cp = (char*)prefix; 8654887Schin if(c=='.') 8664887Schin cp[m-1] = 0; 8674887Schin outval(".",prefix-n,wp); 8684887Schin if(c=='.') 8694887Schin cp[m-1] = c; 870*8462SApril.Chin@Sun.COM if(wp->indent>0) 871*8462SApril.Chin@Sun.COM sfnputc(outfile,'\t',--wp->indent); 8724887Schin sfputc(outfile,')'); 8734887Schin } 8744887Schin return(--argv); 8754887Schin } 8764887Schin 8774887Schin /* 8784887Schin * walk the virtual tree and print or delete name-value pairs 8794887Schin */ 880*8462SApril.Chin@Sun.COM static char *walk_tree(register Namval_t *np, Namval_t *xp, int flags) 8814887Schin { 8824887Schin static Sfio_t *out; 8834887Schin struct Walk walk; 8844887Schin Sfio_t *outfile; 885*8462SApril.Chin@Sun.COM int len, savtop = staktell(); 8864887Schin char *savptr = stakfreeze(0); 8874887Schin register struct argnod *ap=0; 8884887Schin struct argnod *arglist=0; 8894887Schin char *name,*cp, **argv; 8904887Schin char *subscript=0; 8914887Schin void *dir; 892*8462SApril.Chin@Sun.COM int n=0, noscope=(flags&NV_NOSCOPE); 893*8462SApril.Chin@Sun.COM Namarr_t *arp = nv_arrayptr(np); 894*8462SApril.Chin@Sun.COM Dt_t *save_tree = sh.var_tree; 895*8462SApril.Chin@Sun.COM Namval_t *mp=0; 896*8462SApril.Chin@Sun.COM Shell_t *shp = sh_getinterp(); 897*8462SApril.Chin@Sun.COM char *xpname = xp?stakcopy(nv_name(xp)):0; 898*8462SApril.Chin@Sun.COM if(xp) 899*8462SApril.Chin@Sun.COM { 900*8462SApril.Chin@Sun.COM shp->last_root = shp->prev_root; 901*8462SApril.Chin@Sun.COM shp->last_table = shp->prev_table; 902*8462SApril.Chin@Sun.COM } 903*8462SApril.Chin@Sun.COM if(shp->last_table) 904*8462SApril.Chin@Sun.COM shp->last_root = nv_dict(shp->last_table); 905*8462SApril.Chin@Sun.COM if(shp->last_root) 906*8462SApril.Chin@Sun.COM shp->var_tree = shp->last_root; 9074887Schin stakputs(nv_name(np)); 908*8462SApril.Chin@Sun.COM if(arp && !(arp->nelem&ARRAY_SCAN) && (subscript = nv_getsub(np))) 9094887Schin { 910*8462SApril.Chin@Sun.COM mp = nv_opensub(np); 9114887Schin stakputc('['); 9124887Schin stakputs(subscript); 9134887Schin stakputc(']'); 9144887Schin stakputc('.'); 9154887Schin } 916*8462SApril.Chin@Sun.COM else if(*stakptr(staktell()-1) == ']') 917*8462SApril.Chin@Sun.COM mp = np; 9184887Schin name = stakfreeze(1); 919*8462SApril.Chin@Sun.COM len = strlen(name); 920*8462SApril.Chin@Sun.COM shp->last_root = 0; 921*8462SApril.Chin@Sun.COM dir = nv_diropen(mp,name); 922*8462SApril.Chin@Sun.COM walk.root = shp->last_root?shp->last_root:shp->var_tree; 9234887Schin if(subscript) 9244887Schin name[strlen(name)-1] = 0; 9254887Schin while(cp = nv_dirnext(dir)) 9264887Schin { 927*8462SApril.Chin@Sun.COM if(cp[len]!='.') 928*8462SApril.Chin@Sun.COM continue; 929*8462SApril.Chin@Sun.COM if(xp) 930*8462SApril.Chin@Sun.COM { 931*8462SApril.Chin@Sun.COM Dt_t *dp = shp->var_tree; 932*8462SApril.Chin@Sun.COM Namval_t *nq, *mq; 933*8462SApril.Chin@Sun.COM if(strlen(cp)<=len) 934*8462SApril.Chin@Sun.COM continue; 935*8462SApril.Chin@Sun.COM nq = nv_open(cp,walk.root,NV_VARNAME|NV_NOADD|NV_NOASSIGN|NV_NOFAIL); 936*8462SApril.Chin@Sun.COM if(!nq && (flags&NV_MOVE)) 937*8462SApril.Chin@Sun.COM nq = nv_search(cp,walk.root,NV_NOADD); 938*8462SApril.Chin@Sun.COM stakseek(0); 939*8462SApril.Chin@Sun.COM stakputs(xpname); 940*8462SApril.Chin@Sun.COM stakputs(cp+len); 941*8462SApril.Chin@Sun.COM stakputc(0); 942*8462SApril.Chin@Sun.COM shp->var_tree = save_tree; 943*8462SApril.Chin@Sun.COM mq = nv_open(stakptr(0),save_tree,NV_VARNAME|NV_NOASSIGN|NV_NOFAIL); 944*8462SApril.Chin@Sun.COM shp->var_tree = dp; 945*8462SApril.Chin@Sun.COM if(nq && mq) 946*8462SApril.Chin@Sun.COM { 947*8462SApril.Chin@Sun.COM nv_clone(nq,mq,flags|NV_RAW); 948*8462SApril.Chin@Sun.COM if(flags&NV_MOVE) 949*8462SApril.Chin@Sun.COM nv_delete(nq,walk.root,0); 950*8462SApril.Chin@Sun.COM } 951*8462SApril.Chin@Sun.COM continue; 952*8462SApril.Chin@Sun.COM } 9534887Schin stakseek(ARGVAL); 9544887Schin stakputs(cp); 9554887Schin ap = (struct argnod*)stakfreeze(1); 9564887Schin ap->argflag = ARG_RAW; 9574887Schin ap->argchn.ap = arglist; 9584887Schin n++; 9594887Schin arglist = ap; 9604887Schin } 961*8462SApril.Chin@Sun.COM nv_dirclose(dir); 962*8462SApril.Chin@Sun.COM if(xp) 963*8462SApril.Chin@Sun.COM { 964*8462SApril.Chin@Sun.COM shp->var_tree = save_tree; 965*8462SApril.Chin@Sun.COM return((char*)0); 966*8462SApril.Chin@Sun.COM } 9674887Schin argv = (char**)stakalloc((n+1)*sizeof(char*)); 9684887Schin argv += n; 9694887Schin *argv = 0; 9704887Schin for(; ap; ap=ap->argchn.ap) 9714887Schin *--argv = ap->argval; 972*8462SApril.Chin@Sun.COM if(flags&1) 9734887Schin outfile = 0; 9744887Schin else if(!(outfile=out)) 9754887Schin outfile = out = sfnew((Sfio_t*)0,(char*)0,-1,-1,SF_WRITE|SF_STRING); 9764887Schin else 9774887Schin sfseek(outfile,0L,SEEK_SET); 9784887Schin walk.out = outfile; 979*8462SApril.Chin@Sun.COM walk.indent = (flags&NV_EXPORT)?-1:0; 980*8462SApril.Chin@Sun.COM walk.nofollow = 0; 9814887Schin walk.noscope = noscope; 982*8462SApril.Chin@Sun.COM walk.array = 0; 983*8462SApril.Chin@Sun.COM walk.flags = flags; 9844887Schin genvalue(argv,name,0,&walk); 9854887Schin stakset(savptr,savtop); 986*8462SApril.Chin@Sun.COM shp->var_tree = save_tree; 9874887Schin if(!outfile) 9884887Schin return((char*)0); 9894887Schin sfputc(out,0); 9904887Schin return((char*)out->_data); 9914887Schin } 9924887Schin 993*8462SApril.Chin@Sun.COM Namfun_t *nv_isvtree(Namval_t *np) 994*8462SApril.Chin@Sun.COM { 995*8462SApril.Chin@Sun.COM if(np) 996*8462SApril.Chin@Sun.COM return(nv_hasdisc(np,&treedisc)); 997*8462SApril.Chin@Sun.COM return(0); 998*8462SApril.Chin@Sun.COM } 999*8462SApril.Chin@Sun.COM 10004887Schin /* 10014887Schin * get discipline for compound initializations 10024887Schin */ 10034887Schin char *nv_getvtree(register Namval_t *np, Namfun_t *fp) 10044887Schin { 1005*8462SApril.Chin@Sun.COM int flags=0; 1006*8462SApril.Chin@Sun.COM for(; fp && fp->next; fp=fp->next) 1007*8462SApril.Chin@Sun.COM { 1008*8462SApril.Chin@Sun.COM if(fp->next->disc && (fp->next->disc->getnum || fp->next->disc->getval)) 1009*8462SApril.Chin@Sun.COM return(nv_getv(np,fp)); 1010*8462SApril.Chin@Sun.COM } 1011*8462SApril.Chin@Sun.COM if(nv_isattr(np,NV_BINARY) && !nv_isattr(np,NV_RAW)) 10124887Schin return(nv_getv(np,fp)); 1013*8462SApril.Chin@Sun.COM if(nv_isattr(np,NV_ARRAY) && !nv_type(np) && nv_arraychild(np,(Namval_t*)0,0)==np) 10144887Schin return(nv_getv(np,fp)); 1015*8462SApril.Chin@Sun.COM if(flags = nv_isattr(np,NV_EXPORT)) 1016*8462SApril.Chin@Sun.COM nv_offattr(np,NV_EXPORT); 1017*8462SApril.Chin@Sun.COM return(walk_tree(np,(Namval_t*)0,flags)); 10184887Schin } 10194887Schin 10204887Schin /* 10214887Schin * put discipline for compound initializations 10224887Schin */ 10234887Schin static void put_tree(register Namval_t *np, const char *val, int flags,Namfun_t *fp) 10244887Schin { 10254887Schin struct Namarray *ap; 10264887Schin int nleft = 0; 1027*8462SApril.Chin@Sun.COM if(!val && !fp->next && nv_isattr(np,NV_NOFREE)) 1028*8462SApril.Chin@Sun.COM return; 1029*8462SApril.Chin@Sun.COM if(!nv_isattr(np,(NV_INTEGER|NV_BINARY))) 1030*8462SApril.Chin@Sun.COM { 1031*8462SApril.Chin@Sun.COM Shell_t *shp = sh_getinterp(); 1032*8462SApril.Chin@Sun.COM Namval_t *last_table = shp->last_table; 1033*8462SApril.Chin@Sun.COM Dt_t *last_root = shp->last_root; 1034*8462SApril.Chin@Sun.COM Namval_t *mp = val?nv_open(val,shp->var_tree,NV_VARNAME|NV_NOADD|NV_NOASSIGN|NV_NOFAIL):0; 1035*8462SApril.Chin@Sun.COM if(mp && nv_isvtree(mp)) 1036*8462SApril.Chin@Sun.COM { 1037*8462SApril.Chin@Sun.COM shp->prev_table = shp->last_table; 1038*8462SApril.Chin@Sun.COM shp->prev_root = shp->last_root; 1039*8462SApril.Chin@Sun.COM shp->last_table = last_table; 1040*8462SApril.Chin@Sun.COM shp->last_root = last_root; 1041*8462SApril.Chin@Sun.COM if(!(flags&NV_APPEND)) 1042*8462SApril.Chin@Sun.COM walk_tree(np,(Namval_t*)0,(flags&NV_NOSCOPE)|1); 1043*8462SApril.Chin@Sun.COM nv_clone(mp,np,NV_COMVAR); 1044*8462SApril.Chin@Sun.COM return; 1045*8462SApril.Chin@Sun.COM } 1046*8462SApril.Chin@Sun.COM walk_tree(np,(Namval_t*)0,(flags&NV_NOSCOPE)|1); 1047*8462SApril.Chin@Sun.COM } 10484887Schin nv_putv(np, val, flags,fp); 1049*8462SApril.Chin@Sun.COM if(val && nv_isattr(np,(NV_INTEGER|NV_BINARY))) 10504887Schin return; 10514887Schin if(ap= nv_arrayptr(np)) 10524887Schin nleft = array_elem(ap); 10534887Schin if(nleft==0) 10544887Schin { 10554887Schin fp = nv_stack(np,fp); 10564887Schin if(fp = nv_stack(np,NIL(Namfun_t*))) 10574887Schin free((void*)fp); 10584887Schin } 10594887Schin } 10604887Schin 10614887Schin /* 10624887Schin * Insert discipline to cause $x to print current tree 10634887Schin */ 10644887Schin void nv_setvtree(register Namval_t *np) 10654887Schin { 10664887Schin register Namfun_t *nfp; 1067*8462SApril.Chin@Sun.COM if(sh.subshell) 1068*8462SApril.Chin@Sun.COM sh_assignok(np,1); 10694887Schin if(nv_hasdisc(np, &treedisc)) 10704887Schin return; 10714887Schin nfp = newof(NIL(void*),Namfun_t,1,0); 10724887Schin nfp->disc = &treedisc; 10734887Schin nv_stack(np, nfp); 10744887Schin } 10754887Schin 1076