386BSD 0.1 development
[unix-history] / usr / src / usr.bin / awk / zmalloc.c
CommitLineData
a7e60862
WJ
1
2/********************************************
3zmalloc.c
4copyright 1991, Michael D. Brennan
5
6This is a source file for mawk, an implementation of
7the AWK programming language.
8
9Mawk is distributed without warranty under the terms of
10the GNU General Public License, version 2, 1991.
11********************************************/
12
13/*$Log: zmalloc.c,v $
14 * Revision 5.1 91/12/05 07:56:35 brennan
15 * 1.1 pre-release
16 *
17*/
18
19/* zmalloc.c */
20#include "mawk.h"
21#include "zmalloc.h"
22
23void PROTO( mawk_exit, (int) ) ;
24
25extern struct yacc_mem *yacc_memp ;
26
27/*
28 zmalloc() gets mem from malloc() in CHUNKS of 2048 bytes
29 and cuts these blocks into smaller pieces that are multiples
30 of eight bytes. When a piece is returned via zfree(), it goes
31 on a linked linear list indexed by its size. The lists are
32 an array, pool[].
33
34 E.g., if you ask for 22 bytes with p = zmalloc(22), you actually get
35 a piece of size 24. When you free it with zfree(p,22) , it is added
36 to the list at pool[2].
37*/
38
39#define POOLSZ 16
40
41#define CHUNK 256
42 /* number of blocks to get from malloc */
43
44static PTR PROTO( emalloc, (unsigned) ) ;
45void PROTO( errmsg, (int , char *, ...) ) ;
46
47static PTR emalloc(size)
48 unsigned size ;
49{ PTR p ;
50 static char out[] = "out of memory" ;
51
52 if( !(p = (PTR) malloc(SIZE_T(size))) )
53 if ( mawk_state == EXECUTION ) rt_error(out) ;
54 else /* I don't think this will ever happen */
55 { compile_error(out) ; mawk_exit(1) ; }
56 return p ;
57}
58
59
60typedef union zblock {
61char dummy[ZBLOCKSZ] ;
62union zblock *link ;
63} ZBLOCK ;
64
65/* ZBLOCKS of sizes 1, 2, ... 16
66 which is bytes of sizes 8, 16, ... , 128
67 are stored on the linked linear lists in
68 pool[0], pool[1], ... , pool[15]
69*/
70
71static ZBLOCK *pool[POOLSZ] ;
72
73PTR bmalloc( blocks )
74 register unsigned blocks ;
75{
76 register ZBLOCK *p ;
77 static unsigned amt_avail ;
78 static ZBLOCK *avail ;
79
80 if ( blocks > POOLSZ ) return emalloc(blocks<<ZSHIFT) ;
81
82 if ( p = pool[blocks-1] )
83 { pool[blocks-1] = p->link ; return (PTR) p ; }
84
85 if ( blocks > amt_avail )
86 { if ( amt_avail ) /* free avail */
87 { avail->link = pool[--amt_avail] ; pool[amt_avail] = avail ; }
88
89 /* use parser tables first */
90 if ( yacc_memp->zblocks >= blocks )
91 { avail = (ZBLOCK *) yacc_memp->mem ;
92 amt_avail = yacc_memp++ -> zblocks ;
93 /* make sure its -- aligned */
94 if ( (int) avail & 7 )
95 { avail = (ZBLOCK*)((char *)avail + 8 - ((int)avail&7)) ;
96 amt_avail-- ;
97 }
98 }
99 else
100 if ( !(avail = (ZBLOCK *) malloc(SIZE_T(CHUNK*ZBLOCKSZ))) )
101 { /* if we get here, almost out of memory */
102 amt_avail = 0 ;
103 return emalloc(blocks << ZSHIFT) ;
104 }
105 else amt_avail = CHUNK ;
106 }
107
108 /* get p from the avail pile */
109 p = avail ; avail += blocks ; amt_avail -= blocks ;
110 return (PTR) p ;
111}
112
113void bfree( p, blocks)
114 register PTR p ;
115 register unsigned blocks ;
116{
117
118 if ( blocks > POOLSZ ) free(p) ;
119 else
120 {
121 ((ZBLOCK *)p)->link = pool[--blocks] ;
122 pool[blocks] = (ZBLOCK *) p ;
123 }
124}
125
126PTR zrealloc( p, old_size, new_size )
127 register PTR p ;
128 unsigned old_size, new_size ;
129{ register PTR q ;
130
131 (void) memcpy(q = zmalloc(new_size), p,
132 SIZE_T(old_size < new_size ? old_size : new_size)) ;
133
134 zfree(p, old_size) ;
135 return q ;
136}
137
138