1 /* sswf_memory.c -- written by Alexis WILKE for Made to Order Software Corp. (c) 2002-2009 */
2 
3 /*
4 
5 Copyright (c) 2002-2009 Made to Order Software Corp.
6 
7 Permission is hereby granted, free of charge, to any
8 person obtaining a copy of this software and
9 associated documentation files (the "Software"), to
10 deal in the Software without restriction, including
11 without limitation the rights to use, copy, modify,
12 merge, publish, distribute, sublicense, and/or sell
13 copies of the Software, and to permit persons to whom
14 the Software is furnished to do so, subject to the
15 following conditions:
16 
17 The above copyright notice and this permission notice
18 shall be included in all copies or substantial
19 portions of the Software.
20 
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
22 ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
23 LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
24 FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
25 EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
27 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
28 ARISING FROM, OUT OF OR IN CONNECTION WITH THE
29 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30 SOFTWARE.
31 
32 */
33 
34 
35 #include	"sswf.h"
36 
37 #if DEBUG
38 struct mem_info_t {
39 	unsigned long		magic;		/* the 'SSWF' identifier */
40 	struct mem_info_t *	next;		/* link all the memory blocks */
41 	struct mem_info_t *	previous;
42 	const char *		name;		/* some info about this memory buffer */
43 	unsigned long		serial;		/* a counter */
44 	size_t			size;		/* user allocation size */
45 };
46 #define	SSWF_MEM_INFO_SIZEOF	SSWF_MEM_ALIGN(sizeof(struct mem_info_t))
47 #define	SSWF_MEM_INFO_MAGIC	((unsigned long) 0x53535746)
48 
49 #define	SSWF_MEM_SAFE		(sizeof(double) * 32)
50 #define	SSWF_MEM_TEST		0xBADC0FFE
51 #define	SSWF_MEM_CLEAR		0xCB
52 
53 static	struct mem_info_t *	mem_head;
54 static	unsigned long		mem_serial;
55 
56 
57 #else
58 #define	SSWF_MEM_INFO_SIZEOF	0
59 #define	SSWF_MEM_SAFE		0
60 #endif
61 
62 
63 
64 
65 #if DEBUG
sswf_alloc(size_t size,const char * name)66 void *sswf_alloc(size_t size, const char *name)
67 #else
68 void *sswf_alloc(size_t size)
69 #endif
70 {
71 #if DEBUG
72 	long	*l, *m;
73 	int	idx;
74 #endif
75 	void	*p;
76 
77 	p = malloc(((size + sizeof(long) - 1) & - (long) sizeof(long)) + SSWF_MEM_INFO_SIZEOF + SSWF_MEM_SAFE * 2);
78 	if(p == NULL) {
79 		fprintf(stderr, "FATAL ERROR: out of memory allocating %d bytes.\n", (int) size);
80 		exit(-1);
81 		/*NOTREACHED*/
82 	}
83 
84 #if DEBUG
85 	((struct mem_info_t *) p)->magic = SSWF_MEM_INFO_MAGIC;
86 	((struct mem_info_t *) p)->next = mem_head;
87 	if(mem_head != NULL) {
88 		mem_head->previous = (struct mem_info_t *) p;
89 	}
90 	((struct mem_info_t *) p)->previous = NULL;
91 	mem_head = (struct mem_info_t *) p;
92 	((struct mem_info_t *) p)->name = name;
93 	mem_serial++;
94 	((struct mem_info_t *) p)->serial = mem_serial;
95 	((struct mem_info_t *) p)->size = size;
96 	l = (long *) ((char *) p + SSWF_MEM_INFO_SIZEOF);
97 	p = (char *) p + SSWF_MEM_INFO_SIZEOF + SSWF_MEM_SAFE;
98 	m = (long *) ((char *) p + ((size + sizeof(long) - 1) & - (long) sizeof(long)));
99 	idx = SSWF_MEM_SAFE / sizeof(long);
100 	do {
101 		*l++ = *m++ = SSWF_MEM_TEST;
102 		idx--;
103 	} while(idx > 0);
104 #endif
105 
106 	return p;
107 }
108 
109 
110 #if DEBUG
sswf_test_safe(void * p,const char * what)111 static void sswf_test_safe(void *p, const char *what)
112 {
113 	long		*l, *m;
114 	int		idx, head, tail;
115 
116 	assert(((long) p & (SSWF_MEM_ALIGN_SIZE - 1)) == 0, "%s an unaligned memory buffer at %p", what, (char *) p + SSWF_MEM_INFO_SIZEOF + SSWF_MEM_SAFE);
117 	assert(((struct mem_info_t *) p)->magic == SSWF_MEM_INFO_MAGIC, "%s a memory buffer without a magic marker at %p", what, (char *) p + SSWF_MEM_INFO_SIZEOF + SSWF_MEM_SAFE);
118 	l = (long *) ((char *) p + SSWF_MEM_INFO_SIZEOF);
119 	m = (long *) ((char *) l + SSWF_MEM_SAFE + ((((struct mem_info_t *) p)->size + sizeof(long) - 1) & - (long) sizeof(long)));
120 	head = 0;
121 	tail = 0;
122 	idx = SSWF_MEM_SAFE / sizeof(long);
123 	do {
124 		if(*l++ != SSWF_MEM_TEST) {
125 			head = 1;
126 		}
127 		if(*m++ != SSWF_MEM_TEST) {
128 			tail = 1;
129 		}
130 		idx--;
131 	} while(idx > 0);
132 	if(head) {
133 		/* an error occured, print out the corresponding data */
134 		l = (long *) ((char *) p + SSWF_MEM_INFO_SIZEOF);
135 		idx = SSWF_MEM_SAFE / sizeof(long);
136 		do {
137 			idx--;
138 			if((idx & 7) == 7) {
139 				printf("%08X- ", (unsigned int) (SSWF_MEM_SAFE - idx * sizeof(long)));
140 			}
141 			printf(" %08lX", *l++);
142 			if((idx & 7) == 0) {
143 				printf("\n");
144 			}
145 		} while(idx > 0);
146 	}
147 	if(tail) {
148 		m = (long *) ((char *) p + SSWF_MEM_INFO_SIZEOF + SSWF_MEM_SAFE + ((((struct mem_info_t *) p)->size + sizeof(long) - 1) & - (long) sizeof(long)));
149 		idx = SSWF_MEM_SAFE / sizeof(long);
150 		do {
151 			idx--;
152 			if((idx & 7) == 7) {
153 				printf("%08X- ", (unsigned int) (SSWF_MEM_SAFE - idx * sizeof(long) + 256));
154 			}
155 			printf(" %08lX", *m++);
156 			if((idx & 7) == 0) {
157 				printf("\n");
158 			}
159 		} while(idx > 0);
160 	}
161 	assert(!head && !tail, "head and/or tail data was overwritten");
162 }
163 #endif
164 
165 
166 
167 #if DEBUG
sswf_realloc(void * p,size_t size,const char * name)168 void *sswf_realloc(void *p, size_t size, const char *name)
169 #else
170 void *sswf_realloc(void *p, size_t size)
171 #endif
172 {
173 #if DEBUG
174 	long		*m;
175 	int		idx;
176 
177 	if(p == NULL) {
178 		return sswf_alloc(size, name);
179 	}
180 
181 	p = (char *) p - SSWF_MEM_INFO_SIZEOF - SSWF_MEM_SAFE;
182 	sswf_test_safe(p, "reallocating");
183 #else
184 	if(p == NULL) {
185 		return sswf_alloc(size);
186 	}
187 #endif
188 	p = realloc(p, size + SSWF_MEM_INFO_SIZEOF + SSWF_MEM_SAFE * 2);
189 	if(p == NULL) {
190 		fprintf(stderr, "FATAL ERROR: out of memory re-allocating %d bytes.\n", (int) size);
191 		exit(-1);
192 		/*NOTREACHED*/
193 	}
194 
195 #if DEBUG
196 	/*((struct mem_info_t *) p)->magic = SSWF_MEM_INFO_MAGIC; -- shouldn't have changed */
197 	/* p has changed so the next/previous of the previous/next nodes need fixing */
198 	if(((struct mem_info_t *) p)->next != NULL) {
199 		((struct mem_info_t *) p)->next->previous = (struct mem_info_t *) p;
200 	}
201 	if(((struct mem_info_t *) p)->previous != NULL) {
202 		((struct mem_info_t *) p)->previous->next = (struct mem_info_t *) p;
203 	}
204 	else {
205 		mem_head = (struct mem_info_t *) p;
206 	}
207 	((struct mem_info_t *) p)->name = name;
208 	mem_serial++;
209 	((struct mem_info_t *) p)->serial = mem_serial;
210 	((struct mem_info_t *) p)->size = size;
211 	p = (char *) p + SSWF_MEM_INFO_SIZEOF + SSWF_MEM_SAFE;
212 	m = (long *) ((char *) p + ((size + sizeof(long) - 1) & - (long) sizeof(long)));
213 	idx = SSWF_MEM_SAFE / sizeof(long);
214 	do {
215 		*m++ = SSWF_MEM_TEST;
216 		idx--;
217 	} while(idx > 0);
218 #endif
219 
220 	return p;
221 }
222 
223 
224 
sswf_free(void * p)225 void sswf_free(void *p)
226 {
227 	/* accept NULL pointers */
228 	if(p == NULL) {
229 		return;
230 	}
231 #if DEBUG
232 	p = (char *) p - SSWF_MEM_INFO_SIZEOF - SSWF_MEM_SAFE;
233 	sswf_test_safe(p, "freeing");
234 
235 	if(((struct mem_info_t *) p)->next != NULL) {
236 		((struct mem_info_t *) p)->next->previous = ((struct mem_info_t *) p)->previous;
237 	}
238 	if(((struct mem_info_t *) p)->previous != NULL) {
239 		((struct mem_info_t *) p)->previous->next = ((struct mem_info_t *) p)->next;
240 	}
241 	else {
242 		mem_head = ((struct mem_info_t *) p)->next;
243 	}
244 	/* clear this buffer so we can't free it again and again */
245 	memset(p, SSWF_MEM_CLEAR, ((struct mem_info_t *) p)->size + SSWF_MEM_INFO_SIZEOF + SSWF_MEM_SAFE * 2);
246 #endif
247 	free(p);
248 }
249 
250 
sswf_clean(void * p)251 void sswf_clean(void *p)
252 {
253 	/* p is really a pointer to a pointer in this case */
254 	if(p == NULL) {
255 		return;
256 	}
257 	if(* (void **) p == NULL) {
258 		return;
259 	}
260 	sswf_free(* (void **) p);
261 	* (void **) p = NULL;
262 }
263 
264 
265 
sswf_strdup(const char * string)266 char *sswf_strdup(const char *string)
267 {
268 	int		l;
269 	char		*r;
270 
271 	if(string == NULL) {
272 		l = 1;
273 	}
274 	else {
275 		l = strlen(string) + 1;
276 	}
277 
278 	r = sswf_malloc(l, "dynamic string (strdup)");
279 
280 	if(l > 1) {
281 		/* l includes the nul terminator */
282 		memcpy(r, string, l);
283 	}
284 	else {
285 		*r = '\0';
286 	}
287 
288 	return r;
289 }
290 
291 
sswf_strcat(const char * a,const char * b)292 char *sswf_strcat(const char *a, const char *b)
293 {
294 	int		la, lb;
295 	char		*r;
296 
297 	if(a == NULL) {
298 		return sswf_strdup(b);
299 	}
300 	if(b == NULL) {
301 		return sswf_strdup(a);
302 	}
303 
304 	la = strlen(a);
305 	lb = strlen(b);
306 
307 	r = sswf_malloc(la + lb + 1, "dynamic string (sswf_strcat)");
308 
309 	if(la > 0) {
310 		memcpy(r, a, la);
311 	}
312 	if(lb > 0) {
313 		memcpy(r + la, b, lb);
314 	}
315 	r[la + lb] = '\0';
316 
317 	return r;
318 }
319 
320 
321 
sswf_strcat3(const char * a,const char * b,const char * c)322 char *sswf_strcat3(const char *a, const char *b, const char *c)
323 {
324 	int		la, lb, lc;
325 	char		*r;
326 
327 	if(a == NULL) {
328 		a = "";
329 	}
330 	if(b == NULL) {
331 		b = "";
332 	}
333 	if(c == NULL) {
334 		c = "";
335 	}
336 
337 	la = strlen(a);
338 	lb = strlen(b);
339 	lc = strlen(c);
340 
341 	r = sswf_malloc(la + lb + lc + 1, "dynamic string (sswf_strcat3)");
342 
343 	if(la > 0) {
344 		memcpy(r, a, la);
345 	}
346 	if(lb > 0) {
347 		memcpy(r + la, b, lb);
348 	}
349 	if(lc > 0) {
350 		memcpy(r + la + lb, c, lc);
351 	}
352 	r[la + lb + lc] = '\0';
353 
354 	return r;
355 }
356 
357 
358 
sswf_strchild(const char * a,const char * b)359 char *sswf_strchild(const char *a, const char *b)
360 {
361 	int		la, lb;
362 	const char	*e;
363 	char		*r;
364 
365 	if(a == NULL) {
366 		return sswf_strdup(b);
367 	}
368 	if(b == NULL) {
369 		return sswf_strdup(a);
370 	}
371 
372 	e = a;
373 	while(*e != '\0') {
374 		e++;
375 	}
376 	if(e > a && (e[-1] == '/' || e[-1] == '\\' || e[-1] == ':')) {
377 		return sswf_strcat(a, b);
378 	}
379 
380 	la = strlen(a);
381 	lb = strlen(b);
382 
383 	r = sswf_malloc(la + lb + 2, "dynamic string (strcat)");
384 
385 	if(la > 0) {
386 		memcpy(r, a, la);
387 	}
388 	r[la] = '/';		/* TODO: we need to fix this with the system separator instead */
389 	if(lb > 0) {
390 		memcpy(r + la + 1, b, lb);
391 	}
392 	r[la + lb + 1] = '\0';
393 
394 	return r;
395 }
396 
397 
398 
399 #if DEBUG
sswf_info(void)400 void sswf_info(void)
401 {
402 	struct mem_info_t	*p;
403 	size_t			count, total;
404 
405 	printf("\n*** Memory Info:\n");
406 	total = 0;
407 	count = 0;
408 	p = mem_head;
409 	if(p == NULL) {
410 		printf("!!! No memory leaks. Very good. !!!\n");
411 		return;
412 	}
413 	if(p->previous != NULL) {
414 		printf("+++ INVALID +++ First block not a head list block!\n");
415 	}
416 	while(p != NULL) {
417 		if(p->magic != SSWF_MEM_INFO_MAGIC) {
418 			printf("+++ INVALID +++ ");
419 		}
420 		count++;
421 		printf("0x%08lX: Block #%06ld (Serial #%06ld) - %7ld bytes - %s", (long) ((char *) p + SSWF_MEM_INFO_SIZEOF + SSWF_MEM_SAFE), (long) count, (long) p->serial, (long) p->size, p->name);
422 		if(p->name != NULL && strncmp(p->name, "dynamic string", 14) == 0) {
423 			printf(" [%s]", (char *) p + SSWF_MEM_INFO_SIZEOF + SSWF_MEM_SAFE);
424 		}
425 		printf("\n");
426 		total += p->size;
427 		p = p->next;
428 	}
429 
430 	printf("Total of %ld blocks for %ld bytes.\n", (long) count, (long) total);
431 }
432 
sswf_info_serial(void)433 void sswf_info_serial(void)
434 {
435 	printf("At this point, the memory serial counter is #%ld\n", mem_serial);
436 }
437 #endif
438 
439 
440