Imported Upstream version 2.9.0
[debian/cc1111] / 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 #include <stdlib.h>
32 #include <string.h>
33 #include <memory.h>
34 #include <assert.h>
35 #include "newalloc.h"
36
37 #if OPT_ENABLE_LIBGC
38 #include <gc/gc.h>
39
40 #define MALLOC  GC_malloc
41 #define REALLOC GC_realloc
42 /* PENDING: This is a mild hack.  If we try to GC_free something
43    allocated with malloc() then the program will segfault.  Might as
44    well drop it and let the garbase collector take care of things.
45 */
46 #define FREE(_a)
47
48 #else
49
50 #define MALLOC  malloc
51 #define REALLOC realloc
52 #define FREE    free
53
54 #endif
55
56 #define TRACEMALLOC     0
57
58 #if TRACEMALLOC
59 enum 
60   {
61     TRACESIZE = 4096
62   };
63
64 static int _allocs[TRACESIZE];
65 static int _above;
66
67 static void
68 _dumpTrace(int code, void *parg)
69 {
70   int i;
71   for (i = 0; i < TRACESIZE; i++)
72     {
73       if (_allocs[i])
74         {
75           printf("%u %u\n", _allocs[i], i);
76         }
77     }
78   printf("%u above\n", _above);
79 }
80
81 static void
82 _log(int size)
83 {
84   static int registered;
85
86   if (registered == 0)
87     {
88       on_exit(_dumpTrace, NULL);
89       registered = 1;
90     }
91   if (size == 12)
92     {
93       _above++;
94     }
95
96   if (size >= TRACESIZE)
97     {
98       _above++;
99     }
100   else
101     {
102       _allocs[size]++;
103     }
104 }
105 #endif
106
107 /*
108 -------------------------------------------------------------------------------
109 Clear_realloc - Reallocate a memory block and clear any memory added with
110 out of memory error detection
111
112 -------------------------------------------------------------------------------
113 */
114
115 void *Clear_realloc(void *OldPtr,size_t OldSize,size_t NewSize)
116
117 {
118 void *NewPtr ;
119
120 NewPtr = REALLOC(OldPtr,NewSize) ;
121
122 if (!NewPtr)
123   {
124   printf("ERROR - No more memory\n") ;
125 /*  werror(E_OUT_OF_MEM,__FILE__,NewSize);*/
126   exit (1);
127   }
128
129 if (NewPtr)
130   if (NewSize > OldSize)
131     memset((char *) NewPtr + OldSize,0x00,NewSize - OldSize) ;
132
133 return NewPtr ;
134 }
135 /*
136 -------------------------------------------------------------------------------
137 Safe_realloc - Reallocate a memory block with out of memory error detection
138
139 -------------------------------------------------------------------------------
140 */
141
142 void *Safe_realloc(void *OldPtr,size_t NewSize)
143
144 {
145 void *NewPtr ;
146
147 NewPtr = REALLOC(OldPtr,NewSize) ;
148
149 if (!NewPtr)
150   {
151   printf("ERROR - No more memory\n") ;
152 /*  werror(E_OUT_OF_MEM,__FILE__,NewSize);*/
153   exit (1);
154   }
155
156 return NewPtr ;
157 }
158 /*
159 -------------------------------------------------------------------------------
160 Safe_calloc - Allocate a block of memory from the application heap, clearing
161 all data to zero and checking for out of memory errors.
162
163 -------------------------------------------------------------------------------
164 */
165
166 void *Safe_calloc(size_t Elements,size_t Size)
167
168 {
169 void *NewPtr ;
170
171 NewPtr = MALLOC(Elements*Size) ;
172 #if TRACEMALLOC
173  _log(Elements*Size);
174 #endif
175  
176 if (!NewPtr)
177   {
178   printf("ERROR - No more memory\n") ;
179 /*  werror(E_OUT_OF_MEM,__FILE__,Size);*/
180   exit (1);
181   }
182
183  memset(NewPtr, 0, Elements*Size);
184
185 return NewPtr ;
186 }
187 /*
188 -------------------------------------------------------------------------------
189 Safe_malloc - Allocate a block of memory from the application heap
190 and checking for out of memory errors.
191
192 -------------------------------------------------------------------------------
193 */
194
195 void *Safe_malloc(size_t Size)
196
197 {
198 void *NewPtr ;
199
200 NewPtr = MALLOC(Size) ;
201
202 #if TRACEMALLOC
203  _log(Size);
204 #endif
205
206 if (!NewPtr)
207   {
208   printf("ERROR - No more memory\n") ;
209 /*  werror(E_OUT_OF_MEM,__FILE__,Size);*/
210   exit (1);
211   }
212
213 return NewPtr ;
214 }
215
216 void *Safe_alloc(size_t Size)
217 {
218   return Safe_calloc(1, Size);
219 }
220
221 void Safe_free(void *p)
222 {
223   FREE(p);
224 }
225
226 char *Safe_strdup(const char *sz)
227 {
228   char *pret;
229   assert(sz);
230
231   pret = Safe_alloc(strlen(sz) +1);
232   strcpy(pret, sz);
233
234   return pret;
235 }
236
237 void *traceAlloc(allocTrace *ptrace, void *p)
238 {
239   assert(ptrace);
240   assert(p);
241
242   /* Also handles where max == 0 */
243   if (ptrace->num == ptrace->max)
244     {
245       /* Add an offset to handle max == 0 */
246       ptrace->max = (ptrace->max+2)*2;
247       ptrace->palloced = Safe_realloc(ptrace->palloced, ptrace->max * sizeof(*ptrace->palloced));
248     }
249   ptrace->palloced[ptrace->num++] = p;
250
251   return p;
252 }
253
254 void freeTrace(allocTrace *ptrace)
255 {
256   int i;
257   assert(ptrace);
258
259   for (i = 0; i < ptrace->num; i++)
260     {
261       Safe_free(ptrace->palloced[i]);
262     }
263   ptrace->num = 0;
264
265   Safe_free(ptrace->palloced);
266   ptrace->palloced = NULL;
267   ptrace->max = 0;
268 }