diff options
author | Andy Fiddaman <omnios@citrus-it.co.uk> | 2020-12-27 17:47:37 +0000 |
---|---|---|
committer | Andy Fiddaman <omnios@citrus-it.co.uk> | 2021-01-30 17:13:33 +0000 |
commit | b30d193948be5a7794d7ae3ba0ed9c2f72c88e0f (patch) | |
tree | 6a37e590faffb9bb9af66887de645c546445036c /usr/src/lib/libshell/common/sh/array.c | |
parent | df36e06d12cbf655ddf22339ef8c39fa2b83ebf8 (diff) | |
download | illumos-joyent-b30d193948be5a7794d7ae3ba0ed9c2f72c88e0f.tar.gz |
13405 ksh93 update to 2012-08-01
13434 sh: mishandles backslash as last character of a block of input
11750 ksh mkdir builtin doesn't honor special file permissions
9199 ksh93 builtin *grep -v mishandles blank lines, blows up libgcrypt-config
6756 sh (and ksh) have issues with ${1+"$@"}
6520 ksh: sleep could wait forever
4860 ksh93: core in printf
3791 /bin/sh's builtin 'rm' busted: 'rm -f' without arguments returns error
1047 ksh overwrites child core files
880 ksh93 coredumps on 'unset'
499 "interrupted system call" when using "tee" builtin in ksh
Reviewed by: Robert Mustacchi <rm@fingolfin.org>
Reviewed by: Hans Rosenfeld <rosenfeld@grumpf.hope-2000.org>
Reviewed by: Dominik Hassler <hadfl@omnios.org>
Approved by: Rich Lowe <richlowe@richlowe.net>
Diffstat (limited to 'usr/src/lib/libshell/common/sh/array.c')
-rw-r--r-- | usr/src/lib/libshell/common/sh/array.c | 1355 |
1 files changed, 0 insertions, 1355 deletions
diff --git a/usr/src/lib/libshell/common/sh/array.c b/usr/src/lib/libshell/common/sh/array.c deleted file mode 100644 index 795d434eda..0000000000 --- a/usr/src/lib/libshell/common/sh/array.c +++ /dev/null @@ -1,1355 +0,0 @@ -/*********************************************************************** -* * -* This software is part of the ast package * -* Copyright (c) 1982-2010 AT&T Intellectual Property * -* and is licensed under the * -* Common Public License, Version 1.0 * -* by AT&T Intellectual Property * -* * -* A copy of the License is available at * -* http://www.opensource.org/licenses/cpl1.0.txt * -* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * -* * -* Information and Software Systems Research * -* AT&T Research * -* Florham Park NJ * -* * -* David Korn <dgk@research.att.com> * -* * -***********************************************************************/ -#pragma prototyped -/* - * Array processing routines - * - * David Korn - * AT&T Labs - * dgk@research.att.com - * - */ - -#include "defs.h" -#include <stak.h> -#include "name.h" - -#define NUMSIZE (4+(ARRAY_MAX>999)+(ARRAY_MAX>9999)+(ARRAY_MAX>99999)) -#define is_associative(ap) array_assoc((Namarr_t*)(ap)) -#define array_setbit(cp, n, b) (cp[n] |= (b)) -#define array_clrbit(cp, n, b) (cp[n] &= ~(b)) -#define array_isbit(cp, n, b) (cp[n] & (b)) -#define NV_CHILD NV_EXPORT -#define ARRAY_CHILD 1 -#define ARRAY_NOFREE 2 - -struct index_array -{ - Namarr_t header; - void *xp; /* if set, subscripts will be converted */ - int cur; /* index of current element */ - int maxi; /* maximum index for array */ - unsigned char *bits; /* bit array for child subscripts */ - union Value val[1]; /* array of value holders */ -}; - -struct assoc_array -{ - Namarr_t header; - Namval_t *pos; - Namval_t *nextpos; - Namval_t *cur; -}; - -static Namarr_t *array_scope(Namval_t *np, Namarr_t *ap, int flags) -{ - Namarr_t *aq; - struct index_array *ar; - size_t size = ap->hdr.dsize; - if(size==0) - size = ap->hdr.disc->dsize; - if(!(aq=newof(NIL(Namarr_t*),Namarr_t,1,size-sizeof(Namarr_t)))) - return(0); - memcpy(aq,ap,size); - aq->hdr.nofree &= ~1; - aq->hdr.nofree |= (flags&NV_RDONLY)?1:0; - if(is_associative(aq)) - { - aq->scope = (void*)dtopen(&_Nvdisc,Dtoset); - dtview((Dt_t*)aq->scope,aq->table); - aq->table = (Dt_t*)aq->scope; - return(aq); - } - aq->scope = (void*)ap; - ar = (struct index_array*)aq; - memset(ar->val, 0, ar->maxi*sizeof(char*)); - return(aq); -} - -static int array_unscope(Namval_t *np,Namarr_t *ap) -{ - Namfun_t *fp; - if(!ap->scope) - return(0); - if(is_associative(ap)) - (*ap->fun)(np, NIL(char*), NV_AFREE); - if((fp = nv_disc(np,(Namfun_t*)ap,NV_POP)) && !(fp->nofree&1)) - free((void*)fp); - nv_delete(np,(Dt_t*)0,0); - return(1); -} - -static void array_syncsub(Namarr_t *ap, Namarr_t *aq) -{ - ((struct index_array*)ap)->cur = ((struct index_array*)aq)->cur; -} - -static int array_covered(Namval_t *np, struct index_array *ap) -{ - struct index_array *aq = (struct index_array*)ap->header.scope; - if(!ap->header.fun && aq) - return ((ap->cur<aq->maxi) && aq->val[ap->cur].cp); - return(0); -} - -/* - * replace discipline with new one - */ -static void array_setptr(register Namval_t *np, struct index_array *old, struct index_array *new) -{ - register Namfun_t **fp = &np->nvfun; - while(*fp && *fp!= &old->header.hdr) - fp = &((*fp)->next); - if(*fp) - { - new->header.hdr.next = (*fp)->next; - *fp = &new->header.hdr; - } - else sfprintf(sfstderr,"discipline not replaced\n"); -} - -/* - * Calculate the amount of space to be allocated to hold an - * indexed array into which <maxi> is a legal index. The number of - * elements that will actually fit into the array (> <maxi> - * but <= ARRAY_MAX) is returned. - * - */ -static int arsize(struct index_array *ap, register int maxi) -{ - if(ap && maxi < 2*ap->maxi) - maxi = 2*ap->maxi; - maxi = roundof(maxi,ARRAY_INCR); - return (maxi>ARRAY_MAX?ARRAY_MAX:maxi); -} - -static struct index_array *array_grow(Namval_t*, struct index_array*,int); - -/* return index of highest element of an array */ -int array_maxindex(Namval_t *np) -{ - register struct index_array *ap = (struct index_array*)nv_arrayptr(np); - register int i = ap->maxi; - if(is_associative(ap)) - return(-1); - while(i>0 && ap->val[--i].cp==0); - return(i+1); -} - -static union Value *array_getup(Namval_t *np, Namarr_t *arp, int update) -{ - register struct index_array *ap = (struct index_array*)arp; - register union Value *up; - int nofree; - if(!arp) - return(&np->nvalue); - if(is_associative(ap)) - { - Namval_t *mp; - mp = (Namval_t*)((*arp->fun)(np,NIL(char*),NV_ACURRENT)); - if(mp) - { - nofree = nv_isattr(mp,NV_NOFREE); - up = &mp->nvalue; - } - else - return((union Value*)((*arp->fun)(np,NIL(char*),0))); - } - else - { - if(ap->cur >= ap->maxi) - errormsg(SH_DICT,ERROR_exit(1),e_subscript,nv_name(np)); - up = &(ap->val[ap->cur]); - nofree = array_isbit(ap->bits,ap->cur,ARRAY_NOFREE); - } - if(update) - { - if(nofree) - nv_onattr(np,NV_NOFREE); - else - nv_offattr(np,NV_NOFREE); - } - return(up); -} - -int nv_arrayisset(Namval_t *np, Namarr_t *arp) -{ - register struct index_array *ap = (struct index_array*)arp; - union Value *up; - if(is_associative(ap)) - return((np = nv_opensub(np)) && !nv_isnull(np)); - if(ap->cur >= ap->maxi) - return(0); - up = &(ap->val[ap->cur]); - return(up->cp && up->cp!=Empty); -} - -/* - * Get the Value pointer for an array. - * Delete space as necessary if flag is ARRAY_DELETE - * After the lookup is done the last @ or * subscript is incremented - */ -static Namval_t *array_find(Namval_t *np,Namarr_t *arp, int flag) -{ - register struct index_array *ap = (struct index_array*)arp; - register union Value *up; - Namval_t *mp; - int wasundef; - if(flag&ARRAY_LOOKUP) - ap->header.nelem &= ~ARRAY_NOSCOPE; - else - ap->header.nelem |= ARRAY_NOSCOPE; - if(wasundef = ap->header.nelem&ARRAY_UNDEF) - { - ap->header.nelem &= ~ARRAY_UNDEF; - /* delete array is the same as delete array[@] */ - if(flag&ARRAY_DELETE) - { - nv_putsub(np, NIL(char*), ARRAY_SCAN|ARRAY_NOSCOPE); - ap->header.nelem |= ARRAY_SCAN; - } - else /* same as array[0] */ - { - if(is_associative(ap)) - (*ap->header.fun)(np,"0",flag==ARRAY_ASSIGN?NV_AADD:0); - else - ap->cur = 0; - } - } - if(is_associative(ap)) - { - mp = (Namval_t*)((*arp->fun)(np,NIL(char*),NV_ACURRENT)); - if(!mp) - up = (union Value*)∓ - else if(nv_isarray(mp)) - { - if(wasundef) - nv_putsub(mp,NIL(char*),ARRAY_UNDEF); - return(mp); - } - else - { - up = &mp->nvalue; - if(nv_isvtree(mp)) - { - if(!up->cp && flag==ARRAY_ASSIGN) - { - nv_arraychild(np,mp,0); - ap->header.nelem++; - } - return(mp); - } - } - } - else - { - if(!(ap->header.nelem&ARRAY_SCAN) && ap->cur >= ap->maxi) - ap = array_grow(np, ap, (int)ap->cur); - if(ap->cur>=ap->maxi) - errormsg(SH_DICT,ERROR_exit(1),e_subscript,nv_name(np)); - up = &(ap->val[ap->cur]); - if((!up->cp||up->cp==Empty) && nv_type(np) && nv_isvtree(np)) - { - char *cp; - if(!ap->header.table) - ap->header.table = dtopen(&_Nvdisc,Dtoset); - sfprintf(sh.strbuf,"%d",ap->cur); - cp = sfstruse(sh.strbuf); - mp = nv_search(cp, ap->header.table, NV_ADD); - mp->nvenv = (char*)np; - nv_arraychild(np,mp,0); - } - if(up->np && array_isbit(ap->bits,ap->cur,ARRAY_CHILD)) - { - if(wasundef && nv_isarray(up->np)) - nv_putsub(up->np,NIL(char*),ARRAY_UNDEF); - return(up->np); - } - } - np->nvalue.cp = up->cp; - if(!up->cp) - { - char *xp = nv_setdisc(np,"get",np,(Namfun_t*)np); - if(flag!=ARRAY_ASSIGN) - return(xp && xp!=(char*)np?np:0); - if(!array_covered(np,ap)) - ap->header.nelem++; - } - return(np); -} - -#if SHOPT_TYPEDEF -int nv_arraysettype(Namval_t *np, Namval_t *tp, const char *sub, int flags) -{ - Namval_t *nq; - char *av[2]; - int rdonly = nv_isattr(np,NV_RDONLY); - int xtrace = sh_isoption(SH_XTRACE); - Namarr_t *ap = nv_arrayptr(np); - av[1] = 0; - sh.last_table = 0; - if(!ap->table) - ap->table = dtopen(&_Nvdisc,Dtoset); - if(nq = nv_search(sub, ap->table, NV_ADD)) - { - if(!nq->nvfun && nq->nvalue.cp && *nq->nvalue.cp==0) - _nv_unset(nq,NV_RDONLY); - nv_arraychild(np,nq,0); - if(!nv_isattr(tp,NV_BINARY)) - { - sfprintf(sh.strbuf,"%s=%s",nv_name(nq),nv_getval(np)); - av[0] = strdup(sfstruse(sh.strbuf)); - } - if(!nv_clone(tp,nq,flags|NV_NOFREE)) - return(0); - ap->nelem |= ARRAY_SCAN; - if(!rdonly) - nv_offattr(nq,NV_RDONLY); - if(!nv_isattr(tp,NV_BINARY)) - { - if(xtrace) - sh_offoption(SH_XTRACE); - ap->nelem &= ~ARRAY_SCAN; - sh_eval(sh_sfeval(av),0); - ap->nelem |= ARRAY_SCAN; - free((void*)av[0]); - if(xtrace) - sh_onoption(SH_XTRACE); - } - return(1); - } - return(0); -} -#endif /* SHOPT_TYPEDEF */ - - -static Namfun_t *array_clone(Namval_t *np, Namval_t *mp, int flags, Namfun_t *fp) -{ - Namarr_t *ap = (Namarr_t*)fp; - Namval_t *nq, *mq; - char *name, *sub=0; - int nelem, skipped=0; - Dt_t *otable=ap->table; - struct index_array *aq = (struct index_array*)ap, *ar; - Shell_t *shp = sh_getinterp(); - if(flags&NV_MOVE) - { - if((flags&NV_COMVAR) && nv_putsub(np,NIL(char*),ARRAY_SCAN)) - { - do - { - if(nq=nv_opensub(np)) - nq->nvenv = (void*)mp; - } - while(nv_nextsub(np)); - } - return(fp); - } - nelem = ap->nelem; - if(nelem&ARRAY_NOCLONE) - return(0); - if((flags&NV_TYPE) && !ap->scope) - { - ap = array_scope(np,ap,flags); - return(&ap->hdr); - } - ap = (Namarr_t*)nv_clone_disc(fp,0); - if(flags&NV_COMVAR) - { - ap->scope = 0; - ap->nelem = 0; - sh.prev_table = sh.last_table; - sh.prev_root = sh.last_root; - } - if(ap->table) - { - ap->table = dtopen(&_Nvdisc,Dtoset); - if(ap->scope && !(flags&NV_COMVAR)) - { - ap->scope = ap->table; - dtview(ap->table, otable->view); - } - } - mp->nvfun = (Namfun_t*)ap; - mp->nvflag &= NV_MINIMAL; - mp->nvflag |= (np->nvflag&~(NV_MINIMAL|NV_NOFREE)); - if(!(nelem&(ARRAY_SCAN|ARRAY_UNDEF)) && (sub=nv_getsub(np))) - sub = strdup(sub); - ar = (struct index_array*)ap; - if(!is_associative(ap)) - ar->bits = (unsigned char*)&ar->val[ar->maxi]; - if(!nv_putsub(np,NIL(char*),ARRAY_SCAN|((flags&NV_COMVAR)?0:ARRAY_NOSCOPE))) - { - if(ap->fun) - (*ap->fun)(np,(char*)np,0); - skipped=1; - goto skip; - } - do - { - name = nv_getsub(np); - nv_putsub(mp,name,ARRAY_ADD|ARRAY_NOSCOPE); - mq = 0; - if(nq=nv_opensub(np)) - mq = nv_search(name,ap->table,NV_ADD); - if(nq && (flags&NV_COMVAR) && nv_isvtree(nq)) - { - mq->nvalue.cp = 0; - if(!is_associative(ap)) - ar->val[ar->cur].np = mq; - nv_clone(nq,mq,flags); - } - else if(flags&NV_ARRAY) - { - if((flags&NV_NOFREE) && !is_associative(ap)) - array_setbit(aq->bits,aq->cur,ARRAY_NOFREE); - else if(nq && (flags&NV_NOFREE)) - { - mq->nvalue = nq->nvalue; - nv_onattr(nq,NV_NOFREE); - } - } - else if(nv_isattr(np,NV_INTEGER)) - { - Sfdouble_t d= nv_getnum(np); - if(!is_associative(ap)) - ar->val[ar->cur].cp = 0; - nv_putval(mp,(char*)&d,NV_LDOUBLE); - } - else - { - if(!is_associative(ap)) - ar->val[ar->cur].cp = 0; - nv_putval(mp,nv_getval(np),NV_RDONLY); - } - aq->header.nelem |= ARRAY_NOSCOPE; - } - while(nv_nextsub(np)); -skip: - if(sub) - { - if(!skipped) - nv_putsub(np,sub,0L); - free((void*)sub); - } - aq->header.nelem = ap->nelem = nelem; - return(&ap->hdr); -} - -static char *array_getval(Namval_t *np, Namfun_t *disc) -{ - register Namarr_t *aq,*ap = (Namarr_t*)disc; - register Namval_t *mp; - if((mp=array_find(np,ap,ARRAY_LOOKUP))!=np) - { - if(!mp && !is_associative(ap) && (aq=(Namarr_t*)ap->scope)) - { - array_syncsub(aq,ap); - if((mp=array_find(np,aq,ARRAY_LOOKUP))==np) - return(nv_getv(np,&aq->hdr)); - } - return(mp?nv_getval(mp):0); - } - return(nv_getv(np,&ap->hdr)); -} - -static Sfdouble_t array_getnum(Namval_t *np, Namfun_t *disc) -{ - register Namarr_t *aq,*ap = (Namarr_t*)disc; - register Namval_t *mp; - if((mp=array_find(np,ap,ARRAY_LOOKUP))!=np) - { - if(!mp && !is_associative(ap) && (aq=(Namarr_t*)ap->scope)) - { - array_syncsub(aq,ap); - if((mp=array_find(np,aq,ARRAY_LOOKUP))==np) - return(nv_getn(np,&aq->hdr)); - } - return(mp?nv_getnum(mp):0); - } - return(nv_getn(np,&ap->hdr)); -} - -static void array_putval(Namval_t *np, const char *string, int flags, Namfun_t *dp) -{ - register Namarr_t *ap = (Namarr_t*)dp; - register union Value *up; - register Namval_t *mp; - register struct index_array *aq = (struct index_array*)ap; - int scan,nofree = nv_isattr(np,NV_NOFREE); - do - { - mp = array_find(np,ap,string?ARRAY_ASSIGN:ARRAY_DELETE); - scan = ap->nelem&ARRAY_SCAN; - if(mp && mp!=np) - { - if(!is_associative(ap) && string && !(flags&NV_APPEND) && !nv_type(np) && nv_isvtree(mp)) - { - if(!nv_isattr(np,NV_NOFREE)) - _nv_unset(mp,flags&NV_RDONLY); - array_clrbit(aq->bits,aq->cur,ARRAY_CHILD); - aq->val[aq->cur].cp = 0; - if(!nv_isattr(mp,NV_NOFREE)) - nv_delete(mp,ap->table,0); - goto skip; - } - nv_putval(mp, string, flags); - if(string) - { -#if SHOPT_TYPEDEF - if(ap->hdr.type && ap->hdr.type!=nv_type(mp)) - nv_arraysettype(np,ap->hdr.type,nv_getsub(np),0); -#endif /* SHOPT_TYPEDEF */ - continue; - } - ap->nelem |= scan; - } - if(!string) - { - if(mp) - { - if(is_associative(ap)) - { - (*ap->fun)(np,NIL(char*),NV_ADELETE); - np->nvalue.cp = 0; - } - else - { - if(mp!=np) - { - array_clrbit(aq->bits,aq->cur,ARRAY_CHILD); - aq->val[aq->cur].cp = 0; - nv_delete(mp,ap->table,0); - } - if(!array_covered(np,(struct index_array*)ap)) - ap->nelem--; - } - } - if(array_elem(ap)==0 && (ap->nelem&ARRAY_SCAN)) - { - if(is_associative(ap)) - (*ap->fun)(np, NIL(char*), NV_AFREE); - else if(ap->table) - dtclose(ap->table); - nv_offattr(np,NV_ARRAY); - } - if(!mp || mp!=np || is_associative(ap)) - continue; - } - skip: - /* prevent empty string from being deleted */ - up = array_getup(np,ap,!nofree); - if(up->cp == Empty) - up->cp = 0; - if(nv_isarray(np)) - np->nvalue.up = up; - nv_putv(np,string,flags,&ap->hdr); - if(!is_associative(ap)) - { - if(string) - array_clrbit(aq->bits,aq->cur,ARRAY_NOFREE); - else if(mp==np) - aq->val[aq->cur].cp = 0; - } -#if SHOPT_TYPEDEF - if(string && ap->hdr.type && nv_isvtree(np)) - nv_arraysettype(np,ap->hdr.type,nv_getsub(np),0); -#endif /* SHOPT_TYPEDEF */ - } - while(!string && nv_nextsub(np)); - if(ap) - ap->nelem &= ~ARRAY_NOSCOPE; - if(nofree) - nv_onattr(np,NV_NOFREE); - else - nv_offattr(np,NV_NOFREE); - if(!string && !nv_isattr(np,NV_ARRAY)) - { - Namfun_t *nfp; - if(!is_associative(ap) && aq->xp) - { - _nv_unset(nv_namptr(aq->xp,0),NV_RDONLY); - free((void*)aq->xp); - } - if((nfp = nv_disc(np,(Namfun_t*)ap,NV_POP)) && !(nfp->nofree&1)) - free((void*)nfp); - if(!nv_isnull(np)) - { - nv_onattr(np,NV_NOFREE); - _nv_unset(np,flags); - } - if(np->nvalue.cp==Empty) - np->nvalue.cp = 0; - } - if(!string && (flags&NV_TYPE)) - array_unscope(np,ap); -} - -static const Namdisc_t array_disc = -{ - sizeof(Namarr_t), - array_putval, - array_getval, - array_getnum, - 0, - 0, - array_clone -}; - -static void array_copytree(Namval_t *np, Namval_t *mp) -{ - Namfun_t *fp = nv_disc(np,NULL,NV_POP); - nv_offattr(np,NV_ARRAY); - nv_clone(np,mp,0); - if(np->nvalue.cp && !nv_isattr(np,NV_NOFREE)) - free((void*)np->nvalue.cp); - np->nvalue.cp = 0; - np->nvalue.up = &mp->nvalue; - fp->nofree &= ~1; - nv_disc(np,(Namfun_t*)fp, NV_FIRST); - fp->nofree |= 1; - nv_onattr(np,NV_ARRAY); - mp->nvenv = (char*)np; -} - -/* - * Increase the size of the indexed array of elements in <arp> - * so that <maxi> is a legal index. If <arp> is 0, an array - * of the required size is allocated. A pointer to the - * allocated Namarr_t structure is returned. - * <maxi> becomes the current index of the array. - */ -static struct index_array *array_grow(Namval_t *np, register struct index_array *arp,int maxi) -{ - register struct index_array *ap; - register int i; - register int newsize = arsize(arp,maxi+1); - if (maxi >= ARRAY_MAX) - errormsg(SH_DICT,ERROR_exit(1),e_subscript, fmtbase((long)maxi,10,0)); - i = (newsize-1)*sizeof(union Value*)+newsize; - ap = new_of(struct index_array,i); - memset((void*)ap,0,sizeof(*ap)+i); - ap->maxi = newsize; - ap->cur = maxi; - ap->bits = (unsigned char*)&ap->val[newsize]; - memset(ap->bits, 0, newsize); - if(arp) - { - ap->header = arp->header; - ap->header.hdr.dsize = sizeof(*ap) + i; - for(i=0;i < arp->maxi;i++) - ap->val[i].cp = arp->val[i].cp; - memcpy(ap->bits, arp->bits, arp->maxi); - array_setptr(np,arp,ap); - free((void*)arp); - } - else - { - Namval_t *mp=0; - ap->header.hdr.dsize = sizeof(*ap) + i; - i = 0; - ap->header.fun = 0; - if(nv_isnull(np) && nv_isattr(np,NV_NOFREE)) - { - i = ARRAY_TREE; - nv_offattr(np,NV_NOFREE); - } - if(np->nvalue.cp==Empty) - np->nvalue.cp=0; - if(nv_hasdisc(np,&array_disc) || nv_isvtree(np)) - { - ap->header.table = dtopen(&_Nvdisc,Dtoset); - mp = nv_search("0", ap->header.table,NV_ADD); - if(mp && nv_isnull(mp)) - { - Namfun_t *fp; - ap->val[0].np = mp; - array_setbit(ap->bits,0,ARRAY_CHILD); - for(fp=np->nvfun; fp && !fp->disc->readf; fp=fp->next); - if(fp && fp->disc && fp->disc->readf) - (*fp->disc->readf)(mp,(Sfio_t*)0,0,fp); - i++; - } - } - else if((ap->val[0].cp=np->nvalue.cp)) - i++; - else if(nv_isattr(np,NV_INTEGER) && !nv_isnull(np)) - { - Sfdouble_t d= nv_getnum(np); - i++; - } - ap->header.nelem = i; - ap->header.hdr.disc = &array_disc; - nv_disc(np,(Namfun_t*)ap, NV_FIRST); - nv_onattr(np,NV_ARRAY); - if(mp) - { - array_copytree(np,mp); - ap->header.hdr.nofree &= ~1; - } - } - for(;i < newsize;i++) - ap->val[i].cp = 0; - return(ap); -} - -int nv_atypeindex(Namval_t *np, const char *tname) -{ - Namval_t *tp; - int offset = staktell(); - int n = strlen(tname)-1; - sfprintf(stkstd,"%s.%.*s%c",NV_CLASS,n,tname,0); - tp = nv_open(stakptr(offset), sh.var_tree, NV_NOADD|NV_VARNAME); - stakseek(offset); - if(tp) - { - struct index_array *ap = (struct index_array*)nv_arrayptr(np); - if(!nv_hasdisc(tp,&ENUM_disc)) - errormsg(SH_DICT,ERROR_exit(1),e_notenum,tp->nvname); - if(!ap) - ap = array_grow(np,ap,1); - ap->xp = calloc(NV_MINSZ,1); - np = nv_namptr(ap->xp,0); - np->nvname = tp->nvname; - nv_onattr(np,NV_MINIMAL); - nv_clone(tp,np,NV_NOFREE); - nv_offattr(np,NV_RDONLY); - return(1); - } - errormsg(SH_DICT,ERROR_exit(1),e_unknowntype, n,tname); - return(0); -} - -Namarr_t *nv_arrayptr(register Namval_t *np) -{ - if(nv_isattr(np,NV_ARRAY)) - return((Namarr_t*)nv_hasdisc(np, &array_disc)); - return(0); -} - -/* - * Verify that argument is an indexed array and convert to associative, - * freeing relevant storage - */ -static Namarr_t *nv_changearray(Namval_t *np, void *(*fun)(Namval_t*,const char*,int)) -{ - register Namarr_t *ap; - char numbuff[NUMSIZE+1]; - unsigned dot, digit, n; - union Value *up; - struct index_array *save_ap; - register char *string_index=&numbuff[NUMSIZE]; - numbuff[NUMSIZE]='\0'; - - if(!fun || !(ap = nv_arrayptr(np)) || is_associative(ap)) - return(NIL(Namarr_t*)); - - nv_stack(np,&ap->hdr); - save_ap = (struct index_array*)nv_stack(np,0); - ap = (Namarr_t*)((*fun)(np, NIL(char*), NV_AINIT)); - ap->nelem = 0; - ap->fun = fun; - nv_onattr(np,NV_ARRAY); - - for(dot = 0; dot < (unsigned)save_ap->maxi; dot++) - { - if(save_ap->val[dot].cp) - { - if ((digit = dot)== 0) - *--string_index = '0'; - else while( n = digit ) - { - digit /= 10; - *--string_index = '0' + (n-10*digit); - } - nv_putsub(np, string_index, ARRAY_ADD); - up = (union Value*)((*ap->fun)(np,NIL(char*),0)); - up->cp = save_ap->val[dot].cp; - save_ap->val[dot].cp = 0; - } - string_index = &numbuff[NUMSIZE]; - } - free((void*)save_ap); - return(ap); -} - -/* - * set the associative array processing method for node <np> to <fun> - * The array pointer is returned if sucessful. - */ -Namarr_t *nv_setarray(Namval_t *np, void *(*fun)(Namval_t*,const char*,int)) -{ - register Namarr_t *ap; - char *value=0; - Namfun_t *fp; - int nelem = 0; - if(fun && (ap = nv_arrayptr(np))) - { - /* - * if it's already an indexed array, convert to - * associative structure - */ - if(!is_associative(ap)) - ap = nv_changearray(np, fun); - return(ap); - } - if(nv_isnull(np) && nv_isattr(np,NV_NOFREE)) - { - nelem = ARRAY_TREE; - nv_offattr(np,NV_NOFREE); - } - if(!(fp=nv_isvtree(np))) - value = nv_getval(np); - if(fun && !ap && (ap = (Namarr_t*)((*fun)(np, NIL(char*), NV_AINIT)))) - { - /* check for preexisting initialization and save */ - ap->nelem = nelem; - ap->fun = fun; - nv_onattr(np,NV_ARRAY); - if(fp || value) - { - nv_putsub(np, "0", ARRAY_ADD); - if(value) - nv_putval(np, value, 0); - else - { - Namval_t *mp = (Namval_t*)((*fun)(np,NIL(char*),NV_ACURRENT)); - array_copytree(np,mp); - } - } - return(ap); - } - return(NIL(Namarr_t*)); -} - -/* - * move parent subscript into child - */ -Namval_t *nv_arraychild(Namval_t *np, Namval_t *nq, int c) -{ - Namfun_t *fp; - register Namarr_t *ap = nv_arrayptr(np); - union Value *up; - Namval_t *tp; - if(!nq) - return(ap?array_find(np,ap, ARRAY_LOOKUP):0); - if(!ap) - { - nv_putsub(np, NIL(char*), ARRAY_FILL); - ap = nv_arrayptr(np); - } - if(!(up = array_getup(np,ap,0))) - return((Namval_t*)0); - np->nvalue.cp = up->cp; - if((tp=nv_type(np)) || c) - { - ap->nelem |= ARRAY_NOCLONE; - nq->nvenv = (char*)np; - if(c=='t') - nv_clone(tp,nq, 0); - else - nv_clone(np, nq, NV_NODISC); - nv_offattr(nq,NV_ARRAY); - ap->nelem &= ~ARRAY_NOCLONE; - } - nq->nvenv = (char*)np; - if((fp=nq->nvfun) && fp->disc && fp->disc->setdisc && (fp = nv_disc(nq,fp,NV_POP))) - free((void*)fp); - if(!ap->fun) - { - struct index_array *aq = (struct index_array*)ap; - array_setbit(aq->bits,aq->cur,ARRAY_CHILD); - up->np = nq; - } - if(c=='.') - nv_setvtree(nq); - return(nq); -} - -/* - * This routine sets subscript of <np> to the next element, if any. - * The return value is zero, if there are no more elements - * Otherwise, 1 is returned. - */ -int nv_nextsub(Namval_t *np) -{ - register struct index_array *ap = (struct index_array*)nv_arrayptr(np); - register unsigned dot; - struct index_array *aq=0, *ar=0; - if(!ap || !(ap->header.nelem&ARRAY_SCAN)) - return(0); - if(is_associative(ap)) - { - Namval_t *nq; - if(nq=(*ap->header.fun)(np,NIL(char*),NV_ANEXT)) - { - if(nv_isattr(nq,NV_CHILD)) - nv_putsub(nq->nvalue.np,NIL(char*),ARRAY_UNDEF); - return(1); - } - ap->header.nelem &= ~(ARRAY_SCAN|ARRAY_NOCHILD); - return(0); - } - if(!(ap->header.nelem&ARRAY_NOSCOPE)) - ar = (struct index_array*)ap->header.scope; - for(dot=ap->cur+1; dot < (unsigned)ap->maxi; dot++) - { - aq = ap; - if(!ap->val[dot].cp && !(ap->header.nelem&ARRAY_NOSCOPE)) - { - if(!(aq=ar) || dot>=(unsigned)aq->maxi) - continue; - } - if(aq->val[dot].cp) - { - ap->cur = dot; - if(array_isbit(aq->bits, dot,ARRAY_CHILD)) - { - Namval_t *mp = aq->val[dot].np; - if((aq->header.nelem&ARRAY_NOCHILD) && nv_isvtree(mp) && !mp->nvfun->dsize) - continue; - if(nv_isarray(mp)) - nv_putsub(mp,NIL(char*),ARRAY_UNDEF); - } - return(1); - } - } - ap->header.nelem &= ~(ARRAY_SCAN|ARRAY_NOCHILD); - ap->cur = 0; - return(0); -} - -/* - * Set an array subscript for node <np> given the subscript <sp> - * An array is created if necessary. - * <mode> can be a number, plus or more of symbolic constants - * ARRAY_SCAN, ARRAY_UNDEF, ARRAY_ADD - * The node pointer is returned which can be NULL if <np> is - * not already array and the ARRAY_ADD bit of <mode> is not set. - * ARRAY_FILL sets the specified subscript to the empty string when - * ARRAY_ADD is specified and there is no value or sets all - * the elements up to the number specified if ARRAY_ADD is not specified - */ -Namval_t *nv_putsub(Namval_t *np,register char *sp,register long mode) -{ - register struct index_array *ap = (struct index_array*)nv_arrayptr(np); - register int size = (mode&ARRAY_MASK); - if(!ap || !ap->header.fun) - { - if(sp) - { - if(ap && ap->xp && !strmatch(sp,"+([0-9])")) - { - Namval_t *mp = nv_namptr(ap->xp,0); - nv_putval(mp, sp,0); - size = nv_getnum(mp); - } - else - size = (int)sh_arith((char*)sp); - } - if(size <0 && ap) - size += array_maxindex(np); - if(size >= ARRAY_MAX || (size < 0)) - { - errormsg(SH_DICT,ERROR_exit(1),e_subscript, nv_name(np)); - return(NIL(Namval_t*)); - } - if(!ap || size>=ap->maxi) - { - if(size==0 && !(mode&ARRAY_FILL)) - return(NIL(Namval_t*)); - if(sh.subshell) - np = sh_assignok(np,1); - ap = array_grow(np, ap,size); - } - ap->header.nelem &= ~ARRAY_UNDEF; - ap->header.nelem |= (mode&(ARRAY_SCAN|ARRAY_NOCHILD|ARRAY_UNDEF|ARRAY_NOSCOPE)); -#if 0 - if(array_isbit(ap->bits,oldsize,ARRAY_CHILD)) - mp = ap->val[oldsize].np; - if(size != oldsize && mp->nvalue.cp) - { - Namfun_t *nfp; - for(nfp=np->nvfun; nfp; nfp=nfp->next) - { - if(nfp->disc && nfp->disc->readf) - { - (*nfp->disc->readf)(mp,(Sfio_t*)0,0,nfp); - break; - } - } - } -#endif - ap->cur = size; - if((mode&ARRAY_SCAN) && (ap->cur--,!nv_nextsub(np))) - np = 0; - if(mode&(ARRAY_FILL|ARRAY_ADD)) - { - if(!(mode&ARRAY_ADD)) - { - int n; - for(n=0; n <= size; n++) - { - if(!ap->val[n].cp) - { - ap->val[n].cp = Empty; - if(!array_covered(np,ap)) - ap->header.nelem++; - } - } - if(n=ap->maxi-ap->maxi) - memset(&ap->val[size],0,n*sizeof(union Value)); - } - else if(!ap->val[size].cp) - { - if(sh.subshell) - np = sh_assignok(np,1); - ap->val[size].cp = Empty; - if(!array_covered(np,ap)) - ap->header.nelem++; - } - } - else if(!(mode&ARRAY_SCAN)) - { - ap->header.nelem &= ~ARRAY_SCAN; - if(array_isbit(ap->bits,size,ARRAY_CHILD)) - nv_putsub(ap->val[size].np,NIL(char*),ARRAY_UNDEF); - if(sp && !(mode&ARRAY_ADD) && !ap->val[size].cp) - np = 0; - } - return((Namval_t*)np); - } - ap->header.nelem &= ~ARRAY_UNDEF; - if(!(mode&ARRAY_FILL)) - ap->header.nelem &= ~ARRAY_SCAN; - ap->header.nelem |= (mode&(ARRAY_SCAN|ARRAY_NOCHILD|ARRAY_UNDEF|ARRAY_NOSCOPE)); - if(sp) - { - if(mode&ARRAY_SETSUB) - { - (*ap->header.fun)(np, sp, NV_ASETSUB); - return(np); - } - (*ap->header.fun)(np, sp, (mode&ARRAY_ADD)?NV_AADD:0); - if(!(mode&(ARRAY_SCAN|ARRAY_ADD)) && !(*ap->header.fun)(np,NIL(char*),NV_ACURRENT)) - np = 0; - } - else if(mode&ARRAY_SCAN) - (*ap->header.fun)(np,(char*)np,0); - else if(mode&ARRAY_UNDEF) - (*ap->header.fun)(np, "",0); - if((mode&ARRAY_SCAN) && !nv_nextsub(np)) - np = 0; - return(np); -} - -/* - * process an array subscript for node <np> given the subscript <cp> - * returns pointer to character after the subscript - */ -char *nv_endsubscript(Namval_t *np, register char *cp, int mode) -{ - register int count=1, quoted=0, c; - register char *sp = cp+1; - /* first find matching ']' */ - while(count>0 && (c= *++cp)) - { - if(c=='\\' && (!(mode&NV_SUBQUOTE) || (c=cp[1])=='[' || c==']' || c=='\\' || c=='*' || c=='@')) - { - quoted=1; - cp++; - } - else if(c=='[') - count++; - else if(c==']') - count--; - } - *cp = 0; - if(quoted) - { - /* strip escape characters */ - count = staktell(); - stakwrite(sp,1+cp-sp); - sh_trim(sp=stakptr(count)); - } - if(mode && np) - { - Namarr_t *ap = nv_arrayptr(np); - int scan = 0; - if(ap) - scan = ap->nelem&ARRAY_SCAN; - if((mode&NV_ASSIGN) && (cp[1]=='=' || cp[1]=='+')) - mode |= NV_ADD; - nv_putsub(np, sp, ((mode&NV_ADD)?ARRAY_ADD:0)|(cp[1]&&(mode&NV_ADD)?ARRAY_FILL:mode&ARRAY_FILL)); - if(scan) - ap->nelem |= scan; - } - if(quoted) - stakseek(count); - *cp++ = c; - return(cp); -} - - -Namval_t *nv_opensub(Namval_t* np) -{ - register struct index_array *ap = (struct index_array*)nv_arrayptr(np); - if(ap) - { - if(is_associative(ap)) - return((Namval_t*)((*ap->header.fun)(np,NIL(char*),NV_ACURRENT))); - else if(array_isbit(ap->bits,ap->cur,ARRAY_CHILD)) - return(ap->val[ap->cur].np); - } - return(NIL(Namval_t*)); -} - -char *nv_getsub(Namval_t* np) -{ - static char numbuff[NUMSIZE]; - register struct index_array *ap; - register unsigned dot, n; - register char *cp = &numbuff[NUMSIZE]; - if(!np || !(ap = (struct index_array*)nv_arrayptr(np))) - return(NIL(char*)); - if(is_associative(ap)) - return((char*)((*ap->header.fun)(np,NIL(char*),NV_ANAME))); - if(ap->xp) - { - np = nv_namptr(ap->xp,0); - np->nvalue.s = ap->cur; - return(nv_getval(np)); - } - if((dot = ap->cur)==0) - *--cp = '0'; - else while(n=dot) - { - dot /= 10; - *--cp = '0' + (n-10*dot); - } - return(cp); -} - -/* - * If <np> is an indexed array node, the current subscript index - * returned, otherwise returns -1 - */ -int nv_aindex(register Namval_t* np) -{ - Namarr_t *ap = nv_arrayptr(np); - if(!ap) - return(0); - else if(is_associative(ap)) - return(-1); - return(((struct index_array*)(ap))->cur&ARRAY_MASK); -} - -int nv_arraynsub(register Namarr_t* ap) -{ - return(array_elem(ap)); -} - -int nv_aimax(register Namval_t* np) -{ - struct index_array *ap = (struct index_array*)nv_arrayptr(np); - int sub = -1; - if(!ap || is_associative(&ap->header)) - return(-1); - sub = ap->maxi; - while(--sub>0 && ap->val[sub].cp==0); - return(sub); -} - -/* - * This is the default implementation for associative arrays - */ -void *nv_associative(register Namval_t *np,const char *sp,int mode) -{ - register struct assoc_array *ap = (struct assoc_array*)nv_arrayptr(np); - register int type; - switch(mode) - { - case NV_AINIT: - if(ap = (struct assoc_array*)calloc(1,sizeof(struct assoc_array))) - { - ap->header.table = dtopen(&_Nvdisc,Dtoset); - ap->cur = 0; - ap->pos = 0; - ap->header.hdr.disc = &array_disc; - nv_disc(np,(Namfun_t*)ap, NV_FIRST); - ap->header.hdr.dsize = sizeof(struct assoc_array); - ap->header.hdr.nofree &= ~1; - } - return((void*)ap); - case NV_ADELETE: - if(ap->cur) - { - if(!ap->header.scope || (Dt_t*)ap->header.scope==ap->header.table || !nv_search(ap->cur->nvname,(Dt_t*)ap->header.scope,0)) - ap->header.nelem--; - _nv_unset(ap->cur,NV_RDONLY); - nv_delete(ap->cur,ap->header.table,0); - ap->cur = 0; - } - return((void*)ap); - case NV_AFREE: - ap->pos = 0; - if(ap->header.scope) - { - ap->header.table = dtview(ap->header.table,(Dt_t*)0); - dtclose(ap->header.scope); - ap->header.scope = 0; - } - else - dtclose(ap->header.table); - return((void*)ap); - case NV_ANEXT: - if(!ap->pos) - { - if((ap->header.nelem&ARRAY_NOSCOPE) && ap->header.scope && dtvnext(ap->header.table)) - { - ap->header.scope = dtvnext(ap->header.table); - ap->header.table->view = 0; - } - if(!(ap->pos=ap->cur)) - ap->pos = (Namval_t*)dtfirst(ap->header.table); - } - else - ap->pos = ap->nextpos; - for(;ap->cur=ap->pos; ap->pos=ap->nextpos) - { - ap->nextpos = (Namval_t*)dtnext(ap->header.table,ap->pos); - if(ap->cur->nvalue.cp) - { - if((ap->header.nelem&ARRAY_NOCHILD) && nv_isattr(ap->cur,NV_CHILD)) - continue; - return((void*)ap); - } - } - if((ap->header.nelem&ARRAY_NOSCOPE) && ap->header.scope && !dtvnext(ap->header.table)) - { - ap->header.table->view = (Dt_t*)ap->header.scope; - ap->header.scope = ap->header.table; - } - return(NIL(void*)); - case NV_ASETSUB: - ap->cur = (Namval_t*)sp; - return((void*)ap->cur); - case NV_ACURRENT: - if(ap->cur) - ap->cur->nvenv = (char*)np; - return((void*)ap->cur); - case NV_ANAME: - if(ap->cur) - { - Shell_t *shp = sh_getinterp(); - if(!shp->instance && nv_isnull(ap->cur)) - return(NIL(void*)); - return((void*)ap->cur->nvname); - } - return(NIL(void*)); - default: - if(sp) - { - Namval_t *mp=0; - ap->cur = 0; - if(sp==(char*)np) - return(0); - type = nv_isattr(np,NV_PUBLIC&~(NV_ARRAY|NV_CHILD|NV_MINIMAL)); - if(mode) - mode = NV_ADD|HASH_NOSCOPE; - else if(ap->header.nelem&ARRAY_NOSCOPE) - mode = HASH_NOSCOPE; - if(*sp==0 && sh_isoption(SH_XTRACE) && (mode&NV_ADD)) - errormsg(SH_DICT,ERROR_warn(0),"adding empty subscript"); - if(sh.subshell && (mp=nv_search(sp,ap->header.table,0)) && nv_isnull(mp)) - ap->cur = mp; - if((mp || (mp=nv_search(sp,ap->header.table,mode))) && nv_isnull(mp) && (mode&NV_ADD)) - { - nv_onattr(mp,type); - mp->nvenv = (char*)np; - if((mode&NV_ADD) && nv_type(np)) - nv_arraychild(np,mp,0); - if(sh.subshell) - np = sh_assignok(np,1); - if(!ap->header.scope || !nv_search(sp,dtvnext(ap->header.table),0)) - ap->header.nelem++; - if(nv_isnull(mp)) - { - if(ap->header.nelem&ARRAY_TREE) - nv_setvtree(mp); - mp->nvalue.cp = Empty; - } - } - else if(ap->header.nelem&ARRAY_SCAN) - { - Namval_t fake; - fake.nvname = (char*)sp; - ap->pos = mp = (Namval_t*)dtprev(ap->header.table,&fake); - ap->nextpos = (Namval_t*)dtnext(ap->header.table,mp); - } - else if(!mp && *sp && mode==0) - mp = nv_search(sp,ap->header.table,NV_ADD); - np = mp; - if(ap->pos && ap->pos==np) - ap->header.nelem |= ARRAY_SCAN; - else if(!(ap->header.nelem&ARRAY_SCAN)) - ap->pos = 0; - ap->cur = np; - } - if(ap->cur) - return((void*)(&ap->cur->nvalue)); - else - return((void*)(&ap->cur)); - } -} - -/* - * Assign values to an array - */ -void nv_setvec(register Namval_t *np,int append,register int argc,register char *argv[]) -{ - int arg0=0; - struct index_array *ap=0,*aq; - if(nv_isarray(np)) - { - ap = (struct index_array*)nv_arrayptr(np); - if(ap && is_associative(ap)) - errormsg(SH_DICT,ERROR_exit(1),"cannot append index array to associative array %s",nv_name(np)); - } - if(append) - { - if(ap) - { - if(!(aq = (struct index_array*)ap->header.scope)) - aq = ap; - arg0 = ap->maxi; - while(--arg0>0 && ap->val[arg0].cp==0 && aq->val[arg0].cp==0); - arg0++; - } - else if(!nv_isnull(np)) - arg0=1; - } - while(--argc >= 0) - { - nv_putsub(np,NIL(char*),(long)argc+arg0|ARRAY_FILL|ARRAY_ADD); - nv_putval(np,argv[argc],0); - } -} - |