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