14887Schin /*********************************************************************** 24887Schin * * 34887Schin * This software is part of the ast package * 4*12068SRoger.Faulkner@Oracle.COM * Copyright (c) 1982-2010 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 19210898Sroland.mainz@nrubsig.org int nv_arrayisset(Namval_t *np, Namarr_t *arp) 19310898Sroland.mainz@nrubsig.org { 19410898Sroland.mainz@nrubsig.org register struct index_array *ap = (struct index_array*)arp; 19510898Sroland.mainz@nrubsig.org union Value *up; 19610898Sroland.mainz@nrubsig.org if(is_associative(ap)) 19710898Sroland.mainz@nrubsig.org return((np = nv_opensub(np)) && !nv_isnull(np)); 19810898Sroland.mainz@nrubsig.org if(ap->cur >= ap->maxi) 19910898Sroland.mainz@nrubsig.org return(0); 20010898Sroland.mainz@nrubsig.org up = &(ap->val[ap->cur]); 20110898Sroland.mainz@nrubsig.org return(up->cp && up->cp!=Empty); 20210898Sroland.mainz@nrubsig.org } 20310898Sroland.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 { 289*12068SRoger.Faulkner@Oracle.COM char *xp = nv_setdisc(np,"get",np,(Namfun_t*)np); 2904887Schin if(flag!=ARRAY_ASSIGN) 291*12068SRoger.Faulkner@Oracle.COM return(xp && xp!=(char*)np?np:0); 2928462SApril.Chin@Sun.COM if(!array_covered(np,ap)) 2938462SApril.Chin@Sun.COM ap->header.nelem++; 2944887Schin } 2954887Schin return(np); 2964887Schin } 2974887Schin 2988462SApril.Chin@Sun.COM #if SHOPT_TYPEDEF 2998462SApril.Chin@Sun.COM int nv_arraysettype(Namval_t *np, Namval_t *tp, const char *sub, int flags) 3008462SApril.Chin@Sun.COM { 3018462SApril.Chin@Sun.COM Namval_t *nq; 3028462SApril.Chin@Sun.COM char *av[2]; 3038462SApril.Chin@Sun.COM int rdonly = nv_isattr(np,NV_RDONLY); 3048462SApril.Chin@Sun.COM int xtrace = sh_isoption(SH_XTRACE); 3058462SApril.Chin@Sun.COM Namarr_t *ap = nv_arrayptr(np); 3068462SApril.Chin@Sun.COM av[1] = 0; 3078462SApril.Chin@Sun.COM sh.last_table = 0; 3088462SApril.Chin@Sun.COM if(!ap->table) 3098462SApril.Chin@Sun.COM ap->table = dtopen(&_Nvdisc,Dtoset); 3108462SApril.Chin@Sun.COM if(nq = nv_search(sub, ap->table, NV_ADD)) 3118462SApril.Chin@Sun.COM { 3128462SApril.Chin@Sun.COM if(!nq->nvfun && nq->nvalue.cp && *nq->nvalue.cp==0) 3138462SApril.Chin@Sun.COM _nv_unset(nq,NV_RDONLY); 3148462SApril.Chin@Sun.COM nv_arraychild(np,nq,0); 3158462SApril.Chin@Sun.COM if(!nv_isattr(tp,NV_BINARY)) 3168462SApril.Chin@Sun.COM { 3178462SApril.Chin@Sun.COM sfprintf(sh.strbuf,"%s=%s",nv_name(nq),nv_getval(np)); 3188462SApril.Chin@Sun.COM av[0] = strdup(sfstruse(sh.strbuf)); 3198462SApril.Chin@Sun.COM } 3208462SApril.Chin@Sun.COM if(!nv_clone(tp,nq,flags|NV_NOFREE)) 3218462SApril.Chin@Sun.COM return(0); 3228462SApril.Chin@Sun.COM ap->nelem |= ARRAY_SCAN; 3238462SApril.Chin@Sun.COM if(!rdonly) 3248462SApril.Chin@Sun.COM nv_offattr(nq,NV_RDONLY); 3258462SApril.Chin@Sun.COM if(!nv_isattr(tp,NV_BINARY)) 3268462SApril.Chin@Sun.COM { 3278462SApril.Chin@Sun.COM if(xtrace) 3288462SApril.Chin@Sun.COM sh_offoption(SH_XTRACE); 3298462SApril.Chin@Sun.COM ap->nelem &= ~ARRAY_SCAN; 3308462SApril.Chin@Sun.COM sh_eval(sh_sfeval(av),0); 3318462SApril.Chin@Sun.COM ap->nelem |= ARRAY_SCAN; 3328462SApril.Chin@Sun.COM free((void*)av[0]); 3338462SApril.Chin@Sun.COM if(xtrace) 3348462SApril.Chin@Sun.COM sh_onoption(SH_XTRACE); 3358462SApril.Chin@Sun.COM } 3368462SApril.Chin@Sun.COM return(1); 3378462SApril.Chin@Sun.COM } 3388462SApril.Chin@Sun.COM return(0); 3398462SApril.Chin@Sun.COM } 3408462SApril.Chin@Sun.COM #endif /* SHOPT_TYPEDEF */ 3418462SApril.Chin@Sun.COM 3428462SApril.Chin@Sun.COM 3434887Schin static Namfun_t *array_clone(Namval_t *np, Namval_t *mp, int flags, Namfun_t *fp) 3444887Schin { 3454887Schin Namarr_t *ap = (Namarr_t*)fp; 3464887Schin Namval_t *nq, *mq; 3474887Schin char *name, *sub=0; 3488462SApril.Chin@Sun.COM int nelem, skipped=0; 3498462SApril.Chin@Sun.COM Dt_t *otable=ap->table; 3508462SApril.Chin@Sun.COM struct index_array *aq = (struct index_array*)ap, *ar; 3518462SApril.Chin@Sun.COM Shell_t *shp = sh_getinterp(); 3528462SApril.Chin@Sun.COM if(flags&NV_MOVE) 3538462SApril.Chin@Sun.COM { 3548462SApril.Chin@Sun.COM if((flags&NV_COMVAR) && nv_putsub(np,NIL(char*),ARRAY_SCAN)) 3558462SApril.Chin@Sun.COM { 3568462SApril.Chin@Sun.COM do 3578462SApril.Chin@Sun.COM { 3588462SApril.Chin@Sun.COM if(nq=nv_opensub(np)) 3598462SApril.Chin@Sun.COM nq->nvenv = (void*)mp; 3608462SApril.Chin@Sun.COM } 3618462SApril.Chin@Sun.COM while(nv_nextsub(np)); 3628462SApril.Chin@Sun.COM } 3638462SApril.Chin@Sun.COM return(fp); 3648462SApril.Chin@Sun.COM } 3658462SApril.Chin@Sun.COM nelem = ap->nelem; 3664887Schin if(nelem&ARRAY_NOCLONE) 3674887Schin return(0); 3688462SApril.Chin@Sun.COM if((flags&NV_TYPE) && !ap->scope) 3698462SApril.Chin@Sun.COM { 3708462SApril.Chin@Sun.COM ap = array_scope(np,ap,flags); 3718462SApril.Chin@Sun.COM return(&ap->hdr); 3728462SApril.Chin@Sun.COM } 3738462SApril.Chin@Sun.COM ap = (Namarr_t*)nv_clone_disc(fp,0); 3748462SApril.Chin@Sun.COM if(flags&NV_COMVAR) 3754887Schin { 3768462SApril.Chin@Sun.COM ap->scope = 0; 3778462SApril.Chin@Sun.COM ap->nelem = 0; 3788462SApril.Chin@Sun.COM sh.prev_table = sh.last_table; 3798462SApril.Chin@Sun.COM sh.prev_root = sh.last_root; 3804887Schin } 3818462SApril.Chin@Sun.COM if(ap->table) 3828462SApril.Chin@Sun.COM { 3838462SApril.Chin@Sun.COM ap->table = dtopen(&_Nvdisc,Dtoset); 3848462SApril.Chin@Sun.COM if(ap->scope && !(flags&NV_COMVAR)) 3858462SApril.Chin@Sun.COM { 3868462SApril.Chin@Sun.COM ap->scope = ap->table; 3878462SApril.Chin@Sun.COM dtview(ap->table, otable->view); 3888462SApril.Chin@Sun.COM } 3898462SApril.Chin@Sun.COM } 3908462SApril.Chin@Sun.COM mp->nvfun = (Namfun_t*)ap; 3918462SApril.Chin@Sun.COM mp->nvflag &= NV_MINIMAL; 3928462SApril.Chin@Sun.COM mp->nvflag |= (np->nvflag&~(NV_MINIMAL|NV_NOFREE)); 3934887Schin if(!(nelem&(ARRAY_SCAN|ARRAY_UNDEF)) && (sub=nv_getsub(np))) 3944887Schin sub = strdup(sub); 3954887Schin ar = (struct index_array*)ap; 3968462SApril.Chin@Sun.COM if(!is_associative(ap)) 3978462SApril.Chin@Sun.COM ar->bits = (unsigned char*)&ar->val[ar->maxi]; 3988462SApril.Chin@Sun.COM if(!nv_putsub(np,NIL(char*),ARRAY_SCAN|((flags&NV_COMVAR)?0:ARRAY_NOSCOPE))) 3998462SApril.Chin@Sun.COM { 4008462SApril.Chin@Sun.COM if(ap->fun) 4018462SApril.Chin@Sun.COM (*ap->fun)(np,(char*)np,0); 4028462SApril.Chin@Sun.COM skipped=1; 4038462SApril.Chin@Sun.COM goto skip; 4048462SApril.Chin@Sun.COM } 4054887Schin do 4064887Schin { 4078462SApril.Chin@Sun.COM name = nv_getsub(np); 4088462SApril.Chin@Sun.COM nv_putsub(mp,name,ARRAY_ADD|ARRAY_NOSCOPE); 4098462SApril.Chin@Sun.COM mq = 0; 4108462SApril.Chin@Sun.COM if(nq=nv_opensub(np)) 4118462SApril.Chin@Sun.COM mq = nv_search(name,ap->table,NV_ADD); 4128462SApril.Chin@Sun.COM if(nq && (flags&NV_COMVAR) && nv_isvtree(nq)) 4134887Schin { 4148462SApril.Chin@Sun.COM mq->nvalue.cp = 0; 4158462SApril.Chin@Sun.COM if(!is_associative(ap)) 4168462SApril.Chin@Sun.COM ar->val[ar->cur].np = mq; 4178462SApril.Chin@Sun.COM nv_clone(nq,mq,flags); 4188462SApril.Chin@Sun.COM } 4198462SApril.Chin@Sun.COM else if(flags&NV_ARRAY) 4208462SApril.Chin@Sun.COM { 4218462SApril.Chin@Sun.COM if((flags&NV_NOFREE) && !is_associative(ap)) 4228462SApril.Chin@Sun.COM array_setbit(aq->bits,aq->cur,ARRAY_NOFREE); 4238462SApril.Chin@Sun.COM else if(nq && (flags&NV_NOFREE)) 4244887Schin { 4258462SApril.Chin@Sun.COM mq->nvalue = nq->nvalue; 4268462SApril.Chin@Sun.COM nv_onattr(nq,NV_NOFREE); 4274887Schin } 4284887Schin } 4294887Schin else if(nv_isattr(np,NV_INTEGER)) 4304887Schin { 4314887Schin Sfdouble_t d= nv_getnum(np); 4328462SApril.Chin@Sun.COM if(!is_associative(ap)) 4338462SApril.Chin@Sun.COM ar->val[ar->cur].cp = 0; 4344887Schin nv_putval(mp,(char*)&d,NV_LDOUBLE); 4354887Schin } 4364887Schin else 4378462SApril.Chin@Sun.COM { 4388462SApril.Chin@Sun.COM if(!is_associative(ap)) 4398462SApril.Chin@Sun.COM ar->val[ar->cur].cp = 0; 4404887Schin nv_putval(mp,nv_getval(np),NV_RDONLY); 4418462SApril.Chin@Sun.COM } 4428462SApril.Chin@Sun.COM aq->header.nelem |= ARRAY_NOSCOPE; 4434887Schin } 4444887Schin while(nv_nextsub(np)); 4458462SApril.Chin@Sun.COM skip: 4464887Schin if(sub) 4474887Schin { 4488462SApril.Chin@Sun.COM if(!skipped) 4498462SApril.Chin@Sun.COM nv_putsub(np,sub,0L); 4504887Schin free((void*)sub); 4514887Schin } 4528462SApril.Chin@Sun.COM aq->header.nelem = ap->nelem = nelem; 4538462SApril.Chin@Sun.COM return(&ap->hdr); 4544887Schin } 4554887Schin 4564887Schin static char *array_getval(Namval_t *np, Namfun_t *disc) 4574887Schin { 4588462SApril.Chin@Sun.COM register Namarr_t *aq,*ap = (Namarr_t*)disc; 4594887Schin register Namval_t *mp; 4604887Schin if((mp=array_find(np,ap,ARRAY_LOOKUP))!=np) 4618462SApril.Chin@Sun.COM { 4628462SApril.Chin@Sun.COM if(!mp && !is_associative(ap) && (aq=(Namarr_t*)ap->scope)) 4638462SApril.Chin@Sun.COM { 4648462SApril.Chin@Sun.COM array_syncsub(aq,ap); 4658462SApril.Chin@Sun.COM if((mp=array_find(np,aq,ARRAY_LOOKUP))==np) 4668462SApril.Chin@Sun.COM return(nv_getv(np,&aq->hdr)); 4678462SApril.Chin@Sun.COM } 4684887Schin return(mp?nv_getval(mp):0); 4698462SApril.Chin@Sun.COM } 4704887Schin return(nv_getv(np,&ap->hdr)); 4714887Schin } 4724887Schin 4734887Schin static Sfdouble_t array_getnum(Namval_t *np, Namfun_t *disc) 4744887Schin { 4758462SApril.Chin@Sun.COM register Namarr_t *aq,*ap = (Namarr_t*)disc; 4764887Schin register Namval_t *mp; 4774887Schin if((mp=array_find(np,ap,ARRAY_LOOKUP))!=np) 4788462SApril.Chin@Sun.COM { 4798462SApril.Chin@Sun.COM if(!mp && !is_associative(ap) && (aq=(Namarr_t*)ap->scope)) 4808462SApril.Chin@Sun.COM { 4818462SApril.Chin@Sun.COM array_syncsub(aq,ap); 4828462SApril.Chin@Sun.COM if((mp=array_find(np,aq,ARRAY_LOOKUP))==np) 4838462SApril.Chin@Sun.COM return(nv_getn(np,&aq->hdr)); 4848462SApril.Chin@Sun.COM } 4854887Schin return(mp?nv_getnum(mp):0); 4868462SApril.Chin@Sun.COM } 4874887Schin return(nv_getn(np,&ap->hdr)); 4884887Schin } 4894887Schin 4904887Schin static void array_putval(Namval_t *np, const char *string, int flags, Namfun_t *dp) 4914887Schin { 4924887Schin register Namarr_t *ap = (Namarr_t*)dp; 4934887Schin register union Value *up; 4944887Schin register Namval_t *mp; 4954887Schin register struct index_array *aq = (struct index_array*)ap; 4968462SApril.Chin@Sun.COM int scan,nofree = nv_isattr(np,NV_NOFREE); 4974887Schin do 4984887Schin { 4994887Schin mp = array_find(np,ap,string?ARRAY_ASSIGN:ARRAY_DELETE); 5008462SApril.Chin@Sun.COM scan = ap->nelem&ARRAY_SCAN; 5014887Schin if(mp && mp!=np) 5028462SApril.Chin@Sun.COM { 50310898Sroland.mainz@nrubsig.org if(!is_associative(ap) && string && !(flags&NV_APPEND) && !nv_type(np) && nv_isvtree(mp)) 5048462SApril.Chin@Sun.COM { 5058462SApril.Chin@Sun.COM if(!nv_isattr(np,NV_NOFREE)) 5068462SApril.Chin@Sun.COM _nv_unset(mp,flags&NV_RDONLY); 5078462SApril.Chin@Sun.COM array_clrbit(aq->bits,aq->cur,ARRAY_CHILD); 5088462SApril.Chin@Sun.COM aq->val[aq->cur].cp = 0; 5098462SApril.Chin@Sun.COM if(!nv_isattr(mp,NV_NOFREE)) 5108462SApril.Chin@Sun.COM nv_delete(mp,ap->table,0); 5118462SApril.Chin@Sun.COM goto skip; 5128462SApril.Chin@Sun.COM } 5134887Schin nv_putval(mp, string, flags); 5148462SApril.Chin@Sun.COM if(string) 5158462SApril.Chin@Sun.COM { 5168462SApril.Chin@Sun.COM #if SHOPT_TYPEDEF 5178462SApril.Chin@Sun.COM if(ap->hdr.type && ap->hdr.type!=nv_type(mp)) 5188462SApril.Chin@Sun.COM nv_arraysettype(np,ap->hdr.type,nv_getsub(np),0); 5198462SApril.Chin@Sun.COM #endif /* SHOPT_TYPEDEF */ 5208462SApril.Chin@Sun.COM continue; 5218462SApril.Chin@Sun.COM } 5228462SApril.Chin@Sun.COM ap->nelem |= scan; 5238462SApril.Chin@Sun.COM } 5244887Schin if(!string) 5254887Schin { 5264887Schin if(mp) 5274887Schin { 5288462SApril.Chin@Sun.COM if(is_associative(ap)) 5294887Schin { 5304887Schin (*ap->fun)(np,NIL(char*),NV_ADELETE); 5318462SApril.Chin@Sun.COM np->nvalue.cp = 0; 5328462SApril.Chin@Sun.COM } 5338462SApril.Chin@Sun.COM else 5344887Schin { 5358462SApril.Chin@Sun.COM if(mp!=np) 5368462SApril.Chin@Sun.COM { 5378462SApril.Chin@Sun.COM array_clrbit(aq->bits,aq->cur,ARRAY_CHILD); 5388462SApril.Chin@Sun.COM aq->val[aq->cur].cp = 0; 5398462SApril.Chin@Sun.COM nv_delete(mp,ap->table,0); 5408462SApril.Chin@Sun.COM } 5418462SApril.Chin@Sun.COM if(!array_covered(np,(struct index_array*)ap)) 5428462SApril.Chin@Sun.COM ap->nelem--; 5434887Schin } 5444887Schin } 54510898Sroland.mainz@nrubsig.org if(array_elem(ap)==0 && (ap->nelem&ARRAY_SCAN)) 5464887Schin { 5474887Schin if(is_associative(ap)) 5484887Schin (*ap->fun)(np, NIL(char*), NV_AFREE); 5498462SApril.Chin@Sun.COM else if(ap->table) 5508462SApril.Chin@Sun.COM dtclose(ap->table); 5514887Schin nv_offattr(np,NV_ARRAY); 5524887Schin } 5538462SApril.Chin@Sun.COM if(!mp || mp!=np || is_associative(ap)) 5544887Schin continue; 5554887Schin } 5568462SApril.Chin@Sun.COM skip: 5574887Schin /* prevent empty string from being deleted */ 5588462SApril.Chin@Sun.COM up = array_getup(np,ap,!nofree); 5598462SApril.Chin@Sun.COM if(up->cp == Empty) 5608462SApril.Chin@Sun.COM up->cp = 0; 5618462SApril.Chin@Sun.COM if(nv_isarray(np)) 5628462SApril.Chin@Sun.COM np->nvalue.up = up; 5634887Schin nv_putv(np,string,flags,&ap->hdr); 5648462SApril.Chin@Sun.COM if(!is_associative(ap)) 5658462SApril.Chin@Sun.COM { 5668462SApril.Chin@Sun.COM if(string) 5678462SApril.Chin@Sun.COM array_clrbit(aq->bits,aq->cur,ARRAY_NOFREE); 5688462SApril.Chin@Sun.COM else if(mp==np) 5698462SApril.Chin@Sun.COM aq->val[aq->cur].cp = 0; 5708462SApril.Chin@Sun.COM } 5718462SApril.Chin@Sun.COM #if SHOPT_TYPEDEF 5728462SApril.Chin@Sun.COM if(string && ap->hdr.type && nv_isvtree(np)) 5738462SApril.Chin@Sun.COM nv_arraysettype(np,ap->hdr.type,nv_getsub(np),0); 5748462SApril.Chin@Sun.COM #endif /* SHOPT_TYPEDEF */ 5754887Schin } 5764887Schin while(!string && nv_nextsub(np)); 5778462SApril.Chin@Sun.COM if(ap) 5788462SApril.Chin@Sun.COM ap->nelem &= ~ARRAY_NOSCOPE; 5798462SApril.Chin@Sun.COM if(nofree) 5808462SApril.Chin@Sun.COM nv_onattr(np,NV_NOFREE); 5818462SApril.Chin@Sun.COM else 5828462SApril.Chin@Sun.COM nv_offattr(np,NV_NOFREE); 5834887Schin if(!string && !nv_isattr(np,NV_ARRAY)) 5844887Schin { 5854887Schin Namfun_t *nfp; 5868462SApril.Chin@Sun.COM if(!is_associative(ap) && aq->xp) 5878462SApril.Chin@Sun.COM { 5888462SApril.Chin@Sun.COM _nv_unset(nv_namptr(aq->xp,0),NV_RDONLY); 5898462SApril.Chin@Sun.COM free((void*)aq->xp); 5908462SApril.Chin@Sun.COM } 5918462SApril.Chin@Sun.COM if((nfp = nv_disc(np,(Namfun_t*)ap,NV_POP)) && !(nfp->nofree&1)) 5924887Schin free((void*)nfp); 5938462SApril.Chin@Sun.COM if(!nv_isnull(np)) 5948462SApril.Chin@Sun.COM { 5958462SApril.Chin@Sun.COM nv_onattr(np,NV_NOFREE); 5968462SApril.Chin@Sun.COM _nv_unset(np,flags); 5978462SApril.Chin@Sun.COM } 5988462SApril.Chin@Sun.COM if(np->nvalue.cp==Empty) 5998462SApril.Chin@Sun.COM np->nvalue.cp = 0; 6004887Schin } 6018462SApril.Chin@Sun.COM if(!string && (flags&NV_TYPE)) 6028462SApril.Chin@Sun.COM array_unscope(np,ap); 6034887Schin } 6044887Schin 6054887Schin static const Namdisc_t array_disc = 6064887Schin { 6074887Schin sizeof(Namarr_t), 6084887Schin array_putval, 6094887Schin array_getval, 6104887Schin array_getnum, 6114887Schin 0, 6124887Schin 0, 6134887Schin array_clone 6144887Schin }; 6154887Schin 6168462SApril.Chin@Sun.COM static void array_copytree(Namval_t *np, Namval_t *mp) 6178462SApril.Chin@Sun.COM { 6188462SApril.Chin@Sun.COM Namfun_t *fp = nv_disc(np,NULL,NV_POP); 6198462SApril.Chin@Sun.COM nv_offattr(np,NV_ARRAY); 6208462SApril.Chin@Sun.COM nv_clone(np,mp,0); 62110898Sroland.mainz@nrubsig.org if(np->nvalue.cp && !nv_isattr(np,NV_NOFREE)) 62210898Sroland.mainz@nrubsig.org free((void*)np->nvalue.cp); 62310898Sroland.mainz@nrubsig.org np->nvalue.cp = 0; 6248462SApril.Chin@Sun.COM np->nvalue.up = &mp->nvalue; 6258462SApril.Chin@Sun.COM fp->nofree &= ~1; 6268462SApril.Chin@Sun.COM nv_disc(np,(Namfun_t*)fp, NV_FIRST); 6278462SApril.Chin@Sun.COM fp->nofree |= 1; 6288462SApril.Chin@Sun.COM nv_onattr(np,NV_ARRAY); 6298462SApril.Chin@Sun.COM mp->nvenv = (char*)np; 6308462SApril.Chin@Sun.COM } 6318462SApril.Chin@Sun.COM 6324887Schin /* 6334887Schin * Increase the size of the indexed array of elements in <arp> 6344887Schin * so that <maxi> is a legal index. If <arp> is 0, an array 6354887Schin * of the required size is allocated. A pointer to the 6364887Schin * allocated Namarr_t structure is returned. 6374887Schin * <maxi> becomes the current index of the array. 6384887Schin */ 6394887Schin static struct index_array *array_grow(Namval_t *np, register struct index_array *arp,int maxi) 6404887Schin { 6414887Schin register struct index_array *ap; 6428462SApril.Chin@Sun.COM register int i; 6438462SApril.Chin@Sun.COM register int newsize = arsize(arp,maxi+1); 6444887Schin if (maxi >= ARRAY_MAX) 6454887Schin errormsg(SH_DICT,ERROR_exit(1),e_subscript, fmtbase((long)maxi,10,0)); 6468462SApril.Chin@Sun.COM i = (newsize-1)*sizeof(union Value*)+newsize; 6478462SApril.Chin@Sun.COM ap = new_of(struct index_array,i); 6488462SApril.Chin@Sun.COM memset((void*)ap,0,sizeof(*ap)+i); 6494887Schin ap->maxi = newsize; 6504887Schin ap->cur = maxi; 6514887Schin ap->bits = (unsigned char*)&ap->val[newsize]; 6528462SApril.Chin@Sun.COM memset(ap->bits, 0, newsize); 6534887Schin if(arp) 6544887Schin { 6554887Schin ap->header = arp->header; 6568462SApril.Chin@Sun.COM ap->header.hdr.dsize = sizeof(*ap) + i; 6578462SApril.Chin@Sun.COM for(i=0;i < arp->maxi;i++) 6584887Schin ap->val[i].cp = arp->val[i].cp; 6598462SApril.Chin@Sun.COM memcpy(ap->bits, arp->bits, arp->maxi); 6604887Schin array_setptr(np,arp,ap); 6614887Schin free((void*)arp); 6624887Schin } 6634887Schin else 6644887Schin { 6658462SApril.Chin@Sun.COM Namval_t *mp=0; 6668462SApril.Chin@Sun.COM ap->header.hdr.dsize = sizeof(*ap) + i; 6678462SApril.Chin@Sun.COM i = 0; 6684887Schin ap->header.fun = 0; 6698462SApril.Chin@Sun.COM if(nv_isnull(np) && nv_isattr(np,NV_NOFREE)) 6704887Schin { 6718462SApril.Chin@Sun.COM i = ARRAY_TREE; 6728462SApril.Chin@Sun.COM nv_offattr(np,NV_NOFREE); 6738462SApril.Chin@Sun.COM } 6748462SApril.Chin@Sun.COM if(np->nvalue.cp==Empty) 6758462SApril.Chin@Sun.COM np->nvalue.cp=0; 6768462SApril.Chin@Sun.COM if(nv_hasdisc(np,&array_disc) || nv_isvtree(np)) 6778462SApril.Chin@Sun.COM { 6788462SApril.Chin@Sun.COM ap->header.table = dtopen(&_Nvdisc,Dtoset); 67910898Sroland.mainz@nrubsig.org mp = nv_search("0", ap->header.table,NV_ADD); 6804887Schin if(mp && nv_isnull(mp)) 6814887Schin { 6828462SApril.Chin@Sun.COM Namfun_t *fp; 6834887Schin ap->val[0].np = mp; 6848462SApril.Chin@Sun.COM array_setbit(ap->bits,0,ARRAY_CHILD); 6858462SApril.Chin@Sun.COM for(fp=np->nvfun; fp && !fp->disc->readf; fp=fp->next); 68610898Sroland.mainz@nrubsig.org if(fp && fp->disc && fp->disc->readf) 6878462SApril.Chin@Sun.COM (*fp->disc->readf)(mp,(Sfio_t*)0,0,fp); 6888462SApril.Chin@Sun.COM i++; 6894887Schin } 6908462SApril.Chin@Sun.COM } 6918462SApril.Chin@Sun.COM else if((ap->val[0].cp=np->nvalue.cp)) 6924887Schin i++; 69310898Sroland.mainz@nrubsig.org else if(nv_isattr(np,NV_INTEGER) && !nv_isnull(np)) 6944887Schin { 6954887Schin Sfdouble_t d= nv_getnum(np); 6964887Schin i++; 6974887Schin } 6984887Schin ap->header.nelem = i; 6994887Schin ap->header.hdr.disc = &array_disc; 7008462SApril.Chin@Sun.COM nv_disc(np,(Namfun_t*)ap, NV_FIRST); 7018462SApril.Chin@Sun.COM nv_onattr(np,NV_ARRAY); 7028462SApril.Chin@Sun.COM if(mp) 7038462SApril.Chin@Sun.COM { 7048462SApril.Chin@Sun.COM array_copytree(np,mp); 7058462SApril.Chin@Sun.COM ap->header.hdr.nofree &= ~1; 7068462SApril.Chin@Sun.COM } 7074887Schin } 7084887Schin for(;i < newsize;i++) 7094887Schin ap->val[i].cp = 0; 7104887Schin return(ap); 7114887Schin } 7124887Schin 7138462SApril.Chin@Sun.COM int nv_atypeindex(Namval_t *np, const char *tname) 7148462SApril.Chin@Sun.COM { 7158462SApril.Chin@Sun.COM Namval_t *tp; 7168462SApril.Chin@Sun.COM int offset = staktell(); 7178462SApril.Chin@Sun.COM int n = strlen(tname)-1; 7188462SApril.Chin@Sun.COM sfprintf(stkstd,"%s.%.*s%c",NV_CLASS,n,tname,0); 7198462SApril.Chin@Sun.COM tp = nv_open(stakptr(offset), sh.var_tree, NV_NOADD|NV_VARNAME); 7208462SApril.Chin@Sun.COM stakseek(offset); 7218462SApril.Chin@Sun.COM if(tp) 7228462SApril.Chin@Sun.COM { 7238462SApril.Chin@Sun.COM struct index_array *ap = (struct index_array*)nv_arrayptr(np); 7248462SApril.Chin@Sun.COM if(!nv_hasdisc(tp,&ENUM_disc)) 7258462SApril.Chin@Sun.COM errormsg(SH_DICT,ERROR_exit(1),e_notenum,tp->nvname); 7268462SApril.Chin@Sun.COM if(!ap) 7278462SApril.Chin@Sun.COM ap = array_grow(np,ap,1); 7288462SApril.Chin@Sun.COM ap->xp = calloc(NV_MINSZ,1); 7298462SApril.Chin@Sun.COM np = nv_namptr(ap->xp,0); 7308462SApril.Chin@Sun.COM np->nvname = tp->nvname; 7318462SApril.Chin@Sun.COM nv_onattr(np,NV_MINIMAL); 7328462SApril.Chin@Sun.COM nv_clone(tp,np,NV_NOFREE); 7338462SApril.Chin@Sun.COM nv_offattr(np,NV_RDONLY); 7348462SApril.Chin@Sun.COM return(1); 7358462SApril.Chin@Sun.COM } 7368462SApril.Chin@Sun.COM errormsg(SH_DICT,ERROR_exit(1),e_unknowntype, n,tname); 7378462SApril.Chin@Sun.COM return(0); 7388462SApril.Chin@Sun.COM } 7398462SApril.Chin@Sun.COM 7404887Schin Namarr_t *nv_arrayptr(register Namval_t *np) 7414887Schin { 7424887Schin if(nv_isattr(np,NV_ARRAY)) 7434887Schin return((Namarr_t*)nv_hasdisc(np, &array_disc)); 7444887Schin return(0); 7454887Schin } 7464887Schin 7474887Schin /* 7484887Schin * Verify that argument is an indexed array and convert to associative, 7494887Schin * freeing relevant storage 7504887Schin */ 7514887Schin static Namarr_t *nv_changearray(Namval_t *np, void *(*fun)(Namval_t*,const char*,int)) 7524887Schin { 7534887Schin register Namarr_t *ap; 7544887Schin char numbuff[NUMSIZE+1]; 7554887Schin unsigned dot, digit, n; 7564887Schin union Value *up; 7574887Schin struct index_array *save_ap; 7584887Schin register char *string_index=&numbuff[NUMSIZE]; 7594887Schin numbuff[NUMSIZE]='\0'; 7604887Schin 7614887Schin if(!fun || !(ap = nv_arrayptr(np)) || is_associative(ap)) 7624887Schin return(NIL(Namarr_t*)); 7634887Schin 7644887Schin nv_stack(np,&ap->hdr); 7654887Schin save_ap = (struct index_array*)nv_stack(np,0); 7664887Schin ap = (Namarr_t*)((*fun)(np, NIL(char*), NV_AINIT)); 7674887Schin ap->nelem = 0; 7684887Schin ap->fun = fun; 7694887Schin nv_onattr(np,NV_ARRAY); 7704887Schin 7714887Schin for(dot = 0; dot < (unsigned)save_ap->maxi; dot++) 7724887Schin { 7734887Schin if(save_ap->val[dot].cp) 7744887Schin { 7754887Schin if ((digit = dot)== 0) 7764887Schin *--string_index = '0'; 7774887Schin else while( n = digit ) 7784887Schin { 7794887Schin digit /= 10; 7804887Schin *--string_index = '0' + (n-10*digit); 7814887Schin } 7824887Schin nv_putsub(np, string_index, ARRAY_ADD); 7834887Schin up = (union Value*)((*ap->fun)(np,NIL(char*),0)); 7844887Schin up->cp = save_ap->val[dot].cp; 7854887Schin save_ap->val[dot].cp = 0; 7864887Schin } 7874887Schin string_index = &numbuff[NUMSIZE]; 7884887Schin } 7894887Schin free((void*)save_ap); 7904887Schin return(ap); 7914887Schin } 7924887Schin 7934887Schin /* 7944887Schin * set the associative array processing method for node <np> to <fun> 7954887Schin * The array pointer is returned if sucessful. 7964887Schin */ 7974887Schin Namarr_t *nv_setarray(Namval_t *np, void *(*fun)(Namval_t*,const char*,int)) 7984887Schin { 7994887Schin register Namarr_t *ap; 8008462SApril.Chin@Sun.COM char *value=0; 8018462SApril.Chin@Sun.COM Namfun_t *fp; 8028462SApril.Chin@Sun.COM int nelem = 0; 8034887Schin if(fun && (ap = nv_arrayptr(np))) 8044887Schin { 8054887Schin /* 8064887Schin * if it's already an indexed array, convert to 8074887Schin * associative structure 8084887Schin */ 8094887Schin if(!is_associative(ap)) 8104887Schin ap = nv_changearray(np, fun); 8114887Schin return(ap); 8124887Schin } 8138462SApril.Chin@Sun.COM if(nv_isnull(np) && nv_isattr(np,NV_NOFREE)) 8148462SApril.Chin@Sun.COM { 8158462SApril.Chin@Sun.COM nelem = ARRAY_TREE; 8168462SApril.Chin@Sun.COM nv_offattr(np,NV_NOFREE); 8178462SApril.Chin@Sun.COM } 8188462SApril.Chin@Sun.COM if(!(fp=nv_isvtree(np))) 8198462SApril.Chin@Sun.COM value = nv_getval(np); 8204887Schin if(fun && !ap && (ap = (Namarr_t*)((*fun)(np, NIL(char*), NV_AINIT)))) 8214887Schin { 8224887Schin /* check for preexisting initialization and save */ 8238462SApril.Chin@Sun.COM ap->nelem = nelem; 8244887Schin ap->fun = fun; 8254887Schin nv_onattr(np,NV_ARRAY); 8268462SApril.Chin@Sun.COM if(fp || value) 8274887Schin { 8284887Schin nv_putsub(np, "0", ARRAY_ADD); 8298462SApril.Chin@Sun.COM if(value) 8308462SApril.Chin@Sun.COM nv_putval(np, value, 0); 8318462SApril.Chin@Sun.COM else 8328462SApril.Chin@Sun.COM { 8338462SApril.Chin@Sun.COM Namval_t *mp = (Namval_t*)((*fun)(np,NIL(char*),NV_ACURRENT)); 8348462SApril.Chin@Sun.COM array_copytree(np,mp); 8358462SApril.Chin@Sun.COM } 8364887Schin } 8374887Schin return(ap); 8384887Schin } 8394887Schin return(NIL(Namarr_t*)); 8404887Schin } 8414887Schin 8424887Schin /* 8434887Schin * move parent subscript into child 8444887Schin */ 8454887Schin Namval_t *nv_arraychild(Namval_t *np, Namval_t *nq, int c) 8464887Schin { 8478462SApril.Chin@Sun.COM Namfun_t *fp; 8488462SApril.Chin@Sun.COM register Namarr_t *ap = nv_arrayptr(np); 8498462SApril.Chin@Sun.COM union Value *up; 8508462SApril.Chin@Sun.COM Namval_t *tp; 8518462SApril.Chin@Sun.COM if(!nq) 8528462SApril.Chin@Sun.COM return(ap?array_find(np,ap, ARRAY_LOOKUP):0); 8538462SApril.Chin@Sun.COM if(!ap) 8548462SApril.Chin@Sun.COM { 8558462SApril.Chin@Sun.COM nv_putsub(np, NIL(char*), ARRAY_FILL); 8568462SApril.Chin@Sun.COM ap = nv_arrayptr(np); 8578462SApril.Chin@Sun.COM } 8588462SApril.Chin@Sun.COM if(!(up = array_getup(np,ap,0))) 8594887Schin return((Namval_t*)0); 8604887Schin np->nvalue.cp = up->cp; 8618462SApril.Chin@Sun.COM if((tp=nv_type(np)) || c) 8624887Schin { 8638462SApril.Chin@Sun.COM ap->nelem |= ARRAY_NOCLONE; 8648462SApril.Chin@Sun.COM nq->nvenv = (char*)np; 8658462SApril.Chin@Sun.COM if(c=='t') 8668462SApril.Chin@Sun.COM nv_clone(tp,nq, 0); 8678462SApril.Chin@Sun.COM else 8688462SApril.Chin@Sun.COM nv_clone(np, nq, NV_NODISC); 8698462SApril.Chin@Sun.COM nv_offattr(nq,NV_ARRAY); 8708462SApril.Chin@Sun.COM ap->nelem &= ~ARRAY_NOCLONE; 8714887Schin } 8728462SApril.Chin@Sun.COM nq->nvenv = (char*)np; 8738462SApril.Chin@Sun.COM if((fp=nq->nvfun) && fp->disc && fp->disc->setdisc && (fp = nv_disc(nq,fp,NV_POP))) 8748462SApril.Chin@Sun.COM free((void*)fp); 8758462SApril.Chin@Sun.COM if(!ap->fun) 8764887Schin { 8774887Schin struct index_array *aq = (struct index_array*)ap; 8788462SApril.Chin@Sun.COM array_setbit(aq->bits,aq->cur,ARRAY_CHILD); 8794887Schin up->np = nq; 8804887Schin } 8814887Schin if(c=='.') 8824887Schin nv_setvtree(nq); 8834887Schin return(nq); 8844887Schin } 8854887Schin 8864887Schin /* 8874887Schin * This routine sets subscript of <np> to the next element, if any. 8884887Schin * The return value is zero, if there are no more elements 8894887Schin * Otherwise, 1 is returned. 8904887Schin */ 8914887Schin int nv_nextsub(Namval_t *np) 8924887Schin { 8938462SApril.Chin@Sun.COM register struct index_array *ap = (struct index_array*)nv_arrayptr(np); 8948462SApril.Chin@Sun.COM register unsigned dot; 8958462SApril.Chin@Sun.COM struct index_array *aq=0, *ar=0; 8964887Schin if(!ap || !(ap->header.nelem&ARRAY_SCAN)) 8974887Schin return(0); 8984887Schin if(is_associative(ap)) 8994887Schin { 9008462SApril.Chin@Sun.COM Namval_t *nq; 9018462SApril.Chin@Sun.COM if(nq=(*ap->header.fun)(np,NIL(char*),NV_ANEXT)) 9024887Schin { 9038462SApril.Chin@Sun.COM if(nv_isattr(nq,NV_CHILD)) 9048462SApril.Chin@Sun.COM nv_putsub(nq->nvalue.np,NIL(char*),ARRAY_UNDEF); 9054887Schin return(1); 9064887Schin } 9074887Schin ap->header.nelem &= ~(ARRAY_SCAN|ARRAY_NOCHILD); 9084887Schin return(0); 9094887Schin } 9108462SApril.Chin@Sun.COM if(!(ap->header.nelem&ARRAY_NOSCOPE)) 9118462SApril.Chin@Sun.COM ar = (struct index_array*)ap->header.scope; 9124887Schin for(dot=ap->cur+1; dot < (unsigned)ap->maxi; dot++) 9134887Schin { 9148462SApril.Chin@Sun.COM aq = ap; 9158462SApril.Chin@Sun.COM if(!ap->val[dot].cp && !(ap->header.nelem&ARRAY_NOSCOPE)) 9168462SApril.Chin@Sun.COM { 9178462SApril.Chin@Sun.COM if(!(aq=ar) || dot>=(unsigned)aq->maxi) 9188462SApril.Chin@Sun.COM continue; 9198462SApril.Chin@Sun.COM } 9208462SApril.Chin@Sun.COM if(aq->val[dot].cp) 9214887Schin { 9224887Schin ap->cur = dot; 9238462SApril.Chin@Sun.COM if(array_isbit(aq->bits, dot,ARRAY_CHILD)) 9244887Schin { 9258462SApril.Chin@Sun.COM Namval_t *mp = aq->val[dot].np; 926*12068SRoger.Faulkner@Oracle.COM if((aq->header.nelem&ARRAY_NOCHILD) && nv_isvtree(mp) && !mp->nvfun->dsize) 9274887Schin continue; 928*12068SRoger.Faulkner@Oracle.COM if(nv_isarray(mp)) 929*12068SRoger.Faulkner@Oracle.COM nv_putsub(mp,NIL(char*),ARRAY_UNDEF); 9304887Schin } 9314887Schin return(1); 9324887Schin } 9334887Schin } 9344887Schin ap->header.nelem &= ~(ARRAY_SCAN|ARRAY_NOCHILD); 9354887Schin ap->cur = 0; 9364887Schin return(0); 9374887Schin } 9384887Schin 9394887Schin /* 9404887Schin * Set an array subscript for node <np> given the subscript <sp> 9414887Schin * An array is created if necessary. 9424887Schin * <mode> can be a number, plus or more of symbolic constants 9434887Schin * ARRAY_SCAN, ARRAY_UNDEF, ARRAY_ADD 9444887Schin * The node pointer is returned which can be NULL if <np> is 9454887Schin * not already array and the ARRAY_ADD bit of <mode> is not set. 9464887Schin * ARRAY_FILL sets the specified subscript to the empty string when 9474887Schin * ARRAY_ADD is specified and there is no value or sets all 9484887Schin * the elements up to the number specified if ARRAY_ADD is not specified 9494887Schin */ 9504887Schin Namval_t *nv_putsub(Namval_t *np,register char *sp,register long mode) 9514887Schin { 9524887Schin register struct index_array *ap = (struct index_array*)nv_arrayptr(np); 9534887Schin register int size = (mode&ARRAY_MASK); 9544887Schin if(!ap || !ap->header.fun) 9554887Schin { 9564887Schin if(sp) 9578462SApril.Chin@Sun.COM { 9588462SApril.Chin@Sun.COM if(ap && ap->xp && !strmatch(sp,"+([0-9])")) 9598462SApril.Chin@Sun.COM { 9608462SApril.Chin@Sun.COM Namval_t *mp = nv_namptr(ap->xp,0); 9618462SApril.Chin@Sun.COM nv_putval(mp, sp,0); 9628462SApril.Chin@Sun.COM size = nv_getnum(mp); 9638462SApril.Chin@Sun.COM } 9648462SApril.Chin@Sun.COM else 9658462SApril.Chin@Sun.COM size = (int)sh_arith((char*)sp); 9668462SApril.Chin@Sun.COM } 9678462SApril.Chin@Sun.COM if(size <0 && ap) 9688462SApril.Chin@Sun.COM size += array_maxindex(np); 9694887Schin if(size >= ARRAY_MAX || (size < 0)) 9704887Schin { 9714887Schin errormsg(SH_DICT,ERROR_exit(1),e_subscript, nv_name(np)); 9724887Schin return(NIL(Namval_t*)); 9734887Schin } 9744887Schin if(!ap || size>=ap->maxi) 9754887Schin { 9764887Schin if(size==0 && !(mode&ARRAY_FILL)) 9774887Schin return(NIL(Namval_t*)); 9784887Schin if(sh.subshell) 9794887Schin np = sh_assignok(np,1); 9804887Schin ap = array_grow(np, ap,size); 9814887Schin } 9824887Schin ap->header.nelem &= ~ARRAY_UNDEF; 9838462SApril.Chin@Sun.COM ap->header.nelem |= (mode&(ARRAY_SCAN|ARRAY_NOCHILD|ARRAY_UNDEF|ARRAY_NOSCOPE)); 9848462SApril.Chin@Sun.COM #if 0 9858462SApril.Chin@Sun.COM if(array_isbit(ap->bits,oldsize,ARRAY_CHILD)) 9868462SApril.Chin@Sun.COM mp = ap->val[oldsize].np; 9878462SApril.Chin@Sun.COM if(size != oldsize && mp->nvalue.cp) 9888462SApril.Chin@Sun.COM { 9898462SApril.Chin@Sun.COM Namfun_t *nfp; 9908462SApril.Chin@Sun.COM for(nfp=np->nvfun; nfp; nfp=nfp->next) 9918462SApril.Chin@Sun.COM { 9928462SApril.Chin@Sun.COM if(nfp->disc && nfp->disc->readf) 9938462SApril.Chin@Sun.COM { 9948462SApril.Chin@Sun.COM (*nfp->disc->readf)(mp,(Sfio_t*)0,0,nfp); 9958462SApril.Chin@Sun.COM break; 9968462SApril.Chin@Sun.COM } 9978462SApril.Chin@Sun.COM } 9988462SApril.Chin@Sun.COM } 9998462SApril.Chin@Sun.COM #endif 10004887Schin ap->cur = size; 10018462SApril.Chin@Sun.COM if((mode&ARRAY_SCAN) && (ap->cur--,!nv_nextsub(np))) 10024887Schin np = 0; 10038462SApril.Chin@Sun.COM if(mode&(ARRAY_FILL|ARRAY_ADD)) 10044887Schin { 10054887Schin if(!(mode&ARRAY_ADD)) 10064887Schin { 10074887Schin int n; 10088462SApril.Chin@Sun.COM for(n=0; n <= size; n++) 10094887Schin { 10104887Schin if(!ap->val[n].cp) 10118462SApril.Chin@Sun.COM { 10124887Schin ap->val[n].cp = Empty; 10138462SApril.Chin@Sun.COM if(!array_covered(np,ap)) 10148462SApril.Chin@Sun.COM ap->header.nelem++; 10158462SApril.Chin@Sun.COM } 10164887Schin } 10174887Schin if(n=ap->maxi-ap->maxi) 10184887Schin memset(&ap->val[size],0,n*sizeof(union Value)); 10194887Schin } 10204887Schin else if(!ap->val[size].cp) 10214887Schin { 10224887Schin if(sh.subshell) 10234887Schin np = sh_assignok(np,1); 10244887Schin ap->val[size].cp = Empty; 10258462SApril.Chin@Sun.COM if(!array_covered(np,ap)) 10268462SApril.Chin@Sun.COM ap->header.nelem++; 10274887Schin } 10284887Schin } 10294887Schin else if(!(mode&ARRAY_SCAN)) 10304887Schin { 10314887Schin ap->header.nelem &= ~ARRAY_SCAN; 10328462SApril.Chin@Sun.COM if(array_isbit(ap->bits,size,ARRAY_CHILD)) 10334887Schin nv_putsub(ap->val[size].np,NIL(char*),ARRAY_UNDEF); 10348462SApril.Chin@Sun.COM if(sp && !(mode&ARRAY_ADD) && !ap->val[size].cp) 10358462SApril.Chin@Sun.COM np = 0; 10364887Schin } 10374887Schin return((Namval_t*)np); 10384887Schin } 10394887Schin ap->header.nelem &= ~ARRAY_UNDEF; 10404887Schin if(!(mode&ARRAY_FILL)) 10414887Schin ap->header.nelem &= ~ARRAY_SCAN; 10428462SApril.Chin@Sun.COM ap->header.nelem |= (mode&(ARRAY_SCAN|ARRAY_NOCHILD|ARRAY_UNDEF|ARRAY_NOSCOPE)); 10434887Schin if(sp) 10444887Schin { 10454887Schin if(mode&ARRAY_SETSUB) 10464887Schin { 10474887Schin (*ap->header.fun)(np, sp, NV_ASETSUB); 10484887Schin return(np); 10494887Schin } 10508462SApril.Chin@Sun.COM (*ap->header.fun)(np, sp, (mode&ARRAY_ADD)?NV_AADD:0); 10518462SApril.Chin@Sun.COM if(!(mode&(ARRAY_SCAN|ARRAY_ADD)) && !(*ap->header.fun)(np,NIL(char*),NV_ACURRENT)) 10528462SApril.Chin@Sun.COM np = 0; 10534887Schin } 10544887Schin else if(mode&ARRAY_SCAN) 10554887Schin (*ap->header.fun)(np,(char*)np,0); 10564887Schin else if(mode&ARRAY_UNDEF) 10574887Schin (*ap->header.fun)(np, "",0); 10584887Schin if((mode&ARRAY_SCAN) && !nv_nextsub(np)) 10594887Schin np = 0; 10604887Schin return(np); 10614887Schin } 10624887Schin 10634887Schin /* 10644887Schin * process an array subscript for node <np> given the subscript <cp> 10654887Schin * returns pointer to character after the subscript 10664887Schin */ 10674887Schin char *nv_endsubscript(Namval_t *np, register char *cp, int mode) 10684887Schin { 10694887Schin register int count=1, quoted=0, c; 10704887Schin register char *sp = cp+1; 10714887Schin /* first find matching ']' */ 10724887Schin while(count>0 && (c= *++cp)) 10734887Schin { 10744887Schin if(c=='\\' && (!(mode&NV_SUBQUOTE) || (c=cp[1])=='[' || c==']' || c=='\\' || c=='*' || c=='@')) 10754887Schin { 10764887Schin quoted=1; 10774887Schin cp++; 10784887Schin } 10794887Schin else if(c=='[') 10804887Schin count++; 10814887Schin else if(c==']') 10824887Schin count--; 10834887Schin } 10844887Schin *cp = 0; 10854887Schin if(quoted) 10864887Schin { 10874887Schin /* strip escape characters */ 10884887Schin count = staktell(); 10894887Schin stakwrite(sp,1+cp-sp); 10904887Schin sh_trim(sp=stakptr(count)); 10914887Schin } 10924887Schin if(mode && np) 10938462SApril.Chin@Sun.COM { 109410898Sroland.mainz@nrubsig.org Namarr_t *ap = nv_arrayptr(np); 109510898Sroland.mainz@nrubsig.org int scan = 0; 109610898Sroland.mainz@nrubsig.org if(ap) 109710898Sroland.mainz@nrubsig.org scan = ap->nelem&ARRAY_SCAN; 10988462SApril.Chin@Sun.COM if((mode&NV_ASSIGN) && (cp[1]=='=' || cp[1]=='+')) 10998462SApril.Chin@Sun.COM mode |= NV_ADD; 11008462SApril.Chin@Sun.COM nv_putsub(np, sp, ((mode&NV_ADD)?ARRAY_ADD:0)|(cp[1]&&(mode&NV_ADD)?ARRAY_FILL:mode&ARRAY_FILL)); 110110898Sroland.mainz@nrubsig.org if(scan) 110210898Sroland.mainz@nrubsig.org ap->nelem |= scan; 11038462SApril.Chin@Sun.COM } 11044887Schin if(quoted) 11054887Schin stakseek(count); 11064887Schin *cp++ = c; 11074887Schin return(cp); 11084887Schin } 11094887Schin 11104887Schin 11114887Schin Namval_t *nv_opensub(Namval_t* np) 11124887Schin { 11134887Schin register struct index_array *ap = (struct index_array*)nv_arrayptr(np); 11148462SApril.Chin@Sun.COM if(ap) 11158462SApril.Chin@Sun.COM { 11168462SApril.Chin@Sun.COM if(is_associative(ap)) 11178462SApril.Chin@Sun.COM return((Namval_t*)((*ap->header.fun)(np,NIL(char*),NV_ACURRENT))); 11188462SApril.Chin@Sun.COM else if(array_isbit(ap->bits,ap->cur,ARRAY_CHILD)) 11198462SApril.Chin@Sun.COM return(ap->val[ap->cur].np); 11208462SApril.Chin@Sun.COM } 11214887Schin return(NIL(Namval_t*)); 11224887Schin } 11234887Schin 11244887Schin char *nv_getsub(Namval_t* np) 11254887Schin { 11264887Schin static char numbuff[NUMSIZE]; 11274887Schin register struct index_array *ap; 11284887Schin register unsigned dot, n; 11294887Schin register char *cp = &numbuff[NUMSIZE]; 11304887Schin if(!np || !(ap = (struct index_array*)nv_arrayptr(np))) 11314887Schin return(NIL(char*)); 11324887Schin if(is_associative(ap)) 11334887Schin return((char*)((*ap->header.fun)(np,NIL(char*),NV_ANAME))); 11348462SApril.Chin@Sun.COM if(ap->xp) 11358462SApril.Chin@Sun.COM { 11368462SApril.Chin@Sun.COM np = nv_namptr(ap->xp,0); 11378462SApril.Chin@Sun.COM np->nvalue.s = ap->cur; 11388462SApril.Chin@Sun.COM return(nv_getval(np)); 11398462SApril.Chin@Sun.COM } 11404887Schin if((dot = ap->cur)==0) 11414887Schin *--cp = '0'; 11424887Schin else while(n=dot) 11434887Schin { 11444887Schin dot /= 10; 11454887Schin *--cp = '0' + (n-10*dot); 11464887Schin } 11474887Schin return(cp); 11484887Schin } 11494887Schin 11504887Schin /* 11514887Schin * If <np> is an indexed array node, the current subscript index 11524887Schin * returned, otherwise returns -1 11534887Schin */ 11544887Schin int nv_aindex(register Namval_t* np) 11554887Schin { 11564887Schin Namarr_t *ap = nv_arrayptr(np); 11578462SApril.Chin@Sun.COM if(!ap) 11588462SApril.Chin@Sun.COM return(0); 11598462SApril.Chin@Sun.COM else if(is_associative(ap)) 11604887Schin return(-1); 11614887Schin return(((struct index_array*)(ap))->cur&ARRAY_MASK); 11624887Schin } 11634887Schin 11648462SApril.Chin@Sun.COM int nv_arraynsub(register Namarr_t* ap) 11658462SApril.Chin@Sun.COM { 11668462SApril.Chin@Sun.COM return(array_elem(ap)); 11678462SApril.Chin@Sun.COM } 11688462SApril.Chin@Sun.COM 11698462SApril.Chin@Sun.COM int nv_aimax(register Namval_t* np) 11708462SApril.Chin@Sun.COM { 11718462SApril.Chin@Sun.COM struct index_array *ap = (struct index_array*)nv_arrayptr(np); 11728462SApril.Chin@Sun.COM int sub = -1; 11738462SApril.Chin@Sun.COM if(!ap || is_associative(&ap->header)) 11748462SApril.Chin@Sun.COM return(-1); 11758462SApril.Chin@Sun.COM sub = ap->maxi; 11768462SApril.Chin@Sun.COM while(--sub>0 && ap->val[sub].cp==0); 11778462SApril.Chin@Sun.COM return(sub); 11788462SApril.Chin@Sun.COM } 11794887Schin 11804887Schin /* 11818462SApril.Chin@Sun.COM * This is the default implementation for associative arrays 11824887Schin */ 11834887Schin void *nv_associative(register Namval_t *np,const char *sp,int mode) 11844887Schin { 11854887Schin register struct assoc_array *ap = (struct assoc_array*)nv_arrayptr(np); 11864887Schin register int type; 11874887Schin switch(mode) 11884887Schin { 11894887Schin case NV_AINIT: 11904887Schin if(ap = (struct assoc_array*)calloc(1,sizeof(struct assoc_array))) 11914887Schin { 11928462SApril.Chin@Sun.COM ap->header.table = dtopen(&_Nvdisc,Dtoset); 11934887Schin ap->cur = 0; 11944887Schin ap->pos = 0; 11954887Schin ap->header.hdr.disc = &array_disc; 11968462SApril.Chin@Sun.COM nv_disc(np,(Namfun_t*)ap, NV_FIRST); 11978462SApril.Chin@Sun.COM ap->header.hdr.dsize = sizeof(struct assoc_array); 11988462SApril.Chin@Sun.COM ap->header.hdr.nofree &= ~1; 11994887Schin } 12004887Schin return((void*)ap); 12014887Schin case NV_ADELETE: 12024887Schin if(ap->cur) 12034887Schin { 12048462SApril.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)) 12058462SApril.Chin@Sun.COM ap->header.nelem--; 12068462SApril.Chin@Sun.COM _nv_unset(ap->cur,NV_RDONLY); 12078462SApril.Chin@Sun.COM nv_delete(ap->cur,ap->header.table,0); 12088462SApril.Chin@Sun.COM ap->cur = 0; 12094887Schin } 12104887Schin return((void*)ap); 12114887Schin case NV_AFREE: 12124887Schin ap->pos = 0; 12138462SApril.Chin@Sun.COM if(ap->header.scope) 12148462SApril.Chin@Sun.COM { 12158462SApril.Chin@Sun.COM ap->header.table = dtview(ap->header.table,(Dt_t*)0); 12168462SApril.Chin@Sun.COM dtclose(ap->header.scope); 12178462SApril.Chin@Sun.COM ap->header.scope = 0; 12188462SApril.Chin@Sun.COM } 12198462SApril.Chin@Sun.COM else 12208462SApril.Chin@Sun.COM dtclose(ap->header.table); 12214887Schin return((void*)ap); 12224887Schin case NV_ANEXT: 12234887Schin if(!ap->pos) 12244887Schin { 12258462SApril.Chin@Sun.COM if((ap->header.nelem&ARRAY_NOSCOPE) && ap->header.scope && dtvnext(ap->header.table)) 12268462SApril.Chin@Sun.COM { 12278462SApril.Chin@Sun.COM ap->header.scope = dtvnext(ap->header.table); 12288462SApril.Chin@Sun.COM ap->header.table->view = 0; 12298462SApril.Chin@Sun.COM } 12304887Schin if(!(ap->pos=ap->cur)) 12318462SApril.Chin@Sun.COM ap->pos = (Namval_t*)dtfirst(ap->header.table); 12324887Schin } 12334887Schin else 12344887Schin ap->pos = ap->nextpos; 12354887Schin for(;ap->cur=ap->pos; ap->pos=ap->nextpos) 12364887Schin { 12378462SApril.Chin@Sun.COM ap->nextpos = (Namval_t*)dtnext(ap->header.table,ap->pos); 12384887Schin if(ap->cur->nvalue.cp) 12394887Schin { 12404887Schin if((ap->header.nelem&ARRAY_NOCHILD) && nv_isattr(ap->cur,NV_CHILD)) 12414887Schin continue; 12424887Schin return((void*)ap); 12434887Schin } 12444887Schin } 12458462SApril.Chin@Sun.COM if((ap->header.nelem&ARRAY_NOSCOPE) && ap->header.scope && !dtvnext(ap->header.table)) 12468462SApril.Chin@Sun.COM { 12478462SApril.Chin@Sun.COM ap->header.table->view = (Dt_t*)ap->header.scope; 12488462SApril.Chin@Sun.COM ap->header.scope = ap->header.table; 12498462SApril.Chin@Sun.COM } 12504887Schin return(NIL(void*)); 12514887Schin case NV_ASETSUB: 12524887Schin ap->cur = (Namval_t*)sp; 12538462SApril.Chin@Sun.COM return((void*)ap->cur); 12544887Schin case NV_ACURRENT: 12558462SApril.Chin@Sun.COM if(ap->cur) 12568462SApril.Chin@Sun.COM ap->cur->nvenv = (char*)np; 12574887Schin return((void*)ap->cur); 12584887Schin case NV_ANAME: 12594887Schin if(ap->cur) 1260*12068SRoger.Faulkner@Oracle.COM { 1261*12068SRoger.Faulkner@Oracle.COM Shell_t *shp = sh_getinterp(); 1262*12068SRoger.Faulkner@Oracle.COM if(!shp->instance && nv_isnull(ap->cur)) 1263*12068SRoger.Faulkner@Oracle.COM return(NIL(void*)); 12648462SApril.Chin@Sun.COM return((void*)ap->cur->nvname); 1265*12068SRoger.Faulkner@Oracle.COM } 12664887Schin return(NIL(void*)); 12674887Schin default: 12684887Schin if(sp) 12694887Schin { 12708462SApril.Chin@Sun.COM Namval_t *mp=0; 12718462SApril.Chin@Sun.COM ap->cur = 0; 12724887Schin if(sp==(char*)np) 12738462SApril.Chin@Sun.COM return(0); 12748462SApril.Chin@Sun.COM type = nv_isattr(np,NV_PUBLIC&~(NV_ARRAY|NV_CHILD|NV_MINIMAL)); 12758462SApril.Chin@Sun.COM if(mode) 12768462SApril.Chin@Sun.COM mode = NV_ADD|HASH_NOSCOPE; 12778462SApril.Chin@Sun.COM else if(ap->header.nelem&ARRAY_NOSCOPE) 12788462SApril.Chin@Sun.COM mode = HASH_NOSCOPE; 1279*12068SRoger.Faulkner@Oracle.COM if(*sp==0 && sh_isoption(SH_XTRACE) && (mode&NV_ADD)) 128010898Sroland.mainz@nrubsig.org errormsg(SH_DICT,ERROR_warn(0),"adding empty subscript"); 12818462SApril.Chin@Sun.COM if(sh.subshell && (mp=nv_search(sp,ap->header.table,0)) && nv_isnull(mp)) 12828462SApril.Chin@Sun.COM ap->cur = mp; 12838462SApril.Chin@Sun.COM if((mp || (mp=nv_search(sp,ap->header.table,mode))) && nv_isnull(mp) && (mode&NV_ADD)) 12844887Schin { 12858462SApril.Chin@Sun.COM nv_onattr(mp,type); 12868462SApril.Chin@Sun.COM mp->nvenv = (char*)np; 12878462SApril.Chin@Sun.COM if((mode&NV_ADD) && nv_type(np)) 12888462SApril.Chin@Sun.COM nv_arraychild(np,mp,0); 12898462SApril.Chin@Sun.COM if(sh.subshell) 12908462SApril.Chin@Sun.COM np = sh_assignok(np,1); 12918462SApril.Chin@Sun.COM if(!ap->header.scope || !nv_search(sp,dtvnext(ap->header.table),0)) 12928462SApril.Chin@Sun.COM ap->header.nelem++; 12938462SApril.Chin@Sun.COM if(nv_isnull(mp)) 12948462SApril.Chin@Sun.COM { 12958462SApril.Chin@Sun.COM if(ap->header.nelem&ARRAY_TREE) 12968462SApril.Chin@Sun.COM nv_setvtree(mp); 12978462SApril.Chin@Sun.COM mp->nvalue.cp = Empty; 12988462SApril.Chin@Sun.COM } 12994887Schin } 13008462SApril.Chin@Sun.COM else if(ap->header.nelem&ARRAY_SCAN) 13018462SApril.Chin@Sun.COM { 13028462SApril.Chin@Sun.COM Namval_t fake; 13038462SApril.Chin@Sun.COM fake.nvname = (char*)sp; 13048462SApril.Chin@Sun.COM ap->pos = mp = (Namval_t*)dtprev(ap->header.table,&fake); 13058462SApril.Chin@Sun.COM ap->nextpos = (Namval_t*)dtnext(ap->header.table,mp); 13068462SApril.Chin@Sun.COM } 1307*12068SRoger.Faulkner@Oracle.COM else if(!mp && *sp && mode==0) 1308*12068SRoger.Faulkner@Oracle.COM mp = nv_search(sp,ap->header.table,NV_ADD); 13098462SApril.Chin@Sun.COM np = mp; 131010898Sroland.mainz@nrubsig.org if(ap->pos && ap->pos==np) 131110898Sroland.mainz@nrubsig.org ap->header.nelem |= ARRAY_SCAN; 131210898Sroland.mainz@nrubsig.org else if(!(ap->header.nelem&ARRAY_SCAN)) 13134887Schin ap->pos = 0; 13144887Schin ap->cur = np; 13154887Schin } 13164887Schin if(ap->cur) 13174887Schin return((void*)(&ap->cur->nvalue)); 13184887Schin else 13194887Schin return((void*)(&ap->cur)); 13204887Schin } 13214887Schin } 13224887Schin 13234887Schin /* 13244887Schin * Assign values to an array 13254887Schin */ 13264887Schin void nv_setvec(register Namval_t *np,int append,register int argc,register char *argv[]) 13274887Schin { 13284887Schin int arg0=0; 13298462SApril.Chin@Sun.COM struct index_array *ap=0,*aq; 13304887Schin if(nv_isarray(np)) 13314887Schin { 13324887Schin ap = (struct index_array*)nv_arrayptr(np); 13334887Schin if(ap && is_associative(ap)) 13348462SApril.Chin@Sun.COM errormsg(SH_DICT,ERROR_exit(1),"cannot append index array to associative array %s",nv_name(np)); 13354887Schin } 13364887Schin if(append) 13374887Schin { 13384887Schin if(ap) 13394887Schin { 13408462SApril.Chin@Sun.COM if(!(aq = (struct index_array*)ap->header.scope)) 13418462SApril.Chin@Sun.COM aq = ap; 13424887Schin arg0 = ap->maxi; 13438462SApril.Chin@Sun.COM while(--arg0>0 && ap->val[arg0].cp==0 && aq->val[arg0].cp==0); 13444887Schin arg0++; 13454887Schin } 13464887Schin else if(!nv_isnull(np)) 13474887Schin arg0=1; 13484887Schin } 13494887Schin while(--argc >= 0) 13504887Schin { 13518462SApril.Chin@Sun.COM nv_putsub(np,NIL(char*),(long)argc+arg0|ARRAY_FILL|ARRAY_ADD); 13524887Schin nv_putval(np,argv[argc],0); 13534887Schin } 13544887Schin } 13554887Schin 1356