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 * Array processing routines 234887Schin * 244887Schin * David Korn 254887Schin * AT&T Labs 264887Schin * dgk@research.att.com 274887Schin * 284887Schin */ 294887Schin 304887Schin #include "defs.h" 314887Schin #include <stak.h> 324887Schin #include "name.h" 334887Schin 344887Schin #define NUMSIZE (4+(ARRAY_MAX>999)+(ARRAY_MAX>9999)+(ARRAY_MAX>99999)) 354887Schin #define is_associative(ap) array_assoc((Namarr_t*)(ap)) 36*8462SApril.Chin@Sun.COM #define array_setbit(cp, n, b) (cp[n] |= (b)) 37*8462SApril.Chin@Sun.COM #define array_clrbit(cp, n, b) (cp[n] &= ~(b)) 38*8462SApril.Chin@Sun.COM #define array_isbit(cp, n, b) (cp[n] & (b)) 394887Schin #define NV_CHILD NV_EXPORT 40*8462SApril.Chin@Sun.COM #define ARRAY_CHILD 1 41*8462SApril.Chin@Sun.COM #define ARRAY_NOFREE 2 424887Schin 434887Schin struct index_array 444887Schin { 454887Schin Namarr_t header; 46*8462SApril.Chin@Sun.COM void *xp; /* if set, subscripts will be converted */ 474887Schin int cur; /* index of current element */ 484887Schin int maxi; /* maximum index for array */ 494887Schin unsigned char *bits; /* bit array for child subscripts */ 504887Schin union Value val[1]; /* array of value holders */ 514887Schin }; 524887Schin 534887Schin struct assoc_array 544887Schin { 554887Schin Namarr_t header; 564887Schin Namval_t *pos; 574887Schin Namval_t *nextpos; 584887Schin Namval_t *cur; 594887Schin }; 604887Schin 61*8462SApril.Chin@Sun.COM static Namarr_t *array_scope(Namval_t *np, Namarr_t *ap, int flags) 62*8462SApril.Chin@Sun.COM { 63*8462SApril.Chin@Sun.COM Namarr_t *aq; 64*8462SApril.Chin@Sun.COM struct index_array *ar; 65*8462SApril.Chin@Sun.COM size_t size = ap->hdr.dsize; 66*8462SApril.Chin@Sun.COM if(size==0) 67*8462SApril.Chin@Sun.COM size = ap->hdr.disc->dsize; 68*8462SApril.Chin@Sun.COM if(!(aq=newof(NIL(Namarr_t*),Namarr_t,1,size-sizeof(Namarr_t)))) 69*8462SApril.Chin@Sun.COM return(0); 70*8462SApril.Chin@Sun.COM memcpy(aq,ap,size); 71*8462SApril.Chin@Sun.COM aq->hdr.nofree &= ~1; 72*8462SApril.Chin@Sun.COM aq->hdr.nofree |= (flags&NV_RDONLY)?1:0; 73*8462SApril.Chin@Sun.COM if(is_associative(aq)) 74*8462SApril.Chin@Sun.COM { 75*8462SApril.Chin@Sun.COM aq->scope = (void*)dtopen(&_Nvdisc,Dtoset); 76*8462SApril.Chin@Sun.COM dtview((Dt_t*)aq->scope,aq->table); 77*8462SApril.Chin@Sun.COM aq->table = (Dt_t*)aq->scope; 78*8462SApril.Chin@Sun.COM return(aq); 79*8462SApril.Chin@Sun.COM } 80*8462SApril.Chin@Sun.COM aq->scope = (void*)ap; 81*8462SApril.Chin@Sun.COM ar = (struct index_array*)aq; 82*8462SApril.Chin@Sun.COM memset(ar->val, 0, ar->maxi*sizeof(char*)); 83*8462SApril.Chin@Sun.COM return(aq); 84*8462SApril.Chin@Sun.COM } 85*8462SApril.Chin@Sun.COM 86*8462SApril.Chin@Sun.COM static int array_unscope(Namval_t *np,Namarr_t *ap) 87*8462SApril.Chin@Sun.COM { 88*8462SApril.Chin@Sun.COM Namfun_t *fp; 89*8462SApril.Chin@Sun.COM if(!ap->scope) 90*8462SApril.Chin@Sun.COM return(0); 91*8462SApril.Chin@Sun.COM if(is_associative(ap)) 92*8462SApril.Chin@Sun.COM (*ap->fun)(np, NIL(char*), NV_AFREE); 93*8462SApril.Chin@Sun.COM if((fp = nv_disc(np,(Namfun_t*)ap,NV_POP)) && !(fp->nofree&1)) 94*8462SApril.Chin@Sun.COM free((void*)fp); 95*8462SApril.Chin@Sun.COM nv_delete(np,(Dt_t*)0,0); 96*8462SApril.Chin@Sun.COM return(1); 97*8462SApril.Chin@Sun.COM } 98*8462SApril.Chin@Sun.COM 99*8462SApril.Chin@Sun.COM static void array_syncsub(Namarr_t *ap, Namarr_t *aq) 100*8462SApril.Chin@Sun.COM { 101*8462SApril.Chin@Sun.COM ((struct index_array*)ap)->cur = ((struct index_array*)aq)->cur; 102*8462SApril.Chin@Sun.COM } 103*8462SApril.Chin@Sun.COM 104*8462SApril.Chin@Sun.COM static int array_covered(Namval_t *np, struct index_array *ap) 105*8462SApril.Chin@Sun.COM { 106*8462SApril.Chin@Sun.COM struct index_array *aq = (struct index_array*)ap->header.scope; 107*8462SApril.Chin@Sun.COM if(!ap->header.fun && aq) 108*8462SApril.Chin@Sun.COM return ((ap->cur<aq->maxi) && aq->val[ap->cur].cp); 109*8462SApril.Chin@Sun.COM return(0); 110*8462SApril.Chin@Sun.COM } 111*8462SApril.Chin@Sun.COM 1124887Schin /* 1134887Schin * replace discipline with new one 1144887Schin */ 1154887Schin static void array_setptr(register Namval_t *np, struct index_array *old, struct index_array *new) 1164887Schin { 1174887Schin register Namfun_t **fp = &np->nvfun; 1184887Schin while(*fp && *fp!= &old->header.hdr) 1194887Schin fp = &((*fp)->next); 1204887Schin if(*fp) 1214887Schin { 1224887Schin new->header.hdr.next = (*fp)->next; 1234887Schin *fp = &new->header.hdr; 1244887Schin } 1254887Schin else sfprintf(sfstderr,"discipline not replaced\n"); 1264887Schin } 1274887Schin 1284887Schin /* 1294887Schin * Calculate the amount of space to be allocated to hold an 1304887Schin * indexed array into which <maxi> is a legal index. The number of 1314887Schin * elements that will actually fit into the array (> <maxi> 1324887Schin * but <= ARRAY_MAX) is returned. 1334887Schin * 1344887Schin */ 135*8462SApril.Chin@Sun.COM static int arsize(struct index_array *ap, register int maxi) 1364887Schin { 137*8462SApril.Chin@Sun.COM if(ap && maxi < 2*ap->maxi) 138*8462SApril.Chin@Sun.COM maxi = 2*ap->maxi; 139*8462SApril.Chin@Sun.COM maxi = roundof(maxi,ARRAY_INCR); 140*8462SApril.Chin@Sun.COM return (maxi>ARRAY_MAX?ARRAY_MAX:maxi); 1414887Schin } 1424887Schin 1434887Schin static struct index_array *array_grow(Namval_t*, struct index_array*,int); 1444887Schin 1454887Schin /* return index of highest element of an array */ 1464887Schin int array_maxindex(Namval_t *np) 1474887Schin { 1484887Schin register struct index_array *ap = (struct index_array*)nv_arrayptr(np); 1494887Schin register int i = ap->maxi; 1504887Schin if(is_associative(ap)) 1514887Schin return(-1); 1524887Schin while(i>0 && ap->val[--i].cp==0); 1534887Schin return(i+1); 1544887Schin } 1554887Schin 156*8462SApril.Chin@Sun.COM static union Value *array_getup(Namval_t *np, Namarr_t *arp, int update) 1574887Schin { 1584887Schin register struct index_array *ap = (struct index_array*)arp; 1594887Schin register union Value *up; 160*8462SApril.Chin@Sun.COM int nofree; 161*8462SApril.Chin@Sun.COM if(!arp) 1624887Schin return(&np->nvalue); 1634887Schin if(is_associative(ap)) 164*8462SApril.Chin@Sun.COM { 165*8462SApril.Chin@Sun.COM Namval_t *mp; 166*8462SApril.Chin@Sun.COM mp = (Namval_t*)((*arp->fun)(np,NIL(char*),NV_ACURRENT)); 167*8462SApril.Chin@Sun.COM if(mp) 168*8462SApril.Chin@Sun.COM { 169*8462SApril.Chin@Sun.COM nofree = nv_isattr(mp,NV_NOFREE); 170*8462SApril.Chin@Sun.COM up = &mp->nvalue; 171*8462SApril.Chin@Sun.COM } 172*8462SApril.Chin@Sun.COM else 173*8462SApril.Chin@Sun.COM return((union Value*)((*arp->fun)(np,NIL(char*),0))); 174*8462SApril.Chin@Sun.COM } 1754887Schin else 1764887Schin { 1774887Schin if(ap->cur >= ap->maxi) 1784887Schin errormsg(SH_DICT,ERROR_exit(1),e_subscript,nv_name(np)); 1794887Schin up = &(ap->val[ap->cur]); 180*8462SApril.Chin@Sun.COM nofree = array_isbit(ap->bits,ap->cur,ARRAY_NOFREE); 181*8462SApril.Chin@Sun.COM } 182*8462SApril.Chin@Sun.COM if(update) 183*8462SApril.Chin@Sun.COM { 184*8462SApril.Chin@Sun.COM if(nofree) 185*8462SApril.Chin@Sun.COM nv_onattr(np,NV_NOFREE); 186*8462SApril.Chin@Sun.COM else 187*8462SApril.Chin@Sun.COM nv_offattr(np,NV_NOFREE); 1884887Schin } 1894887Schin return(up); 1904887Schin } 1914887Schin 1924887Schin /* 1934887Schin * Get the Value pointer for an array. 1944887Schin * Delete space as necessary if flag is ARRAY_DELETE 1954887Schin * After the lookup is done the last @ or * subscript is incremented 1964887Schin */ 1974887Schin static Namval_t *array_find(Namval_t *np,Namarr_t *arp, int flag) 1984887Schin { 1994887Schin register struct index_array *ap = (struct index_array*)arp; 2004887Schin register union Value *up; 2014887Schin Namval_t *mp; 2024887Schin int wasundef; 203*8462SApril.Chin@Sun.COM if(flag&ARRAY_LOOKUP) 204*8462SApril.Chin@Sun.COM ap->header.nelem &= ~ARRAY_NOSCOPE; 205*8462SApril.Chin@Sun.COM else 206*8462SApril.Chin@Sun.COM ap->header.nelem |= ARRAY_NOSCOPE; 2074887Schin if(wasundef = ap->header.nelem&ARRAY_UNDEF) 2084887Schin { 2094887Schin ap->header.nelem &= ~ARRAY_UNDEF; 2104887Schin /* delete array is the same as delete array[@] */ 2114887Schin if(flag&ARRAY_DELETE) 2124887Schin { 213*8462SApril.Chin@Sun.COM nv_putsub(np, NIL(char*), ARRAY_SCAN|ARRAY_NOSCOPE); 2144887Schin ap->header.nelem |= ARRAY_SCAN; 2154887Schin } 2164887Schin else /* same as array[0] */ 2174887Schin { 2184887Schin if(is_associative(ap)) 2194887Schin (*ap->header.fun)(np,"0",flag==ARRAY_ASSIGN?NV_AADD:0); 2204887Schin else 2214887Schin ap->cur = 0; 2224887Schin } 2234887Schin } 2244887Schin if(is_associative(ap)) 2254887Schin { 2264887Schin mp = (Namval_t*)((*arp->fun)(np,NIL(char*),NV_ACURRENT)); 2274887Schin if(!mp) 2284887Schin up = (union Value*)∓ 229*8462SApril.Chin@Sun.COM else if(nv_isarray(mp)) 2304887Schin { 231*8462SApril.Chin@Sun.COM if(wasundef) 232*8462SApril.Chin@Sun.COM nv_putsub(mp,NIL(char*),ARRAY_UNDEF); 233*8462SApril.Chin@Sun.COM return(mp); 2344887Schin } 2354887Schin else 236*8462SApril.Chin@Sun.COM { 2374887Schin up = &mp->nvalue; 238*8462SApril.Chin@Sun.COM if(nv_isvtree(mp)) 239*8462SApril.Chin@Sun.COM { 240*8462SApril.Chin@Sun.COM if(!up->cp && flag==ARRAY_ASSIGN) 241*8462SApril.Chin@Sun.COM { 242*8462SApril.Chin@Sun.COM nv_arraychild(np,mp,0); 243*8462SApril.Chin@Sun.COM ap->header.nelem++; 244*8462SApril.Chin@Sun.COM } 245*8462SApril.Chin@Sun.COM return(mp); 246*8462SApril.Chin@Sun.COM } 247*8462SApril.Chin@Sun.COM } 2484887Schin } 2494887Schin else 2504887Schin { 2514887Schin if(!(ap->header.nelem&ARRAY_SCAN) && ap->cur >= ap->maxi) 2524887Schin ap = array_grow(np, ap, (int)ap->cur); 2534887Schin if(ap->cur>=ap->maxi) 2544887Schin errormsg(SH_DICT,ERROR_exit(1),e_subscript,nv_name(np)); 2554887Schin up = &(ap->val[ap->cur]); 256*8462SApril.Chin@Sun.COM if((!up->cp||up->cp==Empty) && nv_type(np) && nv_isvtree(np)) 257*8462SApril.Chin@Sun.COM { 258*8462SApril.Chin@Sun.COM char *cp; 259*8462SApril.Chin@Sun.COM if(!ap->header.table) 260*8462SApril.Chin@Sun.COM ap->header.table = dtopen(&_Nvdisc,Dtoset); 261*8462SApril.Chin@Sun.COM sfprintf(sh.strbuf,"%d",ap->cur); 262*8462SApril.Chin@Sun.COM cp = sfstruse(sh.strbuf); 263*8462SApril.Chin@Sun.COM mp = nv_search(cp, ap->header.table, NV_ADD); 264*8462SApril.Chin@Sun.COM mp->nvenv = (char*)np; 265*8462SApril.Chin@Sun.COM nv_arraychild(np,mp,0); 266*8462SApril.Chin@Sun.COM } 267*8462SApril.Chin@Sun.COM if(up->np && array_isbit(ap->bits,ap->cur,ARRAY_CHILD)) 2684887Schin { 2694887Schin if(wasundef && nv_isarray(up->np)) 2704887Schin nv_putsub(up->np,NIL(char*),ARRAY_UNDEF); 2714887Schin return(up->np); 2724887Schin } 2734887Schin } 2744887Schin np->nvalue.cp = up->cp; 2754887Schin if(!up->cp) 2764887Schin { 2774887Schin if(flag!=ARRAY_ASSIGN) 2784887Schin return(0); 279*8462SApril.Chin@Sun.COM if(!array_covered(np,ap)) 280*8462SApril.Chin@Sun.COM ap->header.nelem++; 2814887Schin } 2824887Schin return(np); 2834887Schin } 2844887Schin 285*8462SApril.Chin@Sun.COM #if SHOPT_TYPEDEF 286*8462SApril.Chin@Sun.COM int nv_arraysettype(Namval_t *np, Namval_t *tp, const char *sub, int flags) 287*8462SApril.Chin@Sun.COM { 288*8462SApril.Chin@Sun.COM Namval_t *nq; 289*8462SApril.Chin@Sun.COM char *av[2]; 290*8462SApril.Chin@Sun.COM int rdonly = nv_isattr(np,NV_RDONLY); 291*8462SApril.Chin@Sun.COM int xtrace = sh_isoption(SH_XTRACE); 292*8462SApril.Chin@Sun.COM Namarr_t *ap = nv_arrayptr(np); 293*8462SApril.Chin@Sun.COM av[1] = 0; 294*8462SApril.Chin@Sun.COM sh.last_table = 0; 295*8462SApril.Chin@Sun.COM if(!ap->table) 296*8462SApril.Chin@Sun.COM ap->table = dtopen(&_Nvdisc,Dtoset); 297*8462SApril.Chin@Sun.COM if(nq = nv_search(sub, ap->table, NV_ADD)) 298*8462SApril.Chin@Sun.COM { 299*8462SApril.Chin@Sun.COM if(!nq->nvfun && nq->nvalue.cp && *nq->nvalue.cp==0) 300*8462SApril.Chin@Sun.COM _nv_unset(nq,NV_RDONLY); 301*8462SApril.Chin@Sun.COM nv_arraychild(np,nq,0); 302*8462SApril.Chin@Sun.COM if(!nv_isattr(tp,NV_BINARY)) 303*8462SApril.Chin@Sun.COM { 304*8462SApril.Chin@Sun.COM sfprintf(sh.strbuf,"%s=%s",nv_name(nq),nv_getval(np)); 305*8462SApril.Chin@Sun.COM av[0] = strdup(sfstruse(sh.strbuf)); 306*8462SApril.Chin@Sun.COM } 307*8462SApril.Chin@Sun.COM if(!nv_clone(tp,nq,flags|NV_NOFREE)) 308*8462SApril.Chin@Sun.COM return(0); 309*8462SApril.Chin@Sun.COM ap->nelem |= ARRAY_SCAN; 310*8462SApril.Chin@Sun.COM if(!rdonly) 311*8462SApril.Chin@Sun.COM nv_offattr(nq,NV_RDONLY); 312*8462SApril.Chin@Sun.COM if(!nv_isattr(tp,NV_BINARY)) 313*8462SApril.Chin@Sun.COM { 314*8462SApril.Chin@Sun.COM if(xtrace) 315*8462SApril.Chin@Sun.COM sh_offoption(SH_XTRACE); 316*8462SApril.Chin@Sun.COM ap->nelem &= ~ARRAY_SCAN; 317*8462SApril.Chin@Sun.COM sh_eval(sh_sfeval(av),0); 318*8462SApril.Chin@Sun.COM ap->nelem |= ARRAY_SCAN; 319*8462SApril.Chin@Sun.COM free((void*)av[0]); 320*8462SApril.Chin@Sun.COM if(xtrace) 321*8462SApril.Chin@Sun.COM sh_onoption(SH_XTRACE); 322*8462SApril.Chin@Sun.COM } 323*8462SApril.Chin@Sun.COM return(1); 324*8462SApril.Chin@Sun.COM } 325*8462SApril.Chin@Sun.COM return(0); 326*8462SApril.Chin@Sun.COM } 327*8462SApril.Chin@Sun.COM #endif /* SHOPT_TYPEDEF */ 328*8462SApril.Chin@Sun.COM 329*8462SApril.Chin@Sun.COM 3304887Schin static Namfun_t *array_clone(Namval_t *np, Namval_t *mp, int flags, Namfun_t *fp) 3314887Schin { 3324887Schin Namarr_t *ap = (Namarr_t*)fp; 3334887Schin Namval_t *nq, *mq; 3344887Schin char *name, *sub=0; 335*8462SApril.Chin@Sun.COM int nelem, skipped=0; 336*8462SApril.Chin@Sun.COM Dt_t *otable=ap->table; 337*8462SApril.Chin@Sun.COM struct index_array *aq = (struct index_array*)ap, *ar; 338*8462SApril.Chin@Sun.COM Shell_t *shp = sh_getinterp(); 339*8462SApril.Chin@Sun.COM if(flags&NV_MOVE) 340*8462SApril.Chin@Sun.COM { 341*8462SApril.Chin@Sun.COM if((flags&NV_COMVAR) && nv_putsub(np,NIL(char*),ARRAY_SCAN)) 342*8462SApril.Chin@Sun.COM { 343*8462SApril.Chin@Sun.COM do 344*8462SApril.Chin@Sun.COM { 345*8462SApril.Chin@Sun.COM if(nq=nv_opensub(np)) 346*8462SApril.Chin@Sun.COM nq->nvenv = (void*)mp; 347*8462SApril.Chin@Sun.COM } 348*8462SApril.Chin@Sun.COM while(nv_nextsub(np)); 349*8462SApril.Chin@Sun.COM } 350*8462SApril.Chin@Sun.COM return(fp); 351*8462SApril.Chin@Sun.COM } 352*8462SApril.Chin@Sun.COM nelem = ap->nelem; 3534887Schin if(nelem&ARRAY_NOCLONE) 3544887Schin return(0); 355*8462SApril.Chin@Sun.COM if((flags&NV_TYPE) && !ap->scope) 356*8462SApril.Chin@Sun.COM { 357*8462SApril.Chin@Sun.COM ap = array_scope(np,ap,flags); 358*8462SApril.Chin@Sun.COM return(&ap->hdr); 359*8462SApril.Chin@Sun.COM } 360*8462SApril.Chin@Sun.COM ap = (Namarr_t*)nv_clone_disc(fp,0); 361*8462SApril.Chin@Sun.COM if(flags&NV_COMVAR) 3624887Schin { 363*8462SApril.Chin@Sun.COM ap->scope = 0; 364*8462SApril.Chin@Sun.COM ap->nelem = 0; 365*8462SApril.Chin@Sun.COM sh.prev_table = sh.last_table; 366*8462SApril.Chin@Sun.COM sh.prev_root = sh.last_root; 3674887Schin } 368*8462SApril.Chin@Sun.COM if(ap->table) 369*8462SApril.Chin@Sun.COM { 370*8462SApril.Chin@Sun.COM ap->table = dtopen(&_Nvdisc,Dtoset); 371*8462SApril.Chin@Sun.COM if(ap->scope && !(flags&NV_COMVAR)) 372*8462SApril.Chin@Sun.COM { 373*8462SApril.Chin@Sun.COM ap->scope = ap->table; 374*8462SApril.Chin@Sun.COM dtview(ap->table, otable->view); 375*8462SApril.Chin@Sun.COM } 376*8462SApril.Chin@Sun.COM } 377*8462SApril.Chin@Sun.COM mp->nvfun = (Namfun_t*)ap; 378*8462SApril.Chin@Sun.COM mp->nvflag &= NV_MINIMAL; 379*8462SApril.Chin@Sun.COM mp->nvflag |= (np->nvflag&~(NV_MINIMAL|NV_NOFREE)); 3804887Schin if(!(nelem&(ARRAY_SCAN|ARRAY_UNDEF)) && (sub=nv_getsub(np))) 3814887Schin sub = strdup(sub); 3824887Schin ar = (struct index_array*)ap; 383*8462SApril.Chin@Sun.COM if(!is_associative(ap)) 384*8462SApril.Chin@Sun.COM ar->bits = (unsigned char*)&ar->val[ar->maxi]; 385*8462SApril.Chin@Sun.COM if(!nv_putsub(np,NIL(char*),ARRAY_SCAN|((flags&NV_COMVAR)?0:ARRAY_NOSCOPE))) 386*8462SApril.Chin@Sun.COM { 387*8462SApril.Chin@Sun.COM if(ap->fun) 388*8462SApril.Chin@Sun.COM (*ap->fun)(np,(char*)np,0); 389*8462SApril.Chin@Sun.COM skipped=1; 390*8462SApril.Chin@Sun.COM goto skip; 391*8462SApril.Chin@Sun.COM } 3924887Schin do 3934887Schin { 394*8462SApril.Chin@Sun.COM name = nv_getsub(np); 395*8462SApril.Chin@Sun.COM nv_putsub(mp,name,ARRAY_ADD|ARRAY_NOSCOPE); 396*8462SApril.Chin@Sun.COM mq = 0; 397*8462SApril.Chin@Sun.COM if(nq=nv_opensub(np)) 398*8462SApril.Chin@Sun.COM mq = nv_search(name,ap->table,NV_ADD); 399*8462SApril.Chin@Sun.COM if(nq && (flags&NV_COMVAR) && nv_isvtree(nq)) 4004887Schin { 401*8462SApril.Chin@Sun.COM mq->nvalue.cp = 0; 402*8462SApril.Chin@Sun.COM if(!is_associative(ap)) 403*8462SApril.Chin@Sun.COM ar->val[ar->cur].np = mq; 404*8462SApril.Chin@Sun.COM nv_clone(nq,mq,flags); 405*8462SApril.Chin@Sun.COM } 406*8462SApril.Chin@Sun.COM else if(flags&NV_ARRAY) 407*8462SApril.Chin@Sun.COM { 408*8462SApril.Chin@Sun.COM if((flags&NV_NOFREE) && !is_associative(ap)) 409*8462SApril.Chin@Sun.COM array_setbit(aq->bits,aq->cur,ARRAY_NOFREE); 410*8462SApril.Chin@Sun.COM else if(nq && (flags&NV_NOFREE)) 4114887Schin { 412*8462SApril.Chin@Sun.COM mq->nvalue = nq->nvalue; 413*8462SApril.Chin@Sun.COM nv_onattr(nq,NV_NOFREE); 4144887Schin } 4154887Schin } 4164887Schin else if(nv_isattr(np,NV_INTEGER)) 4174887Schin { 4184887Schin Sfdouble_t d= nv_getnum(np); 419*8462SApril.Chin@Sun.COM if(!is_associative(ap)) 420*8462SApril.Chin@Sun.COM ar->val[ar->cur].cp = 0; 4214887Schin nv_putval(mp,(char*)&d,NV_LDOUBLE); 4224887Schin } 4234887Schin else 424*8462SApril.Chin@Sun.COM { 425*8462SApril.Chin@Sun.COM if(!is_associative(ap)) 426*8462SApril.Chin@Sun.COM ar->val[ar->cur].cp = 0; 4274887Schin nv_putval(mp,nv_getval(np),NV_RDONLY); 428*8462SApril.Chin@Sun.COM } 429*8462SApril.Chin@Sun.COM aq->header.nelem |= ARRAY_NOSCOPE; 4304887Schin } 4314887Schin while(nv_nextsub(np)); 432*8462SApril.Chin@Sun.COM skip: 4334887Schin if(sub) 4344887Schin { 435*8462SApril.Chin@Sun.COM if(!skipped) 436*8462SApril.Chin@Sun.COM nv_putsub(np,sub,0L); 4374887Schin free((void*)sub); 4384887Schin } 439*8462SApril.Chin@Sun.COM aq->header.nelem = ap->nelem = nelem; 440*8462SApril.Chin@Sun.COM return(&ap->hdr); 4414887Schin } 4424887Schin 4434887Schin static char *array_getval(Namval_t *np, Namfun_t *disc) 4444887Schin { 445*8462SApril.Chin@Sun.COM register Namarr_t *aq,*ap = (Namarr_t*)disc; 4464887Schin register Namval_t *mp; 4474887Schin if((mp=array_find(np,ap,ARRAY_LOOKUP))!=np) 448*8462SApril.Chin@Sun.COM { 449*8462SApril.Chin@Sun.COM if(!mp && !is_associative(ap) && (aq=(Namarr_t*)ap->scope)) 450*8462SApril.Chin@Sun.COM { 451*8462SApril.Chin@Sun.COM array_syncsub(aq,ap); 452*8462SApril.Chin@Sun.COM if((mp=array_find(np,aq,ARRAY_LOOKUP))==np) 453*8462SApril.Chin@Sun.COM return(nv_getv(np,&aq->hdr)); 454*8462SApril.Chin@Sun.COM } 4554887Schin return(mp?nv_getval(mp):0); 456*8462SApril.Chin@Sun.COM } 4574887Schin return(nv_getv(np,&ap->hdr)); 4584887Schin } 4594887Schin 4604887Schin static Sfdouble_t array_getnum(Namval_t *np, Namfun_t *disc) 4614887Schin { 462*8462SApril.Chin@Sun.COM register Namarr_t *aq,*ap = (Namarr_t*)disc; 4634887Schin register Namval_t *mp; 4644887Schin if((mp=array_find(np,ap,ARRAY_LOOKUP))!=np) 465*8462SApril.Chin@Sun.COM { 466*8462SApril.Chin@Sun.COM if(!mp && !is_associative(ap) && (aq=(Namarr_t*)ap->scope)) 467*8462SApril.Chin@Sun.COM { 468*8462SApril.Chin@Sun.COM array_syncsub(aq,ap); 469*8462SApril.Chin@Sun.COM if((mp=array_find(np,aq,ARRAY_LOOKUP))==np) 470*8462SApril.Chin@Sun.COM return(nv_getn(np,&aq->hdr)); 471*8462SApril.Chin@Sun.COM } 4724887Schin return(mp?nv_getnum(mp):0); 473*8462SApril.Chin@Sun.COM } 4744887Schin return(nv_getn(np,&ap->hdr)); 4754887Schin } 4764887Schin 4774887Schin static void array_putval(Namval_t *np, const char *string, int flags, Namfun_t *dp) 4784887Schin { 4794887Schin register Namarr_t *ap = (Namarr_t*)dp; 4804887Schin register union Value *up; 4814887Schin register Namval_t *mp; 4824887Schin register struct index_array *aq = (struct index_array*)ap; 483*8462SApril.Chin@Sun.COM int scan,nofree = nv_isattr(np,NV_NOFREE); 4844887Schin do 4854887Schin { 4864887Schin mp = array_find(np,ap,string?ARRAY_ASSIGN:ARRAY_DELETE); 487*8462SApril.Chin@Sun.COM scan = ap->nelem&ARRAY_SCAN; 4884887Schin if(mp && mp!=np) 489*8462SApril.Chin@Sun.COM { 490*8462SApril.Chin@Sun.COM if(!is_associative(ap) && string && !nv_type(np) && nv_isvtree(mp)) 491*8462SApril.Chin@Sun.COM { 492*8462SApril.Chin@Sun.COM if(!nv_isattr(np,NV_NOFREE)) 493*8462SApril.Chin@Sun.COM _nv_unset(mp,flags&NV_RDONLY); 494*8462SApril.Chin@Sun.COM array_clrbit(aq->bits,aq->cur,ARRAY_CHILD); 495*8462SApril.Chin@Sun.COM aq->val[aq->cur].cp = 0; 496*8462SApril.Chin@Sun.COM if(!nv_isattr(mp,NV_NOFREE)) 497*8462SApril.Chin@Sun.COM nv_delete(mp,ap->table,0); 498*8462SApril.Chin@Sun.COM goto skip; 499*8462SApril.Chin@Sun.COM } 5004887Schin nv_putval(mp, string, flags); 501*8462SApril.Chin@Sun.COM if(string) 502*8462SApril.Chin@Sun.COM { 503*8462SApril.Chin@Sun.COM #if SHOPT_TYPEDEF 504*8462SApril.Chin@Sun.COM if(ap->hdr.type && ap->hdr.type!=nv_type(mp)) 505*8462SApril.Chin@Sun.COM nv_arraysettype(np,ap->hdr.type,nv_getsub(np),0); 506*8462SApril.Chin@Sun.COM #endif /* SHOPT_TYPEDEF */ 507*8462SApril.Chin@Sun.COM continue; 508*8462SApril.Chin@Sun.COM } 509*8462SApril.Chin@Sun.COM ap->nelem |= scan; 510*8462SApril.Chin@Sun.COM } 5114887Schin if(!string) 5124887Schin { 5134887Schin if(mp) 5144887Schin { 515*8462SApril.Chin@Sun.COM if(is_associative(ap)) 5164887Schin { 5174887Schin (*ap->fun)(np,NIL(char*),NV_ADELETE); 518*8462SApril.Chin@Sun.COM np->nvalue.cp = 0; 519*8462SApril.Chin@Sun.COM } 520*8462SApril.Chin@Sun.COM else 5214887Schin { 522*8462SApril.Chin@Sun.COM if(mp!=np) 523*8462SApril.Chin@Sun.COM { 524*8462SApril.Chin@Sun.COM array_clrbit(aq->bits,aq->cur,ARRAY_CHILD); 525*8462SApril.Chin@Sun.COM aq->val[aq->cur].cp = 0; 526*8462SApril.Chin@Sun.COM nv_delete(mp,ap->table,0); 527*8462SApril.Chin@Sun.COM } 528*8462SApril.Chin@Sun.COM if(!array_covered(np,(struct index_array*)ap)) 529*8462SApril.Chin@Sun.COM ap->nelem--; 5304887Schin } 5314887Schin } 5324887Schin if(array_elem(ap)==0 && ((ap->nelem&ARRAY_SCAN) || !is_associative(ap))) 5334887Schin { 5344887Schin if(is_associative(ap)) 5354887Schin (*ap->fun)(np, NIL(char*), NV_AFREE); 536*8462SApril.Chin@Sun.COM else if(ap->table) 537*8462SApril.Chin@Sun.COM dtclose(ap->table); 5384887Schin nv_offattr(np,NV_ARRAY); 5394887Schin } 540*8462SApril.Chin@Sun.COM if(!mp || mp!=np || is_associative(ap)) 5414887Schin continue; 5424887Schin } 543*8462SApril.Chin@Sun.COM skip: 5444887Schin /* prevent empty string from being deleted */ 545*8462SApril.Chin@Sun.COM up = array_getup(np,ap,!nofree); 546*8462SApril.Chin@Sun.COM if(up->cp == Empty) 547*8462SApril.Chin@Sun.COM up->cp = 0; 548*8462SApril.Chin@Sun.COM if(nv_isarray(np)) 549*8462SApril.Chin@Sun.COM np->nvalue.up = up; 5504887Schin nv_putv(np,string,flags,&ap->hdr); 551*8462SApril.Chin@Sun.COM if(!is_associative(ap)) 552*8462SApril.Chin@Sun.COM { 553*8462SApril.Chin@Sun.COM if(string) 554*8462SApril.Chin@Sun.COM array_clrbit(aq->bits,aq->cur,ARRAY_NOFREE); 555*8462SApril.Chin@Sun.COM else if(mp==np) 556*8462SApril.Chin@Sun.COM aq->val[aq->cur].cp = 0; 557*8462SApril.Chin@Sun.COM } 558*8462SApril.Chin@Sun.COM #if SHOPT_TYPEDEF 559*8462SApril.Chin@Sun.COM if(string && ap->hdr.type && nv_isvtree(np)) 560*8462SApril.Chin@Sun.COM nv_arraysettype(np,ap->hdr.type,nv_getsub(np),0); 561*8462SApril.Chin@Sun.COM #endif /* SHOPT_TYPEDEF */ 5624887Schin } 5634887Schin while(!string && nv_nextsub(np)); 564*8462SApril.Chin@Sun.COM if(ap) 565*8462SApril.Chin@Sun.COM ap->nelem &= ~ARRAY_NOSCOPE; 566*8462SApril.Chin@Sun.COM if(nofree) 567*8462SApril.Chin@Sun.COM nv_onattr(np,NV_NOFREE); 568*8462SApril.Chin@Sun.COM else 569*8462SApril.Chin@Sun.COM nv_offattr(np,NV_NOFREE); 5704887Schin if(!string && !nv_isattr(np,NV_ARRAY)) 5714887Schin { 5724887Schin Namfun_t *nfp; 573*8462SApril.Chin@Sun.COM if(!is_associative(ap) && aq->xp) 574*8462SApril.Chin@Sun.COM { 575*8462SApril.Chin@Sun.COM _nv_unset(nv_namptr(aq->xp,0),NV_RDONLY); 576*8462SApril.Chin@Sun.COM free((void*)aq->xp); 577*8462SApril.Chin@Sun.COM } 578*8462SApril.Chin@Sun.COM if((nfp = nv_disc(np,(Namfun_t*)ap,NV_POP)) && !(nfp->nofree&1)) 5794887Schin free((void*)nfp); 580*8462SApril.Chin@Sun.COM if(!nv_isnull(np)) 581*8462SApril.Chin@Sun.COM { 582*8462SApril.Chin@Sun.COM nv_onattr(np,NV_NOFREE); 583*8462SApril.Chin@Sun.COM _nv_unset(np,flags); 584*8462SApril.Chin@Sun.COM } 585*8462SApril.Chin@Sun.COM if(np->nvalue.cp==Empty) 586*8462SApril.Chin@Sun.COM np->nvalue.cp = 0; 5874887Schin } 588*8462SApril.Chin@Sun.COM if(!string && (flags&NV_TYPE)) 589*8462SApril.Chin@Sun.COM array_unscope(np,ap); 5904887Schin } 5914887Schin 5924887Schin static const Namdisc_t array_disc = 5934887Schin { 5944887Schin sizeof(Namarr_t), 5954887Schin array_putval, 5964887Schin array_getval, 5974887Schin array_getnum, 5984887Schin 0, 5994887Schin 0, 6004887Schin array_clone 6014887Schin }; 6024887Schin 603*8462SApril.Chin@Sun.COM static void array_copytree(Namval_t *np, Namval_t *mp) 604*8462SApril.Chin@Sun.COM { 605*8462SApril.Chin@Sun.COM char *val; 606*8462SApril.Chin@Sun.COM Namfun_t *fp = nv_disc(np,NULL,NV_POP); 607*8462SApril.Chin@Sun.COM nv_offattr(np,NV_ARRAY); 608*8462SApril.Chin@Sun.COM nv_clone(np,mp,0); 609*8462SApril.Chin@Sun.COM np->nvalue.up = &mp->nvalue; 610*8462SApril.Chin@Sun.COM val = sfstruse(sh.strbuf); 611*8462SApril.Chin@Sun.COM fp->nofree &= ~1; 612*8462SApril.Chin@Sun.COM nv_disc(np,(Namfun_t*)fp, NV_FIRST); 613*8462SApril.Chin@Sun.COM fp->nofree |= 1; 614*8462SApril.Chin@Sun.COM nv_onattr(np,NV_ARRAY); 615*8462SApril.Chin@Sun.COM mp->nvenv = (char*)np; 616*8462SApril.Chin@Sun.COM } 617*8462SApril.Chin@Sun.COM 6184887Schin /* 6194887Schin * Increase the size of the indexed array of elements in <arp> 6204887Schin * so that <maxi> is a legal index. If <arp> is 0, an array 6214887Schin * of the required size is allocated. A pointer to the 6224887Schin * allocated Namarr_t structure is returned. 6234887Schin * <maxi> becomes the current index of the array. 6244887Schin */ 6254887Schin static struct index_array *array_grow(Namval_t *np, register struct index_array *arp,int maxi) 6264887Schin { 6274887Schin register struct index_array *ap; 628*8462SApril.Chin@Sun.COM register int i; 629*8462SApril.Chin@Sun.COM register int newsize = arsize(arp,maxi+1); 6304887Schin if (maxi >= ARRAY_MAX) 6314887Schin errormsg(SH_DICT,ERROR_exit(1),e_subscript, fmtbase((long)maxi,10,0)); 632*8462SApril.Chin@Sun.COM i = (newsize-1)*sizeof(union Value*)+newsize; 633*8462SApril.Chin@Sun.COM ap = new_of(struct index_array,i); 634*8462SApril.Chin@Sun.COM memset((void*)ap,0,sizeof(*ap)+i); 6354887Schin ap->maxi = newsize; 6364887Schin ap->cur = maxi; 6374887Schin ap->bits = (unsigned char*)&ap->val[newsize]; 638*8462SApril.Chin@Sun.COM memset(ap->bits, 0, newsize); 6394887Schin if(arp) 6404887Schin { 6414887Schin ap->header = arp->header; 642*8462SApril.Chin@Sun.COM ap->header.hdr.dsize = sizeof(*ap) + i; 643*8462SApril.Chin@Sun.COM for(i=0;i < arp->maxi;i++) 6444887Schin ap->val[i].cp = arp->val[i].cp; 645*8462SApril.Chin@Sun.COM memcpy(ap->bits, arp->bits, arp->maxi); 6464887Schin array_setptr(np,arp,ap); 6474887Schin free((void*)arp); 6484887Schin } 6494887Schin else 6504887Schin { 651*8462SApril.Chin@Sun.COM Namval_t *mp=0; 652*8462SApril.Chin@Sun.COM ap->header.hdr.dsize = sizeof(*ap) + i; 653*8462SApril.Chin@Sun.COM i = 0; 6544887Schin ap->header.fun = 0; 655*8462SApril.Chin@Sun.COM if(nv_isnull(np) && nv_isattr(np,NV_NOFREE)) 6564887Schin { 657*8462SApril.Chin@Sun.COM i = ARRAY_TREE; 658*8462SApril.Chin@Sun.COM nv_offattr(np,NV_NOFREE); 659*8462SApril.Chin@Sun.COM } 660*8462SApril.Chin@Sun.COM if(np->nvalue.cp==Empty) 661*8462SApril.Chin@Sun.COM np->nvalue.cp=0; 662*8462SApril.Chin@Sun.COM if(nv_hasdisc(np,&array_disc) || nv_isvtree(np)) 663*8462SApril.Chin@Sun.COM { 664*8462SApril.Chin@Sun.COM ap->header.table = dtopen(&_Nvdisc,Dtoset); 665*8462SApril.Chin@Sun.COM mp = nv_search("0", ap->header.table, 0); 666*8462SApril.Chin@Sun.COM 6674887Schin if(mp && nv_isnull(mp)) 6684887Schin { 669*8462SApril.Chin@Sun.COM Namfun_t *fp; 6704887Schin ap->val[0].np = mp; 671*8462SApril.Chin@Sun.COM array_setbit(ap->bits,0,ARRAY_CHILD); 672*8462SApril.Chin@Sun.COM for(fp=np->nvfun; fp && !fp->disc->readf; fp=fp->next); 673*8462SApril.Chin@Sun.COM if(fp) 674*8462SApril.Chin@Sun.COM (*fp->disc->readf)(mp,(Sfio_t*)0,0,fp); 675*8462SApril.Chin@Sun.COM i++; 6764887Schin } 677*8462SApril.Chin@Sun.COM } 678*8462SApril.Chin@Sun.COM else if((ap->val[0].cp=np->nvalue.cp)) 6794887Schin i++; 6804887Schin else if(nv_isattr(np,NV_INTEGER)) 6814887Schin { 6824887Schin Sfdouble_t d= nv_getnum(np); 6834887Schin i++; 6844887Schin } 6854887Schin ap->header.nelem = i; 6864887Schin ap->header.hdr.disc = &array_disc; 687*8462SApril.Chin@Sun.COM nv_disc(np,(Namfun_t*)ap, NV_FIRST); 688*8462SApril.Chin@Sun.COM nv_onattr(np,NV_ARRAY); 689*8462SApril.Chin@Sun.COM if(mp) 690*8462SApril.Chin@Sun.COM { 691*8462SApril.Chin@Sun.COM array_copytree(np,mp); 692*8462SApril.Chin@Sun.COM ap->header.hdr.nofree &= ~1; 693*8462SApril.Chin@Sun.COM } 6944887Schin } 6954887Schin for(;i < newsize;i++) 6964887Schin ap->val[i].cp = 0; 6974887Schin return(ap); 6984887Schin } 6994887Schin 700*8462SApril.Chin@Sun.COM int nv_atypeindex(Namval_t *np, const char *tname) 701*8462SApril.Chin@Sun.COM { 702*8462SApril.Chin@Sun.COM Namval_t *tp; 703*8462SApril.Chin@Sun.COM int offset = staktell(); 704*8462SApril.Chin@Sun.COM int n = strlen(tname)-1; 705*8462SApril.Chin@Sun.COM sfprintf(stkstd,"%s.%.*s%c",NV_CLASS,n,tname,0); 706*8462SApril.Chin@Sun.COM tp = nv_open(stakptr(offset), sh.var_tree, NV_NOADD|NV_VARNAME); 707*8462SApril.Chin@Sun.COM stakseek(offset); 708*8462SApril.Chin@Sun.COM if(tp) 709*8462SApril.Chin@Sun.COM { 710*8462SApril.Chin@Sun.COM struct index_array *ap = (struct index_array*)nv_arrayptr(np); 711*8462SApril.Chin@Sun.COM if(!nv_hasdisc(tp,&ENUM_disc)) 712*8462SApril.Chin@Sun.COM errormsg(SH_DICT,ERROR_exit(1),e_notenum,tp->nvname); 713*8462SApril.Chin@Sun.COM if(!ap) 714*8462SApril.Chin@Sun.COM ap = array_grow(np,ap,1); 715*8462SApril.Chin@Sun.COM ap->xp = calloc(NV_MINSZ,1); 716*8462SApril.Chin@Sun.COM np = nv_namptr(ap->xp,0); 717*8462SApril.Chin@Sun.COM np->nvname = tp->nvname; 718*8462SApril.Chin@Sun.COM nv_onattr(np,NV_MINIMAL); 719*8462SApril.Chin@Sun.COM nv_clone(tp,np,NV_NOFREE); 720*8462SApril.Chin@Sun.COM nv_offattr(np,NV_RDONLY); 721*8462SApril.Chin@Sun.COM return(1); 722*8462SApril.Chin@Sun.COM } 723*8462SApril.Chin@Sun.COM errormsg(SH_DICT,ERROR_exit(1),e_unknowntype, n,tname); 724*8462SApril.Chin@Sun.COM return(0); 725*8462SApril.Chin@Sun.COM } 726*8462SApril.Chin@Sun.COM 7274887Schin Namarr_t *nv_arrayptr(register Namval_t *np) 7284887Schin { 7294887Schin if(nv_isattr(np,NV_ARRAY)) 7304887Schin return((Namarr_t*)nv_hasdisc(np, &array_disc)); 7314887Schin return(0); 7324887Schin } 7334887Schin 7344887Schin /* 7354887Schin * Verify that argument is an indexed array and convert to associative, 7364887Schin * freeing relevant storage 7374887Schin */ 7384887Schin static Namarr_t *nv_changearray(Namval_t *np, void *(*fun)(Namval_t*,const char*,int)) 7394887Schin { 7404887Schin register Namarr_t *ap; 7414887Schin char numbuff[NUMSIZE+1]; 7424887Schin unsigned dot, digit, n; 7434887Schin union Value *up; 7444887Schin struct index_array *save_ap; 7454887Schin register char *string_index=&numbuff[NUMSIZE]; 7464887Schin numbuff[NUMSIZE]='\0'; 7474887Schin 7484887Schin if(!fun || !(ap = nv_arrayptr(np)) || is_associative(ap)) 7494887Schin return(NIL(Namarr_t*)); 7504887Schin 7514887Schin nv_stack(np,&ap->hdr); 7524887Schin save_ap = (struct index_array*)nv_stack(np,0); 7534887Schin ap = (Namarr_t*)((*fun)(np, NIL(char*), NV_AINIT)); 7544887Schin ap->nelem = 0; 7554887Schin ap->fun = fun; 7564887Schin nv_onattr(np,NV_ARRAY); 7574887Schin 7584887Schin for(dot = 0; dot < (unsigned)save_ap->maxi; dot++) 7594887Schin { 7604887Schin if(save_ap->val[dot].cp) 7614887Schin { 7624887Schin if ((digit = dot)== 0) 7634887Schin *--string_index = '0'; 7644887Schin else while( n = digit ) 7654887Schin { 7664887Schin digit /= 10; 7674887Schin *--string_index = '0' + (n-10*digit); 7684887Schin } 7694887Schin nv_putsub(np, string_index, ARRAY_ADD); 7704887Schin up = (union Value*)((*ap->fun)(np,NIL(char*),0)); 7714887Schin up->cp = save_ap->val[dot].cp; 7724887Schin save_ap->val[dot].cp = 0; 7734887Schin } 7744887Schin string_index = &numbuff[NUMSIZE]; 7754887Schin } 7764887Schin free((void*)save_ap); 7774887Schin return(ap); 7784887Schin } 7794887Schin 7804887Schin /* 7814887Schin * set the associative array processing method for node <np> to <fun> 7824887Schin * The array pointer is returned if sucessful. 7834887Schin */ 7844887Schin Namarr_t *nv_setarray(Namval_t *np, void *(*fun)(Namval_t*,const char*,int)) 7854887Schin { 7864887Schin register Namarr_t *ap; 787*8462SApril.Chin@Sun.COM char *value=0; 788*8462SApril.Chin@Sun.COM Namfun_t *fp; 789*8462SApril.Chin@Sun.COM int nelem = 0; 7904887Schin if(fun && (ap = nv_arrayptr(np))) 7914887Schin { 7924887Schin /* 7934887Schin * if it's already an indexed array, convert to 7944887Schin * associative structure 7954887Schin */ 7964887Schin if(!is_associative(ap)) 7974887Schin ap = nv_changearray(np, fun); 7984887Schin return(ap); 7994887Schin } 800*8462SApril.Chin@Sun.COM if(nv_isnull(np) && nv_isattr(np,NV_NOFREE)) 801*8462SApril.Chin@Sun.COM { 802*8462SApril.Chin@Sun.COM nelem = ARRAY_TREE; 803*8462SApril.Chin@Sun.COM nv_offattr(np,NV_NOFREE); 804*8462SApril.Chin@Sun.COM } 805*8462SApril.Chin@Sun.COM if(!(fp=nv_isvtree(np))) 806*8462SApril.Chin@Sun.COM value = nv_getval(np); 8074887Schin if(fun && !ap && (ap = (Namarr_t*)((*fun)(np, NIL(char*), NV_AINIT)))) 8084887Schin { 8094887Schin /* check for preexisting initialization and save */ 810*8462SApril.Chin@Sun.COM ap->nelem = nelem; 8114887Schin ap->fun = fun; 8124887Schin nv_onattr(np,NV_ARRAY); 813*8462SApril.Chin@Sun.COM if(fp || value) 8144887Schin { 8154887Schin nv_putsub(np, "0", ARRAY_ADD); 816*8462SApril.Chin@Sun.COM if(value) 817*8462SApril.Chin@Sun.COM nv_putval(np, value, 0); 818*8462SApril.Chin@Sun.COM else 819*8462SApril.Chin@Sun.COM { 820*8462SApril.Chin@Sun.COM Namval_t *mp = (Namval_t*)((*fun)(np,NIL(char*),NV_ACURRENT)); 821*8462SApril.Chin@Sun.COM array_copytree(np,mp); 822*8462SApril.Chin@Sun.COM } 8234887Schin } 8244887Schin return(ap); 8254887Schin } 8264887Schin return(NIL(Namarr_t*)); 8274887Schin } 8284887Schin 8294887Schin /* 8304887Schin * move parent subscript into child 8314887Schin */ 8324887Schin Namval_t *nv_arraychild(Namval_t *np, Namval_t *nq, int c) 8334887Schin { 834*8462SApril.Chin@Sun.COM Namfun_t *fp; 835*8462SApril.Chin@Sun.COM register Namarr_t *ap = nv_arrayptr(np); 836*8462SApril.Chin@Sun.COM union Value *up; 837*8462SApril.Chin@Sun.COM Namval_t *tp; 838*8462SApril.Chin@Sun.COM if(!nq) 839*8462SApril.Chin@Sun.COM return(ap?array_find(np,ap, ARRAY_LOOKUP):0); 840*8462SApril.Chin@Sun.COM if(!ap) 841*8462SApril.Chin@Sun.COM { 842*8462SApril.Chin@Sun.COM nv_putsub(np, NIL(char*), ARRAY_FILL); 843*8462SApril.Chin@Sun.COM ap = nv_arrayptr(np); 844*8462SApril.Chin@Sun.COM } 845*8462SApril.Chin@Sun.COM if(!(up = array_getup(np,ap,0))) 8464887Schin return((Namval_t*)0); 8474887Schin np->nvalue.cp = up->cp; 848*8462SApril.Chin@Sun.COM if((tp=nv_type(np)) || c) 8494887Schin { 850*8462SApril.Chin@Sun.COM ap->nelem |= ARRAY_NOCLONE; 851*8462SApril.Chin@Sun.COM nq->nvenv = (char*)np; 852*8462SApril.Chin@Sun.COM if(c=='t') 853*8462SApril.Chin@Sun.COM nv_clone(tp,nq, 0); 854*8462SApril.Chin@Sun.COM else 855*8462SApril.Chin@Sun.COM nv_clone(np, nq, NV_NODISC); 856*8462SApril.Chin@Sun.COM nv_offattr(nq,NV_ARRAY); 857*8462SApril.Chin@Sun.COM ap->nelem &= ~ARRAY_NOCLONE; 8584887Schin } 859*8462SApril.Chin@Sun.COM nq->nvenv = (char*)np; 860*8462SApril.Chin@Sun.COM if((fp=nq->nvfun) && fp->disc && fp->disc->setdisc && (fp = nv_disc(nq,fp,NV_POP))) 861*8462SApril.Chin@Sun.COM free((void*)fp); 862*8462SApril.Chin@Sun.COM if(!ap->fun) 8634887Schin { 8644887Schin struct index_array *aq = (struct index_array*)ap; 865*8462SApril.Chin@Sun.COM array_setbit(aq->bits,aq->cur,ARRAY_CHILD); 8664887Schin up->np = nq; 8674887Schin } 8684887Schin if(c=='.') 8694887Schin nv_setvtree(nq); 8704887Schin return(nq); 8714887Schin } 8724887Schin 8734887Schin /* 8744887Schin * This routine sets subscript of <np> to the next element, if any. 8754887Schin * The return value is zero, if there are no more elements 8764887Schin * Otherwise, 1 is returned. 8774887Schin */ 8784887Schin int nv_nextsub(Namval_t *np) 8794887Schin { 880*8462SApril.Chin@Sun.COM register struct index_array *ap = (struct index_array*)nv_arrayptr(np); 881*8462SApril.Chin@Sun.COM register unsigned dot; 882*8462SApril.Chin@Sun.COM struct index_array *aq=0, *ar=0; 8834887Schin if(!ap || !(ap->header.nelem&ARRAY_SCAN)) 8844887Schin return(0); 8854887Schin if(is_associative(ap)) 8864887Schin { 887*8462SApril.Chin@Sun.COM Namval_t *nq; 888*8462SApril.Chin@Sun.COM if(nq=(*ap->header.fun)(np,NIL(char*),NV_ANEXT)) 8894887Schin { 890*8462SApril.Chin@Sun.COM if(nv_isattr(nq,NV_CHILD)) 891*8462SApril.Chin@Sun.COM nv_putsub(nq->nvalue.np,NIL(char*),ARRAY_UNDEF); 8924887Schin return(1); 8934887Schin } 8944887Schin ap->header.nelem &= ~(ARRAY_SCAN|ARRAY_NOCHILD); 8954887Schin return(0); 8964887Schin } 897*8462SApril.Chin@Sun.COM if(!(ap->header.nelem&ARRAY_NOSCOPE)) 898*8462SApril.Chin@Sun.COM ar = (struct index_array*)ap->header.scope; 8994887Schin for(dot=ap->cur+1; dot < (unsigned)ap->maxi; dot++) 9004887Schin { 901*8462SApril.Chin@Sun.COM aq = ap; 902*8462SApril.Chin@Sun.COM if(!ap->val[dot].cp && !(ap->header.nelem&ARRAY_NOSCOPE)) 903*8462SApril.Chin@Sun.COM { 904*8462SApril.Chin@Sun.COM if(!(aq=ar) || dot>=(unsigned)aq->maxi) 905*8462SApril.Chin@Sun.COM continue; 906*8462SApril.Chin@Sun.COM } 907*8462SApril.Chin@Sun.COM if(aq->val[dot].cp) 9084887Schin { 9094887Schin ap->cur = dot; 910*8462SApril.Chin@Sun.COM if(array_isbit(aq->bits, dot,ARRAY_CHILD)) 9114887Schin { 912*8462SApril.Chin@Sun.COM Namval_t *mp = aq->val[dot].np; 913*8462SApril.Chin@Sun.COM if((aq->header.nelem&ARRAY_NOCHILD) && nv_isvtree(mp)) 9144887Schin continue; 915*8462SApril.Chin@Sun.COM nv_putsub(mp,NIL(char*),ARRAY_UNDEF); 9164887Schin } 9174887Schin return(1); 9184887Schin } 9194887Schin } 9204887Schin ap->header.nelem &= ~(ARRAY_SCAN|ARRAY_NOCHILD); 9214887Schin ap->cur = 0; 9224887Schin return(0); 9234887Schin } 9244887Schin 9254887Schin /* 9264887Schin * Set an array subscript for node <np> given the subscript <sp> 9274887Schin * An array is created if necessary. 9284887Schin * <mode> can be a number, plus or more of symbolic constants 9294887Schin * ARRAY_SCAN, ARRAY_UNDEF, ARRAY_ADD 9304887Schin * The node pointer is returned which can be NULL if <np> is 9314887Schin * not already array and the ARRAY_ADD bit of <mode> is not set. 9324887Schin * ARRAY_FILL sets the specified subscript to the empty string when 9334887Schin * ARRAY_ADD is specified and there is no value or sets all 9344887Schin * the elements up to the number specified if ARRAY_ADD is not specified 9354887Schin */ 9364887Schin Namval_t *nv_putsub(Namval_t *np,register char *sp,register long mode) 9374887Schin { 9384887Schin register struct index_array *ap = (struct index_array*)nv_arrayptr(np); 9394887Schin register int size = (mode&ARRAY_MASK); 9404887Schin if(!ap || !ap->header.fun) 9414887Schin { 9424887Schin if(sp) 943*8462SApril.Chin@Sun.COM { 944*8462SApril.Chin@Sun.COM if(ap && ap->xp && !strmatch(sp,"+([0-9])")) 945*8462SApril.Chin@Sun.COM { 946*8462SApril.Chin@Sun.COM Namval_t *mp = nv_namptr(ap->xp,0); 947*8462SApril.Chin@Sun.COM nv_putval(mp, sp,0); 948*8462SApril.Chin@Sun.COM size = nv_getnum(mp); 949*8462SApril.Chin@Sun.COM } 950*8462SApril.Chin@Sun.COM else 951*8462SApril.Chin@Sun.COM size = (int)sh_arith((char*)sp); 952*8462SApril.Chin@Sun.COM } 953*8462SApril.Chin@Sun.COM if(size <0 && ap) 954*8462SApril.Chin@Sun.COM size += array_maxindex(np); 9554887Schin if(size >= ARRAY_MAX || (size < 0)) 9564887Schin { 9574887Schin errormsg(SH_DICT,ERROR_exit(1),e_subscript, nv_name(np)); 9584887Schin return(NIL(Namval_t*)); 9594887Schin } 9604887Schin if(!ap || size>=ap->maxi) 9614887Schin { 9624887Schin if(size==0 && !(mode&ARRAY_FILL)) 9634887Schin return(NIL(Namval_t*)); 9644887Schin if(sh.subshell) 9654887Schin np = sh_assignok(np,1); 9664887Schin ap = array_grow(np, ap,size); 9674887Schin } 9684887Schin ap->header.nelem &= ~ARRAY_UNDEF; 969*8462SApril.Chin@Sun.COM ap->header.nelem |= (mode&(ARRAY_SCAN|ARRAY_NOCHILD|ARRAY_UNDEF|ARRAY_NOSCOPE)); 970*8462SApril.Chin@Sun.COM #if 0 971*8462SApril.Chin@Sun.COM if(array_isbit(ap->bits,oldsize,ARRAY_CHILD)) 972*8462SApril.Chin@Sun.COM mp = ap->val[oldsize].np; 973*8462SApril.Chin@Sun.COM if(size != oldsize && mp->nvalue.cp) 974*8462SApril.Chin@Sun.COM { 975*8462SApril.Chin@Sun.COM Namfun_t *nfp; 976*8462SApril.Chin@Sun.COM for(nfp=np->nvfun; nfp; nfp=nfp->next) 977*8462SApril.Chin@Sun.COM { 978*8462SApril.Chin@Sun.COM if(nfp->disc && nfp->disc->readf) 979*8462SApril.Chin@Sun.COM { 980*8462SApril.Chin@Sun.COM (*nfp->disc->readf)(mp,(Sfio_t*)0,0,nfp); 981*8462SApril.Chin@Sun.COM break; 982*8462SApril.Chin@Sun.COM } 983*8462SApril.Chin@Sun.COM } 984*8462SApril.Chin@Sun.COM } 985*8462SApril.Chin@Sun.COM #endif 9864887Schin ap->cur = size; 987*8462SApril.Chin@Sun.COM if((mode&ARRAY_SCAN) && (ap->cur--,!nv_nextsub(np))) 9884887Schin np = 0; 989*8462SApril.Chin@Sun.COM if(mode&(ARRAY_FILL|ARRAY_ADD)) 9904887Schin { 9914887Schin if(!(mode&ARRAY_ADD)) 9924887Schin { 9934887Schin int n; 994*8462SApril.Chin@Sun.COM for(n=0; n <= size; n++) 9954887Schin { 9964887Schin if(!ap->val[n].cp) 997*8462SApril.Chin@Sun.COM { 9984887Schin ap->val[n].cp = Empty; 999*8462SApril.Chin@Sun.COM if(!array_covered(np,ap)) 1000*8462SApril.Chin@Sun.COM ap->header.nelem++; 1001*8462SApril.Chin@Sun.COM } 10024887Schin } 10034887Schin if(n=ap->maxi-ap->maxi) 10044887Schin memset(&ap->val[size],0,n*sizeof(union Value)); 10054887Schin } 10064887Schin else if(!ap->val[size].cp) 10074887Schin { 10084887Schin if(sh.subshell) 10094887Schin np = sh_assignok(np,1); 10104887Schin ap->val[size].cp = Empty; 1011*8462SApril.Chin@Sun.COM if(!array_covered(np,ap)) 1012*8462SApril.Chin@Sun.COM ap->header.nelem++; 10134887Schin } 10144887Schin } 10154887Schin else if(!(mode&ARRAY_SCAN)) 10164887Schin { 10174887Schin ap->header.nelem &= ~ARRAY_SCAN; 1018*8462SApril.Chin@Sun.COM if(array_isbit(ap->bits,size,ARRAY_CHILD)) 10194887Schin nv_putsub(ap->val[size].np,NIL(char*),ARRAY_UNDEF); 1020*8462SApril.Chin@Sun.COM if(sp && !(mode&ARRAY_ADD) && !ap->val[size].cp) 1021*8462SApril.Chin@Sun.COM np = 0; 10224887Schin } 10234887Schin return((Namval_t*)np); 10244887Schin } 10254887Schin ap->header.nelem &= ~ARRAY_UNDEF; 10264887Schin if(!(mode&ARRAY_FILL)) 10274887Schin ap->header.nelem &= ~ARRAY_SCAN; 1028*8462SApril.Chin@Sun.COM ap->header.nelem |= (mode&(ARRAY_SCAN|ARRAY_NOCHILD|ARRAY_UNDEF|ARRAY_NOSCOPE)); 10294887Schin if(sp) 10304887Schin { 10314887Schin if(mode&ARRAY_SETSUB) 10324887Schin { 10334887Schin (*ap->header.fun)(np, sp, NV_ASETSUB); 10344887Schin return(np); 10354887Schin } 1036*8462SApril.Chin@Sun.COM (*ap->header.fun)(np, sp, (mode&ARRAY_ADD)?NV_AADD:0); 1037*8462SApril.Chin@Sun.COM if(!(mode&(ARRAY_SCAN|ARRAY_ADD)) && !(*ap->header.fun)(np,NIL(char*),NV_ACURRENT)) 1038*8462SApril.Chin@Sun.COM np = 0; 10394887Schin } 10404887Schin else if(mode&ARRAY_SCAN) 10414887Schin (*ap->header.fun)(np,(char*)np,0); 10424887Schin else if(mode&ARRAY_UNDEF) 10434887Schin (*ap->header.fun)(np, "",0); 10444887Schin if((mode&ARRAY_SCAN) && !nv_nextsub(np)) 10454887Schin np = 0; 10464887Schin return(np); 10474887Schin } 10484887Schin 10494887Schin /* 10504887Schin * process an array subscript for node <np> given the subscript <cp> 10514887Schin * returns pointer to character after the subscript 10524887Schin */ 10534887Schin char *nv_endsubscript(Namval_t *np, register char *cp, int mode) 10544887Schin { 10554887Schin register int count=1, quoted=0, c; 10564887Schin register char *sp = cp+1; 10574887Schin /* first find matching ']' */ 10584887Schin while(count>0 && (c= *++cp)) 10594887Schin { 10604887Schin if(c=='\\' && (!(mode&NV_SUBQUOTE) || (c=cp[1])=='[' || c==']' || c=='\\' || c=='*' || c=='@')) 10614887Schin { 10624887Schin quoted=1; 10634887Schin cp++; 10644887Schin } 10654887Schin else if(c=='[') 10664887Schin count++; 10674887Schin else if(c==']') 10684887Schin count--; 10694887Schin } 10704887Schin *cp = 0; 10714887Schin if(quoted) 10724887Schin { 10734887Schin /* strip escape characters */ 10744887Schin count = staktell(); 10754887Schin stakwrite(sp,1+cp-sp); 10764887Schin sh_trim(sp=stakptr(count)); 10774887Schin } 10784887Schin if(mode && np) 1079*8462SApril.Chin@Sun.COM { 1080*8462SApril.Chin@Sun.COM if((mode&NV_ASSIGN) && (cp[1]=='=' || cp[1]=='+')) 1081*8462SApril.Chin@Sun.COM mode |= NV_ADD; 1082*8462SApril.Chin@Sun.COM nv_putsub(np, sp, ((mode&NV_ADD)?ARRAY_ADD:0)|(cp[1]&&(mode&NV_ADD)?ARRAY_FILL:mode&ARRAY_FILL)); 1083*8462SApril.Chin@Sun.COM } 10844887Schin if(quoted) 10854887Schin stakseek(count); 10864887Schin *cp++ = c; 10874887Schin return(cp); 10884887Schin } 10894887Schin 10904887Schin 10914887Schin Namval_t *nv_opensub(Namval_t* np) 10924887Schin { 10934887Schin register struct index_array *ap = (struct index_array*)nv_arrayptr(np); 1094*8462SApril.Chin@Sun.COM if(ap) 1095*8462SApril.Chin@Sun.COM { 1096*8462SApril.Chin@Sun.COM if(is_associative(ap)) 1097*8462SApril.Chin@Sun.COM return((Namval_t*)((*ap->header.fun)(np,NIL(char*),NV_ACURRENT))); 1098*8462SApril.Chin@Sun.COM else if(array_isbit(ap->bits,ap->cur,ARRAY_CHILD)) 1099*8462SApril.Chin@Sun.COM return(ap->val[ap->cur].np); 1100*8462SApril.Chin@Sun.COM } 11014887Schin return(NIL(Namval_t*)); 11024887Schin } 11034887Schin 11044887Schin char *nv_getsub(Namval_t* np) 11054887Schin { 11064887Schin static char numbuff[NUMSIZE]; 11074887Schin register struct index_array *ap; 11084887Schin register unsigned dot, n; 11094887Schin register char *cp = &numbuff[NUMSIZE]; 11104887Schin if(!np || !(ap = (struct index_array*)nv_arrayptr(np))) 11114887Schin return(NIL(char*)); 11124887Schin if(is_associative(ap)) 11134887Schin return((char*)((*ap->header.fun)(np,NIL(char*),NV_ANAME))); 1114*8462SApril.Chin@Sun.COM if(ap->xp) 1115*8462SApril.Chin@Sun.COM { 1116*8462SApril.Chin@Sun.COM np = nv_namptr(ap->xp,0); 1117*8462SApril.Chin@Sun.COM np->nvalue.s = ap->cur; 1118*8462SApril.Chin@Sun.COM return(nv_getval(np)); 1119*8462SApril.Chin@Sun.COM } 11204887Schin if((dot = ap->cur)==0) 11214887Schin *--cp = '0'; 11224887Schin else while(n=dot) 11234887Schin { 11244887Schin dot /= 10; 11254887Schin *--cp = '0' + (n-10*dot); 11264887Schin } 11274887Schin return(cp); 11284887Schin } 11294887Schin 11304887Schin /* 11314887Schin * If <np> is an indexed array node, the current subscript index 11324887Schin * returned, otherwise returns -1 11334887Schin */ 11344887Schin int nv_aindex(register Namval_t* np) 11354887Schin { 11364887Schin Namarr_t *ap = nv_arrayptr(np); 1137*8462SApril.Chin@Sun.COM if(!ap) 1138*8462SApril.Chin@Sun.COM return(0); 1139*8462SApril.Chin@Sun.COM else if(is_associative(ap)) 11404887Schin return(-1); 11414887Schin return(((struct index_array*)(ap))->cur&ARRAY_MASK); 11424887Schin } 11434887Schin 1144*8462SApril.Chin@Sun.COM int nv_arraynsub(register Namarr_t* ap) 1145*8462SApril.Chin@Sun.COM { 1146*8462SApril.Chin@Sun.COM return(array_elem(ap)); 1147*8462SApril.Chin@Sun.COM } 1148*8462SApril.Chin@Sun.COM 1149*8462SApril.Chin@Sun.COM int nv_aimax(register Namval_t* np) 1150*8462SApril.Chin@Sun.COM { 1151*8462SApril.Chin@Sun.COM struct index_array *ap = (struct index_array*)nv_arrayptr(np); 1152*8462SApril.Chin@Sun.COM int sub = -1; 1153*8462SApril.Chin@Sun.COM if(!ap || is_associative(&ap->header)) 1154*8462SApril.Chin@Sun.COM return(-1); 1155*8462SApril.Chin@Sun.COM sub = ap->maxi; 1156*8462SApril.Chin@Sun.COM while(--sub>0 && ap->val[sub].cp==0); 1157*8462SApril.Chin@Sun.COM return(sub); 1158*8462SApril.Chin@Sun.COM } 11594887Schin 11604887Schin /* 1161*8462SApril.Chin@Sun.COM * This is the default implementation for associative arrays 11624887Schin */ 11634887Schin void *nv_associative(register Namval_t *np,const char *sp,int mode) 11644887Schin { 11654887Schin register struct assoc_array *ap = (struct assoc_array*)nv_arrayptr(np); 11664887Schin register int type; 11674887Schin switch(mode) 11684887Schin { 11694887Schin case NV_AINIT: 11704887Schin if(ap = (struct assoc_array*)calloc(1,sizeof(struct assoc_array))) 11714887Schin { 1172*8462SApril.Chin@Sun.COM ap->header.table = dtopen(&_Nvdisc,Dtoset); 11734887Schin ap->cur = 0; 11744887Schin ap->pos = 0; 11754887Schin ap->header.hdr.disc = &array_disc; 1176*8462SApril.Chin@Sun.COM nv_disc(np,(Namfun_t*)ap, NV_FIRST); 1177*8462SApril.Chin@Sun.COM ap->header.hdr.dsize = sizeof(struct assoc_array); 1178*8462SApril.Chin@Sun.COM ap->header.hdr.nofree &= ~1; 11794887Schin } 11804887Schin return((void*)ap); 11814887Schin case NV_ADELETE: 11824887Schin if(ap->cur) 11834887Schin { 1184*8462SApril.Chin@Sun.COM if(!ap->header.scope || (Dt_t*)ap->header.scope==ap->header.table || !nv_search(ap->cur->nvname,(Dt_t*)ap->header.scope,0)) 1185*8462SApril.Chin@Sun.COM ap->header.nelem--; 1186*8462SApril.Chin@Sun.COM _nv_unset(ap->cur,NV_RDONLY); 1187*8462SApril.Chin@Sun.COM nv_delete(ap->cur,ap->header.table,0); 1188*8462SApril.Chin@Sun.COM ap->cur = 0; 11894887Schin } 11904887Schin return((void*)ap); 11914887Schin case NV_AFREE: 11924887Schin ap->pos = 0; 1193*8462SApril.Chin@Sun.COM if(ap->header.scope) 1194*8462SApril.Chin@Sun.COM { 1195*8462SApril.Chin@Sun.COM ap->header.table = dtview(ap->header.table,(Dt_t*)0); 1196*8462SApril.Chin@Sun.COM dtclose(ap->header.scope); 1197*8462SApril.Chin@Sun.COM ap->header.scope = 0; 1198*8462SApril.Chin@Sun.COM } 1199*8462SApril.Chin@Sun.COM else 1200*8462SApril.Chin@Sun.COM dtclose(ap->header.table); 12014887Schin return((void*)ap); 12024887Schin case NV_ANEXT: 12034887Schin if(!ap->pos) 12044887Schin { 1205*8462SApril.Chin@Sun.COM if((ap->header.nelem&ARRAY_NOSCOPE) && ap->header.scope && dtvnext(ap->header.table)) 1206*8462SApril.Chin@Sun.COM { 1207*8462SApril.Chin@Sun.COM ap->header.scope = dtvnext(ap->header.table); 1208*8462SApril.Chin@Sun.COM ap->header.table->view = 0; 1209*8462SApril.Chin@Sun.COM } 12104887Schin if(!(ap->pos=ap->cur)) 1211*8462SApril.Chin@Sun.COM ap->pos = (Namval_t*)dtfirst(ap->header.table); 12124887Schin } 12134887Schin else 12144887Schin ap->pos = ap->nextpos; 12154887Schin for(;ap->cur=ap->pos; ap->pos=ap->nextpos) 12164887Schin { 1217*8462SApril.Chin@Sun.COM ap->nextpos = (Namval_t*)dtnext(ap->header.table,ap->pos); 12184887Schin if(ap->cur->nvalue.cp) 12194887Schin { 12204887Schin if((ap->header.nelem&ARRAY_NOCHILD) && nv_isattr(ap->cur,NV_CHILD)) 12214887Schin continue; 12224887Schin return((void*)ap); 12234887Schin } 12244887Schin } 1225*8462SApril.Chin@Sun.COM if((ap->header.nelem&ARRAY_NOSCOPE) && ap->header.scope && !dtvnext(ap->header.table)) 1226*8462SApril.Chin@Sun.COM { 1227*8462SApril.Chin@Sun.COM ap->header.table->view = (Dt_t*)ap->header.scope; 1228*8462SApril.Chin@Sun.COM ap->header.scope = ap->header.table; 1229*8462SApril.Chin@Sun.COM } 12304887Schin return(NIL(void*)); 12314887Schin case NV_ASETSUB: 12324887Schin ap->cur = (Namval_t*)sp; 1233*8462SApril.Chin@Sun.COM return((void*)ap->cur); 12344887Schin case NV_ACURRENT: 1235*8462SApril.Chin@Sun.COM if(ap->cur) 1236*8462SApril.Chin@Sun.COM ap->cur->nvenv = (char*)np; 12374887Schin return((void*)ap->cur); 12384887Schin case NV_ANAME: 12394887Schin if(ap->cur) 1240*8462SApril.Chin@Sun.COM return((void*)ap->cur->nvname); 12414887Schin return(NIL(void*)); 12424887Schin default: 12434887Schin if(sp) 12444887Schin { 1245*8462SApril.Chin@Sun.COM Namval_t *mp=0; 1246*8462SApril.Chin@Sun.COM ap->cur = 0; 12474887Schin if(sp==(char*)np) 1248*8462SApril.Chin@Sun.COM return(0); 1249*8462SApril.Chin@Sun.COM type = nv_isattr(np,NV_PUBLIC&~(NV_ARRAY|NV_CHILD|NV_MINIMAL)); 1250*8462SApril.Chin@Sun.COM if(mode) 1251*8462SApril.Chin@Sun.COM mode = NV_ADD|HASH_NOSCOPE; 1252*8462SApril.Chin@Sun.COM else if(ap->header.nelem&ARRAY_NOSCOPE) 1253*8462SApril.Chin@Sun.COM mode = HASH_NOSCOPE; 1254*8462SApril.Chin@Sun.COM if(*sp==0 && (mode&NV_ADD)) 1255*8462SApril.Chin@Sun.COM sfprintf(sfstderr,"adding empty subscript\n"); 1256*8462SApril.Chin@Sun.COM if(sh.subshell && (mp=nv_search(sp,ap->header.table,0)) && nv_isnull(mp)) 1257*8462SApril.Chin@Sun.COM ap->cur = mp; 1258*8462SApril.Chin@Sun.COM if((mp || (mp=nv_search(sp,ap->header.table,mode))) && nv_isnull(mp) && (mode&NV_ADD)) 12594887Schin { 1260*8462SApril.Chin@Sun.COM nv_onattr(mp,type); 1261*8462SApril.Chin@Sun.COM mp->nvenv = (char*)np; 1262*8462SApril.Chin@Sun.COM if((mode&NV_ADD) && nv_type(np)) 1263*8462SApril.Chin@Sun.COM nv_arraychild(np,mp,0); 1264*8462SApril.Chin@Sun.COM if(sh.subshell) 1265*8462SApril.Chin@Sun.COM np = sh_assignok(np,1); 1266*8462SApril.Chin@Sun.COM if(!ap->header.scope || !nv_search(sp,dtvnext(ap->header.table),0)) 1267*8462SApril.Chin@Sun.COM ap->header.nelem++; 1268*8462SApril.Chin@Sun.COM if(nv_isnull(mp)) 1269*8462SApril.Chin@Sun.COM { 1270*8462SApril.Chin@Sun.COM if(ap->header.nelem&ARRAY_TREE) 1271*8462SApril.Chin@Sun.COM nv_setvtree(mp); 1272*8462SApril.Chin@Sun.COM mp->nvalue.cp = Empty; 1273*8462SApril.Chin@Sun.COM } 12744887Schin } 1275*8462SApril.Chin@Sun.COM else if(ap->header.nelem&ARRAY_SCAN) 1276*8462SApril.Chin@Sun.COM { 1277*8462SApril.Chin@Sun.COM Namval_t fake; 1278*8462SApril.Chin@Sun.COM fake.nvname = (char*)sp; 1279*8462SApril.Chin@Sun.COM ap->pos = mp = (Namval_t*)dtprev(ap->header.table,&fake); 1280*8462SApril.Chin@Sun.COM ap->nextpos = (Namval_t*)dtnext(ap->header.table,mp); 1281*8462SApril.Chin@Sun.COM } 1282*8462SApril.Chin@Sun.COM np = mp; 1283*8462SApril.Chin@Sun.COM if(ap->pos != np && !(ap->header.nelem&ARRAY_SCAN)) 12844887Schin ap->pos = 0; 12854887Schin ap->cur = np; 12864887Schin } 12874887Schin if(ap->cur) 12884887Schin return((void*)(&ap->cur->nvalue)); 12894887Schin else 12904887Schin return((void*)(&ap->cur)); 12914887Schin } 12924887Schin } 12934887Schin 12944887Schin /* 12954887Schin * Assign values to an array 12964887Schin */ 12974887Schin void nv_setvec(register Namval_t *np,int append,register int argc,register char *argv[]) 12984887Schin { 12994887Schin int arg0=0; 1300*8462SApril.Chin@Sun.COM struct index_array *ap=0,*aq; 13014887Schin if(nv_isarray(np)) 13024887Schin { 13034887Schin ap = (struct index_array*)nv_arrayptr(np); 13044887Schin if(ap && is_associative(ap)) 1305*8462SApril.Chin@Sun.COM errormsg(SH_DICT,ERROR_exit(1),"cannot append index array to associative array %s",nv_name(np)); 13064887Schin } 13074887Schin if(append) 13084887Schin { 13094887Schin if(ap) 13104887Schin { 1311*8462SApril.Chin@Sun.COM if(!(aq = (struct index_array*)ap->header.scope)) 1312*8462SApril.Chin@Sun.COM aq = ap; 13134887Schin arg0 = ap->maxi; 1314*8462SApril.Chin@Sun.COM while(--arg0>0 && ap->val[arg0].cp==0 && aq->val[arg0].cp==0); 13154887Schin arg0++; 13164887Schin } 13174887Schin else if(!nv_isnull(np)) 13184887Schin arg0=1; 13194887Schin } 13204887Schin while(--argc >= 0) 13214887Schin { 1322*8462SApril.Chin@Sun.COM nv_putsub(np,NIL(char*),(long)argc+arg0|ARRAY_FILL|ARRAY_ADD); 13234887Schin nv_putval(np,argv[argc],0); 13244887Schin } 13254887Schin } 13264887Schin 1327