summaryrefslogtreecommitdiff
path: root/usr/src/lib/libshell/common/sh/array.c
diff options
context:
space:
mode:
authorApril Chin <April.Chin@Sun.COM>2008-12-27 14:59:38 -0800
committerApril Chin <April.Chin@Sun.COM>2008-12-27 14:59:38 -0800
commit7c2fbfb345896881c631598ee3852ce9ce33fb07 (patch)
tree4b173b5657508562dfc0aa05f7d056d1e9add505 /usr/src/lib/libshell/common/sh/array.c
parent6071ac1de68fed78e1e10052045bbb5f1732a263 (diff)
downloadillumos-joyent-7c2fbfb345896881c631598ee3852ce9ce33fb07.tar.gz
PSARC/2008/094 ksh93 Update 1
PSARC/2008/344 ksh93 Integration Update 1 Amendments 1 PSARC/2008/589 Remove /usr/bin/printf from PSARC case 2008 094 6619428 *ksh93* RFE: Update ksh93 in Solaris to ast-ksh.2008-11-04 6788659 RFE: Update libpp in Solaris to ast-open.2008-07-25 6561901 RFE: Add "shcomp" (shell script compiler) + kernel module to exec binary sh code 6599668 RFE: Move consumers of alias.sh over to ksh93 6595183 *ksh93* RFE: Update ksh93-integration demo code 6775901 *ksh93* no C message catalogs are generated for ksh93 6451262 *sleep* RFE: /usr/bin/sleep should support floating-point values 6687139 *ksh93* command substitution, exec, and stdout redirection cause allocation loop 6703761 *ksh93* crashes in script containing uncommon output redirections 6715496 *ksh93* SEGVs on array reinitialization 6713682 *ksh93* Creating a compound variable in a subshell "bleeds through" to the calling subshell 6672350 *ksh93* causes parent shell to die when child shell is suspended 6745015 *ksh93* VARIABLE=`command substitution` assignment is not reliable on OpenSolaris 6710205 *ksh93* problem with command substitution (within back quotes) containing \$' 6737600 *ksh93* exits debugger when user presses ctrl-c 6748645 *ksh93* fc -l -e - is mis-parsed, outputs wrong error message "-e - requires single argument" 6754020 *ksh93* does weird '[' expansion 6753538 *ksh93* umask modification leaks out of a ksh93 subshell 6766246 *ksh93* bug in pattern matching 6763594 *ksh93* executes command after "command" builtin twice on failure 6762665 *ksh93* Difficult-to-reproduce SIGSEGV in ksh93
Diffstat (limited to 'usr/src/lib/libshell/common/sh/array.c')
-rw-r--r--usr/src/lib/libshell/common/sh/array.c825
1 files changed, 643 insertions, 182 deletions
diff --git a/usr/src/lib/libshell/common/sh/array.c b/usr/src/lib/libshell/common/sh/array.c
index 5b33f20e5a..ed46e84738 100644
--- a/usr/src/lib/libshell/common/sh/array.c
+++ b/usr/src/lib/libshell/common/sh/array.c
@@ -1,10 +1,10 @@
/***********************************************************************
* *
* This software is part of the ast package *
-* Copyright (c) 1982-2007 AT&T Knowledge Ventures *
+* Copyright (c) 1982-2008 AT&T Intellectual Property *
* and is licensed under the *
* Common Public License, Version 1.0 *
-* by AT&T Knowledge Ventures *
+* by AT&T Intellectual Property *
* *
* A copy of the License is available at *
* http://www.opensource.org/licenses/cpl1.0.txt *
@@ -33,16 +33,17 @@
#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) (cp[(n)/CHAR_BIT] |= 1<<(((n)&(CHAR_BIT-1))))
-#define array_clrbit(cp, n) (cp[(n)/CHAR_BIT] &= ~(1<<(((n)&(CHAR_BIT-1)))))
-#define array_isbit(cp, n) (cp[(n)/CHAR_BIT] & 1<<(((n)&(CHAR_BIT-1))))
+#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
-
-static char Empty[] = "";
+#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 */
@@ -52,12 +53,62 @@ struct index_array
struct assoc_array
{
Namarr_t header;
- Dt_t *table;
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
*/
@@ -81,10 +132,12 @@ static void array_setptr(register Namval_t *np, struct index_array *old, struct
* but <= ARRAY_MAX) is returned.
*
*/
-static int arsize(register int maxi)
+static int arsize(struct index_array *ap, register int maxi)
{
- register int i = roundof(maxi,ARRAY_INCR);
- return (i>ARRAY_MAX?ARRAY_MAX:i);
+ 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);
@@ -100,19 +153,38 @@ int array_maxindex(Namval_t *np)
return(i+1);
}
-static union Value *array_getup(Namval_t *np, Namarr_t *arp)
+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;
- if(!nv_isarray(np))
+ int nofree;
+ if(!arp)
return(&np->nvalue);
if(is_associative(ap))
- up = (union Value*)((*arp->fun)(np,NIL(char*),0));
+ {
+ 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);
}
@@ -128,13 +200,17 @@ static Namval_t *array_find(Namval_t *np,Namarr_t *arp, int flag)
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);
+ nv_putsub(np, NIL(char*), ARRAY_SCAN|ARRAY_NOSCOPE);
ap->header.nelem |= ARRAY_SCAN;
}
else /* same as array[0] */
@@ -150,14 +226,25 @@ static Namval_t *array_find(Namval_t *np,Namarr_t *arp, int flag)
mp = (Namval_t*)((*arp->fun)(np,NIL(char*),NV_ACURRENT));
if(!mp)
up = (union Value*)&mp;
- else if(nv_isattr(mp,NV_CHILD))
+ else if(nv_isarray(mp))
{
- if(wasundef && nv_isarray(mp->nvalue.np))
- nv_putsub(mp->nvalue.np,NIL(char*),ARRAY_UNDEF);
- return(mp->nvalue.np);
+ 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
{
@@ -166,7 +253,18 @@ static Namval_t *array_find(Namval_t *np,Namarr_t *arp, int flag)
if(ap->cur>=ap->maxi)
errormsg(SH_DICT,ERROR_exit(1),e_subscript,nv_name(np));
up = &(ap->val[ap->cur]);
- if(up->np && array_isbit(ap->bits,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);
@@ -178,97 +276,201 @@ static Namval_t *array_find(Namval_t *np,Namarr_t *arp, int flag)
{
if(flag!=ARRAY_ASSIGN)
return(0);
- ap->header.nelem++;
+ 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 = ap->nelem,offset=staktell();
- struct index_array *aq, *ar;
+ 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(array_assoc(ap))
- nv_setarray(mp,ap->fun);
- else
+ if((flags&NV_TYPE) && !ap->scope)
{
- nv_putsub(mp,NIL(char*),ap->nelem);
- if(aq=(struct index_array*)nv_arrayptr(mp))
- aq->bits = (unsigned char*)&aq->val[aq->maxi];
+ 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;
- nv_onattr(mp,nv_isattr(np,NV_INTEGER|NV_UTOL|NV_LTOU|NV_LJUST|NV_RJUST|NV_ZFILL|NV_BINARY));
- nv_putsub(np,NIL(char*),ARRAY_SCAN);
+ 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
{
- if(array_assoc(ap))
- name = (char*)((*ap->fun)(np,NIL(char*),NV_ANAME));
- else
- name = nv_getsub(np);
- nv_putsub(mp,name,ARRAY_ADD);
- if((!array_assoc(ap) && array_isbit(ar->bits,ar->cur) && (nq=np)) ||
- (array_assoc(ap) && (nq = (Namval_t*)((*ap->fun)(np,NIL(char*),NV_ACURRENT))) && nv_isattr(nq, NV_CHILD)))
- {
- sfprintf(stkstd,"%s[%s]",nv_name(mp),name);
- stakputc(0);
- mq = nv_search(stakptr(offset), sh.var_tree, NV_ADD);
- stakseek(offset);
- if(mq)
+ 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))
{
- nv_clone(nq->nvalue.np,mq,0);
- if(array_assoc(ap))
- {
- nq = (Namval_t*)((*ap->fun)(mp,NIL(char*),NV_ACURRENT));
- nq->nvalue.np = mp;
- nv_onattr(nq,NV_CHILD);
- }
- else if(aq)
- {
- array_setbit(aq->bits,aq->cur);
- aq->val[aq->cur].np = mq;
- }
+ 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)
{
- nv_putsub(np,sub,0L);
+ if(!skipped)
+ nv_putsub(np,sub,0L);
free((void*)sub);
}
- ap->nelem = nelem;
- ((Namarr_t*)mp->nvfun)->nelem = nelem;
- return(nv_stack(mp,(Namfun_t*)0));
+ aq->header.nelem = ap->nelem = nelem;
+ return(&ap->hdr);
}
static char *array_getval(Namval_t *np, Namfun_t *disc)
{
- register Namarr_t *ap = (Namarr_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 *ap = (Namarr_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));
}
@@ -278,52 +480,113 @@ static void array_putval(Namval_t *np, const char *string, int flags, Namfun_t *
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 && !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(mp!=np)
- {
- dtdelete(sh.var_tree,(void*)mp);
- free((void*)mp);
- }
if(is_associative(ap))
+ {
(*ap->fun)(np,NIL(char*),NV_ADELETE);
- else if(mp!=np)
+ np->nvalue.cp = 0;
+ }
+ else
{
- array_clrbit(aq->bits,aq->cur);
- aq->val[aq->cur].cp = 0;
+ 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--;
}
- ap->nelem--;
}
if(array_elem(ap)==0 && ((ap->nelem&ARRAY_SCAN) || !is_associative(ap)))
{
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)
+ if(!mp || mp!=np || is_associative(ap))
continue;
}
+ skip:
/* prevent empty string from being deleted */
- if(np->nvalue.cp == Empty)
- np->nvalue.cp = 0;
+ 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);
- up = array_getup(np,ap);
- up->cp = np->nvalue.cp;
+ 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(nfp = nv_disc(np,(Namfun_t*)ap,NV_POP))
+ 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 =
@@ -337,6 +600,21 @@ static const Namdisc_t array_disc =
array_clone
};
+static void array_copytree(Namval_t *np, Namval_t *mp)
+{
+ char *val;
+ Namfun_t *fp = nv_disc(np,NULL,NV_POP);
+ nv_offattr(np,NV_ARRAY);
+ nv_clone(np,mp,0);
+ np->nvalue.up = &mp->nvalue;
+ val = sfstruse(sh.strbuf);
+ 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
@@ -347,61 +625,105 @@ static const Namdisc_t array_disc =
static struct index_array *array_grow(Namval_t *np, register struct index_array *arp,int maxi)
{
register struct index_array *ap;
- register int i=0;
- register int newsize = arsize(maxi+1);
+ 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));
- ap = new_of(struct index_array,(newsize-1)*sizeof(union Value*)+newsize/CHAR_BIT);
- memset((void*)ap,0,sizeof(*ap));
+ 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/CHAR_BIT);
+ memset(ap->bits, 0, newsize);
if(arp)
{
ap->header = arp->header;
- for(;i < arp->maxi;i++)
+ 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/CHAR_BIT));
+ 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((ap->val[0].cp=np->nvalue.cp))
- i++;
- else if(nv_hasdisc(np,&array_disc))
- {
- Namval_t *mp;
- int offset = staktell();
- sfprintf(stkstd,"%s[0]",nv_name(np));
- stakputc(0);
- mp = nv_search(stakptr(offset), sh.var_tree, NV_ADD);
- stakseek(offset);
+ 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, 0);
+
if(mp && nv_isnull(mp))
{
- nv_clone(np,mp,0);
+ Namfun_t *fp;
ap->val[0].np = mp;
- array_setbit(ap->bits,0);
+ array_setbit(ap->bits,0,ARRAY_CHILD);
+ for(fp=np->nvfun; fp && !fp->disc->readf; fp=fp->next);
+ if(fp)
+ (*fp->disc->readf)(mp,(Sfio_t*)0,0,fp);
+ i++;
}
- i++;
}
+ else if((ap->val[0].cp=np->nvalue.cp))
+ i++;
else if(nv_isattr(np,NV_INTEGER))
{
Sfdouble_t d= nv_getnum(np);
i++;
}
ap->header.nelem = i;
- ap->header.hdr.nofree = 1;
ap->header.hdr.disc = &array_disc;
- nv_disc(np,(Namfun_t*)ap, NV_LAST);
+ 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))
@@ -446,7 +768,6 @@ static Namarr_t *nv_changearray(Namval_t *np, void *(*fun)(Namval_t*,const char*
}
nv_putsub(np, string_index, ARRAY_ADD);
up = (union Value*)((*ap->fun)(np,NIL(char*),0));
- ap->nelem++;
up->cp = save_ap->val[dot].cp;
save_ap->val[dot].cp = 0;
}
@@ -463,7 +784,9 @@ static Namarr_t *nv_changearray(Namval_t *np, void *(*fun)(Namval_t*,const char*
Namarr_t *nv_setarray(Namval_t *np, void *(*fun)(Namval_t*,const char*,int))
{
register Namarr_t *ap;
- char *value;
+ char *value=0;
+ Namfun_t *fp;
+ int nelem = 0;
if(fun && (ap = nv_arrayptr(np)))
{
/*
@@ -474,17 +797,29 @@ Namarr_t *nv_setarray(Namval_t *np, void *(*fun)(Namval_t*,const char*,int))
ap = nv_changearray(np, fun);
return(ap);
}
- value = nv_getval(np);
+ 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 = 0;
+ ap->nelem = nelem;
ap->fun = fun;
nv_onattr(np,NV_ARRAY);
- if(value)
+ if(fp || value)
{
nv_putsub(np, "0", ARRAY_ADD);
- nv_putval(np, value, 0);
+ 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);
}
@@ -496,27 +831,38 @@ Namarr_t *nv_setarray(Namval_t *np, void *(*fun)(Namval_t*,const char*,int))
*/
Namval_t *nv_arraychild(Namval_t *np, Namval_t *nq, int c)
{
- register Namarr_t *ap = nv_arrayptr(np);
- union Value *up;
- if(!(up = array_getup(np,ap)))
- return((Namval_t*)0);
+ Namfun_t *fp;
+ register Namarr_t *ap = nv_arrayptr(np);
+ union Value *up;
+ Namval_t *tp;
if(!nq)
- return(array_find(np,ap, ARRAY_LOOKUP));
+ 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;
- ap->nelem |= ARRAY_NOCLONE;
- nv_clone(np, nq, NV_NODISC);
- nv_offattr(nq,NV_ARRAY);
- ap->nelem &= ~ARRAY_NOCLONE;
- if(ap->fun)
+ if((tp=nv_type(np)) || c)
{
- up->np = (Namval_t*)((*ap->fun)(np,NIL(char*),NV_ACURRENT));
- nv_onattr(up->np, NV_CHILD);
- (up->np)->nvalue.np = nq;
+ 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;
}
- else
+ 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_setbit(aq->bits,aq->cur,ARRAY_CHILD);
up->np = nq;
}
if(c=='.')
@@ -531,33 +877,42 @@ Namval_t *nv_arraychild(Namval_t *np, Namval_t *nq, int c)
*/
int nv_nextsub(Namval_t *np)
{
- register struct index_array *ap = (struct index_array*)nv_arrayptr(np);
- register unsigned dot;
+ 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))
{
- struct assoc_array *aq;
- if(aq=(*ap->header.fun)(np,NIL(char*),NV_ANEXT))
+ Namval_t *nq;
+ if(nq=(*ap->header.fun)(np,NIL(char*),NV_ANEXT))
{
- if(nv_isattr(aq->cur,NV_CHILD))
- nv_putsub(aq->cur->nvalue.np,NIL(char*),ARRAY_UNDEF);
+ 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++)
{
- if(ap->val[dot].cp)
+ 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(ap->bits, dot))
+ if(array_isbit(aq->bits, dot,ARRAY_CHILD))
{
-
- if(ap->header.nelem&ARRAY_NOCHILD)
+ Namval_t *mp = aq->val[dot].np;
+ if((aq->header.nelem&ARRAY_NOCHILD) && nv_isvtree(mp))
continue;
- nv_putsub(ap->val[dot].np,NIL(char*),ARRAY_UNDEF);
+ nv_putsub(mp,NIL(char*),ARRAY_UNDEF);
}
return(1);
}
@@ -585,7 +940,18 @@ Namval_t *nv_putsub(Namval_t *np,register char *sp,register long mode)
if(!ap || !ap->header.fun)
{
if(sp)
- size = (int)sh_arith((char*)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));
@@ -598,24 +964,42 @@ Namval_t *nv_putsub(Namval_t *np,register char *sp,register long mode)
if(sh.subshell)
np = sh_assignok(np,1);
ap = array_grow(np, ap,size);
- nv_onattr(np,NV_ARRAY);
}
ap->header.nelem &= ~ARRAY_UNDEF;
- ap->header.nelem |= (mode&(ARRAY_SCAN|ARRAY_NOCHILD|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->val[size].cp && !nv_nextsub(np))
+ if((mode&ARRAY_SCAN) && (ap->cur--,!nv_nextsub(np)))
np = 0;
- if(mode&ARRAY_FILL)
+ if(mode&(ARRAY_FILL|ARRAY_ADD))
{
if(!(mode&ARRAY_ADD))
{
int n;
- for(n=0; n < size; 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++;
+ }
}
- ap->header.nelem = n|(ap->header.nelem&(ARRAY_SCAN|ARRAY_UNDEF));
if(n=ap->maxi-ap->maxi)
memset(&ap->val[size],0,n*sizeof(union Value));
}
@@ -624,37 +1008,34 @@ Namval_t *nv_putsub(Namval_t *np,register char *sp,register long mode)
if(sh.subshell)
np = sh_assignok(np,1);
ap->val[size].cp = Empty;
- ap->header.nelem++;
+ if(!array_covered(np,ap))
+ ap->header.nelem++;
}
}
else if(!(mode&ARRAY_SCAN))
{
ap->header.nelem &= ~ARRAY_SCAN;
- if(array_isbit(ap->bits,size))
+ 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));
+ ap->header.nelem |= (mode&(ARRAY_SCAN|ARRAY_NOCHILD|ARRAY_UNDEF|ARRAY_NOSCOPE));
if(sp)
{
- union Value *up;
if(mode&ARRAY_SETSUB)
{
(*ap->header.fun)(np, sp, NV_ASETSUB);
return(np);
}
- up = (union Value*)(*ap->header.fun)(np, sp, (mode&ARRAY_ADD)?NV_AADD:0);
- if(up && !up->cp && (mode&ARRAY_ADD) && (mode&ARRAY_FILL))
- {
- if(sh.subshell)
- np = sh_assignok(np,1);
- up->cp = Empty;
- ap->header.nelem++;
- }
+ (*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);
@@ -695,7 +1076,11 @@ char *nv_endsubscript(Namval_t *np, register char *cp, int mode)
sh_trim(sp=stakptr(count));
}
if(mode && np)
- nv_putsub(np, sp, ARRAY_ADD|(cp[1]?ARRAY_FILL:mode&ARRAY_FILL));
+ {
+ 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(quoted)
stakseek(count);
*cp++ = c;
@@ -706,8 +1091,13 @@ char *nv_endsubscript(Namval_t *np, register char *cp, int mode)
Namval_t *nv_opensub(Namval_t* np)
{
register struct index_array *ap = (struct index_array*)nv_arrayptr(np);
- if(ap && is_associative(ap))
- return((Namval_t*)((*ap->header.fun)(np,NIL(char*),NV_ACURRENT)));
+ 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*));
}
@@ -721,6 +1111,12 @@ char *nv_getsub(Namval_t* 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)
@@ -738,14 +1134,31 @@ char *nv_getsub(Namval_t* np)
int nv_aindex(register Namval_t* np)
{
Namarr_t *ap = nv_arrayptr(np);
- if(!ap || is_associative(ap))
+ 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 associate arrays
+ * This is the default implementation for associative arrays
*/
void *nv_associative(register Namval_t *np,const char *sp,int mode)
{
@@ -756,42 +1169,52 @@ void *nv_associative(register Namval_t *np,const char *sp,int mode)
case NV_AINIT:
if(ap = (struct assoc_array*)calloc(1,sizeof(struct assoc_array)))
{
- ap->table = dtopen(&_Nvdisc,Dtbag);
+ ap->header.table = dtopen(&_Nvdisc,Dtoset);
ap->cur = 0;
ap->pos = 0;
ap->header.hdr.disc = &array_disc;
- ap->header.hdr.nofree = 1;
- nv_disc(np,(Namfun_t*)ap, NV_LAST);
+ 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(nv_isattr(ap->cur,NV_NOFREE))
- nv_offattr(ap->cur,NV_NOFREE);
- else
- {
- dtdelete(ap->table,(void*)ap->cur);
- free((void*)ap->cur);
- ap->cur = 0;
- }
+ 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;
- dtclose(ap->table);
+ 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->table);
+ 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->table,ap->pos);
+ 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))
@@ -799,29 +1222,66 @@ void *nv_associative(register Namval_t *np,const char *sp,int mode)
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;
- /* FALL THROUGH*/
+ 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)
- return((void*)nv_name(ap->cur));
+ return((void*)ap->cur->nvname);
return(NIL(void*));
default:
if(sp)
{
+ Namval_t *mp=0;
+ ap->cur = 0;
if(sp==(char*)np)
- {
- ap->cur = 0;
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 && (mode&NV_ADD))
+ sfprintf(sfstderr,"adding empty subscript\n");
+ 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(!(ap->header.nelem&ARRAY_SCAN))
+ np = mp;
+ if(ap->pos != np && !(ap->header.nelem&ARRAY_SCAN))
ap->pos = 0;
- type = nv_isattr(np,NV_PUBLIC&~(NV_ARRAY|NV_CHILD));
- if((np=nv_search(sp,ap->table,mode?NV_ADD:0)) && nv_isnull(np))
- nv_onattr(np,type);
ap->cur = np;
}
if(ap->cur)
@@ -837,19 +1297,21 @@ void *nv_associative(register Namval_t *np,const char *sp,int mode)
void nv_setvec(register Namval_t *np,int append,register int argc,register char *argv[])
{
int arg0=0;
- struct index_array *ap=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 associate array %s",nv_name(np));
+ 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);
+ while(--arg0>0 && ap->val[arg0].cp==0 && aq->val[arg0].cp==0);
arg0++;
}
else if(!nv_isnull(np))
@@ -857,8 +1319,7 @@ void nv_setvec(register Namval_t *np,int append,register int argc,register char
}
while(--argc >= 0)
{
- if((argc+arg0)>0 || nv_isattr(np,NV_ARRAY))
- nv_putsub(np,NIL(char*),(long)argc+arg0);
+ nv_putsub(np,NIL(char*),(long)argc+arg0|ARRAY_FILL|ARRAY_ADD);
nv_putval(np,argv[argc],0);
}
}