blob: 4cf160310587fcdaac902a444338a0ccbd33c858 [file] [log] [blame]
Daniel Veillard6454aec1999-09-02 22:04:43 +00001/*
2 * memory.c: libxml memory allocator wrapper.
3 *
4 * Daniel.Veillard@w3.org
5 */
6
Daniel Veillard7f7d1111999-09-22 09:46:25 +00007#ifdef WIN32
Daniel Veillard3c558c31999-12-22 11:30:41 +00008#include "win32config.h"
Daniel Veillard7f7d1111999-09-22 09:46:25 +00009#else
10#include "config.h"
11#endif
12
Daniel Veillard6454aec1999-09-02 22:04:43 +000013#include <stdio.h>
Daniel Veillard7f7d1111999-09-22 09:46:25 +000014#include <string.h>
15
16#ifdef HAVE_SYS_TYPES_H
17#include <sys/types.h>
18#endif
19#ifdef HAVE_TIME_H
20#include <time.h>
21#endif
22#ifdef HAVE_MALLOC_H
Daniel Veillard6454aec1999-09-02 22:04:43 +000023#include <malloc.h>
Daniel Veillard7f7d1111999-09-22 09:46:25 +000024#endif
Daniel Veillard7c1206f1999-10-14 09:10:25 +000025#ifdef HAVE_STDLIB_H
26#include <stdlib.h>
27#endif
Daniel Veillard5e5c6231999-12-29 12:49:06 +000028#ifdef HAVE_CTYPE_H
29#include <ctype.h>
30#endif
Daniel Veillard7c1206f1999-10-14 09:10:25 +000031
Daniel Veillard7f7d1111999-09-22 09:46:25 +000032
Daniel Veillard361d8452000-04-03 19:48:13 +000033#include <libxml/xmlmemory.h>
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +000034#include <libxml/xmlerror.h>
Daniel Veillard6454aec1999-09-02 22:04:43 +000035
Daniel Veillard6454aec1999-09-02 22:04:43 +000036#ifdef xmlMalloc
37#undef xmlMalloc
38#endif
39#ifdef xmlRealloc
40#undef xmlRealloc
41#endif
42#ifdef xmlMemStrdup
43#undef xmlMemStrdup
44#endif
Daniel Veillard00fdf371999-10-08 09:40:39 +000045
Daniel Veillard6454aec1999-09-02 22:04:43 +000046
47/*
48 * Each of the blocks allocated begin with a header containing informations
49 */
50
51#define MEMTAG 0x5aa5
52
53#define MALLOC_TYPE 1
54#define REALLOC_TYPE 2
55#define STRDUP_TYPE 3
56
57typedef struct memnod {
58 unsigned int mh_tag;
59 unsigned int mh_type;
60 unsigned long mh_number;
61 size_t mh_size;
62#ifdef MEM_LIST
63 struct memnod *mh_next;
64 struct memnod *mh_prev;
65#endif
66 const char *mh_file;
67 unsigned int mh_line;
68} MEMHDR;
69
70
71#ifdef SUN4
72#define ALIGN_SIZE 16
73#else
74#define ALIGN_SIZE sizeof(double)
75#endif
76#define HDR_SIZE sizeof(MEMHDR)
77#define RESERVE_SIZE (((HDR_SIZE + (ALIGN_SIZE-1)) \
78 / ALIGN_SIZE ) * ALIGN_SIZE)
79
80
81#define CLIENT_2_HDR(a) ((MEMHDR *) (((char *) (a)) - RESERVE_SIZE))
82#define HDR_2_CLIENT(a) ((void *) (((char *) (a)) + RESERVE_SIZE))
83
84
85static unsigned long debugMemSize = 0;
Daniel Veillard7c1206f1999-10-14 09:10:25 +000086static unsigned long debugMaxMemSize = 0;
Daniel Veillard6454aec1999-09-02 22:04:43 +000087static int block=0;
Daniel Veillard7c1206f1999-10-14 09:10:25 +000088int xmlMemStopAtBlock = 0;
89int xmlMemInitialized = 0;
Daniel Veillard6454aec1999-09-02 22:04:43 +000090#ifdef MEM_LIST
91static MEMHDR *memlist = NULL;
92#endif
93
94void debugmem_tag_error(void *addr);
95#ifdef MEM_LIST
96void debugmem_list_add(MEMHDR *);
97void debugmem_list_delete(MEMHDR *);
98#endif
99#define Mem_Tag_Err(a) debugmem_tag_error(a);
100
101#ifndef TEST_POINT
102#define TEST_POINT
103#endif
104
105/**
Daniel Veillard7c1206f1999-10-14 09:10:25 +0000106 * xmlMallocBreakpoint:
107 *
108 * Breakpoint to use in conjunction with xmlMemStopAtBlock. When the block
109 * number reaches the specified value this function is called. One need to add a breakpoint
110 * to it to get the context in which the given block is allocated.
111 */
112
113void
114xmlMallocBreakpoint(void) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000115 xmlGenericError(xmlGenericErrorContext,
116 "xmlMallocBreakpoint reached on block %d\n", xmlMemStopAtBlock);
Daniel Veillard7c1206f1999-10-14 09:10:25 +0000117}
118
119/**
Daniel Veillard6454aec1999-09-02 22:04:43 +0000120 * xmlMallocLoc:
121 * @size: an int specifying the size in byte to allocate.
122 * @file: the file name or NULL
Daniel Veillard06047432000-04-24 11:33:38 +0000123 * @line: the line number
Daniel Veillard6454aec1999-09-02 22:04:43 +0000124 *
125 * a malloc() equivalent, with logging of the allocation info.
126 *
127 * Returns a pointer to the allocated area or NULL in case of lack of memory.
128 */
129
130void *
131xmlMallocLoc(int size, const char * file, int line)
132{
133 MEMHDR *p;
134
Daniel Veillard7c1206f1999-10-14 09:10:25 +0000135 if (!xmlMemInitialized) xmlInitMemory();
Daniel Veillard6454aec1999-09-02 22:04:43 +0000136#ifdef DEBUG_MEMORY
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000137 xmlGenericError(xmlGenericErrorContext,
138 "Malloc(%d)\n",size);
Daniel Veillard6454aec1999-09-02 22:04:43 +0000139#endif
140
141 TEST_POINT
142
143 p = (MEMHDR *) malloc(RESERVE_SIZE+size);
144
145 if (!p) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000146 xmlGenericError(xmlGenericErrorContext,
147 "xmlMalloc : Out of free space\n");
Daniel Veillard10a2c651999-12-12 13:03:50 +0000148 xmlMemoryDump();
149 return(NULL);
Daniel Veillard6454aec1999-09-02 22:04:43 +0000150 }
151 p->mh_tag = MEMTAG;
152 p->mh_number = ++block;
153 p->mh_size = size;
154 p->mh_type = MALLOC_TYPE;
155 p->mh_file = file;
156 p->mh_line = line;
157 debugMemSize += size;
Daniel Veillard7c1206f1999-10-14 09:10:25 +0000158 if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize;
Daniel Veillard6454aec1999-09-02 22:04:43 +0000159#ifdef MEM_LIST
160 debugmem_list_add(p);
161#endif
162
163#ifdef DEBUG_MEMORY
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000164 xmlGenericError(xmlGenericErrorContext,
165 "Malloc(%d) Ok\n",size);
Daniel Veillard6454aec1999-09-02 22:04:43 +0000166#endif
167
Daniel Veillard7c1206f1999-10-14 09:10:25 +0000168 if (xmlMemStopAtBlock == block) xmlMallocBreakpoint();
Daniel Veillard6454aec1999-09-02 22:04:43 +0000169
170 TEST_POINT
171
172 return(HDR_2_CLIENT(p));
173}
174
175/**
Daniel Veillard8f621982000-03-20 13:07:15 +0000176 * xmlMemMalloc:
Daniel Veillard6454aec1999-09-02 22:04:43 +0000177 * @size: an int specifying the size in byte to allocate.
178 *
179 * a malloc() equivalent, with logging of the allocation info.
180 *
181 * Returns a pointer to the allocated area or NULL in case of lack of memory.
182 */
183
184void *
Daniel Veillard8f621982000-03-20 13:07:15 +0000185xmlMemMalloc(int size)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000186{
187 return(xmlMallocLoc(size, "none", 0));
188}
189
190/**
191 * xmlReallocLoc:
192 * @ptr: the initial memory block pointer
193 * @size: an int specifying the size in byte to allocate.
194 * @file: the file name or NULL
Daniel Veillard06047432000-04-24 11:33:38 +0000195 * @line: the line number
Daniel Veillard6454aec1999-09-02 22:04:43 +0000196 *
197 * a realloc() equivalent, with logging of the allocation info.
198 *
199 * Returns a pointer to the allocated area or NULL in case of lack of memory.
200 */
201
202void *
203xmlReallocLoc(void *ptr,int size, const char * file, int line)
204{
205 MEMHDR *p;
206 unsigned long number;
207
Daniel Veillard7c1206f1999-10-14 09:10:25 +0000208 if (!xmlMemInitialized) xmlInitMemory();
Daniel Veillard6454aec1999-09-02 22:04:43 +0000209 TEST_POINT
210
211 p = CLIENT_2_HDR(ptr);
212 number = p->mh_number;
213 if (p->mh_tag != MEMTAG) {
Daniel Veillard7f7d1111999-09-22 09:46:25 +0000214 Mem_Tag_Err(p);
Daniel Veillard6454aec1999-09-02 22:04:43 +0000215 goto error;
216 }
217 p->mh_tag = ~MEMTAG;
218 debugMemSize -= p->mh_size;
219#ifdef MEM_LIST
220 debugmem_list_delete(p);
221#endif
222
223 p = (MEMHDR *) realloc(p,RESERVE_SIZE+size);
224 if (!p) {
225 goto error;
226 }
227 p->mh_tag = MEMTAG;
228 p->mh_number = number;
229 p->mh_type = REALLOC_TYPE;
230 p->mh_size = size;
231 p->mh_file = file;
232 p->mh_line = line;
233 debugMemSize += size;
Daniel Veillard7c1206f1999-10-14 09:10:25 +0000234 if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize;
Daniel Veillard6454aec1999-09-02 22:04:43 +0000235#ifdef MEM_LIST
236 debugmem_list_add(p);
237#endif
238
239 TEST_POINT
240
241 return(HDR_2_CLIENT(p));
242
243error:
244 return(NULL);
245}
246
247/**
Daniel Veillard8f621982000-03-20 13:07:15 +0000248 * xmlMemRealloc:
Daniel Veillard6454aec1999-09-02 22:04:43 +0000249 * @ptr: the initial memory block pointer
250 * @size: an int specifying the size in byte to allocate.
251 *
252 * a realloc() equivalent, with logging of the allocation info.
253 *
254 * Returns a pointer to the allocated area or NULL in case of lack of memory.
255 */
256
257void *
Daniel Veillard8f621982000-03-20 13:07:15 +0000258xmlMemRealloc(void *ptr,int size) {
Daniel Veillard6454aec1999-09-02 22:04:43 +0000259 return(xmlReallocLoc(ptr, size, "none", 0));
260}
261
262/**
Daniel Veillard8f621982000-03-20 13:07:15 +0000263 * xmlMemFree:
Daniel Veillard6454aec1999-09-02 22:04:43 +0000264 * @ptr: the memory block pointer
265 *
266 * a free() equivalent, with error checking.
Daniel Veillard6454aec1999-09-02 22:04:43 +0000267 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000268void
Daniel Veillard8f621982000-03-20 13:07:15 +0000269xmlMemFree(void *ptr)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000270{
271 MEMHDR *p;
272
273 TEST_POINT
274
275 p = CLIENT_2_HDR(ptr);
276 if (p->mh_tag != MEMTAG) {
Daniel Veillard7f7d1111999-09-22 09:46:25 +0000277 Mem_Tag_Err(p);
278 goto error;
Daniel Veillard6454aec1999-09-02 22:04:43 +0000279 }
280 p->mh_tag = ~MEMTAG;
281 debugMemSize -= p->mh_size;
282
283#ifdef MEM_LIST
284 debugmem_list_delete(p);
285#endif
286 free(p);
287
288 TEST_POINT
289
290 return;
291
292error:
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000293 xmlGenericError(xmlGenericErrorContext,
294 "xmlFree(%X) error\n", (unsigned int) ptr);
Daniel Veillard6454aec1999-09-02 22:04:43 +0000295 return;
296}
297
298/**
299 * xmlMemStrdupLoc:
300 * @ptr: the initial string pointer
301 * @file: the file name or NULL
Daniel Veillard06047432000-04-24 11:33:38 +0000302 * @line: the line number
Daniel Veillard6454aec1999-09-02 22:04:43 +0000303 *
304 * a strdup() equivalent, with logging of the allocation info.
305 *
306 * Returns a pointer to the new string or NULL if allocation error occured.
307 */
308
309char *
310xmlMemStrdupLoc(const char *str, const char *file, int line)
311{
312 char *s;
313 size_t size = strlen(str) + 1;
314 MEMHDR *p;
315
Daniel Veillard7c1206f1999-10-14 09:10:25 +0000316 if (!xmlMemInitialized) xmlInitMemory();
Daniel Veillard6454aec1999-09-02 22:04:43 +0000317 TEST_POINT
318
319 p = (MEMHDR *) malloc(RESERVE_SIZE+size);
320 if (!p) {
Daniel Veillard7f7d1111999-09-22 09:46:25 +0000321 goto error;
Daniel Veillard6454aec1999-09-02 22:04:43 +0000322 }
323 p->mh_tag = MEMTAG;
324 p->mh_number = ++block;
325 p->mh_size = size;
326 p->mh_type = STRDUP_TYPE;
327 p->mh_file = file;
328 p->mh_line = line;
329 debugMemSize += size;
Daniel Veillard7c1206f1999-10-14 09:10:25 +0000330 if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize;
Daniel Veillard6454aec1999-09-02 22:04:43 +0000331#ifdef MEM_LIST
332 debugmem_list_add(p);
333#endif
Daniel Veillard32bc74e2000-07-14 14:49:25 +0000334 s = (char *) HDR_2_CLIENT(p);
Daniel Veillard6454aec1999-09-02 22:04:43 +0000335
Daniel Veillard7c1206f1999-10-14 09:10:25 +0000336 if (xmlMemStopAtBlock == block) xmlMallocBreakpoint();
337
Daniel Veillard6454aec1999-09-02 22:04:43 +0000338 if (s != NULL)
Daniel Veillard7f7d1111999-09-22 09:46:25 +0000339 strcpy(s,str);
Daniel Veillard6454aec1999-09-02 22:04:43 +0000340 else
Daniel Veillard7f7d1111999-09-22 09:46:25 +0000341 goto error;
Daniel Veillard6454aec1999-09-02 22:04:43 +0000342
343 TEST_POINT
344
345 return(s);
346
347error:
348 return(NULL);
349}
350
351/**
Daniel Veillard8f621982000-03-20 13:07:15 +0000352 * xmlMemoryStrdup:
Daniel Veillard6454aec1999-09-02 22:04:43 +0000353 * @ptr: the initial string pointer
354 *
355 * a strdup() equivalent, with logging of the allocation info.
356 *
357 * Returns a pointer to the new string or NULL if allocation error occured.
358 */
359
360char *
Daniel Veillard8f621982000-03-20 13:07:15 +0000361xmlMemoryStrdup(const char *str) {
Daniel Veillard6454aec1999-09-02 22:04:43 +0000362 return(xmlMemStrdupLoc(str, "none", 0));
363}
364
365/**
366 * xmlMemUsed:
367 *
368 * returns the amount of memory currenly allocated
369 *
370 * Returns an int representing the amount of memory allocated.
371 */
372
373int
374xmlMemUsed(void) {
375 return(debugMemSize);
376}
377
Daniel Veillard5e5c6231999-12-29 12:49:06 +0000378#ifdef MEM_LIST
379/**
380 * xmlMemContentShow:
381 * @fp: a FILE descriptor used as the output file
382 * @p: a memory block header
383 *
384 * tries to show some content from the memory block
385 */
386
387void
388xmlMemContentShow(FILE *fp, MEMHDR *p)
389{
390 int i,j,len = p->mh_size;
Daniel Veillard32bc74e2000-07-14 14:49:25 +0000391 const char *buf = (const char *) HDR_2_CLIENT(p);
Daniel Veillard5e5c6231999-12-29 12:49:06 +0000392
Daniel Veillard126f2792000-10-24 17:10:12 +0000393 if (p == NULL) {
394 fprintf(fp, " NULL");
395 return;
396 }
397
Daniel Veillard5e5c6231999-12-29 12:49:06 +0000398 for (i = 0;i < len;i++) {
399 if (buf[i] == 0) break;
400 if (!isprint(buf[i])) break;
401 }
402 if ((i < 4) && ((buf[i] != 0) || (i == 0))) {
403 if (len >= 4) {
404 MEMHDR *q;
405 void *cur;
406
407 for (j = 0;j < len -3;j += 4) {
408 cur = *((void **) &buf[j]);
409 q = CLIENT_2_HDR(cur);
410 p = memlist;
411 while (p != NULL) {
412 if (p == q) break;
413 p = p->mh_next;
414 }
Daniel Veillard126f2792000-10-24 17:10:12 +0000415 if ((p != NULL) && (p == q)) {
Daniel Veillard5e5c6231999-12-29 12:49:06 +0000416 fprintf(fp, " pointer to #%lu at index %d",
417 p->mh_number, j);
418 return;
419 }
420 }
421 }
422 } else if ((i == 0) && (buf[i] == 0)) {
423 fprintf(fp," null");
424 } else {
425 if (buf[i] == 0) fprintf(fp," \"%.25s\"", buf);
426 else {
427 fprintf(fp," [");
428 for (j = 0;j < i;j++)
429 fprintf(fp,"%c", buf[j]);
430 fprintf(fp,"]");
431 }
432 }
433}
434#endif
435
Daniel Veillard6454aec1999-09-02 22:04:43 +0000436/**
Daniel Veillarddbfd6411999-12-28 16:35:14 +0000437 * xmlMemShow:
438 * @fp: a FILE descriptor used as the output file
439 * @nr: number of entries to dump
440 *
441 * show a show display of the memory allocated, and dump
442 * the @nr last allocated areas which were not freed
443 */
444
445void
446xmlMemShow(FILE *fp, int nr)
447{
448#ifdef MEM_LIST
449 MEMHDR *p;
450#endif
451
452 if (fp != NULL)
453 fprintf(fp," MEMORY ALLOCATED : %lu, MAX was %lu\n",
454 debugMemSize, debugMaxMemSize);
455#ifdef MEM_LIST
456 if (nr > 0) {
457 fprintf(fp,"NUMBER SIZE TYPE WHERE\n");
458 p = memlist;
459 while ((p) && nr > 0) {
460 fprintf(fp,"%6lu %6u ",p->mh_number,p->mh_size);
461 switch (p->mh_type) {
462 case STRDUP_TYPE:fprintf(fp,"strdup() in ");break;
463 case MALLOC_TYPE:fprintf(fp,"malloc() in ");break;
464 case REALLOC_TYPE:fprintf(fp,"realloc() in ");break;
465 default:fprintf(fp," ??? in ");break;
466 }
467 if (p->mh_file != NULL)
468 fprintf(fp,"%s(%d)", p->mh_file, p->mh_line);
469 if (p->mh_tag != MEMTAG)
470 fprintf(fp," INVALID");
Daniel Veillard5e5c6231999-12-29 12:49:06 +0000471 xmlMemContentShow(fp, p);
Daniel Veillarddbfd6411999-12-28 16:35:14 +0000472 fprintf(fp,"\n");
473 nr--;
474 p = p->mh_next;
475 }
476 }
477#endif /* MEM_LIST */
478}
479
480/**
Daniel Veillard6454aec1999-09-02 22:04:43 +0000481 * xmlMemDisplay:
482 * @fp: a FILE descriptor used as the output file, if NULL, the result is
Daniel Veillarddbfd6411999-12-28 16:35:14 +0000483 * written to the file .memorylist
Daniel Veillard6454aec1999-09-02 22:04:43 +0000484 *
485 * show in-extenso the memory blocks allocated
486 */
487
488void
489xmlMemDisplay(FILE *fp)
490{
491#ifdef MEM_LIST
Daniel Veillard7f7d1111999-09-22 09:46:25 +0000492 MEMHDR *p;
493 int idx;
494#if defined(HAVE_LOCALTIME) && defined(HAVE_STRFTIME)
495 time_t currentTime;
496 char buf[500];
497 struct tm * tstruct;
498
499 currentTime = time(NULL);
500 tstruct = localtime(&currentTime);
501 strftime(buf, sizeof(buf) - 1, "%c", tstruct);
502 fprintf(fp," %s\n\n", buf);
503#endif
504
Daniel Veillard6454aec1999-09-02 22:04:43 +0000505
Daniel Veillard7c1206f1999-10-14 09:10:25 +0000506 fprintf(fp," MEMORY ALLOCATED : %lu, MAX was %lu\n",
507 debugMemSize, debugMaxMemSize);
Daniel Veillard7f7d1111999-09-22 09:46:25 +0000508 fprintf(fp,"BLOCK NUMBER SIZE TYPE\n");
509 idx = 0;
510 p = memlist;
511 while (p) {
Daniel Veillard6454aec1999-09-02 22:04:43 +0000512 fprintf(fp,"%-5u %6lu %6u ",idx++,p->mh_number,p->mh_size);
Daniel Veillard7f7d1111999-09-22 09:46:25 +0000513 switch (p->mh_type) {
514 case STRDUP_TYPE:fprintf(fp,"strdup() in ");break;
515 case MALLOC_TYPE:fprintf(fp,"malloc() in ");break;
516 case REALLOC_TYPE:fprintf(fp,"realloc() in ");break;
517 default:fprintf(fp," ??? in ");break;
518 }
Daniel Veillard6454aec1999-09-02 22:04:43 +0000519 if (p->mh_file != NULL) fprintf(fp,"%s(%d)", p->mh_file, p->mh_line);
Daniel Veillard7f7d1111999-09-22 09:46:25 +0000520 if (p->mh_tag != MEMTAG)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000521 fprintf(fp," INVALID");
Daniel Veillard5e5c6231999-12-29 12:49:06 +0000522 xmlMemContentShow(fp, p);
Daniel Veillard7f7d1111999-09-22 09:46:25 +0000523 fprintf(fp,"\n");
524 p = p->mh_next;
525 }
Daniel Veillard6454aec1999-09-02 22:04:43 +0000526#else
Daniel Veillard7f7d1111999-09-22 09:46:25 +0000527 fprintf(fp,"Memory list not compiled (MEM_LIST not defined !)\n");
Daniel Veillard6454aec1999-09-02 22:04:43 +0000528#endif
529}
530
531#ifdef MEM_LIST
532
533void debugmem_list_add(MEMHDR *p)
534{
Daniel Veillard7f7d1111999-09-22 09:46:25 +0000535 p->mh_next = memlist;
536 p->mh_prev = NULL;
537 if (memlist) memlist->mh_prev = p;
538 memlist = p;
Daniel Veillard6454aec1999-09-02 22:04:43 +0000539#ifdef MEM_LIST_DEBUG
Daniel Veillard7f7d1111999-09-22 09:46:25 +0000540 if (stderr)
541 Mem_Display(stderr);
Daniel Veillard6454aec1999-09-02 22:04:43 +0000542#endif
543}
544
545void debugmem_list_delete(MEMHDR *p)
546{
Daniel Veillard7f7d1111999-09-22 09:46:25 +0000547 if (p->mh_next)
548 p->mh_next->mh_prev = p->mh_prev;
549 if (p->mh_prev)
550 p->mh_prev->mh_next = p->mh_next;
551 else memlist = p->mh_next;
Daniel Veillard6454aec1999-09-02 22:04:43 +0000552#ifdef MEM_LIST_DEBUG
Daniel Veillard7f7d1111999-09-22 09:46:25 +0000553 if (stderr)
554 Mem_Display(stderr);
Daniel Veillard6454aec1999-09-02 22:04:43 +0000555#endif
556}
557
558#endif
559
560/*
561 * debugmem_tag_error : internal error function.
562 */
563
564void debugmem_tag_error(void *p)
565{
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000566 xmlGenericError(xmlGenericErrorContext,
567 "Memory tag error occurs :%p \n\t bye\n", p);
Daniel Veillard6454aec1999-09-02 22:04:43 +0000568#ifdef MEM_LIST
Daniel Veillard7f7d1111999-09-22 09:46:25 +0000569 if (stderr)
570 xmlMemDisplay(stderr);
Daniel Veillard6454aec1999-09-02 22:04:43 +0000571#endif
572}
573
574FILE *xmlMemoryDumpFile = NULL;
575
576
577/**
578 * xmlMemoryDump:
579 *
580 * Dump in-extenso the memory blocks allocated to the file .memorylist
581 */
582
583void
584xmlMemoryDump(void)
585{
Daniel Veillard8f621982000-03-20 13:07:15 +0000586#if defined(DEBUG_MEMORY_LOCATION) | defined(DEBUG_MEMORY)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000587 FILE *dump;
588
589 dump = fopen(".memdump", "w");
590 if (dump == NULL) xmlMemoryDumpFile = stdout;
591 else xmlMemoryDumpFile = dump;
592
593 xmlMemDisplay(xmlMemoryDumpFile);
594
595 if (dump != NULL) fclose(dump);
Daniel Veillard8f621982000-03-20 13:07:15 +0000596#endif
Daniel Veillard6454aec1999-09-02 22:04:43 +0000597}
598
599
600/****************************************************************
601 * *
602 * Initialization Routines *
603 * *
604 ****************************************************************/
605
Daniel Veillard8f621982000-03-20 13:07:15 +0000606#if defined(DEBUG_MEMORY_LOCATION) | defined(DEBUG_MEMORY)
607xmlFreeFunc xmlFree = (xmlFreeFunc) xmlMemFree;
608xmlMallocFunc xmlMalloc = (xmlMallocFunc) xmlMemMalloc;
609xmlReallocFunc xmlRealloc = (xmlReallocFunc) xmlMemRealloc;
610xmlStrdupFunc xmlMemStrdup = (xmlStrdupFunc) xmlMemoryStrdup;
611#else
612xmlFreeFunc xmlFree = (xmlFreeFunc) free;
613xmlMallocFunc xmlMalloc = (xmlMallocFunc) malloc;
614xmlReallocFunc xmlRealloc = (xmlReallocFunc) realloc;
615xmlStrdupFunc xmlMemStrdup = (xmlStrdupFunc) strdup;
616#endif
617
Daniel Veillard6454aec1999-09-02 22:04:43 +0000618/**
619 * xmlInitMemory:
620 *
621 * Initialize the memory layer.
Daniel Veillard00fdf371999-10-08 09:40:39 +0000622 *
623 * Returns 0 on success
Daniel Veillard6454aec1999-09-02 22:04:43 +0000624 */
625
Daniel Veillard8f621982000-03-20 13:07:15 +0000626static int xmlInitMemoryDone = 0;
Daniel Veillard6454aec1999-09-02 22:04:43 +0000627
628int
629xmlInitMemory(void)
630{
631 int ret;
Daniel Veillard7c1206f1999-10-14 09:10:25 +0000632
633#ifdef HAVE_STDLIB_H
634 char *breakpoint;
Daniel Veillard8f621982000-03-20 13:07:15 +0000635#endif
Daniel Veillard7c1206f1999-10-14 09:10:25 +0000636
Daniel Veillard8f621982000-03-20 13:07:15 +0000637 if (xmlInitMemoryDone) return(-1);
638
639#ifdef HAVE_STDLIB_H
Daniel Veillard7c1206f1999-10-14 09:10:25 +0000640 breakpoint = getenv("XML_MEM_BREAKPOINT");
641 if (breakpoint != NULL) {
642 sscanf(breakpoint, "%d", &xmlMemStopAtBlock);
643 }
644#endif
Daniel Veillard6454aec1999-09-02 22:04:43 +0000645
646#ifdef DEBUG_MEMORY
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000647 xmlGenericError(xmlGenericErrorContext,
648 "xmlInitMemory() Ok\n");
Daniel Veillard6454aec1999-09-02 22:04:43 +0000649#endif
650 ret = 0;
651 return(ret);
652}
653
Daniel Veillard8f621982000-03-20 13:07:15 +0000654/**
655 * xmlMemSetup:
656 * @freeFunc: the free() function to use
657 * @mallocFunc: the malloc() function to use
658 * @reallocFunc: the realloc() function to use
659 * @strdupFunc: the strdup() function to use
660 *
661 * Override the default memory access functions with a new set
662 * This has to be called before any other libxml routines !
663 *
664 * Should this be blocked if there was already some allocations
665 * done ?
666 *
667 * Returns 0 on success
668 */
669int
670xmlMemSetup(xmlFreeFunc freeFunc, xmlMallocFunc mallocFunc,
671 xmlReallocFunc reallocFunc, xmlStrdupFunc strdupFunc) {
Daniel Veillard36650692000-07-21 15:16:39 +0000672 if (freeFunc == NULL)
Daniel Veillard8f621982000-03-20 13:07:15 +0000673 return(-1);
Daniel Veillard36650692000-07-21 15:16:39 +0000674 if (mallocFunc == NULL)
Daniel Veillard8f621982000-03-20 13:07:15 +0000675 return(-1);
Daniel Veillard36650692000-07-21 15:16:39 +0000676 if (reallocFunc == NULL)
Daniel Veillard8f621982000-03-20 13:07:15 +0000677 return(-1);
Daniel Veillard36650692000-07-21 15:16:39 +0000678 if (strdupFunc == NULL)
Daniel Veillard8f621982000-03-20 13:07:15 +0000679 return(-1);
680 xmlFree = freeFunc;
681 xmlMalloc = mallocFunc;
682 xmlRealloc = reallocFunc;
683 xmlMemStrdup = strdupFunc;
684 return(0);
685}
686
687/**
688 * xmlMemGet:
689 * @freeFunc: the free() function in use
690 * @mallocFunc: the malloc() function in use
691 * @reallocFunc: the realloc() function in use
692 * @strdupFunc: the strdup() function in use
693 *
694 * Return the memory access functions set currently in use
695 *
696 * Returns 0 on success
697 */
698int
699xmlMemGet(xmlFreeFunc *freeFunc, xmlMallocFunc *mallocFunc,
700 xmlReallocFunc *reallocFunc, xmlStrdupFunc *strdupFunc) {
701 if (freeFunc != NULL) *freeFunc = xmlFree;
702 if (mallocFunc != NULL) *mallocFunc = xmlMalloc;
703 if (reallocFunc != NULL) *reallocFunc = xmlRealloc;
704 if (strdupFunc != NULL) *strdupFunc = xmlMemStrdup;
705 return(0);
706}
707