1993-03-21 12:45:37 +03:00
|
|
|
|
|
|
|
/********************************************
|
|
|
|
zmalloc.c
|
|
|
|
copyright 1991, Michael D. Brennan
|
|
|
|
|
|
|
|
This is a source file for mawk, an implementation of
|
|
|
|
the AWK programming language.
|
|
|
|
|
|
|
|
Mawk is distributed without warranty under the terms of
|
|
|
|
the GNU General Public License, version 2, 1991.
|
|
|
|
********************************************/
|
|
|
|
|
|
|
|
/*$Log: zmalloc.c,v $
|
1993-07-03 03:56:52 +04:00
|
|
|
/*Revision 1.2 1993/07/02 23:58:03 jtc
|
|
|
|
/*Updated to mawk 1.1.4
|
1993-03-21 12:45:37 +03:00
|
|
|
/*
|
1993-07-03 03:56:52 +04:00
|
|
|
* Revision 5.1.1.1 1993/02/06 11:12:19 mike
|
|
|
|
* fix bug in reuse of parser table memory
|
|
|
|
* for most users ifdef the mess out
|
|
|
|
*
|
|
|
|
* Revision 5.1 1991/12/05 07:56:35 brennan
|
1993-03-21 12:45:37 +03:00
|
|
|
* 1.1 pre-release
|
1993-07-03 03:56:52 +04:00
|
|
|
*
|
1993-03-21 12:45:37 +03:00
|
|
|
*/
|
|
|
|
|
|
|
|
/* zmalloc.c */
|
|
|
|
#include "mawk.h"
|
|
|
|
#include "zmalloc.h"
|
|
|
|
|
|
|
|
void PROTO( mawk_exit, (int) ) ;
|
|
|
|
|
|
|
|
extern struct yacc_mem *yacc_memp ;
|
|
|
|
|
|
|
|
/*
|
|
|
|
zmalloc() gets mem from malloc() in CHUNKS of 2048 bytes
|
|
|
|
and cuts these blocks into smaller pieces that are multiples
|
|
|
|
of eight bytes. When a piece is returned via zfree(), it goes
|
|
|
|
on a linked linear list indexed by its size. The lists are
|
|
|
|
an array, pool[].
|
|
|
|
|
|
|
|
E.g., if you ask for 22 bytes with p = zmalloc(22), you actually get
|
|
|
|
a piece of size 24. When you free it with zfree(p,22) , it is added
|
|
|
|
to the list at pool[2].
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define POOLSZ 16
|
|
|
|
|
|
|
|
#define CHUNK 256
|
|
|
|
/* number of blocks to get from malloc */
|
|
|
|
|
|
|
|
static PTR PROTO( emalloc, (unsigned) ) ;
|
|
|
|
void PROTO( errmsg, (int , char *, ...) ) ;
|
|
|
|
|
|
|
|
static PTR emalloc(size)
|
|
|
|
unsigned size ;
|
|
|
|
{ PTR p ;
|
|
|
|
static char out[] = "out of memory" ;
|
|
|
|
|
|
|
|
if( !(p = (PTR) malloc(SIZE_T(size))) )
|
|
|
|
if ( mawk_state == EXECUTION ) rt_error(out) ;
|
|
|
|
else /* I don't think this will ever happen */
|
|
|
|
{ compile_error(out) ; mawk_exit(1) ; }
|
|
|
|
return p ;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
typedef union zblock {
|
|
|
|
char dummy[ZBLOCKSZ] ;
|
|
|
|
union zblock *link ;
|
|
|
|
} ZBLOCK ;
|
|
|
|
|
|
|
|
/* ZBLOCKS of sizes 1, 2, ... 16
|
|
|
|
which is bytes of sizes 8, 16, ... , 128
|
|
|
|
are stored on the linked linear lists in
|
|
|
|
pool[0], pool[1], ... , pool[15]
|
|
|
|
*/
|
|
|
|
|
|
|
|
static ZBLOCK *pool[POOLSZ] ;
|
|
|
|
|
|
|
|
PTR bmalloc( blocks )
|
|
|
|
register unsigned blocks ;
|
|
|
|
{
|
|
|
|
register ZBLOCK *p ;
|
|
|
|
static unsigned amt_avail ;
|
|
|
|
static ZBLOCK *avail ;
|
|
|
|
|
|
|
|
if ( blocks > POOLSZ ) return emalloc(blocks<<ZSHIFT) ;
|
|
|
|
|
|
|
|
if ( p = pool[blocks-1] )
|
|
|
|
{ pool[blocks-1] = p->link ; return (PTR) p ; }
|
|
|
|
|
|
|
|
if ( blocks > amt_avail )
|
1993-07-03 03:56:52 +04:00
|
|
|
{
|
|
|
|
if ( amt_avail != 0 ) /* free avail */
|
|
|
|
{
|
|
|
|
avail->link = pool[--amt_avail] ;
|
|
|
|
pool[amt_avail] = avail ;
|
|
|
|
}
|
1993-03-21 12:45:37 +03:00
|
|
|
|
1993-07-03 03:56:52 +04:00
|
|
|
#if MSDOS || HAVE_SMALL_MEMORY
|
|
|
|
/* this hack is dangerous (I've blown it twice), not portable,
|
|
|
|
and counts on byacc not changing, but it is a big win on
|
|
|
|
DOS. On paged vmem systems it is a nop so ifdef it out.
|
|
|
|
*/
|
1993-03-21 12:45:37 +03:00
|
|
|
/* use parser tables first */
|
1993-07-03 03:56:52 +04:00
|
|
|
if ( yacc_memp->zblocks > blocks )
|
|
|
|
{
|
|
|
|
avail = (ZBLOCK *) yacc_memp->mem ;
|
1993-03-21 12:45:37 +03:00
|
|
|
amt_avail = yacc_memp++ -> zblocks ;
|
|
|
|
/* make sure its -- aligned */
|
1993-07-03 03:56:52 +04:00
|
|
|
{
|
|
|
|
int k = (int) avail & 7 ;
|
|
|
|
if ( k )
|
|
|
|
{
|
|
|
|
avail = (ZBLOCK*)((char *)avail + (8-k)) ;
|
|
|
|
amt_avail-- ;
|
|
|
|
}
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
1993-07-03 03:56:52 +04:00
|
|
|
#endif
|
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
if ( !(avail = (ZBLOCK *) malloc(SIZE_T(CHUNK*ZBLOCKSZ))) )
|
|
|
|
{ /* if we get here, almost out of memory */
|
|
|
|
amt_avail = 0 ;
|
|
|
|
return emalloc(blocks << ZSHIFT) ;
|
|
|
|
}
|
|
|
|
else amt_avail = CHUNK ;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* get p from the avail pile */
|
|
|
|
p = avail ; avail += blocks ; amt_avail -= blocks ;
|
|
|
|
return (PTR) p ;
|
|
|
|
}
|
|
|
|
|
|
|
|
void bfree( p, blocks)
|
|
|
|
register PTR p ;
|
|
|
|
register unsigned blocks ;
|
|
|
|
{
|
|
|
|
|
|
|
|
if ( blocks > POOLSZ ) free(p) ;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
((ZBLOCK *)p)->link = pool[--blocks] ;
|
|
|
|
pool[blocks] = (ZBLOCK *) p ;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
PTR zrealloc( p, old_size, new_size )
|
|
|
|
register PTR p ;
|
|
|
|
unsigned old_size, new_size ;
|
|
|
|
{ register PTR q ;
|
|
|
|
|
|
|
|
(void) memcpy(q = zmalloc(new_size), p,
|
|
|
|
SIZE_T(old_size < new_size ? old_size : new_size)) ;
|
|
|
|
|
|
|
|
zfree(p, old_size) ;
|
|
|
|
return q ;
|
|
|
|
}
|
|
|
|
|
|
|
|
|