Annotation of XML/xmlmemory.c, revision 1.16

1.1       daniel      1: /*
                      2:  * memory.c:  libxml memory allocator wrapper.
                      3:  *
                      4:  * Daniel.Veillard@w3.org
                      5:  */
                      6: 
1.3       daniel      7: #ifdef WIN32
1.9       daniel      8: #include "win32config.h"
1.3       daniel      9: #else
1.4       daniel     10: #include "config.h"
1.3       daniel     11: #endif
                     12: 
                     13: #include <stdio.h>
                     14: #include <string.h>
                     15: 
                     16: #ifdef HAVE_SYS_TYPES_H
1.1       daniel     17: #include <sys/types.h>
1.3       daniel     18: #endif
1.4       daniel     19: #ifdef HAVE_TIME_H
                     20: #include <time.h>
                     21: #endif
1.3       daniel     22: #ifdef HAVE_MALLOC_H
1.1       daniel     23: #include <malloc.h>
1.3       daniel     24: #endif
1.7       daniel     25: #ifdef HAVE_STDLIB_H
                     26: #include <stdlib.h>
                     27: #endif
1.11      daniel     28: #ifdef HAVE_CTYPE_H
                     29: #include <ctype.h>
                     30: #endif
1.7       daniel     31: 
1.3       daniel     32: 
1.14      daniel     33: #include <libxml/xmlmemory.h>
1.1       daniel     34: 
                     35: #ifdef xmlMalloc
                     36: #undef xmlMalloc
                     37: #endif
                     38: #ifdef xmlRealloc
                     39: #undef xmlRealloc
                     40: #endif
                     41: #ifdef xmlMemStrdup
                     42: #undef xmlMemStrdup
                     43: #endif
1.6       daniel     44: 
1.1       daniel     45: 
                     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: 
                     56: typedef 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: 
                     84: static unsigned long  debugMemSize = 0;
1.7       daniel     85: static unsigned long  debugMaxMemSize = 0;
1.1       daniel     86: static int block=0;
1.7       daniel     87: int xmlMemStopAtBlock = 0;
                     88: int xmlMemInitialized = 0;
1.1       daniel     89: #ifdef MEM_LIST
                     90: static MEMHDR *memlist = NULL;
                     91: #endif
                     92: 
                     93: void debugmem_tag_error(void *addr);
                     94: #ifdef MEM_LIST
                     95: void  debugmem_list_add(MEMHDR *);
                     96: void 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: /**
1.7       daniel    105:  * 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: 
                    112: void
                    113: xmlMallocBreakpoint(void) {
                    114:     fprintf(stderr, "xmlMallocBreakpoint reached on block %d\n", xmlMemStopAtBlock);
                    115: }
                    116: 
                    117: /**
1.1       daniel    118:  * xmlMallocLoc:
                    119:  * @size:  an int specifying the size in byte to allocate.
                    120:  * @file:  the file name or NULL
1.15      daniel    121:  * @line:  the line number
1.1       daniel    122:  *
                    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: 
                    128: void *
                    129: xmlMallocLoc(int size, const char * file, int line)
                    130: {
                    131:     MEMHDR *p;
                    132:     
1.7       daniel    133:     if (!xmlMemInitialized) xmlInitMemory();
1.1       daniel    134: #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) {
1.8       daniel    143:        fprintf(stderr, "xmlMalloc : Out of free space\n");
                    144:        xmlMemoryDump();
                    145:        return(NULL);
1.1       daniel    146:     }   
                    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;
1.7       daniel    154:     if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize;
1.1       daniel    155: #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:     
1.7       daniel    163:     if (xmlMemStopAtBlock == block) xmlMallocBreakpoint();
1.1       daniel    164: 
                    165:     TEST_POINT
                    166: 
                    167:     return(HDR_2_CLIENT(p));
                    168: }
                    169: 
                    170: /**
1.12      daniel    171:  * xmlMemMalloc:
1.1       daniel    172:  * @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: 
                    179: void *
1.12      daniel    180: xmlMemMalloc(int size)
1.1       daniel    181: {
                    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
1.15      daniel    190:  * @line:  the line number
1.1       daniel    191:  *
                    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: 
                    197: void *
                    198: xmlReallocLoc(void *ptr,int size, const char * file, int line)
                    199: {
                    200:     MEMHDR *p;
                    201:     unsigned long number;
                    202: 
1.7       daniel    203:     if (!xmlMemInitialized) xmlInitMemory();
1.1       daniel    204:     TEST_POINT
                    205: 
                    206:     p = CLIENT_2_HDR(ptr);
                    207:     number = p->mh_number;
                    208:     if (p->mh_tag != MEMTAG) {
1.4       daniel    209:        Mem_Tag_Err(p);
1.1       daniel    210:         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;
1.7       daniel    229:     if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize;
1.1       daniel    230: #ifdef MEM_LIST
                    231:     debugmem_list_add(p);
                    232: #endif
                    233: 
                    234:     TEST_POINT
                    235: 
                    236:     return(HDR_2_CLIENT(p));
                    237:     
                    238: error:    
                    239:     return(NULL);
                    240: }
                    241: 
                    242: /**
1.12      daniel    243:  * xmlMemRealloc:
1.1       daniel    244:  * @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: 
                    252: void *
1.12      daniel    253: xmlMemRealloc(void *ptr,int size) {
1.1       daniel    254:     return(xmlReallocLoc(ptr, size, "none", 0));
                    255: }
                    256: 
                    257: /**
1.12      daniel    258:  * xmlMemFree:
1.1       daniel    259:  * @ptr:  the memory block pointer
                    260:  *
                    261:  * a free() equivalent, with error checking.
                    262:  */
                    263: void
1.12      daniel    264: xmlMemFree(void *ptr)
1.1       daniel    265: {
                    266:     MEMHDR *p;
                    267: 
                    268:     TEST_POINT
                    269: 
                    270:     p = CLIENT_2_HDR(ptr);
                    271:     if (p->mh_tag != MEMTAG) {
1.4       daniel    272:        Mem_Tag_Err(p);
                    273:        goto error;
1.1       daniel    274:     }
                    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:     
                    287: error:    
                    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
1.15      daniel    296:  * @line:  the line number
1.1       daniel    297:  *
                    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: 
                    303: char *
                    304: xmlMemStrdupLoc(const char *str, const char *file, int line)
                    305: {
                    306:     char *s;
                    307:     size_t size = strlen(str) + 1;
                    308:     MEMHDR *p;
                    309: 
1.7       daniel    310:     if (!xmlMemInitialized) xmlInitMemory();
1.1       daniel    311:     TEST_POINT
                    312: 
                    313:     p = (MEMHDR *) malloc(RESERVE_SIZE+size);
                    314:     if (!p) {
1.4       daniel    315:       goto error;
1.1       daniel    316:     }
                    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;
1.7       daniel    324:     if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize;
1.1       daniel    325: #ifdef MEM_LIST
                    326:     debugmem_list_add(p);
                    327: #endif
1.16    ! veillard  328:     s = (char *) HDR_2_CLIENT(p);
1.1       daniel    329:     
1.7       daniel    330:     if (xmlMemStopAtBlock == block) xmlMallocBreakpoint();
                    331: 
1.1       daniel    332:     if (s != NULL)
1.4       daniel    333:       strcpy(s,str);
1.1       daniel    334:     else
1.4       daniel    335:       goto error;
1.1       daniel    336:     
                    337:     TEST_POINT
                    338: 
                    339:     return(s);
                    340: 
                    341: error:
                    342:     return(NULL);
                    343: }
                    344: 
                    345: /**
1.12      daniel    346:  * xmlMemoryStrdup:
1.1       daniel    347:  * @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: 
                    354: char *
1.12      daniel    355: xmlMemoryStrdup(const char *str) {
1.1       daniel    356:     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: 
                    367: int
                    368: xmlMemUsed(void) {
                    369:      return(debugMemSize);
                    370: }
                    371: 
1.11      daniel    372: #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: 
                    381: void
                    382: xmlMemContentShow(FILE *fp, MEMHDR *p)
                    383: {
                    384:     int i,j,len = p->mh_size;
1.16    ! veillard  385:     const char *buf = (const char *) HDR_2_CLIENT(p);
1.11      daniel    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: 
1.1       daniel    425: /**
1.10      daniel    426:  * 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: 
                    434: void
                    435: xmlMemShow(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");
1.11      daniel    460:            xmlMemContentShow(fp, p);
1.10      daniel    461:            fprintf(fp,"\n");
                    462:            nr--;
                    463:            p = p->mh_next;
                    464:        }
                    465:     }
                    466: #endif /* MEM_LIST */    
                    467: }
                    468: 
                    469: /**
1.1       daniel    470:  * xmlMemDisplay:
                    471:  * @fp:  a FILE descriptor used as the output file, if NULL, the result is
1.10      daniel    472:  *       written to the file .memorylist
1.1       daniel    473:  *
                    474:  * show in-extenso the memory blocks allocated
                    475:  */
                    476: 
                    477: void
                    478: xmlMemDisplay(FILE *fp)
                    479: {
                    480: #ifdef MEM_LIST
1.4       daniel    481:     MEMHDR *p;
                    482:     int     idx;
                    483: #if defined(HAVE_LOCALTIME) && defined(HAVE_STRFTIME)
1.5       daniel    484:     time_t currentTime;
1.4       daniel    485:     char buf[500];
                    486:     struct tm * tstruct;
                    487: 
1.5       daniel    488:     currentTime = time(NULL);
                    489:     tstruct = localtime(&currentTime);
1.4       daniel    490:     strftime(buf, sizeof(buf) - 1, "%c", tstruct);
                    491:     fprintf(fp,"      %s\n\n", buf);
                    492: #endif
                    493: 
1.1       daniel    494:     
1.7       daniel    495:     fprintf(fp,"      MEMORY ALLOCATED : %lu, MAX was %lu\n",
                    496:             debugMemSize, debugMaxMemSize);
1.4       daniel    497:     fprintf(fp,"BLOCK  NUMBER   SIZE  TYPE\n");
                    498:     idx = 0;
                    499:     p = memlist;
                    500:     while (p) {
1.1       daniel    501:          fprintf(fp,"%-5u  %6lu %6u ",idx++,p->mh_number,p->mh_size);
1.4       daniel    502:         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:         }
1.1       daniel    508:          if (p->mh_file != NULL) fprintf(fp,"%s(%d)", p->mh_file, p->mh_line);
1.4       daniel    509:         if (p->mh_tag != MEMTAG)
1.1       daniel    510:              fprintf(fp,"  INVALID");
1.11      daniel    511:        xmlMemContentShow(fp, p);
1.4       daniel    512:         fprintf(fp,"\n");
                    513:         p = p->mh_next;
                    514:     }
1.1       daniel    515: #else
1.4       daniel    516:     fprintf(fp,"Memory list not compiled (MEM_LIST not defined !)\n");
1.1       daniel    517: #endif
                    518: }
                    519: 
                    520: #ifdef MEM_LIST
                    521: 
                    522: void debugmem_list_add(MEMHDR *p)
                    523: {
1.4       daniel    524:      p->mh_next = memlist;
                    525:      p->mh_prev = NULL;
                    526:      if (memlist) memlist->mh_prev = p;
                    527:      memlist = p;
1.1       daniel    528: #ifdef MEM_LIST_DEBUG
1.4       daniel    529:      if (stderr)
                    530:      Mem_Display(stderr);
1.1       daniel    531: #endif
                    532: }
                    533: 
                    534: void debugmem_list_delete(MEMHDR *p)
                    535: {
1.4       daniel    536:      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;
1.1       daniel    541: #ifdef MEM_LIST_DEBUG
1.4       daniel    542:      if (stderr)
                    543:      Mem_Display(stderr);
1.1       daniel    544: #endif
                    545: }
                    546: 
                    547: #endif
                    548: 
                    549: /*
                    550:  * debugmem_tag_error : internal error function.
                    551:  */
                    552:  
                    553: void debugmem_tag_error(void *p)
                    554: {
1.4       daniel    555:      fprintf(stderr, "Memory tag error occurs :%p \n\t bye\n", p);
1.1       daniel    556: #ifdef MEM_LIST
1.4       daniel    557:      if (stderr)
                    558:      xmlMemDisplay(stderr);
1.1       daniel    559: #endif
                    560: }
                    561: 
                    562: FILE *xmlMemoryDumpFile = NULL;
                    563: 
                    564: 
                    565: /**
                    566:  * xmlMemoryDump:
                    567:  *
                    568:  * Dump in-extenso the memory blocks allocated to the file .memorylist
                    569:  */
                    570: 
                    571: void
                    572: xmlMemoryDump(void)
                    573: {
1.13      daniel    574: #if defined(DEBUG_MEMORY_LOCATION) | defined(DEBUG_MEMORY)
1.1       daniel    575:     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);
1.13      daniel    584: #endif
1.1       daniel    585: }
                    586: 
                    587: 
                    588: /****************************************************************
                    589:  *                                                             *
                    590:  *             Initialization Routines                         *
                    591:  *                                                             *
                    592:  ****************************************************************/
                    593: 
1.12      daniel    594: #if defined(DEBUG_MEMORY_LOCATION) | defined(DEBUG_MEMORY)
1.13      daniel    595: xmlFreeFunc xmlFree = (xmlFreeFunc) xmlMemFree;
                    596: xmlMallocFunc xmlMalloc = (xmlMallocFunc) xmlMemMalloc;
                    597: xmlReallocFunc xmlRealloc = (xmlReallocFunc) xmlMemRealloc;
                    598: xmlStrdupFunc xmlMemStrdup = (xmlStrdupFunc) xmlMemoryStrdup;
1.12      daniel    599: #else
1.13      daniel    600: xmlFreeFunc xmlFree = (xmlFreeFunc) free;
                    601: xmlMallocFunc xmlMalloc = (xmlMallocFunc) malloc;
                    602: xmlReallocFunc xmlRealloc = (xmlReallocFunc) realloc;
                    603: xmlStrdupFunc xmlMemStrdup = (xmlStrdupFunc) strdup;
1.12      daniel    604: #endif
                    605: 
1.1       daniel    606: /**
                    607:  * xmlInitMemory:
                    608:  *
                    609:  * Initialize the memory layer.
1.6       daniel    610:  *
                    611:  * Returns 0 on success
1.1       daniel    612:  */
                    613: 
1.12      daniel    614: static int xmlInitMemoryDone = 0;
1.1       daniel    615: 
                    616: int
                    617: xmlInitMemory(void)
                    618: {
                    619:      int ret;
1.7       daniel    620:      
                    621: #ifdef HAVE_STDLIB_H
                    622:      char *breakpoint;
1.12      daniel    623: #endif     
                    624: 
                    625:      if (xmlInitMemoryDone) return(-1);
1.7       daniel    626: 
1.12      daniel    627: #ifdef HAVE_STDLIB_H
1.7       daniel    628:      breakpoint = getenv("XML_MEM_BREAKPOINT");
                    629:      if (breakpoint != NULL) {
                    630:          sscanf(breakpoint, "%d", &xmlMemStopAtBlock);
                    631:      }
                    632: #endif     
1.1       daniel    633:     
                    634: #ifdef DEBUG_MEMORY
                    635:      fprintf(stderr, "xmlInitMemory() Ok\n");
                    636: #endif     
                    637:      ret = 0;
                    638:      return(ret);
1.12      daniel    639: }
                    640: 
                    641: /**
                    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
1.13      daniel    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 ?
1.12      daniel    653:  *
                    654:  * Returns 0 on success
                    655:  */
                    656: int
                    657: xmlMemSetup(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:  */
                    685: int
                    686: xmlMemGet(xmlFreeFunc *freeFunc, xmlMallocFunc *mallocFunc,
                    687:          xmlReallocFunc *reallocFunc, xmlStrdupFunc *strdupFunc) {
1.13      daniel    688:     if (freeFunc != NULL) *freeFunc = xmlFree;
                    689:     if (mallocFunc != NULL) *mallocFunc = xmlMalloc;
                    690:     if (reallocFunc != NULL) *reallocFunc = xmlRealloc;
                    691:     if (strdupFunc != NULL) *strdupFunc = xmlMemStrdup;
1.12      daniel    692:     return(0);
1.1       daniel    693: }
                    694: 

Webmaster