Annotation of XML/xmlmemory.c, revision 1.19

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

Webmaster