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: