Git init
[external/mawk.git] / zmalloc.c
1
2 /********************************************
3 zmalloc.c
4 copyright 1991, Michael D. Brennan
5
6 This is a source file for mawk, an implementation of
7 the AWK programming language.
8
9 Mawk is distributed without warranty under the terms of
10 the GNU General Public License, version 2, 1991.
11 ********************************************/
12
13 /*$Log: zmalloc.c,v $
14  * Revision 1.6  1995/06/06  00:18:35  mike
15  * change mawk_exit(1) to mawk_exit(2)
16  *
17  * Revision 1.5  1995/03/08  00:06:26  mike
18  * add a pointer cast
19  *
20  * Revision 1.4  1993/07/14  12:45:15  mike
21  * run thru indent
22  *
23  * Revision 1.3  1993/07/07  00:07:54  mike
24  * more work on 1.2
25  *
26  * Revision 1.2  1993/07/03  21:15:35  mike
27  * bye bye yacc_mem
28  *
29  * Revision 1.1.1.1  1993/07/03  18:58:23  mike
30  * move source to cvs
31  *
32  * Revision 5.4  1993/02/13  21:57:38  mike
33  * merge patch3
34  *
35  * Revision 5.3  1993/01/14  13:12:33  mike
36  * casts in front of malloc
37  *
38  * Revision 5.1.1.1  1993/02/06  11:12:19  mike
39  * fix bug in reuse of parser table memory
40  * for most users ifdef the mess out
41  *
42  * Revision 5.1  1991/12/05  07:56:35  brennan
43  * 1.1 pre-release
44  *
45 */
46
47 /*  zmalloc.c  */
48 #include  "mawk.h"
49 #include  "zmalloc.h"
50
51
52
53 /*
54   zmalloc() gets mem from malloc() in CHUNKS of 2048 bytes
55   and cuts these blocks into smaller pieces that are multiples
56   of eight bytes.  When a piece is returned via zfree(), it goes
57   on a linked linear list indexed by its size.  The lists are
58   an array, pool[].
59
60   E.g., if you ask for 22 bytes with p = zmalloc(22), you actually get
61   a piece of size 24.  When you free it with zfree(p,22) , it is added
62   to the list at pool[2].
63 */
64
65 #define POOLSZ      16
66
67 #define  CHUNK          256
68  /* number of blocks to get from malloc */
69
70 static void PROTO(out_of_mem, (void)) ;
71
72
73 static void
74 out_of_mem()
75 {
76    static char out[] = "out of memory" ;
77
78    if (mawk_state == EXECUTION)  rt_error(out) ;
79    else
80    {
81       /* I don't think this will ever happen */
82       compile_error(out) ; mawk_exit(2) ; 
83    }
84 }
85
86
87 typedef union zblock
88 {
89    char dummy[ZBLOCKSZ] ;
90    union zblock *link ;
91 } ZBLOCK ;
92
93 /* ZBLOCKS of sizes 1, 2, ... 16
94    which is bytes of sizes 8, 16, ... , 128
95    are stored on the linked linear lists in
96    pool[0], pool[1], ... , pool[15]
97 */
98
99 static ZBLOCK *pool[POOLSZ] ;
100
101 /* zmalloc() is a macro in front of bmalloc "BLOCK malloc" */
102
103 PTR
104 bmalloc(blocks)
105    register unsigned blocks ;
106 {
107    register ZBLOCK *p ;
108    static unsigned amt_avail ;
109    static ZBLOCK *avail ;
110
111    if (blocks > POOLSZ)
112    {
113       p = (ZBLOCK *) malloc(blocks << ZSHIFT) ;
114       if (!p)  out_of_mem() ;
115       return (PTR) p ;
116    }
117
118    if ((p = pool[blocks - 1]))
119    {
120       pool[blocks - 1] = p->link ;
121       return (PTR) p ;
122    }
123
124    if (blocks > amt_avail)
125    {
126       if (amt_avail != 0)       /* free avail */
127       {
128          avail->link = pool[--amt_avail] ;
129          pool[amt_avail] = avail ;
130       }
131
132       if (!(avail = (ZBLOCK *) malloc(CHUNK * ZBLOCKSZ)))
133       {
134          /* if we get here, almost out of memory */
135          amt_avail = 0 ;
136          p = (ZBLOCK *) malloc(blocks << ZSHIFT) ;
137          if (!p)  out_of_mem() ;
138          return (PTR) p ;
139       }
140       else  amt_avail = CHUNK ;
141    }
142
143    /* get p from the avail pile */
144    p = avail ; avail += blocks ; amt_avail -= blocks ; 
145    return (PTR) p ;
146 }
147
148 void
149 bfree(p, blocks)
150    register PTR p ;
151    register unsigned blocks ;
152 {
153
154    if (blocks > POOLSZ)  free(p) ;
155    else
156    {
157       ((ZBLOCK *) p)->link = pool[--blocks] ;
158       pool[blocks] = (ZBLOCK *) p ;
159    }
160 }
161
162 PTR
163 zrealloc(p, old_size, new_size)
164    register PTR p ;
165    unsigned old_size, new_size ;
166 {
167    register PTR q ;
168
169    if (new_size > (POOLSZ << ZSHIFT) &&
170        old_size > (POOLSZ << ZSHIFT))
171    {
172       if (!(q = realloc(p, new_size)))  out_of_mem() ;
173    }
174    else
175    {
176       q = zmalloc(new_size) ;
177       memcpy(q, p, old_size < new_size ? old_size : new_size) ;
178       zfree(p, old_size) ;
179    }
180    return q ;
181 }
182
183
184
185 #ifndef  __GNUC__
186 /* pacifier for Bison , this is really dead code */
187 PTR
188 alloca(sz)
189    unsigned sz ;
190 {
191    /* hell just froze over */
192    exit(100) ;
193    return (PTR) 0 ;
194 }
195 #endif