112     memcpy(data, ptr, 
size);
   133     memcpy(s, str, len + 1);
   149 #define SIZE(_size) (sizeof(WsMemBlockHdr) + (_size))   151 #define MAGIC 0xfe01fa77   153 struct WsMemBlockHdrRec
   156     struct WsMemBlockHdrRec *next;
   157     struct WsMemBlockHdrRec *prev;
   163 typedef struct WsMemBlockHdrRec WsMemBlockHdr;
   166 WsMemBlockHdr *blocks = NULL;
   169 unsigned int num_blocks = 0;
   172 unsigned int max_num_blocks = 0;
   179 size_t max_balance = 0;
   182 unsigned int alloc_number = 0;
   185 unsigned int num_successful_allocs = -1;
   188 static void add_block(WsMemBlockHdr *b, 
size_t size, 
const char *
file, 
int line)
   207     if (balance > max_balance)
   208         max_balance = balance;
   210     if (num_blocks > max_num_blocks)
   211         max_num_blocks = num_blocks;
   215 static void remove_block(WsMemBlockHdr *b)
   217     if (b->magic != MAGIC)
   218         ws_fatal(
"remove_block(): invalid magic\n");
   221         b->next->prev = b->prev;
   223         b->prev->next = b->next;
   230     memset(b, 0xfe, SIZE(b->size));
   234 void *ws_malloc_i(
size_t size, 
const char *
file, 
int line)
   238     if (alloc_number++ >= num_successful_allocs)
   252 void *ws_calloc_i(
size_t num, 
size_t size, 
const char *
file, 
int line)
   254     void *p = ws_malloc_i(num * 
size, 
file, line);
   257         memset(p, 0, num * 
size);
   263 void *ws_realloc_i(
void *ptr, 
size_t size, 
const char *
file, 
int line)
   265     WsMemBlockHdr *b = ((WsMemBlockHdr *) ptr) - 1;
   269         return ws_malloc_i(
size, 
file, line);
   280     memcpy(n, ptr, b->size);
   290 void *ws_memdup_i(
const void *ptr, 
size_t size, 
const char *
file, 
int line)
   292     void *p = ws_malloc_i(
size + 1, 
file, line);
   295         unsigned char *cp = (
unsigned char *) p;
   297         memcpy(p, ptr, 
size);
   305 void *ws_strdup_i(
const char *str, 
const char *
file, 
int line)
   307     return ws_memdup_i(str, strlen(str), 
file, line);
   311 void ws_free_i(
void *ptr)
   313     WsMemBlockHdr *b = ((WsMemBlockHdr *) ptr) - 1;
   323 int ws_has_leaks(
void)
   325     return num_blocks || balance;
   329 void ws_dump_blocks(
void)
   333     fprintf(stderr, 
"ws: maximum memory usage: %u blocks, %ld bytes\n",
   334             max_num_blocks, (
long) max_balance);
   335     fprintf(stderr, 
"ws: number of allocs: %u\n", alloc_number);
   337     if (num_blocks || balance) {
   338         fprintf(stderr, 
"ws: memory leaks: %u blocks, %ld bytes:\n",
   339                 num_blocks, (
long) balance);
   341         for (b = blocks; b; b = b->next)
   342             fprintf(stderr, 
"%s:%d: %ld\n", b->file, b->line, (
long) b->size);
   347 void ws_clear_leaks(
unsigned int num_successful_allocs_)
   350     num_successful_allocs = num_successful_allocs_;
 void ws_fatal(char *fmt,...)
 
void * ws_calloc(size_t num, size_t size)
 
void * ws_realloc(void *ptr, size_t size)
 
void * ws_memdup(const void *ptr, size_t size)
 
void * ws_strdup(const char *str)
 
void * ws_malloc(size_t size)