xml/libxml2libs/src/libxml2/libxml2_xmlmemory.c
changeset 0 e35f40988205
equal deleted inserted replaced
-1:000000000000 0:e35f40988205
       
     1 /*
       
     2  * libxml2_xmlmemory.c:  libxml memory allocator wrapper.
       
     3  *
       
     4  * daniel@veillard.com
       
     5  * See Copyright for the status of this software.
       
     6  * Portion Copyright © 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. 
       
     7  */
       
     8 
       
     9 #define IN_LIBXML
       
    10 #include "xmlenglibxml.h"
       
    11 
       
    12 #include <string.h>
       
    13 
       
    14 #ifdef HAVE_SYS_TYPES_H
       
    15 #include <sys/types.h>
       
    16 #endif
       
    17 
       
    18 #ifdef HAVE_TIME_H
       
    19 #include <time.h>
       
    20 #endif
       
    21 
       
    22 #ifdef HAVE_STDLIB_H
       
    23 #include <stdlib.h>
       
    24 #else
       
    25 #ifdef HAVE_MALLOC_H
       
    26 #include <malloc.h>
       
    27 #endif
       
    28 #endif
       
    29 
       
    30 #ifdef HAVE_CTYPE_H
       
    31 #include <ctype.h>
       
    32 #endif
       
    33 
       
    34 /**
       
    35  * MEM_LIST:
       
    36  *
       
    37  * keep track of all allocated blocks for error reporting
       
    38  * Always build the memory list !
       
    39  */
       
    40 #ifdef DEBUG_MEMORY_LOCATION
       
    41 #ifndef MEM_LIST
       
    42 #define MEM_LIST /* keep a list of all the allocated memory blocks */
       
    43 #endif
       
    44 #endif
       
    45 
       
    46 #include <stdapis/libxml2/libxml2_globals.h>
       
    47 
       
    48 void xmlMallocBreakpoint(void);
       
    49 
       
    50 /************************************************************************
       
    51  *                                                                      *
       
    52  *      Macros, variables and associated types                          *
       
    53  *                                                                      *
       
    54  ************************************************************************/
       
    55 
       
    56 
       
    57 /*
       
    58  * Each of the blocks allocated begin with a header containing information
       
    59  */
       
    60 
       
    61 #define MEMTAG 0x5aa5
       
    62 
       
    63 #define MALLOC_TYPE 1
       
    64 #define REALLOC_TYPE 2
       
    65 #define STRDUP_TYPE 3
       
    66 #define MALLOC_ATOMIC_TYPE 4
       
    67 #define REALLOC_ATOMIC_TYPE 5
       
    68 
       
    69 typedef struct memnod {
       
    70     unsigned int   mh_tag;
       
    71     unsigned int   mh_type;
       
    72     unsigned long  mh_number;
       
    73     size_t         mh_size;
       
    74 #ifdef MEM_LIST
       
    75    struct memnod* mh_next;
       
    76    struct memnod* mh_prev;
       
    77 #endif
       
    78    const char*    mh_file;
       
    79    unsigned int   mh_line;
       
    80 }  MEMHDR;
       
    81 
       
    82 
       
    83 #ifdef SUN4
       
    84 #define ALIGN_SIZE  16
       
    85 #else
       
    86 #define ALIGN_SIZE  sizeof(double)
       
    87 #endif
       
    88 #define HDR_SIZE    sizeof(MEMHDR)
       
    89 #define RESERVE_SIZE (((HDR_SIZE + (ALIGN_SIZE-1)) \
       
    90                       / ALIGN_SIZE ) * ALIGN_SIZE)
       
    91 
       
    92 
       
    93 #define CLIENT_2_HDR(a) ((MEMHDR*) (((char *) (a)) - RESERVE_SIZE))
       
    94 #define HDR_2_CLIENT(a) ((void*)   (((char *) (a)) + RESERVE_SIZE))
       
    95 
       
    96 #ifdef MEM_LIST
       
    97 static MEMHDR *memlist = NULL;
       
    98 #endif
       
    99 
       
   100 static void debugmem_tag_error(void *addr);
       
   101 #ifdef MEM_LIST
       
   102 static void debugmem_list_add(MEMHDR*);
       
   103 static void debugmem_list_delete(MEMHDR*);
       
   104 #endif
       
   105 #define Mem_Tag_Err(a) debugmem_tag_error(a);
       
   106 
       
   107 #ifndef TEST_POINT
       
   108 #define TEST_POINT
       
   109 #endif
       
   110 
       
   111 /**
       
   112  * xmlMallocBreakpoint:
       
   113  *
       
   114  * Breakpoint to use in conjunction with xmlMemStopAtBlock. When the block
       
   115  * number reaches the specified value this function is called. One need to add a breakpoint
       
   116  * to it to get the context in which the given block is allocated.
       
   117  */
       
   118 
       
   119 void
       
   120 xmlMallocBreakpoint(void) {
       
   121 	LOAD_GS_DIRECT
       
   122     xmlGenericError(xmlGenericErrorContext,
       
   123         EMBED_ERRTXT("xmlMallocBreakpoint reached on block %d\n"), xmlMemStopAtBlock);
       
   124 }
       
   125 
       
   126 /**
       
   127  * xmlMallocLoc:
       
   128  * @param size an int specifying the size in byte to allocate.
       
   129  * @param file the file name or NULL
       
   130  * @param line the line number
       
   131  *
       
   132  * a malloc() equivalent, with logging of the allocation info.
       
   133  *
       
   134  * Returns a pointer to the allocated area or NULL in case of lack of memory.
       
   135  */
       
   136 XMLPUBFUNEXPORT void*
       
   137 xmlMallocLoc(size_t size, const char * file, int line)
       
   138 {
       
   139     LOAD_GS_DIRECT
       
   140     MEMHDR *p;
       
   141     void *ret;
       
   142 
       
   143     if (!xmlMemInitialized) xmlInitMemory();
       
   144 #ifdef DEBUG_MEMORY
       
   145     xmlGenericError(xmlGenericErrorContext, "Malloc(%d)\n",size);
       
   146 #endif
       
   147 
       
   148     TEST_POINT
       
   149 
       
   150     p = (MEMHDR *) malloc(RESERVE_SIZE+size);
       
   151 
       
   152     if (!p) {
       
   153         xmlGenericError(xmlGenericErrorContext, "xmlMallocLoc : Out of free space\n");
       
   154         xmlMemoryDump();
       
   155         return(NULL);
       
   156     }
       
   157     p->mh_tag = MEMTAG;
       
   158     p->mh_size = size;
       
   159     p->mh_type = MALLOC_TYPE;
       
   160     p->mh_file = file;
       
   161     p->mh_line = line;
       
   162     xmlMutexLock(xmlMemMutex);
       
   163     p->mh_number = ++g_block;
       
   164     debugMemSize += size;
       
   165     if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize;
       
   166 #ifdef MEM_LIST
       
   167     debugmem_list_add(p);
       
   168 #endif
       
   169     xmlMutexUnlock(xmlMemMutex);
       
   170 
       
   171 #ifdef DEBUG_MEMORY
       
   172     xmlGenericError(xmlGenericErrorContext, "Malloc(%d) Ok\n",size);
       
   173 #endif
       
   174 
       
   175     if (xmlMemStopAtBlock == p->mh_number) xmlMallocBreakpoint();
       
   176 
       
   177     // agathe problem here
       
   178     ret = HDR_2_CLIENT(p);
       
   179 
       
   180     if (xmlMemTraceBlockAt == ret) {
       
   181         xmlGenericError(xmlGenericErrorContext, "%p : Malloc(%d) Ok\n", xmlMemTraceBlockAt, size);
       
   182         xmlMallocBreakpoint();
       
   183     }
       
   184 
       
   185     TEST_POINT
       
   186 
       
   187     return(ret);
       
   188 }
       
   189 
       
   190 /**
       
   191  * xmlMallocAtomicLoc:
       
   192  * @param size an int specifying the size in byte to allocate.
       
   193  * @param file the file name or NULL
       
   194  * @param line the line number
       
   195  *
       
   196  * a malloc() equivalent, with logging of the allocation info.
       
   197  *
       
   198  * Returns a pointer to the allocated area or NULL in case of lack of memory.
       
   199  */
       
   200 
       
   201 XMLPUBFUNEXPORT void *
       
   202 xmlMallocAtomicLoc(size_t size, const char * file, int line)
       
   203 {
       
   204     LOAD_GS_DIRECT
       
   205     MEMHDR *p;
       
   206     void *ret;
       
   207 
       
   208     if (!xmlMemInitialized) xmlInitMemory();
       
   209 #ifdef DEBUG_MEMORY
       
   210     xmlGenericError(xmlGenericErrorContext,
       
   211         "Malloc(%d)\n",size);
       
   212 #endif
       
   213 
       
   214     TEST_POINT
       
   215 
       
   216     p = (MEMHDR *) malloc(RESERVE_SIZE+size);
       
   217 
       
   218     if (!p) {
       
   219         xmlGenericError(xmlGenericErrorContext,
       
   220                 "xmlMallocLoc : Out of free space\n");
       
   221         xmlMemoryDump();
       
   222         return(NULL);
       
   223     }
       
   224     p->mh_tag = MEMTAG;
       
   225     p->mh_size = size;
       
   226     p->mh_type = MALLOC_ATOMIC_TYPE;
       
   227     p->mh_file = file;
       
   228     p->mh_line = line;
       
   229     xmlMutexLock(xmlMemMutex);
       
   230     p->mh_number = ++g_block;
       
   231     debugMemSize += size;
       
   232     if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize;
       
   233 #ifdef MEM_LIST
       
   234     debugmem_list_add(p);
       
   235 #endif
       
   236     xmlMutexUnlock(xmlMemMutex);
       
   237 
       
   238 #ifdef DEBUG_MEMORY
       
   239     xmlGenericError(xmlGenericErrorContext,
       
   240             "Malloc(%d) Ok\n",size);
       
   241 #endif
       
   242 
       
   243     if (xmlMemStopAtBlock == p->mh_number) xmlMallocBreakpoint();
       
   244 
       
   245     ret = HDR_2_CLIENT(p);
       
   246 
       
   247     if (xmlMemTraceBlockAt == ret) {
       
   248         xmlGenericError(xmlGenericErrorContext,
       
   249                         "%p : Malloc(%d) Ok\n", xmlMemTraceBlockAt, size);
       
   250         xmlMallocBreakpoint();
       
   251     }
       
   252 
       
   253     TEST_POINT
       
   254 
       
   255     return(ret);
       
   256 }
       
   257 /**
       
   258  * xmlMemMalloc:
       
   259  * @param size an int specifying the size in byte to allocate.
       
   260  *
       
   261  * a malloc() equivalent, with logging of the allocation info.
       
   262  *
       
   263  * Returns a pointer to the allocated area or NULL in case of lack of memory.
       
   264  */
       
   265 
       
   266 XMLPUBFUNEXPORT void *
       
   267 xmlMemMalloc(size_t size)
       
   268 {
       
   269      return(xmlMallocLoc(size, "none", 0));
       
   270 }
       
   271 
       
   272 /**
       
   273  * xmlReallocLoc:
       
   274  * @param ptr the initial memory block pointer
       
   275  * @param size an int specifying the size in byte to allocate.
       
   276  * @param file the file name or NULL
       
   277  * @param line the line number
       
   278  *
       
   279  * a realloc() equivalent, with logging of the allocation info.
       
   280  *
       
   281  * Returns a pointer to the allocated area or NULL in case of lack of memory.
       
   282  */
       
   283 
       
   284 XMLPUBFUNEXPORT void *
       
   285 xmlReallocLoc(void *ptr,size_t size, const char * file, int line)
       
   286 {
       
   287     LOAD_GS_DIRECT
       
   288     MEMHDR *p;
       
   289     unsigned long number;
       
   290 
       
   291     if (ptr == NULL)
       
   292         return(xmlMallocLoc(size, file, line));
       
   293 
       
   294     if (!xmlMemInitialized) xmlInitMemory();
       
   295     TEST_POINT
       
   296 
       
   297     p = CLIENT_2_HDR(ptr);
       
   298     number = p->mh_number;
       
   299     if (p->mh_tag != MEMTAG) {
       
   300        Mem_Tag_Err(p);
       
   301          goto error;
       
   302     }
       
   303     p->mh_tag = ~MEMTAG;
       
   304     xmlMutexLock(xmlMemMutex);
       
   305     debugMemSize -= p->mh_size;
       
   306 #ifdef MEM_LIST
       
   307     debugmem_list_delete(p);
       
   308 #endif
       
   309     xmlMutexUnlock(xmlMemMutex);
       
   310 
       
   311     p = (MEMHDR *) realloc(p,RESERVE_SIZE+size);
       
   312     if (!p) {
       
   313          goto error;
       
   314     }
       
   315     if (xmlMemTraceBlockAt == ptr) {
       
   316         xmlGenericError(xmlGenericErrorContext,
       
   317                         EMBED_ERRTXT("%p : Realloced(%d -> %d) Ok\n"),
       
   318                         xmlMemTraceBlockAt, p->mh_size, size);
       
   319         xmlMallocBreakpoint();
       
   320     }
       
   321     p->mh_tag = MEMTAG;
       
   322     p->mh_number = number;
       
   323     p->mh_type = REALLOC_TYPE;
       
   324     p->mh_size = size;
       
   325     p->mh_file = file;
       
   326     p->mh_line = line;
       
   327     xmlMutexLock(xmlMemMutex);
       
   328     debugMemSize += size;
       
   329     if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize;
       
   330 #ifdef MEM_LIST
       
   331     debugmem_list_add(p);
       
   332 #endif
       
   333     xmlMutexUnlock(xmlMemMutex);
       
   334 
       
   335     TEST_POINT
       
   336 
       
   337     return(HDR_2_CLIENT(p));
       
   338 
       
   339 error:
       
   340     return(NULL);
       
   341 }
       
   342 
       
   343 /**
       
   344  * xmlMemRealloc:
       
   345  * @param ptr the initial memory block pointer
       
   346  * @param size an int specifying the size in byte to allocate.
       
   347  *
       
   348  * a realloc() equivalent, with logging of the allocation info.
       
   349  *
       
   350  * Returns a pointer to the allocated area or NULL in case of lack of memory.
       
   351  */
       
   352 XMLPUBFUNEXPORT void *
       
   353 xmlMemRealloc(void *ptr,size_t size) {
       
   354     return(xmlReallocLoc(ptr, size, "none", 0));
       
   355 }
       
   356 
       
   357 /**
       
   358  * xmlMemFree:
       
   359  * @param ptr the memory block pointer
       
   360  *
       
   361  * a free() equivalent, with error checking.
       
   362  */
       
   363 XMLPUBFUNEXPORT void
       
   364 xmlMemFree(void *ptr)
       
   365 {
       
   366     LOAD_GS_DIRECT
       
   367     MEMHDR *p;
       
   368     char *target;
       
   369 
       
   370     if (ptr == (void *) -1) {
       
   371         xmlGenericError(xmlGenericErrorContext,
       
   372             EMBED_ERRTXT("trying to free pointer from freed area\n"));
       
   373         goto error;
       
   374     }
       
   375 
       
   376     if (xmlMemTraceBlockAt == ptr) {
       
   377         xmlGenericError(xmlGenericErrorContext,
       
   378                         EMBED_ERRTXT("%p : Freed()\n"), xmlMemTraceBlockAt);
       
   379         xmlMallocBreakpoint();
       
   380     }
       
   381 
       
   382     TEST_POINT
       
   383 
       
   384     target = (char *) ptr;
       
   385 
       
   386     p = CLIENT_2_HDR(ptr);
       
   387     if (p->mh_tag != MEMTAG) {
       
   388         Mem_Tag_Err(p);
       
   389         goto error;
       
   390     }
       
   391     p->mh_tag = ~MEMTAG;
       
   392     memset(target, -1, p->mh_size);
       
   393     xmlMutexLock(xmlMemMutex);
       
   394     debugMemSize -= p->mh_size;
       
   395 #ifdef MEM_LIST
       
   396     debugmem_list_delete(p);
       
   397 #endif
       
   398     xmlMutexUnlock(xmlMemMutex);
       
   399 
       
   400     free(p);
       
   401 
       
   402     TEST_POINT
       
   403 
       
   404     return;
       
   405 
       
   406 error:
       
   407     xmlGenericError(xmlGenericErrorContext,
       
   408         EMBED_ERRTXT("xmlMemFree(%lX) error\n"), (unsigned long) ptr);
       
   409     xmlMallocBreakpoint();
       
   410     return;
       
   411 }
       
   412 
       
   413 /**
       
   414  * xmlMemStrdupLoc:
       
   415  * @param str the initial string pointer
       
   416  * @param file the file name or NULL
       
   417  * @param line the line number
       
   418  *
       
   419  * a strdup() equivalent, with logging of the allocation info.
       
   420  *
       
   421  * Returns a pointer to the new string or NULL if allocation error occurred.
       
   422  */
       
   423 
       
   424 XMLPUBFUNEXPORT char *
       
   425 xmlMemStrdupLoc(const char *str, const char *file, int line)
       
   426 {
       
   427     LOAD_GS_DIRECT
       
   428     char *s;
       
   429     size_t size = strlen(str) + 1;
       
   430     MEMHDR *p;
       
   431 
       
   432     if (!xmlMemInitialized) xmlInitMemory();
       
   433     TEST_POINT
       
   434 
       
   435     p = (MEMHDR *) malloc(RESERVE_SIZE+size);
       
   436     if (!p) {
       
   437       goto error;
       
   438     }
       
   439     p->mh_tag = MEMTAG;
       
   440     p->mh_size = size;
       
   441     p->mh_type = STRDUP_TYPE;
       
   442     p->mh_file = file;
       
   443     p->mh_line = line;
       
   444     xmlMutexLock(xmlMemMutex);
       
   445     p->mh_number = ++g_block;
       
   446     debugMemSize += size;
       
   447     if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize;
       
   448 #ifdef MEM_LIST
       
   449     debugmem_list_add(p);
       
   450 #endif
       
   451     xmlMutexUnlock(xmlMemMutex);
       
   452 
       
   453     s = (char *) HDR_2_CLIENT(p);
       
   454 
       
   455     if (xmlMemStopAtBlock == p->mh_number) xmlMallocBreakpoint();
       
   456 
       
   457     if (s != NULL)
       
   458       strcpy(s,str);
       
   459     else
       
   460       goto error;
       
   461 
       
   462     TEST_POINT
       
   463 
       
   464     if (xmlMemTraceBlockAt == s) {
       
   465         xmlGenericError(xmlGenericErrorContext,
       
   466                         EMBED_ERRTXT("%p : Strdup() Ok\n"), xmlMemTraceBlockAt);
       
   467         xmlMallocBreakpoint();
       
   468     }
       
   469 
       
   470     return(s);
       
   471 
       
   472 error:
       
   473     return(NULL);
       
   474 }
       
   475 
       
   476 /**
       
   477  * xmlMemoryStrdup:
       
   478  * @param str the initial string pointer
       
   479  *
       
   480  * a strdup() equivalent, with logging of the allocation info.
       
   481  *
       
   482  * Returns a pointer to the new string or NULL if allocation error occurred.
       
   483  */
       
   484 XMLPUBFUNEXPORT char *
       
   485 xmlMemoryStrdup(const char *str) {
       
   486     return(xmlMemStrdupLoc(str, "none", 0));
       
   487 }
       
   488 
       
   489 /**
       
   490  * xmlMemUsed:
       
   491  *
       
   492  * Provides the amount of memory currently allocated
       
   493  *
       
   494  * Returns an int representing the amount of memory allocated.
       
   495  */
       
   496 
       
   497 XMLPUBFUNEXPORT int
       
   498 xmlMemUsed(void) {
       
   499 	LOAD_GS_DIRECT
       
   500      return(debugMemSize);
       
   501 }
       
   502 
       
   503 #ifdef MEM_LIST
       
   504 /**
       
   505  * xmlMemContentShow:
       
   506  * @param fp a FILE descriptor used as the output file
       
   507  * @param p a memory block header
       
   508  *
       
   509  * tries to show some content from the memory block
       
   510  */
       
   511 
       
   512 static void
       
   513 xmlMemContentShow(FILE *fp, MEMHDR *p)
       
   514 {
       
   515     int i,j,len = p->mh_size;
       
   516     const char *buf = (const char *) HDR_2_CLIENT(p);
       
   517 
       
   518     if (p == NULL) {
       
   519         fprintf(fp, " NULL");
       
   520         return;
       
   521     }
       
   522 
       
   523     for (i = 0;i < len;i++) {
       
   524         if (buf[i] == 0) break;
       
   525         if (!isprint((unsigned char) buf[i])) break;
       
   526     }
       
   527     if ((i < 4) && ((buf[i] != 0) || (i == 0))) {
       
   528         if (len >= 4) {
       
   529             MEMHDR *q;
       
   530             void *cur;
       
   531 
       
   532             for (j = 0;j < len -3;j += 4) {
       
   533                 cur = *((void **) &buf[j]);
       
   534                 q = CLIENT_2_HDR(cur);
       
   535                 p = memlist;
       
   536                 while (p != NULL) {
       
   537                     if (p == q) break;
       
   538                     p = p->mh_next;
       
   539                 }
       
   540                 if ((p != NULL) && (p == q)) {
       
   541                     fprintf(fp, " pointer to #%lu at index %d",
       
   542                             p->mh_number, j);
       
   543                     return;
       
   544                 }
       
   545             }
       
   546         }
       
   547     } else if ((i == 0) && (buf[i] == 0)) {
       
   548         fprintf(fp," null");
       
   549     } else {
       
   550         if (buf[i] == 0) fprintf(fp," \"%.25s\"", buf);
       
   551         else {
       
   552             fprintf(fp," [");
       
   553             for (j = 0;j < i;j++)
       
   554                 fprintf(fp,"%c", buf[j]);
       
   555             fprintf(fp,"]");
       
   556         }
       
   557     }
       
   558 }
       
   559 #endif
       
   560 
       
   561 #ifndef XMLENGINE_EXCLUDE_FILE_FUNC
       
   562 /**
       
   563  * xmlMemDisplay:
       
   564  * @param fp a FILE descriptor used as the output file, if NULL, the result is
       
   565  *       written to the file .memorylist
       
   566  *
       
   567  * show in-extenso the memory blocks allocated
       
   568  */
       
   569 void
       
   570 xmlMemDisplay(FILE *fp)
       
   571 {
       
   572 #ifdef MEM_LIST
       
   573     MEMHDR *p;
       
   574     unsigned idx;
       
   575     int     nb = 0;
       
   576 #if defined(HAVE_LOCALTIME) && defined(HAVE_STRFTIME)
       
   577     time_t currentTime;
       
   578     char buf[500];
       
   579     struct tm * tstruct;
       
   580 
       
   581     currentTime = time(NULL);
       
   582     tstruct = localtime(&currentTime);
       
   583     strftime(buf, sizeof(buf) - 1, "%I:%M:%S %p", tstruct);
       
   584     fprintf(fp,"      %s\n\n", buf);
       
   585 #endif
       
   586 
       
   587 
       
   588     fprintf(fp,"      MEMORY ALLOCATED : %lu, MAX was %lu\n",
       
   589             debugMemSize, debugMaxMemSize);
       
   590     fprintf(fp,"BLOCK  NUMBER   SIZE  TYPE\n");
       
   591     idx = 0;
       
   592     xmlMutexLock(xmlMemMutex);
       
   593     p = memlist;
       
   594     while (p) {
       
   595           fprintf(fp,"%-5u  %6lu %6lu ",idx++,p->mh_number,
       
   596                   (unsigned long)p->mh_size);
       
   597         switch (p->mh_type) {
       
   598            case STRDUP_TYPE:fprintf(fp,"strdup()  in ");break;
       
   599            case MALLOC_TYPE:fprintf(fp,"malloc()  in ");break;
       
   600           case REALLOC_TYPE:fprintf(fp,"realloc() in ");break;
       
   601            case MALLOC_ATOMIC_TYPE:fprintf(fp,"atomicmalloc()  in ");break;
       
   602           case REALLOC_ATOMIC_TYPE:fprintf(fp,"atomicrealloc() in ");break;
       
   603                     default:fprintf(fp,"   ???    in ");break;
       
   604         }
       
   605           if (p->mh_file != NULL) fprintf(fp,"%s(%d)", p->mh_file, p->mh_line);
       
   606         if (p->mh_tag != MEMTAG)
       
   607               fprintf(fp,"  INVALID");
       
   608         nb++;
       
   609         if (nb < 100)
       
   610             xmlMemContentShow(fp, p);
       
   611         else
       
   612             fprintf(fp," skip");
       
   613 
       
   614         fprintf(fp,"\n");
       
   615         p = p->mh_next;
       
   616     }
       
   617     xmlMutexUnlock(xmlMemMutex);
       
   618 #else
       
   619     fprintf(fp,EMBED_ERRTXT("Memory list not compiled (MEM_LIST not defined !)\n"));
       
   620 #endif
       
   621 }
       
   622 #endif /*  XMLENGINE_EXCLUDE_FILE_FUNC */
       
   623 
       
   624 #ifdef MEM_LIST
       
   625 
       
   626 static void debugmem_list_add(MEMHDR *p)
       
   627 {
       
   628      p->mh_next = memlist;
       
   629      p->mh_prev = NULL;
       
   630      if (memlist) memlist->mh_prev = p;
       
   631      memlist = p;
       
   632 #ifdef MEM_LIST_DEBUG
       
   633      if (stderr)
       
   634      Mem_Display(stderr);
       
   635 #endif
       
   636 }
       
   637 
       
   638 static void debugmem_list_delete(MEMHDR *p)
       
   639 {
       
   640      if (p->mh_next)
       
   641      p->mh_next->mh_prev = p->mh_prev;
       
   642      if (p->mh_prev)
       
   643      p->mh_prev->mh_next = p->mh_next;
       
   644      else memlist = p->mh_next;
       
   645 #ifdef MEM_LIST_DEBUG
       
   646      if (stderr)
       
   647      Mem_Display(stderr);
       
   648 #endif
       
   649 }
       
   650 
       
   651 #endif
       
   652 
       
   653 /*
       
   654  * debugmem_tag_error:
       
   655  *
       
   656  * internal error function.
       
   657  */
       
   658 
       
   659 static void debugmem_tag_error(void *p)
       
   660 {
       
   661      xmlGenericError(xmlGenericErrorContext,
       
   662          EMBED_ERRTXT("Memory tag error occurs :%p \n\t bye\n"), p);
       
   663 #ifdef MEM_LIST
       
   664      if (stderr)
       
   665      xmlMemDisplay(stderr);
       
   666 #endif
       
   667 }
       
   668 
       
   669 #ifdef MEM_LIST
       
   670 static FILE *xmlMemoryDumpFile = NULL;
       
   671 #endif
       
   672 
       
   673 #ifndef XMLENGINE_EXCLUDE_FILE_FUNC
       
   674 /**
       
   675  * xmlMemShow:
       
   676  * @param fp a FILE descriptor used as the output file
       
   677  * @param nr number of entries to dump
       
   678  *
       
   679  * show a show display of the memory allocated, and dump
       
   680  * the nr last allocated areas which were not freed
       
   681  */
       
   682 void
       
   683 xmlMemShow(FILE *fp, int nr ATTRIBUTE_UNUSED)
       
   684 {
       
   685 #ifdef MEM_LIST
       
   686     MEMHDR *p;
       
   687 #endif
       
   688 
       
   689     if (fp != NULL)
       
   690         fprintf(fp,EMBED_ERRTXT("      MEMORY ALLOCATED : %lu, MAX was %lu\n"),
       
   691                 debugMemSize, debugMaxMemSize);
       
   692 #ifdef MEM_LIST
       
   693     xmlMutexLock(xmlMemMutex);
       
   694     if (nr > 0) {
       
   695         fprintf(fp,"NUMBER   SIZE  TYPE   WHERE\n");
       
   696         p = memlist;
       
   697         while ((p) && nr > 0) {
       
   698               fprintf(fp,"%6lu %6lu ",p->mh_number,(unsigned long)p->mh_size);
       
   699             switch (p->mh_type) {
       
   700                case STRDUP_TYPE:fprintf(fp,"strdup()  in ");break;
       
   701                case MALLOC_TYPE:fprintf(fp,"malloc()  in ");break;
       
   702                case MALLOC_ATOMIC_TYPE:fprintf(fp,"atomicmalloc()  in ");break;
       
   703               case REALLOC_TYPE:fprintf(fp,"realloc() in ");break;
       
   704               case REALLOC_ATOMIC_TYPE:fprintf(fp,"atomicrealloc() in ");break;
       
   705                 default:fprintf(fp,"   ???    in ");break;
       
   706             }
       
   707             if (p->mh_file != NULL)
       
   708                 fprintf(fp,"%s(%d)", p->mh_file, p->mh_line);
       
   709             if (p->mh_tag != MEMTAG)
       
   710                 fprintf(fp,"  INVALID");
       
   711             xmlMemContentShow(fp, p);
       
   712             fprintf(fp,"\n");
       
   713             nr--;
       
   714             p = p->mh_next;
       
   715         }
       
   716     }
       
   717     xmlMutexUnlock(xmlMemMutex);
       
   718 #endif /* MEM_LIST */
       
   719 }
       
   720 #endif /*  XMLENGINE_EXCLUDE_FILE_FUNC */
       
   721 
       
   722 /**
       
   723  * xmlMemoryDump:
       
   724  *
       
   725  * Dump in-extenso the memory blocks allocated to the file .memorylist
       
   726  */
       
   727 
       
   728 XMLPUBFUNEXPORT void
       
   729 xmlMemoryDump(void)
       
   730 {
       
   731 #ifdef MEM_LIST
       
   732     FILE *dump;
       
   733 
       
   734     if (debugMaxMemSize == 0)
       
   735         return;
       
   736     dump = fopen(".memdump", "w");
       
   737     if (dump == NULL)
       
   738         xmlMemoryDumpFile = stderr;
       
   739     else xmlMemoryDumpFile = dump;
       
   740 
       
   741     xmlMemDisplay(xmlMemoryDumpFile);
       
   742 
       
   743     if (dump != NULL) fclose(dump);
       
   744 #endif /* MEM_LIST */
       
   745 }
       
   746 
       
   747 
       
   748 /****************************************************************
       
   749  *                                                              *
       
   750  *              Initialization Routines                         *
       
   751  *                                                              *
       
   752  ****************************************************************/
       
   753 
       
   754 /**
       
   755  * xmlInitMemory:
       
   756  *
       
   757  * Initialize the memory layer.
       
   758  *
       
   759  * Returns 0 on success
       
   760  *
       
   761  * OOM: maybe possible -- during calls to standard library (???)
       
   762  */
       
   763 XMLPUBFUNEXPORT int
       
   764 xmlInitMemory(void)
       
   765 {
       
   766 #ifdef DEBUG_MEMORY
       
   767      xmlGenericError(xmlGenericErrorContext, "xmlInitMemory() Ok\n");
       
   768 #endif
       
   769      return(0);
       
   770 }
       
   771 
       
   772 /**
       
   773  * xmlCleanupMemory:
       
   774  *
       
   775  * Free up all the memory associated with memorys
       
   776  *
       
   777  * OOM: never
       
   778  */
       
   779 XMLPUBFUNEXPORT void
       
   780 xmlCleanupMemory(void) {
       
   781 	LOAD_GS_DIRECT
       
   782     if (xmlMemInitialized == 0)
       
   783         return;
       
   784 
       
   785     xmlFreeMutex(xmlMemMutex);
       
   786     xmlMemInitialized = 0;
       
   787 }
       
   788