Annotation of XML/xmlmemory.c, revision 1.12

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.1       daniel     33: #include "xmlmemory.h"
                     34: 
1.2       daniel     35: #ifndef NO_DEBUG_MEMORY
1.1       daniel     36: #ifdef xmlMalloc
                     37: #undef xmlMalloc
                     38: #endif
                     39: #ifdef xmlRealloc
                     40: #undef xmlRealloc
                     41: #endif
                     42: #ifdef xmlMemStrdup
                     43: #undef xmlMemStrdup
                     44: #endif
1.6       daniel     45: 
1.1       daniel     46: 
                     47: /*
                     48:  * Each of the blocks allocated begin with a header containing informations
                     49:  */
                     50: 
                     51: #define MEMTAG 0x5aa5
                     52: 
                     53: #define MALLOC_TYPE 1
                     54: #define REALLOC_TYPE 2
                     55: #define STRDUP_TYPE 3
                     56: 
                     57: typedef struct memnod {
                     58:     unsigned int   mh_tag;
                     59:     unsigned int   mh_type;
                     60:     unsigned long  mh_number;
                     61:     size_t         mh_size;
                     62: #ifdef MEM_LIST
                     63:    struct memnod *mh_next;
                     64:    struct memnod *mh_prev;
                     65: #endif
                     66:    const char    *mh_file;
                     67:    unsigned int   mh_line;
                     68: }  MEMHDR;
                     69: 
                     70: 
                     71: #ifdef SUN4
                     72: #define ALIGN_SIZE  16
                     73: #else
                     74: #define ALIGN_SIZE  sizeof(double)
                     75: #endif
                     76: #define HDR_SIZE    sizeof(MEMHDR)
                     77: #define RESERVE_SIZE (((HDR_SIZE + (ALIGN_SIZE-1)) \
                     78:                      / ALIGN_SIZE ) * ALIGN_SIZE)
                     79: 
                     80: 
                     81: #define CLIENT_2_HDR(a) ((MEMHDR *) (((char *) (a)) - RESERVE_SIZE))
                     82: #define HDR_2_CLIENT(a)    ((void *) (((char *) (a)) + RESERVE_SIZE))
                     83: 
                     84: 
                     85: static unsigned long  debugMemSize = 0;
1.7       daniel     86: static unsigned long  debugMaxMemSize = 0;
1.1       daniel     87: static int block=0;
1.7       daniel     88: int xmlMemStopAtBlock = 0;
                     89: int xmlMemInitialized = 0;
1.1       daniel     90: #ifdef MEM_LIST
                     91: static MEMHDR *memlist = NULL;
                     92: #endif
                     93: 
                     94: void debugmem_tag_error(void *addr);
                     95: #ifdef MEM_LIST
                     96: void  debugmem_list_add(MEMHDR *);
                     97: void debugmem_list_delete(MEMHDR *);
                     98: #endif
                     99: #define Mem_Tag_Err(a) debugmem_tag_error(a);
                    100: 
                    101: #ifndef TEST_POINT
                    102: #define TEST_POINT
                    103: #endif
                    104: 
                    105: /**
1.7       daniel    106:  * xmlMallocBreakpoint:
                    107:  *
                    108:  * Breakpoint to use in conjunction with xmlMemStopAtBlock. When the block
                    109:  * number reaches the specified value this function is called. One need to add a breakpoint
                    110:  * to it to get the context in which the given block is allocated.
                    111:  */
                    112: 
                    113: void
                    114: xmlMallocBreakpoint(void) {
                    115:     fprintf(stderr, "xmlMallocBreakpoint reached on block %d\n", xmlMemStopAtBlock);
                    116: }
                    117: 
                    118: /**
1.1       daniel    119:  * xmlMallocLoc:
                    120:  * @size:  an int specifying the size in byte to allocate.
                    121:  * @file:  the file name or NULL
1.7       daniel    122:   @file:  the line number
1.1       daniel    123:  *
                    124:  * a malloc() equivalent, with logging of the allocation info.
                    125:  *
                    126:  * Returns a pointer to the allocated area or NULL in case of lack of memory.
                    127:  */
                    128: 
                    129: void *
                    130: xmlMallocLoc(int size, const char * file, int line)
                    131: {
                    132:     MEMHDR *p;
                    133:     
1.7       daniel    134:     if (!xmlMemInitialized) xmlInitMemory();
1.1       daniel    135: #ifdef DEBUG_MEMORY
                    136:     fprintf(stderr, "Malloc(%d)\n",size);
                    137: #endif
                    138: 
                    139:     TEST_POINT
                    140:     
                    141:     p = (MEMHDR *) malloc(RESERVE_SIZE+size);
                    142: 
                    143:     if (!p) {
1.8       daniel    144:        fprintf(stderr, "xmlMalloc : Out of free space\n");
                    145:        xmlMemoryDump();
                    146:        return(NULL);
1.1       daniel    147:     }   
                    148:     p->mh_tag = MEMTAG;
                    149:     p->mh_number = ++block;
                    150:     p->mh_size = size;
                    151:     p->mh_type = MALLOC_TYPE;
                    152:     p->mh_file = file;
                    153:     p->mh_line = line;
                    154:     debugMemSize += size;
1.7       daniel    155:     if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize;
1.1       daniel    156: #ifdef MEM_LIST
                    157:     debugmem_list_add(p);
                    158: #endif
                    159: 
                    160: #ifdef DEBUG_MEMORY
                    161:     fprintf(stderr, "Malloc(%d) Ok\n",size);
                    162: #endif
                    163:     
1.7       daniel    164:     if (xmlMemStopAtBlock == block) xmlMallocBreakpoint();
1.1       daniel    165: 
                    166:     TEST_POINT
                    167: 
                    168:     return(HDR_2_CLIENT(p));
                    169: }
                    170: 
                    171: /**
1.12    ! daniel    172:  * xmlMemMalloc:
1.1       daniel    173:  * @size:  an int specifying the size in byte to allocate.
                    174:  *
                    175:  * a malloc() equivalent, with logging of the allocation info.
                    176:  *
                    177:  * Returns a pointer to the allocated area or NULL in case of lack of memory.
                    178:  */
                    179: 
                    180: void *
1.12    ! daniel    181: xmlMemMalloc(int size)
1.1       daniel    182: {
                    183:     return(xmlMallocLoc(size, "none", 0));
                    184: }
                    185: 
                    186: /**
                    187:  * xmlReallocLoc:
                    188:  * @ptr:  the initial memory block pointer
                    189:  * @size:  an int specifying the size in byte to allocate.
                    190:  * @file:  the file name or NULL
                    191:  * @file:  the line number
                    192:  *
                    193:  * a realloc() equivalent, with logging of the allocation info.
                    194:  *
                    195:  * Returns a pointer to the allocated area or NULL in case of lack of memory.
                    196:  */
                    197: 
                    198: void *
                    199: xmlReallocLoc(void *ptr,int size, const char * file, int line)
                    200: {
                    201:     MEMHDR *p;
                    202:     unsigned long number;
                    203: 
1.7       daniel    204:     if (!xmlMemInitialized) xmlInitMemory();
1.1       daniel    205:     TEST_POINT
                    206: 
                    207:     p = CLIENT_2_HDR(ptr);
                    208:     number = p->mh_number;
                    209:     if (p->mh_tag != MEMTAG) {
1.4       daniel    210:        Mem_Tag_Err(p);
1.1       daniel    211:         goto error;
                    212:     }
                    213:     p->mh_tag = ~MEMTAG;
                    214:     debugMemSize -= p->mh_size;
                    215: #ifdef MEM_LIST
                    216:     debugmem_list_delete(p);
                    217: #endif
                    218: 
                    219:     p = (MEMHDR *) realloc(p,RESERVE_SIZE+size);
                    220:     if (!p) {
                    221:         goto error;
                    222:     }
                    223:     p->mh_tag = MEMTAG;
                    224:     p->mh_number = number;
                    225:     p->mh_type = REALLOC_TYPE;
                    226:     p->mh_size = size;
                    227:     p->mh_file = file;
                    228:     p->mh_line = line;
                    229:     debugMemSize += size;
1.7       daniel    230:     if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize;
1.1       daniel    231: #ifdef MEM_LIST
                    232:     debugmem_list_add(p);
                    233: #endif
                    234: 
                    235:     TEST_POINT
                    236: 
                    237:     return(HDR_2_CLIENT(p));
                    238:     
                    239: error:    
                    240:     return(NULL);
                    241: }
                    242: 
                    243: /**
1.12    ! daniel    244:  * xmlMemRealloc:
1.1       daniel    245:  * @ptr:  the initial memory block pointer
                    246:  * @size:  an int specifying the size in byte to allocate.
                    247:  *
                    248:  * a realloc() equivalent, with logging of the allocation info.
                    249:  *
                    250:  * Returns a pointer to the allocated area or NULL in case of lack of memory.
                    251:  */
                    252: 
                    253: void *
1.12    ! daniel    254: xmlMemRealloc(void *ptr,int size) {
1.1       daniel    255:     return(xmlReallocLoc(ptr, size, "none", 0));
                    256: }
                    257: 
                    258: /**
1.12    ! daniel    259:  * xmlMemFree:
1.1       daniel    260:  * @ptr:  the memory block pointer
                    261:  *
                    262:  * a free() equivalent, with error checking.
                    263:  */
                    264: void
1.12    ! daniel    265: xmlMemFree(void *ptr)
1.1       daniel    266: {
                    267:     MEMHDR *p;
                    268: 
                    269:     TEST_POINT
                    270: 
                    271:     p = CLIENT_2_HDR(ptr);
                    272:     if (p->mh_tag != MEMTAG) {
1.4       daniel    273:        Mem_Tag_Err(p);
                    274:        goto error;
1.1       daniel    275:     }
                    276:     p->mh_tag = ~MEMTAG;
                    277:     debugMemSize -= p->mh_size;
                    278: 
                    279: #ifdef MEM_LIST
                    280:     debugmem_list_delete(p);
                    281: #endif
                    282:     free(p);
                    283: 
                    284:     TEST_POINT
                    285: 
                    286:     return;
                    287:     
                    288: error:    
                    289:     fprintf(stderr, "xmlFree(%X) error\n", (unsigned int) ptr);
                    290:     return;
                    291: }
                    292: 
                    293: /**
                    294:  * xmlMemStrdupLoc:
                    295:  * @ptr:  the initial string pointer
                    296:  * @file:  the file name or NULL
                    297:  * @file:  the line number
                    298:  *
                    299:  * a strdup() equivalent, with logging of the allocation info.
                    300:  *
                    301:  * Returns a pointer to the new string or NULL if allocation error occured.
                    302:  */
                    303: 
                    304: char *
                    305: xmlMemStrdupLoc(const char *str, const char *file, int line)
                    306: {
                    307:     char *s;
                    308:     size_t size = strlen(str) + 1;
                    309:     MEMHDR *p;
                    310: 
1.7       daniel    311:     if (!xmlMemInitialized) xmlInitMemory();
1.1       daniel    312:     TEST_POINT
                    313: 
                    314:     p = (MEMHDR *) malloc(RESERVE_SIZE+size);
                    315:     if (!p) {
1.4       daniel    316:       goto error;
1.1       daniel    317:     }
                    318:     p->mh_tag = MEMTAG;
                    319:     p->mh_number = ++block;
                    320:     p->mh_size = size;
                    321:     p->mh_type = STRDUP_TYPE;
                    322:     p->mh_file = file;
                    323:     p->mh_line = line;
                    324:     debugMemSize += size;
1.7       daniel    325:     if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize;
1.1       daniel    326: #ifdef MEM_LIST
                    327:     debugmem_list_add(p);
                    328: #endif
                    329:     s = HDR_2_CLIENT(p);
                    330:     
1.7       daniel    331:     if (xmlMemStopAtBlock == block) xmlMallocBreakpoint();
                    332: 
1.1       daniel    333:     if (s != NULL)
1.4       daniel    334:       strcpy(s,str);
1.1       daniel    335:     else
1.4       daniel    336:       goto error;
1.1       daniel    337:     
                    338:     TEST_POINT
                    339: 
                    340:     return(s);
                    341: 
                    342: error:
                    343:     return(NULL);
                    344: }
                    345: 
                    346: /**
1.12    ! daniel    347:  * xmlMemoryStrdup:
1.1       daniel    348:  * @ptr:  the initial string pointer
                    349:  *
                    350:  * a strdup() equivalent, with logging of the allocation info.
                    351:  *
                    352:  * Returns a pointer to the new string or NULL if allocation error occured.
                    353:  */
                    354: 
                    355: char *
1.12    ! daniel    356: xmlMemoryStrdup(const char *str) {
1.1       daniel    357:     return(xmlMemStrdupLoc(str, "none", 0));
                    358: }
                    359: 
                    360: /**
                    361:  * xmlMemUsed:
                    362:  *
                    363:  * returns the amount of memory currenly allocated
                    364:  *
                    365:  * Returns an int representing the amount of memory allocated.
                    366:  */
                    367: 
                    368: int
                    369: xmlMemUsed(void) {
                    370:      return(debugMemSize);
                    371: }
                    372: 
1.11      daniel    373: #ifdef MEM_LIST
                    374: /**
                    375:  * xmlMemContentShow:
                    376:  * @fp:  a FILE descriptor used as the output file
                    377:  * @p:  a memory block header
                    378:  *
                    379:  * tries to show some content from the memory block
                    380:  */
                    381: 
                    382: void
                    383: xmlMemContentShow(FILE *fp, MEMHDR *p)
                    384: {
                    385:     int i,j,len = p->mh_size;
                    386:     const char *buf = HDR_2_CLIENT(p);
                    387: 
                    388:     for (i = 0;i < len;i++) {
                    389:         if (buf[i] == 0) break;
                    390:        if (!isprint(buf[i])) break;
                    391:     }
                    392:     if ((i < 4) && ((buf[i] != 0) || (i == 0))) {
                    393:         if (len >= 4) {
                    394:            MEMHDR *q;
                    395:            void *cur;
                    396: 
                    397:             for (j = 0;j < len -3;j += 4) {
                    398:                cur = *((void **) &buf[j]);
                    399:                q = CLIENT_2_HDR(cur);
                    400:                p = memlist;
                    401:                while (p != NULL) {
                    402:                    if (p == q) break;
                    403:                    p = p->mh_next;
                    404:                }
                    405:                if (p == q) {
                    406:                    fprintf(fp, " pointer to #%lu at index %d",
                    407:                            p->mh_number, j);
                    408:                    return;
                    409:                }
                    410:            }
                    411:        }
                    412:     } else if ((i == 0) && (buf[i] == 0)) {
                    413:         fprintf(fp," null");
                    414:     } else {
                    415:         if (buf[i] == 0) fprintf(fp," \"%.25s\"", buf); 
                    416:        else {
                    417:             fprintf(fp," [");
                    418:            for (j = 0;j < i;j++)
                    419:                 fprintf(fp,"%c", buf[j]);
                    420:             fprintf(fp,"]");
                    421:        }
                    422:     }
                    423: }
                    424: #endif
                    425: 
1.1       daniel    426: /**
1.10      daniel    427:  * xmlMemShow:
                    428:  * @fp:  a FILE descriptor used as the output file
                    429:  * @nr:  number of entries to dump
                    430:  *
                    431:  * show a show display of the memory allocated, and dump
                    432:  * the @nr last allocated areas which were not freed
                    433:  */
                    434: 
                    435: void
                    436: xmlMemShow(FILE *fp, int nr)
                    437: {
                    438: #ifdef MEM_LIST
                    439:     MEMHDR *p;
                    440: #endif
                    441: 
                    442:     if (fp != NULL)
                    443:        fprintf(fp,"      MEMORY ALLOCATED : %lu, MAX was %lu\n",
                    444:                debugMemSize, debugMaxMemSize);
                    445: #ifdef MEM_LIST
                    446:     if (nr > 0) {
                    447:        fprintf(fp,"NUMBER   SIZE  TYPE   WHERE\n");
                    448:        p = memlist;
                    449:        while ((p) && nr > 0) {
                    450:              fprintf(fp,"%6lu %6u ",p->mh_number,p->mh_size);
                    451:            switch (p->mh_type) {
                    452:               case STRDUP_TYPE:fprintf(fp,"strdup()  in ");break;
                    453:               case MALLOC_TYPE:fprintf(fp,"malloc()  in ");break;
                    454:              case REALLOC_TYPE:fprintf(fp,"realloc() in ");break;
                    455:                        default:fprintf(fp,"   ???    in ");break;
                    456:            }
                    457:            if (p->mh_file != NULL)
                    458:                fprintf(fp,"%s(%d)", p->mh_file, p->mh_line);
                    459:            if (p->mh_tag != MEMTAG)
                    460:                fprintf(fp,"  INVALID");
1.11      daniel    461:            xmlMemContentShow(fp, p);
1.10      daniel    462:            fprintf(fp,"\n");
                    463:            nr--;
                    464:            p = p->mh_next;
                    465:        }
                    466:     }
                    467: #endif /* MEM_LIST */    
                    468: }
                    469: 
                    470: /**
1.1       daniel    471:  * xmlMemDisplay:
                    472:  * @fp:  a FILE descriptor used as the output file, if NULL, the result is
1.10      daniel    473:  *       written to the file .memorylist
1.1       daniel    474:  *
                    475:  * show in-extenso the memory blocks allocated
                    476:  */
                    477: 
                    478: void
                    479: xmlMemDisplay(FILE *fp)
                    480: {
                    481: #ifdef MEM_LIST
1.4       daniel    482:     MEMHDR *p;
                    483:     int     idx;
                    484: #if defined(HAVE_LOCALTIME) && defined(HAVE_STRFTIME)
1.5       daniel    485:     time_t currentTime;
1.4       daniel    486:     char buf[500];
                    487:     struct tm * tstruct;
                    488: 
1.5       daniel    489:     currentTime = time(NULL);
                    490:     tstruct = localtime(&currentTime);
1.4       daniel    491:     strftime(buf, sizeof(buf) - 1, "%c", tstruct);
                    492:     fprintf(fp,"      %s\n\n", buf);
                    493: #endif
                    494: 
1.1       daniel    495:     
1.7       daniel    496:     fprintf(fp,"      MEMORY ALLOCATED : %lu, MAX was %lu\n",
                    497:             debugMemSize, debugMaxMemSize);
1.4       daniel    498:     fprintf(fp,"BLOCK  NUMBER   SIZE  TYPE\n");
                    499:     idx = 0;
                    500:     p = memlist;
                    501:     while (p) {
1.1       daniel    502:          fprintf(fp,"%-5u  %6lu %6u ",idx++,p->mh_number,p->mh_size);
1.4       daniel    503:         switch (p->mh_type) {
                    504:            case STRDUP_TYPE:fprintf(fp,"strdup()  in ");break;
                    505:            case MALLOC_TYPE:fprintf(fp,"malloc()  in ");break;
                    506:           case REALLOC_TYPE:fprintf(fp,"realloc() in ");break;
                    507:                     default:fprintf(fp,"   ???    in ");break;
                    508:         }
1.1       daniel    509:          if (p->mh_file != NULL) fprintf(fp,"%s(%d)", p->mh_file, p->mh_line);
1.4       daniel    510:         if (p->mh_tag != MEMTAG)
1.1       daniel    511:              fprintf(fp,"  INVALID");
1.11      daniel    512:        xmlMemContentShow(fp, p);
1.4       daniel    513:         fprintf(fp,"\n");
                    514:         p = p->mh_next;
                    515:     }
1.1       daniel    516: #else
1.4       daniel    517:     fprintf(fp,"Memory list not compiled (MEM_LIST not defined !)\n");
1.1       daniel    518: #endif
                    519: }
                    520: 
                    521: #ifdef MEM_LIST
                    522: 
                    523: void debugmem_list_add(MEMHDR *p)
                    524: {
1.4       daniel    525:      p->mh_next = memlist;
                    526:      p->mh_prev = NULL;
                    527:      if (memlist) memlist->mh_prev = p;
                    528:      memlist = p;
1.1       daniel    529: #ifdef MEM_LIST_DEBUG
1.4       daniel    530:      if (stderr)
                    531:      Mem_Display(stderr);
1.1       daniel    532: #endif
                    533: }
                    534: 
                    535: void debugmem_list_delete(MEMHDR *p)
                    536: {
1.4       daniel    537:      if (p->mh_next)
                    538:      p->mh_next->mh_prev = p->mh_prev;
                    539:      if (p->mh_prev)
                    540:      p->mh_prev->mh_next = p->mh_next;
                    541:      else memlist = p->mh_next;
1.1       daniel    542: #ifdef MEM_LIST_DEBUG
1.4       daniel    543:      if (stderr)
                    544:      Mem_Display(stderr);
1.1       daniel    545: #endif
                    546: }
                    547: 
                    548: #endif
                    549: 
                    550: /*
                    551:  * debugmem_tag_error : internal error function.
                    552:  */
                    553:  
                    554: void debugmem_tag_error(void *p)
                    555: {
1.4       daniel    556:      fprintf(stderr, "Memory tag error occurs :%p \n\t bye\n", p);
1.1       daniel    557: #ifdef MEM_LIST
1.4       daniel    558:      if (stderr)
                    559:      xmlMemDisplay(stderr);
1.1       daniel    560: #endif
                    561: }
                    562: 
                    563: FILE *xmlMemoryDumpFile = NULL;
                    564: 
                    565: 
                    566: /**
                    567:  * xmlMemoryDump:
                    568:  *
                    569:  * Dump in-extenso the memory blocks allocated to the file .memorylist
                    570:  */
                    571: 
                    572: void
                    573: xmlMemoryDump(void)
                    574: {
                    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);
                    584: }
                    585: 
                    586: 
                    587: /****************************************************************
                    588:  *                                                             *
                    589:  *             Initialization Routines                         *
                    590:  *                                                             *
                    591:  ****************************************************************/
                    592: 
1.12    ! daniel    593: #if defined(DEBUG_MEMORY_LOCATION) | defined(DEBUG_MEMORY)
        !           594: xmlFreeFunc xmlFree = xmlMemFree;
        !           595: xmlMallocFunc xmlMalloc = xmlMemMalloc;
        !           596: xmlReallocFunc xmlRealloc = xmlMemRealloc;
        !           597: xmlStrdupFunc xmlMemStrdup = xmlMemoryStrdup;
        !           598: #else
        !           599: xmlFreeFunc xmlFree = free;
        !           600: xmlMallocFunc xmlMalloc = malloc;
        !           601: xmlReallocFunc xmlRealloc = realloc;
        !           602: xmlStrdupFunc xmlMemStrdup = strdup;
        !           603: #endif
        !           604: 
1.1       daniel    605: /**
                    606:  * xmlInitMemory:
                    607:  *
                    608:  * Initialize the memory layer.
1.6       daniel    609:  *
                    610:  * Returns 0 on success
1.1       daniel    611:  */
                    612: 
1.12    ! daniel    613: static int xmlInitMemoryDone = 0;
1.1       daniel    614: 
                    615: int
                    616: xmlInitMemory(void)
                    617: {
                    618:      int ret;
1.7       daniel    619:      
                    620: #ifdef HAVE_STDLIB_H
                    621:      char *breakpoint;
1.12    ! daniel    622: #endif     
        !           623: 
        !           624:      if (xmlInitMemoryDone) return(-1);
1.7       daniel    625: 
1.12    ! daniel    626: #ifdef HAVE_STDLIB_H
1.7       daniel    627:      breakpoint = getenv("XML_MEM_BREAKPOINT");
                    628:      if (breakpoint != NULL) {
                    629:          sscanf(breakpoint, "%d", &xmlMemStopAtBlock);
                    630:      }
                    631: #endif     
1.1       daniel    632:     
                    633: #ifdef DEBUG_MEMORY
                    634:      fprintf(stderr, "xmlInitMemory() Ok\n");
                    635: #endif     
                    636:      ret = 0;
                    637:      return(ret);
1.12    ! daniel    638: }
        !           639: 
        !           640: /**
        !           641:  * xmlMemSetup:
        !           642:  * @freeFunc: the free() function to use
        !           643:  * @mallocFunc: the malloc() function to use
        !           644:  * @reallocFunc: the realloc() function to use
        !           645:  * @strdupFunc: the strdup() function to use
        !           646:  *
        !           647:  * Override the default memory access functions with a new set
        !           648:  *
        !           649:  * Returns 0 on success
        !           650:  */
        !           651: int
        !           652: xmlMemSetup(xmlFreeFunc freeFunc, xmlMallocFunc mallocFunc,
        !           653:             xmlReallocFunc reallocFunc, xmlStrdupFunc strdupFunc) {
        !           654:     if (freeFunc != NULL)
        !           655:        return(-1);
        !           656:     if (mallocFunc != NULL)
        !           657:        return(-1);
        !           658:     if (reallocFunc != NULL)
        !           659:        return(-1);
        !           660:     if (strdupFunc != NULL)
        !           661:        return(-1);
        !           662:     xmlFree = freeFunc;
        !           663:     xmlMalloc = mallocFunc;
        !           664:     xmlRealloc = reallocFunc;
        !           665:     xmlMemStrdup = strdupFunc;
        !           666:     return(0);
        !           667: }
        !           668: 
        !           669: /**
        !           670:  * xmlMemGet:
        !           671:  * @freeFunc: the free() function in use
        !           672:  * @mallocFunc: the malloc() function in use
        !           673:  * @reallocFunc: the realloc() function in use
        !           674:  * @strdupFunc: the strdup() function in use
        !           675:  *
        !           676:  * Return the memory access functions set currently in use
        !           677:  *
        !           678:  * Returns 0 on success
        !           679:  */
        !           680: int
        !           681: xmlMemGet(xmlFreeFunc *freeFunc, xmlMallocFunc *mallocFunc,
        !           682:          xmlReallocFunc *reallocFunc, xmlStrdupFunc *strdupFunc) {
        !           683:     if (freeFunc != NULL) freeFunc = xmlFree;
        !           684:     if (mallocFunc != NULL) mallocFunc = xmlMalloc;
        !           685:     if (reallocFunc != NULL) reallocFunc = xmlRealloc;
        !           686:     if (strdupFunc != NULL) strdupFunc = xmlMemStrdup;
        !           687:     return(0);
1.1       daniel    688: }
                    689: 
1.2       daniel    690: #endif /* ! NO_DEBUG_MEMORY */

Webmaster