14887Schin /*********************************************************************** 24887Schin * * 34887Schin * This software is part of the ast package * 4*10898Sroland.mainz@nrubsig.org * Copyright (c) 1982-2009 AT&T Intellectual Property * 54887Schin * and is licensed under the * 64887Schin * Common Public License, Version 1.0 * 78462SApril.Chin@Sun.COM * by AT&T Intellectual Property * 84887Schin * * 94887Schin * A copy of the License is available at * 104887Schin * http://www.opensource.org/licenses/cpl1.0.txt * 114887Schin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 124887Schin * * 134887Schin * Information and Software Systems Research * 144887Schin * AT&T Research * 154887Schin * Florham Park NJ * 164887Schin * * 174887Schin * David Korn <dgk@research.att.com> * 184887Schin * * 194887Schin ***********************************************************************/ 204887Schin #pragma prototyped 214887Schin /* 224887Schin * 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)) 368462SApril.Chin@Sun.COM #define array_setbit(cp, n, b) (cp[n] |= (b)) 378462SApril.Chin@Sun.COM #define array_clrbit(cp, n, b) (cp[n] &= ~(b)) 388462SApril.Chin@Sun.COM #define array_isbit(cp, n, b) (cp[n] & (b)) 394887Schin #define NV_CHILD NV_EXPORT 408462SApril.Chin@Sun.COM #define ARRAY_CHILD 1 418462SApril.Chin@Sun.COM #define ARRAY_NOFREE 2 424887Schin 434887Schin struct index_array 444887Schin { 454887Schin Namarr_t header; 468462SApril.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 618462SApril.Chin@Sun.COM static Namarr_t *array_scope(Namval_t *np, Namarr_t *ap, int flags) 628462SApril.Chin@Sun.COM { 638462SApril.Chin@Sun.COM Namarr_t *aq; 648462SApril.Chin@Sun.COM struct index_array *ar; 658462SApril.Chin@Sun.COM size_t size = ap->hdr.dsize; 668462SApril.Chin@Sun.COM if(size==0) 678462SApril.Chin@Sun.COM size = ap->hdr.disc->dsize; 688462SApril.Chin@Sun.COM if(!(aq=newof(NIL(Namarr_t*),Namarr_t,1,size-sizeof(Namarr_t)))) 698462SApril.Chin@Sun.COM return(0); 708462SApril.Chin@Sun.COM memcpy(aq,ap,size); 718462SApril.Chin@Sun.COM aq->hdr.nofree &= ~1; 728462SApril.Chin@Sun.COM aq->hdr.nofree |= (flags&NV_RDONLY)?1:0; 738462SApril.Chin@Sun.COM if(is_associative(aq)) 748462SApril.Chin@Sun.COM { 758462SApril.Chin@Sun.COM aq->scope = (void*)dtopen(&_Nvdisc,Dtoset); 768462SApril.Chin@Sun.COM dtview((Dt_t*)aq->scope,aq->table); 778462SApril.Chin@Sun.COM aq->table = (Dt_t*)aq->scope; 788462SApril.Chin@Sun.COM return(aq); 798462SApril.Chin@Sun.COM } 808462SApril.Chin@Sun.COM aq->scope = (void*)ap; 818462SApril.Chin@Sun.COM ar = (struct index_array*)aq; 828462SApril.Chin@Sun.COM memset(ar->val, 0, ar->maxi*sizeof(char*)); 838462SApril.Chin@Sun.COM return(aq); 848462SApril.Chin@Sun.COM } 858462SApril.Chin@Sun.COM 868462SApril.Chin@Sun.COM static int array_unscope(Namval_t *np,Namarr_t *ap) 878462SApril.Chin@Sun.COM { 888462SApril.Chin@Sun.COM Namfun_t *fp; 898462SApril.Chin@Sun.COM if(!ap->scope) 908462SApril.Chin@Sun.COM return(0); 918462SApril.Chin@Sun.COM if(is_associative(ap)) 928462SApril.Chin@Sun.COM (*ap->fun)(np, NIL(char*), NV_AFREE); 938462SApril.Chin@Sun.COM if((fp = nv_disc(np,(Namfun_t*)ap,NV_POP)) && !(fp->nofree&1)) 948462SApril.Chin@Sun.COM free((void*)fp); 958462SApril.Chin@Sun.COM nv_delete(np,(Dt_t*)0,0); 968462SApril.Chin@Sun.COM return(1); 978462SApril.Chin@Sun.COM } 988462SApril.Chin@Sun.COM 998462SApril.Chin@Sun.COM static void array_syncsub(Namarr_t *ap, Namarr_t *aq) 1008462SApril.Chin@Sun.COM { 1018462SApril.Chin@Sun.COM ((struct index_array*)ap)->cur = ((struct index_array*)aq)->cur; 1028462SApril.Chin@Sun.COM } 1038462SApril.Chin@Sun.COM 1048462SApril.Chin@Sun.COM static int array_covered(Namval_t *np, struct index_array *ap) 1058462SApril.Chin@Sun.COM { 1068462SApril.Chin@Sun.COM struct index_array *aq = (struct index_array*)ap->header.scope; 1078462SApril.Chin@Sun.COM if(!ap->header.fun && aq) 1088462SApril.Chin@Sun.COM return ((ap->cur<aq->maxi) && aq->val[ap->cur].cp); 1098462SApril.Chin@Sun.COM return(0); 1108462SApril.Chin@Sun.COM } 1118462SApril.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 */ 1358462SApril.Chin@Sun.COM static int arsize(struct index_array *ap, register int maxi) 1364887Schin { 1378462SApril.Chin@Sun.COM if(ap && maxi < 2*ap->maxi) 1388462SApril.Chin@Sun.COM maxi = 2*ap->maxi; 1398462SApril.Chin@Sun.COM maxi = roundof(maxi,ARRAY_INCR); 1408462SApril.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 1568462SApril.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; 1608462SApril.Chin@Sun.COM int nofree; 1618462SApril.Chin@Sun.COM if(!arp) 1624887Schin return(&np->nvalue); 1634887Schin if(is_associative(ap)) 1648462SApril.Chin@Sun.COM { 1658462SApril.Chin@Sun.COM Namval_t *mp; 1668462SApril.Chin@Sun.COM mp = (Namval_t*)((*arp->fun)(np,NIL(char*),NV_ACURRENT)); 1678462SApril.Chin@Sun.COM if(mp) 1688462SApril.Chin@Sun.COM { 1698462SApril.Chin@Sun.COM nofree = nv_isattr(mp,NV_NOFREE); 1708462SApril.Chin@Sun.COM up = &mp->nvalue; 1718462SApril.Chin@Sun.COM } 1728462SApril.Chin@Sun.COM else 1738462SApril.Chin@Sun.COM return((union Value*)((*arp->fun)(np,NIL(char*),0))); 1748462SApril.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]); 1808462SApril.Chin@Sun.COM nofree = array_isbit(ap->bits,ap->cur,ARRAY_NOFREE); 1818462SApril.Chin@Sun.COM } 1828462SApril.Chin@Sun.COM if(update) 1838462SApril.Chin@Sun.COM { 1848462SApril.Chin@Sun.COM if(nofree) 1858462SApril.Chin@Sun.COM nv_onattr(np,NV_NOFREE); 1868462SApril.Chin@Sun.COM else 1878462SApril.Chin@Sun.COM nv_offattr(np,NV_NOFREE); 1884887Schin } 1894887Schin return(up); 1904887Schin } 1914887Schin 192*10898Sroland.mainz@nrubsig.org int nv_arrayisset(Namval_t *np, Namarr_t *arp) 193*10898Sroland.mainz@nrubsig.org { 194*10898Sroland.mainz@nrubsig.org register struct index_array *ap = (struct index_array*)arp; 195*10898Sroland.mainz@nrubsig.org union Value *up; 196*10898Sroland.mainz@nrubsig.org if(is_associative(ap)) 197*10898Sroland.mainz@nrubsig.org return((np = nv_opensub(np)) && !nv_isnull(np)); 198*10898Sroland.mainz@nrubsig.org if(ap->cur >= ap->maxi) 199*10898Sroland.mainz@nrubsig.org return(0); 200*10898Sroland.mainz@nrubsig.org up = &(ap->val[ap->cur]); 201*10898Sroland.mainz@nrubsig.org return(up->cp && up->cp!=Empty); 202*10898Sroland.mainz@nrubsig.org } 203*10898Sroland.mainz@nrubsig.org 2044887Schin /* 2054887Schin * Get the Value pointer for an array. 2064887Schin * Delete space as necessary if flag is ARRAY_DELETE 2074887Schin * After the lookup is done the last @ or * subscript is incremented 2084887Schin */ 2094887Schin static Namval_t *array_find(Namval_t *np,Namarr_t *arp, int flag) 2104887Schin { 2114887Schin register struct index_array *ap = (struct index_array*)arp; 2124887Schin register union Value *up; 2134887Schin Namval_t *mp; 2144887Schin int wasundef; 2158462SApril.Chin@Sun.COM if(flag&ARRAY_LOOKUP) 2168462SApril.Chin@Sun.COM ap->header.nelem &= ~ARRAY_NOSCOPE; 2178462SApril.Chin@Sun.COM else 2188462SApril.Chin@Sun.COM ap->header.nelem |= ARRAY_NOSCOPE; 2194887Schin if(wasundef = ap->header.nelem&ARRAY_UNDEF) 2204887Schin { 2214887Schin ap->header.nelem &= ~ARRAY_UNDEF; 2224887Schin /* delete array is the same as delete array[@] */ 2234887Schin if(flag&ARRAY_DELETE) 2244887Schin { 2258462SApril.Chin@Sun.COM nv_putsub(np, NIL(char*), ARRAY_SCAN|ARRAY_NOSCOPE); 2264887Schin ap->header.nelem |= ARRAY_SCAN; 2274887Schin } 2284887Schin else /* same as array[0] */ 2294887Schin { 2304887Schin if(is_associative(ap)) 2314887Schin (*ap->header.fun)(np,"0",flag==ARRAY_ASSIGN?NV_AADD:0); 2324887Schin else 2334887Schin ap->cur = 0; 2344887Schin } 2354887Schin } 2364887Schin if(is_associative(ap)) 2374887Schin { 2384887Schin mp = (Namval_t*)((*arp->fun)(np,NIL(char*),NV_ACURRENT)); 2394887Schin if(!mp) 2404887Schin up = (union Value*)∓ 2418462SApril.Chin@Sun.COM else if(nv_isarray(mp)) 2424887Schin { 2438462SApril.Chin@Sun.COM if(wasundef) 2448462SApril.Chin@Sun.COM nv_putsub(mp,NIL(char*),ARRAY_UNDEF); 2458462SApril.Chin@Sun.COM return(mp); 2464887Schin } 2474887Schin else 2488462SApril.Chin@Sun.COM { 2494887Schin up = &mp->nvalue; 2508462SApril.Chin@Sun.COM if(nv_isvtree(mp)) 2518462SApril.Chin@Sun.COM { 2528462SApril.Chin@Sun.COM if(!up->cp && flag==ARRAY_ASSIGN) 2538462SApril.Chin@Sun.COM { 2548462SApril.Chin@Sun.COM nv_arraychild(np,mp,0); 2558462SApril.Chin@Sun.COM ap->header.nelem++; 2568462SApril.Chin@Sun.COM } 2578462SApril.Chin@Sun.COM return(mp); 2588462SApril.Chin@Sun.COM } 2598462SApril.Chin@Sun.COM } 2604887Schin } 2614887Schin else 2624887Schin { 2634887Schin if(!(ap->header.nelem&ARRAY_SCAN) && ap->cur >= ap->maxi) 2644887Schin ap = array_grow(np, ap, (int)ap->cur); 2654887Schin if(ap->cur>=ap->maxi) 2664887Schin errormsg(SH_DICT,ERROR_exit(1),e_subscript,nv_name(np)); 2674887Schin up = &(ap->val[ap->cur]); 2688462SApril.Chin@Sun.COM if((!up->cp||up->cp==Empty) && nv_type(np) && nv_isvtree(np)) 2698462SApril.Chin@Sun.COM { 2708462SApril.Chin@Sun.COM char *cp; 2718462SApril.Chin@Sun.COM if(!ap->header.table) 2728462SApril.Chin@Sun.COM ap->header.table = dtopen(&_Nvdisc,Dtoset); 2738462SApril.Chin@Sun.COM sfprintf(sh.strbuf,"%d",ap->cur); 2748462SApril.Chin@Sun.COM cp = sfstruse(sh.strbuf); 2758462SApril.Chin@Sun.COM mp = nv_search(cp, ap->header.table, NV_ADD); 2768462SApril.Chin@Sun.COM mp->nvenv = (char*)np; 2778462SApril.Chin@Sun.COM nv_arraychild(np,mp,0); 2788462SApril.Chin@Sun.COM } 2798462SApril.Chin@Sun.COM if(up->np && array_isbit(ap->bits,ap->cur,ARRAY_CHILD)) 2804887Schin { 2814887Schin if(wasundef && nv_isarray(up->np)) 2824887Schin nv_putsub(up->np,NIL(char*),ARRAY_UNDEF); 2834887Schin return(up->np); 2844887Schin } 2854887Schin } 2864887Schin np->nvalue.cp = up->cp; 2874887Schin if(!up->cp) 2884887Schin { 2894887Schin if(flag!=ARRAY_ASSIGN) 2904887Schin return(0); 2918462SApril.Chin@Sun.COM if(!array_covered(np,ap)) 2928462SApril.Chin@Sun.COM ap->header.nelem++; 2934887Schin } 2944887Schin return(np); 2954887Schin } 2964887Schin 2978462SApril.Chin@Sun.COM #if SHOPT_TYPEDEF 2988462SApril.Chin@Sun.COM int nv_arraysettype(Namval_t *np, Namval_t *tp, const char *sub, int flags) 2998462SApril.Chin@Sun.COM { 3008462SApril.Chin@Sun.COM Namval_t *nq; 3018462SApril.Chin@Sun.COM char *av[2]; 3028462SApril.Chin@Sun.COM int rdonly = nv_isattr(np,NV_RDONLY); 3038462SApril.Chin@Sun.COM int xtrace = sh_isoption(SH_XTRACE); 3048462SApril.Chin@Sun.COM Namarr_t *ap = nv_arrayptr(np); 3058462SApril.Chin@Sun.COM av[1] = 0; 3068462SApril.Chin@Sun.COM sh.last_table = 0; 3078462SApril.Chin@Sun.COM if(!ap->table) 3088462SApril.Chin@Sun.COM ap->table = dtopen(&_Nvdisc,Dtoset); 3098462SApril.Chin@Sun.COM if(nq = nv_search(sub, ap->table, NV_ADD)) 3108462SApril.Chin@Sun.COM { 3118462SApril.Chin@Sun.COM if(!nq->nvfun && nq->nvalue.cp && *nq->nvalue.cp==0) 3128462SApril.Chin@Sun.COM _nv_unset(nq,NV_RDONLY); 3138462SApril.Chin@Sun.COM nv_arraychild(np,nq,0); 3148462SApril.Chin@Sun.COM if(!nv_isattr(tp,NV_BINARY)) 3158462SApril.Chin@Sun.COM { 3168462SApril.Chin@Sun.COM sfprintf(sh.strbuf,"%s=%s",nv_name(nq),nv_getval(np)); 3178462SApril.Chin@Sun.COM av[0] = strdup(sfstruse(sh.strbuf)); 3188462SApril.Chin@Sun.COM } 3198462SApril.Chin@Sun.COM if(!nv_clone(tp,nq,flags|NV_NOFREE)) 3208462SApril.Chin@Sun.COM return(0); 3218462SApril.Chin@Sun.COM ap->nelem |= ARRAY_SCAN; 3228462SApril.Chin@Sun.COM if(!rdonly) 3238462SApril.Chin@Sun.COM nv_offattr(nq,NV_RDONLY); 3248462SApril.Chin@Sun.COM if(!nv_isattr(tp,NV_BINARY)) 3258462SApril.Chin@Sun.COM { 3268462SApril.Chin@Sun.COM if(xtrace) 3278462SApril.Chin@Sun.COM sh_offoption(SH_XTRACE); 3288462SApril.Chin@Sun.COM ap->nelem &= ~ARRAY_SCAN; 3298462SApril.Chin@Sun.COM sh_eval(sh_sfeval(av),0); 3308462SApril.Chin@Sun.COM ap->nelem |= ARRAY_SCAN; 3318462SApril.Chin@Sun.COM free((void*)av[0]); 3328462SApril.Chin@Sun.COM if(xtrace) 3338462SApril.Chin@Sun.COM sh_onoption(SH_XTRACE); 3348462SApril.Chin@Sun.COM } 3358462SApril.Chin@Sun.COM return(1); 3368462SApril.Chin@Sun.COM } 3378462SApril.Chin@Sun.COM return(0); 3388462SApril.Chin@Sun.COM } 3398462SApril.Chin@Sun.COM #endif /* SHOPT_TYPEDEF */ 3408462SApril.Chin@Sun.COM 3418462SApril.Chin@Sun.COM 3424887Schin static Namfun_t *array_clone(Namval_t *np, Namval_t *mp, int flags, Namfun_t *fp) 3434887Schin { 3444887Schin Namarr_t *ap = (Namarr_t*)fp; 3454887Schin Namval_t *nq, *mq; 3464887Schin char *name, *sub=0; 3478462SApril.Chin@Sun.COM int nelem, skipped=0; 3488462SApril.Chin@Sun.COM Dt_t *otable=ap->table; 3498462SApril.Chin@Sun.COM struct index_array *aq = (struct index_array*)ap, *ar; 3508462SApril.Chin@Sun.COM Shell_t *shp = sh_getinterp(); 3518462SApril.Chin@Sun.COM if(flags&NV_MOVE) 3528462SApril.Chin@Sun.COM { 3538462SApril.Chin@Sun.COM if((flags&NV_COMVAR) && nv_putsub(np,NIL(char*),ARRAY_SCAN)) 3548462SApril.Chin@Sun.COM { 3558462SApril.Chin@Sun.COM do 3568462SApril.Chin@Sun.COM { 3578462SApril.Chin@Sun.COM if(nq=nv_opensub(np)) 3588462SApril.Chin@Sun.COM nq->nvenv = (void*)mp; 3598462SApril.Chin@Sun.COM } 3608462SApril.Chin@Sun.COM while(nv_nextsub(np)); 3618462SApril.Chin@Sun.COM } 3628462SApril.Chin@Sun.COM return(fp); 3638462SApril.Chin@Sun.COM } 3648462SApril.Chin@Sun.COM nelem = ap->nelem; 3654887Schin if(nelem&ARRAY_NOCLONE) 3664887Schin return(0); 3678462SApril.Chin@Sun.COM if((flags&NV_TYPE) && !ap->scope) 3688462SApril.Chin@Sun.COM { 3698462SApril.Chin@Sun.COM ap = array_scope(np,ap,flags); 3708462SApril.Chin@Sun.COM return(&ap->hdr); 3718462SApril.Chin@Sun.COM } 3728462SApril.Chin@Sun.COM ap = (Namarr_t*)nv_clone_disc(fp,0); 3738462SApril.Chin@Sun.COM if(flags&NV_COMVAR) 3744887Schin { 3758462SApril.Chin@Sun.COM ap->scope = 0; 3768462SApril.Chin@Sun.COM ap->nelem = 0; 3778462SApril.Chin@Sun.COM sh.prev_table = sh.last_table; 3788462SApril.Chin@Sun.COM sh.prev_root = sh.last_root; 3794887Schin } 3808462SApril.Chin@Sun.COM if(ap->table) 3818462SApril.Chin@Sun.COM { 3828462SApril.Chin@Sun.COM ap->table = dtopen(&_Nvdisc,Dtoset); 3838462SApril.Chin@Sun.COM if(ap->scope && !(flags&NV_COMVAR)) 3848462SApril.Chin@Sun.COM { 3858462SApril.Chin@Sun.COM ap->scope = ap->table; 3868462SApril.Chin@Sun.COM dtview(ap->table, otable->view); 3878462SApril.Chin@Sun.COM } 3888462SApril.Chin@Sun.COM } 3898462SApril.Chin@Sun.COM mp->nvfun = (Namfun_t*)ap; 3908462SApril.Chin@Sun.COM mp->nvflag &= NV_MINIMAL; 3918462SApril.Chin@Sun.COM mp->nvflag |= (np->nvflag&~(NV_MINIMAL|NV_NOFREE)); 3924887Schin if(!(nelem&(ARRAY_SCAN|ARRAY_UNDEF)) && (sub=nv_getsub(np))) 3934887Schin sub = strdup(sub); 3944887Schin ar = (struct index_array*)ap; 3958462SApril.Chin@Sun.COM if(!is_associative(ap)) 3968462SApril.Chin@Sun.COM ar->bits = (unsigned char*)&ar->val[ar->maxi]; 3978462SApril.Chin@Sun.COM if(!nv_putsub(np,NIL(char*),ARRAY_SCAN|((flags&NV_COMVAR)?0:ARRAY_NOSCOPE))) 3988462SApril.Chin@Sun.COM { 3998462SApril.Chin@Sun.COM if(ap->fun) 4008462SApril.Chin@Sun.COM (*ap->fun)(np,(char*)np,0); 4018462SApril.Chin@Sun.COM skipped=1; 4028462SApril.Chin@Sun.COM goto skip; 4038462SApril.Chin@Sun.COM } 4044887Schin do 4054887Schin { 4068462SApril.Chin@Sun.COM name = nv_getsub(np); 4078462SApril.Chin@Sun.COM nv_putsub(mp,name,ARRAY_ADD|ARRAY_NOSCOPE); 4088462SApril.Chin@Sun.COM mq = 0; 4098462SApril.Chin@Sun.COM if(nq=nv_opensub(np)) 4108462SApril.Chin@Sun.COM mq = nv_search(name,ap->table,NV_ADD); 4118462SApril.Chin@Sun.COM if(nq && (flags&NV_COMVAR) && nv_isvtree(nq)) 4124887Schin { 4138462SApril.Chin@Sun.COM mq->nvalue.cp = 0; 4148462SApril.Chin@Sun.COM if(!is_associative(ap)) 4158462SApril.Chin@Sun.COM ar->val[ar->cur].np = mq; 4168462SApril.Chin@Sun.COM nv_clone(nq,mq,flags); 4178462SApril.Chin@Sun.COM } 4188462SApril.Chin@Sun.COM else if(flags&NV_ARRAY) 4198462SApril.Chin@Sun.COM { 4208462SApril.Chin@Sun.COM if((flags&NV_NOFREE) && !is_associative(ap)) 4218462SApril.Chin@Sun.COM array_setbit(aq->bits,aq->cur,ARRAY_NOFREE); 4228462SApril.Chin@Sun.COM else if(nq && (flags&NV_NOFREE)) 4234887Schin { 4248462SApril.Chin@Sun.COM mq->nvalue = nq->nvalue; 4258462SApril.Chin@Sun.COM nv_onattr(nq,NV_NOFREE); 4264887Schin } 4274887Schin } 4284887Schin else if(nv_isattr(np,NV_INTEGER)) 4294887Schin { 4304887Schin Sfdouble_t d= nv_getnum(np); 4318462SApril.Chin@Sun.COM if(!is_associative(ap)) 4328462SApril.Chin@Sun.COM ar->val[ar->cur].cp = 0; 4334887Schin nv_putval(mp,(char*)&d,NV_LDOUBLE); 4344887Schin } 4354887Schin else 4368462SApril.Chin@Sun.COM { 4378462SApril.Chin@Sun.COM if(!is_associative(ap)) 4388462SApril.Chin@Sun.COM ar->val[ar->cur].cp = 0; 4394887Schin nv_putval(mp,nv_getval(np),NV_RDONLY); 4408462SApril.Chin@Sun.COM } 4418462SApril.Chin@Sun.COM aq->header.nelem |= ARRAY_NOSCOPE; 4424887Schin } 4434887Schin while(nv_nextsub(np)); 4448462SApril.Chin@Sun.COM skip: 4454887Schin if(sub) 4464887Schin { 4478462SApril.Chin@Sun.COM if(!skipped) 4488462SApril.Chin@Sun.COM nv_putsub(np,sub,0L); 4494887Schin free((void*)sub); 4504887Schin } 4518462SApril.Chin@Sun.COM aq->header.nelem = ap->nelem = nelem; 4528462SApril.Chin@Sun.COM return(&ap->hdr); 4534887Schin } 4544887Schin 4554887Schin static char *array_getval(Namval_t *np, Namfun_t *disc) 4564887Schin { 4578462SApril.Chin@Sun.COM register Namarr_t *aq,*ap = (Namarr_t*)disc; 4584887Schin register Namval_t *mp; 4594887Schin if((mp=array_find(np,ap,ARRAY_LOOKUP))!=np) 4608462SApril.Chin@Sun.COM { 4618462SApril.Chin@Sun.COM if(!mp && !is_associative(ap) && (aq=(Namarr_t*)ap->scope)) 4628462SApril.Chin@Sun.COM { 4638462SApril.Chin@Sun.COM array_syncsub(aq,ap); 4648462SApril.Chin@Sun.COM if((mp=array_find(np,aq,ARRAY_LOOKUP))==np) 4658462SApril.Chin@Sun.COM return(nv_getv(np,&aq->hdr)); 4668462SApril.Chin@Sun.COM } 4674887Schin return(mp?nv_getval(mp):0); 4688462SApril.Chin@Sun.COM } 4694887Schin return(nv_getv(np,&ap->hdr)); 4704887Schin } 4714887Schin 4724887Schin static Sfdouble_t array_getnum(Namval_t *np, Namfun_t *disc) 4734887Schin { 4748462SApril.Chin@Sun.COM register Namarr_t *aq,*ap = (Namarr_t*)disc; 4754887Schin register Namval_t *mp; 4764887Schin if((mp=array_find(np,ap,ARRAY_LOOKUP))!=np) 4778462SApril.Chin@Sun.COM { 4788462SApril.Chin@Sun.COM if(!mp && !is_associative(ap) && (aq=(Namarr_t*)ap->scope)) 4798462SApril.Chin@Sun.COM { 4808462SApril.Chin@Sun.COM array_syncsub(aq,ap); 4818462SApril.Chin@Sun.COM if((mp=array_find(np,aq,ARRAY_LOOKUP))==np) 4828462SApril.Chin@Sun.COM return(nv_getn(np,&aq->hdr)); 4838462SApril.Chin@Sun.COM } 4844887Schin return(mp?nv_getnum(mp):0); 4858462SApril.Chin@Sun.COM } 4864887Schin return(nv_getn(np,&ap->hdr)); 4874887Schin } 4884887Schin 4894887Schin static void array_putval(Namval_t *np, const char *string, int flags, Namfun_t *dp) 4904887Schin { 4914887Schin register Namarr_t *ap = (Namarr_t*)dp; 4924887Schin register union Value *up; 4934887Schin register Namval_t *mp; 4944887Schin register struct index_array *aq = (struct index_array*)ap; 4958462SApril.Chin@Sun.COM int scan,nofree = nv_isattr(np,NV_NOFREE); 4964887Schin do 4974887Schin { 4984887Schin mp = array_find(np,ap,string?ARRAY_ASSIGN:ARRAY_DELETE); 4998462SApril.Chin@Sun.COM scan = ap->nelem&ARRAY_SCAN; 5004887Schin if(mp && mp!=np) 5018462SApril.Chin@Sun.COM { 502*10898Sroland.mainz@nrubsig.org if(!is_associative(ap) && string && !(flags&NV_APPEND) && !nv_type(np) && nv_isvtree(mp)) 5038462SApril.Chin@Sun.COM { 5048462SApril.Chin@Sun.COM if(!nv_isattr(np,NV_NOFREE)) 5058462SApril.Chin@Sun.COM _nv_unset(mp,flags&NV_RDONLY); 5068462SApril.Chin@Sun.COM array_clrbit(aq->bits,aq->cur,ARRAY_CHILD); 5078462SApril.Chin@Sun.COM aq->val[aq->cur].cp = 0; 5088462SApril.Chin@Sun.COM if(!nv_isattr(mp,NV_NOFREE)) 5098462SApril.Chin@Sun.COM nv_delete(mp,ap->table,0); 5108462SApril.Chin@Sun.COM goto skip; 5118462SApril.Chin@Sun.COM } 5124887Schin nv_putval(mp, string, flags); 5138462SApril.Chin@Sun.COM if(string) 5148462SApril.Chin@Sun.COM { 5158462SApril.Chin@Sun.COM #if SHOPT_TYPEDEF 5168462SApril.Chin@Sun.COM if(ap->hdr.type && ap->hdr.type!=nv_type(mp)) 5178462SApril.Chin@Sun.COM nv_arraysettype(np,ap->hdr.type,nv_getsub(np),0); 5188462SApril.Chin@Sun.COM #endif /* SHOPT_TYPEDEF */ 5198462SApril.Chin@Sun.COM continue; 5208462SApril.Chin@Sun.COM } 5218462SApril.Chin@Sun.COM ap->nelem |= scan; 5228462SApril.Chin@Sun.COM } 5234887Schin if(!string) 5244887Schin { 5254887Schin if(mp) 5264887Schin { 5278462SApril.Chin@Sun.COM if(is_associative(ap)) 5284887Schin { 5294887Schin (*ap->fun)(np,NIL(char*),NV_ADELETE); 5308462SApril.Chin@Sun.COM np->nvalue.cp = 0; 5318462SApril.Chin@Sun.COM } 5328462SApril.Chin@Sun.COM else 5334887Schin { 5348462SApril.Chin@Sun.COM if(mp!=np) 5358462SApril.Chin@Sun.COM { 5368462SApril.Chin@Sun.COM array_clrbit(aq->bits,aq->cur,ARRAY_CHILD); 5378462SApril.Chin@Sun.COM aq->val[aq->cur].cp = 0; 5388462SApril.Chin@Sun.COM nv_delete(mp,ap->table,0); 5398462SApril.Chin@Sun.COM } 5408462SApril.Chin@Sun.COM if(!array_covered(np,(struct index_array*)ap)) 5418462SApril.Chin@Sun.COM ap->nelem--; 5424887Schin } 5434887Schin } 544*10898Sroland.mainz@nrubsig.org if(array_elem(ap)==0 && (ap->nelem&ARRAY_SCAN)) 5454887Schin { 5464887Schin if(is_associative(ap)) 5474887Schin (*ap->fun)(np, NIL(char*), NV_AFREE); 5488462SApril.Chin@Sun.COM else if(ap->table) 5498462SApril.Chin@Sun.COM dtclose(ap->table); 5504887Schin nv_offattr(np,NV_ARRAY); 5514887Schin } 5528462SApril.Chin@Sun.COM if(!mp || mp!=np || is_associative(ap)) 5534887Schin continue; 5544887Schin } 5558462SApril.Chin@Sun.COM skip: 5564887Schin /* prevent empty string from being deleted */ 5578462SApril.Chin@Sun.COM up = array_getup(np,ap,!nofree); 5588462SApril.Chin@Sun.COM if(up->cp == Empty) 5598462SApril.Chin@Sun.COM up->cp = 0; 5608462SApril.Chin@Sun.COM if(nv_isarray(np)) 5618462SApril.Chin@Sun.COM np->nvalue.up = up; 5624887Schin nv_putv(np,string,flags,&ap->hdr); 5638462SApril.Chin@Sun.COM if(!is_associative(ap)) 5648462SApril.Chin@Sun.COM { 5658462SApril.Chin@Sun.COM if(string) 5668462SApril.Chin@Sun.COM array_clrbit(aq->bits,aq->cur,ARRAY_NOFREE); 5678462SApril.Chin@Sun.COM else if(mp==np) 5688462SApril.Chin@Sun.COM aq->val[aq->cur].cp = 0; 5698462SApril.Chin@Sun.COM } 5708462SApril.Chin@Sun.COM #if SHOPT_TYPEDEF 5718462SApril.Chin@Sun.COM if(string && ap->hdr.type && nv_isvtree(np)) 5728462SApril.Chin@Sun.COM nv_arraysettype(np,ap->hdr.type,nv_getsub(np),0); 5738462SApril.Chin@Sun.COM #endif /* SHOPT_TYPEDEF */ 5744887Schin } 5754887Schin while(!string && nv_nextsub(np)); 5768462SApril.Chin@Sun.COM if(ap) 5778462SApril.Chin@Sun.COM ap->nelem &= ~ARRAY_NOSCOPE; 5788462SApril.Chin@Sun.COM if(nofree) 5798462SApril.Chin@Sun.COM nv_onattr(np,NV_NOFREE); 5808462SApril.Chin@Sun.COM else 5818462SApril.Chin@Sun.COM nv_offattr(np,NV_NOFREE); 5824887Schin if(!string && !nv_isattr(np,NV_ARRAY)) 5834887Schin { 5844887Schin Namfun_t *nfp; 5858462SApril.Chin@Sun.COM if(!is_associative(ap) && aq->xp) 5868462SApril.Chin@Sun.COM { 5878462SApril.Chin@Sun.COM _nv_unset(nv_namptr(aq->xp,0),NV_RDONLY); 5888462SApril.Chin@Sun.COM free((void*)aq->xp); 5898462SApril.Chin@Sun.COM } 5908462SApril.Chin@Sun.COM if((nfp = nv_disc(np,(Namfun_t*)ap,NV_POP)) && !(nfp->nofree&1)) 5914887Schin free((void*)nfp); 5928462SApril.Chin@Sun.COM if(!nv_isnull(np)) 5938462SApril.Chin@Sun.COM { 5948462SApril.Chin@Sun.COM nv_onattr(np,NV_NOFREE); 5958462SApril.Chin@Sun.COM _nv_unset(np,flags); 5968462SApril.Chin@Sun.COM } 5978462SApril.Chin@Sun.COM if(np->nvalue.cp==Empty) 5988462SApril.Chin@Sun.COM np->nvalue.cp = 0; 5994887Schin } 6008462SApril.Chin@Sun.COM if(!string && (flags&NV_TYPE)) 6018462SApril.Chin@Sun.COM array_unscope(np,ap); 6024887Schin } 6034887Schin 6044887Schin static const Namdisc_t array_disc = 6054887Schin { 6064887Schin sizeof(Namarr_t), 6074887Schin array_putval, 6084887Schin array_getval, 6094887Schin array_getnum, 6104887Schin 0, 6114887Schin 0, 6124887Schin array_clone 6134887Schin }; 6144887Schin 6158462SApril.Chin@Sun.COM static void array_copytree(Namval_t *np, Namval_t *mp) 6168462SApril.Chin@Sun.COM { 6178462SApril.Chin@Sun.COM Namfun_t *fp = nv_disc(np,NULL,NV_POP); 6188462SApril.Chin@Sun.COM nv_offattr(np,NV_ARRAY); 6198462SApril.Chin@Sun.COM nv_clone(np,mp,0); 620*10898Sroland.mainz@nrubsig.org if(np->nvalue.cp && !nv_isattr(np,NV_NOFREE)) 621*10898Sroland.mainz@nrubsig.org free((void*)np->nvalue.cp); 622*10898Sroland.mainz@nrubsig.org np->nvalue.cp = 0; 6238462SApril.Chin@Sun.COM np->nvalue.up = &mp->nvalue; 6248462SApril.Chin@Sun.COM fp->nofree &= ~1; 6258462SApril.Chin@Sun.COM nv_disc(np,(Namfun_t*)fp, NV_FIRST); 6268462SApril.Chin@Sun.COM fp->nofree |= 1; 6278462SApril.Chin@Sun.COM nv_onattr(np,NV_ARRAY); 6288462SApril.Chin@Sun.COM mp->nvenv = (char*)np; 6298462SApril.Chin@Sun.COM } 6308462SApril.Chin@Sun.COM 6314887Schin /* 6324887Schin * Increase the size of the indexed array of elements in <arp> 6334887Schin * so that <maxi> is a legal index. If <arp> is 0, an array 6344887Schin * of the required size is allocated. A pointer to the 6354887Schin * allocated Namarr_t structure is returned. 6364887Schin * <maxi> becomes the current index of the array. 6374887Schin */ 6384887Schin static struct index_array *array_grow(Namval_t *np, register struct index_array *arp,int maxi) 6394887Schin { 6404887Schin register struct index_array *ap; 6418462SApril.Chin@Sun.COM register int i; 6428462SApril.Chin@Sun.COM register int newsize = arsize(arp,maxi+1); 6434887Schin if (maxi >= ARRAY_MAX) 6444887Schin errormsg(SH_DICT,ERROR_exit(1),e_subscript, fmtbase((long)maxi,10,0)); 6458462SApril.Chin@Sun.COM i = (newsize-1)*sizeof(union Value*)+newsize; 6468462SApril.Chin@Sun.COM ap = new_of(struct index_array,i); 6478462SApril.Chin@Sun.COM memset((void*)ap,0,sizeof(*ap)+i); 6484887Schin ap->maxi = newsize; 6494887Schin ap->cur = maxi; 6504887Schin ap->bits = (unsigned char*)&ap->val[newsize]; 6518462SApril.Chin@Sun.COM memset(ap->bits, 0, newsize); 6524887Schin if(arp) 6534887Schin { 6544887Schin ap->header = arp->header; 6558462SApril.Chin@Sun.COM ap->header.hdr.dsize = sizeof(*ap) + i; 6568462SApril.Chin@Sun.COM for(i=0;i < arp->maxi;i++) 6574887Schin ap->val[i].cp = arp->val[i].cp; 6588462SApril.Chin@Sun.COM memcpy(ap->bits, arp->bits, arp->maxi); 6594887Schin array_setptr(np,arp,ap); 6604887Schin free((void*)arp); 6614887Schin } 6624887Schin else 6634887Schin { 6648462SApril.Chin@Sun.COM Namval_t *mp=0; 6658462SApril.Chin@Sun.COM ap->header.hdr.dsize = sizeof(*ap) + i; 6668462SApril.Chin@Sun.COM i = 0; 6674887Schin ap->header.fun = 0; 6688462SApril.Chin@Sun.COM if(nv_isnull(np) && nv_isattr(np,NV_NOFREE)) 6694887Schin { 6708462SApril.Chin@Sun.COM i = ARRAY_TREE; 6718462SApril.Chin@Sun.COM nv_offattr(np,NV_NOFREE); 6728462SApril.Chin@Sun.COM } 6738462SApril.Chin@Sun.COM if(np->nvalue.cp==Empty) 6748462SApril.Chin@Sun.COM np->nvalue.cp=0; 6758462SApril.Chin@Sun.COM if(nv_hasdisc(np,&array_disc) || nv_isvtree(np)) 6768462SApril.Chin@Sun.COM { 6778462SApril.Chin@Sun.COM ap->header.table = dtopen(&_Nvdisc,Dtoset); 678*10898Sroland.mainz@nrubsig.org mp = nv_search("0", ap->header.table,NV_ADD); 6794887Schin if(mp && nv_isnull(mp)) 6804887Schin { 6818462SApril.Chin@Sun.COM Namfun_t *fp; 6824887Schin ap->val[0].np = mp; 6838462SApril.Chin@Sun.COM array_setbit(ap->bits,0,ARRAY_CHILD); 6848462SApril.Chin@Sun.COM for(fp=np->nvfun; fp && !fp->disc->readf; fp=fp->next); 685*10898Sroland.mainz@nrubsig.org if(fp && fp->disc && fp->disc->readf) 6868462SApril.Chin@Sun.COM (*fp->disc->readf)(mp,(Sfio_t*)0,0,fp); 6878462SApril.Chin@Sun.COM i++; 6884887Schin } 6898462SApril.Chin@Sun.COM } 6908462SApril.Chin@Sun.COM else if((ap->val[0].cp=np->nvalue.cp)) 6914887Schin i++; 692*10898Sroland.mainz@nrubsig.org else if(nv_isattr(np,NV_INTEGER) && !nv_isnull(np)) 6934887Schin { 6944887Schin Sfdouble_t d= nv_getnum(np); 6954887Schin i++; 6964887Schin } 6974887Schin ap->header.nelem = i; 6984887Schin ap->header.hdr.disc = &array_disc; 6998462SApril.Chin@Sun.COM nv_disc(np,(Namfun_t*)ap, NV_FIRST); 7008462SApril.Chin@Sun.COM nv_onattr(np,NV_ARRAY); 7018462SApril.Chin@Sun.COM if(mp) 7028462SApril.Chin@Sun.COM { 7038462SApril.Chin@Sun.COM array_copytree(np,mp); 7048462SApril.Chin@Sun.COM ap->header.hdr.nofree &= ~1; 7058462SApril.Chin@Sun.COM } 7064887Schin } 7074887Schin for(;i < newsize;i++) 7084887Schin ap->val[i].cp = 0; 7094887Schin return(ap); 7104887Schin } 7114887Schin 7128462SApril.Chin@Sun.COM int nv_atypeindex(Namval_t *np, const char *tname) 7138462SApril.Chin@Sun.COM { 7148462SApril.Chin@Sun.COM Namval_t *tp; 7158462SApril.Chin@Sun.COM int offset = staktell(); 7168462SApril.Chin@Sun.COM int n = strlen(tname)-1; 7178462SApril.Chin@Sun.COM sfprintf(stkstd,"%s.%.*s%c",NV_CLASS,n,tname,0); 7188462SApril.Chin@Sun.COM tp = nv_open(stakptr(offset), sh.var_tree, NV_NOADD|NV_VARNAME); 7198462SApril.Chin@Sun.COM stakseek(offset); 7208462SApril.Chin@Sun.COM if(tp) 7218462SApril.Chin@Sun.COM { 7228462SApril.Chin@Sun.COM struct index_array *ap = (struct index_array*)nv_arrayptr(np); 7238462SApril.Chin@Sun.COM if(!nv_hasdisc(tp,&ENUM_disc)) 7248462SApril.Chin@Sun.COM errormsg(SH_DICT,ERROR_exit(1),e_notenum,tp->nvname); 7258462SApril.Chin@Sun.COM if(!ap) 7268462SApril.Chin@Sun.COM ap = array_grow(np,ap,1); 7278462SApril.Chin@Sun.COM ap->xp = calloc(NV_MINSZ,1); 7288462SApril.Chin@Sun.COM np = nv_namptr(ap->xp,0); 7298462SApril.Chin@Sun.COM np->nvname = tp->nvname; 7308462SApril.Chin@Sun.COM nv_onattr(np,NV_MINIMAL); 7318462SApril.Chin@Sun.COM nv_clone(tp,np,NV_NOFREE); 7328462SApril.Chin@Sun.COM nv_offattr(np,NV_RDONLY); 7338462SApril.Chin@Sun.COM return(1); 7348462SApril.Chin@Sun.COM } 7358462SApril.Chin@Sun.COM errormsg(SH_DICT,ERROR_exit(1),e_unknowntype, n,tname); 7368462SApril.Chin@Sun.COM return(0); 7378462SApril.Chin@Sun.COM } 7388462SApril.Chin@Sun.COM 7394887Schin Namarr_t *nv_arrayptr(register Namval_t *np) 7404887Schin { 7414887Schin if(nv_isattr(np,NV_ARRAY)) 7424887Schin return((Namarr_t*)nv_hasdisc(np, &array_disc)); 7434887Schin return(0); 7444887Schin } 7454887Schin 7464887Schin /* 7474887Schin * Verify that argument is an indexed array and convert to associative, 7484887Schin * freeing relevant storage 7494887Schin */ 7504887Schin static Namarr_t *nv_changearray(Namval_t *np, void *(*fun)(Namval_t*,const char*,int)) 7514887Schin { 7524887Schin register Namarr_t *ap; 7534887Schin char numbuff[NUMSIZE+1]; 7544887Schin unsigned dot, digit, n; 7554887Schin union Value *up; 7564887Schin struct index_array *save_ap; 7574887Schin register char *string_index=&numbuff[NUMSIZE]; 7584887Schin numbuff[NUMSIZE]='\0'; 7594887Schin 7604887Schin if(!fun || !(ap = nv_arrayptr(np)) || is_associative(ap)) 7614887Schin return(NIL(Namarr_t*)); 7624887Schin 7634887Schin nv_stack(np,&ap->hdr); 7644887Schin save_ap = (struct index_array*)nv_stack(np,0); 7654887Schin ap = (Namarr_t*)((*fun)(np, NIL(char*), NV_AINIT)); 7664887Schin ap->nelem = 0; 7674887Schin ap->fun = fun; 7684887Schin nv_onattr(np,NV_ARRAY); 7694887Schin 7704887Schin for(dot = 0; dot < (unsigned)save_ap->maxi; dot++) 7714887Schin { 7724887Schin if(save_ap->val[dot].cp) 7734887Schin { 7744887Schin if ((digit = dot)== 0) 7754887Schin *--string_index = '0'; 7764887Schin else while( n = digit ) 7774887Schin { 7784887Schin digit /= 10; 7794887Schin *--string_index = '0' + (n-10*digit); 7804887Schin } 7814887Schin nv_putsub(np, string_index, ARRAY_ADD); 7824887Schin up = (union Value*)((*ap->fun)(np,NIL(char*),0)); 7834887Schin up->cp = save_ap->val[dot].cp; 7844887Schin save_ap->val[dot].cp = 0; 7854887Schin } 7864887Schin string_index = &numbuff[NUMSIZE]; 7874887Schin } 7884887Schin free((void*)save_ap); 7894887Schin return(ap); 7904887Schin } 7914887Schin 7924887Schin /* 7934887Schin * set the associative array processing method for node <np> to <fun> 7944887Schin * The array pointer is returned if sucessful. 7954887Schin */ 7964887Schin Namarr_t *nv_setarray(Namval_t *np, void *(*fun)(Namval_t*,const char*,int)) 7974887Schin { 7984887Schin register Namarr_t *ap; 7998462SApril.Chin@Sun.COM char *value=0; 8008462SApril.Chin@Sun.COM Namfun_t *fp; 8018462SApril.Chin@Sun.COM int nelem = 0; 8024887Schin if(fun && (ap = nv_arrayptr(np))) 8034887Schin { 8044887Schin /* 8054887Schin * if it's already an indexed array, convert to 8064887Schin * associative structure 8074887Schin */ 8084887Schin if(!is_associative(ap)) 8094887Schin ap = nv_changearray(np, fun); 8104887Schin return(ap); 8114887Schin } 8128462SApril.Chin@Sun.COM if(nv_isnull(np) && nv_isattr(np,NV_NOFREE)) 8138462SApril.Chin@Sun.COM { 8148462SApril.Chin@Sun.COM nelem = ARRAY_TREE; 8158462SApril.Chin@Sun.COM nv_offattr(np,NV_NOFREE); 8168462SApril.Chin@Sun.COM } 8178462SApril.Chin@Sun.COM if(!(fp=nv_isvtree(np))) 8188462SApril.Chin@Sun.COM value = nv_getval(np); 8194887Schin if(fun && !ap && (ap = (Namarr_t*)((*fun)(np, NIL(char*), NV_AINIT)))) 8204887Schin { 8214887Schin /* check for preexisting initialization and save */ 8228462SApril.Chin@Sun.COM ap->nelem = nelem; 8234887Schin ap->fun = fun; 8244887Schin nv_onattr(np,NV_ARRAY); 8258462SApril.Chin@Sun.COM if(fp || value) 8264887Schin { 8274887Schin nv_putsub(np, "0", ARRAY_ADD); 8288462SApril.Chin@Sun.COM if(value) 8298462SApril.Chin@Sun.COM nv_putval(np, value, 0); 8308462SApril.Chin@Sun.COM else 8318462SApril.Chin@Sun.COM { 8328462SApril.Chin@Sun.COM Namval_t *mp = (Namval_t*)((*fun)(np,NIL(char*),NV_ACURRENT)); 8338462SApril.Chin@Sun.COM array_copytree(np,mp); 8348462SApril.Chin@Sun.COM } 8354887Schin } 8364887Schin return(ap); 8374887Schin } 8384887Schin return(NIL(Namarr_t*)); 8394887Schin } 8404887Schin 8414887Schin /* 8424887Schin * move parent subscript into child 8434887Schin */ 8444887Schin Namval_t *nv_arraychild(Namval_t *np, Namval_t *nq, int c) 8454887Schin { 8468462SApril.Chin@Sun.COM Namfun_t *fp; 8478462SApril.Chin@Sun.COM register Namarr_t *ap = nv_arrayptr(np); 8488462SApril.Chin@Sun.COM union Value *up; 8498462SApril.Chin@Sun.COM Namval_t *tp; 8508462SApril.Chin@Sun.COM if(!nq) 8518462SApril.Chin@Sun.COM return(ap?array_find(np,ap, ARRAY_LOOKUP):0); 8528462SApril.Chin@Sun.COM if(!ap) 8538462SApril.Chin@Sun.COM { 8548462SApril.Chin@Sun.COM nv_putsub(np, NIL(char*), ARRAY_FILL); 8558462SApril.Chin@Sun.COM ap = nv_arrayptr(np); 8568462SApril.Chin@Sun.COM } 8578462SApril.Chin@Sun.COM if(!(up = array_getup(np,ap,0))) 8584887Schin return((Namval_t*)0); 8594887Schin np->nvalue.cp = up->cp; 8608462SApril.Chin@Sun.COM if((tp=nv_type(np)) || c) 8614887Schin { 8628462SApril.Chin@Sun.COM ap->nelem |= ARRAY_NOCLONE; 8638462SApril.Chin@Sun.COM nq->nvenv = (char*)np; 8648462SApril.Chin@Sun.COM if(c=='t') 8658462SApril.Chin@Sun.COM nv_clone(tp,nq, 0); 8668462SApril.Chin@Sun.COM else 8678462SApril.Chin@Sun.COM nv_clone(np, nq, NV_NODISC); 8688462SApril.Chin@Sun.COM nv_offattr(nq,NV_ARRAY); 8698462SApril.Chin@Sun.COM ap->nelem &= ~ARRAY_NOCLONE; 8704887Schin } 8718462SApril.Chin@Sun.COM nq->nvenv = (char*)np; 8728462SApril.Chin@Sun.COM if((fp=nq->nvfun) && fp->disc && fp->disc->setdisc && (fp = nv_disc(nq,fp,NV_POP))) 8738462SApril.Chin@Sun.COM free((void*)fp); 8748462SApril.Chin@Sun.COM if(!ap->fun) 8754887Schin { 8764887Schin struct index_array *aq = (struct index_array*)ap; 8778462SApril.Chin@Sun.COM array_setbit(aq->bits,aq->cur,ARRAY_CHILD); 8784887Schin up->np = nq; 8794887Schin } 8804887Schin if(c=='.') 8814887Schin nv_setvtree(nq); 8824887Schin return(nq); 8834887Schin } 8844887Schin 8854887Schin /* 8864887Schin * This routine sets subscript of <np> to the next element, if any. 8874887Schin * The return value is zero, if there are no more elements 8884887Schin * Otherwise, 1 is returned. 8894887Schin */ 8904887Schin int nv_nextsub(Namval_t *np) 8914887Schin { 8928462SApril.Chin@Sun.COM register struct index_array *ap = (struct index_array*)nv_arrayptr(np); 8938462SApril.Chin@Sun.COM register unsigned dot; 8948462SApril.Chin@Sun.COM struct index_array *aq=0, *ar=0; 8954887Schin if(!ap || !(ap->header.nelem&ARRAY_SCAN)) 8964887Schin return(0); 8974887Schin if(is_associative(ap)) 8984887Schin { 8998462SApril.Chin@Sun.COM Namval_t *nq; 9008462SApril.Chin@Sun.COM if(nq=(*ap->header.fun)(np,NIL(char*),NV_ANEXT)) 9014887Schin { 9028462SApril.Chin@Sun.COM if(nv_isattr(nq,NV_CHILD)) 9038462SApril.Chin@Sun.COM nv_putsub(nq->nvalue.np,NIL(char*),ARRAY_UNDEF); 9044887Schin return(1); 9054887Schin } 9064887Schin ap->header.nelem &= ~(ARRAY_SCAN|ARRAY_NOCHILD); 9074887Schin return(0); 9084887Schin } 9098462SApril.Chin@Sun.COM if(!(ap->header.nelem&ARRAY_NOSCOPE)) 9108462SApril.Chin@Sun.COM ar = (struct index_array*)ap->header.scope; 9114887Schin for(dot=ap->cur+1; dot < (unsigned)ap->maxi; dot++) 9124887Schin { 9138462SApril.Chin@Sun.COM aq = ap; 9148462SApril.Chin@Sun.COM if(!ap->val[dot].cp && !(ap->header.nelem&ARRAY_NOSCOPE)) 9158462SApril.Chin@Sun.COM { 9168462SApril.Chin@Sun.COM if(!(aq=ar) || dot>=(unsigned)aq->maxi) 9178462SApril.Chin@Sun.COM continue; 9188462SApril.Chin@Sun.COM } 9198462SApril.Chin@Sun.COM if(aq->val[dot].cp) 9204887Schin { 9214887Schin ap->cur = dot; 9228462SApril.Chin@Sun.COM if(array_isbit(aq->bits, dot,ARRAY_CHILD)) 9234887Schin { 9248462SApril.Chin@Sun.COM Namval_t *mp = aq->val[dot].np; 9258462SApril.Chin@Sun.COM if((aq->header.nelem&ARRAY_NOCHILD) && nv_isvtree(mp)) 9264887Schin continue; 9278462SApril.Chin@Sun.COM nv_putsub(mp,NIL(char*),ARRAY_UNDEF); 9284887Schin } 9294887Schin return(1); 9304887Schin } 9314887Schin } 9324887Schin ap->header.nelem &= ~(ARRAY_SCAN|ARRAY_NOCHILD); 9334887Schin ap->cur = 0; 9344887Schin return(0); 9354887Schin } 9364887Schin 9374887Schin /* 9384887Schin * Set an array subscript for node <np> given the subscript <sp> 9394887Schin * An array is created if necessary. 9404887Schin * <mode> can be a number, plus or more of symbolic constants 9414887Schin * ARRAY_SCAN, ARRAY_UNDEF, ARRAY_ADD 9424887Schin * The node pointer is returned which can be NULL if <np> is 9434887Schin * not already array and the ARRAY_ADD bit of <mode> is not set. 9444887Schin * ARRAY_FILL sets the specified subscript to the empty string when 9454887Schin * ARRAY_ADD is specified and there is no value or sets all 9464887Schin * the elements up to the number specified if ARRAY_ADD is not specified 9474887Schin */ 9484887Schin Namval_t *nv_putsub(Namval_t *np,register char *sp,register long mode) 9494887Schin { 9504887Schin register struct index_array *ap = (struct index_array*)nv_arrayptr(np); 9514887Schin register int size = (mode&ARRAY_MASK); 9524887Schin if(!ap || !ap->header.fun) 9534887Schin { 9544887Schin if(sp) 9558462SApril.Chin@Sun.COM { 9568462SApril.Chin@Sun.COM if(ap && ap->xp && !strmatch(sp,"+([0-9])")) 9578462SApril.Chin@Sun.COM { 9588462SApril.Chin@Sun.COM Namval_t *mp = nv_namptr(ap->xp,0); 9598462SApril.Chin@Sun.COM nv_putval(mp, sp,0); 9608462SApril.Chin@Sun.COM size = nv_getnum(mp); 9618462SApril.Chin@Sun.COM } 9628462SApril.Chin@Sun.COM else 9638462SApril.Chin@Sun.COM size = (int)sh_arith((char*)sp); 9648462SApril.Chin@Sun.COM } 9658462SApril.Chin@Sun.COM if(size <0 && ap) 9668462SApril.Chin@Sun.COM size += array_maxindex(np); 9674887Schin if(size >= ARRAY_MAX || (size < 0)) 9684887Schin { 9694887Schin errormsg(SH_DICT,ERROR_exit(1),e_subscript, nv_name(np)); 9704887Schin return(NIL(Namval_t*)); 9714887Schin } 9724887Schin if(!ap || size>=ap->maxi) 9734887Schin { 9744887Schin if(size==0 && !(mode&ARRAY_FILL)) 9754887Schin return(NIL(Namval_t*)); 9764887Schin if(sh.subshell) 9774887Schin np = sh_assignok(np,1); 9784887Schin ap = array_grow(np, ap,size); 9794887Schin } 9804887Schin ap->header.nelem &= ~ARRAY_UNDEF; 9818462SApril.Chin@Sun.COM ap->header.nelem |= (mode&(ARRAY_SCAN|ARRAY_NOCHILD|ARRAY_UNDEF|ARRAY_NOSCOPE)); 9828462SApril.Chin@Sun.COM #if 0 9838462SApril.Chin@Sun.COM if(array_isbit(ap->bits,oldsize,ARRAY_CHILD)) 9848462SApril.Chin@Sun.COM mp = ap->val[oldsize].np; 9858462SApril.Chin@Sun.COM if(size != oldsize && mp->nvalue.cp) 9868462SApril.Chin@Sun.COM { 9878462SApril.Chin@Sun.COM Namfun_t *nfp; 9888462SApril.Chin@Sun.COM for(nfp=np->nvfun; nfp; nfp=nfp->next) 9898462SApril.Chin@Sun.COM { 9908462SApril.Chin@Sun.COM if(nfp->disc && nfp->disc->readf) 9918462SApril.Chin@Sun.COM { 9928462SApril.Chin@Sun.COM (*nfp->disc->readf)(mp,(Sfio_t*)0,0,nfp); 9938462SApril.Chin@Sun.COM break; 9948462SApril.Chin@Sun.COM } 9958462SApril.Chin@Sun.COM } 9968462SApril.Chin@Sun.COM } 9978462SApril.Chin@Sun.COM #endif 9984887Schin ap->cur = size; 9998462SApril.Chin@Sun.COM if((mode&ARRAY_SCAN) && (ap->cur--,!nv_nextsub(np))) 10004887Schin np = 0; 10018462SApril.Chin@Sun.COM if(mode&(ARRAY_FILL|ARRAY_ADD)) 10024887Schin { 10034887Schin if(!(mode&ARRAY_ADD)) 10044887Schin { 10054887Schin int n; 10068462SApril.Chin@Sun.COM for(n=0; n <= size; n++) 10074887Schin { 10084887Schin if(!ap->val[n].cp) 10098462SApril.Chin@Sun.COM { 10104887Schin ap->val[n].cp = Empty; 10118462SApril.Chin@Sun.COM if(!array_covered(np,ap)) 10128462SApril.Chin@Sun.COM ap->header.nelem++; 10138462SApril.Chin@Sun.COM } 10144887Schin } 10154887Schin if(n=ap->maxi-ap->maxi) 10164887Schin memset(&ap->val[size],0,n*sizeof(union Value)); 10174887Schin } 10184887Schin else if(!ap->val[size].cp) 10194887Schin { 10204887Schin if(sh.subshell) 10214887Schin np = sh_assignok(np,1); 10224887Schin ap->val[size].cp = Empty; 10238462SApril.Chin@Sun.COM if(!array_covered(np,ap)) 10248462SApril.Chin@Sun.COM ap->header.nelem++; 10254887Schin } 10264887Schin } 10274887Schin else if(!(mode&ARRAY_SCAN)) 10284887Schin { 10294887Schin ap->header.nelem &= ~ARRAY_SCAN; 10308462SApril.Chin@Sun.COM if(array_isbit(ap->bits,size,ARRAY_CHILD)) 10314887Schin nv_putsub(ap->val[size].np,NIL(char*),ARRAY_UNDEF); 10328462SApril.Chin@Sun.COM if(sp && !(mode&ARRAY_ADD) && !ap->val[size].cp) 10338462SApril.Chin@Sun.COM np = 0; 10344887Schin } 10354887Schin return((Namval_t*)np); 10364887Schin } 10374887Schin ap->header.nelem &= ~ARRAY_UNDEF; 10384887Schin if(!(mode&ARRAY_FILL)) 10394887Schin ap->header.nelem &= ~ARRAY_SCAN; 10408462SApril.Chin@Sun.COM ap->header.nelem |= (mode&(ARRAY_SCAN|ARRAY_NOCHILD|ARRAY_UNDEF|ARRAY_NOSCOPE)); 10414887Schin if(sp) 10424887Schin { 10434887Schin if(mode&ARRAY_SETSUB) 10444887Schin { 10454887Schin (*ap->header.fun)(np, sp, NV_ASETSUB); 10464887Schin return(np); 10474887Schin } 10488462SApril.Chin@Sun.COM (*ap->header.fun)(np, sp, (mode&ARRAY_ADD)?NV_AADD:0); 10498462SApril.Chin@Sun.COM if(!(mode&(ARRAY_SCAN|ARRAY_ADD)) && !(*ap->header.fun)(np,NIL(char*),NV_ACURRENT)) 10508462SApril.Chin@Sun.COM np = 0; 10514887Schin } 10524887Schin else if(mode&ARRAY_SCAN) 10534887Schin (*ap->header.fun)(np,(char*)np,0); 10544887Schin else if(mode&ARRAY_UNDEF) 10554887Schin (*ap->header.fun)(np, "",0); 10564887Schin if((mode&ARRAY_SCAN) && !nv_nextsub(np)) 10574887Schin np = 0; 10584887Schin return(np); 10594887Schin } 10604887Schin 10614887Schin /* 10624887Schin * process an array subscript for node <np> given the subscript <cp> 10634887Schin * returns pointer to character after the subscript 10644887Schin */ 10654887Schin char *nv_endsubscript(Namval_t *np, register char *cp, int mode) 10664887Schin { 10674887Schin register int count=1, quoted=0, c; 10684887Schin register char *sp = cp+1; 10694887Schin /* first find matching ']' */ 10704887Schin while(count>0 && (c= *++cp)) 10714887Schin { 10724887Schin if(c=='\\' && (!(mode&NV_SUBQUOTE) || (c=cp[1])=='[' || c==']' || c=='\\' || c=='*' || c=='@')) 10734887Schin { 10744887Schin quoted=1; 10754887Schin cp++; 10764887Schin } 10774887Schin else if(c=='[') 10784887Schin count++; 10794887Schin else if(c==']') 10804887Schin count--; 10814887Schin } 10824887Schin *cp = 0; 10834887Schin if(quoted) 10844887Schin { 10854887Schin /* strip escape characters */ 10864887Schin count = staktell(); 10874887Schin stakwrite(sp,1+cp-sp); 10884887Schin sh_trim(sp=stakptr(count)); 10894887Schin } 10904887Schin if(mode && np) 10918462SApril.Chin@Sun.COM { 1092*10898Sroland.mainz@nrubsig.org Namarr_t *ap = nv_arrayptr(np); 1093*10898Sroland.mainz@nrubsig.org int scan = 0; 1094*10898Sroland.mainz@nrubsig.org if(ap) 1095*10898Sroland.mainz@nrubsig.org scan = ap->nelem&ARRAY_SCAN; 10968462SApril.Chin@Sun.COM if((mode&NV_ASSIGN) && (cp[1]=='=' || cp[1]=='+')) 10978462SApril.Chin@Sun.COM mode |= NV_ADD; 10988462SApril.Chin@Sun.COM nv_putsub(np, sp, ((mode&NV_ADD)?ARRAY_ADD:0)|(cp[1]&&(mode&NV_ADD)?ARRAY_FILL:mode&ARRAY_FILL)); 1099*10898Sroland.mainz@nrubsig.org if(scan) 1100*10898Sroland.mainz@nrubsig.org ap->nelem |= scan; 11018462SApril.Chin@Sun.COM } 11024887Schin if(quoted) 11034887Schin stakseek(count); 11044887Schin *cp++ = c; 11054887Schin return(cp); 11064887Schin } 11074887Schin 11084887Schin 11094887Schin Namval_t *nv_opensub(Namval_t* np) 11104887Schin { 11114887Schin register struct index_array *ap = (struct index_array*)nv_arrayptr(np); 11128462SApril.Chin@Sun.COM if(ap) 11138462SApril.Chin@Sun.COM { 11148462SApril.Chin@Sun.COM if(is_associative(ap)) 11158462SApril.Chin@Sun.COM return((Namval_t*)((*ap->header.fun)(np,NIL(char*),NV_ACURRENT))); 11168462SApril.Chin@Sun.COM else if(array_isbit(ap->bits,ap->cur,ARRAY_CHILD)) 11178462SApril.Chin@Sun.COM return(ap->val[ap->cur].np); 11188462SApril.Chin@Sun.COM } 11194887Schin return(NIL(Namval_t*)); 11204887Schin } 11214887Schin 11224887Schin char *nv_getsub(Namval_t* np) 11234887Schin { 11244887Schin static char numbuff[NUMSIZE]; 11254887Schin register struct index_array *ap; 11264887Schin register unsigned dot, n; 11274887Schin register char *cp = &numbuff[NUMSIZE]; 11284887Schin if(!np || !(ap = (struct index_array*)nv_arrayptr(np))) 11294887Schin return(NIL(char*)); 11304887Schin if(is_associative(ap)) 11314887Schin return((char*)((*ap->header.fun)(np,NIL(char*),NV_ANAME))); 11328462SApril.Chin@Sun.COM if(ap->xp) 11338462SApril.Chin@Sun.COM { 11348462SApril.Chin@Sun.COM np = nv_namptr(ap->xp,0); 11358462SApril.Chin@Sun.COM np->nvalue.s = ap->cur; 11368462SApril.Chin@Sun.COM return(nv_getval(np)); 11378462SApril.Chin@Sun.COM } 11384887Schin if((dot = ap->cur)==0) 11394887Schin *--cp = '0'; 11404887Schin else while(n=dot) 11414887Schin { 11424887Schin dot /= 10; 11434887Schin *--cp = '0' + (n-10*dot); 11444887Schin } 11454887Schin return(cp); 11464887Schin } 11474887Schin 11484887Schin /* 11494887Schin * If <np> is an indexed array node, the current subscript index 11504887Schin * returned, otherwise returns -1 11514887Schin */ 11524887Schin int nv_aindex(register Namval_t* np) 11534887Schin { 11544887Schin Namarr_t *ap = nv_arrayptr(np); 11558462SApril.Chin@Sun.COM if(!ap) 11568462SApril.Chin@Sun.COM return(0); 11578462SApril.Chin@Sun.COM else if(is_associative(ap)) 11584887Schin return(-1); 11594887Schin return(((struct index_array*)(ap))->cur&ARRAY_MASK); 11604887Schin } 11614887Schin 11628462SApril.Chin@Sun.COM int nv_arraynsub(register Namarr_t* ap) 11638462SApril.Chin@Sun.COM { 11648462SApril.Chin@Sun.COM return(array_elem(ap)); 11658462SApril.Chin@Sun.COM } 11668462SApril.Chin@Sun.COM 11678462SApril.Chin@Sun.COM int nv_aimax(register Namval_t* np) 11688462SApril.Chin@Sun.COM { 11698462SApril.Chin@Sun.COM struct index_array *ap = (struct index_array*)nv_arrayptr(np); 11708462SApril.Chin@Sun.COM int sub = -1; 11718462SApril.Chin@Sun.COM if(!ap || is_associative(&ap->header)) 11728462SApril.Chin@Sun.COM return(-1); 11738462SApril.Chin@Sun.COM sub = ap->maxi; 11748462SApril.Chin@Sun.COM while(--sub>0 && ap->val[sub].cp==0); 11758462SApril.Chin@Sun.COM return(sub); 11768462SApril.Chin@Sun.COM } 11774887Schin 11784887Schin /* 11798462SApril.Chin@Sun.COM * This is the default implementation for associative arrays 11804887Schin */ 11814887Schin void *nv_associative(register Namval_t *np,const char *sp,int mode) 11824887Schin { 11834887Schin register struct assoc_array *ap = (struct assoc_array*)nv_arrayptr(np); 11844887Schin register int type; 11854887Schin switch(mode) 11864887Schin { 11874887Schin case NV_AINIT: 11884887Schin if(ap = (struct assoc_array*)calloc(1,sizeof(struct assoc_array))) 11894887Schin { 11908462SApril.Chin@Sun.COM ap->header.table = dtopen(&_Nvdisc,Dtoset); 11914887Schin ap->cur = 0; 11924887Schin ap->pos = 0; 11934887Schin ap->header.hdr.disc = &array_disc; 11948462SApril.Chin@Sun.COM nv_disc(np,(Namfun_t*)ap, NV_FIRST); 11958462SApril.Chin@Sun.COM ap->header.hdr.dsize = sizeof(struct assoc_array); 11968462SApril.Chin@Sun.COM ap->header.hdr.nofree &= ~1; 11974887Schin } 11984887Schin return((void*)ap); 11994887Schin case NV_ADELETE: 12004887Schin if(ap->cur) 12014887Schin { 12028462SApril.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)) 12038462SApril.Chin@Sun.COM ap->header.nelem--; 12048462SApril.Chin@Sun.COM _nv_unset(ap->cur,NV_RDONLY); 12058462SApril.Chin@Sun.COM nv_delete(ap->cur,ap->header.table,0); 12068462SApril.Chin@Sun.COM ap->cur = 0; 12074887Schin } 12084887Schin return((void*)ap); 12094887Schin case NV_AFREE: 12104887Schin ap->pos = 0; 12118462SApril.Chin@Sun.COM if(ap->header.scope) 12128462SApril.Chin@Sun.COM { 12138462SApril.Chin@Sun.COM ap->header.table = dtview(ap->header.table,(Dt_t*)0); 12148462SApril.Chin@Sun.COM dtclose(ap->header.scope); 12158462SApril.Chin@Sun.COM ap->header.scope = 0; 12168462SApril.Chin@Sun.COM } 12178462SApril.Chin@Sun.COM else 12188462SApril.Chin@Sun.COM dtclose(ap->header.table); 12194887Schin return((void*)ap); 12204887Schin case NV_ANEXT: 12214887Schin if(!ap->pos) 12224887Schin { 12238462SApril.Chin@Sun.COM if((ap->header.nelem&ARRAY_NOSCOPE) && ap->header.scope && dtvnext(ap->header.table)) 12248462SApril.Chin@Sun.COM { 12258462SApril.Chin@Sun.COM ap->header.scope = dtvnext(ap->header.table); 12268462SApril.Chin@Sun.COM ap->header.table->view = 0; 12278462SApril.Chin@Sun.COM } 12284887Schin if(!(ap->pos=ap->cur)) 12298462SApril.Chin@Sun.COM ap->pos = (Namval_t*)dtfirst(ap->header.table); 12304887Schin } 12314887Schin else 12324887Schin ap->pos = ap->nextpos; 12334887Schin for(;ap->cur=ap->pos; ap->pos=ap->nextpos) 12344887Schin { 12358462SApril.Chin@Sun.COM ap->nextpos = (Namval_t*)dtnext(ap->header.table,ap->pos); 12364887Schin if(ap->cur->nvalue.cp) 12374887Schin { 12384887Schin if((ap->header.nelem&ARRAY_NOCHILD) && nv_isattr(ap->cur,NV_CHILD)) 12394887Schin continue; 12404887Schin return((void*)ap); 12414887Schin } 12424887Schin } 12438462SApril.Chin@Sun.COM if((ap->header.nelem&ARRAY_NOSCOPE) && ap->header.scope && !dtvnext(ap->header.table)) 12448462SApril.Chin@Sun.COM { 12458462SApril.Chin@Sun.COM ap->header.table->view = (Dt_t*)ap->header.scope; 12468462SApril.Chin@Sun.COM ap->header.scope = ap->header.table; 12478462SApril.Chin@Sun.COM } 12484887Schin return(NIL(void*)); 12494887Schin case NV_ASETSUB: 12504887Schin ap->cur = (Namval_t*)sp; 12518462SApril.Chin@Sun.COM return((void*)ap->cur); 12524887Schin case NV_ACURRENT: 12538462SApril.Chin@Sun.COM if(ap->cur) 12548462SApril.Chin@Sun.COM ap->cur->nvenv = (char*)np; 12554887Schin return((void*)ap->cur); 12564887Schin case NV_ANAME: 12574887Schin if(ap->cur) 12588462SApril.Chin@Sun.COM return((void*)ap->cur->nvname); 12594887Schin return(NIL(void*)); 12604887Schin default: 12614887Schin if(sp) 12624887Schin { 12638462SApril.Chin@Sun.COM Namval_t *mp=0; 12648462SApril.Chin@Sun.COM ap->cur = 0; 12654887Schin if(sp==(char*)np) 12668462SApril.Chin@Sun.COM return(0); 12678462SApril.Chin@Sun.COM type = nv_isattr(np,NV_PUBLIC&~(NV_ARRAY|NV_CHILD|NV_MINIMAL)); 12688462SApril.Chin@Sun.COM if(mode) 12698462SApril.Chin@Sun.COM mode = NV_ADD|HASH_NOSCOPE; 12708462SApril.Chin@Sun.COM else if(ap->header.nelem&ARRAY_NOSCOPE) 12718462SApril.Chin@Sun.COM mode = HASH_NOSCOPE; 12728462SApril.Chin@Sun.COM if(*sp==0 && (mode&NV_ADD)) 1273*10898Sroland.mainz@nrubsig.org errormsg(SH_DICT,ERROR_warn(0),"adding empty subscript"); 12748462SApril.Chin@Sun.COM if(sh.subshell && (mp=nv_search(sp,ap->header.table,0)) && nv_isnull(mp)) 12758462SApril.Chin@Sun.COM ap->cur = mp; 12768462SApril.Chin@Sun.COM if((mp || (mp=nv_search(sp,ap->header.table,mode))) && nv_isnull(mp) && (mode&NV_ADD)) 12774887Schin { 12788462SApril.Chin@Sun.COM nv_onattr(mp,type); 12798462SApril.Chin@Sun.COM mp->nvenv = (char*)np; 12808462SApril.Chin@Sun.COM if((mode&NV_ADD) && nv_type(np)) 12818462SApril.Chin@Sun.COM nv_arraychild(np,mp,0); 12828462SApril.Chin@Sun.COM if(sh.subshell) 12838462SApril.Chin@Sun.COM np = sh_assignok(np,1); 12848462SApril.Chin@Sun.COM if(!ap->header.scope || !nv_search(sp,dtvnext(ap->header.table),0)) 12858462SApril.Chin@Sun.COM ap->header.nelem++; 12868462SApril.Chin@Sun.COM if(nv_isnull(mp)) 12878462SApril.Chin@Sun.COM { 12888462SApril.Chin@Sun.COM if(ap->header.nelem&ARRAY_TREE) 12898462SApril.Chin@Sun.COM nv_setvtree(mp); 12908462SApril.Chin@Sun.COM mp->nvalue.cp = Empty; 12918462SApril.Chin@Sun.COM } 12924887Schin } 12938462SApril.Chin@Sun.COM else if(ap->header.nelem&ARRAY_SCAN) 12948462SApril.Chin@Sun.COM { 12958462SApril.Chin@Sun.COM Namval_t fake; 12968462SApril.Chin@Sun.COM fake.nvname = (char*)sp; 12978462SApril.Chin@Sun.COM ap->pos = mp = (Namval_t*)dtprev(ap->header.table,&fake); 12988462SApril.Chin@Sun.COM ap->nextpos = (Namval_t*)dtnext(ap->header.table,mp); 12998462SApril.Chin@Sun.COM } 13008462SApril.Chin@Sun.COM np = mp; 1301*10898Sroland.mainz@nrubsig.org if(ap->pos && ap->pos==np) 1302*10898Sroland.mainz@nrubsig.org ap->header.nelem |= ARRAY_SCAN; 1303*10898Sroland.mainz@nrubsig.org else if(!(ap->header.nelem&ARRAY_SCAN)) 13044887Schin ap->pos = 0; 13054887Schin ap->cur = np; 13064887Schin } 13074887Schin if(ap->cur) 13084887Schin return((void*)(&ap->cur->nvalue)); 13094887Schin else 13104887Schin return((void*)(&ap->cur)); 13114887Schin } 13124887Schin } 13134887Schin 13144887Schin /* 13154887Schin * Assign values to an array 13164887Schin */ 13174887Schin void nv_setvec(register Namval_t *np,int append,register int argc,register char *argv[]) 13184887Schin { 13194887Schin int arg0=0; 13208462SApril.Chin@Sun.COM struct index_array *ap=0,*aq; 13214887Schin if(nv_isarray(np)) 13224887Schin { 13234887Schin ap = (struct index_array*)nv_arrayptr(np); 13244887Schin if(ap && is_associative(ap)) 13258462SApril.Chin@Sun.COM errormsg(SH_DICT,ERROR_exit(1),"cannot append index array to associative array %s",nv_name(np)); 13264887Schin } 13274887Schin if(append) 13284887Schin { 13294887Schin if(ap) 13304887Schin { 13318462SApril.Chin@Sun.COM if(!(aq = (struct index_array*)ap->header.scope)) 13328462SApril.Chin@Sun.COM aq = ap; 13334887Schin arg0 = ap->maxi; 13348462SApril.Chin@Sun.COM while(--arg0>0 && ap->val[arg0].cp==0 && aq->val[arg0].cp==0); 13354887Schin arg0++; 13364887Schin } 13374887Schin else if(!nv_isnull(np)) 13384887Schin arg0=1; 13394887Schin } 13404887Schin while(--argc >= 0) 13414887Schin { 13428462SApril.Chin@Sun.COM nv_putsub(np,NIL(char*),(long)argc+arg0|ARRAY_FILL|ARRAY_ADD); 13434887Schin nv_putval(np,argv[argc],0); 13444887Schin } 13454887Schin } 13464887Schin 1347