/******************************************** 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 $ * Revision 1.6 1995/06/06 00:18:35 mike * change mawk_exit(1) to mawk_exit(2) * * Revision 1.5 1995/03/08 00:06:26 mike * add a pointer cast * * Revision 1.4 1993/07/14 12:45:15 mike * run thru indent * * Revision 1.3 1993/07/07 00:07:54 mike * more work on 1.2 * * Revision 1.2 1993/07/03 21:15:35 mike * bye bye yacc_mem * * Revision 1.1.1.1 1993/07/03 18:58:23 mike * move source to cvs * * Revision 5.4 1993/02/13 21:57:38 mike * merge patch3 * * Revision 5.3 1993/01/14 13:12:33 mike * casts in front of malloc * * 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 * 1.1 pre-release * */ /* zmalloc.c */ #include "mawk.h" #include "zmalloc.h" /* 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 void PROTO(out_of_mem, (void)) ; static void out_of_mem() { static char out[] = "out of memory" ; if (mawk_state == EXECUTION) rt_error(out) ; else { /* I don't think this will ever happen */ compile_error(out) ; mawk_exit(2) ; } } 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] ; /* zmalloc() is a macro in front of bmalloc "BLOCK malloc" */ PTR bmalloc(blocks) register unsigned blocks ; { register ZBLOCK *p ; static unsigned amt_avail ; static ZBLOCK *avail ; if (blocks > POOLSZ) { p = (ZBLOCK *) malloc(blocks << ZSHIFT) ; if (!p) out_of_mem() ; return (PTR) p ; } if ((p = pool[blocks - 1])) { pool[blocks - 1] = p->link ; return (PTR) p ; } if (blocks > amt_avail) { if (amt_avail != 0) /* free avail */ { avail->link = pool[--amt_avail] ; pool[amt_avail] = avail ; } if (!(avail = (ZBLOCK *) malloc(CHUNK * ZBLOCKSZ))) { /* if we get here, almost out of memory */ amt_avail = 0 ; p = (ZBLOCK *) malloc(blocks << ZSHIFT) ; if (!p) out_of_mem() ; return (PTR) p ; } 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 ; if (new_size > (POOLSZ << ZSHIFT) && old_size > (POOLSZ << ZSHIFT)) { if (!(q = realloc(p, new_size))) out_of_mem() ; } else { q = zmalloc(new_size) ; memcpy(q, p, old_size < new_size ? old_size : new_size) ; zfree(p, old_size) ; } return q ; } #ifndef __GNUC__ /* pacifier for Bison , this is really dead code */ PTR alloca(sz) unsigned sz ; { /* hell just froze over */ exit(100) ; return (PTR) 0 ; } #endif