1*4887Schin /*********************************************************************** 2*4887Schin * * 3*4887Schin * This software is part of the ast package * 4*4887Schin * Copyright (c) 1982-2007 AT&T Knowledge Ventures * 5*4887Schin * and is licensed under the * 6*4887Schin * Common Public License, Version 1.0 * 7*4887Schin * by AT&T Knowledge Ventures * 8*4887Schin * * 9*4887Schin * A copy of the License is available at * 10*4887Schin * http://www.opensource.org/licenses/cpl1.0.txt * 11*4887Schin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 12*4887Schin * * 13*4887Schin * Information and Software Systems Research * 14*4887Schin * AT&T Research * 15*4887Schin * Florham Park NJ * 16*4887Schin * * 17*4887Schin * David Korn <dgk@research.att.com> * 18*4887Schin * * 19*4887Schin ***********************************************************************/ 20*4887Schin #pragma prototyped 21*4887Schin 22*4887Schin /* 23*4887Schin * code for tree nodes and name walking 24*4887Schin * 25*4887Schin * David Korn 26*4887Schin * AT&T Labs 27*4887Schin * 28*4887Schin */ 29*4887Schin 30*4887Schin #include "defs.h" 31*4887Schin #include "name.h" 32*4887Schin #include "argnod.h" 33*4887Schin 34*4887Schin struct nvdir 35*4887Schin { 36*4887Schin Dt_t *root; 37*4887Schin Namval_t *hp; 38*4887Schin Namval_t *table; 39*4887Schin Namval_t *(*nextnode)(Namval_t*,Dt_t*,Namfun_t*); 40*4887Schin Namfun_t *fun; 41*4887Schin struct nvdir *prev; 42*4887Schin int len; 43*4887Schin int offset; 44*4887Schin char data[1]; 45*4887Schin }; 46*4887Schin 47*4887Schin char *nv_getvtree(Namval_t*, Namfun_t *); 48*4887Schin static void put_tree(Namval_t*, const char*, int,Namfun_t*); 49*4887Schin 50*4887Schin static Namval_t *create_tree(Namval_t *np,const char *name,int flag,Namfun_t *dp) 51*4887Schin { 52*4887Schin register Namfun_t *fp=dp; 53*4887Schin while(fp=fp->next) 54*4887Schin { 55*4887Schin if(fp->disc && fp->disc->createf) 56*4887Schin { 57*4887Schin if(np=(*fp->disc->createf)(np,name,flag,fp)) 58*4887Schin dp->last = fp->last; 59*4887Schin return(np); 60*4887Schin } 61*4887Schin } 62*4887Schin return((flag&NV_NOADD)?0:np); 63*4887Schin } 64*4887Schin 65*4887Schin static const Namdisc_t treedisc = 66*4887Schin { 67*4887Schin 0, 68*4887Schin put_tree, 69*4887Schin nv_getvtree, 70*4887Schin 0, 71*4887Schin 0, 72*4887Schin create_tree 73*4887Schin }; 74*4887Schin 75*4887Schin static char *nextdot(const char *str) 76*4887Schin { 77*4887Schin register char *cp; 78*4887Schin if(*str=='.') 79*4887Schin str++; 80*4887Schin if(*str =='[') 81*4887Schin { 82*4887Schin cp = nv_endsubscript((Namval_t*)0,(char*)str,0); 83*4887Schin return(*cp=='.'?cp:0); 84*4887Schin } 85*4887Schin else 86*4887Schin return(strchr(str,'.')); 87*4887Schin } 88*4887Schin 89*4887Schin static Namfun_t *nextdisc(Namval_t *np) 90*4887Schin { 91*4887Schin register Namfun_t *fp; 92*4887Schin if(nv_isref(np)) 93*4887Schin return(0); 94*4887Schin for(fp=np->nvfun;fp;fp=fp->next) 95*4887Schin { 96*4887Schin if(fp && fp->disc && fp->disc->nextf) 97*4887Schin return(fp); 98*4887Schin } 99*4887Schin return(0); 100*4887Schin } 101*4887Schin 102*4887Schin void *nv_diropen(const char *name) 103*4887Schin { 104*4887Schin char *next,*last; 105*4887Schin int c,len=strlen(name); 106*4887Schin struct nvdir *save, *dp = new_of(struct nvdir,len); 107*4887Schin Namval_t *np, fake; 108*4887Schin Namfun_t *nfp; 109*4887Schin if(!dp) 110*4887Schin return(0); 111*4887Schin memset((void*)dp, 0, sizeof(*dp)); 112*4887Schin last=dp->data; 113*4887Schin if(name[len-1]=='*' || name[len-1]=='@') 114*4887Schin len -= 1; 115*4887Schin name = memcpy(last,name,len); 116*4887Schin last[len] = 0; 117*4887Schin dp->len = len; 118*4887Schin dp->root = sh.var_tree; 119*4887Schin dp->table = sh.last_table; 120*4887Schin if(*name) 121*4887Schin { 122*4887Schin fake.nvname = (char*)name; 123*4887Schin dp->hp = (Namval_t*)dtprev(dp->root,&fake); 124*4887Schin dp->hp = (Namval_t*)dtnext(dp->root,dp->hp); 125*4887Schin } 126*4887Schin else 127*4887Schin dp->hp = (Namval_t*)dtfirst(dp->root); 128*4887Schin while(next= nextdot(last)) 129*4887Schin { 130*4887Schin c = *next; 131*4887Schin *next = 0; 132*4887Schin np = nv_search(last,dp->root,0); 133*4887Schin *next = c; 134*4887Schin if(np && ((nfp=nextdisc(np)) || nv_istable(np))) 135*4887Schin { 136*4887Schin if(!(save = new_of(struct nvdir,0))) 137*4887Schin return(0); 138*4887Schin *save = *dp; 139*4887Schin dp->prev = save; 140*4887Schin if(nv_istable(np)) 141*4887Schin dp->root = nv_dict(np); 142*4887Schin else 143*4887Schin dp->root = (Dt_t*)dp; 144*4887Schin dp->offset = last-(char*)name; 145*4887Schin if(dp->offset<len) 146*4887Schin dp->len = len-dp->offset; 147*4887Schin else 148*4887Schin dp->len = 0; 149*4887Schin if(nfp) 150*4887Schin { 151*4887Schin dp->nextnode = nfp->disc->nextf; 152*4887Schin dp->table = np; 153*4887Schin dp->fun = nfp; 154*4887Schin dp->hp = (*dp->nextnode)(np,(Dt_t*)0,nfp); 155*4887Schin } 156*4887Schin else 157*4887Schin dp->nextnode = 0; 158*4887Schin } 159*4887Schin else 160*4887Schin break; 161*4887Schin last = next+1; 162*4887Schin } 163*4887Schin return((void*)dp); 164*4887Schin } 165*4887Schin 166*4887Schin 167*4887Schin static Namval_t *nextnode(struct nvdir *dp) 168*4887Schin { 169*4887Schin if(dp->nextnode) 170*4887Schin return((*dp->nextnode)(dp->hp,dp->root,dp->fun)); 171*4887Schin if(dp->len && memcmp(dp->data, dp->hp->nvname, dp->len)) 172*4887Schin return(0); 173*4887Schin return((Namval_t*)dtnext(dp->root,dp->hp)); 174*4887Schin } 175*4887Schin 176*4887Schin char *nv_dirnext(void *dir) 177*4887Schin { 178*4887Schin register struct nvdir *save, *dp = (struct nvdir*)dir; 179*4887Schin register Namval_t *np, *last_table; 180*4887Schin register char *cp; 181*4887Schin Namfun_t *nfp; 182*4887Schin while(1) 183*4887Schin { 184*4887Schin while(np=dp->hp) 185*4887Schin { 186*4887Schin dp->hp = nextnode(dp); 187*4887Schin if(nv_isnull(np)) 188*4887Schin continue; 189*4887Schin last_table = sh.last_table; 190*4887Schin sh.last_table = dp->table; 191*4887Schin cp = nv_name(np); 192*4887Schin sh.last_table = last_table; 193*4887Schin if(!dp->len || memcmp(cp+dp->offset,dp->data,dp->len)==0) 194*4887Schin { 195*4887Schin if((nfp=nextdisc(np)) || nv_istable(np)) 196*4887Schin { 197*4887Schin Dt_t *root; 198*4887Schin if(nv_istable(np)) 199*4887Schin root = nv_dict(np); 200*4887Schin else 201*4887Schin root = (Dt_t*)dp; 202*4887Schin /* check for recursive walk */ 203*4887Schin for(save=dp; save; save=save->prev) 204*4887Schin { 205*4887Schin if(save->root==root) 206*4887Schin break; 207*4887Schin } 208*4887Schin if(save) 209*4887Schin continue; 210*4887Schin if(!(save = new_of(struct nvdir,0))) 211*4887Schin return(0); 212*4887Schin *save = *dp; 213*4887Schin dp->prev = save; 214*4887Schin dp->root = root; 215*4887Schin dp->len = 0; 216*4887Schin if(nfp && np->nvfun) 217*4887Schin { 218*4887Schin dp->nextnode = nfp->disc->nextf; 219*4887Schin dp->table = np; 220*4887Schin dp->fun = nfp; 221*4887Schin dp->hp = (*dp->nextnode)(np,(Dt_t*)0,nfp); 222*4887Schin } 223*4887Schin else 224*4887Schin dp->nextnode = 0; 225*4887Schin } 226*4887Schin return(cp); 227*4887Schin } 228*4887Schin } 229*4887Schin if(!(save=dp->prev)) 230*4887Schin break; 231*4887Schin #if 0 232*4887Schin sh.last_table = dp->table; 233*4887Schin #endif 234*4887Schin *dp = *save; 235*4887Schin free((void*)save); 236*4887Schin } 237*4887Schin return(0); 238*4887Schin } 239*4887Schin 240*4887Schin void nv_dirclose(void *dir) 241*4887Schin { 242*4887Schin struct nvdir *dp = (struct nvdir*)dir; 243*4887Schin if(dp->prev) 244*4887Schin nv_dirclose((void*)dp->prev); 245*4887Schin free(dir); 246*4887Schin } 247*4887Schin 248*4887Schin static void outtype(Namval_t *np, Namfun_t *fp, Sfio_t* out, const char *prefix) 249*4887Schin { 250*4887Schin char *type=0; 251*4887Schin Namval_t *tp = fp->type; 252*4887Schin if(!tp && fp->disc && fp->disc->typef) 253*4887Schin tp = (*fp->disc->typef)(np,fp); 254*4887Schin for(fp=fp->next;fp;fp=fp->next) 255*4887Schin { 256*4887Schin if(fp->type || (fp->disc && fp->disc->typef &&(*fp->disc->typef)(np,fp))) 257*4887Schin { 258*4887Schin outtype(np,fp,out,prefix); 259*4887Schin break; 260*4887Schin } 261*4887Schin } 262*4887Schin if(prefix && *prefix=='t') 263*4887Schin type = "-T"; 264*4887Schin else if(!prefix) 265*4887Schin type = "type"; 266*4887Schin if(type) 267*4887Schin sfprintf(out,"%s %s ",type,tp->nvname); 268*4887Schin } 269*4887Schin 270*4887Schin /* 271*4887Schin * print the attributes of name value pair give by <np> 272*4887Schin */ 273*4887Schin void nv_attribute(register Namval_t *np,Sfio_t *out,char *prefix,int noname) 274*4887Schin { 275*4887Schin register const Shtable_t *tp; 276*4887Schin register char *cp; 277*4887Schin register unsigned val; 278*4887Schin register unsigned mask; 279*4887Schin register unsigned attr; 280*4887Schin Namfun_t *fp=0; 281*4887Schin for(fp=np->nvfun;fp;fp=fp->next) 282*4887Schin { 283*4887Schin if(fp->type || (fp->disc && fp->disc->typef &&(*fp->disc->typef)(np,fp))) 284*4887Schin break; 285*4887Schin } 286*4887Schin #if 0 287*4887Schin if(!fp && !nv_isattr(np,~NV_ARRAY)) 288*4887Schin { 289*4887Schin if(!nv_isattr(np,NV_ARRAY) || nv_aindex(np)>=0) 290*4887Schin return; 291*4887Schin } 292*4887Schin #else 293*4887Schin if(!fp && !nv_isattr(np,~NV_MINIMAL)) 294*4887Schin return; 295*4887Schin #endif 296*4887Schin 297*4887Schin if ((attr=nv_isattr(np,~NV_NOFREE)) || fp) 298*4887Schin { 299*4887Schin if((attr&NV_NOPRINT)==NV_NOPRINT) 300*4887Schin attr &= ~NV_NOPRINT; 301*4887Schin if(!attr && !fp) 302*4887Schin return; 303*4887Schin if(prefix) 304*4887Schin sfputr(out,prefix,' '); 305*4887Schin for(tp = shtab_attributes; *tp->sh_name;tp++) 306*4887Schin { 307*4887Schin val = tp->sh_number; 308*4887Schin mask = val; 309*4887Schin if(fp && (val&NV_INTEGER)) 310*4887Schin break; 311*4887Schin /* 312*4887Schin * the following test is needed to prevent variables 313*4887Schin * with E attribute from being given the F 314*4887Schin * attribute as well 315*4887Schin */ 316*4887Schin if(val==(NV_INTEGER|NV_DOUBLE) && (attr&NV_EXPNOTE)) 317*4887Schin continue; 318*4887Schin if(val&NV_INTEGER) 319*4887Schin mask |= NV_DOUBLE; 320*4887Schin else if(val&NV_HOST) 321*4887Schin mask = NV_HOST; 322*4887Schin if((attr&mask)==val) 323*4887Schin { 324*4887Schin if(val==NV_ARRAY) 325*4887Schin { 326*4887Schin Namarr_t *ap = nv_arrayptr(np); 327*4887Schin if(array_assoc(ap)) 328*4887Schin { 329*4887Schin if(tp->sh_name[1]!='A') 330*4887Schin continue; 331*4887Schin } 332*4887Schin else if(tp->sh_name[1]=='A') 333*4887Schin continue; 334*4887Schin #if 0 335*4887Schin cp = "associative"; 336*4887Schin else 337*4887Schin cp = "indexed"; 338*4887Schin if(!prefix) 339*4887Schin sfputr(out,cp,' '); 340*4887Schin else if(*cp=='i') 341*4887Schin tp++; 342*4887Schin #endif 343*4887Schin } 344*4887Schin if(prefix) 345*4887Schin { 346*4887Schin if(*tp->sh_name=='-') 347*4887Schin sfprintf(out,"%.2s ",tp->sh_name); 348*4887Schin } 349*4887Schin else 350*4887Schin sfputr(out,tp->sh_name+2,' '); 351*4887Schin if ((val&(NV_LJUST|NV_RJUST|NV_ZFILL)) && !(val&NV_INTEGER) && val!=NV_HOST) 352*4887Schin sfprintf(out,"%d ",nv_size(np)); 353*4887Schin } 354*4887Schin if(val==NV_INTEGER && nv_isattr(np,NV_INTEGER)) 355*4887Schin { 356*4887Schin if(nv_size(np) != 10) 357*4887Schin { 358*4887Schin if(nv_isattr(np, NV_DOUBLE)) 359*4887Schin cp = "precision"; 360*4887Schin else 361*4887Schin cp = "base"; 362*4887Schin if(!prefix) 363*4887Schin sfputr(out,cp,' '); 364*4887Schin sfprintf(out,"%d ",nv_size(np)); 365*4887Schin } 366*4887Schin break; 367*4887Schin } 368*4887Schin } 369*4887Schin if(fp) 370*4887Schin outtype(np,fp,out,prefix); 371*4887Schin if(noname) 372*4887Schin return; 373*4887Schin sfputr(out,nv_name(np),'\n'); 374*4887Schin } 375*4887Schin } 376*4887Schin 377*4887Schin struct Walk 378*4887Schin { 379*4887Schin Sfio_t *out; 380*4887Schin Dt_t *root; 381*4887Schin int noscope; 382*4887Schin int indent; 383*4887Schin }; 384*4887Schin 385*4887Schin static void outval(char *name, const char *vname, struct Walk *wp) 386*4887Schin { 387*4887Schin register Namval_t *np, *nq; 388*4887Schin register Namfun_t *fp; 389*4887Schin int isarray=0, associative=0, special=0; 390*4887Schin if(!(np=nv_open(vname,wp->root,NV_ARRAY|NV_VARNAME|NV_NOADD|NV_NOASSIGN|wp->noscope))) 391*4887Schin return; 392*4887Schin if(nv_isarray(np) && *name=='.') 393*4887Schin special = 1; 394*4887Schin if(!special && (fp=nv_hasdisc(np,&treedisc))) 395*4887Schin { 396*4887Schin if(!wp->out) 397*4887Schin { 398*4887Schin fp = nv_stack(np,fp); 399*4887Schin if(fp = nv_stack(np,NIL(Namfun_t*))) 400*4887Schin free((void*)fp); 401*4887Schin np->nvfun = 0; 402*4887Schin } 403*4887Schin return; 404*4887Schin } 405*4887Schin if(nv_isnull(np)) 406*4887Schin return; 407*4887Schin if(special || nv_isarray(np)) 408*4887Schin { 409*4887Schin isarray=1; 410*4887Schin associative= nv_aindex(np)<0; 411*4887Schin if(array_elem(nv_arrayptr(np))==0) 412*4887Schin isarray=2; 413*4887Schin else 414*4887Schin nq = nv_putsub(np,NIL(char*),ARRAY_SCAN|(wp->out?ARRAY_NOCHILD:0)); 415*4887Schin } 416*4887Schin if(!wp->out) 417*4887Schin { 418*4887Schin _nv_unset(np,NV_RDONLY); 419*4887Schin nv_close(np); 420*4887Schin return; 421*4887Schin } 422*4887Schin if(isarray==1 && !nq) 423*4887Schin return; 424*4887Schin if(special) 425*4887Schin { 426*4887Schin associative = 1; 427*4887Schin sfnputc(wp->out,'\t',wp->indent); 428*4887Schin } 429*4887Schin else 430*4887Schin { 431*4887Schin sfnputc(wp->out,'\t',wp->indent); 432*4887Schin nv_attribute(np,wp->out,"typeset",'='); 433*4887Schin nv_outname(wp->out,name,-1); 434*4887Schin sfputc(wp->out,(isarray==2?'\n':'=')); 435*4887Schin if(isarray) 436*4887Schin { 437*4887Schin if(isarray==2) 438*4887Schin return; 439*4887Schin sfwrite(wp->out,"(\n",2); 440*4887Schin sfnputc(wp->out,'\t',++wp->indent); 441*4887Schin } 442*4887Schin } 443*4887Schin while(1) 444*4887Schin { 445*4887Schin char *fmtq,*ep; 446*4887Schin if(isarray && associative) 447*4887Schin { 448*4887Schin if(!(fmtq = nv_getsub(np))) 449*4887Schin break; 450*4887Schin sfprintf(wp->out,"[%s]",sh_fmtq(fmtq)); 451*4887Schin sfputc(wp->out,'='); 452*4887Schin } 453*4887Schin if(!(fmtq = sh_fmtq(nv_getval(np)))) 454*4887Schin fmtq = ""; 455*4887Schin else if(!associative && (ep=strchr(fmtq,'='))) 456*4887Schin { 457*4887Schin char *qp = strchr(fmtq,'\''); 458*4887Schin if(!qp || qp>ep) 459*4887Schin { 460*4887Schin sfwrite(wp->out,fmtq,ep-fmtq); 461*4887Schin sfputc(wp->out,'\\'); 462*4887Schin fmtq = ep; 463*4887Schin } 464*4887Schin } 465*4887Schin if(*name=='[' && !isarray) 466*4887Schin sfprintf(wp->out,"(%s)\n",fmtq); 467*4887Schin else 468*4887Schin sfputr(wp->out,fmtq,'\n'); 469*4887Schin if(!nv_nextsub(np)) 470*4887Schin break; 471*4887Schin sfnputc(wp->out,'\t',wp->indent); 472*4887Schin } 473*4887Schin if(isarray && !special) 474*4887Schin { 475*4887Schin sfnputc(wp->out,'\t',--wp->indent); 476*4887Schin sfwrite(wp->out,")\n",2); 477*4887Schin } 478*4887Schin } 479*4887Schin 480*4887Schin /* 481*4887Schin * format initialization list given a list of assignments <argp> 482*4887Schin */ 483*4887Schin static char **genvalue(char **argv, const char *prefix, int n, struct Walk *wp) 484*4887Schin { 485*4887Schin register char *cp,*nextcp,*arg; 486*4887Schin register int m,r; 487*4887Schin register Sfio_t *outfile = wp->out; 488*4887Schin if(n==0) 489*4887Schin m = strlen(prefix); 490*4887Schin else if(cp=nextdot(prefix)) 491*4887Schin m = cp-prefix; 492*4887Schin else 493*4887Schin m = strlen(prefix)-1; 494*4887Schin m++; 495*4887Schin if(outfile) 496*4887Schin { 497*4887Schin sfwrite(outfile,"(\n",2); 498*4887Schin wp->indent++; 499*4887Schin } 500*4887Schin for(; arg= *argv; argv++) 501*4887Schin { 502*4887Schin cp = arg + n; 503*4887Schin if(n==0 && cp[m-1]!='.') 504*4887Schin continue; 505*4887Schin if(n && cp[m-1]==0) 506*4887Schin break; 507*4887Schin if(n==0 || strncmp(arg,prefix-n,m+n)==0) 508*4887Schin { 509*4887Schin cp +=m; 510*4887Schin r = 0; 511*4887Schin if(*cp=='.') 512*4887Schin cp++,r++; 513*4887Schin if(nextcp=nextdot(cp)) 514*4887Schin { 515*4887Schin if(outfile) 516*4887Schin { 517*4887Schin sfnputc(outfile,'\t',wp->indent); 518*4887Schin nv_outname(outfile,cp,nextcp-cp); 519*4887Schin sfputc(outfile,'='); 520*4887Schin } 521*4887Schin argv = genvalue(argv,cp,n+m+r,wp); 522*4887Schin if(outfile) 523*4887Schin sfputc(outfile,'\n'); 524*4887Schin if(*argv) 525*4887Schin continue; 526*4887Schin break; 527*4887Schin } 528*4887Schin else if(outfile && argv[1] && memcmp(arg,argv[1],r=strlen(arg))==0 && argv[1][r]=='[') 529*4887Schin { 530*4887Schin Namval_t *np = nv_open(arg,wp->root,NV_VARNAME|NV_NOADD|NV_NOASSIGN|wp->noscope); 531*4887Schin if(!np) 532*4887Schin continue; 533*4887Schin sfnputc(outfile,'\t',wp->indent); 534*4887Schin nv_attribute(np,outfile,"typeset",1); 535*4887Schin nv_close(np); 536*4887Schin sfputr(outfile,arg+m+(n?n+1:0),'='); 537*4887Schin argv = genvalue(++argv,cp,cp-arg ,wp); 538*4887Schin sfputc(outfile,'\n'); 539*4887Schin } 540*4887Schin else if(outfile && *cp=='[') 541*4887Schin { 542*4887Schin sfnputc(outfile,'\t',wp->indent); 543*4887Schin sfputr(outfile,cp,'='); 544*4887Schin argv = genvalue(++argv,cp,cp-arg ,wp); 545*4887Schin sfputc(outfile,'\n'); 546*4887Schin } 547*4887Schin else 548*4887Schin outval(cp,arg,wp); 549*4887Schin } 550*4887Schin else 551*4887Schin break; 552*4887Schin } 553*4887Schin if(outfile) 554*4887Schin { 555*4887Schin int c = prefix[m-1]; 556*4887Schin cp = (char*)prefix; 557*4887Schin if(c=='.') 558*4887Schin cp[m-1] = 0; 559*4887Schin outval(".",prefix-n,wp); 560*4887Schin if(c=='.') 561*4887Schin cp[m-1] = c; 562*4887Schin sfnputc(outfile,'\t',wp->indent-1); 563*4887Schin sfputc(outfile,')'); 564*4887Schin } 565*4887Schin return(--argv); 566*4887Schin } 567*4887Schin 568*4887Schin /* 569*4887Schin * walk the virtual tree and print or delete name-value pairs 570*4887Schin */ 571*4887Schin static char *walk_tree(register Namval_t *np, int dlete) 572*4887Schin { 573*4887Schin static Sfio_t *out; 574*4887Schin struct Walk walk; 575*4887Schin Sfio_t *outfile; 576*4887Schin int savtop = staktell(); 577*4887Schin char *savptr = stakfreeze(0); 578*4887Schin register struct argnod *ap=0; 579*4887Schin struct argnod *arglist=0; 580*4887Schin char *name,*cp, **argv; 581*4887Schin char *subscript=0; 582*4887Schin void *dir; 583*4887Schin int n=0, noscope=(dlete&NV_NOSCOPE); 584*4887Schin stakputs(nv_name(np)); 585*4887Schin if(subscript = nv_getsub(np)) 586*4887Schin { 587*4887Schin stakputc('['); 588*4887Schin stakputs(subscript); 589*4887Schin stakputc(']'); 590*4887Schin stakputc('.'); 591*4887Schin } 592*4887Schin name = stakfreeze(1); 593*4887Schin dir = nv_diropen(name); 594*4887Schin if(subscript) 595*4887Schin name[strlen(name)-1] = 0; 596*4887Schin while(cp = nv_dirnext(dir)) 597*4887Schin { 598*4887Schin stakseek(ARGVAL); 599*4887Schin stakputs(cp); 600*4887Schin ap = (struct argnod*)stakfreeze(1); 601*4887Schin ap->argflag = ARG_RAW; 602*4887Schin ap->argchn.ap = arglist; 603*4887Schin n++; 604*4887Schin arglist = ap; 605*4887Schin } 606*4887Schin argv = (char**)stakalloc((n+1)*sizeof(char*)); 607*4887Schin argv += n; 608*4887Schin *argv = 0; 609*4887Schin for(; ap; ap=ap->argchn.ap) 610*4887Schin *--argv = ap->argval; 611*4887Schin nv_dirclose(dir); 612*4887Schin if(dlete&1) 613*4887Schin outfile = 0; 614*4887Schin else if(!(outfile=out)) 615*4887Schin outfile = out = sfnew((Sfio_t*)0,(char*)0,-1,-1,SF_WRITE|SF_STRING); 616*4887Schin else 617*4887Schin sfseek(outfile,0L,SEEK_SET); 618*4887Schin walk.out = outfile; 619*4887Schin walk.root = sh.last_root; 620*4887Schin walk.indent = 0; 621*4887Schin walk.noscope = noscope; 622*4887Schin genvalue(argv,name,0,&walk); 623*4887Schin stakset(savptr,savtop); 624*4887Schin if(!outfile) 625*4887Schin return((char*)0); 626*4887Schin sfputc(out,0); 627*4887Schin return((char*)out->_data); 628*4887Schin } 629*4887Schin 630*4887Schin /* 631*4887Schin * get discipline for compound initializations 632*4887Schin */ 633*4887Schin char *nv_getvtree(register Namval_t *np, Namfun_t *fp) 634*4887Schin { 635*4887Schin NOT_USED(fp); 636*4887Schin if(nv_isattr(np,NV_BINARY) && nv_isattr(np,NV_RAW)) 637*4887Schin return(nv_getv(np,fp)); 638*4887Schin if(nv_isattr(np,NV_ARRAY) && nv_arraychild(np,(Namval_t*)0,0)==np) 639*4887Schin return(nv_getv(np,fp)); 640*4887Schin return(walk_tree(np,0)); 641*4887Schin } 642*4887Schin 643*4887Schin /* 644*4887Schin * put discipline for compound initializations 645*4887Schin */ 646*4887Schin static void put_tree(register Namval_t *np, const char *val, int flags,Namfun_t *fp) 647*4887Schin { 648*4887Schin struct Namarray *ap; 649*4887Schin int nleft = 0; 650*4887Schin if(!nv_isattr(np,NV_INTEGER)) 651*4887Schin walk_tree(np,(flags&NV_NOSCOPE)|1); 652*4887Schin nv_putv(np, val, flags,fp); 653*4887Schin if(nv_isattr(np,NV_INTEGER)) 654*4887Schin return; 655*4887Schin if(ap= nv_arrayptr(np)) 656*4887Schin nleft = array_elem(ap); 657*4887Schin if(nleft==0) 658*4887Schin { 659*4887Schin fp = nv_stack(np,fp); 660*4887Schin if(fp = nv_stack(np,NIL(Namfun_t*))) 661*4887Schin { 662*4887Schin free((void*)fp); 663*4887Schin } 664*4887Schin } 665*4887Schin } 666*4887Schin 667*4887Schin /* 668*4887Schin * Insert discipline to cause $x to print current tree 669*4887Schin */ 670*4887Schin void nv_setvtree(register Namval_t *np) 671*4887Schin { 672*4887Schin register Namfun_t *nfp; 673*4887Schin if(nv_hasdisc(np, &treedisc)) 674*4887Schin return; 675*4887Schin nfp = newof(NIL(void*),Namfun_t,1,0); 676*4887Schin nfp->disc = &treedisc; 677*4887Schin nv_stack(np, nfp); 678*4887Schin } 679*4887Schin 680