OSDN Git Service

Manuel Novoa III modified malloc.c and avlmacro.h to reduce code size by
authorEric Andersen <andersen@codepoet.org>
Fri, 12 Jan 2001 09:42:21 +0000 (09:42 -0000)
committerEric Andersen <andersen@codepoet.org>
Fri, 12 Jan 2001 09:42:21 +0000 (09:42 -0000)
using functions instead on Inlining (size vas speed tradeoff).  I ran the
results through indent.  Looking pretty good IMHO.

libc/stdlib/malloc/alloc.c
libc/stdlib/malloc/avlmacro.h
libc/stdlib/malloc/malloc.c

index 22d508c..4988bb0 100644 (file)
@@ -8,12 +8,14 @@
 
 #ifdef L_calloc_dbg
 
-void *
-calloc_dbg(size_t num, size_t size, char * function, char * file, int line)
+void *calloc_dbg(size_t num, size_t size, char *function, char *file,
+                                int line)
 {
-       void * ptr;
-       fprintf(stderr, "calloc of %ld bytes at %s @%s:%d = ", (long)(num*size), function, file, line);
-       ptr = calloc(num,size);
+       void *ptr;
+
+       fprintf(stderr, "calloc of %ld bytes at %s @%s:%d = ",
+                       (long) (num * size), function, file, line);
+       ptr = calloc(num, size);
        fprintf(stderr, "%p\n", ptr);
        return ptr;
 }
@@ -22,13 +24,14 @@ calloc_dbg(size_t num, size_t size, char * function, char * file, int line)
 
 #ifdef L_malloc_dbg
 
-void *
-malloc_dbg(size_t len, char * function, char * file, int line)
+void *malloc_dbg(size_t len, char *function, char *file, int line)
 {
-       void * result;
-       fprintf(stderr, "malloc of %ld bytes at %s @%s:%d = ", (long)len, function, file, line);
+       void *result;
+
+       fprintf(stderr, "malloc of %ld bytes at %s @%s:%d = ", (long) len,
+                       function, file, line);
        result = malloc(len);
-       fprintf(stderr, "%p\n", result);    
+       fprintf(stderr, "%p\n", result);
        return result;
 }
 
@@ -36,13 +39,11 @@ malloc_dbg(size_t len, char * function, char * file, int line)
 
 #ifdef L_free_dbg
 
-void
-free_dbg(void * ptr, char * function, char * file, int line)
+void free_dbg(void *ptr, char *function, char *file, int line)
 {
-       fprintf(stderr, "free of %p at %s @%s:%d\n", ptr, function, file, line);
-       free(ptr);
+       fprintf(stderr, "free of %p at %s @%s:%d\n", ptr, function, file,
+                       line);
+       free(ptr);
 }
 
 #endif
-
-
index 8050172..cce2c38 100644 (file)
@@ -2,9 +2,21 @@
 /* COPYRIGHT (C) 1998 VALERY SHCHEDRIN                               */
 /* IT IS DISTRIBUTED UNDER GLPL (GNU GENERAL LIBRARY PUBLIC LICENSE) */
 
-#define balance(objname, pr, root, ht_changed) \
+/*
+ * Manuel Novoa III       Jan 2001
+ *
+ * Modified to decrease object size.
+ *   Tree balancing is now done in a fuction rather than inline.
+ *   Removed common code in balance by use of a goto.
+ *   Added macro Avl_Tree_no_replace since ptrs_replace was not used.
+ *   Prepended may symbols with "__" for possible conversion to extern.
+ */
+
+#define __Avl_balance_proto(objname, pr, root) \
+  static int __Avl_##objname##pr##balance(objname **root) \
   { \
     objname *p; \
+    int ht_changed; \
     p = *root; \
     if (p->bal_##pr < -1) \
     { \
        pp=p->l_##pr; *root=p->l_##pr->r_##pr; p->l_##pr = (*root)->r_##pr; \
        (*root)->r_##pr = p; pp->r_##pr = (*root)->l_##pr; \
        p = *root; p->l_##pr = pp; \
-       if (p->bal_##pr > 0) p->l_##pr ->bal_##pr = -p->bal_##pr ; \
-       else p->l_##pr ->bal_##pr = 0; \
-       if (p->bal_##pr < 0) p->r_##pr ->bal_##pr = -p->bal_##pr ; \
-       else p->r_##pr ->bal_##pr = 0; \
-       p->bal_##pr = 0; \
-       ht_changed = 1; \
+    goto pr_common_ht_changed; \
       } \
       else \
       { \
@@ -37,6 +44,7 @@
        pp=p->r_##pr ; *root=p->r_##pr ->l_##pr ; p->r_##pr =(*root)->l_##pr ; \
        (*root)->l_##pr = p; pp->l_##pr = (*root)->r_##pr ; \
        p = *root; p->r_##pr = pp; \
+    pr_common_ht_changed: \
        if (p->bal_##pr > 0) p->l_##pr ->bal_##pr = -p->bal_##pr ; \
        else p->l_##pr ->bal_##pr = 0; \
        if (p->bal_##pr < 0) p->r_##pr ->bal_##pr = -p->bal_##pr ; \
        p->bal_##pr = - (--((*root)->bal_##pr )); \
       } \
     } else ht_changed = 0; \
+   return ht_changed; \
   }
 
-#define Avl_r_insert_proto(objname, pr, COMPARE) \
-  static int Avl_##objname##pr##_r_insert(objname **root) \
+#define balance(objname, pr, root) \
+  __Avl_##objname##pr##balance(root)
+
+#define __Avl_r_insert_proto(objname, pr, COMPARE) \
+  static int __Avl_##objname##pr##_r_insert(objname **root) \
   { \
     int i; /* height increase */ \
     if (!*root) \
     { \
-      *root = Avl_##objname##pr##_new_node; \
-      Avl_##objname##pr##_new_node = NULL; \
+      *root = __Avl_##objname##pr##_new_node; \
+      __Avl_##objname##pr##_new_node = NULL; \
       return 1; \
     } \
-    COMPARE(i, Avl_##objname##pr##_new_node, *root); \
+    COMPARE(i, __Avl_##objname##pr##_new_node, *root); \
     \
     if (i < 0) \
     { /* insert into the left subtree */ \
-      i = -Avl_##objname##pr##_r_insert(&((*root)->l_##pr)); \
-      if (Avl_##objname##pr##_new_node != NULL) return 0; /* already there */ \
+      i = -__Avl_##objname##pr##_r_insert(&((*root)->l_##pr)); \
+      if (__Avl_##objname##pr##_new_node != NULL) return 0; /* already there */ \
     } \
     else if (i > 0) \
     { /* insert into the right subtree */ \
-      i = Avl_##objname##pr##_r_insert(&((*root)->r_##pr)); \
-      if (Avl_##objname##pr##_new_node != NULL) return 0; /* already there */ \
+      i = __Avl_##objname##pr##_r_insert(&((*root)->r_##pr)); \
+      if (__Avl_##objname##pr##_new_node != NULL) return 0; /* already there */ \
     } \
     else \
     { /* found */ \
-      Avl_##objname##pr##_new_node = *root; \
+      __Avl_##objname##pr##_new_node = *root; \
       return 0; \
     } \
     if (!i) return 0; \
     (*root)->bal_##pr += i; /* update balance factor */ \
     if ((*root)->bal_##pr) \
     { \
-      balance(objname,pr,root,i); \
-      return 1-i; \
+      return 1 - balance(objname,pr,root); \
     } \
     else return 0; \
   }
 
-#define Avl_r_delete_proto(objname,pr,COMPARE) \
-  static int Avl_##objname##pr##_r_delete(objname **root) \
+#define __Avl_r_delete_proto(objname,pr,COMPARE) \
+  static int __Avl_##objname##pr##_r_delete(objname **root) \
   { \
     int i; /* height decrease */ \
     \
     if (!*root) return 0; /* not found */ \
     \
-    COMPARE(i, Avl_##objname##pr##_new_node, *root); \
+    COMPARE(i, __Avl_##objname##pr##_new_node, *root); \
     \
     if (i < 0) \
-      i = -Avl_##objname##pr##_r_delete(&((*root)->l_##pr)); \
+      i = -__Avl_##objname##pr##_r_delete(&((*root)->l_##pr)); \
     else if (i > 0) \
-      i =  Avl_##objname##pr##_r_delete(&((*root)->r_##pr)); \
+      i =  __Avl_##objname##pr##_r_delete(&((*root)->r_##pr)); \
     else \
     { \
       if (!(*root)->l_##pr) \
       } \
       else \
       { \
-       i = Avl_##objname##pr##_r_delfix(&((*root)->r_##pr)); \
-       Avl_##objname##pr##_new_node->l_##pr = (*root)->l_##pr; \
-       Avl_##objname##pr##_new_node->r_##pr = (*root)->r_##pr; \
-       Avl_##objname##pr##_new_node->bal_##pr = (*root)->bal_##pr; \
-       *root = Avl_##objname##pr##_new_node; \
+       i = __Avl_##objname##pr##_r_delfix(&((*root)->r_##pr)); \
+       __Avl_##objname##pr##_new_node->l_##pr = (*root)->l_##pr; \
+       __Avl_##objname##pr##_new_node->r_##pr = (*root)->r_##pr; \
+       __Avl_##objname##pr##_new_node->bal_##pr = (*root)->bal_##pr; \
+       *root = __Avl_##objname##pr##_new_node; \
       } \
     } \
     if (!i) return 0; \
     (*root)->bal_##pr -= i; \
     if ((*root)->bal_##pr) \
     { \
-      balance(objname,pr,root,i); \
-      return i; \
+      return balance(objname,pr,root); \
     } \
     return 1; \
   }
 
-#define Avl_r_delfix_proto(objname,pr) \
-  static int Avl_##objname##pr##_r_delfix(objname **root) \
+#define __Avl_r_delfix_proto(objname,pr) \
+  static int __Avl_##objname##pr##_r_delfix(objname **root) \
   { \
     int i; /* height decrease */ \
     \
     if (!(*root)->l_##pr) \
     { \
-      Avl_##objname##pr##_new_node = *root; \
+      __Avl_##objname##pr##_new_node = *root; \
       *root = (*root)->r_##pr; \
       return 1; \
     } \
-    i = -Avl_##objname##pr##_r_delfix(&((*root)->l_##pr)); \
+    i = -__Avl_##objname##pr##_r_delfix(&((*root)->l_##pr)); \
     if (!i) return 0; \
     (*root)->bal_##pr -= i; \
     if ((*root)->bal_##pr) \
     { \
-      balance(objname,pr,root,i); \
-      return i; \
+      return balance(objname,pr,root); \
     } \
     return 1; \
   }
 
-#define Avl_ins_proto(alias,objname,pr) \
-  static objname *##alias##_ins(objname *data) \
+#define __Avl_ins_proto(alias,objname,pr) \
+  objname *__##alias##_ins(objname *data) \
   { \
-    Avl_##objname##pr##_new_node = data; \
+    __Avl_##objname##pr##_new_node = data; \
     (data)->l_##pr = NULL; \
     (data)->r_##pr = NULL; \
     (data)->bal_##pr = 0; \
-    Avl_##objname##pr##_r_insert(&Avl_##objname##pr##_tree); \
-    if (Avl_##objname##pr##_new_node) \
-      return Avl_##objname##pr##_new_node; \
+    __Avl_##objname##pr##_r_insert(&__Avl_##objname##pr##_tree); \
+    if (__Avl_##objname##pr##_new_node) \
+      return __Avl_##objname##pr##_new_node; \
     return NULL; \
   }
 
-#define Avl_del_proto(alias,objname,pr) \
-  static void alias##_del(objname *data) \
+#define __Avl_del_proto(alias,objname,pr) \
+  void __##alias##_del(objname *data) \
   { \
-    Avl_##objname##pr##_new_node = data; \
-    Avl_##objname##pr##_r_delete(&Avl_##objname##pr##_tree); \
+    __Avl_##objname##pr##_new_node = data; \
+    __Avl_##objname##pr##_r_delete(&__Avl_##objname##pr##_tree); \
   }
 
-#define Avl_replace_proto(alias,objname,pr,COMPARE) \
-  static void alias##_replace(objname *data) \
+#define __Avl_replace_proto(alias,objname,pr,COMPARE) \
+  void __##alias##_replace(objname *data) \
   { \
-    objname **p = &Avl_##objname##pr##_tree; \
+    objname **p = &__Avl_##objname##pr##_tree; \
     int cmp; \
     while (*p) \
     { \
     } \
   }
 
-#define Avl_Root(objname,pr) Avl_##objname##pr##_tree
+#define Avl_Root(objname,pr) __Avl_##objname##pr##_tree
 
-#define Avl_Tree(alias,objname,pr,COMPARE) \
-static objname *Avl_##objname##pr##_tree = NULL; \
-static objname *Avl_##objname##pr##_new_node; \
-Avl_r_insert_proto(objname,pr,COMPARE) \
-Avl_r_delfix_proto(objname,pr) \
-Avl_r_delete_proto(objname,pr,COMPARE) \
-Avl_ins_proto(alias,objname,pr) \
-Avl_del_proto(alias,objname,pr) \
-Avl_replace_proto(alias,objname,pr,COMPARE)
+#define Avl_Tree_no_replace(alias,objname,pr,COMPARE) \
+objname *__Avl_##objname##pr##_tree = NULL; \
+static objname *__Avl_##objname##pr##_new_node; \
+__Avl_balance_proto(objname, pr, root) \
+__Avl_r_insert_proto(objname,pr,COMPARE) \
+__Avl_r_delfix_proto(objname,pr) \
+__Avl_r_delete_proto(objname,pr,COMPARE) \
+__Avl_ins_proto(alias,objname,pr) \
+__Avl_del_proto(alias,objname,pr)
 
+#define Avl_Tree(alias,objname,pr,COMPARE) \
+Avl_Tree_no_replace(alias,objname,pr,COMPARE) \
+__Avl_replace_proto(alias,objname,pr,COMPARE)
index a3f50fb..b20c093 100644 (file)
@@ -1,5 +1,5 @@
 /*
-  mmalloc - heap manager based on heavy use of virtual memory management.
+  malloc - heap manager based on heavy use of virtual memory management.
   Copyright (C) 1998   Valery Shchedrin
 
   This library is free software; you can redistribute it and/or
   
   Public Functions:
   
-  void *mmalloc(size_t size);
+  void *malloc(size_t size);
   
     Allocates `size` bytes
     returns NULL if no free memory available
   
-  void *mcalloc(size_t unit, size_t quantity);
+  void *calloc(size_t unit, size_t quantity);
   
     Allocates `quantity*unit` zeroed bytes via internal malloc call
   
-  void *mrealloc(void *ptr, size_t size);
+  void *realloc(void *ptr, size_t size);
   
     Reallocates already allocated block `ptr`, if `ptr` is not valid block
     then it works as malloc. NULL is returned if no free memory available
   
-  void *mrealloc_no_move(void *ptr, size_t size);
+  void *_realloc_no_move(void *ptr, size_t size);
   
     Reallocates already allocated block `ptr`, if `ptr` is not valid block
     or if reallocation can't be done with shrinking/expanding already
     allocated block NULL is returned
   
-  void mfree(void *ptr);
+  void free(void *ptr);
   
     Frees already allocated block, if `ptr` is incorrect one nothing will
     happen.
 */
 
+/*
+ * Manuel Novoa III         Jan 2001
+ *
+ * Modified to decrease object sizes.
+ *   Broke into independent object files.
+ *   Converted INIT_BLOCK() and FREE_MEM_DEL_BLOCK() from macros to functions.
+ */
+
 #define _POSIX_SOURCE
 #define _XOPEN_SOURCE
 #include <sys/types.h>
 #error This version does not support threads
 #else
 typedef int mutex_t;
+
 #define mutex_lock(x)
 #define mutex_unlock(x)
 #define mutex_init(x)
@@ -104,8 +113,13 @@ typedef int mutex_t;
 //static mutex_t malloc_lock = MUTEX_INITIALIZER;
 #endif
 
-static int mmalloc_initialized = -1;
+extern int __malloc_initialized;
+
+#ifdef L__malloc_init
+int __malloc_initialized = -1;
+
  /* -1 == uninitialized, 0 == initializing, 1 == initialized */
+#endif
 
 #ifndef MAP_FAILED
 #define MAP_FAILED ((void*)-1)
@@ -121,228 +135,299 @@ static int mmalloc_initialized = -1;
 
 /* guess pagesize */
 #ifndef M_PAGESIZE
- #ifdef _SC_PAGESIZE
-  #ifndef _SC_PAGE_SIZE
-   #define _SC_PAGE_SIZE _SC_PAGESIZE
-  #endif
- #endif
- #ifdef _SC_PAGE_SIZE
-  #define M_PAGESIZE sysconf(_SC_PAGE_SIZE)
- #else /* !_SC_PAGESIZE */
-  #if defined(BSD) || defined(DGUX) || defined(HAVE_GETPAGESIZE)
-   extern size_t getpagesize();
-   #define M_PAGESIZE getpagesize()
-  #else /* !HAVE_GETPAGESIZE */
-   #include <sys/param.h>
-   #ifdef EXEC_PAGESIZE
-    #define M_PAGESIZE EXEC_PAGESIZE
-   #else /* !EXEC_PAGESIZE */
-    #ifdef NBPG
-     #ifndef CLSIZE
-      #define M_PAGESIZE NBPG
-     #else /* !CLSIZE */
-      #define M_PAGESIZE (NBPG*CLSIZE)
-     #endif /* CLSIZE */
-    #else
-     #ifdef NBPC
-      #define M_PAGESIZE NBPC
-     #else /* !NBPC */
-      #ifdef PAGESIZE
-       #define M_PAGESIZE PAGESIZE
-      #else /* !PAGESIZE */
-       #define M_PAGESIZE 4096
-      #endif /* PAGESIZE */
-     #endif /* NBPC */
-    #endif /* NBPG */
-   #endif /* EXEC_PAGESIZE */
-  #endif /* HAVE_GETPAGESIZE */
- #endif /* _SC_PAGE_SIZE */
-#endif /* defined(M_PAGESIZE) */
+#ifdef _SC_PAGESIZE
+#ifndef _SC_PAGE_SIZE
+#define _SC_PAGE_SIZE _SC_PAGESIZE
+#endif
+#endif
+#ifdef _SC_PAGE_SIZE
+#define M_PAGESIZE sysconf(_SC_PAGE_SIZE)
+#else                                                  /* !_SC_PAGESIZE */
+#if defined(BSD) || defined(DGUX) || defined(HAVE_GETPAGESIZE)
+extern size_t getpagesize();
+
+#define M_PAGESIZE getpagesize()
+#else                                                  /* !HAVE_GETPAGESIZE */
+#include <sys/param.h>
+#ifdef EXEC_PAGESIZE
+#define M_PAGESIZE EXEC_PAGESIZE
+#else                                                  /* !EXEC_PAGESIZE */
+#ifdef NBPG
+#ifndef CLSIZE
+#define M_PAGESIZE NBPG
+#else                                                  /* !CLSIZE */
+#define M_PAGESIZE (NBPG*CLSIZE)
+#endif                                                 /* CLSIZE */
+#else
+#ifdef NBPC
+#define M_PAGESIZE NBPC
+#else                                                  /* !NBPC */
+#ifdef PAGESIZE
+#define M_PAGESIZE PAGESIZE
+#else                                                  /* !PAGESIZE */
+#define M_PAGESIZE 4096
+#endif                                                 /* PAGESIZE */
+#endif                                                 /* NBPC */
+#endif                                                 /* NBPG */
+#endif                                                 /* EXEC_PAGESIZE */
+#endif                                                 /* HAVE_GETPAGESIZE */
+#endif                                                 /* _SC_PAGE_SIZE */
+#endif                                                 /* defined(M_PAGESIZE) */
 
 /* HUNK MANAGER */
 
-typedef struct Hunk_s  Hunk_t;
+typedef struct Hunk_s Hunk_t;
 
-struct Hunk_s { /* Hunked block - 8 byte overhead */
-  int id; /* unique id */
-  unsigned int total:12, used:12, size : 8;
-  Hunk_t *next; /* next free in free_h */
+struct Hunk_s {                                        /* Hunked block - 8 byte overhead */
+       int id;                                         /* unique id */
+       unsigned int total:12, used:12, size:8;
+       Hunk_t *next;                           /* next free in __free_h */
 };
 
-static Hunk_t *free_h[HUNK_MAXSIZE+1]; /* free hash */
-int total_h[HUNK_MAXSIZE+1]; /* Hunk_t's `total` member */
-
 #define usagemap(h) (((unsigned char *)(h))+sizeof(Hunk_t))
 #define hunk_ptr(h) (((char*)(h))+sizeof(Hunk_t)+ALIGN(DIV8(h->total+7)))
 #define hunk(h)  ((Hunk_t*)(h))
 
-/* hunk_alloc allocates <= HUNK_MAXSIZE blocks */
-static void *hunk_alloc(int size)
+extern Hunk_t *__free_h[HUNK_MAXSIZE + 1];
+extern int __total_h[HUNK_MAXSIZE + 1];
+
+#ifdef L__malloc_init
+Hunk_t *__free_h[HUNK_MAXSIZE + 1];    /* free hash */
+int __total_h[HUNK_MAXSIZE + 1];       /* Hunk_t's `total` member */
+#endif
+
+extern void *__hunk_alloc(int size);
+
+#ifdef L_malloc
+/* __hunk_alloc allocates <= HUNK_MAXSIZE blocks */
+void *__hunk_alloc(int size)
 {
-  Hunk_t *p;
-  unsigned long *cpl;
-  int i, c;
-  
-  if (size >= HUNK_THRESHOLD) size = ALIGN(size);
-  
-  /* Look for already allocated hunkblocks */
-  if ((p = free_h[size]) == NULL)
-  {
-    if ((p = (Hunk_t*)mmap(HUNK_MSTART,HUNK_MSIZE,PROT_READ|PROT_WRITE,
+       Hunk_t *p;
+       unsigned long *cpl;
+       int i, c;
+
+       if (size >= HUNK_THRESHOLD)
+               size = ALIGN(size);
+
+       /* Look for already allocated hunkblocks */
+       if ((p = __free_h[size]) == NULL) {
+               if (
+                       (p =
+                        (Hunk_t *) mmap(HUNK_MSTART, HUNK_MSIZE,
+                                                        PROT_READ | PROT_WRITE,
 #ifdef __HAS_NO_MMU__
-       MAP_SHARED|MAP_ANONYMOUS
+                                                        MAP_SHARED | MAP_ANONYMOUS
 #else
-       MAP_PRIVATE|MAP_ANONYMOUS
+                                                        MAP_PRIVATE | MAP_ANONYMOUS
 #endif
-       ,0,0)) == (Hunk_t*)MAP_FAILED)
-      return NULL;
-    memset(p,0,HUNK_MSIZE);
-    p->id = HUNK_ID;
-    p->total = total_h[size];
-    /* p->used = 0; */
-    p->size = size;
-    /* p->next = (Hunk_t*)NULL; */
-    /* memset(usagemap(p), 0, bound); */
-    free_h[size] = p;
-  }
-
-  /* Locate free point in usagemap */
-  for (cpl=(unsigned long*)usagemap(p);*cpl==0xFFFFFFFF;cpl++);
-  i = ((unsigned char *)cpl) - usagemap(p);
-  if (*(unsigned short*)cpl != 0xFFFF) {
-    if (*(unsigned char*)cpl == 0xFF) {
-      c = *(int*)(((unsigned char *)cpl)+1); i++;
-      } else  c = *(int*)(unsigned char *)cpl;
-  } else {
-    i+=2; c = *(((unsigned char *)cpl)+2);
-    if (c == 0xFF) { c = *(int*)(((unsigned char *)cpl)+3); i++; }
-  }
-  EMUL8(i);
-  if ((c & 0xF) == 0xF) { c >>= 4; i+=4; }
-  if ((c & 0x3) == 0x3) { c >>= 2; i+=2; }
-  if (c & 1) i++;
-  
-  usagemap(p)[DIV8(i)] |= (1 << (i & 7)); /* set bit */
-  
-  /* Increment counter and update hashes */
-  if (++p->used == p->total)
-  {
-    free_h[p->size] = p->next;
-    p->next = NULL;
-  }
-  return hunk_ptr(p)+i*p->size;
+                                                        , 0, 0)) == (Hunk_t *) MAP_FAILED)
+                       return NULL;
+               memset(p, 0, HUNK_MSIZE);
+               p->id = HUNK_ID;
+               p->total = __total_h[size];
+               /* p->used = 0; */
+               p->size = size;
+               /* p->next = (Hunk_t*)NULL; */
+               /* memset(usagemap(p), 0, bound); */
+               __free_h[size] = p;
+       }
+
+       /* Locate free point in usagemap */
+       for (cpl = (unsigned long *) usagemap(p); *cpl == 0xFFFFFFFF; cpl++);
+       i = ((unsigned char *) cpl) - usagemap(p);
+       if (*(unsigned short *) cpl != 0xFFFF) {
+               if (*(unsigned char *) cpl == 0xFF) {
+                       c = *(int *) (((unsigned char *) cpl) + 1);
+                       i++;
+               } else
+                       c = *(int *) (unsigned char *) cpl;
+       } else {
+               i += 2;
+               c = *(((unsigned char *) cpl) + 2);
+               if (c == 0xFF) {
+                       c = *(int *) (((unsigned char *) cpl) + 3);
+                       i++;
+               }
+       }
+       EMUL8(i);
+       if ((c & 0xF) == 0xF) {
+               c >>= 4;
+               i += 4;
+       }
+       if ((c & 0x3) == 0x3) {
+               c >>= 2;
+               i += 2;
+       }
+       if (c & 1)
+               i++;
+
+       usagemap(p)[DIV8(i)] |= (1 << (i & 7)); /* set bit */
+
+       /* Increment counter and update hashes */
+       if (++p->used == p->total) {
+               __free_h[p->size] = p->next;
+               p->next = NULL;
+       }
+       return hunk_ptr(p) + i * p->size;
 }
+#endif                                                 /* L_malloc */
+
+extern void __hunk_free(char *ptr);
 
-/* hunk_free frees blocks allocated by hunk_alloc */
-static void hunk_free(char *ptr)
+#ifdef L__free_support
+/* __hunk_free frees blocks allocated by __hunk_alloc */
+void __hunk_free(char *ptr)
 {
-  unsigned char *up;
-  int i, v;
-  Hunk_t *h;
-  
-  if (!ptr) return;
-  
-  h = (Hunk_t*)PAGE_DOWNALIGNP(ptr);
-  
-  /* Validate `ptr` */
-  if (h->id != HUNK_ID) return;
-  v = ptr - hunk_ptr(h);
-  i = v / h->size;
-  if (v % h->size != 0 || i < 0 || i >= h->total) return;
-  
-  /* Update `usagemap` */
-  up = &(usagemap(h)[DIV8(i)]);
-  i = 1 << (i&7);
-  if (!(*up & i)) return;
-  *up ^= i;
-  
-  /* Update hunk counters */
-  if (h->used == h->total)
-  {
-    if (--h->used)
-    { /* insert into free_h */
-      h->next = free_h[h->size];
-      free_h[h->size] = h;
-    } /* else - it will be unmapped */
-  }
-  else
-  {
-    if (!--h->used)
-    { /* delete from free_h - will be bl_freed*/
-      Hunk_t *p, *pp;
-      for (p=free_h[h->size],pp=NULL;p!=h;pp=p,p=p->next);
-      if (!pp)
-       free_h[h->size] = p->next;
-      else
-       pp->next = p->next;
-    }
-  }
-  
-  /* Unmap empty Hunk_t */
-  if (!h->used) munmap((void*)h,HUNK_MSIZE);
+       unsigned char *up;
+       int i, v;
+       Hunk_t *h;
+
+       if (!ptr)
+               return;
+
+       h = (Hunk_t *) PAGE_DOWNALIGNP(ptr);
+
+       /* Validate `ptr` */
+       if (h->id != HUNK_ID)
+               return;
+       v = ptr - hunk_ptr(h);
+       i = v / h->size;
+       if (v % h->size != 0 || i < 0 || i >= h->total)
+               return;
+
+       /* Update `usagemap` */
+       up = &(usagemap(h)[DIV8(i)]);
+       i = 1 << (i & 7);
+       if (!(*up & i))
+               return;
+       *up ^= i;
+
+       /* Update hunk counters */
+       if (h->used == h->total) {
+               if (--h->used) {                /* insert into __free_h */
+                       h->next = __free_h[h->size];
+                       __free_h[h->size] = h;
+               }                                               /* else - it will be unmapped */
+       } else {
+               if (!--h->used) {               /* delete from __free_h - will be __bl_freed */
+                       Hunk_t *p, *pp;
+
+                       for (p = __free_h[h->size], pp = NULL; p != h;
+                                pp = p, p = p->next);
+                       if (!pp)
+                               __free_h[h->size] = p->next;
+                       else
+                               pp->next = p->next;
+               }
+       }
+
+       /* Unmap empty Hunk_t */
+       if (!h->used)
+               munmap((void *) h, HUNK_MSIZE);
 }
+#endif                                                 /* L__free_support */
 
 /* BLOCK MANAGER */
 
 typedef struct Block_s Block_t;
 
-struct Block_s /* 32-bytes long control structure (if 4-byte aligned) */
-{
-  char *ptr;                        /* pointer to related data */
-  Block_t *next;                    /* next in free_mem list */
-  Block_t *l_free_mem, *r_free_mem; /* left & right subtrees of <free_mem> */
-  Block_t *l_ptrs, *r_ptrs;         /* left & right subtrees of <ptrs> */
-  size_t size;                      /* size - divided by align */
+struct Block_s {                               /* 32-bytes long control structure (if 4-byte aligned) */
+       char *ptr;                                      /* pointer to related data */
+       Block_t *next;                          /* next in free_mem list */
+       Block_t *l_free_mem, *r_free_mem;       /* left & right subtrees of <free_mem> */
+       Block_t *l_ptrs, *r_ptrs;       /* left & right subtrees of <ptrs> */
+       size_t size;                            /* size - divided by align */
 
-  /* packed 4-byte attributes */
+       /* packed 4-byte attributes */
 /* { */
-  signed char bal_free_mem : 8;   /* balance of <free_mem> subtree */
-  signed char bal_ptrs : 8;       /* balance of <ptrs> subtree */
-  unsigned int used : 1;   /* used/free state of the block */
-  unsigned int broken : 1; /* 1 if previous block can't be merged with it */
+       signed char bal_free_mem:8;     /* balance of <free_mem> subtree */
+       signed char bal_ptrs:8;         /* balance of <ptrs> subtree */
+       unsigned int used:1;            /* used/free state of the block */
+       unsigned int broken:1;          /* 1 if previous block can't be merged with it */
 /* } */
 };
 
-static Block_t *bl_last; /* last mmapped block */
+extern Block_t *__bl_last;             /* last mmapped block */
 
-#define bl_get() hunk_alloc(sizeof(Block_t))
-#define bl_rel(p) hunk_free((char*)p)
+#ifdef L__malloc_init
+Block_t *__bl_last;                            /* last mmapped block */
+#endif
 
-/* like C++ templates ;-) */
+#define bl_get() __hunk_alloc(sizeof(Block_t))
+#define bl_rel(p) __hunk_free((char*)p)
+
+extern Block_t *__Avl_Block_tfree_mem_tree;
+extern Block_t *__free_mem_ins(Block_t * data);
+extern void __free_mem_del(Block_t * data);
+extern void __free_mem_replace(Block_t * data);
+extern Block_t *__Avl_Block_tptrs_tree;
+extern Block_t *__ptrs_ins(Block_t * data);
+extern void __ptrs_del(Block_t * data);
 
+extern void __bl_uncommit(Block_t * b);
+extern void __bl_free(Block_t * b);
+
+/* like C++ templates ;-) */
 #include "avlmacro.h"
 
-#define FREE_MEM_COMPARE(i,a,b) { i = (a)->size - (b)->size; }
-#define PTRS_COMPARE(i,a,b) { i = (a)->ptr - (b)->ptr; }
+#define FREE_MEM_COMPARE(i,a,b) \
+{ \
+  if ( (a)->size < (b)->size ) { \
+     i = -1; \
+  } else if ( (a)->size > (b)->size ) { \
+     i = 1; \
+  } else { \
+     i = 0; \
+  } \
+}
 
-Avl_Tree(free_mem,Block_t,free_mem,FREE_MEM_COMPARE)
-Avl_Tree(ptrs,Block_t,ptrs,PTRS_COMPARE)
+#define PTRS_COMPARE(i,a,b) \
+{ \
+  if ( (a)->ptr < (b)->ptr ) { \
+     i = -1; \
+  } else if ( (a)->ptr > (b)->ptr ) { \
+     i = 1; \
+  } else { \
+     i = 0; \
+  } \
+}
 
+#ifdef L__avl_support
+Avl_Tree(free_mem, Block_t, free_mem, FREE_MEM_COMPARE)
+       Avl_Tree_no_replace(ptrs, Block_t, ptrs, PTRS_COMPARE)
+#endif
 #define free_mem_root Avl_Root(Block_t, free_mem)
 #define ptrs_root Avl_Root(Block_t, ptrs)
-
 /* pp is freed block */
-#define FREE_MEM_DEL_BLOCK(pp) \
-{ \
-  for (p = free_mem_root;;) \
-    if (p->size > pp->size) p = p->l_free_mem; \
-    else if (p->size < pp->size) p = p->r_free_mem; \
-    else break; \
-  if (p == pp) \
-  { \
-    if (pp->next) free_mem_replace(pp->next); \
-    else free_mem_del(pp); \
-  } \
-  else \
-  { \
-    for (;p->next != pp; p = p->next); \
-    p->next = pp->next; \
-  } \
+#define FREE_MEM_DEL_BLOCK(pp,p) {p = __free_mem_del_block(pp,p);}
+extern Block_t *__free_mem_del_block(Block_t * pp, Block_t * p);
+
+#ifdef L_malloc
+Block_t *__free_mem_del_block(Block_t * pp, Block_t * p)
+{
+       for (p = free_mem_root;;)
+               if (p->size > pp->size)
+                       p = p->l_free_mem;
+               else if (p->size < pp->size)
+                       p = p->r_free_mem;
+               else
+                       break;
+       if (p == pp) {
+               if (pp->next)
+                       __free_mem_replace(pp->next);
+               else
+                       __free_mem_del(pp);
+       } else {
+               for (; p->next != pp; p = p->next);
+               p->next = pp->next;
+       }
+       return p;
 }
+#endif                                                 /* L_malloc */
 
 #define FREE_MEM_INS_BLOCK(pp) \
 { \
-  if ((p = free_mem_ins(pp)) != NULL)\
+  if ((p = __free_mem_ins(pp)) != NULL)\
   {\
     pp->next = p->next;\
     p->next = pp;\
@@ -353,21 +438,30 @@ Avl_Tree(ptrs,Block_t,ptrs,PTRS_COMPARE)
 /* `b` is current block, `pp` is next block */
 #define COMBINE_BLOCKS(b,pp) \
 {\
-  ptrs_del(pp); \
+  __ptrs_del(pp); \
   b->size += pp->size; \
-  if (pp == bl_last) bl_last = b; \
+  if (pp == __bl_last) __bl_last = b; \
   bl_rel(pp); \
 }
 
 /* initializes new block b */
-#define INIT_BLOCK(b, pppp, sz) \
-{ \
-  memset(b, 0, sizeof(Block_t)); \
-  b->ptr  = pppp; \
-  b->size = sz; \
-  ptrs_ins(b); \
-  FREE_MEM_INS_BLOCK(b); \
+#define INIT_BLOCK(b, pppp, sz) { p = __init_block(b, pppp, sz); }
+
+extern Block_t *__init_block(Block_t * b, char *pppp, size_t sz);
+
+#ifdef L_malloc
+Block_t *__init_block(Block_t * b, char *pppp, size_t sz)
+{
+       Block_t *p;
+
+       memset(b, 0, sizeof(Block_t));
+       b->ptr = pppp;
+       b->size = sz;
+       __ptrs_ins(b);
+       FREE_MEM_INS_BLOCK(b);
+       return p;
 }
+#endif                                                 /* L_malloc */
 
 /* `b` is current block, `sz` its new size */
 /* block `b` will be splitted to one busy & one free block */
@@ -377,393 +471,407 @@ Avl_Tree(ptrs,Block_t,ptrs,PTRS_COMPARE)
   bt = bl_get(); \
   INIT_BLOCK(bt, b->ptr + sz, b->size - sz); \
   b->size = sz; \
-  if (bl_last == b) bl_last = bt; \
-  bl_uncommit(bt);\
+  if (__bl_last == b) __bl_last = bt; \
+  __bl_uncommit(bt);\
 }
 
 /* `b` is current block, `pp` is next free block, `sz` is needed size */
 #define SHRINK_BLOCK(b,pp,sz) \
 {\
-  FREE_MEM_DEL_BLOCK(pp); \
+  FREE_MEM_DEL_BLOCK(pp,p); \
   pp->ptr = b->ptr + sz; \
   pp->size += b->size - sz; \
   b->size = sz; \
   FREE_MEM_INS_BLOCK(pp); \
-  bl_uncommit(pp); \
+  __bl_uncommit(pp); \
 }
 
+#ifdef L_malloc
 static Block_t *bl_mapnew(size_t size)
 {
-  size_t map_size;
-  Block_t *pp, *p;
-  void *pt;
-  
-  map_size = PAGE_ALIGN(size);
-  pt = mmap(LARGE_MSTART,map_size,PROT_READ|PROT_WRITE|PROT_EXEC,
-            MAP_PRIVATE|MAP_ANON,0,0);
-  if (pt == MAP_FAILED) return (Block_t*)NULL;
-  
-  bl_last = pp = bl_get();
-  INIT_BLOCK(pp, (char*)pt, map_size);
-  pp->broken = 1;
-  
-  return pp;
+       size_t map_size;
+       Block_t *pp, *p;
+       void *pt;
+
+       map_size = PAGE_ALIGN(size);
+       pt = mmap(LARGE_MSTART, map_size, PROT_READ | PROT_WRITE | PROT_EXEC,
+                         MAP_PRIVATE | MAP_ANON, 0, 0);
+       if (pt == MAP_FAILED)
+               return (Block_t *) NULL;
+
+       __bl_last = pp = bl_get();
+       INIT_BLOCK(pp, (char *) pt, map_size);
+       pp->broken = 1;
+
+       return pp;
 }
 
-static void bl_uncommit(Block_t *b)
+void __bl_uncommit(Block_t * b)
 {
-  char *u_start, *u_end;
-  
-  u_start = PAGE_ALIGNP(b->ptr);
-  u_end   = PAGE_DOWNALIGNP(b->ptr+b->size);
-  if (u_end <= u_start) return;
+       char *u_start, *u_end;
+
+       u_start = PAGE_ALIGNP(b->ptr);
+       u_end = PAGE_DOWNALIGNP(b->ptr + b->size);
+       if (u_end <= u_start)
+               return;
 
 #if M_DOTRIMMING
-  mmap(u_start,u_end-u_start,PROT_READ|PROT_WRITE|PROT_EXEC,
-    MAP_PRIVATE|MAP_ANON|MAP_FIXED,0,0);
+       mmap(u_start, u_end - u_start, PROT_READ | PROT_WRITE | PROT_EXEC,
+                MAP_PRIVATE | MAP_ANON | MAP_FIXED, 0, 0);
 #endif
 }
 
 /* requested size must be aligned to ALIGNMENT */
 static Block_t *bl_alloc(size_t size)
 {
-  Block_t *p, *pp;
-  
-  /* try to find needed space in existing memory */
-  for (p = free_mem_root, pp = NULL;p;)
-  {
-    if (p->size > size) { pp = p; p = p->l_free_mem; }
-    else if (p->size < size) p = p->r_free_mem;
-    else { pp = p; break; }
-  }
-
-  if (!pp)
-  { /* map some memory */
-    if (!bl_last)
-    { /* just do initial mmap */
-      pp = bl_mapnew(size);
-      if (!pp) return NULL;
-    }
-    else if (!bl_last->used)
-    { /* try growing last unused */
-      if (mremap(PAGE_DOWNALIGNP(bl_last->ptr),
- PAGE_ALIGNP(bl_last->ptr+bl_last->size) - PAGE_DOWNALIGNP(bl_last->ptr),
- PAGE_ALIGNP(bl_last->ptr+size)-PAGE_DOWNALIGNP(bl_last->ptr),
-        0) == MAP_FAILED)
-      { /* unable to grow -- initiate new block */
-       pp = bl_mapnew(size);
-       if (!pp) return NULL;
-      }
-      else
-      {
-       pp = bl_last;
-       FREE_MEM_DEL_BLOCK(pp);
-       pp->size = PAGE_ALIGNP(pp->ptr+size) - pp->ptr;
-       FREE_MEM_INS_BLOCK(pp);
-      }
-    }
-    else
-    { /* bl_last is used block */
-      if (mremap(PAGE_DOWNALIGNP(bl_last->ptr),
-PAGE_ALIGNP(bl_last->ptr+bl_last->size)-PAGE_DOWNALIGNP(bl_last->ptr),
-PAGE_ALIGNP(bl_last->ptr+bl_last->size+size) - PAGE_DOWNALIGNP(bl_last->ptr),
-       0) == MAP_FAILED)
-      {
-       pp = bl_mapnew(size);
-       if (!pp) return NULL;
-      }
-      else
-      {
-       pp = bl_get();
-       INIT_BLOCK(pp,bl_last->ptr+bl_last->size,
- PAGE_ALIGNP(bl_last->ptr+bl_last->size+size)-bl_last->ptr-bl_last->size);
-       bl_last = pp;
-      }
-    }
-  }
-  
-  /* just delete this node from free_mem tree */
-  if (pp->next) free_mem_replace(pp->next); else free_mem_del(pp);
-  pp->used = 1;
-  
-  if (pp->size - size > MALLOC_ALIGN)
-  { /* this block can be splitted (it is unused,not_broken) */
-    SPLIT_BLOCK(pp,size);
-  }
-  
-  return pp;
-}
+       Block_t *p, *pp;
+
+       /* try to find needed space in existing memory */
+       for (p = free_mem_root, pp = NULL; p;) {
+               if (p->size > size) {
+                       pp = p;
+                       p = p->l_free_mem;
+               } else if (p->size < size)
+                       p = p->r_free_mem;
+               else {
+                       pp = p;
+                       break;
+               }
+       }
 
-static void bl_free(Block_t *b)
-{
-  Block_t *p, *bl_next, *bl_prev;
-  
-  /* Look for blocks before & after `b` */
-  for (p = ptrs_root, bl_next = NULL, bl_prev = NULL; p;)
-  {
-    if      (p->ptr > b->ptr) { bl_next = p; p = p->l_ptrs; }
-    else if (p->ptr < b->ptr) { bl_prev = p; p = p->r_ptrs; }
-    else break;
-  }
-  if (b->l_ptrs)
-    for (bl_prev = b->l_ptrs; bl_prev->r_ptrs; bl_prev = bl_prev->r_ptrs);
-  if (b->r_ptrs)
-    for (bl_next = b->r_ptrs; bl_next->l_ptrs; bl_next = bl_next->l_ptrs);
-  
-  if (bl_next && !bl_next->broken && !bl_next->used)
-  {
-    FREE_MEM_DEL_BLOCK(bl_next)
-    COMBINE_BLOCKS(b,bl_next)
-  }
-
-  if (bl_prev && !b->broken && !bl_prev->used)
-  {
-    FREE_MEM_DEL_BLOCK(bl_prev)
-    COMBINE_BLOCKS(bl_prev,b)
-    b = bl_prev;
-  }
-  
-  b->used = 0;
-  FREE_MEM_INS_BLOCK(b)
-  bl_uncommit(b);
+       if (!pp) {                                      /* map some memory */
+               if (!__bl_last) {               /* just do initial mmap */
+                       pp = bl_mapnew(size);
+                       if (!pp)
+                               return NULL;
+               } else if (!__bl_last->used) {  /* try growing last unused */
+                       if (mremap(PAGE_DOWNALIGNP(__bl_last->ptr),
+                                          PAGE_ALIGNP(__bl_last->ptr + __bl_last->size) -
+                                          PAGE_DOWNALIGNP(__bl_last->ptr),
+                                          PAGE_ALIGNP(__bl_last->ptr + size) -
+                                          PAGE_DOWNALIGNP(__bl_last->ptr), 0) == MAP_FAILED) { /* unable to grow -- initiate new block */
+                               pp = bl_mapnew(size);
+                               if (!pp)
+                                       return NULL;
+                       } else {
+                               pp = __bl_last;
+                               FREE_MEM_DEL_BLOCK(pp, p);
+                               pp->size = PAGE_ALIGNP(pp->ptr + size) - pp->ptr;
+                               FREE_MEM_INS_BLOCK(pp);
+                       }
+               } else {                                /* __bl_last is used block */
+                       if (mremap(PAGE_DOWNALIGNP(__bl_last->ptr),
+                                          PAGE_ALIGNP(__bl_last->ptr + __bl_last->size) -
+                                          PAGE_DOWNALIGNP(__bl_last->ptr),
+                                          PAGE_ALIGNP(__bl_last->ptr + __bl_last->size +
+                                                                  size) - PAGE_DOWNALIGNP(__bl_last->ptr),
+                                          0) == MAP_FAILED) {
+                               pp = bl_mapnew(size);
+                               if (!pp)
+                                       return NULL;
+                       } else {
+                               pp = bl_get();
+                               INIT_BLOCK(pp, __bl_last->ptr + __bl_last->size,
+                                                  PAGE_ALIGNP(__bl_last->ptr + __bl_last->size +
+                                                                          size) - __bl_last->ptr -
+                                                  __bl_last->size);
+                               __bl_last = pp;
+                       }
+               }
+       }
+
+       /* just delete this node from free_mem tree */
+       if (pp->next)
+               __free_mem_replace(pp->next);
+       else
+               __free_mem_del(pp);
+       pp->used = 1;
+
+       if (pp->size - size > MALLOC_ALIGN) {   /* this block can be splitted (it is unused,not_broken) */
+               SPLIT_BLOCK(pp, size);
+       }
+
+       return pp;
 }
+#endif                                                 /* L_malloc */
 
-static void malloc_init(void)
+#ifdef L__free_support
+void __bl_free(Block_t * b)
 {
-  int i, mapsize, x, old_x, gcount;
-  
-  mapsize = M_PAGESIZE;
-  
-  mmalloc_initialized = 0;
-  bl_last = NULL;
-  free_mem_root = NULL;
-  ptrs_root = NULL;
-  mapsize -= sizeof(Hunk_t);
-  for (i = 1; i <= HUNK_MAXSIZE; i++)
-  {
-    free_h[i] = (Hunk_t*)NULL;
-    for (x = mapsize/i, gcount = 0, old_x = 0; old_x != x;)
-    {
-      old_x = x;
-      x = (mapsize - ALIGN(DIV8(old_x+7)))/i;
-      if (gcount > 1 && x*i + ALIGN(DIV8(x+7)) <= mapsize) break;
-      if (x*i + ALIGN(DIV8(x+7)) > mapsize) gcount++;
-    }
-    total_h[i] = x;
-  }
-  mutex_init(&malloc_lock);
-  mmalloc_initialized = 1;
+       Block_t *p, *bl_next, *bl_prev;
+
+       /* Look for blocks before & after `b` */
+       for (p = ptrs_root, bl_next = NULL, bl_prev = NULL; p;) {
+               if (p->ptr > b->ptr) {
+                       bl_next = p;
+                       p = p->l_ptrs;
+               } else if (p->ptr < b->ptr) {
+                       bl_prev = p;
+                       p = p->r_ptrs;
+               } else
+                       break;
+       }
+       if (b->l_ptrs)
+               for (bl_prev = b->l_ptrs; bl_prev->r_ptrs;
+                        bl_prev = bl_prev->r_ptrs);
+       if (b->r_ptrs)
+               for (bl_next = b->r_ptrs; bl_next->l_ptrs;
+                        bl_next = bl_next->l_ptrs);
+
+       if (bl_next && !bl_next->broken && !bl_next->used) {
+               FREE_MEM_DEL_BLOCK(bl_next, p)
+                       COMBINE_BLOCKS(b, bl_next)
+       }
+
+       if (bl_prev && !b->broken && !bl_prev->used) {
+               FREE_MEM_DEL_BLOCK(bl_prev, p)
+                       COMBINE_BLOCKS(bl_prev, b)
+                       b = bl_prev;
+       }
+
+       b->used = 0;
+       FREE_MEM_INS_BLOCK(b)
+               __bl_uncommit(b);
 }
+#endif                                                 /* L__free_support */
 
-static void *mmalloc(size_t size)
+extern void __malloc_init(void);
+
+#ifdef L__malloc_init
+void __malloc_init(void)
 {
-  void *p;
-  
-  if (size == 0) return NULL;
-  if (mmalloc_initialized < 0) malloc_init();
-  if (mmalloc_initialized) mutex_lock(&malloc_lock);
-  
-  if (size <= HUNK_MAXSIZE)
-    p = hunk_alloc(size);
-  else
-  {
-    if ((p = bl_alloc(ALIGN(size))) != NULL)
-      p = ((Block_t*)p)->ptr;
-  }
-  
-  if (mmalloc_initialized) mutex_unlock(&malloc_lock);
-  
-  return p;
+       int i, mapsize, x, old_x, gcount;
+
+       mapsize = M_PAGESIZE;
+
+       __malloc_initialized = 0;
+       __bl_last = NULL;
+       free_mem_root = NULL;
+       ptrs_root = NULL;
+       mapsize -= sizeof(Hunk_t);
+       for (i = 1; i <= HUNK_MAXSIZE; i++) {
+               __free_h[i] = (Hunk_t *) NULL;
+               for (x = mapsize / i, gcount = 0, old_x = 0; old_x != x;) {
+                       old_x = x;
+                       x = (mapsize - ALIGN(DIV8(old_x + 7))) / i;
+                       if (gcount > 1 && x * i + ALIGN(DIV8(x + 7)) <= mapsize)
+                               break;
+                       if (x * i + ALIGN(DIV8(x + 7)) > mapsize)
+                               gcount++;
+               }
+               __total_h[i] = x;
+       }
+       mutex_init(&malloc_lock);
+       __malloc_initialized = 1;
 }
+#endif                                                 /* L__malloc_init */
 
-static void mfree(void *ptr)
+#ifdef L_malloc
+void *malloc(size_t size)
 {
-  Block_t *p, *best;
-  if (mmalloc_initialized < 0) return;
-  if (mmalloc_initialized) mutex_lock(&malloc_lock);
-  
-  for (p = ptrs_root, best = NULL;p;)
-  {
-    if (p->ptr > (char*)ptr) p = p->l_ptrs;
-    else { best = p; p = p->r_ptrs; }
-  }
-  
-  if (!best || !best->used || best->ptr != (char*)ptr)
-  {
-    hunk_free(ptr);
-    if (mmalloc_initialized) mutex_unlock(&malloc_lock);
-    return;
-  }
-  
-  bl_free(best);
+       void *p;
 
-  if (mmalloc_initialized) mutex_unlock(&malloc_lock);
-}
+       if (size == 0)
+               return NULL;
 
-static void *mrealloc_no_move(void *ptr, size_t size)
-{
-  Block_t *p, *best, *next;
-  
-  if (size <= HUNK_MAXSIZE) return NULL;
-  
-  if (mmalloc_initialized <= 0) return mmalloc(size);
-  
-  mutex_lock(&malloc_lock);
-  
-  /* Locate block */
-  for (p = ptrs_root, best = NULL;p;)
-  {
-    if (p->ptr > (char*)ptr) p = p->l_ptrs;
-    else { best = p; p = p->r_ptrs; }
-  }
-  
-  if (!best || !best->used || best->ptr != (char*)ptr)
-  {
-    mutex_unlock(&malloc_lock);
-    return NULL;
-  }
-  
-  size = ALIGN(size);
-  
-  if (size == best->size)
-  {
-    mutex_unlock(&malloc_lock);
-    return ptr;
-  }
-  
-  if (best->r_ptrs) /* get block just after */
-    for (next = best->r_ptrs; next->l_ptrs; next = next->l_ptrs);
-  else
-    for (p = ptrs_root, next = NULL;p;)
-    {
-      if (p->ptr > best->ptr) { next = p; p = p->l_ptrs; }
-      else if (p->ptr < best->ptr) p = p->r_ptrs;
-      else break;
-    }
-  
-  if (size < best->size)
-  { /* shrink block */
-    if (!next || next->used || next->broken)
-    {
-      if (best->size - size > MALLOC_ALIGN)
-      { /* do split */
-       SPLIT_BLOCK(best,size);
-      }
-    }
-    else
-    { /* just move border of next block */
-      SHRINK_BLOCK(best,next,size);
-    }
-  }
-  else if (next && !next->broken && !next->used)
-  { /* can expand */
-    if (best->size + next->size > size + HUNK_MAXSIZE)
-    { /* shrink next free block */
-      SHRINK_BLOCK(best,next,size);
-    }
-    else if (best->size + next->size >= size)
-    { /* combine blocks (eat next one) */
-      FREE_MEM_DEL_BLOCK(next);
-      COMBINE_BLOCKS(best,next);
-    }
-    else
-    { /* not enough memory in next block */
-      mutex_unlock(&malloc_lock);
-      return NULL;
-    }
-  }
-  else
-  { /* no next block */
-    mutex_unlock(&malloc_lock);
-    return NULL;
-  }
-  mutex_unlock(&malloc_lock);
-  return best->ptr;
+       if (__malloc_initialized < 0)
+               __malloc_init();
+       if (__malloc_initialized)
+               mutex_lock(&malloc_lock);
+
+       if (size <= HUNK_MAXSIZE)
+               p = __hunk_alloc(size);
+       else {
+               if ((p = bl_alloc(ALIGN(size))) != NULL)
+                       p = ((Block_t *) p)->ptr;
+       }
+
+       if (__malloc_initialized)
+               mutex_unlock(&malloc_lock);
+
+       return p;
 }
+#endif                                                 /* L_malloc */
 
-static void *mrealloc(void *ptr, size_t size)
+#ifdef L_free
+void free(void *ptr)
 {
-  void *tmp;
-  
-  tmp = mrealloc_no_move(ptr, size);
-  
-  if (!tmp)
-  {
-    Block_t *p, *best;
-    
-    mutex_lock(&malloc_lock);
-
-    for (p = ptrs_root, best = NULL;p;)
-    {
-      if (p->ptr > (char*)ptr) p = p->l_ptrs;
-      else { best = p; p = p->r_ptrs; }
-    }
-    
-    if (!best || !best->used || best->ptr != (char*)ptr)
-    {
-      if (ptr)
-      {
-       Hunk_t *h;
-        h = (Hunk_t*)PAGE_DOWNALIGNP(ptr);
-        if (h->id == HUNK_ID)
-        {
-         mutex_unlock(&malloc_lock);
-         if ((size >= HUNK_THRESHOLD && ALIGN(size) == h->size) ||
-             size == h->size) return ptr;
-         if ((tmp = mmalloc(size)) == NULL) return NULL;
-         mutex_lock(&malloc_lock);
-         memcpy(tmp,ptr,((size<h->size)?size:h->size));
-         hunk_free(ptr);
-         mutex_unlock(&malloc_lock);
-         return tmp;
+       Block_t *p, *best;
+
+       if (__malloc_initialized < 0)
+               return;
+       if (__malloc_initialized)
+               mutex_lock(&malloc_lock);
+
+       for (p = ptrs_root, best = NULL; p;) {
+               if (p->ptr > (char *) ptr)
+                       p = p->l_ptrs;
+               else {
+                       best = p;
+                       p = p->r_ptrs;
+               }
        }
-      }
-      mutex_unlock(&malloc_lock);
-      return mmalloc(size);
-    }
-    
-    mutex_unlock(&malloc_lock);
-    
-    /* copy whole block */
-    if ((tmp = mmalloc(size)) == NULL) return NULL;
-    memcpy(tmp,ptr,((size<best->size)?size:best->size));
-    
-    mutex_lock(&malloc_lock);
-    bl_free(best);
-    mutex_unlock(&malloc_lock);
-  }
-  return tmp;
+
+       if (!best || !best->used || best->ptr != (char *) ptr) {
+               __hunk_free(ptr);
+               if (__malloc_initialized)
+                       mutex_unlock(&malloc_lock);
+               return;
+       }
+
+       __bl_free(best);
+
+       if (__malloc_initialized)
+               mutex_unlock(&malloc_lock);
 }
+#endif                                                 /* L_free */
+
+extern void *_realloc_no_move(void *ptr, size_t size);
 
-static void *mcalloc(size_t unit, size_t quantity)
+#ifdef L__realloc_no_move
+void *_realloc_no_move(void *ptr, size_t size)
 {
-  void *p;
-  
-  unit *= quantity;
-  if ((p = mmalloc(unit)) == NULL) return NULL;
-  memset(p,0,unit);
-  return p;
-}
+       Block_t *p, *best, *next;
 
-/* PUBLIC functions */
+       if (size <= HUNK_MAXSIZE)
+               return NULL;
 
-void *malloc(size_t size) {
-  return mmalloc(size);
-}
+       if (__malloc_initialized <= 0)
+               return malloc(size);
 
-void *calloc(size_t unit, size_t quantity) {
-  return mcalloc(unit,quantity);
-}
+       mutex_lock(&malloc_lock);
+
+       /* Locate block */
+       for (p = ptrs_root, best = NULL; p;) {
+               if (p->ptr > (char *) ptr)
+                       p = p->l_ptrs;
+               else {
+                       best = p;
+                       p = p->r_ptrs;
+               }
+       }
+
+       if (!best || !best->used || best->ptr != (char *) ptr) {
+               mutex_unlock(&malloc_lock);
+               return NULL;
+       }
+
+       size = ALIGN(size);
 
-void *realloc(void *ptr, size_t size) {
-  return mrealloc(ptr,size);
+       if (size == best->size) {
+               mutex_unlock(&malloc_lock);
+               return ptr;
+       }
+
+       if (best->r_ptrs)                       /* get block just after */
+               for (next = best->r_ptrs; next->l_ptrs; next = next->l_ptrs);
+       else
+               for (p = ptrs_root, next = NULL; p;) {
+                       if (p->ptr > best->ptr) {
+                               next = p;
+                               p = p->l_ptrs;
+                       } else if (p->ptr < best->ptr)
+                               p = p->r_ptrs;
+                       else
+                               break;
+               }
+
+       if (size < best->size) {        /* shrink block */
+               if (!next || next->used || next->broken) {
+                       if (best->size - size > MALLOC_ALIGN) { /* do split */
+                               SPLIT_BLOCK(best, size);
+                       }
+               } else {                                /* just move border of next block */
+                       SHRINK_BLOCK(best, next, size);
+               }
+       } else if (next && !next->broken && !next->used) {      /* can expand */
+               if (best->size + next->size > size + HUNK_MAXSIZE) {    /* shrink next free block */
+                       SHRINK_BLOCK(best, next, size);
+               } else if (best->size + next->size >= size) {   /* combine blocks (eat next one) */
+                       FREE_MEM_DEL_BLOCK(next, p);
+                       COMBINE_BLOCKS(best, next);
+               } else {                                /* not enough memory in next block */
+                       mutex_unlock(&malloc_lock);
+                       return NULL;
+               }
+       } else {                                        /* no next block */
+               mutex_unlock(&malloc_lock);
+               return NULL;
+       }
+       mutex_unlock(&malloc_lock);
+       return best->ptr;
 }
+#endif                                                 /* L__realloc_no_move */
 
-void free(void *ptr) {
-  return mfree(ptr);
+#ifdef L_realloc
+void *realloc(void *ptr, size_t size)
+{
+       void *tmp;
+
+       tmp = _realloc_no_move(ptr, size);
+
+       if (!tmp) {
+               Block_t *p, *best;
+
+               mutex_lock(&malloc_lock);
+
+               for (p = ptrs_root, best = NULL; p;) {
+                       if (p->ptr > (char *) ptr)
+                               p = p->l_ptrs;
+                       else {
+                               best = p;
+                               p = p->r_ptrs;
+                       }
+               }
+
+               if (!best || !best->used || best->ptr != (char *) ptr) {
+                       if (ptr) {
+                               Hunk_t *h;
+
+                               h = (Hunk_t *) PAGE_DOWNALIGNP(ptr);
+                               if (h->id == HUNK_ID) {
+                                       mutex_unlock(&malloc_lock);
+                                       if ((size >= HUNK_THRESHOLD && ALIGN(size) == h->size)
+                                               || size == h->size)
+                                               return ptr;
+                                       if ((tmp = malloc(size)) == NULL)
+                                               return NULL;
+                                       mutex_lock(&malloc_lock);
+                                       memcpy(tmp, ptr, ((size < h->size) ? size : h->size));
+                                       __hunk_free(ptr);
+                                       mutex_unlock(&malloc_lock);
+                                       return tmp;
+                               }
+                       }
+                       mutex_unlock(&malloc_lock);
+                       return malloc(size);
+               }
+
+               mutex_unlock(&malloc_lock);
+
+               /* copy whole block */
+               if ((tmp = malloc(size)) == NULL)
+                       return NULL;
+               memcpy(tmp, ptr, ((size < best->size) ? size : best->size));
+
+               mutex_lock(&malloc_lock);
+               __bl_free(best);
+               mutex_unlock(&malloc_lock);
+       }
+       return tmp;
 }
+#endif                                                 /* L_realloc */
+
+#ifdef L_calloc
+void *calloc(size_t unit, size_t quantity)
+{
+       void *p;
 
+       unit *= quantity;
 
+       if ((p = malloc(unit)) == NULL)
+               return NULL;
+       memset(p, 0, unit);
+       return p;
+}
+#endif                                                 /* L_calloc */