ff163999dbfa757ecdbf0449ec20c14fd357f032
[fw/sdcc] / support / Util / NewAlloc.c
1 /*
2 ===============================================================================
3 NEWALLOC - SDCC Memory allocation functions
4
5 These functions are wrappers for the standard malloc, realloc and free
6 functions.
7
8
9      This program is free software; you can redistribute it and/or modify it
10    under the terms of the GNU General Public License as published by the
11    Free Software Foundation; either version 2, or (at your option) any
12    later version.
13
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22
23    In other words, you are welcome to use, share and improve this program.
24    You are forbidden to forbid anyone else to use, share and improve
25    what you give them.   Help stamp out software-hoarding!
26
27 ===============================================================================
28 */
29
30 #include <stdio.h>
31 #if defined(__APPLE__) && defined(__MACH__)
32 #include <sys/malloc.h>
33 #else
34 #include <malloc.h>
35 #endif
36 #include <stdlib.h>
37 #include <string.h>
38 #include <memory.h>
39 #include <assert.h>
40 #include "newalloc.h"
41
42 #if OPT_ENABLE_LIBGC
43 #include <gc/gc.h>
44
45 #define MALLOC  GC_malloc
46 #define REALLOC GC_realloc
47 /* PENDING: This is a mild hack.  If we try to GC_free something
48    allocated with malloc() then the program will segfault.  Might as
49    well drop it and let the garbase collector take care of things.
50 */
51 #define FREE(_a)        
52
53 #else
54
55 #define MALLOC  malloc
56 #define REALLOC realloc
57 #define FREE    free
58
59 #endif
60
61 #define TRACEMALLOC     0
62
63 #if TRACEMALLOC
64 enum 
65   {
66     TRACESIZE = 4096
67   };
68
69 static int _allocs[TRACESIZE];
70 static int _above;
71
72 static void
73 _dumpTrace(int code, void *parg)
74 {
75   int i;
76   for (i = 0; i < TRACESIZE; i++)
77     {
78       if (_allocs[i])
79         {
80           printf("%u %u\n", _allocs[i], i);
81         }
82     }
83   printf("%u above\n", _above);
84 }
85
86 static void
87 _log(int size)
88 {
89   static int registered;
90
91   if (registered == 0)
92     {
93       on_exit(_dumpTrace, NULL);
94       registered = 1;
95     }
96   if (size == 12)
97     {
98       _above++;
99     }
100
101   if (size >= TRACESIZE)
102     {
103       _above++;
104     }
105   else
106     {
107       _allocs[size]++;
108     }
109 }
110 #endif
111
112 /*
113 -------------------------------------------------------------------------------
114 Clear_realloc - Reallocate a memory block and clear any memory added with
115 out of memory error detection
116
117 -------------------------------------------------------------------------------
118 */
119
120 void *Clear_realloc(void *OldPtr,size_t OldSize,size_t NewSize)
121
122 {
123 void *NewPtr ;
124
125 NewPtr = REALLOC(OldPtr,NewSize) ;
126
127 if (!NewPtr)
128   {
129   printf("ERROR - No more memory\n") ;
130 /*  werror(E_OUT_OF_MEM,__FILE__,NewSize);*/
131   exit (1);
132   }
133
134 if (NewPtr)
135   if (NewSize > OldSize)
136     memset((char *) NewPtr + OldSize,0x00,NewSize - OldSize) ;
137
138 return NewPtr ;
139 }
140 /*
141 -------------------------------------------------------------------------------
142 Safe_realloc - Reallocate a memory block with out of memory error detection
143
144 -------------------------------------------------------------------------------
145 */
146
147 void *Safe_realloc(void *OldPtr,size_t NewSize)
148
149 {
150 void *NewPtr ;
151
152 NewPtr = REALLOC(OldPtr,NewSize) ;
153
154 if (!NewPtr)
155   {
156   printf("ERROR - No more memory\n") ;
157 /*  werror(E_OUT_OF_MEM,__FILE__,NewSize);*/
158   exit (1);
159   }
160
161 return NewPtr ;
162 }
163 /*
164 -------------------------------------------------------------------------------
165 Safe_calloc - Allocate a block of memory from the application heap, clearing
166 all data to zero and checking for out of memory errors.
167
168 -------------------------------------------------------------------------------
169 */
170
171 void *Safe_calloc(size_t Elements,size_t Size)
172
173 {
174 void *NewPtr ;
175
176 NewPtr = MALLOC(Elements*Size) ;
177 #if TRACEMALLOC
178  _log(Elements*Size);
179 #endif
180  
181 if (!NewPtr)
182   {
183   printf("ERROR - No more memory\n") ;
184 /*  werror(E_OUT_OF_MEM,__FILE__,Size);*/
185   exit (1);
186   }
187
188  memset(NewPtr, 0, Elements*Size);
189
190 return NewPtr ;
191 }
192 /*
193 -------------------------------------------------------------------------------
194 Safe_malloc - Allocate a block of memory from the application heap
195 and checking for out of memory errors.
196
197 -------------------------------------------------------------------------------
198 */
199
200 void *Safe_malloc(size_t Size)
201
202 {
203 void *NewPtr ;
204
205 NewPtr = MALLOC(Size) ;
206
207 #if TRACEMALLOC
208  _log(Size);
209 #endif
210
211 if (!NewPtr)
212   {
213   printf("ERROR - No more memory\n") ;
214 /*  werror(E_OUT_OF_MEM,__FILE__,Size);*/
215   exit (1);
216   }
217
218 return NewPtr ;
219 }
220
221 void *Safe_alloc(size_t Size)
222 {
223   return Safe_calloc(1, Size);
224 }
225
226 void Safe_free(void *p)
227 {
228   FREE(p);
229 }
230
231 char *Safe_strdup(const char *sz)
232 {
233   char *pret;
234   assert(sz);
235
236   pret = Safe_alloc(strlen(sz) +1);
237   strcpy(pret, sz);
238
239   return pret;
240 }
241
242 void *traceAlloc(allocTrace *ptrace, void *p)
243 {
244   assert(ptrace);
245   assert(p);
246
247   /* Also handles where max == 0 */
248   if (ptrace->num == ptrace->max)
249     {
250       /* Add an offset to handle max == 0 */
251       ptrace->max = (ptrace->max+2)*2;
252       ptrace->palloced = Safe_realloc(ptrace->palloced, ptrace->max * sizeof(*ptrace->palloced));
253     }
254   ptrace->palloced[ptrace->num++] = p;
255
256   return p;
257 }
258
259 void freeTrace(allocTrace *ptrace)
260 {
261   int i;
262   assert(ptrace);
263
264   for (i = 0; i < ptrace->num; i++)
265     {
266       Safe_free(ptrace->palloced[i]);
267     }
268   ptrace->num = 0;
269
270   Safe_free(ptrace->palloced);
271   ptrace->palloced = NULL;
272   ptrace->max = 0;
273 }