blob: e03e51da208cbebcd354cacc841b20091b3e0748 [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 Veillard6454aec1999-09-02 22:04:43 +000034
Daniel Veillard6454aec1999-09-02 22:04:43 +000035#ifdef xmlMalloc
36#undef xmlMalloc
37#endif
38#ifdef xmlRealloc
39#undef xmlRealloc
40#endif
41#ifdef xmlMemStrdup
42#undef xmlMemStrdup
43#endif
Daniel Veillard00fdf371999-10-08 09:40:39 +000044
Daniel Veillard6454aec1999-09-02 22:04:43 +000045
46/*
47 * Each of the blocks allocated begin with a header containing informations
48 */
49
50#define MEMTAG 0x5aa5
51
52#define MALLOC_TYPE 1
53#define REALLOC_TYPE 2
54#define STRDUP_TYPE 3
55
56typedef struct memnod {
57 unsigned int mh_tag;
58 unsigned int mh_type;
59 unsigned long mh_number;
60 size_t mh_size;
61#ifdef MEM_LIST
62 struct memnod *mh_next;
63 struct memnod *mh_prev;
64#endif
65 const char *mh_file;
66 unsigned int mh_line;
67} MEMHDR;
68
69
70#ifdef SUN4
71#define ALIGN_SIZE 16
72#else
73#define ALIGN_SIZE sizeof(double)
74#endif
75#define HDR_SIZE sizeof(MEMHDR)
76#define RESERVE_SIZE (((HDR_SIZE + (ALIGN_SIZE-1)) \
77 / ALIGN_SIZE ) * ALIGN_SIZE)
78
79
80#define CLIENT_2_HDR(a) ((MEMHDR *) (((char *) (a)) - RESERVE_SIZE))
81#define HDR_2_CLIENT(a) ((void *) (((char *) (a)) + RESERVE_SIZE))
82
83
84static unsigned long debugMemSize = 0;
Daniel Veillard7c1206f1999-10-14 09:10:25 +000085static unsigned long debugMaxMemSize = 0;
Daniel Veillard6454aec1999-09-02 22:04:43 +000086static int block=0;
Daniel Veillard7c1206f1999-10-14 09:10:25 +000087int xmlMemStopAtBlock = 0;
88int xmlMemInitialized = 0;
Daniel Veillard6454aec1999-09-02 22:04:43 +000089#ifdef MEM_LIST
90static MEMHDR *memlist = NULL;
91#endif
92
93void debugmem_tag_error(void *addr);
94#ifdef MEM_LIST
95void debugmem_list_add(MEMHDR *);
96void debugmem_list_delete(MEMHDR *);
97#endif
98#define Mem_Tag_Err(a) debugmem_tag_error(a);
99
100#ifndef TEST_POINT
101#define TEST_POINT
102#endif
103
104/**
Daniel Veillard7c1206f1999-10-14 09:10:25 +0000105 * xmlMallocBreakpoint:
106 *
107 * Breakpoint to use in conjunction with xmlMemStopAtBlock. When the block
108 * number reaches the specified value this function is called. One need to add a breakpoint
109 * to it to get the context in which the given block is allocated.
110 */
111
112void
113xmlMallocBreakpoint(void) {
114 fprintf(stderr, "xmlMallocBreakpoint reached on block %d\n", xmlMemStopAtBlock);
115}
116
117/**
Daniel Veillard6454aec1999-09-02 22:04:43 +0000118 * xmlMallocLoc:
119 * @size: an int specifying the size in byte to allocate.
120 * @file: the file name or NULL
Daniel Veillard06047432000-04-24 11:33:38 +0000121 * @line: the line number
Daniel Veillard6454aec1999-09-02 22:04:43 +0000122 *
123 * a malloc() equivalent, with logging of the allocation info.
124 *
125 * Returns a pointer to the allocated area or NULL in case of lack of memory.
126 */
127
128void *
129xmlMallocLoc(int size, const char * file, int line)
130{
131 MEMHDR *p;
132
Daniel Veillard7c1206f1999-10-14 09:10:25 +0000133 if (!xmlMemInitialized) xmlInitMemory();
Daniel Veillard6454aec1999-09-02 22:04:43 +0000134#ifdef DEBUG_MEMORY
135 fprintf(stderr, "Malloc(%d)\n",size);
136#endif
137
138 TEST_POINT
139
140 p = (MEMHDR *) malloc(RESERVE_SIZE+size);
141
142 if (!p) {
Daniel Veillard10a2c651999-12-12 13:03:50 +0000143 fprintf(stderr, "xmlMalloc : Out of free space\n");
144 xmlMemoryDump();
145 return(NULL);
Daniel Veillard6454aec1999-09-02 22:04:43 +0000146 }
147 p->mh_tag = MEMTAG;
148 p->mh_number = ++block;
149 p->mh_size = size;
150 p->mh_type = MALLOC_TYPE;
151 p->mh_file = file;
152 p->mh_line = line;
153 debugMemSize += size;
Daniel Veillard7c1206f1999-10-14 09:10:25 +0000154 if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize;
Daniel Veillard6454aec1999-09-02 22:04:43 +0000155#ifdef MEM_LIST
156 debugmem_list_add(p);
157#endif
158
159#ifdef DEBUG_MEMORY
160 fprintf(stderr, "Malloc(%d) Ok\n",size);
161#endif
162
Daniel Veillard7c1206f1999-10-14 09:10:25 +0000163 if (xmlMemStopAtBlock == block) xmlMallocBreakpoint();
Daniel Veillard6454aec1999-09-02 22:04:43 +0000164
165 TEST_POINT
166
167 return(HDR_2_CLIENT(p));
168}
169
170/**
Daniel Veillard8f621982000-03-20 13:07:15 +0000171 * xmlMemMalloc:
Daniel Veillard6454aec1999-09-02 22:04:43 +0000172 * @size: an int specifying the size in byte to allocate.
173 *
174 * a malloc() equivalent, with logging of the allocation info.
175 *
176 * Returns a pointer to the allocated area or NULL in case of lack of memory.
177 */
178
179void *
Daniel Veillard8f621982000-03-20 13:07:15 +0000180xmlMemMalloc(int size)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000181{
182 return(xmlMallocLoc(size, "none", 0));
183}
184
185/**
186 * xmlReallocLoc:
187 * @ptr: the initial memory block pointer
188 * @size: an int specifying the size in byte to allocate.
189 * @file: the file name or NULL
Daniel Veillard06047432000-04-24 11:33:38 +0000190 * @line: the line number
Daniel Veillard6454aec1999-09-02 22:04:43 +0000191 *
192 * a realloc() equivalent, with logging of the allocation info.
193 *
194 * Returns a pointer to the allocated area or NULL in case of lack of memory.
195 */
196
197void *
198xmlReallocLoc(void *ptr,int size, const char * file, int line)
199{
200 MEMHDR *p;
201 unsigned long number;
202
Daniel Veillard7c1206f1999-10-14 09:10:25 +0000203 if (!xmlMemInitialized) xmlInitMemory();
Daniel Veillard6454aec1999-09-02 22:04:43 +0000204 TEST_POINT
205
206 p = CLIENT_2_HDR(ptr);
207 number = p->mh_number;
208 if (p->mh_tag != MEMTAG) {
Daniel Veillard7f7d1111999-09-22 09:46:25 +0000209 Mem_Tag_Err(p);
Daniel Veillard6454aec1999-09-02 22:04:43 +0000210 goto error;
211 }
212 p->mh_tag = ~MEMTAG;
213 debugMemSize -= p->mh_size;
214#ifdef MEM_LIST
215 debugmem_list_delete(p);
216#endif
217
218 p = (MEMHDR *) realloc(p,RESERVE_SIZE+size);
219 if (!p) {
220 goto error;
221 }
222 p->mh_tag = MEMTAG;
223 p->mh_number = number;
224 p->mh_type = REALLOC_TYPE;
225 p->mh_size = size;
226 p->mh_file = file;
227 p->mh_line = line;
228 debugMemSize += size;
Daniel Veillard7c1206f1999-10-14 09:10:25 +0000229 if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize;
Daniel Veillard6454aec1999-09-02 22:04:43 +0000230#ifdef MEM_LIST
231 debugmem_list_add(p);
232#endif
233
234 TEST_POINT
235
236 return(HDR_2_CLIENT(p));
237
238error:
239 return(NULL);
240}
241
242/**
Daniel Veillard8f621982000-03-20 13:07:15 +0000243 * xmlMemRealloc:
Daniel Veillard6454aec1999-09-02 22:04:43 +0000244 * @ptr: the initial memory block pointer
245 * @size: an int specifying the size in byte to allocate.
246 *
247 * a realloc() equivalent, with logging of the allocation info.
248 *
249 * Returns a pointer to the allocated area or NULL in case of lack of memory.
250 */
251
252void *
Daniel Veillard8f621982000-03-20 13:07:15 +0000253xmlMemRealloc(void *ptr,int size) {
Daniel Veillard6454aec1999-09-02 22:04:43 +0000254 return(xmlReallocLoc(ptr, size, "none", 0));
255}
256
257/**
Daniel Veillard8f621982000-03-20 13:07:15 +0000258 * xmlMemFree:
Daniel Veillard6454aec1999-09-02 22:04:43 +0000259 * @ptr: the memory block pointer
260 *
261 * a free() equivalent, with error checking.
Daniel Veillard6454aec1999-09-02 22:04:43 +0000262 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000263void
Daniel Veillard8f621982000-03-20 13:07:15 +0000264xmlMemFree(void *ptr)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000265{
266 MEMHDR *p;
267
268 TEST_POINT
269
270 p = CLIENT_2_HDR(ptr);
271 if (p->mh_tag != MEMTAG) {
Daniel Veillard7f7d1111999-09-22 09:46:25 +0000272 Mem_Tag_Err(p);
273 goto error;
Daniel Veillard6454aec1999-09-02 22:04:43 +0000274 }
275 p->mh_tag = ~MEMTAG;
276 debugMemSize -= p->mh_size;
277
278#ifdef MEM_LIST
279 debugmem_list_delete(p);
280#endif
281 free(p);
282
283 TEST_POINT
284
285 return;
286
287error:
288 fprintf(stderr, "xmlFree(%X) error\n", (unsigned int) ptr);
289 return;
290}
291
292/**
293 * xmlMemStrdupLoc:
294 * @ptr: the initial string pointer
295 * @file: the file name or NULL
Daniel Veillard06047432000-04-24 11:33:38 +0000296 * @line: the line number
Daniel Veillard6454aec1999-09-02 22:04:43 +0000297 *
298 * a strdup() equivalent, with logging of the allocation info.
299 *
300 * Returns a pointer to the new string or NULL if allocation error occured.
301 */
302
303char *
304xmlMemStrdupLoc(const char *str, const char *file, int line)
305{
306 char *s;
307 size_t size = strlen(str) + 1;
308 MEMHDR *p;
309
Daniel Veillard7c1206f1999-10-14 09:10:25 +0000310 if (!xmlMemInitialized) xmlInitMemory();
Daniel Veillard6454aec1999-09-02 22:04:43 +0000311 TEST_POINT
312
313 p = (MEMHDR *) malloc(RESERVE_SIZE+size);
314 if (!p) {
Daniel Veillard7f7d1111999-09-22 09:46:25 +0000315 goto error;
Daniel Veillard6454aec1999-09-02 22:04:43 +0000316 }
317 p->mh_tag = MEMTAG;
318 p->mh_number = ++block;
319 p->mh_size = size;
320 p->mh_type = STRDUP_TYPE;
321 p->mh_file = file;
322 p->mh_line = line;
323 debugMemSize += size;
Daniel Veillard7c1206f1999-10-14 09:10:25 +0000324 if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize;
Daniel Veillard6454aec1999-09-02 22:04:43 +0000325#ifdef MEM_LIST
326 debugmem_list_add(p);
327#endif
328 s = HDR_2_CLIENT(p);
329
Daniel Veillard7c1206f1999-10-14 09:10:25 +0000330 if (xmlMemStopAtBlock == block) xmlMallocBreakpoint();
331
Daniel Veillard6454aec1999-09-02 22:04:43 +0000332 if (s != NULL)
Daniel Veillard7f7d1111999-09-22 09:46:25 +0000333 strcpy(s,str);
Daniel Veillard6454aec1999-09-02 22:04:43 +0000334 else
Daniel Veillard7f7d1111999-09-22 09:46:25 +0000335 goto error;
Daniel Veillard6454aec1999-09-02 22:04:43 +0000336
337 TEST_POINT
338
339 return(s);
340
341error:
342 return(NULL);
343}
344
345/**
Daniel Veillard8f621982000-03-20 13:07:15 +0000346 * xmlMemoryStrdup:
Daniel Veillard6454aec1999-09-02 22:04:43 +0000347 * @ptr: the initial string pointer
348 *
349 * a strdup() equivalent, with logging of the allocation info.
350 *
351 * Returns a pointer to the new string or NULL if allocation error occured.
352 */
353
354char *
Daniel Veillard8f621982000-03-20 13:07:15 +0000355xmlMemoryStrdup(const char *str) {
Daniel Veillard6454aec1999-09-02 22:04:43 +0000356 return(xmlMemStrdupLoc(str, "none", 0));
357}
358
359/**
360 * xmlMemUsed:
361 *
362 * returns the amount of memory currenly allocated
363 *
364 * Returns an int representing the amount of memory allocated.
365 */
366
367int
368xmlMemUsed(void) {
369 return(debugMemSize);
370}
371
Daniel Veillard5e5c6231999-12-29 12:49:06 +0000372#ifdef MEM_LIST
373/**
374 * xmlMemContentShow:
375 * @fp: a FILE descriptor used as the output file
376 * @p: a memory block header
377 *
378 * tries to show some content from the memory block
379 */
380
381void
382xmlMemContentShow(FILE *fp, MEMHDR *p)
383{
384 int i,j,len = p->mh_size;
385 const char *buf = HDR_2_CLIENT(p);
386
387 for (i = 0;i < len;i++) {
388 if (buf[i] == 0) break;
389 if (!isprint(buf[i])) break;
390 }
391 if ((i < 4) && ((buf[i] != 0) || (i == 0))) {
392 if (len >= 4) {
393 MEMHDR *q;
394 void *cur;
395
396 for (j = 0;j < len -3;j += 4) {
397 cur = *((void **) &buf[j]);
398 q = CLIENT_2_HDR(cur);
399 p = memlist;
400 while (p != NULL) {
401 if (p == q) break;
402 p = p->mh_next;
403 }
404 if (p == q) {
405 fprintf(fp, " pointer to #%lu at index %d",
406 p->mh_number, j);
407 return;
408 }
409 }
410 }
411 } else if ((i == 0) && (buf[i] == 0)) {
412 fprintf(fp," null");
413 } else {
414 if (buf[i] == 0) fprintf(fp," \"%.25s\"", buf);
415 else {
416 fprintf(fp," [");
417 for (j = 0;j < i;j++)
418 fprintf(fp,"%c", buf[j]);
419 fprintf(fp,"]");
420 }
421 }
422}
423#endif
424
Daniel Veillard6454aec1999-09-02 22:04:43 +0000425/**
Daniel Veillarddbfd6411999-12-28 16:35:14 +0000426 * xmlMemShow:
427 * @fp: a FILE descriptor used as the output file
428 * @nr: number of entries to dump
429 *
430 * show a show display of the memory allocated, and dump
431 * the @nr last allocated areas which were not freed
432 */
433
434void
435xmlMemShow(FILE *fp, int nr)
436{
437#ifdef MEM_LIST
438 MEMHDR *p;
439#endif
440
441 if (fp != NULL)
442 fprintf(fp," MEMORY ALLOCATED : %lu, MAX was %lu\n",
443 debugMemSize, debugMaxMemSize);
444#ifdef MEM_LIST
445 if (nr > 0) {
446 fprintf(fp,"NUMBER SIZE TYPE WHERE\n");
447 p = memlist;
448 while ((p) && nr > 0) {
449 fprintf(fp,"%6lu %6u ",p->mh_number,p->mh_size);
450 switch (p->mh_type) {
451 case STRDUP_TYPE:fprintf(fp,"strdup() in ");break;
452 case MALLOC_TYPE:fprintf(fp,"malloc() in ");break;
453 case REALLOC_TYPE:fprintf(fp,"realloc() in ");break;
454 default:fprintf(fp," ??? in ");break;
455 }
456 if (p->mh_file != NULL)
457 fprintf(fp,"%s(%d)", p->mh_file, p->mh_line);
458 if (p->mh_tag != MEMTAG)
459 fprintf(fp," INVALID");
Daniel Veillard5e5c6231999-12-29 12:49:06 +0000460 xmlMemContentShow(fp, p);
Daniel Veillarddbfd6411999-12-28 16:35:14 +0000461 fprintf(fp,"\n");
462 nr--;
463 p = p->mh_next;
464 }
465 }
466#endif /* MEM_LIST */
467}
468
469/**
Daniel Veillard6454aec1999-09-02 22:04:43 +0000470 * xmlMemDisplay:
471 * @fp: a FILE descriptor used as the output file, if NULL, the result is
Daniel Veillarddbfd6411999-12-28 16:35:14 +0000472 * written to the file .memorylist
Daniel Veillard6454aec1999-09-02 22:04:43 +0000473 *
474 * show in-extenso the memory blocks allocated
475 */
476
477void
478xmlMemDisplay(FILE *fp)
479{
480#ifdef MEM_LIST
Daniel Veillard7f7d1111999-09-22 09:46:25 +0000481 MEMHDR *p;
482 int idx;
483#if defined(HAVE_LOCALTIME) && defined(HAVE_STRFTIME)
484 time_t currentTime;
485 char buf[500];
486 struct tm * tstruct;
487
488 currentTime = time(NULL);
489 tstruct = localtime(&currentTime);
490 strftime(buf, sizeof(buf) - 1, "%c", tstruct);
491 fprintf(fp," %s\n\n", buf);
492#endif
493
Daniel Veillard6454aec1999-09-02 22:04:43 +0000494
Daniel Veillard7c1206f1999-10-14 09:10:25 +0000495 fprintf(fp," MEMORY ALLOCATED : %lu, MAX was %lu\n",
496 debugMemSize, debugMaxMemSize);
Daniel Veillard7f7d1111999-09-22 09:46:25 +0000497 fprintf(fp,"BLOCK NUMBER SIZE TYPE\n");
498 idx = 0;
499 p = memlist;
500 while (p) {
Daniel Veillard6454aec1999-09-02 22:04:43 +0000501 fprintf(fp,"%-5u %6lu %6u ",idx++,p->mh_number,p->mh_size);
Daniel Veillard7f7d1111999-09-22 09:46:25 +0000502 switch (p->mh_type) {
503 case STRDUP_TYPE:fprintf(fp,"strdup() in ");break;
504 case MALLOC_TYPE:fprintf(fp,"malloc() in ");break;
505 case REALLOC_TYPE:fprintf(fp,"realloc() in ");break;
506 default:fprintf(fp," ??? in ");break;
507 }
Daniel Veillard6454aec1999-09-02 22:04:43 +0000508 if (p->mh_file != NULL) fprintf(fp,"%s(%d)", p->mh_file, p->mh_line);
Daniel Veillard7f7d1111999-09-22 09:46:25 +0000509 if (p->mh_tag != MEMTAG)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000510 fprintf(fp," INVALID");
Daniel Veillard5e5c6231999-12-29 12:49:06 +0000511 xmlMemContentShow(fp, p);
Daniel Veillard7f7d1111999-09-22 09:46:25 +0000512 fprintf(fp,"\n");
513 p = p->mh_next;
514 }
Daniel Veillard6454aec1999-09-02 22:04:43 +0000515#else
Daniel Veillard7f7d1111999-09-22 09:46:25 +0000516 fprintf(fp,"Memory list not compiled (MEM_LIST not defined !)\n");
Daniel Veillard6454aec1999-09-02 22:04:43 +0000517#endif
518}
519
520#ifdef MEM_LIST
521
522void debugmem_list_add(MEMHDR *p)
523{
Daniel Veillard7f7d1111999-09-22 09:46:25 +0000524 p->mh_next = memlist;
525 p->mh_prev = NULL;
526 if (memlist) memlist->mh_prev = p;
527 memlist = p;
Daniel Veillard6454aec1999-09-02 22:04:43 +0000528#ifdef MEM_LIST_DEBUG
Daniel Veillard7f7d1111999-09-22 09:46:25 +0000529 if (stderr)
530 Mem_Display(stderr);
Daniel Veillard6454aec1999-09-02 22:04:43 +0000531#endif
532}
533
534void debugmem_list_delete(MEMHDR *p)
535{
Daniel Veillard7f7d1111999-09-22 09:46:25 +0000536 if (p->mh_next)
537 p->mh_next->mh_prev = p->mh_prev;
538 if (p->mh_prev)
539 p->mh_prev->mh_next = p->mh_next;
540 else memlist = p->mh_next;
Daniel Veillard6454aec1999-09-02 22:04:43 +0000541#ifdef MEM_LIST_DEBUG
Daniel Veillard7f7d1111999-09-22 09:46:25 +0000542 if (stderr)
543 Mem_Display(stderr);
Daniel Veillard6454aec1999-09-02 22:04:43 +0000544#endif
545}
546
547#endif
548
549/*
550 * debugmem_tag_error : internal error function.
551 */
552
553void debugmem_tag_error(void *p)
554{
Daniel Veillard7f7d1111999-09-22 09:46:25 +0000555 fprintf(stderr, "Memory tag error occurs :%p \n\t bye\n", p);
Daniel Veillard6454aec1999-09-02 22:04:43 +0000556#ifdef MEM_LIST
Daniel Veillard7f7d1111999-09-22 09:46:25 +0000557 if (stderr)
558 xmlMemDisplay(stderr);
Daniel Veillard6454aec1999-09-02 22:04:43 +0000559#endif
560}
561
562FILE *xmlMemoryDumpFile = NULL;
563
564
565/**
566 * xmlMemoryDump:
567 *
568 * Dump in-extenso the memory blocks allocated to the file .memorylist
569 */
570
571void
572xmlMemoryDump(void)
573{
Daniel Veillard8f621982000-03-20 13:07:15 +0000574#if defined(DEBUG_MEMORY_LOCATION) | defined(DEBUG_MEMORY)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000575 FILE *dump;
576
577 dump = fopen(".memdump", "w");
578 if (dump == NULL) xmlMemoryDumpFile = stdout;
579 else xmlMemoryDumpFile = dump;
580
581 xmlMemDisplay(xmlMemoryDumpFile);
582
583 if (dump != NULL) fclose(dump);
Daniel Veillard8f621982000-03-20 13:07:15 +0000584#endif
Daniel Veillard6454aec1999-09-02 22:04:43 +0000585}
586
587
588/****************************************************************
589 * *
590 * Initialization Routines *
591 * *
592 ****************************************************************/
593
Daniel Veillard8f621982000-03-20 13:07:15 +0000594#if defined(DEBUG_MEMORY_LOCATION) | defined(DEBUG_MEMORY)
595xmlFreeFunc xmlFree = (xmlFreeFunc) xmlMemFree;
596xmlMallocFunc xmlMalloc = (xmlMallocFunc) xmlMemMalloc;
597xmlReallocFunc xmlRealloc = (xmlReallocFunc) xmlMemRealloc;
598xmlStrdupFunc xmlMemStrdup = (xmlStrdupFunc) xmlMemoryStrdup;
599#else
600xmlFreeFunc xmlFree = (xmlFreeFunc) free;
601xmlMallocFunc xmlMalloc = (xmlMallocFunc) malloc;
602xmlReallocFunc xmlRealloc = (xmlReallocFunc) realloc;
603xmlStrdupFunc xmlMemStrdup = (xmlStrdupFunc) strdup;
604#endif
605
Daniel Veillard6454aec1999-09-02 22:04:43 +0000606/**
607 * xmlInitMemory:
608 *
609 * Initialize the memory layer.
Daniel Veillard00fdf371999-10-08 09:40:39 +0000610 *
611 * Returns 0 on success
Daniel Veillard6454aec1999-09-02 22:04:43 +0000612 */
613
Daniel Veillard8f621982000-03-20 13:07:15 +0000614static int xmlInitMemoryDone = 0;
Daniel Veillard6454aec1999-09-02 22:04:43 +0000615
616int
617xmlInitMemory(void)
618{
619 int ret;
Daniel Veillard7c1206f1999-10-14 09:10:25 +0000620
621#ifdef HAVE_STDLIB_H
622 char *breakpoint;
Daniel Veillard8f621982000-03-20 13:07:15 +0000623#endif
Daniel Veillard7c1206f1999-10-14 09:10:25 +0000624
Daniel Veillard8f621982000-03-20 13:07:15 +0000625 if (xmlInitMemoryDone) return(-1);
626
627#ifdef HAVE_STDLIB_H
Daniel Veillard7c1206f1999-10-14 09:10:25 +0000628 breakpoint = getenv("XML_MEM_BREAKPOINT");
629 if (breakpoint != NULL) {
630 sscanf(breakpoint, "%d", &xmlMemStopAtBlock);
631 }
632#endif
Daniel Veillard6454aec1999-09-02 22:04:43 +0000633
634#ifdef DEBUG_MEMORY
635 fprintf(stderr, "xmlInitMemory() Ok\n");
636#endif
637 ret = 0;
638 return(ret);
639}
640
Daniel Veillard8f621982000-03-20 13:07:15 +0000641/**
642 * xmlMemSetup:
643 * @freeFunc: the free() function to use
644 * @mallocFunc: the malloc() function to use
645 * @reallocFunc: the realloc() function to use
646 * @strdupFunc: the strdup() function to use
647 *
648 * Override the default memory access functions with a new set
649 * This has to be called before any other libxml routines !
650 *
651 * Should this be blocked if there was already some allocations
652 * done ?
653 *
654 * Returns 0 on success
655 */
656int
657xmlMemSetup(xmlFreeFunc freeFunc, xmlMallocFunc mallocFunc,
658 xmlReallocFunc reallocFunc, xmlStrdupFunc strdupFunc) {
659 if (freeFunc != NULL)
660 return(-1);
661 if (mallocFunc != NULL)
662 return(-1);
663 if (reallocFunc != NULL)
664 return(-1);
665 if (strdupFunc != NULL)
666 return(-1);
667 xmlFree = freeFunc;
668 xmlMalloc = mallocFunc;
669 xmlRealloc = reallocFunc;
670 xmlMemStrdup = strdupFunc;
671 return(0);
672}
673
674/**
675 * xmlMemGet:
676 * @freeFunc: the free() function in use
677 * @mallocFunc: the malloc() function in use
678 * @reallocFunc: the realloc() function in use
679 * @strdupFunc: the strdup() function in use
680 *
681 * Return the memory access functions set currently in use
682 *
683 * Returns 0 on success
684 */
685int
686xmlMemGet(xmlFreeFunc *freeFunc, xmlMallocFunc *mallocFunc,
687 xmlReallocFunc *reallocFunc, xmlStrdupFunc *strdupFunc) {
688 if (freeFunc != NULL) *freeFunc = xmlFree;
689 if (mallocFunc != NULL) *mallocFunc = xmlMalloc;
690 if (reallocFunc != NULL) *reallocFunc = xmlRealloc;
691 if (strdupFunc != NULL) *strdupFunc = xmlMemStrdup;
692 return(0);
693}
694