-
Notifications
You must be signed in to change notification settings - Fork 7
/
ph.c
346 lines (292 loc) · 6.81 KB
/
ph.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#include <stdio.h>
#include <time.h>
#include <string.h>
#include <stdlib.h>
#if __DMC__
#include <new.h>
#else
#include <new>
#endif
#include "cc.h"
#include "global.h"
static char __file__[] = __FILE__; /* for tassert.h */
#include "tassert.h"
/**********************************************
* Do our own storage allocator, a replacement
* for malloc/free.
*/
struct Heap
{
Heap *prev; // previous heap
unsigned char *buf; // buffer
unsigned char *p; // high water mark
unsigned nleft; // number of bytes left
};
Heap *heap=NULL;
void ph_init()
{
if (!heap) {
heap = (Heap *)calloc(1,sizeof(Heap));
}
assert(heap);
}
void ph_term()
{
//printf("ph_term()\n");
#if _WINDLL || DEBUG
Heap *h;
Heap *hprev;
for (h = heap; h; h = hprev)
{
hprev = h->prev;
free(h->buf);
free(h);
}
#endif
}
void ph_newheap(size_t nbytes)
{ unsigned newsize;
Heap *h;
h = (Heap *) malloc(sizeof(Heap));
if (!h)
err_nomem();
newsize = (nbytes > 0xFF00) ? nbytes : 0xFF00;
h->buf = (unsigned char *) malloc(newsize);
if (!h->buf)
{
free(h);
err_nomem();
}
h->nleft = newsize;
h->p = h->buf;
h->prev = heap;
heap = h;
}
void *ph_malloc(size_t nbytes)
{ unsigned char *p;
#ifdef DEBUG
util_progress();
#endif
nbytes += sizeof(unsigned) * 2;
nbytes &= ~(sizeof(unsigned) - 1);
if (nbytes >= heap->nleft)
ph_newheap(nbytes);
p = heap->p;
heap->p += nbytes;
heap->nleft -= nbytes;
*(unsigned *)p = nbytes - sizeof(unsigned);
p += sizeof(unsigned);
return p;
}
#if ASM86
__declspec(naked) void *ph_calloc(size_t nbytes)
{
_asm
{
push dword ptr 4[ESP]
call ph_malloc
test EAX,EAX
je L25
push dword ptr 4[ESP]
push 0
push EAX
call memset
add ESP,0Ch
L25: ret 4
}
}
#else
void *ph_calloc(size_t nbytes)
{ void *p;
p = ph_malloc(nbytes);
return p ? memset(p,0,nbytes) : p;
}
#endif
void ph_free(void *p)
{
}
void *ph_realloc(void *p,size_t nbytes)
{
//dbg_printf("ph_realloc(%p,%d)\n",p,nbytes);
if (!p)
return ph_malloc(nbytes);
if (!nbytes)
{ ph_free(p);
return NULL;
}
void *newp = ph_malloc(nbytes);
if (newp)
{ unsigned oldsize = ((unsigned *)p)[-1];
memcpy(newp,p,oldsize);
ph_free(p);
}
return newp;
}
void err_nomem()
{
printf("Error: out of memory\n");
err_exit();
}
#if !MEM_DEBUG
/***********************
* Replacement for the standard C++ library operator delete().
*/
#if 0
#undef delete
void __cdecl operator delete(void *p)
{
}
#endif
#if 0
/*****************************************
* Using this for array allocations gives
* us an easy way to get at the array dimension.
* Overloading operator new[]() doesn't work because that
* gives us the array allocated size, but we need the dimension.
*/
#ifdef DEBUG
#define ARRAY_PROLOG 'prol'
#define ARRAY_EPILOG 'epil'
#define ARRAY_FILL 'f'
static int array_max_dim;
/*********************************
* Run "reasonableness" checks on array.
*/
void array_debug(void *a)
{ size_t *p = (size_t *)a;
assert(p);
assert(p[-2] == ARRAY_PROLOG);
int length = p[-1];
assert(length >= 0 && length <= array_max_dim);
assert(p[length] == ARRAY_EPILOG);
// Since array contents are aligned pointers or NULL...
for (int i = 0; i < length; i++)
assert((p[i] & 3) == 0);
}
#endif
#undef array_new
void *array_new(int sizelem, int dim)
{ size_t *p;
size_t sz;
#ifdef DEBUG
assert(sizelem == sizeof(void *)); // must be array of pointers
if (!(dim >= 0 && dim < 10000))
printf("dim = %d\n",dim);
assert(dim >= 0 && dim < 10000);
if (dim > array_max_dim)
array_max_dim = dim;
sz = sizeof(size_t) * (3 + dim);
p = ph_calloc(sz);
if (p)
{ p[0] = ARRAY_PROLOG; // leading sentinel
p[1] = dim;
p[2 + dim] = ARRAY_EPILOG; // trailing sentinel
p += 2;
array_debug(p);
}
#else
sz = sizeof(size_t) * (1 + dim);
p = ph_calloc(sz);
if (p)
*p++ = dim;
#endif
return (void *)p;
}
#undef array_delete
void array_delete(void *a, int sizelem)
{
size_t *p = (size_t *)a;
#ifdef DEBUG
array_debug(p);
assert(sizelem == sizeof(size_t));
memset(p - 2,ARRAY_FILL,sizeof(size_t *) * (3 + p[-1]));
ph_free(p - 2);
#else
((size_t *)p)--;
ph_free(p);
#endif
}
size_t array_length(void *p)
{
array_debug(p);
return ((size_t *)p)[-1];
}
/********************************
* Same as System.arraycopy()
*/
void array_copy(void *f,int fi,void *t,int ti,int length)
{
#ifdef DEBUG
assert(length >= 0 && length <= array_max_dim);
int f_length = array_length(f);
int t_length = array_length(t);
assert(fi >= 0 && fi + length <= f_length);
assert(ti >= 0 && ti + length <= t_length);
#endif
memcpy(&((void **)t)[ti],&((void **)f)[fi],length * sizeof(void *));
}
/************************************
* Reallocate.
*/
#undef array_renew
void **array_renew(void *a,int newlength)
{ int sz = sizeof(void *);
int hsz = sizeof(void *);
if (!a)
a = array_new(sz,newlength);
else
{
int oldlength = array_length(a);
#ifdef DEBUG
void *b = array_new(sizeof(void *),newlength);
int len = (oldlength < newlength) ? oldlength : newlength;
array_copy(a,0,b,0,len);
array_delete(a,sizeof(void *));
a = b;
#else
if (oldlength < newlength)
{
(char *)a -= hsz;
a = ph_realloc(a,hsz + newlength * sz);
if (!a)
goto Lret;
(char *)a += hsz;
memset(&((void **)a)[oldlength],0,(newlength - oldlength) * sz);
}
else if (oldlength > newlength)
{
;
}
((size_t *)a)[-1] = newlength;
#endif
}
Lret:
return a;
}
/******************************************
* Sort an array.
*/
#if MACINTOSH
extern "C" int acompare(const void *e1,const void *e2)
#else
int __cdecl acompare(const void *e1,const void *e2)
#endif
{
Object *o1 = *(Object **)e1;
Object *o2 = *(Object **)e2;
return o1->compare(o2);
}
void array_sort(void *a)
{
qsort(a,array_length(a),sizeof(void *),acompare);
}
#endif
#endif