blob: afb8b8aae2724cdfb80301ec297c965fdbb52fec [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
27
28#include <libxml/xmlmemory.h>
Daniel Veillardd0463562001-10-13 09:15:48 +000029#include <libxml/globals.h>
Owen Taylor3473f882001-02-23 17:55:21 +000030#include <libxml/xmlerror.h>
31
Daniel Veillard56a4cb82001-03-24 17:00:36 +000032void xmlMallocBreakpoint(void);
Daniel Veillard8599e702001-07-17 21:38:51 +000033void * xmlMemMalloc(size_t size);
34void * xmlMallocLoc(size_t size, const char * file, int line);
35void * xmlMemRealloc(void *ptr,size_t size);
Daniel Veillard56a4cb82001-03-24 17:00:36 +000036void xmlMemFree(void *ptr);
37char * xmlMemoryStrdup(const char *str);
38
39/************************************************************************
40 * *
41 * Macros, variables and associated types *
42 * *
43 ************************************************************************/
44
45
Owen Taylor3473f882001-02-23 17:55:21 +000046#ifdef xmlMalloc
47#undef xmlMalloc
48#endif
49#ifdef xmlRealloc
50#undef xmlRealloc
51#endif
52#ifdef xmlMemStrdup
53#undef xmlMemStrdup
54#endif
55
56
57/*
58 * Each of the blocks allocated begin with a header containing informations
59 */
60
61#define MEMTAG 0x5aa5
62
63#define MALLOC_TYPE 1
64#define REALLOC_TYPE 2
65#define STRDUP_TYPE 3
66
67typedef struct memnod {
68 unsigned int mh_tag;
69 unsigned int mh_type;
70 unsigned long mh_number;
71 size_t mh_size;
72#ifdef MEM_LIST
73 struct memnod *mh_next;
74 struct memnod *mh_prev;
75#endif
76 const char *mh_file;
77 unsigned int mh_line;
78} MEMHDR;
79
80
81#ifdef SUN4
82#define ALIGN_SIZE 16
83#else
84#define ALIGN_SIZE sizeof(double)
85#endif
86#define HDR_SIZE sizeof(MEMHDR)
87#define RESERVE_SIZE (((HDR_SIZE + (ALIGN_SIZE-1)) \
88 / ALIGN_SIZE ) * ALIGN_SIZE)
89
90
91#define CLIENT_2_HDR(a) ((MEMHDR *) (((char *) (a)) - RESERVE_SIZE))
92#define HDR_2_CLIENT(a) ((void *) (((char *) (a)) + RESERVE_SIZE))
93
94
95static unsigned long debugMemSize = 0;
96static unsigned long debugMaxMemSize = 0;
97static int block=0;
Daniel Veillardb44025c2001-10-11 22:55:55 +000098static int xmlMemStopAtBlock = 0;
99static void *xmlMemTraceBlockAt = NULL;
100static int xmlMemInitialized = 0;
Owen Taylor3473f882001-02-23 17:55:21 +0000101#ifdef MEM_LIST
102static MEMHDR *memlist = NULL;
103#endif
104
105void debugmem_tag_error(void *addr);
106#ifdef MEM_LIST
107void debugmem_list_add(MEMHDR *);
108void debugmem_list_delete(MEMHDR *);
109#endif
110#define Mem_Tag_Err(a) debugmem_tag_error(a);
111
112#ifndef TEST_POINT
113#define TEST_POINT
114#endif
115
116/**
117 * xmlMallocBreakpoint:
118 *
119 * Breakpoint to use in conjunction with xmlMemStopAtBlock. When the block
120 * number reaches the specified value this function is called. One need to add a breakpoint
121 * to it to get the context in which the given block is allocated.
122 */
123
124void
125xmlMallocBreakpoint(void) {
126 xmlGenericError(xmlGenericErrorContext,
127 "xmlMallocBreakpoint reached on block %d\n", xmlMemStopAtBlock);
128}
129
130/**
131 * xmlMallocLoc:
132 * @size: an int specifying the size in byte to allocate.
133 * @file: the file name or NULL
134 * @line: the line number
135 *
136 * a malloc() equivalent, with logging of the allocation info.
137 *
138 * Returns a pointer to the allocated area or NULL in case of lack of memory.
139 */
140
141void *
Daniel Veillard8599e702001-07-17 21:38:51 +0000142xmlMallocLoc(size_t size, const char * file, int line)
Owen Taylor3473f882001-02-23 17:55:21 +0000143{
144 MEMHDR *p;
Daniel Veillard7d7e3792001-07-30 13:42:13 +0000145 void *ret;
Owen Taylor3473f882001-02-23 17:55:21 +0000146
147 if (!xmlMemInitialized) xmlInitMemory();
148#ifdef DEBUG_MEMORY
149 xmlGenericError(xmlGenericErrorContext,
150 "Malloc(%d)\n",size);
151#endif
152
153 TEST_POINT
154
155 p = (MEMHDR *) malloc(RESERVE_SIZE+size);
156
157 if (!p) {
158 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard26908ab2002-01-01 16:50:03 +0000159 "xmlMallocLoc : Out of free space\n");
Owen Taylor3473f882001-02-23 17:55:21 +0000160 xmlMemoryDump();
161 return(NULL);
162 }
163 p->mh_tag = MEMTAG;
164 p->mh_number = ++block;
165 p->mh_size = size;
166 p->mh_type = MALLOC_TYPE;
167 p->mh_file = file;
168 p->mh_line = line;
169 debugMemSize += size;
170 if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize;
171#ifdef MEM_LIST
172 debugmem_list_add(p);
173#endif
174
175#ifdef DEBUG_MEMORY
176 xmlGenericError(xmlGenericErrorContext,
177 "Malloc(%d) Ok\n",size);
178#endif
179
180 if (xmlMemStopAtBlock == block) xmlMallocBreakpoint();
181
Daniel Veillard7d7e3792001-07-30 13:42:13 +0000182 ret = HDR_2_CLIENT(p);
183
184 if (xmlMemTraceBlockAt == ret) {
185 xmlGenericError(xmlGenericErrorContext,
186 "%p : Malloc(%d) Ok\n", xmlMemTraceBlockAt, size);
187 xmlMallocBreakpoint();
188 }
189
Owen Taylor3473f882001-02-23 17:55:21 +0000190 TEST_POINT
191
Daniel Veillard7d7e3792001-07-30 13:42:13 +0000192 return(ret);
Owen Taylor3473f882001-02-23 17:55:21 +0000193}
194
195/**
196 * xmlMemMalloc:
197 * @size: an int specifying the size in byte to allocate.
198 *
199 * a malloc() equivalent, with logging of the allocation info.
200 *
201 * Returns a pointer to the allocated area or NULL in case of lack of memory.
202 */
203
204void *
Daniel Veillard8599e702001-07-17 21:38:51 +0000205xmlMemMalloc(size_t size)
Owen Taylor3473f882001-02-23 17:55:21 +0000206{
207 return(xmlMallocLoc(size, "none", 0));
208}
209
210/**
211 * xmlReallocLoc:
212 * @ptr: the initial memory block pointer
213 * @size: an int specifying the size in byte to allocate.
214 * @file: the file name or NULL
215 * @line: the line number
216 *
217 * a realloc() equivalent, with logging of the allocation info.
218 *
219 * Returns a pointer to the allocated area or NULL in case of lack of memory.
220 */
221
222void *
Daniel Veillard8599e702001-07-17 21:38:51 +0000223xmlReallocLoc(void *ptr,size_t size, const char * file, int line)
Owen Taylor3473f882001-02-23 17:55:21 +0000224{
225 MEMHDR *p;
226 unsigned long number;
227
228 if (!xmlMemInitialized) xmlInitMemory();
229 TEST_POINT
230
231 p = CLIENT_2_HDR(ptr);
232 number = p->mh_number;
233 if (p->mh_tag != MEMTAG) {
234 Mem_Tag_Err(p);
235 goto error;
236 }
237 p->mh_tag = ~MEMTAG;
238 debugMemSize -= p->mh_size;
239#ifdef MEM_LIST
240 debugmem_list_delete(p);
241#endif
242
243 p = (MEMHDR *) realloc(p,RESERVE_SIZE+size);
244 if (!p) {
245 goto error;
246 }
Daniel Veillard7d7e3792001-07-30 13:42:13 +0000247 if (xmlMemTraceBlockAt == ptr) {
248 xmlGenericError(xmlGenericErrorContext,
249 "%p : Realloced(%d -> %d) Ok\n",
250 xmlMemTraceBlockAt, p->mh_size, size);
251 xmlMallocBreakpoint();
252 }
Owen Taylor3473f882001-02-23 17:55:21 +0000253 p->mh_tag = MEMTAG;
254 p->mh_number = number;
255 p->mh_type = REALLOC_TYPE;
256 p->mh_size = size;
257 p->mh_file = file;
258 p->mh_line = line;
259 debugMemSize += size;
260 if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize;
261#ifdef MEM_LIST
262 debugmem_list_add(p);
263#endif
264
265 TEST_POINT
266
267 return(HDR_2_CLIENT(p));
268
269error:
270 return(NULL);
271}
272
273/**
274 * xmlMemRealloc:
275 * @ptr: the initial memory block pointer
276 * @size: an int specifying the size in byte to allocate.
277 *
278 * a realloc() equivalent, with logging of the allocation info.
279 *
280 * Returns a pointer to the allocated area or NULL in case of lack of memory.
281 */
282
283void *
Daniel Veillard8599e702001-07-17 21:38:51 +0000284xmlMemRealloc(void *ptr,size_t size) {
Owen Taylor3473f882001-02-23 17:55:21 +0000285 return(xmlReallocLoc(ptr, size, "none", 0));
286}
287
288/**
289 * xmlMemFree:
290 * @ptr: the memory block pointer
291 *
292 * a free() equivalent, with error checking.
293 */
294void
295xmlMemFree(void *ptr)
296{
297 MEMHDR *p;
Daniel Veillard92ad2102001-03-27 12:47:33 +0000298 char *target;
Owen Taylor3473f882001-02-23 17:55:21 +0000299
Daniel Veillard7d7e3792001-07-30 13:42:13 +0000300 if (ptr == (void *) -1) {
301 xmlGenericError(xmlGenericErrorContext,
302 "trying to free pointer from freed area\n");
303 goto error;
304 }
305
306 if (xmlMemTraceBlockAt == ptr) {
307 xmlGenericError(xmlGenericErrorContext,
308 "%p : Freed()\n", xmlMemTraceBlockAt);
309 xmlMallocBreakpoint();
310 }
311
Owen Taylor3473f882001-02-23 17:55:21 +0000312 TEST_POINT
313
Daniel Veillard92ad2102001-03-27 12:47:33 +0000314 target = (char *) ptr;
315
Owen Taylor3473f882001-02-23 17:55:21 +0000316 p = CLIENT_2_HDR(ptr);
317 if (p->mh_tag != MEMTAG) {
Daniel Veillard7d7e3792001-07-30 13:42:13 +0000318 Mem_Tag_Err(p);
319 goto error;
Owen Taylor3473f882001-02-23 17:55:21 +0000320 }
321 p->mh_tag = ~MEMTAG;
322 debugMemSize -= p->mh_size;
Daniel Veillard92ad2102001-03-27 12:47:33 +0000323 memset(target, -1, p->mh_size);
Owen Taylor3473f882001-02-23 17:55:21 +0000324
325#ifdef MEM_LIST
326 debugmem_list_delete(p);
327#endif
328 free(p);
329
330 TEST_POINT
331
332 return;
333
334error:
335 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard26908ab2002-01-01 16:50:03 +0000336 "xmlMemFree(%lX) error\n", (unsigned long) ptr);
Daniel Veillard7d7e3792001-07-30 13:42:13 +0000337 xmlMallocBreakpoint();
Owen Taylor3473f882001-02-23 17:55:21 +0000338 return;
339}
340
341/**
342 * xmlMemStrdupLoc:
Daniel Veillard9d06d302002-01-22 18:15:52 +0000343 * @str: the initial string pointer
Owen Taylor3473f882001-02-23 17:55:21 +0000344 * @file: the file name or NULL
345 * @line: the line number
346 *
347 * a strdup() equivalent, with logging of the allocation info.
348 *
Daniel Veillard26908ab2002-01-01 16:50:03 +0000349 * Returns a pointer to the new string or NULL if allocation error occurred.
Owen Taylor3473f882001-02-23 17:55:21 +0000350 */
351
352char *
353xmlMemStrdupLoc(const char *str, const char *file, int line)
354{
355 char *s;
356 size_t size = strlen(str) + 1;
357 MEMHDR *p;
358
359 if (!xmlMemInitialized) xmlInitMemory();
360 TEST_POINT
361
362 p = (MEMHDR *) malloc(RESERVE_SIZE+size);
363 if (!p) {
364 goto error;
365 }
366 p->mh_tag = MEMTAG;
367 p->mh_number = ++block;
368 p->mh_size = size;
369 p->mh_type = STRDUP_TYPE;
370 p->mh_file = file;
371 p->mh_line = line;
372 debugMemSize += size;
373 if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize;
374#ifdef MEM_LIST
375 debugmem_list_add(p);
376#endif
377 s = (char *) HDR_2_CLIENT(p);
378
379 if (xmlMemStopAtBlock == block) xmlMallocBreakpoint();
380
381 if (s != NULL)
382 strcpy(s,str);
383 else
384 goto error;
385
386 TEST_POINT
387
Daniel Veillard7d7e3792001-07-30 13:42:13 +0000388 if (xmlMemTraceBlockAt == s) {
389 xmlGenericError(xmlGenericErrorContext,
390 "%p : Strdup() Ok\n", xmlMemTraceBlockAt);
391 xmlMallocBreakpoint();
392 }
393
Owen Taylor3473f882001-02-23 17:55:21 +0000394 return(s);
395
396error:
397 return(NULL);
398}
399
400/**
401 * xmlMemoryStrdup:
402 * @ptr: the initial string pointer
403 *
404 * a strdup() equivalent, with logging of the allocation info.
405 *
Daniel Veillard26908ab2002-01-01 16:50:03 +0000406 * Returns a pointer to the new string or NULL if allocation error occurred.
Owen Taylor3473f882001-02-23 17:55:21 +0000407 */
408
409char *
410xmlMemoryStrdup(const char *str) {
411 return(xmlMemStrdupLoc(str, "none", 0));
412}
413
414/**
415 * xmlMemUsed:
416 *
Daniel Veillard26908ab2002-01-01 16:50:03 +0000417 * returns the amount of memory currently allocated
Owen Taylor3473f882001-02-23 17:55:21 +0000418 *
419 * Returns an int representing the amount of memory allocated.
420 */
421
422int
423xmlMemUsed(void) {
424 return(debugMemSize);
425}
426
427#ifdef MEM_LIST
428/**
429 * xmlMemContentShow:
430 * @fp: a FILE descriptor used as the output file
431 * @p: a memory block header
432 *
433 * tries to show some content from the memory block
434 */
435
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000436static void
Owen Taylor3473f882001-02-23 17:55:21 +0000437xmlMemContentShow(FILE *fp, MEMHDR *p)
438{
439 int i,j,len = p->mh_size;
440 const char *buf = (const char *) HDR_2_CLIENT(p);
441
442 if (p == NULL) {
443 fprintf(fp, " NULL");
444 return;
445 }
446
447 for (i = 0;i < len;i++) {
448 if (buf[i] == 0) break;
449 if (!isprint(buf[i])) break;
450 }
451 if ((i < 4) && ((buf[i] != 0) || (i == 0))) {
452 if (len >= 4) {
453 MEMHDR *q;
454 void *cur;
455
456 for (j = 0;j < len -3;j += 4) {
457 cur = *((void **) &buf[j]);
458 q = CLIENT_2_HDR(cur);
459 p = memlist;
460 while (p != NULL) {
461 if (p == q) break;
462 p = p->mh_next;
463 }
464 if ((p != NULL) && (p == q)) {
465 fprintf(fp, " pointer to #%lu at index %d",
466 p->mh_number, j);
467 return;
468 }
469 }
470 }
471 } else if ((i == 0) && (buf[i] == 0)) {
472 fprintf(fp," null");
473 } else {
474 if (buf[i] == 0) fprintf(fp," \"%.25s\"", buf);
475 else {
476 fprintf(fp," [");
477 for (j = 0;j < i;j++)
478 fprintf(fp,"%c", buf[j]);
479 fprintf(fp,"]");
480 }
481 }
482}
483#endif
484
485/**
486 * xmlMemShow:
487 * @fp: a FILE descriptor used as the output file
488 * @nr: number of entries to dump
489 *
490 * show a show display of the memory allocated, and dump
491 * the @nr last allocated areas which were not freed
492 */
493
494void
495xmlMemShow(FILE *fp, int nr)
496{
497#ifdef MEM_LIST
498 MEMHDR *p;
499#endif
500
501 if (fp != NULL)
502 fprintf(fp," MEMORY ALLOCATED : %lu, MAX was %lu\n",
503 debugMemSize, debugMaxMemSize);
504#ifdef MEM_LIST
505 if (nr > 0) {
506 fprintf(fp,"NUMBER SIZE TYPE WHERE\n");
507 p = memlist;
508 while ((p) && nr > 0) {
509 fprintf(fp,"%6lu %6u ",p->mh_number,p->mh_size);
510 switch (p->mh_type) {
511 case STRDUP_TYPE:fprintf(fp,"strdup() in ");break;
512 case MALLOC_TYPE:fprintf(fp,"malloc() in ");break;
513 case REALLOC_TYPE:fprintf(fp,"realloc() in ");break;
514 default:fprintf(fp," ??? in ");break;
515 }
516 if (p->mh_file != NULL)
517 fprintf(fp,"%s(%d)", p->mh_file, p->mh_line);
518 if (p->mh_tag != MEMTAG)
519 fprintf(fp," INVALID");
520 xmlMemContentShow(fp, p);
521 fprintf(fp,"\n");
522 nr--;
523 p = p->mh_next;
524 }
525 }
526#endif /* MEM_LIST */
527}
528
529/**
530 * xmlMemDisplay:
531 * @fp: a FILE descriptor used as the output file, if NULL, the result is
532 * written to the file .memorylist
533 *
534 * show in-extenso the memory blocks allocated
535 */
536
537void
538xmlMemDisplay(FILE *fp)
539{
540#ifdef MEM_LIST
541 MEMHDR *p;
542 int idx;
Daniel Veillard7d7e3792001-07-30 13:42:13 +0000543 int nb = 0;
Owen Taylor3473f882001-02-23 17:55:21 +0000544#if defined(HAVE_LOCALTIME) && defined(HAVE_STRFTIME)
545 time_t currentTime;
546 char buf[500];
547 struct tm * tstruct;
548
549 currentTime = time(NULL);
550 tstruct = localtime(&currentTime);
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000551 strftime(buf, sizeof(buf) - 1, "%I:%M:%S %p", tstruct);
Owen Taylor3473f882001-02-23 17:55:21 +0000552 fprintf(fp," %s\n\n", buf);
553#endif
554
555
556 fprintf(fp," MEMORY ALLOCATED : %lu, MAX was %lu\n",
557 debugMemSize, debugMaxMemSize);
558 fprintf(fp,"BLOCK NUMBER SIZE TYPE\n");
559 idx = 0;
560 p = memlist;
561 while (p) {
562 fprintf(fp,"%-5u %6lu %6u ",idx++,p->mh_number,p->mh_size);
563 switch (p->mh_type) {
564 case STRDUP_TYPE:fprintf(fp,"strdup() in ");break;
565 case MALLOC_TYPE:fprintf(fp,"malloc() in ");break;
566 case REALLOC_TYPE:fprintf(fp,"realloc() in ");break;
567 default:fprintf(fp," ??? in ");break;
568 }
569 if (p->mh_file != NULL) fprintf(fp,"%s(%d)", p->mh_file, p->mh_line);
570 if (p->mh_tag != MEMTAG)
571 fprintf(fp," INVALID");
Daniel Veillard7d7e3792001-07-30 13:42:13 +0000572 nb++;
573 if (nb < 100)
574 xmlMemContentShow(fp, p);
575 else
576 fprintf(fp," skip");
577
Owen Taylor3473f882001-02-23 17:55:21 +0000578 fprintf(fp,"\n");
579 p = p->mh_next;
580 }
581#else
582 fprintf(fp,"Memory list not compiled (MEM_LIST not defined !)\n");
583#endif
584}
585
586#ifdef MEM_LIST
587
588void debugmem_list_add(MEMHDR *p)
589{
590 p->mh_next = memlist;
591 p->mh_prev = NULL;
592 if (memlist) memlist->mh_prev = p;
593 memlist = p;
594#ifdef MEM_LIST_DEBUG
595 if (stderr)
596 Mem_Display(stderr);
597#endif
598}
599
600void debugmem_list_delete(MEMHDR *p)
601{
602 if (p->mh_next)
603 p->mh_next->mh_prev = p->mh_prev;
604 if (p->mh_prev)
605 p->mh_prev->mh_next = p->mh_next;
606 else memlist = p->mh_next;
607#ifdef MEM_LIST_DEBUG
608 if (stderr)
609 Mem_Display(stderr);
610#endif
611}
612
613#endif
614
615/*
616 * debugmem_tag_error : internal error function.
617 */
618
619void debugmem_tag_error(void *p)
620{
621 xmlGenericError(xmlGenericErrorContext,
622 "Memory tag error occurs :%p \n\t bye\n", p);
623#ifdef MEM_LIST
624 if (stderr)
625 xmlMemDisplay(stderr);
626#endif
627}
628
Daniel Veillardb44025c2001-10-11 22:55:55 +0000629static FILE *xmlMemoryDumpFile = NULL;
Owen Taylor3473f882001-02-23 17:55:21 +0000630
631
632/**
633 * xmlMemoryDump:
634 *
635 * Dump in-extenso the memory blocks allocated to the file .memorylist
636 */
637
638void
639xmlMemoryDump(void)
640{
641#if defined(DEBUG_MEMORY_LOCATION) | defined(DEBUG_MEMORY)
642 FILE *dump;
643
644 dump = fopen(".memdump", "w");
Daniel Veillardcd337f02001-11-22 18:20:37 +0000645 if (dump == NULL)
646 xmlMemoryDumpFile = stderr;
Owen Taylor3473f882001-02-23 17:55:21 +0000647 else xmlMemoryDumpFile = dump;
648
649 xmlMemDisplay(xmlMemoryDumpFile);
650
651 if (dump != NULL) fclose(dump);
652#endif
653}
654
655
656/****************************************************************
657 * *
658 * Initialization Routines *
659 * *
660 ****************************************************************/
661
Owen Taylor3473f882001-02-23 17:55:21 +0000662/**
663 * xmlInitMemory:
664 *
665 * Initialize the memory layer.
666 *
667 * Returns 0 on success
668 */
669
670static int xmlInitMemoryDone = 0;
671
672int
673xmlInitMemory(void)
674{
675 int ret;
676
677#ifdef HAVE_STDLIB_H
678 char *breakpoint;
679#endif
680
681 if (xmlInitMemoryDone) return(-1);
682
683#ifdef HAVE_STDLIB_H
684 breakpoint = getenv("XML_MEM_BREAKPOINT");
685 if (breakpoint != NULL) {
686 sscanf(breakpoint, "%d", &xmlMemStopAtBlock);
687 }
688#endif
Daniel Veillard7d7e3792001-07-30 13:42:13 +0000689#ifdef HAVE_STDLIB_H
690 breakpoint = getenv("XML_MEM_TRACE");
691 if (breakpoint != NULL) {
692 sscanf(breakpoint, "%p", &xmlMemTraceBlockAt);
693 }
694#endif
Owen Taylor3473f882001-02-23 17:55:21 +0000695
696#ifdef DEBUG_MEMORY
697 xmlGenericError(xmlGenericErrorContext,
698 "xmlInitMemory() Ok\n");
699#endif
700 ret = 0;
701 return(ret);
702}
703
704/**
705 * xmlMemSetup:
706 * @freeFunc: the free() function to use
707 * @mallocFunc: the malloc() function to use
708 * @reallocFunc: the realloc() function to use
709 * @strdupFunc: the strdup() function to use
710 *
711 * Override the default memory access functions with a new set
712 * This has to be called before any other libxml routines !
713 *
714 * Should this be blocked if there was already some allocations
715 * done ?
716 *
717 * Returns 0 on success
718 */
719int
720xmlMemSetup(xmlFreeFunc freeFunc, xmlMallocFunc mallocFunc,
721 xmlReallocFunc reallocFunc, xmlStrdupFunc strdupFunc) {
722 if (freeFunc == NULL)
723 return(-1);
724 if (mallocFunc == NULL)
725 return(-1);
726 if (reallocFunc == NULL)
727 return(-1);
728 if (strdupFunc == NULL)
729 return(-1);
730 xmlFree = freeFunc;
731 xmlMalloc = mallocFunc;
732 xmlRealloc = reallocFunc;
733 xmlMemStrdup = strdupFunc;
734 return(0);
735}
736
737/**
738 * xmlMemGet:
739 * @freeFunc: the free() function in use
740 * @mallocFunc: the malloc() function in use
741 * @reallocFunc: the realloc() function in use
742 * @strdupFunc: the strdup() function in use
743 *
744 * Return the memory access functions set currently in use
745 *
746 * Returns 0 on success
747 */
748int
749xmlMemGet(xmlFreeFunc *freeFunc, xmlMallocFunc *mallocFunc,
750 xmlReallocFunc *reallocFunc, xmlStrdupFunc *strdupFunc) {
751 if (freeFunc != NULL) *freeFunc = xmlFree;
752 if (mallocFunc != NULL) *mallocFunc = xmlMalloc;
753 if (reallocFunc != NULL) *reallocFunc = xmlRealloc;
754 if (strdupFunc != NULL) *strdupFunc = xmlMemStrdup;
755 return(0);
756}
757