1
0
Files
irix-657m-src/eoe/cmd/ksh/shlib/growaray.c
2022-09-29 17:59:04 +03:00

376 lines
7.7 KiB
C

/* Copyright (c) 1990, 1991 UNIX System Laboratories, Inc. */
/* Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T */
/* All Rights Reserved */
/* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF */
/* UNIX System Laboratories, Inc. */
/* The copyright notice above does not evidence any */
/* actual or intended publication of such source code. */
#ident "@(#)ksh:shlib/growaray.c 1.3.4.1"
/*
* GROWARAY.C
*
* ARRAY_GROW (ARP, MAXI)
*
* Create or expand the size of an array of namnods, ARP,
* such that MAXI is a legal index into ARP.
*
* See Also: nam_link(III)
*/
#include "name.h"
#define ERROR 1
#define astchar(c) ((c)=='*' || (c)=='@')
#define round(a,b) ((a+b-1)&~(b-1))
#ifdef FLOAT
extern double sh_arith();
#else
extern long sh_arith();
#endif /* FLOAT */
extern char *sh_itos();
extern void sh_fail();
extern void free();
static int arsize();
static int next_value();
static char *array_end();
static unsigned short *cur_sub;
/*
* ARRAY_GROW (ARP, MAXI)
*
* struct Namaray *ARP;
*
* int MAXI;
*
* Increase the size of the array of namnods given by ARP
* so that MAXI is a legal index. If ARP is NULL, an array
* of the required size is allocated. A pointer to the
* allocated Namaray structure is returned.
*
* MAXI becomes the current index of the array.
*/
struct Namaray *array_grow(arp,maxi)
register struct Namaray *arp;
{
register struct Namaray *ap;
register unsigned i = 0;
register int newsize = arsize(maxi+1);
if (maxi >= ARRMAX)
sh_fail (sh_itos(maxi), e_subscript,ERROR);
ap = new_of(struct Namaray,(newsize-1)*sizeof(struct Nodval*));
ap->maxi = newsize;
ap->cur[0] = maxi;
if(arp)
{
ap->nelem = arp->nelem;
for(;i < arp->maxi;i++)
ap->val[i] = arp->val[i];
free((char *)arp);
}
else
ap->nelem = 0;
for(;i < newsize;i++)
ap->val[i] = NULL;
return(ap);
}
/*
* ARSIZE (MAXI)
*
* int MAXI;
*
* Calculate the amount of space to be allocated to hold
* an array into which MAXI is a legal index. The number of
* elements that will actually fit into the array (> MAXI
* but <= ARRMAX) is returned.
*
* ALGORITHM: The size of an array can be incremented in
* lots of ARRINCR elements. Internal size is thus
* the least multiple of ARRINCR that is greater than
* MAXI. (Note that 0-origin indexing is used.)
*/
static int arsize(maxi)
register int maxi;
{
register int i = round(maxi,ARRINCR);
return (i>ARRMAX?ARRMAX:i);
}
/*
* Get the Namval pointer for an array.
* Allocate the space if necessary, if flag is A_ASSIGN
* Delete space as necessary if flag is A_DELETE
* After the lookup is done the last @ or * subscript is incremented
*/
struct Nodval *array_find(np,flag)
struct namnod *np;
{
register unsigned dot;
register struct Namaray *ap = array_ptr(np);
register struct Nodval *nv = &np->value;
int varindex = -1; /* last * or @ index */
#ifdef MULTIDIM
int index = -1; /* subscript index */
while(++index < NDIM)
#else
# define index 0
#endif /* MULTIDIM */
{
np->value.namflg &= ~N_INDIRECT;
dot = ap->cur[index];
/* delete a is the same as delete a[@] */
if(dot&ARRAY_UNDEF)
{
#ifdef MULTIDIM
ap->cur[index+1] = dot;
#endif /* MULTIDIM */
dot = (flag==A_DELETE?ARRAY_AT:0);
ap->cur[index] = dot;
}
if(!(dot&~ARRAY_MASK))
{
if(dot >= ap->maxi)
{
ap = array_grow(ap, (int)dot);
nv->namval.aray = ap;
}
}
else if(flag!=A_ASSIGN)
{
varindex = index;
if((dot &= ARRAY_MASK) == 0)
{
cur_sub = ap->cur;
next_value(nv,index);
dot = ap->cur[index]&ARRAY_MASK;
}
}
if(dot >= ap->maxi)
sh_fail (np->namid, e_subscript,ERROR);
if((nv = ap->val[dot]) == NULL)
{
if(flag!=A_ASSIGN)
return(NULL);
ap->nelem++;
nv = new_of(struct Nodval,0);
ap->val[dot] = nv;
nv->namflg = np->value.namflg & ~N_ARRAY;
nv->namval.cp = NULL;
}
else
nv = unmark(nv);
if(flag==A_DELETE)
{
ap->val[dot] = 0;
if(--ap->nelem == 0)
{
free((char*)ap);
np->value.namflg = 0;
np->value.namval.aray = 0;
return(0);
}
}
#ifdef MULTIDIM
if(nv.namflg&N_ARRAY)
ap = nv->namval.aray;
#else
# undef index
#endif /* MULTIDIM */
}
if(varindex >= 0)
array_ptr(np)->cur[varindex]++;
np->value.namflg |= (nv->namflg&N_INDIRECT);
return(nv);
}
int array_next(np)
struct namnod *np;
{
cur_sub = array_ptr(np)->cur;
return(next_value(&np->value,0));
}
/*
* This routine is called for an array, i.e. nv->namflg&N_ARRAY must be set
* This routine sets dot to the next index, if any.
* The return value is zero, if there are no more elements or if the no
* component has changed.
* If a component has changed, the ARRAY_AT or ARRAY_STAR is returned depending
* on which index has changed
* The routine is called recursively
*/
static int next_value(nv,index)
register struct Nodval *nv;
{
register unsigned savdot = cur_sub[index++];
register unsigned dot = savdot&ARRAY_MASK;
register int ret;
#ifdef MULTIDIM
register int nextdot;
struct Nodval *nvnext;
#endif /* MULTIDIM */
savdot &= ~ARRAY_MASK;
if(savdot==0)
{
#ifdef MULTIDIM
if((nv=nv->namval.aray->val[dot]) && (nv->namflg&N_ARRAY))
return(next_value(nv,index));
#endif /* MULTIDIM */
return(0);
}
if(savdot&ARRAY_STAR)
ret = '*';
else
ret = '@';
while(dot < nv->namval.aray->maxi)
{
#ifdef MULTIDIM
if(nvnext = nv->namval.aray->val[dot])
{
register int next;
cur_sub[index-1] = dot|savdot;
if(nvnext->namflg&N_ARRAY)
{
if(next=next_value(nvnext,index))
return(next);
next = cur_sub[index];
if(next&~ ARRAY_MASK)
cur_sub[index] &= ~ARRAY_MASK;
else if(nvnext->namval.aray->val[next])
return(ret);
}
else if(next==0)
return(ret);
}
#else
if(nv->namval.aray->val[dot])
{
cur_sub[index-1] = dot|savdot;
return(ret);
}
#endif /* MULTIDIM */
dot++;
}
return(0);
}
/*
* process an array subscript for node <np> given the subscript <cp>
*/
char *array_subscript(np,cp)
struct namnod *np;
register char *cp;
{
register int c;
register int dot;
char *sp;
#ifdef MULTIDIM
register int index = -1;
while(++index < NDIM)
{
if( *cp != '[')
{
array_ptr(np)->cur[index] = ARRAY_UNDEF;
continue;
}
#endif /* MULIDIM */
cp = array_end(sp=cp);
c = *++sp;
if(astchar(c) && cp==sp+1)
{
if(!nam_istype(np,N_ARRAY))
return(cp+1);
if(c == '*')
dot = ARRAY_STAR;
else
dot = ARRAY_AT;
}
else
{
c = *cp;
*cp = 0;
dot = (int)sh_arith((char*)sp);
*cp = c;
if(dot >= ARRMAX || (dot < 0))
sh_fail(np->namid,e_subscript,ERROR);
if(!nam_istype(np,N_ARRAY))
array_dotset(np,dot);
}
cp++;
#ifdef MULTIDIM
array_ptr(np)->cur[index] = dot;
}
#else
array_ptr(np)->cur[0] = dot;
#endif /* MULIDIM */
if(*cp == '[')
sh_fail(np->namid,e_subscript,ERROR);
return(cp);
}
/*
* skip to a matching ']' and return pointer to matched character
* routine assumes that you are sitting on the '['
*/
static char *array_end(string)
register char *string;
{
register int count = 1;
register int c;
while(count>0 && (c= *++string))
{
if(c=='[')
count++;
else if(c==']')
count--;
}
return(string);
}
void array_dotset(np, n)
register struct namnod *np;
{
register struct Namaray *ap;
register struct Nodval *vp;
if(!nam_istype(np,N_ARRAY))
{
ap = array_grow((struct Namaray *)NULL,n);
if(np->value.namval.cp)
{
vp = new_of(struct Nodval,0);
*vp = np->value;
ap->nelem = 1;
ap->val[0] = vp;
}
np->value.namval.aray = ap;
nam_ontype(np,N_ARRAY);
}
else
ap = array_ptr(np);
#ifdef MULTIDIM
{
register int i = NDIM;
while(--i >= 0)
ap->cur[i] = n;
}
#else
ap->cur[0] = n;
#endif /*MULTIDIM */
}