5d24b140e24409f173abf335e96ccb35f153c810
[reactos.git] / reactos / lib / kjs / src / alloc.c
1 /*
2 * Memory allocation routines.
3 * Copyright (c) 1998 New Generation Software (NGS) Oy
4 *
5 * Author: Markku Rossi <mtr@ngs.fi>
6 */
7
8 /*
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Library General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
13 *
14 * This library 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 GNU
17 * Library General Public License for more details.
18 *
19 * You should have received a copy of the GNU Library General Public
20 * License along with this library; if not, write to the Free
21 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
22 * MA 02111-1307, USA
23 */
24
25 /*
26 * $Source: /cygdrive/c/RCVS/CVS/ReactOS/reactos/lib/kjs/src/alloc.c,v $
27 * $Id$
28 */
29
30 #include "jsint.h"
31
32 /*
33 * Global functions.
34 */
35
36 #if JS_DEBUG_MEMORY_LEAKS
37
38 struct mem_debug_st
39 {
40 struct mem_debug_st *next;
41 struct mem_debug_st *prev;
42 char *file;
43 int line;
44 size_t size;
45 };
46
47 typedef struct mem_debug_st MemDebug;
48
49 static MemDebug *mem_debug_blocks = NULL;
50
51 int mem_debug_balance = 0;
52
53 unsigned int alloc_fail = 0;
54 unsigned int alloc_count = 0;
55
56 static void
57 register_block (MemDebug *b, size_t size, char *file, int line)
58 {
59 b->next = NULL;
60 b->prev = NULL;
61 b->file = file;
62 b->line = line;
63 b->size = size;
64
65 if (mem_debug_blocks)
66 {
67 b->next = mem_debug_blocks;
68 mem_debug_blocks->prev = b;
69 }
70
71 mem_debug_blocks = b;
72 mem_debug_balance++;
73 }
74
75
76 static void
77 unregister_block (MemDebug *b)
78 {
79 if (b->file == NULL)
80 {
81 fprintf (stderr, "freeing the same block twise\n");
82 abort ();
83 }
84
85 if (b->next)
86 b->next->prev = b->prev;
87
88 if (b->prev)
89 b->prev->next = b->next;
90 else
91 mem_debug_blocks = b->next;
92
93 b->file = NULL;
94
95 mem_debug_balance--;
96 }
97
98
99 static inline int
100 check_fail ()
101 {
102 return alloc_fail != 0 && ++alloc_count >= alloc_fail;
103 }
104
105
106 void
107 js_alloc_dump_blocks ()
108 {
109 MemDebug *b;
110 unsigned int bytes = 0;
111
112 fprintf (stderr, "js_alloc_dump_blocks(): #blocks=%d\n", mem_debug_balance);
113
114 for (b = mem_debug_blocks; b; b = b->next)
115 {
116 fprintf (stderr, "%s:%d: %lu\n", b->file, b->line, b->size);
117 bytes += b->size;
118 }
119
120 fprintf (stderr, "leaks=%u\n", bytes);
121 }
122
123
124
125 void *
126 js_malloc_i (JSVirtualMachine *vm, size_t size, char *file, int line)
127 {
128 MemDebug *ptr;
129
130 ptr = malloc (sizeof (MemDebug) + size);
131 if (check_fail () || ptr == NULL)
132 {
133 if (vm != NULL)
134 {
135 sprintf (vm->error, "VM: memory exhausted");
136 js_vm_error (vm);
137 }
138
139 return NULL;
140 }
141
142 register_block (ptr, size, file, line);
143
144 return (unsigned char *) ptr + sizeof (MemDebug);
145 }
146
147
148 void *
149 js_calloc_i (JSVirtualMachine *vm, size_t num, size_t size, char *file,
150 int line)
151 {
152 MemDebug *ptr;
153
154 ptr = malloc (sizeof (MemDebug) + num * size);
155 if (check_fail () || ptr == NULL)
156 {
157 if (vm != NULL)
158 {
159 sprintf (vm->error, "VM: memory exhausted");
160 js_vm_error (vm);
161 }
162
163 return NULL;
164 }
165
166 memset (ptr, 0, sizeof (MemDebug) + num * size);
167 register_block (ptr, num * size, file, line);
168
169 return (unsigned char *) ptr + sizeof (MemDebug);
170 }
171
172
173 void *
174 js_realloc_i (JSVirtualMachine *vm, void *ptr, size_t size, char *file,
175 int line)
176 {
177 void *nptr;
178 MemDebug *b;
179
180 if (ptr == NULL)
181 return js_malloc_i (vm, size, file, line);
182
183 nptr = js_malloc_i (vm, size, file, line);
184 if (nptr == NULL)
185 {
186 if (vm != NULL)
187 {
188 sprintf (vm->error, "VM: memory exhausted");
189 js_vm_error (vm);
190 }
191
192 return NULL;
193 }
194
195 b = (MemDebug *) ((unsigned char *) ptr - sizeof (MemDebug));
196
197 memcpy (nptr, ptr, size < b->size ? size : b->size);
198
199 js_free (ptr);
200
201 return nptr;
202 }
203
204
205 void
206 js_free (void *ptr)
207 {
208 MemDebug *b;
209
210 if (ptr == NULL)
211 return;
212
213 b = (MemDebug *) ((unsigned char *) ptr - sizeof (MemDebug));
214 unregister_block (b);
215
216 free (b);
217 }
218
219
220 char *
221 js_strdup_i (JSVirtualMachine *vm, const char *str, char *file, int line)
222 {
223 char *tmp;
224
225 tmp = js_malloc_i (vm, strlen (str) + 1, file, line);
226 if (tmp == NULL)
227 return NULL;
228
229 strcpy (tmp, str);
230
231 return tmp;
232 }
233
234 #else /* not JS_DEBUG_MEMORY_LEAKS */
235
236 void *
237 js_malloc (JSVirtualMachine *vm, size_t size)
238 {
239 void *ptr;
240
241 ptr = malloc (size);
242 if (ptr == NULL && vm != NULL)
243 {
244 sprintf (vm->error, "VM: memory exhausted");
245 js_vm_error (vm);
246 }
247
248 return ptr;
249 }
250
251
252 void *
253 js_calloc (JSVirtualMachine *vm, size_t num, size_t size)
254 {
255 void *ptr;
256
257 ptr = calloc (num, size);
258 if (ptr == NULL && vm != NULL)
259 {
260 sprintf (vm->error, "VM: memory exhausted");
261 js_vm_error (vm);
262 }
263
264 return ptr;
265 }
266
267
268 void *
269 js_realloc (JSVirtualMachine *vm, void *ptr, size_t size)
270 {
271 void *nptr;
272
273 if (ptr == NULL)
274 return js_malloc (vm, size);
275
276 nptr = realloc (ptr, size);
277 if (nptr == NULL && vm != NULL)
278 {
279 sprintf (vm->error, "VM: memory exhausted");
280 js_vm_error (vm);
281 }
282
283 return nptr;
284 }
285
286
287 void
288 js_free (void *ptr)
289 {
290 if (ptr == NULL)
291 return;
292
293 free (ptr);
294 }
295
296
297 char *
298 js_strdup (JSVirtualMachine *vm, const char *str)
299 {
300 char *tmp;
301
302 tmp = js_malloc (vm, strlen (str) + 1);
303 if (tmp == NULL)
304 return NULL;
305
306 strcpy (tmp, str);
307
308 return tmp;
309 }
310
311 #endif /* not JS_DEBUG_MEMORY_LEAKS */