blob: 57a7ce59c8f3d115f4c1f4fe0d862d8bda627ff8 [file] [log] [blame]
Owen Taylor3473f882001-02-23 17:55:21 +00001/*
Daniel Veillard26908ab2002-01-01 16:50:03 +00002 * xmlmemory.c: libxml memory allocator wrapper.
Owen Taylor3473f882001-02-23 17:55:21 +00003 *
Daniel Veillardc5d64342001-06-24 12:13:24 +00004 * daniel@veillard.com
Owen Taylor3473f882001-02-23 17:55:21 +00005 */
6
Bjorn Reese70a9da52001-04-21 16:57:29 +00007#include "libxml.h"
Owen Taylor3473f882001-02-23 17:55:21 +00008
Owen Taylor3473f882001-02-23 17:55:21 +00009#include <string.h>
10
11#ifdef HAVE_SYS_TYPES_H
12#include <sys/types.h>
13#endif
14#ifdef HAVE_TIME_H
15#include <time.h>
16#endif
17#ifdef HAVE_MALLOC_H
18#include <malloc.h>
19#endif
20#ifdef HAVE_STDLIB_H
21#include <stdlib.h>
22#endif
23#ifdef HAVE_CTYPE_H
24#include <ctype.h>
25#endif
26
Daniel Veillard70cab352002-02-06 16:06:58 +000027/**
28 * MEM_LIST:
29 *
30 * keep track of all allocated blocks for error reporting
31 * Always build the memory list !
32 */
33#ifndef MEM_LIST
34#define MEM_LIST /* keep a list of all the allocated memory blocks */
35#endif
Owen Taylor3473f882001-02-23 17:55:21 +000036
37#include <libxml/xmlmemory.h>
Daniel Veillardd0463562001-10-13 09:15:48 +000038#include <libxml/globals.h>
Owen Taylor3473f882001-02-23 17:55:21 +000039#include <libxml/xmlerror.h>
40
Daniel Veillard56a4cb82001-03-24 17:00:36 +000041void xmlMallocBreakpoint(void);
Daniel Veillard8599e702001-07-17 21:38:51 +000042void * xmlMemMalloc(size_t size);
43void * xmlMallocLoc(size_t size, const char * file, int line);
44void * xmlMemRealloc(void *ptr,size_t size);
Daniel Veillard56a4cb82001-03-24 17:00:36 +000045void xmlMemFree(void *ptr);
46char * xmlMemoryStrdup(const char *str);
47
48/************************************************************************
49 * *
50 * Macros, variables and associated types *
51 * *
52 ************************************************************************/
53
54
Owen Taylor3473f882001-02-23 17:55:21 +000055#ifdef xmlMalloc
56#undef xmlMalloc
57#endif
58#ifdef xmlRealloc
59#undef xmlRealloc
60#endif
61#ifdef xmlMemStrdup
62#undef xmlMemStrdup
63#endif
64
65
66/*
67 * Each of the blocks allocated begin with a header containing informations
68 */
69
70#define MEMTAG 0x5aa5
71
72#define MALLOC_TYPE 1
73#define REALLOC_TYPE 2
74#define STRDUP_TYPE 3
75
76typedef struct memnod {
77 unsigned int mh_tag;
78 unsigned int mh_type;
79 unsigned long mh_number;
80 size_t mh_size;
81#ifdef MEM_LIST
82 struct memnod *mh_next;
83 struct memnod *mh_prev;
84#endif
85 const char *mh_file;
86 unsigned int mh_line;
87} MEMHDR;
88
89
90#ifdef SUN4
91#define ALIGN_SIZE 16
92#else
93#define ALIGN_SIZE sizeof(double)
94#endif
95#define HDR_SIZE sizeof(MEMHDR)
96#define RESERVE_SIZE (((HDR_SIZE + (ALIGN_SIZE-1)) \
97 / ALIGN_SIZE ) * ALIGN_SIZE)
98
99
100#define CLIENT_2_HDR(a) ((MEMHDR *) (((char *) (a)) - RESERVE_SIZE))
101#define HDR_2_CLIENT(a) ((void *) (((char *) (a)) + RESERVE_SIZE))
102
103
104static unsigned long debugMemSize = 0;
105static unsigned long debugMaxMemSize = 0;
106static int block=0;
Daniel Veillardb44025c2001-10-11 22:55:55 +0000107static int xmlMemStopAtBlock = 0;
108static void *xmlMemTraceBlockAt = NULL;
109static int xmlMemInitialized = 0;
Owen Taylor3473f882001-02-23 17:55:21 +0000110#ifdef MEM_LIST
111static MEMHDR *memlist = NULL;
112#endif
113
114void debugmem_tag_error(void *addr);
115#ifdef MEM_LIST
116void debugmem_list_add(MEMHDR *);
117void debugmem_list_delete(MEMHDR *);
118#endif
119#define Mem_Tag_Err(a) debugmem_tag_error(a);
120
121#ifndef TEST_POINT
122#define TEST_POINT
123#endif
124
125/**
126 * xmlMallocBreakpoint:
127 *
128 * Breakpoint to use in conjunction with xmlMemStopAtBlock. When the block
129 * number reaches the specified value this function is called. One need to add a breakpoint
130 * to it to get the context in which the given block is allocated.
131 */
132
133void
134xmlMallocBreakpoint(void) {
135 xmlGenericError(xmlGenericErrorContext,
136 "xmlMallocBreakpoint reached on block %d\n", xmlMemStopAtBlock);
137}
138
139/**
140 * xmlMallocLoc:
141 * @size: an int specifying the size in byte to allocate.
142 * @file: the file name or NULL
143 * @line: the line number
144 *
145 * a malloc() equivalent, with logging of the allocation info.
146 *
147 * Returns a pointer to the allocated area or NULL in case of lack of memory.
148 */
149
150void *
Daniel Veillard8599e702001-07-17 21:38:51 +0000151xmlMallocLoc(size_t size, const char * file, int line)
Owen Taylor3473f882001-02-23 17:55:21 +0000152{
153 MEMHDR *p;
Daniel Veillard7d7e3792001-07-30 13:42:13 +0000154 void *ret;
Owen Taylor3473f882001-02-23 17:55:21 +0000155
156 if (!xmlMemInitialized) xmlInitMemory();
157#ifdef DEBUG_MEMORY
158 xmlGenericError(xmlGenericErrorContext,
159 "Malloc(%d)\n",size);
160#endif
161
162 TEST_POINT
163
164 p = (MEMHDR *) malloc(RESERVE_SIZE+size);
165
166 if (!p) {
167 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard26908ab2002-01-01 16:50:03 +0000168 "xmlMallocLoc : Out of free space\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000169 xmlMemoryDump();
170 return(NULL);
171 }
172 p->mh_tag = MEMTAG;
173 p->mh_number = ++block;
174 p->mh_size = size;
175 p->mh_type = MALLOC_TYPE;
176 p->mh_file = file;
177 p->mh_line = line;
178 debugMemSize += size;
179 if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize;
180#ifdef MEM_LIST
181 debugmem_list_add(p);
182#endif
183
184#ifdef DEBUG_MEMORY
185 xmlGenericError(xmlGenericErrorContext,
186 "Malloc(%d) Ok\n",size);
187#endif
188
189 if (xmlMemStopAtBlock == block) xmlMallocBreakpoint();
190
Daniel Veillard7d7e3792001-07-30 13:42:13 +0000191 ret = HDR_2_CLIENT(p);
192
193 if (xmlMemTraceBlockAt == ret) {
194 xmlGenericError(xmlGenericErrorContext,
195 "%p : Malloc(%d) Ok\n", xmlMemTraceBlockAt, size);
196 xmlMallocBreakpoint();
197 }
198
Owen Taylor3473f882001-02-23 17:55:21 +0000199 TEST_POINT
200
Daniel Veillard7d7e3792001-07-30 13:42:13 +0000201 return(ret);
Owen Taylor3473f882001-02-23 17:55:21 +0000202}
203
204/**
205 * xmlMemMalloc:
206 * @size: an int specifying the size in byte to allocate.
207 *
208 * a malloc() equivalent, with logging of the allocation info.
209 *
210 * Returns a pointer to the allocated area or NULL in case of lack of memory.
211 */
212
213void *
Daniel Veillard8599e702001-07-17 21:38:51 +0000214xmlMemMalloc(size_t size)
Owen Taylor3473f882001-02-23 17:55:21 +0000215{
216 return(xmlMallocLoc(size, "none", 0));
217}
218
219/**
220 * xmlReallocLoc:
221 * @ptr: the initial memory block pointer
222 * @size: an int specifying the size in byte to allocate.
223 * @file: the file name or NULL
224 * @line: the line number
225 *
226 * a realloc() equivalent, with logging of the allocation info.
227 *
228 * Returns a pointer to the allocated area or NULL in case of lack of memory.
229 */
230
231void *
Daniel Veillard8599e702001-07-17 21:38:51 +0000232xmlReallocLoc(void *ptr,size_t size, const char * file, int line)
Owen Taylor3473f882001-02-23 17:55:21 +0000233{
234 MEMHDR *p;
235 unsigned long number;
236
237 if (!xmlMemInitialized) xmlInitMemory();
238 TEST_POINT
239
240 p = CLIENT_2_HDR(ptr);
241 number = p->mh_number;
242 if (p->mh_tag != MEMTAG) {
243 Mem_Tag_Err(p);
244 goto error;
245 }
246 p->mh_tag = ~MEMTAG;
247 debugMemSize -= p->mh_size;
248#ifdef MEM_LIST
249 debugmem_list_delete(p);
250#endif
251
252 p = (MEMHDR *) realloc(p,RESERVE_SIZE+size);
253 if (!p) {
254 goto error;
255 }
Daniel Veillard7d7e3792001-07-30 13:42:13 +0000256 if (xmlMemTraceBlockAt == ptr) {
257 xmlGenericError(xmlGenericErrorContext,
258 "%p : Realloced(%d -> %d) Ok\n",
259 xmlMemTraceBlockAt, p->mh_size, size);
260 xmlMallocBreakpoint();
261 }
Owen Taylor3473f882001-02-23 17:55:21 +0000262 p->mh_tag = MEMTAG;
263 p->mh_number = number;
264 p->mh_type = REALLOC_TYPE;
265 p->mh_size = size;
266 p->mh_file = file;
267 p->mh_line = line;
268 debugMemSize += size;
269 if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize;
270#ifdef MEM_LIST
271 debugmem_list_add(p);
272#endif
273
274 TEST_POINT
275
276 return(HDR_2_CLIENT(p));
277
278error:
279 return(NULL);
280}
281
282/**
283 * xmlMemRealloc:
284 * @ptr: the initial memory block pointer
285 * @size: an int specifying the size in byte to allocate.
286 *
287 * a realloc() equivalent, with logging of the allocation info.
288 *
289 * Returns a pointer to the allocated area or NULL in case of lack of memory.
290 */
291
292void *
Daniel Veillard8599e702001-07-17 21:38:51 +0000293xmlMemRealloc(void *ptr,size_t size) {
Owen Taylor3473f882001-02-23 17:55:21 +0000294 return(xmlReallocLoc(ptr, size, "none", 0));
295}
296
297/**
298 * xmlMemFree:
299 * @ptr: the memory block pointer
300 *
301 * a free() equivalent, with error checking.
302 */
303void
304xmlMemFree(void *ptr)
305{
306 MEMHDR *p;
Daniel Veillard92ad2102001-03-27 12:47:33 +0000307 char *target;
Owen Taylor3473f882001-02-23 17:55:21 +0000308
Daniel Veillard7d7e3792001-07-30 13:42:13 +0000309 if (ptr == (void *) -1) {
310 xmlGenericError(xmlGenericErrorContext,
311 "trying to free pointer from freed area\n");
312 goto error;
313 }
314
315 if (xmlMemTraceBlockAt == ptr) {
316 xmlGenericError(xmlGenericErrorContext,
317 "%p : Freed()\n", xmlMemTraceBlockAt);
318 xmlMallocBreakpoint();
319 }
320
Owen Taylor3473f882001-02-23 17:55:21 +0000321 TEST_POINT
322
Daniel Veillard92ad2102001-03-27 12:47:33 +0000323 target = (char *) ptr;
324
Owen Taylor3473f882001-02-23 17:55:21 +0000325 p = CLIENT_2_HDR(ptr);
326 if (p->mh_tag != MEMTAG) {
Daniel Veillard7d7e3792001-07-30 13:42:13 +0000327 Mem_Tag_Err(p);
328 goto error;
Owen Taylor3473f882001-02-23 17:55:21 +0000329 }
330 p->mh_tag = ~MEMTAG;
331 debugMemSize -= p->mh_size;
Daniel Veillard92ad2102001-03-27 12:47:33 +0000332 memset(target, -1, p->mh_size);
Owen Taylor3473f882001-02-23 17:55:21 +0000333
334#ifdef MEM_LIST
335 debugmem_list_delete(p);
336#endif
337 free(p);
338
339 TEST_POINT
340
341 return;
342
343error:
344 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard26908ab2002-01-01 16:50:03 +0000345 "xmlMemFree(%lX) error\n", (unsigned long) ptr);
Daniel Veillard7d7e3792001-07-30 13:42:13 +0000346 xmlMallocBreakpoint();
Owen Taylor3473f882001-02-23 17:55:21 +0000347 return;
348}
349
350/**
351 * xmlMemStrdupLoc:
Daniel Veillard9d06d302002-01-22 18:15:52 +0000352 * @str: the initial string pointer
Owen Taylor3473f882001-02-23 17:55:21 +0000353 * @file: the file name or NULL
354 * @line: the line number
355 *
356 * a strdup() equivalent, with logging of the allocation info.
357 *
Daniel Veillard26908ab2002-01-01 16:50:03 +0000358 * Returns a pointer to the new string or NULL if allocation error occurred.
Owen Taylor3473f882001-02-23 17:55:21 +0000359 */
360
361char *
362xmlMemStrdupLoc(const char *str, const char *file, int line)
363{
364 char *s;
365 size_t size = strlen(str) + 1;
366 MEMHDR *p;
367
368 if (!xmlMemInitialized) xmlInitMemory();
369 TEST_POINT
370
371 p = (MEMHDR *) malloc(RESERVE_SIZE+size);
372 if (!p) {
373 goto error;
374 }
375 p->mh_tag = MEMTAG;
376 p->mh_number = ++block;
377 p->mh_size = size;
378 p->mh_type = STRDUP_TYPE;
379 p->mh_file = file;
380 p->mh_line = line;
381 debugMemSize += size;
382 if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize;
383#ifdef MEM_LIST
384 debugmem_list_add(p);
385#endif
386 s = (char *) HDR_2_CLIENT(p);
387
388 if (xmlMemStopAtBlock == block) xmlMallocBreakpoint();
389
390 if (s != NULL)
391 strcpy(s,str);
392 else
393 goto error;
394
395 TEST_POINT
396
Daniel Veillard7d7e3792001-07-30 13:42:13 +0000397 if (xmlMemTraceBlockAt == s) {
398 xmlGenericError(xmlGenericErrorContext,
399 "%p : Strdup() Ok\n", xmlMemTraceBlockAt);
400 xmlMallocBreakpoint();
401 }
402
Owen Taylor3473f882001-02-23 17:55:21 +0000403 return(s);
404
405error:
406 return(NULL);
407}
408
409/**
410 * xmlMemoryStrdup:
411 * @ptr: the initial string pointer
412 *
413 * a strdup() equivalent, with logging of the allocation info.
414 *
Daniel Veillard26908ab2002-01-01 16:50:03 +0000415 * Returns a pointer to the new string or NULL if allocation error occurred.
Owen Taylor3473f882001-02-23 17:55:21 +0000416 */
417
418char *
419xmlMemoryStrdup(const char *str) {
420 return(xmlMemStrdupLoc(str, "none", 0));
421}
422
423/**
424 * xmlMemUsed:
425 *
Daniel Veillard26908ab2002-01-01 16:50:03 +0000426 * returns the amount of memory currently allocated
Owen Taylor3473f882001-02-23 17:55:21 +0000427 *
428 * Returns an int representing the amount of memory allocated.
429 */
430
431int
432xmlMemUsed(void) {
433 return(debugMemSize);
434}
435
436#ifdef MEM_LIST
437/**
438 * xmlMemContentShow:
439 * @fp: a FILE descriptor used as the output file
440 * @p: a memory block header
441 *
442 * tries to show some content from the memory block
443 */
444
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000445static void
Owen Taylor3473f882001-02-23 17:55:21 +0000446xmlMemContentShow(FILE *fp, MEMHDR *p)
447{
448 int i,j,len = p->mh_size;
449 const char *buf = (const char *) HDR_2_CLIENT(p);
450
451 if (p == NULL) {
452 fprintf(fp, " NULL");
453 return;
454 }
455
456 for (i = 0;i < len;i++) {
457 if (buf[i] == 0) break;
458 if (!isprint(buf[i])) break;
459 }
460 if ((i < 4) && ((buf[i] != 0) || (i == 0))) {
461 if (len >= 4) {
462 MEMHDR *q;
463 void *cur;
464
465 for (j = 0;j < len -3;j += 4) {
466 cur = *((void **) &buf[j]);
467 q = CLIENT_2_HDR(cur);
468 p = memlist;
469 while (p != NULL) {
470 if (p == q) break;
471 p = p->mh_next;
472 }
473 if ((p != NULL) && (p == q)) {
474 fprintf(fp, " pointer to #%lu at index %d",
475 p->mh_number, j);
476 return;
477 }
478 }
479 }
480 } else if ((i == 0) && (buf[i] == 0)) {
481 fprintf(fp," null");
482 } else {
483 if (buf[i] == 0) fprintf(fp," \"%.25s\"", buf);
484 else {
485 fprintf(fp," [");
486 for (j = 0;j < i;j++)
487 fprintf(fp,"%c", buf[j]);
488 fprintf(fp,"]");
489 }
490 }
491}
492#endif
493
494/**
495 * xmlMemShow:
496 * @fp: a FILE descriptor used as the output file
497 * @nr: number of entries to dump
498 *
499 * show a show display of the memory allocated, and dump
500 * the @nr last allocated areas which were not freed
501 */
502
503void
504xmlMemShow(FILE *fp, int nr)
505{
506#ifdef MEM_LIST
507 MEMHDR *p;
508#endif
509
510 if (fp != NULL)
511 fprintf(fp," MEMORY ALLOCATED : %lu, MAX was %lu\n",
512 debugMemSize, debugMaxMemSize);
513#ifdef MEM_LIST
514 if (nr > 0) {
515 fprintf(fp,"NUMBER SIZE TYPE WHERE\n");
516 p = memlist;
517 while ((p) && nr > 0) {
518 fprintf(fp,"%6lu %6u ",p->mh_number,p->mh_size);
519 switch (p->mh_type) {
520 case STRDUP_TYPE:fprintf(fp,"strdup() in ");break;
521 case MALLOC_TYPE:fprintf(fp,"malloc() in ");break;
522 case REALLOC_TYPE:fprintf(fp,"realloc() in ");break;
523 default:fprintf(fp," ??? in ");break;
524 }
525 if (p->mh_file != NULL)
526 fprintf(fp,"%s(%d)", p->mh_file, p->mh_line);
527 if (p->mh_tag != MEMTAG)
528 fprintf(fp," INVALID");
529 xmlMemContentShow(fp, p);
530 fprintf(fp,"\n");
531 nr--;
532 p = p->mh_next;
533 }
534 }
535#endif /* MEM_LIST */
536}
537
538/**
539 * xmlMemDisplay:
540 * @fp: a FILE descriptor used as the output file, if NULL, the result is
541 * written to the file .memorylist
542 *
543 * show in-extenso the memory blocks allocated
544 */
545
546void
547xmlMemDisplay(FILE *fp)
548{
549#ifdef MEM_LIST
550 MEMHDR *p;
551 int idx;
Daniel Veillard7d7e3792001-07-30 13:42:13 +0000552 int nb = 0;
Owen Taylor3473f882001-02-23 17:55:21 +0000553#if defined(HAVE_LOCALTIME) && defined(HAVE_STRFTIME)
554 time_t currentTime;
555 char buf[500];
556 struct tm * tstruct;
557
558 currentTime = time(NULL);
559 tstruct = localtime(&currentTime);
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000560 strftime(buf, sizeof(buf) - 1, "%I:%M:%S %p", tstruct);
Owen Taylor3473f882001-02-23 17:55:21 +0000561 fprintf(fp," %s\n\n", buf);
562#endif
563
564
565 fprintf(fp," MEMORY ALLOCATED : %lu, MAX was %lu\n",
566 debugMemSize, debugMaxMemSize);
567 fprintf(fp,"BLOCK NUMBER SIZE TYPE\n");
568 idx = 0;
569 p = memlist;
570 while (p) {
571 fprintf(fp,"%-5u %6lu %6u ",idx++,p->mh_number,p->mh_size);
572 switch (p->mh_type) {
573 case STRDUP_TYPE:fprintf(fp,"strdup() in ");break;
574 case MALLOC_TYPE:fprintf(fp,"malloc() in ");break;
575 case REALLOC_TYPE:fprintf(fp,"realloc() in ");break;
576 default:fprintf(fp," ??? in ");break;
577 }
578 if (p->mh_file != NULL) fprintf(fp,"%s(%d)", p->mh_file, p->mh_line);
579 if (p->mh_tag != MEMTAG)
580 fprintf(fp," INVALID");
Daniel Veillard7d7e3792001-07-30 13:42:13 +0000581 nb++;
582 if (nb < 100)
583 xmlMemContentShow(fp, p);
584 else
585 fprintf(fp," skip");
586
Owen Taylor3473f882001-02-23 17:55:21 +0000587 fprintf(fp,"\n");
588 p = p->mh_next;
589 }
590#else
591 fprintf(fp,"Memory list not compiled (MEM_LIST not defined !)\n");
592#endif
593}
594
595#ifdef MEM_LIST
596
597void debugmem_list_add(MEMHDR *p)
598{
599 p->mh_next = memlist;
600 p->mh_prev = NULL;
601 if (memlist) memlist->mh_prev = p;
602 memlist = p;
603#ifdef MEM_LIST_DEBUG
604 if (stderr)
605 Mem_Display(stderr);
606#endif
607}
608
609void debugmem_list_delete(MEMHDR *p)
610{
611 if (p->mh_next)
612 p->mh_next->mh_prev = p->mh_prev;
613 if (p->mh_prev)
614 p->mh_prev->mh_next = p->mh_next;
615 else memlist = p->mh_next;
616#ifdef MEM_LIST_DEBUG
617 if (stderr)
618 Mem_Display(stderr);
619#endif
620}
621
622#endif
623
624/*
625 * debugmem_tag_error : internal error function.
626 */
627
628void debugmem_tag_error(void *p)
629{
630 xmlGenericError(xmlGenericErrorContext,
631 "Memory tag error occurs :%p \n\t bye\n", p);
632#ifdef MEM_LIST
633 if (stderr)
634 xmlMemDisplay(stderr);
635#endif
636}
637
Daniel Veillardb44025c2001-10-11 22:55:55 +0000638static FILE *xmlMemoryDumpFile = NULL;
Owen Taylor3473f882001-02-23 17:55:21 +0000639
640
641/**
642 * xmlMemoryDump:
643 *
644 * Dump in-extenso the memory blocks allocated to the file .memorylist
645 */
646
647void
648xmlMemoryDump(void)
649{
Owen Taylor3473f882001-02-23 17:55:21 +0000650 FILE *dump;
651
652 dump = fopen(".memdump", "w");
Daniel Veillardcd337f02001-11-22 18:20:37 +0000653 if (dump == NULL)
654 xmlMemoryDumpFile = stderr;
Owen Taylor3473f882001-02-23 17:55:21 +0000655 else xmlMemoryDumpFile = dump;
656
657 xmlMemDisplay(xmlMemoryDumpFile);
658
659 if (dump != NULL) fclose(dump);
Owen Taylor3473f882001-02-23 17:55:21 +0000660}
661
662
663/****************************************************************
664 * *
665 * Initialization Routines *
666 * *
667 ****************************************************************/
668
Owen Taylor3473f882001-02-23 17:55:21 +0000669/**
670 * xmlInitMemory:
671 *
672 * Initialize the memory layer.
673 *
674 * Returns 0 on success
675 */
676
677static int xmlInitMemoryDone = 0;
678
679int
680xmlInitMemory(void)
681{
682 int ret;
683
684#ifdef HAVE_STDLIB_H
685 char *breakpoint;
686#endif
687
688 if (xmlInitMemoryDone) return(-1);
689
690#ifdef HAVE_STDLIB_H
691 breakpoint = getenv("XML_MEM_BREAKPOINT");
692 if (breakpoint != NULL) {
693 sscanf(breakpoint, "%d", &xmlMemStopAtBlock);
694 }
695#endif
Daniel Veillard7d7e3792001-07-30 13:42:13 +0000696#ifdef HAVE_STDLIB_H
697 breakpoint = getenv("XML_MEM_TRACE");
698 if (breakpoint != NULL) {
699 sscanf(breakpoint, "%p", &xmlMemTraceBlockAt);
700 }
701#endif
Owen Taylor3473f882001-02-23 17:55:21 +0000702
703#ifdef DEBUG_MEMORY
704 xmlGenericError(xmlGenericErrorContext,
705 "xmlInitMemory() Ok\n");
706#endif
707 ret = 0;
708 return(ret);
709}
710
711/**
712 * xmlMemSetup:
713 * @freeFunc: the free() function to use
714 * @mallocFunc: the malloc() function to use
715 * @reallocFunc: the realloc() function to use
716 * @strdupFunc: the strdup() function to use
717 *
718 * Override the default memory access functions with a new set
719 * This has to be called before any other libxml routines !
720 *
721 * Should this be blocked if there was already some allocations
722 * done ?
723 *
724 * Returns 0 on success
725 */
726int
727xmlMemSetup(xmlFreeFunc freeFunc, xmlMallocFunc mallocFunc,
728 xmlReallocFunc reallocFunc, xmlStrdupFunc strdupFunc) {
729 if (freeFunc == NULL)
730 return(-1);
731 if (mallocFunc == NULL)
732 return(-1);
733 if (reallocFunc == NULL)
734 return(-1);
735 if (strdupFunc == NULL)
736 return(-1);
737 xmlFree = freeFunc;
738 xmlMalloc = mallocFunc;
739 xmlRealloc = reallocFunc;
740 xmlMemStrdup = strdupFunc;
741 return(0);
742}
743
744/**
745 * xmlMemGet:
746 * @freeFunc: the free() function in use
747 * @mallocFunc: the malloc() function in use
748 * @reallocFunc: the realloc() function in use
749 * @strdupFunc: the strdup() function in use
750 *
751 * Return the memory access functions set currently in use
752 *
753 * Returns 0 on success
754 */
755int
756xmlMemGet(xmlFreeFunc *freeFunc, xmlMallocFunc *mallocFunc,
757 xmlReallocFunc *reallocFunc, xmlStrdupFunc *strdupFunc) {
758 if (freeFunc != NULL) *freeFunc = xmlFree;
759 if (mallocFunc != NULL) *mallocFunc = xmlMalloc;
760 if (reallocFunc != NULL) *reallocFunc = xmlRealloc;
761 if (strdupFunc != NULL) *strdupFunc = xmlMemStrdup;
762 return(0);
763}
764