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 * Array processing routines 23*4887Schin * 24*4887Schin * David Korn 25*4887Schin * AT&T Labs 26*4887Schin * dgk@research.att.com 27*4887Schin * 28*4887Schin */ 29*4887Schin 30*4887Schin #include "defs.h" 31*4887Schin #include <stak.h> 32*4887Schin #include "name.h" 33*4887Schin 34*4887Schin #define NUMSIZE (4+(ARRAY_MAX>999)+(ARRAY_MAX>9999)+(ARRAY_MAX>99999)) 35*4887Schin #define is_associative(ap) array_assoc((Namarr_t*)(ap)) 36*4887Schin #define array_setbit(cp, n) (cp[(n)/CHAR_BIT] |= 1<<(((n)&(CHAR_BIT-1)))) 37*4887Schin #define array_clrbit(cp, n) (cp[(n)/CHAR_BIT] &= ~(1<<(((n)&(CHAR_BIT-1))))) 38*4887Schin #define array_isbit(cp, n) (cp[(n)/CHAR_BIT] & 1<<(((n)&(CHAR_BIT-1)))) 39*4887Schin #define NV_CHILD NV_EXPORT 40*4887Schin 41*4887Schin static char Empty[] = ""; 42*4887Schin 43*4887Schin struct index_array 44*4887Schin { 45*4887Schin Namarr_t header; 46*4887Schin int cur; /* index of current element */ 47*4887Schin int maxi; /* maximum index for array */ 48*4887Schin unsigned char *bits; /* bit array for child subscripts */ 49*4887Schin union Value val[1]; /* array of value holders */ 50*4887Schin }; 51*4887Schin 52*4887Schin struct assoc_array 53*4887Schin { 54*4887Schin Namarr_t header; 55*4887Schin Dt_t *table; 56*4887Schin Namval_t *pos; 57*4887Schin Namval_t *nextpos; 58*4887Schin Namval_t *cur; 59*4887Schin }; 60*4887Schin 61*4887Schin /* 62*4887Schin * replace discipline with new one 63*4887Schin */ 64*4887Schin static void array_setptr(register Namval_t *np, struct index_array *old, struct index_array *new) 65*4887Schin { 66*4887Schin register Namfun_t **fp = &np->nvfun; 67*4887Schin while(*fp && *fp!= &old->header.hdr) 68*4887Schin fp = &((*fp)->next); 69*4887Schin if(*fp) 70*4887Schin { 71*4887Schin new->header.hdr.next = (*fp)->next; 72*4887Schin *fp = &new->header.hdr; 73*4887Schin } 74*4887Schin else sfprintf(sfstderr,"discipline not replaced\n"); 75*4887Schin } 76*4887Schin 77*4887Schin /* 78*4887Schin * Calculate the amount of space to be allocated to hold an 79*4887Schin * indexed array into which <maxi> is a legal index. The number of 80*4887Schin * elements that will actually fit into the array (> <maxi> 81*4887Schin * but <= ARRAY_MAX) is returned. 82*4887Schin * 83*4887Schin */ 84*4887Schin static int arsize(register int maxi) 85*4887Schin { 86*4887Schin register int i = roundof(maxi,ARRAY_INCR); 87*4887Schin return (i>ARRAY_MAX?ARRAY_MAX:i); 88*4887Schin } 89*4887Schin 90*4887Schin static struct index_array *array_grow(Namval_t*, struct index_array*,int); 91*4887Schin 92*4887Schin /* return index of highest element of an array */ 93*4887Schin int array_maxindex(Namval_t *np) 94*4887Schin { 95*4887Schin register struct index_array *ap = (struct index_array*)nv_arrayptr(np); 96*4887Schin register int i = ap->maxi; 97*4887Schin if(is_associative(ap)) 98*4887Schin return(-1); 99*4887Schin while(i>0 && ap->val[--i].cp==0); 100*4887Schin return(i+1); 101*4887Schin } 102*4887Schin 103*4887Schin static union Value *array_getup(Namval_t *np, Namarr_t *arp) 104*4887Schin { 105*4887Schin register struct index_array *ap = (struct index_array*)arp; 106*4887Schin register union Value *up; 107*4887Schin if(!nv_isarray(np)) 108*4887Schin return(&np->nvalue); 109*4887Schin if(is_associative(ap)) 110*4887Schin up = (union Value*)((*arp->fun)(np,NIL(char*),0)); 111*4887Schin else 112*4887Schin { 113*4887Schin if(ap->cur >= ap->maxi) 114*4887Schin errormsg(SH_DICT,ERROR_exit(1),e_subscript,nv_name(np)); 115*4887Schin up = &(ap->val[ap->cur]); 116*4887Schin } 117*4887Schin return(up); 118*4887Schin } 119*4887Schin 120*4887Schin /* 121*4887Schin * Get the Value pointer for an array. 122*4887Schin * Delete space as necessary if flag is ARRAY_DELETE 123*4887Schin * After the lookup is done the last @ or * subscript is incremented 124*4887Schin */ 125*4887Schin static Namval_t *array_find(Namval_t *np,Namarr_t *arp, int flag) 126*4887Schin { 127*4887Schin register struct index_array *ap = (struct index_array*)arp; 128*4887Schin register union Value *up; 129*4887Schin Namval_t *mp; 130*4887Schin int wasundef; 131*4887Schin if(wasundef = ap->header.nelem&ARRAY_UNDEF) 132*4887Schin { 133*4887Schin ap->header.nelem &= ~ARRAY_UNDEF; 134*4887Schin /* delete array is the same as delete array[@] */ 135*4887Schin if(flag&ARRAY_DELETE) 136*4887Schin { 137*4887Schin nv_putsub(np, NIL(char*), ARRAY_SCAN); 138*4887Schin ap->header.nelem |= ARRAY_SCAN; 139*4887Schin } 140*4887Schin else /* same as array[0] */ 141*4887Schin { 142*4887Schin if(is_associative(ap)) 143*4887Schin (*ap->header.fun)(np,"0",flag==ARRAY_ASSIGN?NV_AADD:0); 144*4887Schin else 145*4887Schin ap->cur = 0; 146*4887Schin } 147*4887Schin } 148*4887Schin if(is_associative(ap)) 149*4887Schin { 150*4887Schin mp = (Namval_t*)((*arp->fun)(np,NIL(char*),NV_ACURRENT)); 151*4887Schin if(!mp) 152*4887Schin up = (union Value*)∓ 153*4887Schin else if(nv_isattr(mp,NV_CHILD)) 154*4887Schin { 155*4887Schin if(wasundef && nv_isarray(mp->nvalue.np)) 156*4887Schin nv_putsub(mp->nvalue.np,NIL(char*),ARRAY_UNDEF); 157*4887Schin return(mp->nvalue.np); 158*4887Schin } 159*4887Schin else 160*4887Schin up = &mp->nvalue; 161*4887Schin } 162*4887Schin else 163*4887Schin { 164*4887Schin if(!(ap->header.nelem&ARRAY_SCAN) && ap->cur >= ap->maxi) 165*4887Schin ap = array_grow(np, ap, (int)ap->cur); 166*4887Schin if(ap->cur>=ap->maxi) 167*4887Schin errormsg(SH_DICT,ERROR_exit(1),e_subscript,nv_name(np)); 168*4887Schin up = &(ap->val[ap->cur]); 169*4887Schin if(up->np && array_isbit(ap->bits,ap->cur)) 170*4887Schin { 171*4887Schin if(wasundef && nv_isarray(up->np)) 172*4887Schin nv_putsub(up->np,NIL(char*),ARRAY_UNDEF); 173*4887Schin return(up->np); 174*4887Schin } 175*4887Schin } 176*4887Schin np->nvalue.cp = up->cp; 177*4887Schin if(!up->cp) 178*4887Schin { 179*4887Schin if(flag!=ARRAY_ASSIGN) 180*4887Schin return(0); 181*4887Schin ap->header.nelem++; 182*4887Schin } 183*4887Schin return(np); 184*4887Schin } 185*4887Schin 186*4887Schin static Namfun_t *array_clone(Namval_t *np, Namval_t *mp, int flags, Namfun_t *fp) 187*4887Schin { 188*4887Schin Namarr_t *ap = (Namarr_t*)fp; 189*4887Schin Namval_t *nq, *mq; 190*4887Schin char *name, *sub=0; 191*4887Schin int nelem = ap->nelem,offset=staktell(); 192*4887Schin struct index_array *aq, *ar; 193*4887Schin if(nelem&ARRAY_NOCLONE) 194*4887Schin return(0); 195*4887Schin if(array_assoc(ap)) 196*4887Schin nv_setarray(mp,ap->fun); 197*4887Schin else 198*4887Schin { 199*4887Schin nv_putsub(mp,NIL(char*),ap->nelem); 200*4887Schin if(aq=(struct index_array*)nv_arrayptr(mp)) 201*4887Schin aq->bits = (unsigned char*)&aq->val[aq->maxi]; 202*4887Schin } 203*4887Schin if(!(nelem&(ARRAY_SCAN|ARRAY_UNDEF)) && (sub=nv_getsub(np))) 204*4887Schin sub = strdup(sub); 205*4887Schin ar = (struct index_array*)ap; 206*4887Schin nv_onattr(mp,nv_isattr(np,NV_INTEGER|NV_UTOL|NV_LTOU|NV_LJUST|NV_RJUST|NV_ZFILL|NV_BINARY)); 207*4887Schin nv_putsub(np,NIL(char*),ARRAY_SCAN); 208*4887Schin do 209*4887Schin { 210*4887Schin if(array_assoc(ap)) 211*4887Schin name = (char*)((*ap->fun)(np,NIL(char*),NV_ANAME)); 212*4887Schin else 213*4887Schin name = nv_getsub(np); 214*4887Schin nv_putsub(mp,name,ARRAY_ADD); 215*4887Schin if((!array_assoc(ap) && array_isbit(ar->bits,ar->cur) && (nq=np)) || 216*4887Schin (array_assoc(ap) && (nq = (Namval_t*)((*ap->fun)(np,NIL(char*),NV_ACURRENT))) && nv_isattr(nq, NV_CHILD))) 217*4887Schin { 218*4887Schin sfprintf(stkstd,"%s[%s]",nv_name(mp),name); 219*4887Schin stakputc(0); 220*4887Schin mq = nv_search(stakptr(offset), sh.var_tree, NV_ADD); 221*4887Schin stakseek(offset); 222*4887Schin if(mq) 223*4887Schin { 224*4887Schin nv_clone(nq->nvalue.np,mq,0); 225*4887Schin if(array_assoc(ap)) 226*4887Schin { 227*4887Schin nq = (Namval_t*)((*ap->fun)(mp,NIL(char*),NV_ACURRENT)); 228*4887Schin nq->nvalue.np = mp; 229*4887Schin nv_onattr(nq,NV_CHILD); 230*4887Schin } 231*4887Schin else if(aq) 232*4887Schin { 233*4887Schin array_setbit(aq->bits,aq->cur); 234*4887Schin aq->val[aq->cur].np = mq; 235*4887Schin } 236*4887Schin } 237*4887Schin } 238*4887Schin else if(nv_isattr(np,NV_INTEGER)) 239*4887Schin { 240*4887Schin Sfdouble_t d= nv_getnum(np); 241*4887Schin nv_putval(mp,(char*)&d,NV_LDOUBLE); 242*4887Schin } 243*4887Schin else 244*4887Schin nv_putval(mp,nv_getval(np),NV_RDONLY); 245*4887Schin } 246*4887Schin while(nv_nextsub(np)); 247*4887Schin if(sub) 248*4887Schin { 249*4887Schin nv_putsub(np,sub,0L); 250*4887Schin free((void*)sub); 251*4887Schin } 252*4887Schin ap->nelem = nelem; 253*4887Schin ((Namarr_t*)mp->nvfun)->nelem = nelem; 254*4887Schin return(nv_stack(mp,(Namfun_t*)0)); 255*4887Schin } 256*4887Schin 257*4887Schin static char *array_getval(Namval_t *np, Namfun_t *disc) 258*4887Schin { 259*4887Schin register Namarr_t *ap = (Namarr_t*)disc; 260*4887Schin register Namval_t *mp; 261*4887Schin if((mp=array_find(np,ap,ARRAY_LOOKUP))!=np) 262*4887Schin return(mp?nv_getval(mp):0); 263*4887Schin return(nv_getv(np,&ap->hdr)); 264*4887Schin } 265*4887Schin 266*4887Schin static Sfdouble_t array_getnum(Namval_t *np, Namfun_t *disc) 267*4887Schin { 268*4887Schin register Namarr_t *ap = (Namarr_t*)disc; 269*4887Schin register Namval_t *mp; 270*4887Schin if((mp=array_find(np,ap,ARRAY_LOOKUP))!=np) 271*4887Schin return(mp?nv_getnum(mp):0); 272*4887Schin return(nv_getn(np,&ap->hdr)); 273*4887Schin } 274*4887Schin 275*4887Schin static void array_putval(Namval_t *np, const char *string, int flags, Namfun_t *dp) 276*4887Schin { 277*4887Schin register Namarr_t *ap = (Namarr_t*)dp; 278*4887Schin register union Value *up; 279*4887Schin register Namval_t *mp; 280*4887Schin register struct index_array *aq = (struct index_array*)ap; 281*4887Schin do 282*4887Schin { 283*4887Schin mp = array_find(np,ap,string?ARRAY_ASSIGN:ARRAY_DELETE); 284*4887Schin if(mp && mp!=np) 285*4887Schin nv_putval(mp, string, flags); 286*4887Schin if(!string) 287*4887Schin { 288*4887Schin if(mp) 289*4887Schin { 290*4887Schin if(mp!=np) 291*4887Schin { 292*4887Schin dtdelete(sh.var_tree,(void*)mp); 293*4887Schin free((void*)mp); 294*4887Schin } 295*4887Schin if(is_associative(ap)) 296*4887Schin (*ap->fun)(np,NIL(char*),NV_ADELETE); 297*4887Schin else if(mp!=np) 298*4887Schin { 299*4887Schin array_clrbit(aq->bits,aq->cur); 300*4887Schin aq->val[aq->cur].cp = 0; 301*4887Schin } 302*4887Schin ap->nelem--; 303*4887Schin } 304*4887Schin if(array_elem(ap)==0 && ((ap->nelem&ARRAY_SCAN) || !is_associative(ap))) 305*4887Schin { 306*4887Schin if(is_associative(ap)) 307*4887Schin (*ap->fun)(np, NIL(char*), NV_AFREE); 308*4887Schin nv_offattr(np,NV_ARRAY); 309*4887Schin } 310*4887Schin if(!mp || mp!=np) 311*4887Schin continue; 312*4887Schin } 313*4887Schin /* prevent empty string from being deleted */ 314*4887Schin if(np->nvalue.cp == Empty) 315*4887Schin np->nvalue.cp = 0; 316*4887Schin nv_putv(np,string,flags,&ap->hdr); 317*4887Schin up = array_getup(np,ap); 318*4887Schin up->cp = np->nvalue.cp; 319*4887Schin } 320*4887Schin while(!string && nv_nextsub(np)); 321*4887Schin if(!string && !nv_isattr(np,NV_ARRAY)) 322*4887Schin { 323*4887Schin Namfun_t *nfp; 324*4887Schin if(nfp = nv_disc(np,(Namfun_t*)ap,NV_POP)) 325*4887Schin free((void*)nfp); 326*4887Schin } 327*4887Schin } 328*4887Schin 329*4887Schin static const Namdisc_t array_disc = 330*4887Schin { 331*4887Schin sizeof(Namarr_t), 332*4887Schin array_putval, 333*4887Schin array_getval, 334*4887Schin array_getnum, 335*4887Schin 0, 336*4887Schin 0, 337*4887Schin array_clone 338*4887Schin }; 339*4887Schin 340*4887Schin /* 341*4887Schin * Increase the size of the indexed array of elements in <arp> 342*4887Schin * so that <maxi> is a legal index. If <arp> is 0, an array 343*4887Schin * of the required size is allocated. A pointer to the 344*4887Schin * allocated Namarr_t structure is returned. 345*4887Schin * <maxi> becomes the current index of the array. 346*4887Schin */ 347*4887Schin static struct index_array *array_grow(Namval_t *np, register struct index_array *arp,int maxi) 348*4887Schin { 349*4887Schin register struct index_array *ap; 350*4887Schin register int i=0; 351*4887Schin register int newsize = arsize(maxi+1); 352*4887Schin if (maxi >= ARRAY_MAX) 353*4887Schin errormsg(SH_DICT,ERROR_exit(1),e_subscript, fmtbase((long)maxi,10,0)); 354*4887Schin ap = new_of(struct index_array,(newsize-1)*sizeof(union Value*)+newsize/CHAR_BIT); 355*4887Schin memset((void*)ap,0,sizeof(*ap)); 356*4887Schin ap->maxi = newsize; 357*4887Schin ap->cur = maxi; 358*4887Schin ap->bits = (unsigned char*)&ap->val[newsize]; 359*4887Schin memset(ap->bits, 0, newsize/CHAR_BIT); 360*4887Schin if(arp) 361*4887Schin { 362*4887Schin ap->header = arp->header; 363*4887Schin for(;i < arp->maxi;i++) 364*4887Schin ap->val[i].cp = arp->val[i].cp; 365*4887Schin memcpy(ap->bits, arp->bits, (arp->maxi/CHAR_BIT)); 366*4887Schin array_setptr(np,arp,ap); 367*4887Schin free((void*)arp); 368*4887Schin } 369*4887Schin else 370*4887Schin { 371*4887Schin ap->header.fun = 0; 372*4887Schin if((ap->val[0].cp=np->nvalue.cp)) 373*4887Schin i++; 374*4887Schin else if(nv_hasdisc(np,&array_disc)) 375*4887Schin { 376*4887Schin Namval_t *mp; 377*4887Schin int offset = staktell(); 378*4887Schin sfprintf(stkstd,"%s[0]",nv_name(np)); 379*4887Schin stakputc(0); 380*4887Schin mp = nv_search(stakptr(offset), sh.var_tree, NV_ADD); 381*4887Schin stakseek(offset); 382*4887Schin if(mp && nv_isnull(mp)) 383*4887Schin { 384*4887Schin nv_clone(np,mp,0); 385*4887Schin ap->val[0].np = mp; 386*4887Schin array_setbit(ap->bits,0); 387*4887Schin } 388*4887Schin i++; 389*4887Schin } 390*4887Schin else if(nv_isattr(np,NV_INTEGER)) 391*4887Schin { 392*4887Schin Sfdouble_t d= nv_getnum(np); 393*4887Schin i++; 394*4887Schin } 395*4887Schin ap->header.nelem = i; 396*4887Schin ap->header.hdr.nofree = 1; 397*4887Schin ap->header.hdr.disc = &array_disc; 398*4887Schin nv_disc(np,(Namfun_t*)ap, NV_LAST); 399*4887Schin } 400*4887Schin for(;i < newsize;i++) 401*4887Schin ap->val[i].cp = 0; 402*4887Schin return(ap); 403*4887Schin } 404*4887Schin 405*4887Schin Namarr_t *nv_arrayptr(register Namval_t *np) 406*4887Schin { 407*4887Schin if(nv_isattr(np,NV_ARRAY)) 408*4887Schin return((Namarr_t*)nv_hasdisc(np, &array_disc)); 409*4887Schin return(0); 410*4887Schin } 411*4887Schin 412*4887Schin /* 413*4887Schin * Verify that argument is an indexed array and convert to associative, 414*4887Schin * freeing relevant storage 415*4887Schin */ 416*4887Schin static Namarr_t *nv_changearray(Namval_t *np, void *(*fun)(Namval_t*,const char*,int)) 417*4887Schin { 418*4887Schin register Namarr_t *ap; 419*4887Schin char numbuff[NUMSIZE+1]; 420*4887Schin unsigned dot, digit, n; 421*4887Schin union Value *up; 422*4887Schin struct index_array *save_ap; 423*4887Schin register char *string_index=&numbuff[NUMSIZE]; 424*4887Schin numbuff[NUMSIZE]='\0'; 425*4887Schin 426*4887Schin if(!fun || !(ap = nv_arrayptr(np)) || is_associative(ap)) 427*4887Schin return(NIL(Namarr_t*)); 428*4887Schin 429*4887Schin nv_stack(np,&ap->hdr); 430*4887Schin save_ap = (struct index_array*)nv_stack(np,0); 431*4887Schin ap = (Namarr_t*)((*fun)(np, NIL(char*), NV_AINIT)); 432*4887Schin ap->nelem = 0; 433*4887Schin ap->fun = fun; 434*4887Schin nv_onattr(np,NV_ARRAY); 435*4887Schin 436*4887Schin for(dot = 0; dot < (unsigned)save_ap->maxi; dot++) 437*4887Schin { 438*4887Schin if(save_ap->val[dot].cp) 439*4887Schin { 440*4887Schin if ((digit = dot)== 0) 441*4887Schin *--string_index = '0'; 442*4887Schin else while( n = digit ) 443*4887Schin { 444*4887Schin digit /= 10; 445*4887Schin *--string_index = '0' + (n-10*digit); 446*4887Schin } 447*4887Schin nv_putsub(np, string_index, ARRAY_ADD); 448*4887Schin up = (union Value*)((*ap->fun)(np,NIL(char*),0)); 449*4887Schin ap->nelem++; 450*4887Schin up->cp = save_ap->val[dot].cp; 451*4887Schin save_ap->val[dot].cp = 0; 452*4887Schin } 453*4887Schin string_index = &numbuff[NUMSIZE]; 454*4887Schin } 455*4887Schin free((void*)save_ap); 456*4887Schin return(ap); 457*4887Schin } 458*4887Schin 459*4887Schin /* 460*4887Schin * set the associative array processing method for node <np> to <fun> 461*4887Schin * The array pointer is returned if sucessful. 462*4887Schin */ 463*4887Schin Namarr_t *nv_setarray(Namval_t *np, void *(*fun)(Namval_t*,const char*,int)) 464*4887Schin { 465*4887Schin register Namarr_t *ap; 466*4887Schin char *value; 467*4887Schin if(fun && (ap = nv_arrayptr(np))) 468*4887Schin { 469*4887Schin /* 470*4887Schin * if it's already an indexed array, convert to 471*4887Schin * associative structure 472*4887Schin */ 473*4887Schin if(!is_associative(ap)) 474*4887Schin ap = nv_changearray(np, fun); 475*4887Schin return(ap); 476*4887Schin } 477*4887Schin value = nv_getval(np); 478*4887Schin if(fun && !ap && (ap = (Namarr_t*)((*fun)(np, NIL(char*), NV_AINIT)))) 479*4887Schin { 480*4887Schin /* check for preexisting initialization and save */ 481*4887Schin ap->nelem = 0; 482*4887Schin ap->fun = fun; 483*4887Schin nv_onattr(np,NV_ARRAY); 484*4887Schin if(value) 485*4887Schin { 486*4887Schin nv_putsub(np, "0", ARRAY_ADD); 487*4887Schin nv_putval(np, value, 0); 488*4887Schin } 489*4887Schin return(ap); 490*4887Schin } 491*4887Schin return(NIL(Namarr_t*)); 492*4887Schin } 493*4887Schin 494*4887Schin /* 495*4887Schin * move parent subscript into child 496*4887Schin */ 497*4887Schin Namval_t *nv_arraychild(Namval_t *np, Namval_t *nq, int c) 498*4887Schin { 499*4887Schin register Namarr_t *ap = nv_arrayptr(np); 500*4887Schin union Value *up; 501*4887Schin if(!(up = array_getup(np,ap))) 502*4887Schin return((Namval_t*)0); 503*4887Schin if(!nq) 504*4887Schin return(array_find(np,ap, ARRAY_LOOKUP)); 505*4887Schin np->nvalue.cp = up->cp; 506*4887Schin ap->nelem |= ARRAY_NOCLONE; 507*4887Schin nv_clone(np, nq, NV_NODISC); 508*4887Schin nv_offattr(nq,NV_ARRAY); 509*4887Schin ap->nelem &= ~ARRAY_NOCLONE; 510*4887Schin if(ap->fun) 511*4887Schin { 512*4887Schin up->np = (Namval_t*)((*ap->fun)(np,NIL(char*),NV_ACURRENT)); 513*4887Schin nv_onattr(up->np, NV_CHILD); 514*4887Schin (up->np)->nvalue.np = nq; 515*4887Schin } 516*4887Schin else 517*4887Schin { 518*4887Schin struct index_array *aq = (struct index_array*)ap; 519*4887Schin array_setbit(aq->bits,aq->cur); 520*4887Schin up->np = nq; 521*4887Schin } 522*4887Schin if(c=='.') 523*4887Schin nv_setvtree(nq); 524*4887Schin return(nq); 525*4887Schin } 526*4887Schin 527*4887Schin /* 528*4887Schin * This routine sets subscript of <np> to the next element, if any. 529*4887Schin * The return value is zero, if there are no more elements 530*4887Schin * Otherwise, 1 is returned. 531*4887Schin */ 532*4887Schin int nv_nextsub(Namval_t *np) 533*4887Schin { 534*4887Schin register struct index_array *ap = (struct index_array*)nv_arrayptr(np); 535*4887Schin register unsigned dot; 536*4887Schin if(!ap || !(ap->header.nelem&ARRAY_SCAN)) 537*4887Schin return(0); 538*4887Schin if(is_associative(ap)) 539*4887Schin { 540*4887Schin struct assoc_array *aq; 541*4887Schin if(aq=(*ap->header.fun)(np,NIL(char*),NV_ANEXT)) 542*4887Schin { 543*4887Schin if(nv_isattr(aq->cur,NV_CHILD)) 544*4887Schin nv_putsub(aq->cur->nvalue.np,NIL(char*),ARRAY_UNDEF); 545*4887Schin return(1); 546*4887Schin } 547*4887Schin ap->header.nelem &= ~(ARRAY_SCAN|ARRAY_NOCHILD); 548*4887Schin return(0); 549*4887Schin } 550*4887Schin for(dot=ap->cur+1; dot < (unsigned)ap->maxi; dot++) 551*4887Schin { 552*4887Schin if(ap->val[dot].cp) 553*4887Schin { 554*4887Schin ap->cur = dot; 555*4887Schin if(array_isbit(ap->bits, dot)) 556*4887Schin { 557*4887Schin 558*4887Schin if(ap->header.nelem&ARRAY_NOCHILD) 559*4887Schin continue; 560*4887Schin nv_putsub(ap->val[dot].np,NIL(char*),ARRAY_UNDEF); 561*4887Schin } 562*4887Schin return(1); 563*4887Schin } 564*4887Schin } 565*4887Schin ap->header.nelem &= ~(ARRAY_SCAN|ARRAY_NOCHILD); 566*4887Schin ap->cur = 0; 567*4887Schin return(0); 568*4887Schin } 569*4887Schin 570*4887Schin /* 571*4887Schin * Set an array subscript for node <np> given the subscript <sp> 572*4887Schin * An array is created if necessary. 573*4887Schin * <mode> can be a number, plus or more of symbolic constants 574*4887Schin * ARRAY_SCAN, ARRAY_UNDEF, ARRAY_ADD 575*4887Schin * The node pointer is returned which can be NULL if <np> is 576*4887Schin * not already array and the ARRAY_ADD bit of <mode> is not set. 577*4887Schin * ARRAY_FILL sets the specified subscript to the empty string when 578*4887Schin * ARRAY_ADD is specified and there is no value or sets all 579*4887Schin * the elements up to the number specified if ARRAY_ADD is not specified 580*4887Schin */ 581*4887Schin Namval_t *nv_putsub(Namval_t *np,register char *sp,register long mode) 582*4887Schin { 583*4887Schin register struct index_array *ap = (struct index_array*)nv_arrayptr(np); 584*4887Schin register int size = (mode&ARRAY_MASK); 585*4887Schin if(!ap || !ap->header.fun) 586*4887Schin { 587*4887Schin if(sp) 588*4887Schin size = (int)sh_arith((char*)sp); 589*4887Schin if(size >= ARRAY_MAX || (size < 0)) 590*4887Schin { 591*4887Schin errormsg(SH_DICT,ERROR_exit(1),e_subscript, nv_name(np)); 592*4887Schin return(NIL(Namval_t*)); 593*4887Schin } 594*4887Schin if(!ap || size>=ap->maxi) 595*4887Schin { 596*4887Schin if(size==0 && !(mode&ARRAY_FILL)) 597*4887Schin return(NIL(Namval_t*)); 598*4887Schin if(sh.subshell) 599*4887Schin np = sh_assignok(np,1); 600*4887Schin ap = array_grow(np, ap,size); 601*4887Schin nv_onattr(np,NV_ARRAY); 602*4887Schin } 603*4887Schin ap->header.nelem &= ~ARRAY_UNDEF; 604*4887Schin ap->header.nelem |= (mode&(ARRAY_SCAN|ARRAY_NOCHILD|ARRAY_UNDEF)); 605*4887Schin ap->cur = size; 606*4887Schin if((mode&ARRAY_SCAN) && !ap->val[size].cp && !nv_nextsub(np)) 607*4887Schin np = 0; 608*4887Schin if(mode&ARRAY_FILL) 609*4887Schin { 610*4887Schin if(!(mode&ARRAY_ADD)) 611*4887Schin { 612*4887Schin int n; 613*4887Schin for(n=0; n < size; n++) 614*4887Schin { 615*4887Schin if(!ap->val[n].cp) 616*4887Schin ap->val[n].cp = Empty; 617*4887Schin } 618*4887Schin ap->header.nelem = n|(ap->header.nelem&(ARRAY_SCAN|ARRAY_UNDEF)); 619*4887Schin if(n=ap->maxi-ap->maxi) 620*4887Schin memset(&ap->val[size],0,n*sizeof(union Value)); 621*4887Schin } 622*4887Schin else if(!ap->val[size].cp) 623*4887Schin { 624*4887Schin if(sh.subshell) 625*4887Schin np = sh_assignok(np,1); 626*4887Schin ap->val[size].cp = Empty; 627*4887Schin ap->header.nelem++; 628*4887Schin } 629*4887Schin } 630*4887Schin else if(!(mode&ARRAY_SCAN)) 631*4887Schin { 632*4887Schin ap->header.nelem &= ~ARRAY_SCAN; 633*4887Schin if(array_isbit(ap->bits,size)) 634*4887Schin nv_putsub(ap->val[size].np,NIL(char*),ARRAY_UNDEF); 635*4887Schin } 636*4887Schin return((Namval_t*)np); 637*4887Schin } 638*4887Schin ap->header.nelem &= ~ARRAY_UNDEF; 639*4887Schin if(!(mode&ARRAY_FILL)) 640*4887Schin ap->header.nelem &= ~ARRAY_SCAN; 641*4887Schin ap->header.nelem |= (mode&(ARRAY_SCAN|ARRAY_NOCHILD|ARRAY_UNDEF)); 642*4887Schin if(sp) 643*4887Schin { 644*4887Schin union Value *up; 645*4887Schin if(mode&ARRAY_SETSUB) 646*4887Schin { 647*4887Schin (*ap->header.fun)(np, sp, NV_ASETSUB); 648*4887Schin return(np); 649*4887Schin } 650*4887Schin up = (union Value*)(*ap->header.fun)(np, sp, (mode&ARRAY_ADD)?NV_AADD:0); 651*4887Schin if(up && !up->cp && (mode&ARRAY_ADD) && (mode&ARRAY_FILL)) 652*4887Schin { 653*4887Schin if(sh.subshell) 654*4887Schin np = sh_assignok(np,1); 655*4887Schin up->cp = Empty; 656*4887Schin ap->header.nelem++; 657*4887Schin } 658*4887Schin } 659*4887Schin else if(mode&ARRAY_SCAN) 660*4887Schin (*ap->header.fun)(np,(char*)np,0); 661*4887Schin else if(mode&ARRAY_UNDEF) 662*4887Schin (*ap->header.fun)(np, "",0); 663*4887Schin if((mode&ARRAY_SCAN) && !nv_nextsub(np)) 664*4887Schin np = 0; 665*4887Schin return(np); 666*4887Schin } 667*4887Schin 668*4887Schin /* 669*4887Schin * process an array subscript for node <np> given the subscript <cp> 670*4887Schin * returns pointer to character after the subscript 671*4887Schin */ 672*4887Schin char *nv_endsubscript(Namval_t *np, register char *cp, int mode) 673*4887Schin { 674*4887Schin register int count=1, quoted=0, c; 675*4887Schin register char *sp = cp+1; 676*4887Schin /* first find matching ']' */ 677*4887Schin while(count>0 && (c= *++cp)) 678*4887Schin { 679*4887Schin if(c=='\\' && (!(mode&NV_SUBQUOTE) || (c=cp[1])=='[' || c==']' || c=='\\' || c=='*' || c=='@')) 680*4887Schin { 681*4887Schin quoted=1; 682*4887Schin cp++; 683*4887Schin } 684*4887Schin else if(c=='[') 685*4887Schin count++; 686*4887Schin else if(c==']') 687*4887Schin count--; 688*4887Schin } 689*4887Schin *cp = 0; 690*4887Schin if(quoted) 691*4887Schin { 692*4887Schin /* strip escape characters */ 693*4887Schin count = staktell(); 694*4887Schin stakwrite(sp,1+cp-sp); 695*4887Schin sh_trim(sp=stakptr(count)); 696*4887Schin } 697*4887Schin if(mode && np) 698*4887Schin nv_putsub(np, sp, ARRAY_ADD|(cp[1]?ARRAY_FILL:mode&ARRAY_FILL)); 699*4887Schin if(quoted) 700*4887Schin stakseek(count); 701*4887Schin *cp++ = c; 702*4887Schin return(cp); 703*4887Schin } 704*4887Schin 705*4887Schin 706*4887Schin Namval_t *nv_opensub(Namval_t* np) 707*4887Schin { 708*4887Schin register struct index_array *ap = (struct index_array*)nv_arrayptr(np); 709*4887Schin if(ap && is_associative(ap)) 710*4887Schin return((Namval_t*)((*ap->header.fun)(np,NIL(char*),NV_ACURRENT))); 711*4887Schin return(NIL(Namval_t*)); 712*4887Schin } 713*4887Schin 714*4887Schin char *nv_getsub(Namval_t* np) 715*4887Schin { 716*4887Schin static char numbuff[NUMSIZE]; 717*4887Schin register struct index_array *ap; 718*4887Schin register unsigned dot, n; 719*4887Schin register char *cp = &numbuff[NUMSIZE]; 720*4887Schin if(!np || !(ap = (struct index_array*)nv_arrayptr(np))) 721*4887Schin return(NIL(char*)); 722*4887Schin if(is_associative(ap)) 723*4887Schin return((char*)((*ap->header.fun)(np,NIL(char*),NV_ANAME))); 724*4887Schin if((dot = ap->cur)==0) 725*4887Schin *--cp = '0'; 726*4887Schin else while(n=dot) 727*4887Schin { 728*4887Schin dot /= 10; 729*4887Schin *--cp = '0' + (n-10*dot); 730*4887Schin } 731*4887Schin return(cp); 732*4887Schin } 733*4887Schin 734*4887Schin /* 735*4887Schin * If <np> is an indexed array node, the current subscript index 736*4887Schin * returned, otherwise returns -1 737*4887Schin */ 738*4887Schin int nv_aindex(register Namval_t* np) 739*4887Schin { 740*4887Schin Namarr_t *ap = nv_arrayptr(np); 741*4887Schin if(!ap || is_associative(ap)) 742*4887Schin return(-1); 743*4887Schin return(((struct index_array*)(ap))->cur&ARRAY_MASK); 744*4887Schin } 745*4887Schin 746*4887Schin 747*4887Schin /* 748*4887Schin * This is the default implementation for associate arrays 749*4887Schin */ 750*4887Schin void *nv_associative(register Namval_t *np,const char *sp,int mode) 751*4887Schin { 752*4887Schin register struct assoc_array *ap = (struct assoc_array*)nv_arrayptr(np); 753*4887Schin register int type; 754*4887Schin switch(mode) 755*4887Schin { 756*4887Schin case NV_AINIT: 757*4887Schin if(ap = (struct assoc_array*)calloc(1,sizeof(struct assoc_array))) 758*4887Schin { 759*4887Schin ap->table = dtopen(&_Nvdisc,Dtbag); 760*4887Schin ap->cur = 0; 761*4887Schin ap->pos = 0; 762*4887Schin ap->header.hdr.disc = &array_disc; 763*4887Schin ap->header.hdr.nofree = 1; 764*4887Schin nv_disc(np,(Namfun_t*)ap, NV_LAST); 765*4887Schin } 766*4887Schin return((void*)ap); 767*4887Schin case NV_ADELETE: 768*4887Schin if(ap->cur) 769*4887Schin { 770*4887Schin if(nv_isattr(ap->cur,NV_NOFREE)) 771*4887Schin nv_offattr(ap->cur,NV_NOFREE); 772*4887Schin else 773*4887Schin { 774*4887Schin dtdelete(ap->table,(void*)ap->cur); 775*4887Schin free((void*)ap->cur); 776*4887Schin ap->cur = 0; 777*4887Schin } 778*4887Schin } 779*4887Schin return((void*)ap); 780*4887Schin case NV_AFREE: 781*4887Schin ap->pos = 0; 782*4887Schin dtclose(ap->table); 783*4887Schin return((void*)ap); 784*4887Schin case NV_ANEXT: 785*4887Schin if(!ap->pos) 786*4887Schin { 787*4887Schin if(!(ap->pos=ap->cur)) 788*4887Schin ap->pos = (Namval_t*)dtfirst(ap->table); 789*4887Schin } 790*4887Schin else 791*4887Schin ap->pos = ap->nextpos; 792*4887Schin for(;ap->cur=ap->pos; ap->pos=ap->nextpos) 793*4887Schin { 794*4887Schin ap->nextpos = (Namval_t*)dtnext(ap->table,ap->pos); 795*4887Schin if(ap->cur->nvalue.cp) 796*4887Schin { 797*4887Schin if((ap->header.nelem&ARRAY_NOCHILD) && nv_isattr(ap->cur,NV_CHILD)) 798*4887Schin continue; 799*4887Schin return((void*)ap); 800*4887Schin } 801*4887Schin } 802*4887Schin return(NIL(void*)); 803*4887Schin case NV_ASETSUB: 804*4887Schin ap->cur = (Namval_t*)sp; 805*4887Schin /* FALL THROUGH*/ 806*4887Schin case NV_ACURRENT: 807*4887Schin return((void*)ap->cur); 808*4887Schin case NV_ANAME: 809*4887Schin if(ap->cur) 810*4887Schin return((void*)nv_name(ap->cur)); 811*4887Schin return(NIL(void*)); 812*4887Schin default: 813*4887Schin if(sp) 814*4887Schin { 815*4887Schin if(sp==(char*)np) 816*4887Schin { 817*4887Schin ap->cur = 0; 818*4887Schin return(0); 819*4887Schin } 820*4887Schin else if(!(ap->header.nelem&ARRAY_SCAN)) 821*4887Schin ap->pos = 0; 822*4887Schin type = nv_isattr(np,NV_PUBLIC&~(NV_ARRAY|NV_CHILD)); 823*4887Schin if((np=nv_search(sp,ap->table,mode?NV_ADD:0)) && nv_isnull(np)) 824*4887Schin nv_onattr(np,type); 825*4887Schin ap->cur = np; 826*4887Schin } 827*4887Schin if(ap->cur) 828*4887Schin return((void*)(&ap->cur->nvalue)); 829*4887Schin else 830*4887Schin return((void*)(&ap->cur)); 831*4887Schin } 832*4887Schin } 833*4887Schin 834*4887Schin /* 835*4887Schin * Assign values to an array 836*4887Schin */ 837*4887Schin void nv_setvec(register Namval_t *np,int append,register int argc,register char *argv[]) 838*4887Schin { 839*4887Schin int arg0=0; 840*4887Schin struct index_array *ap=0; 841*4887Schin if(nv_isarray(np)) 842*4887Schin { 843*4887Schin ap = (struct index_array*)nv_arrayptr(np); 844*4887Schin if(ap && is_associative(ap)) 845*4887Schin errormsg(SH_DICT,ERROR_exit(1),"cannot append index array to associate array %s",nv_name(np)); 846*4887Schin } 847*4887Schin if(append) 848*4887Schin { 849*4887Schin if(ap) 850*4887Schin { 851*4887Schin arg0 = ap->maxi; 852*4887Schin while(--arg0>0 && ap->val[arg0].cp==0); 853*4887Schin arg0++; 854*4887Schin } 855*4887Schin else if(!nv_isnull(np)) 856*4887Schin arg0=1; 857*4887Schin } 858*4887Schin while(--argc >= 0) 859*4887Schin { 860*4887Schin if((argc+arg0)>0 || nv_isattr(np,NV_ARRAY)) 861*4887Schin nv_putsub(np,NIL(char*),(long)argc+arg0); 862*4887Schin nv_putval(np,argv[argc],0); 863*4887Schin } 864*4887Schin } 865*4887Schin 866