/* $Header$
 *
 *    Copyright (c) 1989, Larry Wall
 *
 *    You may distribute under the terms of the GNU General Public License
 *    as specified in the README file that comes with the perl 3.0 kit.
 *
 * $Log$
 * Revision 1.2  2004/09/01 14:33:24  criswell
 * Migrating test suite out of the source tree.
 *
 * Revision 1.1  2004/02/17 22:21:15  criswell
 * Initial commit of the perl Malloc Benchmark.  I've cheated a little by
 * generating the yacc output files and committing them directly, but it was
 * easier than disabling the Bison Voodoo that gets executed by default.
 *
 * Revision 4.0  91/03/20  01:03:32  lwall
 * 4.0 baseline.
 * 
 */

#include "EXTERN.h"
#include "perl.h"

STR *
afetch(ar,key,lval)
register ARRAY *ar;
int key;
int lval;
{
    STR *str;

    if (key < 0 || key > ar->ary_fill) {
	if (lval && key >= 0) {
	    if (ar->ary_flags & ARF_REAL)
		str = Str_new(5,0);
	    else
		str = str_mortal(&str_undef);
	    (void)astore(ar,key,str);
	    return str;
	}
	else
	    return &str_undef;
    }
    if (!ar->ary_array[key]) {
	if (lval) {
	    str = Str_new(6,0);
	    (void)astore(ar,key,str);
	    return str;
	}
	return &str_undef;
    }
    return ar->ary_array[key];
}

bool
astore(ar,key,val)
register ARRAY *ar;
int key;
STR *val;
{
    int retval;

    if (key < 0)
	return FALSE;
    if (key > ar->ary_max) {
	int newmax;

	if (ar->ary_alloc != ar->ary_array) {
	    retval = ar->ary_array - ar->ary_alloc;
	    Copy(ar->ary_array, ar->ary_alloc, ar->ary_max+1, STR*);
	    Zero(ar->ary_alloc+ar->ary_max+1, retval, STR*);
	    ar->ary_max += retval;
	    ar->ary_array -= retval;
	    if (key > ar->ary_max - 10) {
		newmax = key + ar->ary_max;
		goto resize;
	    }
	}
	else {
	    if (ar->ary_alloc) {
		newmax = key + ar->ary_max / 5;
	      resize:
		Renew(ar->ary_alloc,newmax+1, STR*);
		Zero(&ar->ary_alloc[ar->ary_max+1], newmax - ar->ary_max, STR*);
	    }
	    else {
		newmax = key < 4 ? 4 : key;
		Newz(2,ar->ary_alloc, newmax+1, STR*);
	    }
	    ar->ary_array = ar->ary_alloc;
	    ar->ary_max = newmax;
	}
    }
    if ((ar->ary_flags & ARF_REAL) && ar->ary_fill < key) {
	while (++ar->ary_fill < key) {
	    if (ar->ary_array[ar->ary_fill] != Nullstr) {
		str_free(ar->ary_array[ar->ary_fill]);
		ar->ary_array[ar->ary_fill] = Nullstr;
	    }
	}
    }
    retval = (ar->ary_array[key] != Nullstr);
    if (retval && (ar->ary_flags & ARF_REAL))
	str_free(ar->ary_array[key]);
    ar->ary_array[key] = val;
    return retval;
}

ARRAY *
anew(stab)
STAB *stab;
{
    register ARRAY *ar;

    New(1,ar,1,ARRAY);
    ar->ary_magic = Str_new(7,0);
    ar->ary_alloc = ar->ary_array = 0;
    str_magic(ar->ary_magic, stab, '#', Nullch, 0);
    ar->ary_max = ar->ary_fill = -1;
    ar->ary_flags = ARF_REAL;
    return ar;
}

ARRAY *
afake(stab,size,strp)
STAB *stab;
register int size;
register STR **strp;
{
    register ARRAY *ar;

    New(3,ar,1,ARRAY);
    New(4,ar->ary_alloc,size+1,STR*);
    Copy(strp,ar->ary_alloc,size,STR*);
    ar->ary_array = ar->ary_alloc;
    ar->ary_magic = Str_new(8,0);
    str_magic(ar->ary_magic, stab, '#', Nullch, 0);
    ar->ary_fill = size - 1;
    ar->ary_max = size - 1;
    ar->ary_flags = 0;
    while (size--) {
	(*strp++)->str_pok &= ~SP_TEMP;
    }
    return ar;
}

void
aclear(ar)
register ARRAY *ar;
{
    register int key;

    if (!ar || !(ar->ary_flags & ARF_REAL) || ar->ary_max < 0)
	return;
    if (key = ar->ary_array - ar->ary_alloc) {
	ar->ary_max += key;
	ar->ary_array -= key;
    }
    for (key = 0; key <= ar->ary_max; key++)
	str_free(ar->ary_array[key]);
    ar->ary_fill = -1;
    Zero(ar->ary_array, ar->ary_max+1, STR*);
}

void
afree(ar)
register ARRAY *ar;
{
    register int key;

    if (!ar)
	return;
    if (key = ar->ary_array - ar->ary_alloc) {
	ar->ary_max += key;
	ar->ary_array -= key;
    }
    if (ar->ary_flags & ARF_REAL) {
	for (key = 0; key <= ar->ary_max; key++)
	    str_free(ar->ary_array[key]);
    }
    str_free(ar->ary_magic);
    Safefree(ar->ary_alloc);
    Safefree(ar);
}

bool
apush(ar,val)
register ARRAY *ar;
STR *val;
{
    return astore(ar,++(ar->ary_fill),val);
}

STR *
apop(ar)
register ARRAY *ar;
{
    STR *retval;

    if (ar->ary_fill < 0)
	return Nullstr;
    retval = ar->ary_array[ar->ary_fill];
    ar->ary_array[ar->ary_fill--] = Nullstr;
    return retval;
}

aunshift(ar,num)
register ARRAY *ar;
register int num;
{
    register int i;
    register STR **sstr,**dstr;

    if (num <= 0)
	return;
    if (ar->ary_array - ar->ary_alloc >= num) {
	ar->ary_max += num;
	ar->ary_fill += num;
	while (num--)
	    *--ar->ary_array = Nullstr;
    }
    else {
	(void)astore(ar,ar->ary_fill+num,(STR*)0);	/* maybe extend array */
	dstr = ar->ary_array + ar->ary_fill;
	sstr = dstr - num;
#ifdef BUGGY_MSC5
 # pragma loop_opt(off)	/* don't loop-optimize the following code */
#endif /* BUGGY_MSC5 */
	for (i = ar->ary_fill; i >= 0; i--) {
	    *dstr-- = *sstr--;
#ifdef BUGGY_MSC5
 # pragma loop_opt()	/* loop-optimization back to command-line setting */
#endif /* BUGGY_MSC5 */
	}
	Zero(ar->ary_array, num, STR*);
    }
}

STR *
ashift(ar)
register ARRAY *ar;
{
    STR *retval;

    if (ar->ary_fill < 0)
	return Nullstr;
    retval = *ar->ary_array;
    *(ar->ary_array++) = Nullstr;
    ar->ary_max--;
    ar->ary_fill--;
    return retval;
}

int
alen(ar)
register ARRAY *ar;
{
    return ar->ary_fill;
}

afill(ar, fill)
register ARRAY *ar;
int fill;
{
    if (fill < 0)
	fill = -1;
    if (fill <= ar->ary_max)
	ar->ary_fill = fill;
    else
	(void)astore(ar,fill,Nullstr);
}
