Index: omalloc/dlmalloc.c
===================================================================
--- omalloc/dlmalloc.c	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
+++ omalloc/dlmalloc.c	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
@@ -0,0 +1,2316 @@
+/*******************************************************************
+ *  File:    dlmalloc.h
+ *  Purpose: implementation of Doug Lea's malloc
+ *  This was obtained by taking cutting out the end of malloc.c 
+ *
+ *  Version: $Id: dlmalloc.c,v 1.1 2000-08-14 12:18:24 obachman Exp $
+ *******************************************************************/
+#ifdef HAVE_CONFIG_H
+#include "omMalloc.h"
+#else
+#include "dlmalloc.h"
+#endif
+
+/* 
+  Emulation of sbrk for WIN32
+  All code within the ifdef WIN32 is untested by me.
+*/
+
+
+#ifdef WIN32
+
+#define AlignPage(add) (((add) + (malloc_getpagesize-1)) &
+~(malloc_getpagesize-1))
+
+/* resrve 64MB to insure large contiguous space */ 
+#define RESERVED_SIZE (1024*1024*64)
+#define NEXT_SIZE (2048*1024)
+#define TOP_MEMORY ((unsigned long)2*1024*1024*1024)
+
+struct GmListElement;
+typedef struct GmListElement GmListElement;
+
+struct GmListElement 
+{
+	GmListElement* next;
+	void* base;
+};
+
+static GmListElement* head = 0;
+static unsigned int gNextAddress = 0;
+static unsigned int gAddressBase = 0;
+static unsigned int gAllocatedSize = 0;
+
+static
+GmListElement* makeGmListElement (void* bas)
+{
+	GmListElement* this;
+	this = (GmListElement*)(void*)LocalAlloc (0, sizeof (GmListElement));
+	ASSERT (this);
+	if (this)
+	{
+		this->base = bas;
+		this->next = head;
+		head = this;
+	}
+	return this;
+}
+
+void gcleanup ()
+{
+	BOOL rval;
+	ASSERT ( (head == NULL) || (head->base == (void*)gAddressBase));
+	if (gAddressBase && (gNextAddress - gAddressBase))
+	{
+		rval = VirtualFree ((void*)gAddressBase, 
+							gNextAddress - gAddressBase, 
+							MEM_DECOMMIT);
+        ASSERT (rval);
+	}
+	while (head)
+	{
+		GmListElement* next = head->next;
+		rval = VirtualFree (head->base, 0, MEM_RELEASE);
+		ASSERT (rval);
+		LocalFree (head);
+		head = next;
+	}
+}
+		
+static
+void* findRegion (void* start_address, unsigned long size)
+{
+	MEMORY_BASIC_INFORMATION info;
+	while ((unsigned long)start_address < TOP_MEMORY)
+	{
+		VirtualQuery (start_address, &info, sizeof (info));
+		if (info.State != MEM_FREE)
+			start_address = (char*)info.BaseAddress + info.RegionSize;
+		else if (info.RegionSize >= size)
+			return start_address;
+		else
+			start_address = (char*)info.BaseAddress + info.RegionSize; 
+	}
+	return NULL;
+	
+}
+
+
+void* wsbrk (long size)
+{
+	void* tmp;
+	if (size > 0)
+	{
+		if (gAddressBase == 0)
+		{
+			gAllocatedSize = max (RESERVED_SIZE, AlignPage (size));
+			gNextAddress = gAddressBase = 
+				(unsigned int)VirtualAlloc (NULL, gAllocatedSize, 
+											MEM_RESERVE, PAGE_NOACCESS);
+		} else if (AlignPage (gNextAddress + size) > (gAddressBase +
+gAllocatedSize))
+		{
+			long new_size = max (NEXT_SIZE, AlignPage (size));
+			void* new_address = (void*)(gAddressBase+gAllocatedSize);
+			do 
+			{
+				new_address = findRegion (new_address, new_size);
+				
+				if (new_address == 0)
+					return (void*)-1;
+
+				gAddressBase = gNextAddress =
+					(unsigned int)VirtualAlloc (new_address, new_size,
+												MEM_RESERVE, PAGE_NOACCESS);
+				// repeat in case of race condition
+				// The region that we found has been snagged 
+				// by another thread
+			}
+			while (gAddressBase == 0);
+
+			ASSERT (new_address == (void*)gAddressBase);
+
+			gAllocatedSize = new_size;
+
+			if (!makeGmListElement ((void*)gAddressBase))
+				return (void*)-1;
+		}
+		if ((size + gNextAddress) > AlignPage (gNextAddress))
+		{
+			void* res;
+			res = VirtualAlloc ((void*)AlignPage (gNextAddress),
+								(size + gNextAddress - 
+								 AlignPage (gNextAddress)), 
+								MEM_COMMIT, PAGE_READWRITE);
+			if (res == 0)
+				return (void*)-1;
+		}
+		tmp = (void*)gNextAddress;
+		gNextAddress = (unsigned int)tmp + size;
+		return tmp;
+	}
+	else if (size < 0)
+	{
+		unsigned int alignedGoal = AlignPage (gNextAddress + size);
+		/* Trim by releasing the virtual memory */
+		if (alignedGoal >= gAddressBase)
+		{
+			VirtualFree ((void*)alignedGoal, gNextAddress - alignedGoal,  
+						 MEM_DECOMMIT);
+			gNextAddress = gNextAddress + size;
+			return (void*)gNextAddress;
+		}
+		else 
+		{
+			VirtualFree ((void*)gAddressBase, gNextAddress - gAddressBase,
+						 MEM_DECOMMIT);
+			gNextAddress = gAddressBase;
+			return (void*)-1;
+		}
+	}
+	else
+	{
+		return (void*)gNextAddress;
+	}
+}
+
+#endif
+
+
+
+
+/*
+  Type declarations
+*/
+
+
+struct malloc_chunk
+{
+  INTERNAL_SIZE_T prev_size; /* Size of previous chunk (if free). */
+  INTERNAL_SIZE_T size;      /* Size in bytes, including overhead. */
+  struct malloc_chunk* fd;   /* double links -- used only if free. */
+  struct malloc_chunk* bk;
+};
+
+typedef struct malloc_chunk* mchunkptr;
+
+/*
+
+   malloc_chunk details:
+
+    (The following includes lightly edited explanations by Colin Plumb.)
+
+    Chunks of memory are maintained using a `boundary tag' method as
+    described in e.g., Knuth or Standish.  (See the paper by Paul
+    Wilson ftp://ftp.cs.utexas.edu/pub/garbage/allocsrv.ps for a
+    survey of such techniques.)  Sizes of free chunks are stored both
+    in the front of each chunk and at the end.  This makes
+    consolidating fragmented chunks into bigger chunks very fast.  The
+    size fields also hold bits representing whether chunks are free or
+    in use.
+
+    An allocated chunk looks like this:  
+
+
+    chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+            |             Size of previous chunk, if allocated            | |
+            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+            |             Size of chunk, in bytes                         |P|
+      mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+            |             User data starts here...                          .
+            .                                                               .
+            .             (malloc_usable_space() bytes)                     .
+            .                                                               |
+nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+            |             Size of chunk                                     |
+            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+
+    Where "chunk" is the front of the chunk for the purpose of most of
+    the malloc code, but "mem" is the pointer that is returned to the
+    user.  "Nextchunk" is the beginning of the next contiguous chunk.
+
+    Chunks always begin on even word boundries, so the mem portion
+    (which is returned to the user) is also on an even word boundary, and
+    thus double-word aligned.
+
+    Free chunks are stored in circular doubly-linked lists, and look like this:
+
+    chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+            |             Size of previous chunk                            |
+            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    `head:' |             Size of chunk, in bytes                         |P|
+      mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+            |             Forward pointer to next chunk in list             |
+            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+            |             Back pointer to previous chunk in list            |
+            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+            |             Unused space (may be 0 bytes long)                .
+            .                                                               .
+            .                                                               |
+nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    `foot:' |             Size of chunk, in bytes                           |
+            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+    The P (PREV_INUSE) bit, stored in the unused low-order bit of the
+    chunk size (which is always a multiple of two words), is an in-use
+    bit for the *previous* chunk.  If that bit is *clear*, then the
+    word before the current chunk size contains the previous chunk
+    size, and can be used to find the front of the previous chunk.
+    (The very first chunk allocated always has this bit set,
+    preventing access to non-existent (or non-owned) memory.)
+
+    Note that the `foot' of the current chunk is actually represented
+    as the prev_size of the NEXT chunk. (This makes it easier to
+    deal with alignments etc).
+
+    The two exceptions to all this are 
+
+     1. The special chunk `top', which doesn't bother using the 
+        trailing size field since there is no
+        next contiguous chunk that would have to index off it. (After
+        initialization, `top' is forced to always exist.  If it would
+        become less than MINSIZE bytes long, it is replenished via
+        malloc_extend_top.)
+
+     2. Chunks allocated via mmap, which have the second-lowest-order
+        bit (IS_MMAPPED) set in their size fields.  Because they are
+        never merged or traversed from any other chunk, they have no
+        foot size or inuse information.
+
+    Available chunks are kept in any of several places (all declared below):
+
+    * `av': An array of chunks serving as bin headers for consolidated
+       chunks. Each bin is doubly linked.  The bins are approximately
+       proportionally (log) spaced.  There are a lot of these bins
+       (128). This may look excessive, but works very well in
+       practice.  All procedures maintain the invariant that no
+       consolidated chunk physically borders another one. Chunks in
+       bins are kept in size order, with ties going to the
+       approximately least recently used chunk.
+
+       The chunks in each bin are maintained in decreasing sorted order by
+       size.  This is irrelevant for the small bins, which all contain
+       the same-sized chunks, but facilitates best-fit allocation for
+       larger chunks. (These lists are just sequential. Keeping them in
+       order almost never requires enough traversal to warrant using
+       fancier ordered data structures.)  Chunks of the same size are
+       linked with the most recently freed at the front, and allocations
+       are taken from the back.  This results in LRU or FIFO allocation
+       order, which tends to give each chunk an equal opportunity to be
+       consolidated with adjacent freed chunks, resulting in larger free
+       chunks and less fragmentation. 
+
+    * `top': The top-most available chunk (i.e., the one bordering the
+       end of available memory) is treated specially. It is never
+       included in any bin, is used only if no other chunk is
+       available, and is released back to the system if it is very
+       large (see M_TRIM_THRESHOLD).
+
+    * `last_remainder': A bin holding only the remainder of the
+       most recently split (non-top) chunk. This bin is checked
+       before other non-fitting chunks, so as to provide better
+       locality for runs of sequentially allocated chunks. 
+
+    *  Implicitly, through the host system's memory mapping tables.
+       If supported, requests greater than a threshold are usually 
+       serviced via calls to mmap, and then later released via munmap.
+
+*/
+
+
+
+
+
+
+
+/*  sizes, alignments */
+
+#define SIZE_SZ                (sizeof(INTERNAL_SIZE_T))
+#define MALLOC_ALIGNMENT       (SIZE_SZ + SIZE_SZ)
+#define MALLOC_ALIGN_MASK      (MALLOC_ALIGNMENT - 1)
+#define MINSIZE                (sizeof(struct malloc_chunk))
+
+/* conversion from malloc headers to user pointers, and back */
+
+#define chunk2mem(p)   ((Void_t*)((char*)(p) + 2*SIZE_SZ))
+#define mem2chunk(mem) ((mchunkptr)((char*)(mem) - 2*SIZE_SZ))
+
+/* pad request bytes into a usable size */
+
+#define request2size(req) \
+ (((long)((req) + (SIZE_SZ + MALLOC_ALIGN_MASK)) < \
+  (long)(MINSIZE + MALLOC_ALIGN_MASK)) ? MINSIZE : \
+   (((req) + (SIZE_SZ + MALLOC_ALIGN_MASK)) & ~(MALLOC_ALIGN_MASK)))
+
+/* Check if m has acceptable alignment */
+
+#define aligned_OK(m)    (((unsigned long)((m)) & (MALLOC_ALIGN_MASK)) == 0)
+
+
+
+
+
+/* 
+  Physical chunk operations  
+*/
+
+
+/* size field is or'ed with PREV_INUSE when previous adjacent chunk in use */
+
+#define PREV_INUSE 0x1 
+
+/* size field is or'ed with IS_MMAPPED if the chunk was obtained with mmap() */
+
+#define IS_MMAPPED 0x2
+
+/* Bits to mask off when extracting size */
+
+#define SIZE_BITS (PREV_INUSE|IS_MMAPPED)
+
+
+/* Ptr to next physical malloc_chunk. */
+
+#define next_chunk(p) ((mchunkptr)( ((char*)(p)) + ((p)->size & ~PREV_INUSE) ))
+
+/* Ptr to previous physical malloc_chunk */
+
+#define prev_chunk(p)\
+   ((mchunkptr)( ((char*)(p)) - ((p)->prev_size) ))
+
+
+/* Treat space at ptr + offset as a chunk */
+
+#define chunk_at_offset(p, s)  ((mchunkptr)(((char*)(p)) + (s)))
+
+
+
+
+
+/* 
+  Dealing with use bits 
+*/
+
+/* extract p's inuse bit */
+
+#define inuse(p)\
+((((mchunkptr)(((char*)(p))+((p)->size & ~PREV_INUSE)))->size) & PREV_INUSE)
+
+/* extract inuse bit of previous chunk */
+
+#define prev_inuse(p)  ((p)->size & PREV_INUSE)
+
+/* check for mmap()'ed chunk */
+
+#define chunk_is_mmapped(p) ((p)->size & IS_MMAPPED)
+
+/* set/clear chunk as in use without otherwise disturbing */
+
+#define set_inuse(p)\
+((mchunkptr)(((char*)(p)) + ((p)->size & ~PREV_INUSE)))->size |= PREV_INUSE
+
+#define clear_inuse(p)\
+((mchunkptr)(((char*)(p)) + ((p)->size & ~PREV_INUSE)))->size &= ~(PREV_INUSE)
+
+/* check/set/clear inuse bits in known places */
+
+#define inuse_bit_at_offset(p, s)\
+ (((mchunkptr)(((char*)(p)) + (s)))->size & PREV_INUSE)
+
+#define set_inuse_bit_at_offset(p, s)\
+ (((mchunkptr)(((char*)(p)) + (s)))->size |= PREV_INUSE)
+
+#define clear_inuse_bit_at_offset(p, s)\
+ (((mchunkptr)(((char*)(p)) + (s)))->size &= ~(PREV_INUSE))
+
+
+
+
+
+/* 
+  Dealing with size fields 
+*/
+
+/* Get size, ignoring use bits */
+
+#define chunksize(p)          ((p)->size & ~(SIZE_BITS))
+
+/* Set size at head, without disturbing its use bit */
+
+#define set_head_size(p, s)   ((p)->size = (((p)->size & PREV_INUSE) | (s)))
+
+/* Set size/use ignoring previous bits in header */
+
+#define set_head(p, s)        ((p)->size = (s))
+
+/* Set size at footer (only when chunk is not in use) */
+
+#define set_foot(p, s)   (((mchunkptr)((char*)(p) + (s)))->prev_size = (s))
+
+
+
+
+
+
+/*
+   Bins
+
+    The bins, `av_' are an array of pairs of pointers serving as the
+    heads of (initially empty) doubly-linked lists of chunks, laid out
+    in a way so that each pair can be treated as if it were in a
+    malloc_chunk. (This way, the fd/bk offsets for linking bin heads
+    and chunks are the same).
+
+    Bins for sizes < 512 bytes contain chunks of all the same size, spaced
+    8 bytes apart. Larger bins are approximately logarithmically
+    spaced. (See the table below.) The `av_' array is never mentioned
+    directly in the code, but instead via bin access macros.
+
+    Bin layout:
+
+    64 bins of size       8
+    32 bins of size      64
+    16 bins of size     512
+     8 bins of size    4096
+     4 bins of size   32768
+     2 bins of size  262144
+     1 bin  of size what's left
+
+    There is actually a little bit of slop in the numbers in bin_index
+    for the sake of speed. This makes no difference elsewhere.
+
+    The special chunks `top' and `last_remainder' get their own bins,
+    (this is implemented via yet more trickery with the av_ array),
+    although `top' is never properly linked to its bin since it is
+    always handled specially.
+
+*/
+
+#define NAV             128   /* number of bins */
+
+typedef struct malloc_chunk* mbinptr;
+
+/* access macros */
+
+#define bin_at(i)      ((mbinptr)((char*)&(av_[2*(i) + 2]) - 2*SIZE_SZ))
+#define next_bin(b)    ((mbinptr)((char*)(b) + 2 * sizeof(mbinptr)))
+#define prev_bin(b)    ((mbinptr)((char*)(b) - 2 * sizeof(mbinptr)))
+
+/*
+   The first 2 bins are never indexed. The corresponding av_ cells are instead
+   used for bookkeeping. This is not to save space, but to simplify
+   indexing, maintain locality, and avoid some initialization tests.
+*/
+
+#define top            (bin_at(0)->fd)   /* The topmost chunk */
+#define last_remainder (bin_at(1))       /* remainder from last split */
+
+
+/*
+   Because top initially points to its own bin with initial
+   zero size, thus forcing extension on the first malloc request, 
+   we avoid having any special code in malloc to check whether 
+   it even exists yet. But we still need to in malloc_extend_top.
+*/
+
+#define initial_top    ((mchunkptr)(bin_at(0)))
+
+/* Helper macro to initialize bins */
+
+#define IAV(i)  bin_at(i), bin_at(i)
+
+static mbinptr av_[NAV * 2 + 2] = {
+ 0, 0,
+ IAV(0),   IAV(1),   IAV(2),   IAV(3),   IAV(4),   IAV(5),   IAV(6),   IAV(7),
+ IAV(8),   IAV(9),   IAV(10),  IAV(11),  IAV(12),  IAV(13),  IAV(14),  IAV(15),
+ IAV(16),  IAV(17),  IAV(18),  IAV(19),  IAV(20),  IAV(21),  IAV(22),  IAV(23),
+ IAV(24),  IAV(25),  IAV(26),  IAV(27),  IAV(28),  IAV(29),  IAV(30),  IAV(31),
+ IAV(32),  IAV(33),  IAV(34),  IAV(35),  IAV(36),  IAV(37),  IAV(38),  IAV(39),
+ IAV(40),  IAV(41),  IAV(42),  IAV(43),  IAV(44),  IAV(45),  IAV(46),  IAV(47),
+ IAV(48),  IAV(49),  IAV(50),  IAV(51),  IAV(52),  IAV(53),  IAV(54),  IAV(55),
+ IAV(56),  IAV(57),  IAV(58),  IAV(59),  IAV(60),  IAV(61),  IAV(62),  IAV(63),
+ IAV(64),  IAV(65),  IAV(66),  IAV(67),  IAV(68),  IAV(69),  IAV(70),  IAV(71),
+ IAV(72),  IAV(73),  IAV(74),  IAV(75),  IAV(76),  IAV(77),  IAV(78),  IAV(79),
+ IAV(80),  IAV(81),  IAV(82),  IAV(83),  IAV(84),  IAV(85),  IAV(86),  IAV(87),
+ IAV(88),  IAV(89),  IAV(90),  IAV(91),  IAV(92),  IAV(93),  IAV(94),  IAV(95),
+ IAV(96),  IAV(97),  IAV(98),  IAV(99),  IAV(100), IAV(101), IAV(102), IAV(103),
+ IAV(104), IAV(105), IAV(106), IAV(107), IAV(108), IAV(109), IAV(110), IAV(111),
+ IAV(112), IAV(113), IAV(114), IAV(115), IAV(116), IAV(117), IAV(118), IAV(119),
+ IAV(120), IAV(121), IAV(122), IAV(123), IAV(124), IAV(125), IAV(126), IAV(127)
+};
+
+
+
+
+/* field-extraction macros */
+
+#define first(b) ((b)->fd)
+#define last(b)  ((b)->bk)
+
+/* 
+  Indexing into bins
+*/
+
+#define bin_index(sz)                                                          \
+(((((unsigned long)(sz)) >> 9) ==    0) ?       (((unsigned long)(sz)) >>  3): \
+ ((((unsigned long)(sz)) >> 9) <=    4) ?  56 + (((unsigned long)(sz)) >>  6): \
+ ((((unsigned long)(sz)) >> 9) <=   20) ?  91 + (((unsigned long)(sz)) >>  9): \
+ ((((unsigned long)(sz)) >> 9) <=   84) ? 110 + (((unsigned long)(sz)) >> 12): \
+ ((((unsigned long)(sz)) >> 9) <=  340) ? 119 + (((unsigned long)(sz)) >> 15): \
+ ((((unsigned long)(sz)) >> 9) <= 1364) ? 124 + (((unsigned long)(sz)) >> 18): \
+                                          126)                     
+/* 
+  bins for chunks < 512 are all spaced 8 bytes apart, and hold
+  identically sized chunks. This is exploited in malloc.
+*/
+
+#define MAX_SMALLBIN         63
+#define MAX_SMALLBIN_SIZE   512
+#define SMALLBIN_WIDTH        8
+
+#define smallbin_index(sz)  (((unsigned long)(sz)) >> 3)
+
+/* 
+   Requests are `small' if both the corresponding and the next bin are small
+*/
+
+#define is_small_request(nb) (nb < MAX_SMALLBIN_SIZE - SMALLBIN_WIDTH)
+
+
+
+
+/*
+    To help compensate for the large number of bins, a one-level index
+    structure is used for bin-by-bin searching.  `binblocks' is a
+    one-word bitvector recording whether groups of BINBLOCKWIDTH bins
+    have any (possibly) non-empty bins, so they can be skipped over
+    all at once during during traversals. The bits are NOT always
+    cleared as soon as all bins in a block are empty, but instead only
+    when all are noticed to be empty during traversal in malloc.
+*/
+
+#define BINBLOCKWIDTH     4   /* bins per block */
+
+#define binblocks      (bin_at(0)->size) /* bitvector of nonempty blocks */
+
+/* bin<->block macros */
+
+#define idx2binblock(ix)    ((unsigned)1 << (ix / BINBLOCKWIDTH))
+#define mark_binblock(ii)   (binblocks |= idx2binblock(ii))
+#define clear_binblock(ii)  (binblocks &= ~(idx2binblock(ii)))
+
+
+
+
+
+
+/*  Other static bookkeeping data */
+
+/* variables holding tunable values */
+
+static unsigned long trim_threshold   = DEFAULT_TRIM_THRESHOLD;
+static unsigned long top_pad          = DEFAULT_TOP_PAD;
+static unsigned int  n_mmaps_max      = DEFAULT_MMAP_MAX;
+static unsigned long mmap_threshold   = DEFAULT_MMAP_THRESHOLD;
+
+/* The first value returned from sbrk */
+static char* sbrk_base = (char*)(-1);
+
+/* The maximum memory obtained from system via sbrk */
+unsigned long max_sbrked_mem = 0; 
+
+/* The maximum via either sbrk or mmap */
+unsigned long max_total_mem = 0; 
+
+/* internal working copy of mallinfo */
+struct mallinfo current_mallinfo = {  0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+
+/* The total memory obtained from system via sbrk */
+#define sbrked_mem  (current_mallinfo.arena)
+
+/* Tracking mmaps */
+
+static unsigned int n_mmaps = 0;
+static unsigned int max_n_mmaps = 0;
+/* obachman: rm'ed static */
+unsigned long mmapped_mem = 0;
+unsigned long max_mmapped_mem = 0;
+
+
+
+
+/* 
+  Debugging support 
+*/
+
+#if DEBUG
+
+
+/*
+  These routines make a number of assertions about the states
+  of data structures that should be true at all times. If any
+  are not true, it's very likely that a user program has somehow
+  trashed memory. (It's also possible that there is a coding error
+  in malloc. In which case, please report it!)
+*/
+
+#if __STD_C
+static void do_check_chunk(mchunkptr p) 
+#else
+static void do_check_chunk(p) mchunkptr p;
+#endif
+{ 
+  INTERNAL_SIZE_T sz = p->size & ~PREV_INUSE;
+
+  /* No checkable chunk is mmapped */
+  assert(!chunk_is_mmapped(p));
+
+  /* Check for legal address ... */
+  assert((char*)p >= sbrk_base);
+  if (p != top) 
+    assert((char*)p + sz <= (char*)top);
+  else
+    assert((char*)p + sz <= sbrk_base + sbrked_mem);
+
+}
+
+
+#if __STD_C
+static void do_check_free_chunk(mchunkptr p) 
+#else
+static void do_check_free_chunk(p) mchunkptr p;
+#endif
+{ 
+  INTERNAL_SIZE_T sz = p->size & ~PREV_INUSE;
+  mchunkptr next = chunk_at_offset(p, sz);
+
+  do_check_chunk(p);
+
+  /* Check whether it claims to be free ... */
+  assert(!inuse(p));
+
+  /* Unless a special marker, must have OK fields */
+  if ((long)sz >= (long)MINSIZE)
+  {
+    assert((sz & MALLOC_ALIGN_MASK) == 0);
+    assert(aligned_OK(chunk2mem(p)));
+    /* ... matching footer field */
+    assert(next->prev_size == sz);
+    /* ... and is fully consolidated */
+    assert(prev_inuse(p));
+    assert (next == top || inuse(next));
+    
+    /* ... and has minimally sane links */
+    assert(p->fd->bk == p);
+    assert(p->bk->fd == p);
+  }
+  else /* markers are always of size SIZE_SZ */
+    assert(sz == SIZE_SZ); 
+}
+
+#if __STD_C
+static void do_check_inuse_chunk(mchunkptr p) 
+#else
+static void do_check_inuse_chunk(p) mchunkptr p;
+#endif
+{ 
+  mchunkptr next = next_chunk(p);
+  do_check_chunk(p);
+
+  /* Check whether it claims to be in use ... */
+  assert(inuse(p));
+
+  /* ... and is surrounded by OK chunks.
+    Since more things can be checked with free chunks than inuse ones,
+    if an inuse chunk borders them and debug is on, it's worth doing them.
+  */
+  if (!prev_inuse(p)) 
+  {
+    mchunkptr prv = prev_chunk(p);
+    assert(next_chunk(prv) == p);
+    do_check_free_chunk(prv);
+  }
+  if (next == top)
+  {
+    assert(prev_inuse(next));
+    assert(chunksize(next) >= MINSIZE);
+  }
+  else if (!inuse(next))
+    do_check_free_chunk(next);
+
+}
+
+#if __STD_C
+static void do_check_malloced_chunk(mchunkptr p, INTERNAL_SIZE_T s) 
+#else
+static void do_check_malloced_chunk(p, s) mchunkptr p; INTERNAL_SIZE_T s;
+#endif
+{
+  INTERNAL_SIZE_T sz = p->size & ~PREV_INUSE;
+  long room = sz - s;
+
+  do_check_inuse_chunk(p);
+
+  /* Legal size ... */
+  assert((long)sz >= (long)MINSIZE);
+  assert((sz & MALLOC_ALIGN_MASK) == 0);
+  assert(room >= 0);
+  assert(room < (long)MINSIZE);
+
+  /* ... and alignment */
+  assert(aligned_OK(chunk2mem(p)));
+
+
+  /* ... and was allocated at front of an available chunk */
+  assert(prev_inuse(p));
+
+}
+
+
+#define check_free_chunk(P)  do_check_free_chunk(P)
+#define check_inuse_chunk(P) do_check_inuse_chunk(P)
+#define check_chunk(P) do_check_chunk(P)
+#define check_malloced_chunk(P,N) do_check_malloced_chunk(P,N)
+#else
+#define check_free_chunk(P) 
+#define check_inuse_chunk(P)
+#define check_chunk(P)
+#define check_malloced_chunk(P,N)
+#endif
+
+
+
+
+/* 
+  Macro-based internal utilities
+*/
+
+
+/*  
+  Linking chunks in bin lists.
+  Call these only with variables, not arbitrary expressions, as arguments.
+*/
+
+/* 
+  Place chunk p of size s in its bin, in size order,
+  putting it ahead of others of same size.
+*/
+
+
+#define frontlink(P, S, IDX, BK, FD)                                          \
+{                                                                             \
+  if (S < MAX_SMALLBIN_SIZE)                                                  \
+  {                                                                           \
+    IDX = smallbin_index(S);                                                  \
+    mark_binblock(IDX);                                                       \
+    BK = bin_at(IDX);                                                         \
+    FD = BK->fd;                                                              \
+    P->bk = BK;                                                               \
+    P->fd = FD;                                                               \
+    FD->bk = BK->fd = P;                                                      \
+  }                                                                           \
+  else                                                                        \
+  {                                                                           \
+    IDX = bin_index(S);                                                       \
+    BK = bin_at(IDX);                                                         \
+    FD = BK->fd;                                                              \
+    if (FD == BK) mark_binblock(IDX);                                         \
+    else                                                                      \
+    {                                                                         \
+      while (FD != BK && S < chunksize(FD)) FD = FD->fd;                      \
+      BK = FD->bk;                                                            \
+    }                                                                         \
+    P->bk = BK;                                                               \
+    P->fd = FD;                                                               \
+    FD->bk = BK->fd = P;                                                      \
+  }                                                                           \
+}
+
+
+/* take a chunk off a list */
+
+#define unlink(P, BK, FD)                                                     \
+{                                                                             \
+  BK = P->bk;                                                                 \
+  FD = P->fd;                                                                 \
+  FD->bk = BK;                                                                \
+  BK->fd = FD;                                                                \
+}                                                                             \
+
+/* Place p as the last remainder */
+
+#define link_last_remainder(P)                                                \
+{                                                                             \
+  last_remainder->fd = last_remainder->bk =  P;                               \
+  P->fd = P->bk = last_remainder;                                             \
+}
+
+/* Clear the last_remainder bin */
+
+#define clear_last_remainder \
+  (last_remainder->fd = last_remainder->bk = last_remainder)
+
+
+
+
+
+
+
+/* Routines dealing with mmap(). */
+
+#if HAVE_MMAP
+
+#if __STD_C
+static mchunkptr mmap_chunk(size_t size)
+#else
+static mchunkptr mmap_chunk(size) size_t size;
+#endif
+{
+  size_t page_mask = malloc_getpagesize - 1;
+  mchunkptr p;
+
+#ifndef MAP_ANONYMOUS
+  static int fd = -1;
+#endif
+
+  if(n_mmaps >= n_mmaps_max) return 0; /* too many regions */
+
+  /* For mmapped chunks, the overhead is one SIZE_SZ unit larger, because
+   * there is no following chunk whose prev_size field could be used.
+   */
+  size = (size + SIZE_SZ + page_mask) & ~page_mask;
+
+#ifdef MAP_ANONYMOUS
+  p = (mchunkptr)mmap(0, size, PROT_READ|PROT_WRITE,
+		      MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
+#else /* !MAP_ANONYMOUS */
+  if (fd < 0) 
+  {
+    fd = open("/dev/zero", O_RDWR);
+    if(fd < 0) return 0;
+  }
+  p = (mchunkptr)mmap(0, size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
+#endif
+
+  if(p == (mchunkptr)-1) return 0;
+
+  n_mmaps++;
+  if (n_mmaps > max_n_mmaps) max_n_mmaps = n_mmaps;
+  
+  /* We demand that eight bytes into a page must be 8-byte aligned. */
+  assert(aligned_OK(chunk2mem(p)));
+
+  /* The offset to the start of the mmapped region is stored
+   * in the prev_size field of the chunk; normally it is zero,
+   * but that can be changed in memalign().
+   */
+  p->prev_size = 0;
+  set_head(p, size|IS_MMAPPED);
+  
+  mmapped_mem += size;
+  if ((unsigned long)mmapped_mem > (unsigned long)max_mmapped_mem) 
+    max_mmapped_mem = mmapped_mem;
+  if ((unsigned long)(mmapped_mem + sbrked_mem) > (unsigned long)max_total_mem) 
+    max_total_mem = mmapped_mem + sbrked_mem;
+  return p;
+}
+
+#if __STD_C
+static void munmap_chunk(mchunkptr p)
+#else
+static void munmap_chunk(p) mchunkptr p;
+#endif
+{
+  INTERNAL_SIZE_T size = chunksize(p);
+  int ret;
+
+  assert (chunk_is_mmapped(p));
+  assert(! ((char*)p >= sbrk_base && (char*)p < sbrk_base + sbrked_mem));
+  assert((n_mmaps > 0));
+  assert(((p->prev_size + size) & (malloc_getpagesize-1)) == 0);
+
+  n_mmaps--;
+  mmapped_mem -= (size + p->prev_size);
+
+  ret = munmap((char *)p - p->prev_size, size + p->prev_size);
+
+  /* munmap returns non-zero on failure */
+  assert(ret == 0);
+}
+
+#if HAVE_MREMAP
+
+#if __STD_C
+static mchunkptr mremap_chunk(mchunkptr p, size_t new_size)
+#else
+static mchunkptr mremap_chunk(p, new_size) mchunkptr p; size_t new_size;
+#endif
+{
+  size_t page_mask = malloc_getpagesize - 1;
+  INTERNAL_SIZE_T offset = p->prev_size;
+  INTERNAL_SIZE_T size = chunksize(p);
+  char *cp;
+
+  assert (chunk_is_mmapped(p));
+  assert(! ((char*)p >= sbrk_base && (char*)p < sbrk_base + sbrked_mem));
+  assert((n_mmaps > 0));
+  assert(((size + offset) & (malloc_getpagesize-1)) == 0);
+
+  /* Note the extra SIZE_SZ overhead as in mmap_chunk(). */
+  new_size = (new_size + offset + SIZE_SZ + page_mask) & ~page_mask;
+
+  cp = (char *)mremap((char *)p - offset, size + offset, new_size, 1);
+
+  if (cp == (char *)-1) return 0;
+
+  p = (mchunkptr)(cp + offset);
+
+  assert(aligned_OK(chunk2mem(p)));
+
+  assert((p->prev_size == offset));
+  set_head(p, (new_size - offset)|IS_MMAPPED);
+
+  mmapped_mem -= size + offset;
+  mmapped_mem += new_size;
+  if ((unsigned long)mmapped_mem > (unsigned long)max_mmapped_mem) 
+    max_mmapped_mem = mmapped_mem;
+  if ((unsigned long)(mmapped_mem + sbrked_mem) > (unsigned long)max_total_mem)
+    max_total_mem = mmapped_mem + sbrked_mem;
+  return p;
+}
+
+#endif /* HAVE_MREMAP */
+
+#endif /* HAVE_MMAP */
+
+
+
+
+
+/* 
+  Extend the top-most chunk by obtaining memory from system.
+  Main interface to sbrk (but see also malloc_trim).
+*/
+
+#if __STD_C
+static void malloc_extend_top(INTERNAL_SIZE_T nb)
+#else
+static void malloc_extend_top(nb) INTERNAL_SIZE_T nb;
+#endif
+{
+  char*     brk;                  /* return value from sbrk */
+  INTERNAL_SIZE_T front_misalign; /* unusable bytes at front of sbrked space */
+  INTERNAL_SIZE_T correction;     /* bytes for 2nd sbrk call */
+  char*     new_brk;              /* return of 2nd sbrk call */
+  INTERNAL_SIZE_T top_size;       /* new size of top chunk */
+
+  mchunkptr old_top     = top;  /* Record state of old top */
+  INTERNAL_SIZE_T old_top_size = chunksize(old_top);
+  char*     old_end      = (char*)(chunk_at_offset(old_top, old_top_size));
+
+  /* Pad request with top_pad plus minimal overhead */
+  
+  INTERNAL_SIZE_T    sbrk_size     = nb + top_pad + MINSIZE;
+  unsigned long pagesz    = malloc_getpagesize;
+
+  /* If not the first time through, round to preserve page boundary */
+  /* Otherwise, we need to correct to a page size below anyway. */
+  /* (We also correct below if an intervening foreign sbrk call.) */
+
+  if (sbrk_base != (char*)(-1))
+    sbrk_size = (sbrk_size + (pagesz - 1)) & ~(pagesz - 1);
+
+  brk = (char*)(MORECORE (sbrk_size));
+
+  /* Fail if sbrk failed or if a foreign sbrk call killed our space */
+  if (brk == (char*)(MORECORE_FAILURE) || 
+      (brk < old_end && old_top != initial_top))
+    return;     
+
+  sbrked_mem += sbrk_size;
+
+  if (brk == old_end) /* can just add bytes to current top */
+  {
+    top_size = sbrk_size + old_top_size;
+    set_head(top, top_size | PREV_INUSE);
+  }
+  else
+  {
+    if (sbrk_base == (char*)(-1))  /* First time through. Record base */
+      sbrk_base = brk;
+    else  /* Someone else called sbrk().  Count those bytes as sbrked_mem. */
+      sbrked_mem += brk - (char*)old_end;
+
+    /* Guarantee alignment of first new chunk made from this space */
+    front_misalign = (unsigned long)chunk2mem(brk) & MALLOC_ALIGN_MASK;
+    if (front_misalign > 0) 
+    {
+      correction = (MALLOC_ALIGNMENT) - front_misalign;
+      brk += correction;
+    }
+    else
+      correction = 0;
+
+    /* Guarantee the next brk will be at a page boundary */
+    correction += pagesz - ((unsigned long)(brk + sbrk_size) & (pagesz - 1));
+
+    /* Allocate correction */
+    new_brk = (char*)(MORECORE (correction));
+    if (new_brk == (char*)(MORECORE_FAILURE)) return; 
+
+    sbrked_mem += correction;
+
+    top = (mchunkptr)brk;
+    top_size = new_brk - brk + correction;
+    set_head(top, top_size | PREV_INUSE);
+
+    if (old_top != initial_top)
+    {
+
+      /* There must have been an intervening foreign sbrk call. */
+      /* A double fencepost is necessary to prevent consolidation */
+
+      /* If not enough space to do this, then user did something very wrong */
+      if (old_top_size < MINSIZE) 
+      {
+        set_head(top, PREV_INUSE); /* will force null return from malloc */
+        return;
+      }
+
+      /* Also keep size a multiple of MALLOC_ALIGNMENT */
+      old_top_size = (old_top_size - 3*SIZE_SZ) & ~MALLOC_ALIGN_MASK;
+      set_head_size(old_top, old_top_size);
+      chunk_at_offset(old_top, old_top_size          )->size =
+        SIZE_SZ|PREV_INUSE;
+      chunk_at_offset(old_top, old_top_size + SIZE_SZ)->size =
+        SIZE_SZ|PREV_INUSE;
+      /* If possible, release the rest. */
+      if (old_top_size >= MINSIZE) 
+        fREe(chunk2mem(old_top));
+    }
+  }
+
+  if ((unsigned long)sbrked_mem > (unsigned long)max_sbrked_mem) 
+    max_sbrked_mem = sbrked_mem;
+  if ((unsigned long)(mmapped_mem + sbrked_mem) > (unsigned long)max_total_mem) 
+    max_total_mem = mmapped_mem + sbrked_mem;
+
+  /* We always land on a page boundary */
+  assert(((unsigned long)((char*)top + top_size) & (pagesz - 1)) == 0);
+}
+
+
+
+
+
+/* Main public routines */
+
+
+/*
+  Malloc Algorthim:
+
+    The requested size is first converted into a usable form, `nb'.
+    This currently means to add 4 bytes overhead plus possibly more to
+    obtain 8-byte alignment and/or to obtain a size of at least
+    MINSIZE (currently 16 bytes), the smallest allocatable size.
+    (All fits are considered `exact' if they are within MINSIZE bytes.)
+
+    From there, the first successful of the following steps is taken:
+
+      1. The bin corresponding to the request size is scanned, and if
+         a chunk of exactly the right size is found, it is taken.
+
+      2. The most recently remaindered chunk is used if it is big
+         enough.  This is a form of (roving) first fit, used only in
+         the absence of exact fits. Runs of consecutive requests use
+         the remainder of the chunk used for the previous such request
+         whenever possible. This limited use of a first-fit style
+         allocation strategy tends to give contiguous chunks
+         coextensive lifetimes, which improves locality and can reduce
+         fragmentation in the long run.
+
+      3. Other bins are scanned in increasing size order, using a
+         chunk big enough to fulfill the request, and splitting off
+         any remainder.  This search is strictly by best-fit; i.e.,
+         the smallest (with ties going to approximately the least
+         recently used) chunk that fits is selected.
+
+      4. If large enough, the chunk bordering the end of memory
+         (`top') is split off. (This use of `top' is in accord with
+         the best-fit search rule.  In effect, `top' is treated as
+         larger (and thus less well fitting) than any other available
+         chunk since it can be extended to be as large as necessary
+         (up to system limitations).
+
+      5. If the request size meets the mmap threshold and the
+         system supports mmap, and there are few enough currently
+         allocated mmapped regions, and a call to mmap succeeds,
+         the request is allocated via direct memory mapping.
+
+      6. Otherwise, the top of memory is extended by
+         obtaining more space from the system (normally using sbrk,
+         but definable to anything else via the MORECORE macro).
+         Memory is gathered from the system (in system page-sized
+         units) in a way that allows chunks obtained across different
+         sbrk calls to be consolidated, but does not require
+         contiguous memory. Thus, it should be safe to intersperse
+         mallocs with other sbrk calls.
+
+
+      All allocations are made from the the `lowest' part of any found
+      chunk. (The implementation invariant is that prev_inuse is
+      always true of any allocated chunk; i.e., that each allocated
+      chunk borders either a previously allocated and still in-use chunk,
+      or the base of its memory arena.)
+
+*/
+
+#if __STD_C
+Void_t* mALLOc(size_t bytes)
+#else
+Void_t* mALLOc(bytes) size_t bytes;
+#endif
+{
+  mchunkptr victim;                  /* inspected/selected chunk */
+  INTERNAL_SIZE_T victim_size;       /* its size */
+  int       idx;                     /* index for bin traversal */
+  mbinptr   bin;                     /* associated bin */
+  mchunkptr remainder;               /* remainder from a split */
+  long      remainder_size;          /* its size */
+  int       remainder_index;         /* its bin index */
+  unsigned long block;               /* block traverser bit */
+  int       startidx;                /* first bin of a traversed block */
+  mchunkptr fwd;                     /* misc temp for linking */
+  mchunkptr bck;                     /* misc temp for linking */
+  mbinptr q;                         /* misc temp */
+
+  INTERNAL_SIZE_T nb  = request2size(bytes);  /* padded request size; */
+
+  /* Check for exact match in a bin */
+
+  if (is_small_request(nb))  /* Faster version for small requests */
+  {
+    idx = smallbin_index(nb); 
+
+    /* No traversal or size check necessary for small bins.  */
+
+    q = bin_at(idx);
+    victim = last(q);
+
+    /* Also scan the next one, since it would have a remainder < MINSIZE */
+    if (victim == q)
+    {
+      q = next_bin(q);
+      victim = last(q);
+    }
+    if (victim != q)
+    {
+      victim_size = chunksize(victim);
+      unlink(victim, bck, fwd);
+      set_inuse_bit_at_offset(victim, victim_size);
+      check_malloced_chunk(victim, nb);
+      return chunk2mem(victim);
+    }
+
+    idx += 2; /* Set for bin scan below. We've already scanned 2 bins. */
+
+  }
+  else
+  {
+    idx = bin_index(nb);
+    bin = bin_at(idx);
+
+    for (victim = last(bin); victim != bin; victim = victim->bk)
+    {
+      victim_size = chunksize(victim);
+      remainder_size = victim_size - nb;
+      
+      if (remainder_size >= (long)MINSIZE) /* too big */
+      {
+        --idx; /* adjust to rescan below after checking last remainder */
+        break;   
+      }
+
+      else if (remainder_size >= 0) /* exact fit */
+      {
+        unlink(victim, bck, fwd);
+        set_inuse_bit_at_offset(victim, victim_size);
+        check_malloced_chunk(victim, nb);
+        return chunk2mem(victim);
+      }
+    }
+
+    ++idx; 
+
+  }
+
+  /* Try to use the last split-off remainder */
+
+  if ( (victim = last_remainder->fd) != last_remainder)
+  {
+    victim_size = chunksize(victim);
+    remainder_size = victim_size - nb;
+
+    if (remainder_size >= (long)MINSIZE) /* re-split */
+    {
+      remainder = chunk_at_offset(victim, nb);
+      set_head(victim, nb | PREV_INUSE);
+      link_last_remainder(remainder);
+      set_head(remainder, remainder_size | PREV_INUSE);
+      set_foot(remainder, remainder_size);
+      check_malloced_chunk(victim, nb);
+      return chunk2mem(victim);
+    }
+
+    clear_last_remainder;
+
+    if (remainder_size >= 0)  /* exhaust */
+    {
+      set_inuse_bit_at_offset(victim, victim_size);
+      check_malloced_chunk(victim, nb);
+      return chunk2mem(victim);
+    }
+
+    /* Else place in bin */
+
+    frontlink(victim, victim_size, remainder_index, bck, fwd);
+  }
+
+  /* 
+     If there are any possibly nonempty big-enough blocks, 
+     search for best fitting chunk by scanning bins in blockwidth units.
+  */
+
+  if ( (block = idx2binblock(idx)) <= binblocks)  
+  {
+
+    /* Get to the first marked block */
+
+    if ( (block & binblocks) == 0) 
+    {
+      /* force to an even block boundary */
+      idx = (idx & ~(BINBLOCKWIDTH - 1)) + BINBLOCKWIDTH;
+      block <<= 1;
+      while ((block & binblocks) == 0)
+      {
+        idx += BINBLOCKWIDTH;
+        block <<= 1;
+      }
+    }
+      
+    /* For each possibly nonempty block ... */
+    for (;;)  
+    {
+      startidx = idx;          /* (track incomplete blocks) */
+      q = bin = bin_at(idx);
+
+      /* For each bin in this block ... */
+      do
+      {
+        /* Find and use first big enough chunk ... */
+
+        for (victim = last(bin); victim != bin; victim = victim->bk)
+        {
+          victim_size = chunksize(victim);
+          remainder_size = victim_size - nb;
+
+          if (remainder_size >= (long)MINSIZE) /* split */
+          {
+            remainder = chunk_at_offset(victim, nb);
+            set_head(victim, nb | PREV_INUSE);
+            unlink(victim, bck, fwd);
+            link_last_remainder(remainder);
+            set_head(remainder, remainder_size | PREV_INUSE);
+            set_foot(remainder, remainder_size);
+            check_malloced_chunk(victim, nb);
+            return chunk2mem(victim);
+          }
+
+          else if (remainder_size >= 0)  /* take */
+          {
+            set_inuse_bit_at_offset(victim, victim_size);
+            unlink(victim, bck, fwd);
+            check_malloced_chunk(victim, nb);
+            return chunk2mem(victim);
+          }
+
+        }
+
+       bin = next_bin(bin);
+
+      } while ((++idx & (BINBLOCKWIDTH - 1)) != 0);
+
+      /* Clear out the block bit. */
+
+      do   /* Possibly backtrack to try to clear a partial block */
+      {
+        if ((startidx & (BINBLOCKWIDTH - 1)) == 0)
+        {
+          binblocks &= ~block;
+          break;
+        }
+        --startidx;
+       q = prev_bin(q);
+      } while (first(q) == q);
+
+      /* Get to the next possibly nonempty block */
+
+      if ( (block <<= 1) <= binblocks && (block != 0) ) 
+      {
+        while ((block & binblocks) == 0)
+        {
+          idx += BINBLOCKWIDTH;
+          block <<= 1;
+        }
+      }
+      else
+        break;
+    }
+  }
+
+
+  /* Try to use top chunk */
+
+  /* Require that there be a remainder, ensuring top always exists  */
+  if ( (remainder_size = chunksize(top) - nb) < (long)MINSIZE)
+  {
+
+#if HAVE_MMAP
+    /* If big and would otherwise need to extend, try to use mmap instead */
+    if ((unsigned long)nb >= (unsigned long)mmap_threshold &&
+        (victim = mmap_chunk(nb)) != 0)
+      return chunk2mem(victim);
+#endif
+
+    /* Try to extend */
+    malloc_extend_top(nb);
+    if ( (remainder_size = chunksize(top) - nb) < (long)MINSIZE)
+      return 0; /* propagate failure */
+  }
+
+  victim = top;
+  set_head(victim, nb | PREV_INUSE);
+  top = chunk_at_offset(victim, nb);
+  set_head(top, remainder_size | PREV_INUSE);
+  check_malloced_chunk(victim, nb);
+  return chunk2mem(victim);
+
+}
+
+
+
+
+
+/*
+
+  free() algorithm :
+
+    cases:
+
+       1. free(0) has no effect.  
+
+       2. If the chunk was allocated via mmap, it is release via munmap().
+
+       3. If a returned chunk borders the current high end of memory,
+          it is consolidated into the top, and if the total unused
+          topmost memory exceeds the trim threshold, malloc_trim is
+          called.
+
+       4. Other chunks are consolidated as they arrive, and
+          placed in corresponding bins. (This includes the case of
+          consolidating with the current `last_remainder').
+
+*/
+
+
+#if __STD_C
+void fREe(Void_t* mem)
+#else
+void fREe(mem) Void_t* mem;
+#endif
+{
+  mchunkptr p;         /* chunk corresponding to mem */
+  INTERNAL_SIZE_T hd;  /* its head field */
+  INTERNAL_SIZE_T sz;  /* its size */
+  int       idx;       /* its bin index */
+  mchunkptr next;      /* next contiguous chunk */
+  INTERNAL_SIZE_T nextsz; /* its size */
+  INTERNAL_SIZE_T prevsz; /* size of previous contiguous chunk */
+  mchunkptr bck;       /* misc temp for linking */
+  mchunkptr fwd;       /* misc temp for linking */
+  int       islr;      /* track whether merging with last_remainder */
+
+  if (mem == 0)                              /* free(0) has no effect */
+    return;
+
+  p = mem2chunk(mem);
+  hd = p->size;
+
+#if HAVE_MMAP
+  if (hd & IS_MMAPPED)                       /* release mmapped memory. */
+  {
+    munmap_chunk(p);
+    return;
+  }
+#endif
+  
+  check_inuse_chunk(p);
+  
+  sz = hd & ~PREV_INUSE;
+  next = chunk_at_offset(p, sz);
+  nextsz = chunksize(next);
+  
+  if (next == top)                            /* merge with top */
+  {
+    sz += nextsz;
+
+    if (!(hd & PREV_INUSE))                    /* consolidate backward */
+    {
+      prevsz = p->prev_size;
+      p = chunk_at_offset(p, -prevsz);
+      sz += prevsz;
+      unlink(p, bck, fwd);
+    }
+
+    set_head(p, sz | PREV_INUSE);
+    top = p;
+    if ((unsigned long)(sz) >= (unsigned long)trim_threshold) 
+      malloc_trim(top_pad); 
+    return;
+  }
+
+  set_head(next, nextsz);                    /* clear inuse bit */
+
+  islr = 0;
+
+  if (!(hd & PREV_INUSE))                    /* consolidate backward */
+  {
+    prevsz = p->prev_size;
+    p = chunk_at_offset(p, -prevsz);
+    sz += prevsz;
+    
+    if (p->fd == last_remainder)             /* keep as last_remainder */
+      islr = 1;
+    else
+      unlink(p, bck, fwd);
+  }
+  
+  if (!(inuse_bit_at_offset(next, nextsz)))   /* consolidate forward */
+  {
+    sz += nextsz;
+    
+    if (!islr && next->fd == last_remainder)  /* re-insert last_remainder */
+    {
+      islr = 1;
+      link_last_remainder(p);   
+    }
+    else
+      unlink(next, bck, fwd);
+  }
+
+
+  set_head(p, sz | PREV_INUSE);
+  set_foot(p, sz);
+  if (!islr)
+    frontlink(p, sz, idx, bck, fwd);  
+}
+
+
+
+
+
+
+/*
+
+  Realloc algorithm:
+
+    Chunks that were obtained via mmap cannot be extended or shrunk
+    unless HAVE_MREMAP is defined, in which case mremap is used.
+    Otherwise, if their reallocation is for additional space, they are
+    copied.  If for less, they are just left alone.
+
+    Otherwise, if the reallocation is for additional space, and the
+    chunk can be extended, it is, else a malloc-copy-free sequence is
+    taken.  There are several different ways that a chunk could be
+    extended. All are tried:
+
+       * Extending forward into following adjacent free chunk.
+       * Shifting backwards, joining preceding adjacent space
+       * Both shifting backwards and extending forward.
+       * Extending into newly sbrked space
+
+    Unless the #define REALLOC_ZERO_BYTES_FREES is set, realloc with a
+    size argument of zero (re)allocates a minimum-sized chunk.
+
+    If the reallocation is for less space, and the new request is for
+    a `small' (<512 bytes) size, then the newly unused space is lopped
+    off and freed.
+
+    The old unix realloc convention of allowing the last-free'd chunk
+    to be used as an argument to realloc is no longer supported.
+    I don't know of any programs still relying on this feature,
+    and allowing it would also allow too many other incorrect 
+    usages of realloc to be sensible.
+
+
+*/
+
+
+#if __STD_C
+Void_t* rEALLOc(Void_t* oldmem, size_t bytes)
+#else
+Void_t* rEALLOc(oldmem, bytes) Void_t* oldmem; size_t bytes;
+#endif
+{
+  INTERNAL_SIZE_T    nb;      /* padded request size */
+
+  mchunkptr oldp;             /* chunk corresponding to oldmem */
+  INTERNAL_SIZE_T    oldsize; /* its size */
+
+  mchunkptr newp;             /* chunk to return */
+  INTERNAL_SIZE_T    newsize; /* its size */
+  Void_t*   newmem;           /* corresponding user mem */
+
+  mchunkptr next;             /* next contiguous chunk after oldp */
+  INTERNAL_SIZE_T  nextsize;  /* its size */
+
+  mchunkptr prev;             /* previous contiguous chunk before oldp */
+  INTERNAL_SIZE_T  prevsize;  /* its size */
+
+  mchunkptr remainder;        /* holds split off extra space from newp */
+  INTERNAL_SIZE_T  remainder_size;   /* its size */
+
+  mchunkptr bck;              /* misc temp for linking */
+  mchunkptr fwd;              /* misc temp for linking */
+
+#ifdef REALLOC_ZERO_BYTES_FREES
+  if (bytes == 0) { fREe(oldmem); return 0; }
+#endif
+
+
+  /* realloc of null is supposed to be same as malloc */
+  if (oldmem == 0) return mALLOc(bytes);
+
+  newp    = oldp    = mem2chunk(oldmem);
+  newsize = oldsize = chunksize(oldp);
+
+
+  nb = request2size(bytes);
+
+#if HAVE_MMAP
+  if (chunk_is_mmapped(oldp)) 
+  {
+#if HAVE_MREMAP
+    newp = mremap_chunk(oldp, nb);
+    if(newp) return chunk2mem(newp);
+#endif
+    /* Note the extra SIZE_SZ overhead. */
+    if(oldsize - SIZE_SZ >= nb) return oldmem; /* do nothing */
+    /* Must alloc, copy, free. */
+    newmem = mALLOc(bytes);
+    if (newmem == 0) return 0; /* propagate failure */
+    MALLOC_COPY(newmem, oldmem, oldsize - 2*SIZE_SZ);
+    munmap_chunk(oldp);
+    return newmem;
+  }
+#endif
+
+  check_inuse_chunk(oldp);
+
+  if ((long)(oldsize) < (long)(nb))  
+  {
+
+    /* Try expanding forward */
+
+    next = chunk_at_offset(oldp, oldsize);
+    if (next == top || !inuse(next)) 
+    {
+      nextsize = chunksize(next);
+
+      /* Forward into top only if a remainder */
+      if (next == top)
+      {
+        if ((long)(nextsize + newsize) >= (long)(nb + MINSIZE))
+        {
+          newsize += nextsize;
+          top = chunk_at_offset(oldp, nb);
+          set_head(top, (newsize - nb) | PREV_INUSE);
+          set_head_size(oldp, nb);
+          return chunk2mem(oldp);
+        }
+      }
+
+      /* Forward into next chunk */
+      else if (((long)(nextsize + newsize) >= (long)(nb)))
+      { 
+        unlink(next, bck, fwd);
+        newsize  += nextsize;
+        goto split;
+      }
+    }
+    else
+    {
+      next = 0;
+      nextsize = 0;
+    }
+
+    /* Try shifting backwards. */
+
+    if (!prev_inuse(oldp))
+    {
+      prev = prev_chunk(oldp);
+      prevsize = chunksize(prev);
+
+      /* try forward + backward first to save a later consolidation */
+
+      if (next != 0)
+      {
+        /* into top */
+        if (next == top)
+        {
+          if ((long)(nextsize + prevsize + newsize) >= (long)(nb + MINSIZE))
+          {
+            unlink(prev, bck, fwd);
+            newp = prev;
+            newsize += prevsize + nextsize;
+            newmem = chunk2mem(newp);
+            MALLOC_COPY(newmem, oldmem, oldsize - SIZE_SZ);
+            top = chunk_at_offset(newp, nb);
+            set_head(top, (newsize - nb) | PREV_INUSE);
+            set_head_size(newp, nb);
+            return newmem;
+          }
+        }
+
+        /* into next chunk */
+        else if (((long)(nextsize + prevsize + newsize) >= (long)(nb)))
+        {
+          unlink(next, bck, fwd);
+          unlink(prev, bck, fwd);
+          newp = prev;
+          newsize += nextsize + prevsize;
+          newmem = chunk2mem(newp);
+          MALLOC_COPY(newmem, oldmem, oldsize - SIZE_SZ);
+          goto split;
+        }
+      }
+      
+      /* backward only */
+      if (prev != 0 && (long)(prevsize + newsize) >= (long)nb)  
+      {
+        unlink(prev, bck, fwd);
+        newp = prev;
+        newsize += prevsize;
+        newmem = chunk2mem(newp);
+        MALLOC_COPY(newmem, oldmem, oldsize - SIZE_SZ);
+        goto split;
+      }
+    }
+
+    /* Must allocate */
+
+    newmem = mALLOc (bytes);
+
+    if (newmem == 0)  /* propagate failure */
+      return 0; 
+
+    /* Avoid copy if newp is next chunk after oldp. */
+    /* (This can only happen when new chunk is sbrk'ed.) */
+
+    if ( (newp = mem2chunk(newmem)) == next_chunk(oldp)) 
+    {
+      newsize += chunksize(newp);
+      newp = oldp;
+      goto split;
+    }
+
+    /* Otherwise copy, free, and exit */
+    MALLOC_COPY(newmem, oldmem, oldsize - SIZE_SZ);
+    fREe(oldmem);
+    return newmem;
+  }
+
+
+ split:  /* split off extra room in old or expanded chunk */
+
+  if (newsize - nb >= MINSIZE) /* split off remainder */
+  {
+    remainder = chunk_at_offset(newp, nb);
+    remainder_size = newsize - nb;
+    set_head_size(newp, nb);
+    set_head(remainder, remainder_size | PREV_INUSE);
+    set_inuse_bit_at_offset(remainder, remainder_size);
+    fREe(chunk2mem(remainder)); /* let free() deal with it */
+  }
+  else
+  {
+    set_head_size(newp, newsize);
+    set_inuse_bit_at_offset(newp, newsize);
+  }
+
+  check_inuse_chunk(newp);
+  return chunk2mem(newp);
+}
+
+
+
+
+
+/*
+
+  memalign algorithm:
+
+    memalign requests more than enough space from malloc, finds a spot
+    within that chunk that meets the alignment request, and then
+    possibly frees the leading and trailing space. 
+
+    The alignment argument must be a power of two. This property is not
+    checked by memalign, so misuse may result in random runtime errors.
+
+    8-byte alignment is guaranteed by normal malloc calls, so don't
+    bother calling memalign with an argument of 8 or less.
+
+    Overreliance on memalign is a sure way to fragment space.
+
+*/
+
+
+#if __STD_C
+Void_t* mEMALIGn(size_t alignment, size_t bytes)
+#else
+Void_t* mEMALIGn(alignment, bytes) size_t alignment; size_t bytes;
+#endif
+{
+  INTERNAL_SIZE_T    nb;      /* padded  request size */
+  char*     m;                /* memory returned by malloc call */
+  mchunkptr p;                /* corresponding chunk */
+  char*     brk;              /* alignment point within p */
+  mchunkptr newp;             /* chunk to return */
+  INTERNAL_SIZE_T  newsize;   /* its size */
+  INTERNAL_SIZE_T  leadsize;  /* leading space befor alignment point */
+  mchunkptr remainder;        /* spare room at end to split off */
+  long      remainder_size;   /* its size */
+
+  /* If need less alignment than we give anyway, just relay to malloc */
+
+  if (alignment <= MALLOC_ALIGNMENT) return mALLOc(bytes);
+
+  /* Otherwise, ensure that it is at least a minimum chunk size */
+  
+  if (alignment <  MINSIZE) alignment = MINSIZE;
+
+  /* Call malloc with worst case padding to hit alignment. */
+
+  nb = request2size(bytes);
+  m  = (char*)(mALLOc(nb + alignment + MINSIZE));
+
+  if (m == 0) return 0; /* propagate failure */
+
+  p = mem2chunk(m);
+
+  if ((((unsigned long)(m)) % alignment) == 0) /* aligned */
+  {
+#if HAVE_MMAP
+    if(chunk_is_mmapped(p))
+      return chunk2mem(p); /* nothing more to do */
+#endif
+  }
+  else /* misaligned */
+  {
+    /* 
+      Find an aligned spot inside chunk.
+      Since we need to give back leading space in a chunk of at 
+      least MINSIZE, if the first calculation places us at
+      a spot with less than MINSIZE leader, we can move to the
+      next aligned spot -- we've allocated enough total room so that
+      this is always possible.
+    */
+
+    brk = (char*)mem2chunk(((unsigned long)(m + alignment - 1)) & -alignment);
+    if ((long)(brk - (char*)(p)) < MINSIZE) brk = brk + alignment;
+
+    newp = (mchunkptr)brk;
+    leadsize = brk - (char*)(p);
+    newsize = chunksize(p) - leadsize;
+
+#if HAVE_MMAP
+    if(chunk_is_mmapped(p)) 
+    {
+      newp->prev_size = p->prev_size + leadsize;
+      set_head(newp, newsize|IS_MMAPPED);
+      return chunk2mem(newp);
+    }
+#endif
+
+    /* give back leader, use the rest */
+
+    set_head(newp, newsize | PREV_INUSE);
+    set_inuse_bit_at_offset(newp, newsize);
+    set_head_size(p, leadsize);
+    fREe(chunk2mem(p));
+    p = newp;
+
+    assert (newsize >= nb && (((unsigned long)(chunk2mem(p))) % alignment) == 0);
+  }
+
+  /* Also give back spare room at the end */
+
+  remainder_size = chunksize(p) - nb;
+
+  if (remainder_size >= (long)MINSIZE)
+  {
+    remainder = chunk_at_offset(p, nb);
+    set_head(remainder, remainder_size | PREV_INUSE);
+    set_head_size(p, nb);
+    fREe(chunk2mem(remainder));
+  }
+
+  check_inuse_chunk(p);
+  return chunk2mem(p);
+
+}
+
+
+
+
+
+/*
+    valloc just invokes memalign with alignment argument equal
+    to the page size of the system (or as near to this as can
+    be figured out from all the includes/defines above.)
+*/
+
+#if __STD_C
+Void_t* vALLOc(size_t bytes)
+#else
+Void_t* vALLOc(bytes) size_t bytes;
+#endif
+{
+  return mEMALIGn (malloc_getpagesize, bytes);
+}
+
+/* 
+  pvalloc just invokes valloc for the nearest pagesize
+  that will accommodate request
+*/
+
+
+#if __STD_C
+Void_t* pvALLOc(size_t bytes)
+#else
+Void_t* pvALLOc(bytes) size_t bytes;
+#endif
+{
+  size_t pagesize = malloc_getpagesize;
+  return mEMALIGn (pagesize, (bytes + pagesize - 1) & ~(pagesize - 1));
+}
+
+/*
+
+  calloc calls malloc, then zeroes out the allocated chunk.
+
+*/
+
+#if __STD_C
+Void_t* cALLOc(size_t n, size_t elem_size)
+#else
+Void_t* cALLOc(n, elem_size) size_t n; size_t elem_size;
+#endif
+{
+  mchunkptr p;
+  INTERNAL_SIZE_T csz;
+
+  INTERNAL_SIZE_T sz = n * elem_size;
+
+  /* check if expand_top called, in which case don't need to clear */
+#if MORECORE_CLEARS
+  mchunkptr oldtop = top;
+  INTERNAL_SIZE_T oldtopsize = chunksize(top);
+#endif
+  Void_t* mem = mALLOc (sz);
+
+  if (mem == 0) 
+    return 0;
+  else
+  {
+    p = mem2chunk(mem);
+
+    /* Two optional cases in which clearing not necessary */
+
+
+#if HAVE_MMAP
+    if (chunk_is_mmapped(p)) return mem;
+#endif
+
+    csz = chunksize(p);
+
+#if MORECORE_CLEARS
+    if (p == oldtop && csz > oldtopsize) 
+    {
+      /* clear only the bytes from non-freshly-sbrked memory */
+      csz = oldtopsize;
+    }
+#endif
+
+    MALLOC_ZERO(mem, csz - SIZE_SZ);
+    return mem;
+  }
+}
+
+/*
+ 
+  cfree just calls free. It is needed/defined on some systems
+  that pair it with calloc, presumably for odd historical reasons.
+
+*/
+
+#if !defined(INTERNAL_LINUX_C_LIB) || !defined(__ELF__)
+#if __STD_C
+void cfree(Void_t *mem)
+#else
+void cfree(mem) Void_t *mem;
+#endif
+{
+  fREe(mem);
+}
+#endif
+
+
+
+
+/*
+
+    Malloc_trim gives memory back to the system (via negative
+    arguments to sbrk) if there is unused memory at the `high' end of
+    the malloc pool. You can call this after freeing large blocks of
+    memory to potentially reduce the system-level memory requirements
+    of a program. However, it cannot guarantee to reduce memory. Under
+    some allocation patterns, some large free blocks of memory will be
+    locked between two used chunks, so they cannot be given back to
+    the system.
+
+    The `pad' argument to malloc_trim represents the amount of free
+    trailing space to leave untrimmed. If this argument is zero,
+    only the minimum amount of memory to maintain internal data
+    structures will be left (one page or less). Non-zero arguments
+    can be supplied to maintain enough trailing space to service
+    future expected allocations without having to re-obtain memory
+    from the system.
+
+    Malloc_trim returns 1 if it actually released any memory, else 0.
+
+*/
+
+#if __STD_C
+int malloc_trim(size_t pad)
+#else
+int malloc_trim(pad) size_t pad;
+#endif
+{
+  long  top_size;        /* Amount of top-most memory */
+  long  extra;           /* Amount to release */
+  char* current_brk;     /* address returned by pre-check sbrk call */
+  char* new_brk;         /* address returned by negative sbrk call */
+
+  unsigned long pagesz = malloc_getpagesize;
+
+  top_size = chunksize(top);
+  extra = ((top_size - pad - MINSIZE + (pagesz-1)) / pagesz - 1) * pagesz;
+
+  if (extra < (long)pagesz)  /* Not enough memory to release */
+    return 0;
+
+  else
+  {
+    /* Test to make sure no one else called sbrk */
+    current_brk = (char*)(MORECORE (0));
+    if (current_brk != (char*)(top) + top_size)
+      return 0;     /* Apparently we don't own memory; must fail */
+
+    else
+    {
+      new_brk = (char*)(MORECORE (-extra));
+      
+      if (new_brk == (char*)(MORECORE_FAILURE)) /* sbrk failed? */
+      {
+        /* Try to figure out what we have */
+        current_brk = (char*)(MORECORE (0));
+        top_size = current_brk - (char*)top;
+        if (top_size >= (long)MINSIZE) /* if not, we are very very dead! */
+        {
+          sbrked_mem = current_brk - sbrk_base;
+          set_head(top, top_size | PREV_INUSE);
+        }
+        check_chunk(top);
+        return 0; 
+      }
+
+      else
+      {
+        /* Success. Adjust top accordingly. */
+        set_head(top, (top_size - extra) | PREV_INUSE);
+        sbrked_mem -= extra;
+        check_chunk(top);
+        return 1;
+      }
+    }
+  }
+}
+
+
+
+
+/*
+  malloc_usable_size:
+
+    This routine tells you how many bytes you can actually use in an
+    allocated chunk, which may be more than you requested (although
+    often not). You can use this many bytes without worrying about
+    overwriting other allocated objects. Not a particularly great
+    programming practice, but still sometimes useful.
+
+*/
+
+#if __STD_C
+size_t malloc_usable_size(Void_t* mem)
+#else
+size_t malloc_usable_size(mem) Void_t* mem;
+#endif
+{
+  mchunkptr p;
+  if (mem == 0)
+    return 0;
+  else
+  {
+    p = mem2chunk(mem);
+    if(!chunk_is_mmapped(p))
+    {
+      if (!inuse(p)) return 0;
+      check_inuse_chunk(p);
+      return chunksize(p) - SIZE_SZ;
+    }
+    return chunksize(p) - 2*SIZE_SZ;
+  }
+}
+
+
+
+
+
+/* Utility to update current_mallinfo for malloc_stats and mallinfo() */
+
+void malloc_update_mallinfo() 
+{
+  int i;
+  mbinptr b;
+  mchunkptr p;
+#if DEBUG
+  mchunkptr q;
+#endif
+
+  INTERNAL_SIZE_T avail = chunksize(top);
+  int   navail = ((long)(avail) >= (long)MINSIZE)? 1 : 0;
+
+  for (i = 1; i < NAV; ++i)
+  {
+    b = bin_at(i);
+    for (p = last(b); p != b; p = p->bk) 
+    {
+#if DEBUG
+      check_free_chunk(p);
+      for (q = next_chunk(p); 
+           q < top && inuse(q) && (long)(chunksize(q)) >= (long)MINSIZE; 
+           q = next_chunk(q))
+        check_inuse_chunk(q);
+#endif
+      avail += chunksize(p);
+      navail++;
+    }
+  }
+
+  current_mallinfo.ordblks = navail;
+  current_mallinfo.uordblks = sbrked_mem - avail;
+  current_mallinfo.fordblks = avail;
+  current_mallinfo.hblks = n_mmaps;
+  current_mallinfo.hblkhd = mmapped_mem;
+  current_mallinfo.keepcost = chunksize(top);
+
+}
+
+
+
+
+/*
+
+  malloc_stats:
+
+    Prints on stderr the amount of space obtain from the system (both
+    via sbrk and mmap), the maximum amount (which may be more than
+    current if malloc_trim and/or munmap got called), the maximum
+    number of simultaneous mmap regions used, and the current number
+    of bytes allocated via malloc (or realloc, etc) but not yet
+    freed. (Note that this is the number of bytes allocated, not the
+    number requested. It will be larger than the number requested
+    because of alignment and bookkeeping overhead.)
+
+*/
+
+void malloc_stats()
+{
+  malloc_update_mallinfo();
+  fprintf(stderr, "max system bytes = %10u\n", 
+          (unsigned int)(max_total_mem));
+  fprintf(stderr, "system bytes     = %10u\n", 
+          (unsigned int)(sbrked_mem + mmapped_mem));
+  fprintf(stderr, "in use bytes     = %10u\n", 
+          (unsigned int)(current_mallinfo.uordblks + mmapped_mem));
+#if HAVE_MMAP
+  fprintf(stderr, "max mmap regions = %10u\n", 
+          (unsigned int)max_n_mmaps);
+#endif
+}
+
+/*
+  mallinfo returns a copy of updated current mallinfo.
+*/
+
+struct mallinfo mALLINFo()
+{
+  malloc_update_mallinfo();
+  return current_mallinfo;
+}
+
+
+
+
+
+/*
+  mallopt:
+
+    mallopt is the general SVID/XPG interface to tunable parameters.
+    The format is to provide a (parameter-number, parameter-value) pair.
+    mallopt then sets the corresponding parameter to the argument
+    value if it can (i.e., so long as the value is meaningful),
+    and returns 1 if successful else 0.
+
+    See descriptions of tunable parameters above.
+
+*/
+
+#if __STD_C
+int mALLOPt(int param_number, int value)
+#else
+int mALLOPt(param_number, value) int param_number; int value;
+#endif
+{
+  switch(param_number) 
+  {
+    case M_TRIM_THRESHOLD:
+      trim_threshold = value; return 1; 
+    case M_TOP_PAD:
+      top_pad = value; return 1; 
+    case M_MMAP_THRESHOLD:
+      mmap_threshold = value; return 1;
+    case M_MMAP_MAX:
+#if HAVE_MMAP
+      n_mmaps_max = value; return 1;
+#else
+      if (value != 0) return 0; else  n_mmaps_max = value; return 1;
+#endif
+
+    default:
+      return 0;
+  }
+}
+
+/*
+
+History:
+
+    V2.6.5 Wed Jun 17 15:57:31 1998  Doug Lea  (dl at gee)
+      * Fixed ordering problem with boundary-stamping
+
+    V2.6.3 Sun May 19 08:17:58 1996  Doug Lea  (dl at gee)
+      * Added pvalloc, as recommended by H.J. Liu
+      * Added 64bit pointer support mainly from Wolfram Gloger
+      * Added anonymously donated WIN32 sbrk emulation
+      * Malloc, calloc, getpagesize: add optimizations from Raymond Nijssen
+      * malloc_extend_top: fix mask error that caused wastage after
+        foreign sbrks
+      * Add linux mremap support code from HJ Liu
+   
+    V2.6.2 Tue Dec  5 06:52:55 1995  Doug Lea  (dl at gee)
+      * Integrated most documentation with the code.
+      * Add support for mmap, with help from 
+        Wolfram Gloger (Gloger@lrz.uni-muenchen.de).
+      * Use last_remainder in more cases.
+      * Pack bins using idea from  colin@nyx10.cs.du.edu
+      * Use ordered bins instead of best-fit threshhold
+      * Eliminate block-local decls to simplify tracing and debugging.
+      * Support another case of realloc via move into top
+      * Fix error occuring when initial sbrk_base not word-aligned.  
+      * Rely on page size for units instead of SBRK_UNIT to
+        avoid surprises about sbrk alignment conventions.
+      * Add mallinfo, mallopt. Thanks to Raymond Nijssen
+        (raymond@es.ele.tue.nl) for the suggestion. 
+      * Add `pad' argument to malloc_trim and top_pad mallopt parameter.
+      * More precautions for cases where other routines call sbrk,
+        courtesy of Wolfram Gloger (Gloger@lrz.uni-muenchen.de).
+      * Added macros etc., allowing use in linux libc from
+        H.J. Lu (hjl@gnu.ai.mit.edu)
+      * Inverted this history list
+
+    V2.6.1 Sat Dec  2 14:10:57 1995  Doug Lea  (dl at gee)
+      * Re-tuned and fixed to behave more nicely with V2.6.0 changes.
+      * Removed all preallocation code since under current scheme
+        the work required to undo bad preallocations exceeds
+        the work saved in good cases for most test programs.
+      * No longer use return list or unconsolidated bins since
+        no scheme using them consistently outperforms those that don't
+        given above changes.
+      * Use best fit for very large chunks to prevent some worst-cases.
+      * Added some support for debugging
+
+    V2.6.0 Sat Nov  4 07:05:23 1995  Doug Lea  (dl at gee)
+      * Removed footers when chunks are in use. Thanks to
+        Paul Wilson (wilson@cs.texas.edu) for the suggestion.
+
+    V2.5.4 Wed Nov  1 07:54:51 1995  Doug Lea  (dl at gee)
+      * Added malloc_trim, with help from Wolfram Gloger 
+        (wmglo@Dent.MED.Uni-Muenchen.DE).
+
+    V2.5.3 Tue Apr 26 10:16:01 1994  Doug Lea  (dl at g)
+
+    V2.5.2 Tue Apr  5 16:20:40 1994  Doug Lea  (dl at g)
+      * realloc: try to expand in both directions
+      * malloc: swap order of clean-bin strategy;
+      * realloc: only conditionally expand backwards
+      * Try not to scavenge used bins
+      * Use bin counts as a guide to preallocation
+      * Occasionally bin return list chunks in first scan
+      * Add a few optimizations from colin@nyx10.cs.du.edu
+
+    V2.5.1 Sat Aug 14 15:40:43 1993  Doug Lea  (dl at g)
+      * faster bin computation & slightly different binning
+      * merged all consolidations to one part of malloc proper
+         (eliminating old malloc_find_space & malloc_clean_bin)
+      * Scan 2 returns chunks (not just 1)
+      * Propagate failure in realloc if malloc returns 0
+      * Add stuff to allow compilation on non-ANSI compilers 
+          from kpv@research.att.com
+     
+    V2.5 Sat Aug  7 07:41:59 1993  Doug Lea  (dl at g.oswego.edu)
+      * removed potential for odd address access in prev_chunk
+      * removed dependency on getpagesize.h
+      * misc cosmetics and a bit more internal documentation
+      * anticosmetics: mangled names in macros to evade debugger strangeness
+      * tested on sparc, hp-700, dec-mips, rs6000 
+          with gcc & native cc (hp, dec only) allowing
+          Detlefs & Zorn comparison study (in SIGPLAN Notices.)
+
+    Trial version Fri Aug 28 13:14:29 1992  Doug Lea  (dl at g.oswego.edu)
+      * Based loosely on libg++-1.2X malloc. (It retains some of the overall 
+         structure of old version,  but most details differ.)
+
+*/
+
Index: omalloc/dlmalloc.h
===================================================================
--- omalloc/dlmalloc.h	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
+++ omalloc/dlmalloc.h	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
@@ -0,0 +1,938 @@
+/*******************************************************************
+ *  File:    dlmalloc.h
+ *  Purpose: declarations for dlmalloc 
+ *  This was obtained by taking cutting out the beginning of malloc.c 
+ *
+ *  Version: $Id: dlmalloc.h,v 1.1 2000-08-14 12:18:25 obachman Exp $
+ *******************************************************************/
+#ifndef DL_MALLOC_H
+#define DL_MALLOC_H
+
+/* define to -1 if you want that this implementation provides
+   malloc/calloc/realloc/free funcs */
+#ifndef OM_PROVIDE_MALLOC
+#define OM_PROVIDE_MALLOC 0
+#endif
+
+
+#define OM_MALLOC_MALLOC   mALLOc
+#define OM_MALLOC_REALLOC  rEALLOc
+#define OM_MALLOC_FREE     fREe
+#define OM_MALLOC_VALLOC   vALLOc
+#define OM_MALLOC_VFREE(addr, size) OM_MALLOC_FREE(addr)
+#define OM_MALLOC_SIZEOF_ADDR(addr) malloc_usable_size(addr)
+
+/* Statistics */
+extern unsigned long mmapped_mem;
+extern unsigned long max_mmapped_mem;
+extern unsigned long max_total_mem; 
+extern unsigned long max_sbrked_mem; 
+extern struct mallinfo current_mallinfo;
+extern void malloc_update_mallinfo();
+
+#define OM_MALLOC_UPDATE_INFO           malloc_update_mallinfo()
+#define OM_MALLOC_USED_BYTES            current_mallinfo.uordblks + mmapped_mem           
+#define OM_MALLOC_AVAIL_BYTES           current_mallinfo.fordblks
+#define OM_MALLOC_CURRENT_BYTES_MMAP    mmapped_mem
+#define OM_MALLOC_MAX_BYTES_MMAP        max_mmapped_mem
+#define OM_MALLOC_CURRENT_BYTES_SYSTEM  current_mallinfo.arena + mmapped_mem
+#define OM_MALLOC_MAX_BYTES_SYSTEM      max_total_mem
+#define OM_MALLOC_CURRENT_BYTES_SBRK    current_mallinfo.arena
+#define OM_MALLOC_MAX_BYTES_SBRK        max_sbrked_mem
+
+/* ---------- To make a malloc.h, start cutting here ------------ */
+
+/* 
+  A version of malloc/free/realloc written by Doug Lea and released to the 
+  public domain.  Send questions/comments/complaints/performance data
+  to dl@cs.oswego.edu
+
+* VERSION 2.6.5  Wed Jun 17 15:55:16 1998  Doug Lea  (dl at gee)
+  
+   Note: There may be an updated version of this malloc obtainable at
+           ftp://g.oswego.edu/pub/misc/malloc.c
+         Check before installing!
+
+   Note: This version differs from 2.6.4 only by correcting a
+         statement ordering error that could cause failures only
+         when calls to this malloc are interposed with calls to
+         other memory allocators.
+
+* Why use this malloc?
+
+  This is not the fastest, most space-conserving, most portable, or
+  most tunable malloc ever written. However it is among the fastest
+  while also being among the most space-conserving, portable and tunable.
+  Consistent balance across these factors results in a good general-purpose 
+  allocator. For a high-level description, see 
+     http://g.oswego.edu/dl/html/malloc.html
+
+* Synopsis of public routines
+
+  (Much fuller descriptions are contained in the program documentation below.)
+
+  malloc(size_t n);
+     Return a pointer to a newly allocated chunk of at least n bytes, or null
+     if no space is available.
+  free(Void_t* p);
+     Release the chunk of memory pointed to by p, or no effect if p is null.
+  realloc(Void_t* p, size_t n);
+     Return a pointer to a chunk of size n that contains the same data
+     as does chunk p up to the minimum of (n, p's size) bytes, or null
+     if no space is available. The returned pointer may or may not be
+     the same as p. If p is null, equivalent to malloc.  Unless the
+     #define REALLOC_ZERO_BYTES_FREES below is set, realloc with a
+     size argument of zero (re)allocates a minimum-sized chunk.
+  memalign(size_t alignment, size_t n);
+     Return a pointer to a newly allocated chunk of n bytes, aligned
+     in accord with the alignment argument, which must be a power of
+     two.
+  valloc(size_t n);
+     Equivalent to memalign(pagesize, n), where pagesize is the page
+     size of the system (or as near to this as can be figured out from
+     all the includes/defines below.)
+  pvalloc(size_t n);
+     Equivalent to valloc(minimum-page-that-holds(n)), that is,
+     round up n to nearest pagesize.
+  calloc(size_t unit, size_t quantity);
+     Returns a pointer to quantity * unit bytes, with all locations
+     set to zero.
+  cfree(Void_t* p);
+     Equivalent to free(p).
+  malloc_trim(size_t pad);
+     Release all but pad bytes of freed top-most memory back 
+     to the system. Return 1 if successful, else 0.
+  malloc_usable_size(Void_t* p);
+     Report the number usable allocated bytes associated with allocated
+     chunk p. This may or may not report more bytes than were requested,
+     due to alignment and minimum size constraints.
+  malloc_stats();
+     Prints brief summary statistics on stderr.
+  mallinfo()
+     Returns (by copy) a struct containing various summary statistics.
+  mallopt(int parameter_number, int parameter_value)
+     Changes one of the tunable parameters described below. Returns
+     1 if successful in changing the parameter, else 0.
+
+* Vital statistics:
+
+  Alignment:                            8-byte
+       8 byte alignment is currently hardwired into the design.  This
+       seems to suffice for all current machines and C compilers.
+
+  Assumed pointer representation:       4 or 8 bytes
+       Code for 8-byte pointers is untested by me but has worked
+       reliably by Wolfram Gloger, who contributed most of the
+       changes supporting this.
+
+  Assumed size_t  representation:       4 or 8 bytes
+       Note that size_t is allowed to be 4 bytes even if pointers are 8.        
+
+  Minimum overhead per allocated chunk: 4 or 8 bytes
+       Each malloced chunk has a hidden overhead of 4 bytes holding size
+       and status information.  
+
+  Minimum allocated size: 4-byte ptrs:  16 bytes    (including 4 overhead)
+                          8-byte ptrs:  24/32 bytes (including, 4/8 overhead)
+                                     
+       When a chunk is freed, 12 (for 4byte ptrs) or 20 (for 8 byte
+       ptrs but 4 byte size) or 24 (for 8/8) additional bytes are 
+       needed; 4 (8) for a trailing size field
+       and 8 (16) bytes for free list pointers. Thus, the minimum
+       allocatable size is 16/24/32 bytes.
+
+       Even a request for zero bytes (i.e., malloc(0)) returns a
+       pointer to something of the minimum allocatable size.
+
+  Maximum allocated size: 4-byte size_t: 2^31 -  8 bytes
+                          8-byte size_t: 2^63 - 16 bytes
+
+       It is assumed that (possibly signed) size_t bit values suffice to
+       represent chunk sizes. `Possibly signed' is due to the fact
+       that `size_t' may be defined on a system as either a signed or
+       an unsigned type. To be conservative, values that would appear
+       as negative numbers are avoided.  
+       Requests for sizes with a negative sign bit will return a
+       minimum-sized chunk.
+
+  Maximum overhead wastage per allocated chunk: normally 15 bytes
+
+       Alignnment demands, plus the minimum allocatable size restriction
+       make the normal worst-case wastage 15 bytes (i.e., up to 15
+       more bytes will be allocated than were requested in malloc), with 
+       two exceptions:
+         1. Because requests for zero bytes allocate non-zero space,
+            the worst case wastage for a request of zero bytes is 24 bytes.
+         2. For requests >= mmap_threshold that are serviced via
+            mmap(), the worst case wastage is 8 bytes plus the remainder
+            from a system page (the minimal mmap unit); typically 4096 bytes.
+
+* Limitations
+
+    Here are some features that are NOT currently supported
+
+    * No user-definable hooks for callbacks and the like.
+    * No automated mechanism for fully checking that all accesses
+      to malloced memory stay within their bounds.
+    * No support for compaction.
+
+* Synopsis of compile-time options:
+
+    People have reported using previous versions of this malloc on all
+    versions of Unix, sometimes by tweaking some of the defines
+    below. It has been tested most extensively on Solaris and
+    Linux. It is also reported to work on WIN32 platforms.
+    People have also reported adapting this malloc for use in
+    stand-alone embedded systems.
+
+    The implementation is in straight, hand-tuned ANSI C.  Among other
+    consequences, it uses a lot of macros.  Because of this, to be at
+    all usable, this code should be compiled using an optimizing compiler
+    (for example gcc -O2) that can simplify expressions and control
+    paths.
+
+  __STD_C                  (default: derived from C compiler defines)
+     Nonzero if using ANSI-standard C compiler, a C++ compiler, or
+     a C compiler sufficiently close to ANSI to get away with it.
+  DEBUG                    (default: NOT defined)
+     Define to enable debugging. Adds fairly extensive assertion-based 
+     checking to help track down memory errors, but noticeably slows down
+     execution.
+  REALLOC_ZERO_BYTES_FREES (default: NOT defined) 
+     Define this if you think that realloc(p, 0) should be equivalent
+     to free(p). Otherwise, since malloc returns a unique pointer for
+     malloc(0), so does realloc(p, 0).
+  HAVE_MEMCPY               (default: defined)
+     Define if you are not otherwise using ANSI STD C, but still 
+     have memcpy and memset in your C library and want to use them.
+     Otherwise, simple internal versions are supplied.
+  USE_MEMCPY               (default: 1 if HAVE_MEMCPY is defined, 0 otherwise)
+     Define as 1 if you want the C library versions of memset and
+     memcpy called in realloc and calloc (otherwise macro versions are used). 
+     At least on some platforms, the simple macro versions usually
+     outperform libc versions.
+  HAVE_MMAP                 (default: defined as 1)
+     Define to non-zero to optionally make malloc() use mmap() to
+     allocate very large blocks.  
+  HAVE_MREMAP                 (default: defined as 0 unless Linux libc set)
+     Define to non-zero to optionally make realloc() use mremap() to
+     reallocate very large blocks.  
+  malloc_getpagesize        (default: derived from system #includes)
+     Either a constant or routine call returning the system page size.
+  HAVE_USR_INCLUDE_MALLOC_H (default: NOT defined) 
+     Optionally define if you are on a system with a /usr/include/malloc.h
+     that declares struct mallinfo. It is not at all necessary to
+     define this even if you do, but will ensure consistency.
+  INTERNAL_SIZE_T           (default: size_t)
+     Define to a 32-bit type (probably `unsigned int') if you are on a 
+     64-bit machine, yet do not want or need to allow malloc requests of 
+     greater than 2^31 to be handled. This saves space, especially for
+     very small chunks.
+  INTERNAL_LINUX_C_LIB      (default: NOT defined)
+     Defined only when compiled as part of Linux libc.
+     Also note that there is some odd internal name-mangling via defines
+     (for example, internally, `malloc' is named `mALLOc') needed
+     when compiling in this case. These look funny but don't otherwise
+     affect anything.
+  WIN32                     (default: undefined)
+     Define this on MS win (95, nt) platforms to compile in sbrk emulation.
+  LACKS_UNISTD_H            (default: undefined)
+     Define this if your system does not have a <unistd.h>.
+  MORECORE                  (default: sbrk)
+     The name of the routine to call to obtain more memory from the system.
+  MORECORE_FAILURE          (default: -1)
+     The value returned upon failure of MORECORE.
+  MORECORE_CLEARS           (default 1)
+     True (1) if the routine mapped to MORECORE zeroes out memory (which
+     holds for sbrk).
+  DEFAULT_TRIM_THRESHOLD
+  DEFAULT_TOP_PAD       
+  DEFAULT_MMAP_THRESHOLD
+  DEFAULT_MMAP_MAX      
+     Default values of tunable parameters (described in detail below)
+     controlling interaction with host system routines (sbrk, mmap, etc).
+     These values may also be changed dynamically via mallopt(). The
+     preset defaults are those that give best performance for typical
+     programs/systems.
+
+
+*/
+
+
+
+
+
+/* Preliminaries */
+
+#ifndef __STD_C
+#ifdef __STDC__
+#define __STD_C     1
+#else
+#if __cplusplus
+#define __STD_C     1
+#else
+#define __STD_C     0
+#endif /*__cplusplus*/
+#endif /*__STDC__*/
+#endif /*__STD_C*/
+
+#ifndef Void_t
+#if __STD_C
+#define Void_t      void
+#else
+#define Void_t      char
+#endif
+#endif /*Void_t*/
+
+#if __STD_C
+#include <stddef.h>   /* for size_t */
+#else
+#include <sys/types.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdio.h>    /* needed for malloc_stats */
+
+
+/*
+  Compile-time options
+*/
+
+
+/*
+    Debugging:
+
+    Because freed chunks may be overwritten with link fields, this
+    malloc will often die when freed memory is overwritten by user
+    programs.  This can be very effective (albeit in an annoying way)
+    in helping track down dangling pointers.
+
+    If you compile with -DDEBUG, a number of assertion checks are
+    enabled that will catch more memory errors. You probably won't be
+    able to make much sense of the actual assertion errors, but they
+    should help you locate incorrectly overwritten memory.  The
+    checking is fairly extensive, and will slow down execution
+    noticeably. Calling malloc_stats or mallinfo with DEBUG set will
+    attempt to check every non-mmapped allocated and free chunk in the
+    course of computing the summmaries. (By nature, mmapped regions
+    cannot be checked very much automatically.)
+
+    Setting DEBUG may also be helpful if you are trying to modify 
+    this code. The assertions in the check routines spell out in more 
+    detail the assumptions and invariants underlying the algorithms.
+
+*/
+
+#if DEBUG 
+#include <assert.h>
+#else
+#define assert(x) ((void)0)
+#endif
+
+
+/*
+  INTERNAL_SIZE_T is the word-size used for internal bookkeeping
+  of chunk sizes. On a 64-bit machine, you can reduce malloc
+  overhead by defining INTERNAL_SIZE_T to be a 32 bit `unsigned int'
+  at the expense of not being able to handle requests greater than
+  2^31. This limitation is hardly ever a concern; you are encouraged
+  to set this. However, the default version is the same as size_t.
+*/
+
+#ifndef INTERNAL_SIZE_T
+#define INTERNAL_SIZE_T size_t
+#endif
+
+/*
+  REALLOC_ZERO_BYTES_FREES should be set if a call to
+  realloc with zero bytes should be the same as a call to free.
+  Some people think it should. Otherwise, since this malloc
+  returns a unique pointer for malloc(0), so does realloc(p, 0). 
+*/
+
+
+/*   #define REALLOC_ZERO_BYTES_FREES */
+
+
+/* 
+  WIN32 causes an emulation of sbrk to be compiled in
+  mmap-based options are not currently supported in WIN32.
+*/
+
+/* #define WIN32 */
+#ifdef WIN32
+#define MORECORE wsbrk
+#define HAVE_MMAP 0
+#endif
+
+
+/*
+  HAVE_MEMCPY should be defined if you are not otherwise using
+  ANSI STD C, but still have memcpy and memset in your C library
+  and want to use them in calloc and realloc. Otherwise simple
+  macro versions are defined here.
+
+  USE_MEMCPY should be defined as 1 if you actually want to
+  have memset and memcpy called. People report that the macro
+  versions are often enough faster than libc versions on many
+  systems that it is better to use them. 
+
+*/
+
+#define HAVE_MEMCPY 
+
+#ifndef USE_MEMCPY
+#ifdef HAVE_MEMCPY
+#define USE_MEMCPY 1
+#else
+#define USE_MEMCPY 0
+#endif
+#endif
+
+#if (__STD_C || defined(HAVE_MEMCPY)) 
+
+#if __STD_C
+void* memset(void*, int, size_t);
+void* memcpy(void*, const void*, size_t);
+#else
+Void_t* memset();
+Void_t* memcpy();
+#endif
+#endif
+
+#if USE_MEMCPY
+
+/* The following macros are only invoked with (2n+1)-multiples of
+   INTERNAL_SIZE_T units, with a positive integer n. This is exploited
+   for fast inline execution when n is small. */
+
+#define MALLOC_ZERO(charp, nbytes)                                            \
+do {                                                                          \
+  INTERNAL_SIZE_T mzsz = (nbytes);                                            \
+  if(mzsz <= 9*sizeof(mzsz)) {                                                \
+    INTERNAL_SIZE_T* mz = (INTERNAL_SIZE_T*) (charp);                         \
+    if(mzsz >= 5*sizeof(mzsz)) {     *mz++ = 0;                               \
+                                     *mz++ = 0;                               \
+      if(mzsz >= 7*sizeof(mzsz)) {   *mz++ = 0;                               \
+                                     *mz++ = 0;                               \
+        if(mzsz >= 9*sizeof(mzsz)) { *mz++ = 0;                               \
+                                     *mz++ = 0; }}}                           \
+                                     *mz++ = 0;                               \
+                                     *mz++ = 0;                               \
+                                     *mz   = 0;                               \
+  } else memset((charp), 0, mzsz);                                            \
+} while(0)
+
+#define MALLOC_COPY(dest,src,nbytes)                                          \
+do {                                                                          \
+  INTERNAL_SIZE_T mcsz = (nbytes);                                            \
+  if(mcsz <= 9*sizeof(mcsz)) {                                                \
+    INTERNAL_SIZE_T* mcsrc = (INTERNAL_SIZE_T*) (src);                        \
+    INTERNAL_SIZE_T* mcdst = (INTERNAL_SIZE_T*) (dest);                       \
+    if(mcsz >= 5*sizeof(mcsz)) {     *mcdst++ = *mcsrc++;                     \
+                                     *mcdst++ = *mcsrc++;                     \
+      if(mcsz >= 7*sizeof(mcsz)) {   *mcdst++ = *mcsrc++;                     \
+                                     *mcdst++ = *mcsrc++;                     \
+        if(mcsz >= 9*sizeof(mcsz)) { *mcdst++ = *mcsrc++;                     \
+                                     *mcdst++ = *mcsrc++; }}}                 \
+                                     *mcdst++ = *mcsrc++;                     \
+                                     *mcdst++ = *mcsrc++;                     \
+                                     *mcdst   = *mcsrc  ;                     \
+  } else memcpy(dest, src, mcsz);                                             \
+} while(0)
+
+#else /* !USE_MEMCPY */
+
+/* Use Duff's device for good zeroing/copying performance. */
+
+#define MALLOC_ZERO(charp, nbytes)                                            \
+do {                                                                          \
+  INTERNAL_SIZE_T* mzp = (INTERNAL_SIZE_T*)(charp);                           \
+  long mctmp = (nbytes)/sizeof(INTERNAL_SIZE_T), mcn;                         \
+  if (mctmp < 8) mcn = 0; else { mcn = (mctmp-1)/8; mctmp %= 8; }             \
+  switch (mctmp) {                                                            \
+    case 0: for(;;) { *mzp++ = 0;                                             \
+    case 7:           *mzp++ = 0;                                             \
+    case 6:           *mzp++ = 0;                                             \
+    case 5:           *mzp++ = 0;                                             \
+    case 4:           *mzp++ = 0;                                             \
+    case 3:           *mzp++ = 0;                                             \
+    case 2:           *mzp++ = 0;                                             \
+    case 1:           *mzp++ = 0; if(mcn <= 0) break; mcn--; }                \
+  }                                                                           \
+} while(0)
+
+#define MALLOC_COPY(dest,src,nbytes)                                          \
+do {                                                                          \
+  INTERNAL_SIZE_T* mcsrc = (INTERNAL_SIZE_T*) src;                            \
+  INTERNAL_SIZE_T* mcdst = (INTERNAL_SIZE_T*) dest;                           \
+  long mctmp = (nbytes)/sizeof(INTERNAL_SIZE_T), mcn;                         \
+  if (mctmp < 8) mcn = 0; else { mcn = (mctmp-1)/8; mctmp %= 8; }             \
+  switch (mctmp) {                                                            \
+    case 0: for(;;) { *mcdst++ = *mcsrc++;                                    \
+    case 7:           *mcdst++ = *mcsrc++;                                    \
+    case 6:           *mcdst++ = *mcsrc++;                                    \
+    case 5:           *mcdst++ = *mcsrc++;                                    \
+    case 4:           *mcdst++ = *mcsrc++;                                    \
+    case 3:           *mcdst++ = *mcsrc++;                                    \
+    case 2:           *mcdst++ = *mcsrc++;                                    \
+    case 1:           *mcdst++ = *mcsrc++; if(mcn <= 0) break; mcn--; }       \
+  }                                                                           \
+} while(0)
+
+#endif
+
+
+/*
+  Define HAVE_MMAP to optionally make malloc() use mmap() to
+  allocate very large blocks.  These will be returned to the
+  operating system immediately after a free().
+*/
+
+#ifndef HAVE_MMAP
+#define HAVE_MMAP 1
+#endif
+
+/*
+  Define HAVE_MREMAP to make realloc() use mremap() to re-allocate
+  large blocks.  This is currently only possible on Linux with
+  kernel versions newer than 1.3.77.
+*/
+
+#ifndef HAVE_MREMAP
+#ifdef INTERNAL_LINUX_C_LIB
+#define HAVE_MREMAP 1
+#else
+#define HAVE_MREMAP 0
+#endif
+#endif
+
+#if HAVE_MMAP
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+
+#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
+#define MAP_ANONYMOUS MAP_ANON
+#endif
+
+#endif /* HAVE_MMAP */
+
+/*
+  Access to system page size. To the extent possible, this malloc
+  manages memory from the system in page-size units.
+  
+  The following mechanics for getpagesize were adapted from 
+  bsd/gnu getpagesize.h 
+*/
+
+#ifndef LACKS_UNISTD_H
+#  include <unistd.h>
+#endif
+
+#ifndef malloc_getpagesize
+#  ifdef _SC_PAGESIZE         /* some SVR4 systems omit an underscore */
+#    ifndef _SC_PAGE_SIZE
+#      define _SC_PAGE_SIZE _SC_PAGESIZE
+#    endif
+#  endif
+#  ifdef _SC_PAGE_SIZE
+#    define malloc_getpagesize sysconf(_SC_PAGE_SIZE)
+#  else
+#    if defined(BSD) || defined(DGUX) || defined(HAVE_GETPAGESIZE)
+       extern size_t getpagesize();
+#      define malloc_getpagesize getpagesize()
+#    else
+#      include <sys/param.h>
+#      ifdef EXEC_PAGESIZE
+#        define malloc_getpagesize EXEC_PAGESIZE
+#      else
+#        ifdef NBPG
+#          ifndef CLSIZE
+#            define malloc_getpagesize NBPG
+#          else
+#            define malloc_getpagesize (NBPG * CLSIZE)
+#          endif
+#        else 
+#          ifdef NBPC
+#            define malloc_getpagesize NBPC
+#          else
+#            ifdef PAGESIZE
+#              define malloc_getpagesize PAGESIZE
+#            else
+#              define malloc_getpagesize (4096) /* just guess */
+#            endif
+#          endif
+#        endif 
+#      endif
+#    endif 
+#  endif
+#endif
+
+
+
+/*
+
+  This version of malloc supports the standard SVID/XPG mallinfo
+  routine that returns a struct containing the same kind of
+  information you can get from malloc_stats. It should work on
+  any SVID/XPG compliant system that has a /usr/include/malloc.h
+  defining struct mallinfo. (If you'd like to install such a thing
+  yourself, cut out the preliminary declarations as described above
+  and below and save them in a malloc.h file. But there's no
+  compelling reason to bother to do this.)
+
+  The main declaration needed is the mallinfo struct that is returned
+  (by-copy) by mallinfo().  The SVID/XPG malloinfo struct contains a
+  bunch of fields, most of which are not even meaningful in this
+  version of malloc. Some of these fields are are instead filled by
+  mallinfo() with other numbers that might possibly be of interest.
+
+  HAVE_USR_INCLUDE_MALLOC_H should be set if you have a
+  /usr/include/malloc.h file that includes a declaration of struct
+  mallinfo.  If so, it is included; else an SVID2/XPG2 compliant
+  version is declared below.  These must be precisely the same for
+  mallinfo() to work.
+
+*/
+
+/* #define HAVE_USR_INCLUDE_MALLOC_H */
+
+#if HAVE_USR_INCLUDE_MALLOC_H
+#include "/usr/include/malloc.h"
+#else
+
+/* SVID2/XPG mallinfo structure */
+
+struct mallinfo {
+  int arena;    /* total space allocated from system */
+  int ordblks;  /* number of non-inuse chunks */
+  int smblks;   /* unused -- always zero */
+  int hblks;    /* number of mmapped regions */
+  int hblkhd;   /* total space in mmapped regions */
+  int usmblks;  /* unused -- always zero */
+  int fsmblks;  /* unused -- always zero */
+  int uordblks; /* total allocated space */
+  int fordblks; /* total non-inuse space */
+  int keepcost; /* top-most, releasable (via malloc_trim) space */
+};	
+
+/* SVID2/XPG mallopt options */
+
+#define M_MXFAST  1    /* UNUSED in this malloc */
+#define M_NLBLKS  2    /* UNUSED in this malloc */
+#define M_GRAIN   3    /* UNUSED in this malloc */
+#define M_KEEP    4    /* UNUSED in this malloc */
+
+#endif
+
+/* mallopt options that actually do something */
+
+#define M_TRIM_THRESHOLD    -1
+#define M_TOP_PAD           -2
+#define M_MMAP_THRESHOLD    -3
+#define M_MMAP_MAX          -4
+
+
+
+#ifndef DEFAULT_TRIM_THRESHOLD
+#define DEFAULT_TRIM_THRESHOLD (128 * 1024)
+#endif
+
+/*
+    M_TRIM_THRESHOLD is the maximum amount of unused top-most memory 
+      to keep before releasing via malloc_trim in free().
+
+      Automatic trimming is mainly useful in long-lived programs.
+      Because trimming via sbrk can be slow on some systems, and can
+      sometimes be wasteful (in cases where programs immediately
+      afterward allocate more large chunks) the value should be high
+      enough so that your overall system performance would improve by
+      releasing.  
+
+      The trim threshold and the mmap control parameters (see below)
+      can be traded off with one another. Trimming and mmapping are
+      two different ways of releasing unused memory back to the
+      system. Between these two, it is often possible to keep
+      system-level demands of a long-lived program down to a bare
+      minimum. For example, in one test suite of sessions measuring
+      the XF86 X server on Linux, using a trim threshold of 128K and a
+      mmap threshold of 192K led to near-minimal long term resource
+      consumption.  
+
+      If you are using this malloc in a long-lived program, it should
+      pay to experiment with these values.  As a rough guide, you
+      might set to a value close to the average size of a process
+      (program) running on your system.  Releasing this much memory
+      would allow such a process to run in memory.  Generally, it's
+      worth it to tune for trimming rather tham memory mapping when a
+      program undergoes phases where several large chunks are
+      allocated and released in ways that can reuse each other's
+      storage, perhaps mixed with phases where there are no such
+      chunks at all.  And in well-behaved long-lived programs,
+      controlling release of large blocks via trimming versus mapping
+      is usually faster.
+
+      However, in most programs, these parameters serve mainly as
+      protection against the system-level effects of carrying around
+      massive amounts of unneeded memory. Since frequent calls to
+      sbrk, mmap, and munmap otherwise degrade performance, the default
+      parameters are set to relatively high values that serve only as
+      safeguards.
+
+      The default trim value is high enough to cause trimming only in
+      fairly extreme (by current memory consumption standards) cases.
+      It must be greater than page size to have any useful effect.  To
+      disable trimming completely, you can set to (unsigned long)(-1);
+
+
+*/
+
+
+#ifndef DEFAULT_TOP_PAD
+#define DEFAULT_TOP_PAD        (0)
+#endif
+
+/*
+    M_TOP_PAD is the amount of extra `padding' space to allocate or 
+      retain whenever sbrk is called. It is used in two ways internally:
+
+      * When sbrk is called to extend the top of the arena to satisfy
+        a new malloc request, this much padding is added to the sbrk
+        request.
+
+      * When malloc_trim is called automatically from free(),
+        it is used as the `pad' argument.
+
+      In both cases, the actual amount of padding is rounded 
+      so that the end of the arena is always a system page boundary.
+
+      The main reason for using padding is to avoid calling sbrk so
+      often. Having even a small pad greatly reduces the likelihood
+      that nearly every malloc request during program start-up (or
+      after trimming) will invoke sbrk, which needlessly wastes
+      time. 
+
+      Automatic rounding-up to page-size units is normally sufficient
+      to avoid measurable overhead, so the default is 0.  However, in
+      systems where sbrk is relatively slow, it can pay to increase
+      this value, at the expense of carrying around more memory than 
+      the program needs.
+
+*/
+
+
+#ifndef DEFAULT_MMAP_THRESHOLD
+#define DEFAULT_MMAP_THRESHOLD (128 * 1024)
+#endif
+
+/*
+
+    M_MMAP_THRESHOLD is the request size threshold for using mmap() 
+      to service a request. Requests of at least this size that cannot 
+      be allocated using already-existing space will be serviced via mmap.  
+      (If enough normal freed space already exists it is used instead.)
+
+      Using mmap segregates relatively large chunks of memory so that
+      they can be individually obtained and released from the host
+      system. A request serviced through mmap is never reused by any
+      other request (at least not directly; the system may just so
+      happen to remap successive requests to the same locations).
+
+      Segregating space in this way has the benefit that mmapped space
+      can ALWAYS be individually released back to the system, which
+      helps keep the system level memory demands of a long-lived
+      program low. Mapped memory can never become `locked' between
+      other chunks, as can happen with normally allocated chunks, which
+      menas that even trimming via malloc_trim would not release them.
+
+      However, it has the disadvantages that:
+
+         1. The space cannot be reclaimed, consolidated, and then
+            used to service later requests, as happens with normal chunks. 
+         2. It can lead to more wastage because of mmap page alignment
+            requirements
+         3. It causes malloc performance to be more dependent on host
+            system memory management support routines which may vary in
+            implementation quality and may impose arbitrary
+            limitations. Generally, servicing a request via normal
+            malloc steps is faster than going through a system's mmap.
+
+      All together, these considerations should lead you to use mmap
+      only for relatively large requests.  
+
+
+*/
+
+
+
+#ifndef DEFAULT_MMAP_MAX
+#if HAVE_MMAP
+#define DEFAULT_MMAP_MAX       (64)
+#else
+#define DEFAULT_MMAP_MAX       (0)
+#endif
+#endif
+
+/*
+    M_MMAP_MAX is the maximum number of requests to simultaneously 
+      service using mmap. This parameter exists because:
+
+         1. Some systems have a limited number of internal tables for
+            use by mmap.
+         2. In most systems, overreliance on mmap can degrade overall
+            performance.
+         3. If a program allocates many large regions, it is probably
+            better off using normal sbrk-based allocation routines that
+            can reclaim and reallocate normal heap memory. Using a
+            small value allows transition into this mode after the
+            first few allocations.
+
+      Setting to 0 disables all use of mmap.  If HAVE_MMAP is not set,
+      the default value is 0, and attempts to set it to non-zero values
+      in mallopt will fail.
+*/
+
+
+
+
+/* 
+
+  Special defines for linux libc
+
+  Except when compiled using these special defines for Linux libc
+  using weak aliases, this malloc is NOT designed to work in
+  multithreaded applications.  No semaphores or other concurrency
+  control are provided to ensure that multiple malloc or free calls
+  don't run at the same time, which could be disasterous. A single
+  semaphore could be used across malloc, realloc, and free (which is
+  essentially the effect of the linux weak alias approach). It would
+  be hard to obtain finer granularity.
+
+*/
+
+
+#ifdef INTERNAL_LINUX_C_LIB
+
+#if __STD_C
+
+Void_t * __default_morecore_init (ptrdiff_t);
+Void_t *(*__morecore)(ptrdiff_t) = __default_morecore_init;
+
+#else
+
+Void_t * __default_morecore_init ();
+Void_t *(*__morecore)() = __default_morecore_init;
+
+#endif
+
+#define MORECORE (*__morecore)
+#define MORECORE_FAILURE 0
+#define MORECORE_CLEARS 1 
+
+#else /* INTERNAL_LINUX_C_LIB */
+
+#if __STD_C
+extern Void_t*     sbrk(ptrdiff_t);
+#else
+extern Void_t*     sbrk();
+#endif
+
+#ifndef MORECORE
+#define MORECORE sbrk
+#endif
+
+#ifndef MORECORE_FAILURE
+#define MORECORE_FAILURE -1
+#endif
+
+#ifndef MORECORE_CLEARS
+#define MORECORE_CLEARS 1
+#endif
+
+#endif /* INTERNAL_LINUX_C_LIB */
+
+#if defined(INTERNAL_LINUX_C_LIB) && defined(__ELF__)
+
+#define cALLOc		__libc_calloc
+#define fREe		__libc_free
+#define mALLOc		__libc_malloc
+#define mEMALIGn	__libc_memalign
+#define rEALLOc		__libc_realloc
+#define vALLOc		__libc_valloc
+#define pvALLOc		__libc_pvalloc
+#define mALLINFo	__libc_mallinfo
+#define mALLOPt		__libc_mallopt
+
+#pragma weak calloc = __libc_calloc
+#pragma weak free = __libc_free
+#pragma weak cfree = __libc_free
+#pragma weak malloc = __libc_malloc
+#pragma weak memalign = __libc_memalign
+#pragma weak realloc = __libc_realloc
+#pragma weak valloc = __libc_valloc
+#pragma weak pvalloc = __libc_pvalloc
+#pragma weak mallinfo = __libc_mallinfo
+#pragma weak mallopt = __libc_mallopt
+
+#else
+
+#if OM_PROVIDE_MALLOC < 0
+#define cALLOc		calloc
+#define fREe		free
+#define mALLOc		malloc
+#define rEALLOc		realloc
+#define mEMALIGn	memalign
+#define vALLOc		valloc
+#define pvALLOc		pvalloc
+#define mALLINFo	mallinfo
+#define mALLOPt		mallopt
+#endif
+
+#endif
+
+/* Public routines */
+
+#if __STD_C
+
+Void_t* mALLOc(size_t);
+void    fREe(Void_t*);
+Void_t* rEALLOc(Void_t*, size_t);
+Void_t* mEMALIGn(size_t, size_t);
+Void_t* vALLOc(size_t);
+Void_t* pvALLOc(size_t);
+Void_t* cALLOc(size_t, size_t);
+void    cfree(Void_t*);
+int     malloc_trim(size_t);
+size_t  malloc_usable_size(Void_t*);
+void    malloc_stats();
+int     mALLOPt(int, int);
+struct mallinfo mALLINFo(void);
+#else
+Void_t* mALLOc();
+void    fREe();
+Void_t* rEALLOc();
+Void_t* mEMALIGn();
+Void_t* vALLOc();
+Void_t* pvALLOc();
+Void_t* cALLOc();
+void    cfree();
+int     malloc_trim();
+size_t  malloc_usable_size();
+void    malloc_stats();
+int     mALLOPt();
+struct mallinfo mALLINFo();
+#endif
+
+
+#ifdef __cplusplus
+};  /* end of extern "C" */
+#endif
+
+/* ---------- To make a malloc.h, end cutting here ------------ */
+
+#endif /* DL_MALLOC_H */
Index: omalloc/install-sh
===================================================================
--- omalloc/install-sh	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
+++ omalloc/install-sh	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
@@ -0,0 +1,246 @@
+#!/bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.
+#
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+tranformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+    case $1 in
+	-c) instcmd="$cpprog"
+	    shift
+	    continue;;
+
+	-d) dir_arg=true
+	    shift
+	    continue;;
+
+	-m) chmodcmd="$chmodprog $2"
+	    shift
+	    shift
+	    continue;;
+
+	-o) chowncmd="$chownprog $2"
+	    shift
+	    shift
+	    continue;;
+
+	-g) chgrpcmd="$chgrpprog $2"
+	    shift
+	    shift
+	    continue;;
+
+	-s) stripcmd="$stripprog"
+	    shift
+	    continue;;
+
+	-t=*) transformarg=`echo $1 | sed 's/-t=//'`
+	    shift
+	    continue;;
+
+	-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+	    shift
+	    continue;;
+
+	*)  if [ x"$src" = x ]
+	    then
+		src=$1
+	    else
+		# this colon is to work around a 386BSD /bin/sh bug
+		:
+		dst=$1
+	    fi
+	    shift
+	    continue;;
+    esac
+done
+
+if [ x"$src" = x ]
+then
+	echo "install:	no input file specified"
+	exit 1
+else
+	true
+fi
+
+if [ x"$dir_arg" != x ]; then
+	dst=$src
+	src=""
+	
+	if [ -d $dst ]; then
+		instcmd=:
+	else
+		instcmd=mkdir
+	fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad 
+# if $src (and thus $dsttmp) contains '*'.
+
+# obachman 6/15/98
+# Here is an ugly fix for a bug in cygwin
+# '[ test -f $src ]' evaluates to true, even if only $src.exe exists
+# However 'cp $src $dst' can  not find $src, if only $src.exe exists
+	if test -f "$src.exe" && test -x "$src.exe"; then
+		src="$src.exe"
+		true
+	elif [ -f $src -o -d $src ]
+	then
+		true
+	else
+		echo "install:  $src does not exist"
+		exit 1
+	fi
+	
+	if [ x"$dst" = x ]
+	then
+		echo "install:	no destination specified"
+		exit 1
+	else
+		true
+	fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+	if [ -d $dst ]
+	then
+		dst="$dst"/`basename $src`
+	else
+		true
+	fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+#  this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='	
+'
+IFS="${IFS-${defaultIFS}}"
+
+oIFS="${IFS}"
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS="${oIFS}"
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+	pathcomp="${pathcomp}${1}"
+	shift
+
+	if [ ! -d "${pathcomp}" ] ;
+        then
+		$mkdirprog "${pathcomp}"
+	else
+		true
+	fi
+
+	pathcomp="${pathcomp}/"
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+	$doit $instcmd $dst &&
+
+	if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
+	if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
+	if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
+	if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+	if [ x"$transformarg" = x ] 
+	then
+		dstfile=`basename $dst`
+	else
+		echo "basename $dst $transformbasename | sed $transformarg$transformbasename"
+		dstfile=`basename $dst $transformbasename | 
+			sed $transformarg`$transformbasename
+	fi
+
+# don't allow the sed command to completely eliminate the filename
+
+	if [ x"$dstfile" = x ] 
+	then
+		dstfile=`basename $dst`
+	else
+		true
+	fi
+
+# Make a temp file name in the proper directory.
+
+	dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+	$doit $instcmd $src $dsttmp &&
+
+	trap "rm -f ${dsttmp}" 0 &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing.  If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+	if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
+	if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
+	if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
+	if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
+
+# Now rename the file to the real destination.
+
+	$doit $rmcmd -f $dstdir/$dstfile &&
+	$doit $mvcmd $dsttmp $dstdir/$dstfile 
+
+fi &&
+
+
+exit 0
Index: omalloc/mkinstalldirs
===================================================================
--- omalloc/mkinstalldirs	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
+++ omalloc/mkinstalldirs	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
@@ -0,0 +1,32 @@
+#!/bin/sh
+# mkinstalldirs --- make directory hierarchy
+# Author: Noah Friedman <friedman@prep.ai.mit.edu>
+# Created: 1993-05-16
+# Last modified: 1994-03-25
+# Public domain
+
+errstatus=0
+
+for file in ${1+"$@"} ; do 
+   set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
+   shift
+
+   pathcomp=
+   for d in ${1+"$@"} ; do
+     pathcomp="$pathcomp$d"
+     case "$pathcomp" in
+       -* ) pathcomp=./$pathcomp ;;
+     esac
+
+     if test ! -d "$pathcomp"; then
+        echo "mkdir $pathcomp" 1>&2
+        mkdir "$pathcomp" || errstatus=$?
+     fi
+
+     pathcomp="$pathcomp/"
+   done
+done
+
+exit $errstatus
+
+# mkinstalldirs ends here
Index: omalloc/omAllocDecl.h
===================================================================
--- omalloc/omAllocDecl.h	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
+++ omalloc/omAllocDecl.h	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
@@ -0,0 +1,347 @@
+/*******************************************************************
+ *  File:    omAllocDecl.h
+ *  Purpose: declaration of Alloc routines
+ *  Author:  obachman (Olaf Bachmann)
+ *  Created: 11/99
+ *  Version: $Id: omAllocDecl.h,v 1.1 2000-08-14 12:18:25 obachman Exp $
+ *******************************************************************/
+#ifndef OM_ALLOC_DECL_H
+#define OM_ALLOC_DECL_H
+
+
+#ifndef OMALLOC_C
+#define calloc      omcalloc
+#define malloc      omalloc
+#define free        omfree
+#define realloc     omrealloc
+#define freeSize    omfreeSize
+#define reallocSize omreallocSize
+#endif
+
+#if !defined(OM_EMULATE_OMALLOC) && !defined(OM_NDEBUG) && (defined(OM_CHECK) || (defined(OM_HAVE_TRACK) && defined(OM_TRACK)))
+
+/*******************************************************************
+ *
+ * Alloc/Free/Check for Debug
+ *
+ *******************************************************************/
+#ifndef OM_CHECK
+#define OM_CHECK    0
+#endif
+#ifndef OM_TRACK 
+#define OM_TRACK    0
+#endif
+
+#define omTypeAllocBin(type,addr,bin)           addr=(type)_omDebugAlloc(bin,OM_FBIN,OM_CTFL)
+#define omTypeAlloc0Bin(type,addr,bin)          addr=(type)_omDebugAlloc(bin,OM_FBIN|OM_FZERO,OM_CTFL)
+#define omAllocBin(bin)                         _omDebugAlloc(bin,OM_FBIN,OM_CTFL)
+#define omAlloc0Bin(bin)                        _omDebugAlloc(bin,OM_FBIN|OM_FZERO,OM_CTFL)
+
+#define omTypeAlloc(type,addr,size)             addr=(type)_omDebugAlloc((void*)(size),OM_FSIZE,OM_CTFL)
+#define omTypeAlloc0(type,addr,size)            addr=(type)_omDebugAlloc((void*)(size),OM_FSIZE|OM_FZERO,OM_CTFL)
+#define omAlloc(size)                           _omDebugAlloc((void*)(size),OM_FSIZE,OM_CTFL)
+#define omAlloc0(size)                          _omDebugAlloc((void*)(size),OM_FSIZE|OM_FZERO,OM_CTFL)
+
+#define omTypeReallocBin(o_addr,o_bin,type,addr,bin)            addr=(type)_omDebugRealloc(o_addr,o_bin,bin,OM_FBIN,OM_FBIN,OM_CTFL)
+#define omTypeRealloc0Bin(o_addr,o_bin,type,addr,bin)           addr=(type)_omDebugRealloc(o_addr,o_bin,bin,OM_FBIN,OM_FBIN|OM_FZERO,OM_CTFL)
+#define omReallocBin(o_addr,o_bin,bin)                          _omDebugRealloc(o_addr,o_bin,bin,OM_FBIN,OM_FBIN,OM_CTFL)
+#define omRealloc0Bin(o_addr,o_bin,bin)                         _omDebugRealloc(o_addr,o_bin,bin,OM_FBIN,OM_FBIN|OM_FZERO,OM_CTFL)
+
+#define omTypeReallocSize(o_addr,o_size,type,addr,size)         addr=(type)_omDebugRealloc(o_addr,(void*)(o_size),(void*)(size),OM_FSIZE,OM_FSIZE,OM_CTFL)
+#define omTypeRealloc0Size(o_addr,o_size,type,addr,size)        addr=(type)_omDebugRealloc(o_addr,(void*)(o_size),(void*)(size),OM_FSIZE,OM_FSIZE|OM_FZERO,OM_CTFL)
+#define omReallocSize(addr,o_size,size)                         _omDebugRealloc(addr,(void*)(o_size),(void*)(size),OM_FSIZE,OM_FSIZE,OM_CTFL)
+#define omRealloc0Size(addr,o_size,size)                        _omDebugRealloc(addr,(void*)(o_size),(void*)(size),OM_FSIZE,OM_FSIZE|OM_FZERO,OM_CTFL)
+
+#define omTypeRealloc(o_addr,type,addr,size)                    addr=(type)_omDebugRealloc(o_addr,NULL,(void*)(size),0,OM_FSIZE,OM_CTFL)
+#define omTypeRealloc0(o_addr,type,addr,size)                   addr=(type)_omDebugRealloc(o_addr,NULL,(void*)(size),0,OM_FSIZE|OM_FZERO,OM_CTFL)
+#define omRealloc(addr,size)                                    _omDebugRealloc(addr,NULL,(void*)(size),0,OM_FSIZE,OM_CTFL)
+#define omRealloc0(addr,size)                                   _omDebugRealloc(addr,NULL,(void*)(size),0,OM_FSIZE|OM_FZERO,OM_CTFL)
+
+#define omFreeBin(addr,bin)     _omDebugFree(addr,bin,OM_FBIN,OM_CFL)
+#define omFreeSize(addr,size)   _omDebugFree(addr,(void*)(size),OM_FSIZE,OM_CFL)
+#define omFree(addr)            _omDebugFree(addr,0,0,OM_CFL)
+
+
+#define omalloc(size)   _omDebugAlloc((void*)(size),OM_FSIZE|OM_FSLOPPY|OM_FALIGN,OM_CTFL)
+#define omalloc0(size)  _omDebugAlloc((void*)(size),OM_FSIZE|OM_FZERO|OM_FSLOPPY|OM_FALIGN,OM_CTFL)
+#define omcalloc(n,size)_omDebugAlloc((void*) ((size)*n),OM_FSIZE|OM_FZERO|OM_FSLOPPY|OM_FALIGN,OM_CTFL)
+
+#define omreallocSize(addr,o_size,size) _omDebugRealloc(addr,(void*)(o_size),(void*)(size),OM_FSIZE|OM_FSLOPPY,OM_FSIZE|OM_FSLOPPY|OM_FALIGN,OM_CTFL)
+#define omrealloc0Size(addr,o_size,size)_omDebugRealloc(addr,(void*)(o_size),(void*)(size),OM_FSIZE|OM_FSLOPPY,OM_FSIZE|OM_FZERO|OM_FSLOPPY|OM_FALIGN,OM_CTFL)
+#define omrealloc(addr,size)            _omDebugRealloc(addr,NULL,(void*)(size),OM_FSLOPPY,OM_FSIZE|OM_FSLOPPY|OM_FALIGN,OM_CTFL)
+#define omrealloc0(addr,size)           _omDebugRealloc(addr,NULL,(void*)(size),OM_FSLOPPY,OM_FSIZE|OM_FZERO|OM_FSLOPPY|OM_FALIGN,OM_CTFL)
+
+#define omfreeSize(addr,size)   _omDebugFree(addr,(void*)(size),OM_FSIZE|OM_FSLOPPY,OM_CFL)
+#define omfree(addr)            _omDebugFree(addr,NULL,OM_FSLOPPY,OM_CFL)
+
+#define omStrDup(s)                             _omDebugStrDup(s,OM_TFL)
+#define omMemDup(addr)                          _omDebugMemDup(addr,0,OM_CTFL)
+
+
+#define omDebugAddrBin(addr, bin)            _omDebugAddr(addr,bin,OM_FBIN,OM_CFL)
+#define omDebugAddrSize(addr,size)           _omDebugAddr(addr,(void*)(size),OM_FSIZE,OM_CFL)
+#define omDebugAddr(addr)                    _omDebugAddr(addr,NULL, 0, OM_CFL)
+#define omdebugAddrSize(addr,size)           _omDebugAddr(addr,(void*)(size),OM_FSIZE|OM_FSLOPPY,OM_CFL)
+#define omdebugAddr(addr)                    _omDebugAddr(addr,NULL, OM_FSLOPPY, OM_CFL)
+#define omDebugBin(bin)                      _omDebugBin(bin,OM_CFL)
+#define omDebugMemory()                      _omDebugMemory(OM_CFL)
+#define omDebugIf(cond, statement)           do { if (cond) {statement;}} while (0)
+
+#if OM_CHECK > 0
+#define omCheckAddrBin      omDebugAddrBin   
+#define omCheckAddrSize     omDebugAddrSize  
+#define omCheckAddr         omDebugAddr      
+#define omcheckAddrSize     omdebugAddrSize  
+#define omcheckAddr         omdebugAddr      
+#define omCheckBin          omDebugBin       
+#define omCheckMemory       omDebugMemory    
+#define omCheckIf           omDebugIf        
+#endif /* OM_CHECK > 0 */
+
+
+#ifdef OM_ALIGNMENT_NEEDS_WORK
+
+#define omTypeAllocAligned(type,addr,size)             addr=(type)_omDebugAlloc((void*)(size),OM_FSIZE|OM_FALIGN,OM_CTFL)
+#define omTypeAlloc0Aligned(type,addr,size)            addr=(type)_omDebugAlloc((void*)(size),OM_FSIZE|OM_FZERO|OM_FALIGN,OM_CTFL)
+#define omAllocAligned(size)                           _omDebugAlloc((void*)(size),OM_FSIZE|OM_FALIGN,OM_CTFL)
+#define omAlloc0Aligned(size)                          _omDebugAlloc((void*)(size),OM_FSIZE|OM_FZERO|OM_FALIGN,OM_CTFL)
+
+#define omTypeReallocAlignedSize(o_addr,o_size,type,addr,size)         addr=(type)_omDebugRealloc(o_addr,(void*)(o_size),(void*)(size),OM_FSIZE,OM_FSIZE|OM_FALIGN,OM_CTFL)
+#define omTypeRealloc0AlignedSize(o_addr,o_size,type,addr,size)        addr=(type)_omDebugRealloc(o_addr,(void*)(o_size),(void*)(size),OM_FSIZE,OM_FSIZE|OM_FZERO|OM_FALIGN,OM_CTFL)
+#define omReallocAlignedSize(addr,o_size,size)                         _omDebugRealloc(addr,(void*)(o_size),(void*)(size),OM_FSIZE,OM_FSIZE|OM_FALIGN,OM_CTFL)
+#define omRealloc0AlignedSize(addr,o_size,size)                        _omDebugRealloc(addr,(void*)(o_size),(void*)(size),OM_FSIZE,OM_FSIZE|OM_FZERO|OM_FALIGN,OM_CTFL)
+
+#define omTypeReallocAligned(o_addr,type,addr,size)                    addr=(type)_omDebugRealloc(o_addr,NULL,(void*)(size),0,OM_FSIZE|OM_FALIGN,OM_CTFL)
+#define omTypeRealloc0Aligned(o_addr,type,addr,size)                   addr=(type)_omDebugRealloc(o_addr,NULL,(void*)(size),0,OM_FSIZE|OM_FZERO|OM_FALIGN,OM_CTFL)
+#define omReallocAligned(addr,size)                                    _omDebugRealloc(addr,NULL,(void*)(size),0,OM_FSIZE|OM_FALIGN,OM_CTFL)
+#define omRealloc0Aligned(addr,size)                                   _omDebugRealloc(addr,NULL,(void*)(size),0,OM_FSIZE|OM_FZERO|OM_FALIGN,OM_CTFL)
+
+#define omMemDupAligned(addr)                       _omDebugMemDup(addr,OM_FALIGN,OM_CTFL)
+
+#define omDebugAddrAlignedBin(addr, bin)            _omDebugAddr(addr,bin,OM_FBIN|OM_FALIGN,OM_CFL)
+#define omDebugAddrAlignedSize(addr,size)           _omDebugAddr(addr,(void*)(size),OM_FSIZE|OM_FALIGN,OM_CFL)
+#define omDebugAddrAligned(addr)                    _omDebugAddr(addr,NULL, OM_FALIGN, OM_CFL)
+#define omdebugAddrAlignedSize(addr,size)           _omDebugAddr(addr,(void*)(size),OM_FSIZE|OM_FSLOPPY|OM_FALIGN,OM_CFL)
+#define omdebugAddrAligned(addr)                    _omDebugAddr(addr,NULL, OM_FSLOPPY|OM_FALIGN, OM_CFL)
+
+#if OM_CHECK > 0
+#define omCheckAddrAlignedBin    omDebugAddrAlignedBin    
+#define omCheckAddrAlignedSize   omDebugAddrAlignedSize  
+#define omCheckAddrAligned       omDebugAddrAligned      
+#define omcheckAddrAlignedSize   omdebugAddrAlignedSize  
+#define omcheckAddrAligned       omdebugAddrAligned      
+#endif
+#endif /* OM_ALIGNMENT_NEEDS_WORK */
+
+#elif !defined(OM_EMULATE_OMALLOC) 
+/*******************************************************************
+ *
+ * Alloc/Free -- the real thing
+ *
+ *******************************************************************/
+#define omTypeAllocBin(type,addr,bin)           __omTypeAllocBin(type,addr,bin)
+#define omTypeAlloc0Bin(type,addr,bin)          __omTypeAlloc0Bin(type,addr,bin)
+#define omAllocBin(bin)                         _omAllocBin(bin)
+#define omAlloc0Bin(bin)                        _omAlloc0Bin(bin)
+
+#define omTypeAlloc(type,addr,size)             __omTypeAlloc(type,addr,size)
+#define omTypeAlloc0(type,addr,size)            __omTypeAlloc0(type,addr,size)
+#define omAlloc(size)                           _omAlloc(size)
+#define omAlloc0(size)                          _omAlloc0(size)
+
+#define omTypeReallocBin(o_addr,o_bin,type,addr,bin)            __omTypeReallocBin(o_addr,o_bin,type,addr,bin)
+#define omTypeRealloc0Bin(o_addr,o_bin,type,addr,bin)           __omTypeRealloc0Bin(o_addr,o_bin,type,addr,bin)
+#define omReallocBin(o_addr,o_bin,bin)                          _omReallocBin(o_addr,o_bin,bin)
+#define omRealloc0Bin(o_addr,o_bin,bin)                         _omRealloc0Bin(o_addr,o_bin,bin)
+
+#define omTypeReallocSize(o_addr,o_size,type,addr,size)         __omTypeReallocSize(o_addr,o_size,type,addr,size)
+#define omTypeRealloc0Size(o_addr,o_size,type,addr,size)        __omTypeRealloc0Size(o_addr,o_size,type,addr,size)
+#define omReallocSize(addr,o_size,size)                         _omReallocSize(addr,o_size,size)
+#define omRealloc0Size(addr,o_size,size)                        _omRealloc0Size(addr,o_size,size)
+
+#define omTypeRealloc(o_addr,type,addr,size)                    __omTypeRealloc(o_addr,type,addr,size)
+#define omTypeRealloc0(o_addr,type,addr,size)                   __omTypeRealloc0(o_addr,type,addr,size)
+#define omRealloc(addr,size)                                    _omRealloc(addr,size)
+#define omRealloc0(addr,size)                                   _omRealloc0(addr,size)
+
+#define omalloc(size)   _omalloc(size)
+#define omalloc0(size)  _omalloc0(size)
+#define omcalloc(n,size)_omalloc0(n*size)
+
+#define omreallocSize(addr,o_size,size) _omreallocSize(addr,o_size,size)
+#define omrealloc0Size(addr,o_size,size)_omrealloc0Size(addr,o_size,size)
+#define omrealloc(addr,size)            _omrealloc(addr, size)
+#define omrealloc0(addr,size)           _omrealloc0(addr, size)
+
+#define omfreeSize(addr,size)   do {if (addr && size) omFreeSize(addr, size);} while (0)
+#define omfree(addr)            do {if (addr) omFree(addr);} while (0)
+
+#ifdef OM_ALIGNMENT_NEEDS_WORK
+#define omTypeAllocAligned(type,addr,size)      __omTypeAllocAligned(type,addr,size)
+#define omTypeAlloc0Aligned(type,addr,size)     __omTypeAlloc0Aligned(type,addr,size)
+#define omAllocAligned(size)                    _omAllocAligned(size)
+#define omAlloc0Aligned(size)                   _omAlloc0Aligned(size)
+
+#define omTypeReallocAlignedSize(o_addr,o_size,type,addr,size)  __omTypeReallocAlignedSize(o_addr,o_size,type,addr,size)
+#define omTypeRealloc0AlignedSize(o_addr,o_size,type,addr,size) __omTypeRealloc0AlignedSize(o_addr,o_size,type,addr,size)
+#define omReallocAlignedSize(addr,o_size,size)                  _omReallocAlignedSize(addr,o_size,size)
+#define omRealloc0AlignedSize(addr,o_size,size)                 _omRealloc0AlignedSize(addr,o_size,size)
+
+#define omTypeReallocAligned(o_addr,type,addr,size)             __omTypeReallocAligned(o_addr,type,addr,size)
+#define omTypeRealloc0Aligned(o_addr,type,addr,size)            __omTypeRealloc0Aligned(o_addr,type,addr,size)
+#define omReallocAligned(addr,size)                             _omReallocAligned(addr,size)
+#define omRealloc0Aligned(addr,size)                            _omRealloc0Aligned(addr,size)
+
+#define omMemDupAligned(addr)                                   _omMemDupAligned(addr)
+#endif  /* OM_ALIGNMENT_NEEDS_WORK */
+
+#define omFreeBin(addr,bin)     __omFreeBin(addr,bin)
+#define omFreeSize(addr,size)   __omFreeSize(addr,size)
+#define omFree(addr)            __omFree(addr)
+
+#define omStrDup(s)         _omStrDup(s)
+#define omMemDup(s)         _omMemDup(s)
+
+
+
+#else /* OM_EMULATE_OMALLOC */
+/*******************************************************************
+ *
+ * Emulation of omalloc's Alloc/Free interface
+ *
+ *******************************************************************/
+
+#include "omMalloc.h"
+
+extern void* omEmulateCalloc(size_t size);
+extern void* omEmulateRealloc0Size(void* o_addr, size_t o_size, size_t n_size);
+extern void* omEmulateRealloc0(void* o_addr, size_t n_size);
+
+#define omTypeAllocBin(type,addr,bin)           addr=(type) OM_MALLOC_MALLOC(bin->sizeW << LOG_SIZEOF_LONG)
+#define omTypeAlloc0Bin(type,addr,bin)          addr=(type) omEmulateAlloc0(bin->sizeW << LOG_SIZEOF_LONG)
+#define omAllocBin(bin)                         OM_MALLOC_MALLOC(bin->sizeW << LOG_SIZEOF_LONG)
+#define omAlloc0Bin(bin)                        omEmulateAlloc0(bin->sizeW << LOG_SIZEOF_LONG)
+
+#define omTypeAlloc(type,addr,size)             addr=(type) OM_MALLOC_MALLOC(size) 
+#define omTypeAlloc0(type,addr,size)            addr=(type) omEmulateAlloc0(size) 
+#define omAlloc(size)                           OM_MALLOC_MALLOC(size)             
+#define omAlloc0(size)                          omEmulateAlloc0(size)             
+
+#define omTypeReallocBin(o_addr,o_bin,type,addr,bin)            addr=(type)OM_MALLOC_REALLOC(o_addr,bin->sizeW << LOG_SIZEOF_LONG)                    
+#define omTypeRealloc0Bin(o_addr,o_bin,type,addr,bin)           addr=(type)omEmulateRealloc0Size(o_addr,o_bin->sizeW << LOG_SIZEOF_LONG,bin->sizeW << LOG_SIZEOF_LONG) 
+#define omReallocBin(o_addr,o_bin,bin)                          OM_MALLOC_REALLOC(o_addr,bin->sizeW << LOG_SIZEOF_LONG)                               
+#define omRealloc0Bin(o_addr,o_bin,bin)                         omEmulateRealloc0Size(o_addr,o_bin->sizeW << LOG_SIZEOF_LONG,bin->sizeW << LOG_SIZEOF_LONG)            
+                                                                
+#define omTypeReallocSize(o_addr,o_size,type,addr,size)         addr=(type)OM_MALLOC_REALLOC(o_addr,size)                    
+#define omTypeRealloc0Size(o_addr,o_size,type,addr,size)        addr=(type)omEmulateRealloc0Size(o_addr,o_size,size) 
+#define omReallocSize(addr,o_size,size)                         OM_MALLOC_REALLOC(addr,size)                               
+#define omRealloc0Size(addr,o_size,size)                        omEmulateRealloc0Size(addr,o_size,size)            
+                                                                
+#define omTypeRealloc(o_addr,type,addr,size)                    addr=(type)OM_MALLOC_REALLOC(o_addr,size)            
+#define omTypeRealloc0(o_addr,type,addr,size)                   addr=(type)omEmulateRealloc0(o_addr,size) 
+#define omRealloc(addr,size)                                    OM_MALLOC_REALLOC(addr,size)                       
+#define omRealloc0(addr,size)                                   omEmulateRealloc0(addr,size)            
+                                                                
+#define omFreeBin(addr,bin)     OM_MALLOC_FREE(addr)
+#define omFreeSize(addr,size)   OM_MALLOC_FREE(addr)      
+#define omFree(addr)            OM_MALLOC_FREE(addr)            
+#endif /* ! debug && ! the real thing */
+
+
+/* define alignment stuff, if necessary */
+#if !defined(omTypeAllocAligned) 
+#define omTypeAllocAligned      omTypeAlloc
+#define omTypeAlloc0Aligned     omTypeAlloc0
+#define omAllocAligned          omAlloc
+#define omAlloc0Aligned         omAlloc0
+
+#define omTypeReallocAlignedSize     omTypeReallocSize  
+#define omTypeRealloc0AlignedSize    omTypeRealloc0Size 
+#define omReallocAlignedSize         omReallocSize      
+#define omRealloc0AlignedSize        omRealloc0Size     
+                                                        
+#define omTypeReallocAligned         omTypeRealloc      
+#define omTypeRealloc0Aligned        omTypeRealloc0     
+#define omReallocAligned             omRealloc          
+#define omRealloc0Aligned            omRealloc0
+
+#define omMemDupAligned     omMemDup
+#endif /* !defined(omTypeAllocAligned) */
+
+#if !defined(omDebugAddrAlignedBin)
+#define omDebugAddrAlignedBin   omDebugAddrBin           
+#define omDebugAddrAlignedSize  omDebugAddrSize          
+#define omDebugAddrAligned      omDebugAddr                   
+#define omdebugAddrAlignedSize  omdebugAddrSize          
+#define omdebugAddrAligned      omdebugAddr 
+#endif /* !defined(omDebugAddrAlignedBin) */
+
+#if !defined(omCheckAddrAlignedBin)
+#define omCheckAddrAlignedBin   omDebugAddrBin           
+#define omCheckAddrAlignedSize  omDebugAddrSize          
+#define omCheckAddrAligned      omDebugAddr                   
+#define omcheckAddrAlignedSize  omdebugAddrSize          
+#define omcheckAddrAligned      omdebugAddr 
+#endif /* !defined(omCheckAddrAlignedBin) */
+ 
+/* define debug stuff, if necessary */
+#if !defined(omDebugAddrBin)
+#define omDebugIf(cond, test)                    ((void) 0)
+#define omDebugAddrBin(addr,bin)                 ((void) 0)
+#define omDebugAddrSize(addr,size)               ((void) 0)                       
+#define omDebugAddr(addr)                        ((void) 0)                               
+#define omdebugAddrSize(addr,size)               ((void) 0)                       
+#define omdebugAddr(addr)                        ((void) 0)                               
+#define omDebugBin(bin)                          ((void) 0)                               
+#define omDebugMemory()                          ((void) 0) 
+#endif /* !defined(omDebugAddrBin) */
+
+/* define check stuff, if necessary */
+#if !defined(omCheckAddrBin)
+#define omCheckIf(cond, test)                    ((void) 0)
+#define omCheckAddrBin(addr,bin)                 ((void) 0)
+#define omCheckAddrSize(addr,size)               ((void) 0)                       
+#define omCheckAddr(addr)                        ((void) 0)                               
+#define omcheckAddrSize(addr,size)               ((void) 0)                       
+#define omcheckAddr(addr)                        ((void) 0)                               
+#define omCheckBin(bin)                          ((void) 0)                               
+#define omCheckMemory()                          ((void) 0)                               
+#endif /* !defined(omCheckAddrBin) */
+
+
+
+#if !defined(OM_NDEBUG) && !defined(OM_EMULATE_MALLOC)
+omError_t omTestAddrBin(void* addr, omBin bin, int check_level);
+omError_t omTestAddrSize(void* addr, size_t size, int check_level);
+omError_t omTestAddr(void* addr, int check_level);
+omError_t omtestAddrSize(void* addr, size_t size, int check_level);
+omError_t omtestAddr(void* addr, int check_level);
+omError_t omTestAddrAlignedBin(void* addr, omBin bin, int check_level);
+omError_t omTestAddrAlignedSize(void* addr, size_t size, int check_level);
+omError_t omTestAddrAligned(void* addr, int check_level);
+omError_t omtestAddrAlignedSize(void* addr, size_t size, int check_level);
+omError_t omtestAddrAligned(void* addr, int check_level);
+omError_t omTestBin(omBin bin, int check_level);
+omError_t omTestMemory(int check_level);
+#define omTestIf(cond, statement)           do { if (cond) {statement;}} while (0)
+
+#else
+
+#define omTestIf(cond, test)                      ((void) 0)
+#define omTestAddrBin(addr,bin,l)                 ((void) 0)
+#define omTestAddrSize(addr,size,l)               ((void) 0)                       
+#define omTestAddr(addr,l)                        ((void) 0)                               
+#define omtestAddrSize(addr,size,l)               ((void) 0)                       
+#define omtestAddr(addr,l)                        ((void) 0)                               
+#define omTestAddrAlignedBin(addr,bin,l)                 ((void) 0)
+#define omTestAddrAlignedSize(addr,size,l)               ((void) 0)                       
+#define omTestAddrAligned(addr,l)                        ((void) 0) 
+#define omtestAddrAlignedSize(addr,size,l)               ((void) 0)  
+#define omtestAddrAligned(addr,l)                        ((void) 0)
+#define omTestBin(bin,l)                          ((void) 0)                               
+#define omTestMemory(l)                           ((void) 0)                               
+
+#endif
+
+#endif /* OM_ALLOC_DECL_H */
+
Index: omalloc/omAllocEmulate.c
===================================================================
--- omalloc/omAllocEmulate.c	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
+++ omalloc/omAllocEmulate.c	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
@@ -0,0 +1,69 @@
+/*******************************************************************
+ *  File:    omAllocEmulate.c
+ *  Purpose: implementation of emulated omalloc routines
+ *  Author:  obachman (Olaf Bachmann)
+ *  Created: 11/99
+ *  Version: $Id: omAllocEmulate.c,v 1.1 2000-08-14 12:18:26 obachman Exp $
+ *******************************************************************/
+#include <stdlib.h>
+
+#include "omMalloc.h"
+
+void* omEmulateAlloc0(size_t size)
+{
+  void* addr = OM_MALLOC_MALLOC(size);
+  memset(addr, 0, size);
+  return addr;
+}
+
+void* omEmulateRealloc0Size(void* o_addr, size_t o_size, size_t n_size)
+{
+  void* addr = OM_MALLOC_REALLOC(o_addr, n_size);
+  
+  if (n_size > o_size)
+    memset(addr + o_size, 0, n_size - o_size);
+
+  return addr;
+}
+
+void* omEmulateRealloc0(void* o_addr, size_t n_size)
+{
+#ifdef OM_MALLOC_SIZEOF_ADDR
+  size_t o_size = OM_MALLOC_SIZEOF_ADDR(o_addr);
+#endif  
+  void* addr = OM_MALLOC_REALLOC(o_addr, n_size);
+#ifdef OM_MALLOC_SIZEOF_ADDR  
+  if (n_size > o_size)
+    memset(addr + o_size, 0, n_size - o_size);
+#endif
+  return addr;
+}
+
+#if defined(OM_EMULATE_OMALLOC) && defined(OM_PROVIDE_MALLOC)
+
+#undef calloc
+#undef malloc
+#undef realloc
+#undef free
+
+void* calloc(size_t n, size_t s)
+{
+  return omEmulateAlloc0(n*s);
+}
+
+void* malloc(size_t size)
+{
+  return OM_MALLOC_MALLOC(size);
+}
+
+void* realloc(void* o_addr, size_t n_size);
+{
+  return OM_MALLOC_REALLOC(size);
+}
+
+void free(void* addr)
+{
+  OM_MALLOC_FREE(addr);
+}
+
+#endif /* defined(OM_EMULATE_OMALLOC) && defined(OM_PROVIDE_MALLOC) */
Index: omalloc/omAllocPrivate.h
===================================================================
--- omalloc/omAllocPrivate.h	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
+++ omalloc/omAllocPrivate.h	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
@@ -0,0 +1,371 @@
+/*******************************************************************
+ *  File:    omAllocPrivate.h
+ *  Purpose: declaration of "private" (but visible to the outside) 
+ *           routines for omalloc
+ *  Author:  obachman (Olaf Bachmann)
+ *  Created: 11/99
+ *  Version: $Id: omAllocPrivate.h,v 1.1 2000-08-14 12:18:26 obachman Exp $
+ *******************************************************************/
+#ifndef OM_ALLOC_PRIVATE_H
+#define OM_ALLOC_PRIVATE_H
+
+/*******************************************************************
+ *  
+ *  Definitions of structures we work with
+ *  
+ *******************************************************************/
+/* Need to define it here, has to be known to macros */
+struct omBinPage_s
+{
+  long          used_blocks;    /* number of used blocks of this page */
+  void*         current;        /* pointer to current freelist */
+  omBinPage     next;           /* next/prev pointer of pages */
+  omBinPage     prev;
+  void*         bin_sticky;     /* bin this page belongs to with 
+                                   sticky tag of page hidden in ptr */
+  omBinPageRegion region;       /* BinPageRegion of this page */
+};
+
+/* Change this appropriately, if you change omBinPage                 */
+/* However, make sure that omBinPage is a multiple of SIZEOF_MAX_TYPE */
+#define SIZEOF_OM_BIN_PAGE_HEADER (5*SIZEOF_VOIDP + SIZEOF_LONG) 
+#define SIZEOF_OM_BIN_PAGE (SIZEOF_SYSTEM_PAGE - SIZEOF_OM_BIN_PAGE_HEADER)
+
+/* keep all members of omBin_s a sizeof(long) type, 
+   otherwise list operations will fail */
+struct omBin_s
+{
+  omBinPage     current_page;   /* page of current freelist */
+  omBinPage     last_page;      /* pointer to last page of freelist */
+  omBin         next;           /* sticky bins of the same size */
+  size_t        sizeW;          /* size in words */
+  long          max_blocks;     /* if > 0   # blocks in one page, 
+                                   if < 0   # pages for one block */
+  unsigned long sticky;         /* sticky tag */
+};
+
+struct omSpecBin_s
+{
+  omSpecBin        next;       /* pointer to next bin */
+  omBin            bin;        /* pointer to bin itself */
+  long             max_blocks; /* max_blocks of bin*/
+  long             ref;        /* ref count */
+};
+
+extern  omSpecBin om_SpecBin;
+extern  omBinPage_t om_ZeroPage[];
+extern  omBin       om_Size2Bin[];
+
+/*******************************************************************
+ *  
+ *  Working with pages/bins
+ *  
+ *******************************************************************/
+#define omGetTopBinOfPage(page) \
+  ((omBin) ( ((unsigned long) ((page)->bin_sticky)) & ~(SIZEOF_VOIDP - 1)))
+#define omGetStickyOfPage(page) \
+  (((unsigned long) ((page)->bin_sticky)) & (SIZEOF_VOIDP-1))
+#define omSetTopBinOfPage(page, bin) \
+  (page)->bin_sticky= (void*)((unsigned long)bin + omGetStickyOfPage(page))
+#define omSetStickyOfPage(page, sticky) \
+  (page)->bin_sticky = (void*)((unsigned long)sticky + \
+                                (unsigned long)omGetTopBinOfPage(page))
+#define omSetTopBinAndStickyOfPage(page, bin, sticky) \
+  (page)->bin_sticky= (void*)((unsigned long)sticky + (unsigned long)bin)
+
+#define omGetTopBinOfAddr(addr) \
+  omGetTopBinOfPage(((omBinPage) omGetPageOfAddr(addr)))
+#define omGetBinOfAddr(addr) omGetBinOfPage(omGetBinPageOfAddr(addr))
+
+#ifndef OM_GENERATE_INC
+extern omBin_t om_StaticBin[];
+extern omBin om_Size2Bin[];
+#ifdef OM_ALIGNMENT_NEEDS_WORK
+extern omBin om_Size2AlignedBin[];
+#endif
+
+/*******************************************************************
+ *  
+ *  SizeOfAddr
+ *  
+ *******************************************************************/
+#ifdef OM_INTERNAL_DEBUG
+size_t omSizeOfBinAddr(void* addr);
+#else
+#define omSizeOfBinAddr(addr) _omSizeOfBinAddr(addr)
+#endif
+
+#define _omSizeOfBinAddr(addr)  ((omSizeWOfBinAddr(addr)) << LOG_SIZEOF_LONG)
+#define omSizeWOfBinAddr(addr) ((omGetTopBinOfAddr(addr))->sizeW)
+
+/*******************************************************************
+ *  
+ *  lowest level alloc/free macros
+ *  
+ *******************************************************************/
+extern void* omAllocBinFromFullPage(omBin bin);
+extern void  omFreeToPageFault(omBinPage page, void* addr);
+
+/*******************************************************************/
+/* Page                                                            */
+#define __omTypeAllocFromNonEmptyPage(type, addr, page) \
+do                                                      \
+{                                                       \
+  ((page)->used_blocks)++;                              \
+  addr = (type)((page)->current);                       \
+  (page)->current =  *((void**) (page)->current);       \
+}                                                       \
+while (0)
+
+#define __omFreeToPage(addr, page)              \
+do                                              \
+{                                               \
+  if ((page)->used_blocks > 0)                  \
+  {                                             \
+    *((void**) (addr)) = (page)->current;       \
+    ((page)->used_blocks)--;                    \
+    (page)->current = (addr);                   \
+  }                                             \
+  else                                          \
+  {                                             \
+    omFreeToPageFault(page, addr);              \
+  }                                             \
+}                                               \
+while (0)
+
+
+/*******************************************************************/
+/* Bin                                                             */
+#define __omTypeAllocBin(type, addr, bin)                   \
+do                                                          \
+{                                                           \
+  register omBinPage __om_page = (bin)->current_page;       \
+  if (__om_page->current != NULL)                           \
+    __omTypeAllocFromNonEmptyPage(type, addr, __om_page);   \
+  else                                                      \
+    addr = (type) omAllocBinFromFullPage(bin);              \
+}                                                           \
+while (0)
+
+#define __omTypeAlloc0Bin(type, addr, bin)      \
+do                                              \
+{                                               \
+  __omTypeAllocBin(type, addr, bin);            \
+  omMemsetW(addr, 0, (bin)->sizeW);             \
+}                                               \
+while (0)
+
+#define __omFreeBin(addr, bin) ___omFreeBin(addr)
+
+#define ___omFreeBin(addr)                                      \
+do                                                              \
+{                                                               \
+  register void* __om_addr = (void*) (addr);                    \
+  register omBinPage __om_page = omGetBinPageOfAddr(__om_addr); \
+  __omFreeToPage(__om_addr, __om_page);                         \
+}                                                               \
+while (0)
+
+#define __omTypeReallocBin(old_addr, old_bin, new_type, new_addr, new_bin)                              \
+do                                                                                                      \
+{                                                                                                       \
+  if (old_bin != new_bin)                                                                               \
+  {                                                                                                     \
+    size_t old_sizeW = (omIsNormalBinPageAddr(old_addr) ? old_bin->sizeW : omSizeWOfAddr(old_addr));    \
+    __omTypeAllocBin(new_type, new_addr, new_bin);                                                      \
+    omMemcpyW(new_addr, old_addr, (new_bin->sizeW > old_sizeW ? old_sizeW : new_bin->sizeW));           \
+    __omFreeBin(old_addr, old_bin);                                                                     \
+  }                                                                                                     \
+  else                                                                                                  \
+  {                                                                                                     \
+    new_addr = (new_type) old_addr;                                                                     \
+  }                                                                                                     \
+}                                                                                                       \
+while (0)
+
+
+#define __omTypeRealloc0Bin(old_addr, old_bin, new_type, new_addr, new_bin)                             \
+do                                                                                                      \
+{                                                                                                       \
+  if (old_bin != new_bin)                                                                               \
+  {                                                                                                     \
+    size_t old_sizeW = (omIsNormalBinPageAddr(old_addr) ? old_bin->sizeW : omSizeWOfAddr(old_addr));    \
+    __omTypeAllocBin(new_type, new_addr, new_bin);                                                      \
+    omMemcpyW(new_addr, old_addr, (new_bin->sizeW > old_sizeW ? old_sizeW : new_bin->sizeW));           \
+    if (new_bin->sizeW > old_sizeW)                                                                     \
+       omMemsetW((void**)new_addr + old_sizeW, 0, new_bin->sizeW - old_sizeW);                          \
+    __omFreeBin(old_addr, old_bin);                                                                     \
+  }                                                                                                     \
+  else                                                                                                  \
+  {                                                                                                     \
+    new_addr = (new_type) old_addr;                                                                     \
+  }                                                                                                     \
+}                                                                                                       \
+while (0)
+
+/*******************************************************************/
+/* Size                                                            */
+#define omSmallSize2Bin(size) om_Size2Bin[((size) -1)>>LOG_SIZEOF_OM_ALIGNMENT]
+
+#define __omTypeAlloc(type, addr, size)         \
+do                                              \
+{                                               \
+  size_t __size = size;                         \
+  if (__size <= OM_MAX_BLOCK_SIZE)              \
+  {                                             \
+    omBin __om_bin = omSmallSize2Bin(__size);   \
+    __omTypeAllocBin(type, addr, __om_bin);     \
+  }                                             \
+  else                                          \
+  {                                             \
+    addr = (type) omAllocLarge(__size);         \
+  }                                             \
+}                                               \
+while(0)
+
+#define __omTypeAlloc0(type, addr, size)        \
+do                                              \
+{                                               \
+  size_t __size = size;                         \
+  if (__size <= OM_MAX_BLOCK_SIZE)              \
+  {                                             \
+    omBin __om_bin = omSmallSize2Bin(__size);   \
+    __omTypeAlloc0Bin(type, addr, __om_bin);    \
+  }                                             \
+  else                                          \
+  {                                             \
+    addr = (type) omAlloc0Large(__size);        \
+  }                                             \
+}                                               \
+while (0)
+
+#ifdef OM_ALIGNMENT_NEEDS_WORK
+#define omSmallSize2AlignedBin(size) om_Size2AlignedBin[((size) -1)>>LOG_SIZEOF_OM_ALIGNMENT]
+
+#define __omTypeAllocAligned(type, addr, size)          \
+do                                                      \
+{                                                       \
+  size_t __size = size;                                 \
+  if (__size <= OM_MAX_BLOCK_SIZE)                      \
+  {                                                     \
+    omBin __om_bin = omSmallSize2AlignedBin(__size);    \
+    __omTypeAllocBin(type, addr, __om_bin);             \
+  }                                                     \
+  else                                                  \
+  {                                                     \
+    addr = (type) omAllocLarge(__size);                 \
+  }                                                     \
+}                                                       \
+while(0)
+
+#define __omTypeAlloc0Aligned(type, addr, size)         \
+do                                                      \
+{                                                       \
+  size_t __size = size;                                 \
+  if (__size <= OM_MAX_BLOCK_SIZE)                      \
+  {                                                     \
+    omBin __om_bin = omSmallSize2AlignedBin(__size);    \
+    __omTypeAlloc0Bin(type, addr, __om_bin);            \
+  }                                                     \
+  else                                                  \
+  {                                                     \
+    addr = (type) omAlloc0Large(__size);                \
+  }                                                     \
+}                                                       \
+while (0)
+#else
+#define __omTypeAllocAligned    __omTypeAlloc
+#define __omTypeAlloc0Aligned   __omTypeAlloc0
+#endif /* OM_ALIGNMENT_NEEDS_WORK */
+      
+#define __omFreeSize(addr, size)                            \
+do                                                          \
+{                                                           \
+  if (size <= OM_MAX_BLOCK_SIZE || omIsBinPageAddr(addr))   \
+  {                                                         \
+    ___omFreeBin(addr);                                     \
+  }                                                         \
+  else                                                      \
+  {                                                         \
+    omFreeLarge(addr);                                      \
+  }                                                         \
+}                                                           \
+while (0)
+
+#define __omFree(addr)                          \
+do                                              \
+{                                               \
+  if (omIsBinPageAddr(addr))                    \
+  {                                             \
+    ___omFreeBin(addr);                         \
+  }                                             \
+  else                                          \
+  {                                             \
+    omFreeLarge(addr);                          \
+  }                                             \
+}                                               \
+while (0)
+
+void* omDoRealloc(void* old_addr, size_t new_size, int flags);
+
+#define ___omTypeRealloc(old_addr, new_type, new_addr, new_size, SIZE_2_BIN, REALLOC_BIN, flags)    \
+do                                                                                                  \
+{                                                                                                   \
+  size_t __new_size = new_size;                                                                     \
+  if (__new_size <= OM_MAX_BLOCK_SIZE && omIsBinPageAddr(old_addr))                                 \
+  {                                                                                                 \
+    omBin __old_bin = omGetBinOfAddr(old_addr);                                                     \
+    omBin __new_bin = SIZE_2_BIN(__new_size);                                                       \
+    REALLOC_BIN(old_addr, __old_bin, new_type, new_addr, __new_bin);                                \
+  }                                                                                                 \
+  else                                                                                              \
+  {                                                                                                 \
+    new_addr = (new_type) omDoRealloc(old_addr, __new_size, flags);                                 \
+  }                                                                                                 \
+}                                                                                                   \
+while (0)
+
+#define ___omTypeReallocSize(old_addr, old_size, new_type, new_addr, new_size, SIZE_2_BIN, REALLOC_BIN, flags)  \
+do                                                                                                              \
+{                                                                                                               \
+  size_t __new_size = new_size;                                                                                 \
+  if (__new_size <= OM_MAX_BLOCK_SIZE && old_size <= OM_MAX_BLOCK_SIZE)                                         \
+  {                                                                                                             \
+    omBin __old_bin = omGetBinOfAddr(old_addr);                                                                 \
+    omBin __new_bin = SIZE_2_BIN(__new_size);                                                                   \
+    REALLOC_BIN(old_addr, __old_bin, new_type, new_addr, __new_bin);                                            \
+  }                                                                                                             \
+  else                                                                                                          \
+  {                                                                                                             \
+    new_addr = (new_type) omDoRealloc(old_addr, __new_size, flags);                                             \
+  }                                                                                                             \
+}                                                                                                               \
+while (0)
+
+#define __omTypeRealloc(old_addr, new_type, new_addr, new_size)                 \
+  ___omTypeRealloc(old_addr, new_type, new_addr, new_size, omSmallSize2Bin, __omTypeReallocBin, 0)
+#define __omTypeRealloc0(old_addr, new_type, new_addr, new_size)                \
+  ___omTypeRealloc(old_addr, new_type, new_addr, new_size, omSmallSize2Bin, __omTypeRealloc0Bin, 1)
+#define __omTypeReallocSize(old_addr, old_size, new_type, new_addr, new_size)     \
+  ___omTypeReallocSize(old_addr, old_size, new_type, new_addr, new_size, omSmallSize2Bin, __omTypeReallocBin, 0)
+#define __omTypeRealloc0Size(old_addr, old_size, new_type, new_addr, new_size)    \
+  ___omTypeReallocSize(old_addr, old_size, new_type, new_addr, new_size, omSmallSize2Bin, __omTypeRealloc0Bin, 1)
+
+#ifdef OM_ALIGNMENT_NEEDS_WORK
+#define __omTypeReallocAligned(old_addr, new_type, new_addr, new_size)                 \
+  ___omTypeRealloc(old_addr, new_type, new_addr, new_size, omSmallSize2AlignedBin, __omTypeReallocBin, 2)
+#define __omTypeRealloc0Aligned(old_addr, new_type, new_addr, new_size)                \
+  ___omTypeRealloc(old_addr, new_type, new_addr, new_size, omSmallSize2AlignedBin, __omTypeRealloc0Bin, 3)
+#define __omTypeReallocAlignedSize(old_addr, old_size, new_type, new_addr, new_size)     \
+  ___omTypeReallocSize(old_addr, old_size, new_type, new_addr, new_size, omSmallSize2AlignedBin, __omTypeReallocBin, 2)
+#define __omTypeRealloc0AlignedSize(old_addr, old_size, new_type, new_addr, new_size)    \
+  ___omTypeReallocSize(old_addr, old_size, new_type, new_addr, new_size, omSmallSize2AlignedBin, __omTypeRealloc0Bin, 3)
+#else
+#define __omTypeReallocAligned      __omTypeRealloc
+#define __omTypeRealloc0Aligned     __omTypeRealloc0
+#define __omTypeReallocAlignedSize      __omTypeReallocSize
+#define __omTypeRealloc0AlignedSize     __omTypeRealloc0Size
+#endif
+
+#endif /* OM_GENERATE_INC */
+#endif /* OM_ALLOC_PRIVATE_H */
Index: omalloc/omAllocSystem.c
===================================================================
--- omalloc/omAllocSystem.c	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
+++ omalloc/omAllocSystem.c	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
@@ -0,0 +1,351 @@
+/*******************************************************************
+ *  File:    omAllocSystem.c
+ *  Purpose: implementation of main lowl-level alloc functions
+ *  Author:  obachman@mathematik.uni-kl.de (Olaf Bachmann)
+ *  Created: 11/99
+ *  Version: $Id: omAllocSystem.c,v 1.1 2000-08-14 12:18:26 obachman Exp $
+ *******************************************************************/
+#ifndef OM_ALLOC_SYSTEM_C
+#define OM_ALLOC_SYSTEM_C
+
+#include <unistd.h>
+#include <limits.h>
+#include "omAlloc.h"
+#include "omDefaultConfig.h"
+#include "omMalloc.h"
+
+#define OM_MALLOC_FROM_SYSTEM   OM_MALLOC_MALLOC
+#define OM_REALLOC_FROM_SYSTEM  OM_MALLOC_REALLOC
+#define OM_FREE_TO_SYSTEM       OM_MALLOC_FREE
+
+/*******************************************************************
+ *  
+ *  AllocLarge/FreeLarge if malloc can not return sizeof(addr)
+ *  
+ *******************************************************************/
+/* allocation of large addr */
+#if defined(OM_MALLOC_PROVIDES_SIZEOF_ADDR) 
+#define _omSizeOfLargeAddr(addr) (OM_MALLOC_SIZEOF_ADDR(addr) & (~SIZEOF_OM_ALIGNMENT_1))
+#else
+void* omAllocLarge(size_t size)
+{
+  void* addr;
+  size = OM_ALIGN_SIZE(size);
+  addr = omAllocFromSystem(size + SIZEOF_STRICT_ALIGNMENT);
+  *((size_t*) addr) = size;
+  return addr + SIZEOF_STRICT_ALIGNMENT;
+}
+
+void* omReallocLarge(void* old_addr, size_t new_size)
+{
+  void* _old_addr;
+  void* new_addr;
+  
+  omAssume(omIsLargeAddr(old_addr));
+  
+  new_size = OM_ALIGN_SIZE(new_size);
+  _old_addr = old_addr - SIZEOF_STRICT_ALIGNMENT;
+  new_addr = omReallocSizeFromSystem(_old_addr, 
+                                     *((size_t*) _old_addr) + SIZEOF_STRICT_ALIGNMENT, 
+                                     new_size + SIZEOF_STRICT_ALIGNMENT);
+  *((size_t*) new_addr) = new_size;
+  return new_addr + SIZEOF_STRICT_ALIGNMENT;
+}
+
+void omFreeLarge(void* addr)
+{
+  void* _addr = addr - SIZEOF_STRICT_ALIGNMENT;
+  omFreeSizeToSystem(_addr, *((size_t*) _addr) + SIZEOF_STRICT_ALIGNMENT);
+}
+
+#define _omSizeOfLargeAddr(addr)  (*((size_t*) ((void*) addr - SIZEOF_STRICT_ALIGNMENT)))
+#endif /* OM_MALLOC_PROVIDES_SIZEOF_ADDR */
+
+void* omAlloc0Large(size_t size)
+{
+  void* addr = omAllocLarge(size);
+  size = omSizeOfLargeAddr(addr);
+  memset(addr, 0, size);
+  return addr;
+}
+
+void* omRealloc0Large(void* old_addr, size_t new_size)
+{
+  size_t old_size;
+  void* new_addr;
+  
+  omAssume(!omIsBinPageAddr(old_addr));
+
+  old_size = omSizeOfLargeAddr(old_addr);
+  
+  new_addr = omReallocLarge(old_addr, new_size);
+  new_size = omSizeOfLargeAddr(new_addr);
+  if (new_size > old_size)
+    memset(new_addr + old_size, 0, new_size - old_size);
+  return new_addr;
+}
+  
+size_t omSizeOfLargeAddr(void* addr)
+{
+  return _omSizeOfLargeAddr(addr);
+}
+
+size_t omSizeOfAddr(void* addr)
+{
+  
+  return (omIsBinPageAddr(addr) ?
+#ifdef OM_HAVE_TRACK
+          (omIsBinAddrTrackAddr(addr) ? omOutSizeOfTrackAddr(addr) : omSizeOfBinAddr(addr)) :
+#else
+          omSizeOfBinAddr(addr) : 
+#endif
+          omSizeOfLargeAddr(addr));
+}
+
+size_t omSizeWOfAddr(void* addr)
+{
+  
+  return (omIsBinPageAddr(addr) ?
+#ifdef OM_HAVE_TRACK
+          (omIsBinAddrTrackAddr(addr) ? omOutSizeOfTrackAddr(addr) >> LOG_SIZEOF_LONG : omSizeWOfBinAddr(addr)) :
+#else
+          omSizeWOfBinAddr(addr) : 
+#endif
+          omSizeOfLargeAddr(addr) >> LOG_SIZEOF_LONG);
+}
+
+/*******************************************************************
+ *  
+ *  Valloc
+ *  
+ *******************************************************************/
+#ifdef OM_HAVE_VALLOC_MMAP
+
+#include "omMmap.c"
+#define OM_VALLOC_FROM_SYSTEM   omVallocMmap
+#define OM_VFREE_TO_SYSTEM      omVfreeMmap
+
+#elif defined(OM_HAVE_VALLOC_MALLOC)
+
+#define OM_VALLOC_FROM_SYSTEM OM_MALLOC_VALLOC
+#define OM_VFREE_TO_SYSTEM    OM_MALLOC_VFREE
+
+#else 
+
+#define OM_VALLOC_FROM_SYSTEM   omEmulateValloc
+#define OM_VFREE_TO_SYSTEM      omEmulateVfree
+
+#define OM_ALIGN_PAGE(addr) ( ((long)addr + (SIZEOF_SYSTEM_PAGE -1)) & ~(SIZEOF_SYSTEM_PAGE - 1))
+/* now we implement an emulation */
+void* omEmulateValloc(size_t size) 
+{
+  void* addr;
+  size_t padding = SIZEOF_VOIDP;
+  size = OM_ALIGN_SIZE(size);
+  while (1)
+  {
+    addr = OM_MALLOC_FROM_SYSTEM(size + padding);
+    if (addr == NULL) return NULL;
+    if ((OM_ALIGN_PAGE(addr) + SIZEOF_VOIDP) - (long) addr <= padding)
+    {
+      void* ret_addr = (void*) OM_ALIGN_PAGE(addr);
+      *((void**) ((void*) ret_addr + size)) = addr;
+      return ret_addr;
+    }
+    else
+    {
+      OM_FREE_TO_SYSTEM(addr);
+      padding = padding << 1;
+    }
+  }
+}
+
+void omEmulateVfree(void* addr, size_t size)
+{
+  size = OM_ALIGN_SIZE(size);
+  OM_FREE_TO_SYSTEM( *((void**) ((void*) addr + size)) );
+}
+#endif /* OM_HAVE_VALLOC_MMAP */
+
+/*******************************************************************
+ *  
+ *  System-level Alloc/Free
+ *  
+ *******************************************************************/
+void* omAllocFromSystem(size_t size)
+{
+  void* ptr;
+
+  ptr = OM_MALLOC_FROM_SYSTEM(size);
+  if (ptr == NULL)
+  {
+    OM_MEMORY_LOW_HOOK();
+    ptr = OM_MALLOC_FROM_SYSTEM(size);
+    if (ptr == NULL)
+    {
+      OM_OUT_OF_MEMORY_HOOK();
+      exit(1);
+    }
+  }
+
+#ifndef OM_NDEBUG
+  if (((unsigned long) ptr) + size > om_MaxAddr)
+    om_MaxAddr = ((unsigned long) ptr) + size;
+  if (((unsigned long) ptr) < om_MinAddr)
+    om_MinAddr = ((unsigned long) ptr);
+#endif  
+
+  om_Info.CurrentBytesFromMalloc += size;
+  if (om_Info.CurrentBytesFromMalloc > om_Info.MaxBytesFromMalloc)
+  {
+    om_Info.MaxBytesFromMalloc = om_Info.CurrentBytesFromMalloc;
+#if defined(OM_HAVE_VALLOC_MMAP) && defined(OM_MALLOC_MAX_BYTES_SYSTEM)
+    if (om_Info.CurrentBytesFromValloc + OM_MALLOC_MAX_BYTES_SYSTEM > om_Info.MaxBytesSystem)
+      om_Info.MaxBytesSystem = om_Info.CurrentBytesFromValloc + OM_MALLOC_MAX_BYTES_SYSTEM;
+#endif 
+#if defined(HAVE_SBRK) && !defined(OM_MALLOC_MAX_BYTES_SBRK)
+    if (! om_SbrkInit) om_SbrkInit = (unsigned long) sbrk(0) - size;
+    if (om_Info.MaxBytesFromMalloc 
+#ifndef OM_HAVE_VALLOC_MMAP
+        + om_Info.CurrentBytesFromValloc 
+#endif
+        > om_Info.MaxBytesSbrk)
+    {
+      om_Info.MaxBytesSbrk = (unsigned long) sbrk(0) - om_SbrkInit;
+    }
+#endif
+  }
+  OM_MALLOC_HOOK(size);
+  return ptr;
+}
+
+void* omReallocFromSystem(void* addr, size_t newsize)
+{
+  return omReallocSizeFromSystem(addr, omSizeOfAddr(addr), newsize);
+}
+
+void* omReallocSizeFromSystem(void* addr, size_t oldsize, size_t newsize)
+{
+  void* res;
+
+  res = OM_REALLOC_FROM_SYSTEM(addr, newsize);
+  if (res == NULL)
+  {
+    OM_MEMORY_LOW_HOOK();
+    /* Can do a realloc again: manpage reads:
+       "If realloc() fails the original block is left untouched - 
+       it is not freed or moved." */
+    res = OM_REALLOC_FROM_SYSTEM(addr, newsize); 
+    if (res == NULL)
+    {
+      OM_OUT_OF_MEMORY_HOOK();
+      /* should never get here */
+      omAssume(0);
+      exit(1);
+    }
+  }
+
+#ifndef OM_NDEBUG
+  if (((unsigned long) res) + newsize > om_MaxAddr)
+    om_MaxAddr = ((unsigned long) res) + newsize;
+  if (((unsigned long) res) < om_MinAddr)
+    om_MinAddr = ((unsigned long) res);
+#endif  
+
+  om_Info.CurrentBytesFromMalloc += (long) newsize - (long) oldsize;
+    
+
+  if (om_Info.CurrentBytesFromMalloc > om_Info.MaxBytesFromMalloc)
+  {
+    om_Info.MaxBytesFromMalloc = om_Info.CurrentBytesFromMalloc;
+#if defined(OM_HAVE_VALLOC_MMAP) && defined(OM_MALLOC_MAX_BYTES_SYSTEM)
+    if (om_Info.CurrentBytesFromValloc + OM_MALLOC_MAX_BYTES_SYSTEM > om_Info.MaxBytesSystem)
+      om_Info.MaxBytesSystem = om_Info.CurrentBytesFromValloc + OM_MALLOC_MAX_BYTES_SYSTEM;
+#endif 
+#if defined(HAVE_SBRK) && !defined(OM_MALLOC_MAX_BYTES_SBRK)
+    if (om_Info.MaxBytesFromMalloc 
+#ifndef OM_HAVE_VALLOC_MMAP
+        + om_Info.CurrentBytesFromValloc 
+#endif
+        > om_Info.MaxBytesSbrk)
+    {
+      om_Info.MaxBytesSbrk = (unsigned long) sbrk(0) - om_SbrkInit;
+    }
+#endif
+  }
+
+  OM_REALLOC_HOOK(oldsize, newsize);
+  return res;
+}
+
+void omFreeToSystem(void* addr)
+{
+  omFreeSizeToSystem(addr, omSizeOfAddr(addr));
+}
+ 
+void omFreeSizeToSystem(void* addr, size_t size)
+{
+  OM_FREE_TO_SYSTEM( addr );
+  om_Info.CurrentBytesFromMalloc -= size;
+  OM_FREE_HOOK(size);
+}
+
+void* _omVallocFromSystem(size_t size, int fail)
+{
+  void* page = OM_VALLOC_FROM_SYSTEM(size);
+  if (page == NULL)
+  {
+    OM_MEMORY_LOW_HOOK();
+    page = OM_VALLOC_FROM_SYSTEM(size);
+    if (page == NULL)
+    {
+      if (fail) return NULL;
+      else
+      {
+        OM_OUT_OF_MEMORY_HOOK();
+        /* should never get here */
+        omAssume(0);
+        exit(1);
+      }
+    }
+  }
+
+#ifndef OM_NDEBUG
+  if (((unsigned long) page) + size > om_MaxAddr)
+    om_MaxAddr = ((unsigned long) page) + size;
+  if (((unsigned long) page) < om_MinAddr)
+    om_MinAddr = ((unsigned long) page);
+#endif  
+
+  omAssume(omIsAddrPageAligned(page));
+  om_Info.CurrentBytesFromValloc += size;
+  if (om_Info.CurrentBytesFromValloc > om_Info.MaxBytesFromValloc)
+  {
+    om_Info.MaxBytesFromValloc = om_Info.CurrentBytesFromValloc;
+#if defined(OM_HAVE_VALLOC_MMAP) && defined(OM_MALLOC_MAX_BYTES_SYSTEM)
+    if (om_Info.MaxBytesFromValloc + OM_MALLOC_MAX_BYTES_SYSTEM > om_Info.MaxBytesSystem)
+      om_Info.MaxBytesSystem = om_Info.MaxBytesFromValloc + OM_MALLOC_MAX_BYTES_SYSTEM;
+#endif
+#if defined(HAVE_SBRK) && !defined(OM_HAVE_VALLOC_MMAP) && !defined(OM_MALLOC_MAX_BYTES_SBRK)
+    if (! om_SbrkInit) om_SbrkInit = (unsigned long) sbrk(0) - size;
+    if (om_Info.CurrentBytesFromMalloc + om_Info.CurrentBytesFromValloc > om_Info.MaxBytesSbrk)
+    {
+      om_Info.MaxBytesSbrk = (unsigned long) sbrk(0) - om_SbrkInit;
+      omAssume(om_Info.MaxBytesSbrk >= om_Info.CurrentBytesFromMalloc 
+               + om_Info.CurrentBytesFromValloc);
+    }
+#endif
+  }
+  OM_VALLOC_HOOK(size);
+  return page;
+}
+
+void omVfreeToSystem(void* page, size_t size)
+{
+  omAssume(omIsAddrPageAligned(page));
+  OM_VFREE_TO_SYSTEM(page, size);
+  om_Info.CurrentBytesFromValloc  -= size;
+  OM_VFREE_HOOK(size);
+}
+
+#endif /* OM_ALLOC_SYSTEM_C */
Index: omalloc/omAllocSystem.h
===================================================================
--- omalloc/omAllocSystem.h	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
+++ omalloc/omAllocSystem.h	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
@@ -0,0 +1,42 @@
+/*******************************************************************
+ *  File:    omAllocSystem.h
+ *  Purpose: declaration of routines for low-level alloc routines
+ *           and page management
+ *  Author:  obachman (Olaf Bachmann)
+ *  Created: 11/99
+ *  Version: $Id: omAllocSystem.h,v 1.1 2000-08-14 12:18:26 obachman Exp $
+ *******************************************************************/
+#ifndef OM_ALLOC_SYSTEM_H
+#define OM_ALLOC_SYSTEM_H
+
+size_t omSizeOfAddr(void* addr);
+size_t omSizeWOfAddr(void* addr);
+
+size_t omSizeOfLargeAddr(void* addr);
+#define omSizeWOfLargeAddr(addr) (omSizeOfLargeAddr(addr) >> LOG_SIZEOF_LONG)
+
+void* omAllocFromSystem(size_t size);
+void* omReallocFromSystem(void* addr, size_t newsize);
+void  omFreeToSystem(void* addr);
+
+void* omReallocSizeFromSystem(void* addr, size_t oldsize, size_t newsize);
+void  omFreeSizeToSystem(void* addr, size_t size);
+
+#define omVallocFromSystem(size) _omVallocFromSystem(size, 0)
+void* _omVallocFromSystem(size_t size, int fail);
+void omVfreeToSystem(void* page, size_t size);
+
+
+#ifdef OM_MALLOC_PROVIDES_SIZEOF_ADDR
+#define omAllocLarge(size)             omAllocFromSystem(OM_ALIGN_SIZE(size))
+#define omReallocLarge(addr, new_size) omReallocSizeFromSystem(addr, omSizeOfLargeAddr(addr), OM_ALIGN_SIZE(new_size))
+#define omFreeLarge(addr)              omFreeSizeToSystem(addr, omSizeOfLargeAddr(addr))
+#else
+void* omAllocLarge(size_t size);
+void* omReallocLarge(void* old_addr, size_t new_size);
+void  omFreeLarge(void* addr);
+#endif
+void* omRealloc0Large(void* old_addr, size_t new_size);
+void* omAlloc0Large(size_t size);
+
+#endif /* OM_ALLOC_SYSTEM_H */
Index: omalloc/omBin.c
===================================================================
--- omalloc/omBin.c	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
+++ omalloc/omBin.c	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
@@ -0,0 +1,664 @@
+/*******************************************************************
+ *  File:    omBin.c
+ *  Purpose: definitions of routines for working with bins
+ *  Author:  obachman (Olaf Bachmann)
+ *  Created: 11/99
+ *  Version: $Id: omBin.c,v 1.1 2000-08-14 12:18:26 obachman Exp $
+ *******************************************************************/
+
+#include "omAlloc.h"
+/* this should go away */
+
+#ifdef OM_INTERNAL_DEBUG
+size_t omSizeOfBinAddr(void* addr)
+{
+  return _omSizeOfBinAddr(addr);
+}
+#endif
+
+/*****************************************************************
+ *
+ * SpecBin business
+ *
+ *****************************************************************/
+#define om_LargeBin ((omBin) 1)
+omBin _omGetSpecBin(size_t size, int align, int track)
+
+{
+  omBin om_new_specBin;
+  long max_blocks;
+  long sizeW;
+
+
+  size = OM_ALIGN_SIZE(size);
+#ifdef OM_ALIGNMENT_NEEDS_WORK
+  if (align || size >= OM_SIZEOF_UNIQUE_MAX_BLOCK_THRESHOLD)
+  {
+    align = 1;
+    size = OM_STRICT_ALIGN_SIZE(size);
+  }
+#else
+  align = 0;
+#endif  
+  
+  if (size > SIZEOF_OM_BIN_PAGE)
+  {
+    /* need page header */
+    max_blocks = - (long) 
+      ((size+(SIZEOF_SYSTEM_PAGE-SIZEOF_OM_BIN_PAGE))+SIZEOF_SYSTEM_PAGE-1)
+      / SIZEOF_SYSTEM_PAGE;
+    sizeW = ((-max_blocks*SIZEOF_SYSTEM_PAGE) - 
+             (SIZEOF_SYSTEM_PAGE - SIZEOF_OM_BIN_PAGE)) / SIZEOF_LONG;
+    om_new_specBin = om_LargeBin;
+  }
+  else
+  {
+    /* SIZEOF_OM_BIN_PAGE == max_blocks*size + r1; r1 < size */
+    /* r1 = max_blocks*(size_padding) + r2; r2 < max_blocks */
+    max_blocks = SIZEOF_OM_BIN_PAGE / size;
+    sizeW = (SIZEOF_OM_BIN_PAGE % size) / max_blocks;
+#ifdef OM_ALIGNMENT_NEEDS_WORK
+    if (align)
+      sizeW = ((size + sizeW) & ~ (SIZEOF_STRICT_ALIGNMENT - 1));
+    else
+#endif
+      sizeW = ((size + sizeW) & ~ (SIZEOF_OM_ALIGNMENT - 1));
+    
+    omAssume(sizeW >= size);
+    omAssume(max_blocks*sizeW <= SIZEOF_OM_BIN_PAGE);
+    omAssume((max_blocks+1)*sizeW > SIZEOF_OM_BIN_PAGE ||
+             max_blocks*(sizeW + SIZEOF_STRICT_ALIGNMENT) > SIZEOF_OM_BIN_PAGE);
+
+    sizeW = sizeW >> LOG_SIZEOF_LONG;
+    if (size > OM_MAX_BLOCK_SIZE)
+    {
+      om_new_specBin = om_LargeBin;
+    }
+#ifdef OM_ALIGNMENT_NEEDS_WORK
+    else if (align)
+    {
+      om_new_specBin = omSmallSize2AlignedBin( size );
+    }
+#endif
+#ifdef OM_HAVE_TRACK
+    else if (track)
+    {
+      om_new_specBin = omSmallSize2TrackBin( size );
+    }
+#endif
+    else 
+    {
+      om_new_specBin = omSmallSize2Bin( size );
+    }
+  }
+
+  if (om_new_specBin == om_LargeBin ||
+      om_new_specBin->max_blocks < max_blocks)
+  {
+    omSpecBin s_bin;
+#ifdef OM_HAVE_TRACK
+    if (track)
+      s_bin = omFindInSortedGList(om_SpecTrackBin, next, max_blocks, max_blocks);
+    else
+#endif
+      s_bin = omFindInSortedGList(om_SpecBin, next, max_blocks, max_blocks);
+
+    if (s_bin != NULL) 
+    {
+      (s_bin->ref)++;
+      omAssume(s_bin->bin != NULL && 
+             s_bin->bin->max_blocks == s_bin->max_blocks &&
+             s_bin->bin->sizeW == sizeW);
+      return s_bin->bin;
+    }
+    s_bin = (omSpecBin) omAlloc(sizeof(omSpecBin_t));
+    s_bin->ref = 1;
+    s_bin->next = NULL;
+    s_bin->max_blocks = max_blocks;
+    s_bin->bin = (omBin) omAlloc(sizeof(omBin_t));
+    s_bin->bin->current_page = om_ZeroPage;
+    s_bin->bin->last_page = NULL;
+    s_bin->bin->next = NULL;
+    s_bin->bin->sizeW = sizeW;
+    s_bin->bin->max_blocks = max_blocks;
+    s_bin->bin->sticky = 0;
+#ifdef OM_HAVE_TRACK
+    if (track)
+    {
+      om_SpecTrackBin = omInsertInSortedGList(om_SpecTrackBin, next, max_blocks, s_bin);
+    }
+    else
+#endif
+      om_SpecBin = omInsertInSortedGList(om_SpecBin, next, max_blocks, s_bin);
+    return s_bin->bin;
+  }
+  else
+  {
+    return om_new_specBin;
+  }
+}
+
+void _omUnGetSpecBin(omBin *bin_p, int force)
+{
+  omBin bin = *bin_p;
+  if (! omIsStaticBin(bin))
+  {
+#ifdef OM_HAVE_TRACK 
+    int track_bin = 0;
+#endif 
+    omSpecBin s_bin;
+
+#ifdef OM_HAVE_TRACK
+    s_bin = omFindInGList(om_SpecTrackBin, next, bin, bin);
+    if (s_bin != NULL)
+      track_bin = 1;
+    else
+#endif
+        s_bin = omFindInSortedGList(om_SpecBin, next, max_blocks, bin->max_blocks);
+        
+    omAssume(s_bin != NULL);
+    if (s_bin != NULL)
+    {
+      (s_bin->ref)--;
+      if (s_bin->ref == 0 || force)
+      {
+        if(s_bin->bin->last_page == NULL || force)
+        {
+#ifdef OM_HAVE_TRACK
+          if (track_bin)
+            om_SpecTrackBin = omRemoveFromSortedGList(om_SpecTrackBin, next, max_blocks, s_bin);
+          else
+#endif
+            om_SpecBin = omRemoveFromSortedGList(om_SpecBin, next, max_blocks, s_bin);
+          omFreeSize(s_bin->bin, sizeof(omBin_t));
+          omFreeSize(s_bin, sizeof(omSpecBin_t));
+        }
+      }
+    }
+  }
+  *bin_p = NULL;
+}
+
+/*****************************************************************
+ *
+ * Statistics
+ *
+ *****************************************************************/
+static void omGetBinStat(omBin bin, int *pages_p, int *used_blocks_p, 
+                          int *free_blocks_p)
+{
+  int pages = 0, used_blocks = 0, free_blocks = 0;
+  int where = 1;
+  
+  omBinPage page = bin->last_page;
+  while (page != NULL)
+  {
+    pages++; if (where == 1) 
+    {
+      used_blocks += omGetUsedBlocksOfPage(page) + 1;
+      if (bin->max_blocks > 0)
+        free_blocks += bin->max_blocks - omGetUsedBlocksOfPage(page) -1;
+    }
+    else 
+    {
+      if (bin->max_blocks > 1)
+        used_blocks += bin->max_blocks;
+      else
+        used_blocks++;
+    }
+    if (page == bin->current_page) where = -1;
+    page = page->prev;
+  }
+  *pages_p = pages;
+  *used_blocks_p = used_blocks;
+  *free_blocks_p = free_blocks;
+}
+
+static void omGetTotalBinStat(omBin bin, int *pages_p, int *used_blocks_p, 
+                               int *free_blocks_p)
+{
+  int t_pages = 0, t_used_blocks = 0, t_free_blocks = 0;
+  int pages = 0, used_blocks = 0, free_blocks = 0;
+ 
+  while (bin != NULL)
+  {
+    omGetBinStat(bin, &pages, &used_blocks, &free_blocks);
+    t_pages += pages;
+    t_used_blocks += used_blocks;
+    t_free_blocks += free_blocks;
+    bin = bin->next;
+  }
+  *pages_p = t_pages;
+  *used_blocks_p = t_used_blocks;
+  *free_blocks_p = t_free_blocks;
+}
+
+static void omPrintBinStat(FILE * fd, omBin bin, int track, int* pages, int* used_blocks, int* free_blocks)
+{
+  if (track)
+  {
+    fprintf(fd, "T \t \t");
+  }
+  else
+  {
+    fprintf(fd, "%s%u\t%ld\t", (omIsStaticNormalBin(bin) ? " " : (omIsTrackBin(bin) ? "T" : "*")),
+            bin->sizeW, bin->max_blocks);
+  }
+  omGetTotalBinStat(bin, pages, used_blocks, free_blocks);
+  fprintf(fd, "%d\t%d\t%d\n", *pages, *free_blocks, *used_blocks);
+  if (bin->next != NULL)
+  {
+    int s_pages, s_free_blocks, s_used_blocks;
+    while (bin != NULL)
+    {
+      omGetBinStat(bin, &s_pages, &s_used_blocks, &s_free_blocks);
+      fprintf(fd, " \t \t%d\t%d\t%d\t%d\n", s_pages, s_free_blocks, s_used_blocks, 
+              (int) bin->sticky);
+      bin = bin->next;
+      *pages += s_pages;
+      *used_blocks += s_used_blocks;
+      *free_blocks += s_free_blocks;
+    }
+  }
+}
+  
+void omPrintBinStats(FILE* fd)
+{
+  int i = OM_MAX_BIN_INDEX, pages=0, used_blocks=0, free_blocks=0;
+  int pages_p, used_blocks_p, free_blocks_p;
+  omSpecBin s_bin = om_SpecBin;
+  
+  fprintf(fd, " SizeW\tBlocks\tUPages\tFBlocks\tUBlocks\tSticky\n");
+  fflush(fd);
+  while (s_bin != NULL || i >= 0)
+  {
+    if (s_bin == NULL || (i >= 0 && (unsigned long) om_StaticBin[i].max_blocks < (unsigned long) s_bin->bin->max_blocks))
+    {
+       omPrintBinStat(fd, &om_StaticBin[i], 0, &pages_p, &used_blocks_p, &free_blocks_p);
+       pages += pages_p;
+       used_blocks += used_blocks_p;
+       free_blocks += free_blocks_p;
+#ifdef OM_HAVE_TRACK
+       if (om_StaticTrackBin[i].current_page != om_ZeroPage) 
+       {
+         omPrintBinStat(fd, &om_StaticTrackBin[i], 1, &pages_p, &used_blocks_p, &free_blocks_p);
+         pages += pages_p;
+         used_blocks += used_blocks_p;
+         free_blocks += free_blocks_p;
+       }
+#endif       
+       i--;
+    }
+    else
+    {
+      omPrintBinStat(fd, s_bin->bin,0, &pages_p, &used_blocks_p, &free_blocks_p);
+      pages += pages_p;
+      used_blocks += used_blocks_p;
+      free_blocks += free_blocks_p;
+      s_bin = s_bin->next;
+    }
+  }
+#ifdef OM_HAVE_TRACK
+  s_bin = om_SpecTrackBin;
+  while (s_bin != NULL)
+  {
+    omPrintBinStat(fd, s_bin->bin, 0,  &pages_p, &used_blocks_p, &free_blocks_p);
+    s_bin = s_bin->next;
+    pages += pages_p;
+    used_blocks += used_blocks_p;
+    free_blocks += free_blocks_p;
+  }
+#endif
+  fprintf(fd, "----------------------------------------\n");
+  fprintf(fd, "      \t      \t%d\t%d\t%d\n", pages, free_blocks, used_blocks);
+}
+ 
+/*****************************************************************
+ *
+ * Sticky business
+ *
+ *****************************************************************/
+#define omGetStickyBin(bin, sticky_tag) \
+   omFindInGList(bin, next, sticky, sticky_tag)
+
+static omBin omCreateStickyBin(omBin bin, unsigned long sticky)
+{
+  omBin s_bin = (omBin) omAlloc(sizeof(omBin_t));
+  s_bin->sticky = sticky;
+  s_bin->current_page = om_ZeroPage;
+  s_bin->last_page = NULL;
+  s_bin->max_blocks = bin->max_blocks;
+  s_bin->sizeW = bin->sizeW;
+  s_bin->next = bin->next;
+  bin->next = s_bin;
+  return s_bin;
+}
+
+unsigned long omGetMaxStickyBinTag(omBin bin)
+{
+  unsigned long sticky = 0;
+  do
+  {
+    if (bin->sticky > sticky) sticky = bin->sticky;
+    bin = bin->next;
+  }
+  while (bin != NULL);
+  return sticky;
+}
+
+unsigned long omGetNewStickyBinTag(omBin bin)
+{
+  unsigned long sticky = omGetMaxStickyBinTag(bin);
+  if (sticky < BIT_SIZEOF_LONG - 2)
+  {
+    sticky++;
+    omCreateStickyBin(bin, sticky);
+    return sticky;
+  }
+  else
+  {
+    omAssume(sticky == BIT_SIZEOF_LONG - 1);
+  }
+  return sticky;
+}
+
+void omSetStickyBinTag(omBin bin, unsigned long sticky_tag)
+{
+  omBin s_bin;
+  s_bin = omGetStickyBin(bin, sticky_tag);
+  
+  if (s_bin != bin)
+  {
+    omBinPage tc, tl;
+    unsigned long ts;
+    
+    if (s_bin == NULL) s_bin = omCreateStickyBin(bin, sticky_tag);
+    ts = bin->sticky;
+    tl = bin->last_page;
+    tc = bin->current_page;
+    bin->sticky = s_bin->sticky;
+    bin->current_page = s_bin->current_page;
+    bin->last_page = s_bin->last_page;
+    s_bin->sticky = ts;
+    s_bin->last_page = tl;
+    s_bin->current_page = tc;
+  }
+}
+
+void omUnSetStickyBinTag(omBin bin, unsigned long sticky)
+{
+  omAssume(omGetStickyBin(bin, 0) != NULL);
+  if (bin->sticky == sticky)
+    omSetStickyBinTag(bin, 0);
+}
+
+static void omMergeStickyPages(omBin to_bin, omBin from_bin)
+{
+#ifdef HAVE_OM_ASSUME
+  int length = omGListLength(to_bin->last_page, prev) +
+    omGListLength(from_bin->last_page, prev);
+#endif  
+  
+  omBinPage page = from_bin->last_page;
+  omAssume(to_bin->sticky == 0);
+  omAssume(to_bin->sizeW == from_bin->sizeW);
+  omAssume(to_bin != from_bin);
+  omAssume(omIsOnGList(to_bin->next, next, from_bin) 
+           || 
+           omIsOnGList(from_bin->next, next, to_bin));
+
+  if (page == NULL) return;
+  do
+  {
+    omSetStickyOfPage(page, 0);
+    if (page->prev == NULL) break;
+    page = page->prev;
+  }
+  while(1);
+
+  if (to_bin->last_page == NULL)
+  {
+    omAssume(to_bin->current_page == om_ZeroPage);
+    to_bin->last_page = from_bin->last_page;
+    to_bin->current_page = from_bin->current_page;
+    return;
+  }
+  
+  omAssume(to_bin->current_page != om_ZeroPage && 
+           to_bin->current_page != NULL);
+
+  if (to_bin->current_page->current != NULL)
+  {
+    if (to_bin->current_page->prev == NULL)
+    {
+      from_bin->last_page->next = to_bin->current_page;
+      to_bin->current_page->prev = from_bin->last_page;
+      to_bin->current_page = from_bin->current_page;
+      return;
+    }
+    to_bin->current_page = to_bin->current_page->prev;
+  }
+  else
+  {
+    /* need to reset this here, since new current_page is going to be
+       from_bin->current_page, and only for current_page may we have 
+       used_blocks != 0 && current == NULL */
+    to_bin->current_page->used_blocks = 0;
+  }
+  
+
+  omAssume(to_bin->current_page != NULL && 
+           to_bin->current_page->current == NULL &&
+           to_bin->current_page->used_blocks == 0);
+
+  from_bin->last_page->next = to_bin->current_page->next;
+  if (to_bin->current_page->next != NULL) 
+    to_bin->current_page->next->prev =  from_bin->last_page;
+  else
+  {
+    omAssume(to_bin->current_page == to_bin->last_page);
+    to_bin->last_page = from_bin->last_page;
+  }
+  to_bin->current_page->next = page;
+  page->prev = to_bin->current_page;
+  to_bin->current_page = from_bin->current_page;
+  
+#ifdef HAVE_OM_ASSUME
+  omAssume(omGListLength(to_bin->last_page, prev) == length);
+#endif
+}
+
+void omDeleteStickyBinTag(omBin bin, unsigned long sticky)
+{
+  omBin no_sticky_bin = NULL;
+  omBin sticky_bin = NULL;
+
+  if (sticky == 0)
+  {
+    omAssume(0);
+    return;
+  }
+  
+  sticky_bin = omGetStickyBin(bin, sticky);
+  if (sticky_bin != NULL)
+  {
+    no_sticky_bin = omGetStickyBin(bin, 0);
+    omAssume(no_sticky_bin != NULL && sticky_bin != no_sticky_bin);
+
+    omMergeStickyPages(no_sticky_bin, sticky_bin);
+
+    if (bin == sticky_bin) 
+    {
+      sticky_bin = no_sticky_bin;
+      omSetStickyBinTag(bin, 0);
+    }
+    bin->next = omRemoveFromGList(bin->next, next, sticky_bin);
+    omFreeSize(sticky_bin, sizeof(omBin_t));
+  }
+}
+
+
+ 
+/*****************************************************************
+*
+* AllBin business
+*
+*****************************************************************/
+unsigned long omGetNewStickyAllBinTag()
+{
+  unsigned long sticky = 0, new_sticky;
+  int i;
+  omSpecBin s_bin;
+  // first, find new sticky tag
+  for (i=0; i<=OM_MAX_BIN_INDEX; i++)
+  {
+    new_sticky = omGetMaxStickyBinTag(&(om_StaticBin[i]));
+    if (new_sticky > sticky) sticky = new_sticky;
+  }
+  s_bin = om_SpecBin;
+  while (s_bin != NULL) 
+  {
+    new_sticky = omGetMaxStickyBinTag(s_bin->bin);
+    if (new_sticky > sticky) sticky = new_sticky;
+    s_bin = s_bin->next;
+  }
+  if (sticky < BIT_SIZEOF_LONG - 2) 
+  {
+    sticky++;
+    for (i=0; i<=OM_MAX_BIN_INDEX; i++)
+    {
+      omCreateStickyBin(&(om_StaticBin[i]), sticky);
+    }
+    s_bin = om_SpecBin;
+    while (s_bin != NULL) 
+    {
+      omCreateStickyBin(s_bin->bin, sticky);
+      s_bin = s_bin->next;
+    }
+    return sticky;
+  }
+  else
+  {
+    omBin bin;
+    omAssume(sticky == BIT_SIZEOF_LONG - 1);
+    for (i=0; i<=OM_MAX_BIN_INDEX; i++)
+    {
+      bin = &om_StaticBin[i];
+      if (omGetStickyBin(bin, BIT_SIZEOF_LONG -1) == NULL)
+        omCreateStickyBin(bin, BIT_SIZEOF_LONG -1);
+    }
+    s_bin = om_SpecBin;
+    while (s_bin != NULL) 
+    {
+      if (omGetStickyBin(s_bin->bin, BIT_SIZEOF_LONG -1) == NULL)
+        omCreateStickyBin(s_bin->bin, BIT_SIZEOF_LONG -1);
+      s_bin = s_bin->next;
+    }
+    return BIT_SIZEOF_LONG - 1;
+  }
+}
+
+void omSetStickyAllBinTag(unsigned long sticky)
+{
+  omSpecBin s_bin = om_SpecBin;
+  int i;
+  for (i=0; i<=OM_MAX_BIN_INDEX; i++)
+  {
+    omSetStickyBinTag(&(om_StaticBin[i]), sticky);
+  }
+  while (s_bin != NULL) 
+  {
+    omSetStickyBinTag(s_bin->bin, sticky);
+    s_bin = s_bin->next;
+  }
+}
+
+void omUnSetStickyAllBinTag(unsigned long sticky)
+{
+  omSpecBin s_bin = om_SpecBin;
+  int i;
+  for (i=0; i<=OM_MAX_BIN_INDEX; i++)
+  {
+    omUnSetStickyBinTag(&(om_StaticBin[i]), sticky);
+  }
+  while (s_bin != NULL) 
+  {
+    omUnSetStickyBinTag(s_bin->bin, sticky);
+    s_bin = s_bin->next;
+  }
+}
+
+void omDeleteStickyAllBinTag(unsigned long sticky)
+{
+  omSpecBin s_bin = om_SpecBin;
+  int i;
+  for (i=0; i<=OM_MAX_BIN_INDEX; i++)
+  {
+    omDeleteStickyBinTag(&(om_StaticBin[i]), sticky);
+  }
+  while (s_bin != NULL) 
+  {
+    omDeleteStickyBinTag(s_bin->bin, sticky);
+    s_bin = s_bin->next;
+  }
+}
+
+#if 0
+void omPrintMissing(omBin bin)
+{
+  omBinPage page = bin->last_page;
+  
+  while (page != NULL)
+  {
+    void* addr = (void*) page + SIZEOF_OM_BIN_PAGE_HEADER;
+    int i;
+    
+    for (i=0; i<bin->max_blocks; i++)
+    {
+      if (! omIsOnList(page->current, addr))
+        printf("%d:%p\n", i, addr);
+      addr += bin->sizeW*SIZEOF_LONG;
+    }
+    page = page->prev;
+  }
+}
+#endif
+
+static  int omGetUsedBytesOfBin(omBin bin)
+{
+  int pages = 0, used_blocks = 0, free_blocks = 0;
+  omGetTotalBinStat(bin, &pages, &used_blocks, &free_blocks);
+  return used_blocks*bin->sizeW*SIZEOF_LONG;
+}
+
+size_t omGetUsedBinBytes()
+{
+  int i = OM_MAX_BIN_INDEX;
+  omSpecBin s_bin = om_SpecBin;
+  size_t used = 0;
+  
+  for (; i>=0; i--)
+  {
+    used += omGetUsedBytesOfBin(&om_StaticBin[i]);
+  }
+  while (s_bin != NULL)
+  {
+    used += omGetUsedBytesOfBin(s_bin->bin);
+    s_bin = s_bin->next;
+  }
+#ifdef OM_HAVE_TRACK
+  for (i=OM_MAX_BIN_INDEX; i>=0; i--)
+  {
+    used += omGetUsedBytesOfBin(&om_StaticTrackBin[i]);
+  }
+  s_bin = om_SpecTrackBin;
+  while (s_bin != NULL)
+  {
+    used += omGetUsedBytesOfBin(s_bin->bin);
+    s_bin = s_bin->next;
+  }
+#endif
+
+  return used;
+}
+
Index: omalloc/omBin.h
===================================================================
--- omalloc/omBin.h	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
+++ omalloc/omBin.h	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
@@ -0,0 +1,57 @@
+/*******************************************************************
+ *  File:    omBin.h
+ *  Purpose: declaration of routines related to Bins
+ *  Author:  obachman (Olaf Bachmann)
+ *  Created: 11/99
+ *  Version: $Id: omBin.h,v 1.1 2000-08-14 12:18:27 obachman Exp $
+ *******************************************************************/
+#ifndef OM_BIN_H
+#define OM_BIN_H
+
+
+
+#define omGetAlignedSpecBin(size) _omGetSpecBin(size, 1, 0)
+#define omGetSpecBin(size) _omGetSpecBin(size, 0, 0)
+omBin _omGetSpecBin(size_t size, int align, int track);
+
+#define omUnGetSpecBin(bin_ptr) _omUnGetSpecBin(bin_ptr, 0)
+#define omDeleteSpecBin(bin_ptr) _omUnGetSpecBin(bin_ptr, 1)
+void  _omUnGetSpecBin(omBin *bin, int force);
+size_t omGetUsedBinBytes();
+
+unsigned long omGetNewStickyBinTag(omBin bin);
+void omSetStickyBinTag(omBin bin, unsigned long sticky);
+void omUnSetStickyBinTag(omBin bin, unsigned long sticky);
+void omDeleteStickyBinTag(omBin bin, unsigned long sticky);
+
+unsigned long omGetNewStickyAllBinTag();
+void omSetStickyAllBinTag(unsigned long sticky);
+void omUnSetStickyAllBinTag(unsigned long sticky);
+void omDeleteStickyAllBinTag(unsigned long sticky);
+
+void omPrintBinStats(FILE* fd);
+
+/*BEGINPRIVATE*/
+#ifdef OM_HAVE_TRACK
+#define omGetSpecTrackBin(size) _omGetSpecBin(size, 0, 1)
+#endif
+
+#define omIsStaticNormalBin(bin)                                            \
+ ((unsigned long) bin >= ((unsigned long) &om_StaticBin[0]) &&              \
+  (unsigned long) bin <= ((unsigned long) &om_StaticBin[OM_MAX_BIN_INDEX]))
+#define omIsNormalBin(bin) omIsStaticNormalBin(bin) || omFindInGList(om_SpecBin, next, bin, bin)
+
+#ifdef OM_HAVE_TRACK
+#define omIsStaticTrackBin(bin)                                                  \
+ ((unsigned long) bin >= ((unsigned long) &om_StaticTrackBin[0]) &&              \
+  (unsigned long) bin <= ((unsigned long) &om_StaticTrackBin[OM_MAX_BIN_INDEX]))
+#define omIsTrackBin(bin) omIsStaticTrackBin(bin) || omFindInGList(om_SpecTrackBin, next, bin, bin)
+#else
+#define omIsStaticTrackBin(bin) 0
+#define omIsTrackBin(bin)       0
+#endif
+#define omIsStaticBin(bin) omIsStaticNormalBin(bin) || omIsStaticTrackBin(bin)
+/*ENDPRIVATE*/
+
+#endif /* OM_BIN_H */
+
Index: omalloc/omBinPage.c
===================================================================
--- omalloc/omBinPage.c	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
+++ omalloc/omBinPage.c	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
@@ -0,0 +1,609 @@
+/*******************************************************************
+ *  File:    omBinPage.c
+ *  Purpose: implementation of routines for primitve BinPage managment
+ *  Author:  obachman (Olaf Bachmann)
+ *  Created: 11/99
+ *  Version: $Id: omBinPage.c,v 1.1 2000-08-14 12:18:27 obachman Exp $
+ *******************************************************************/
+#include <limits.h>
+#include "omAlloc.h"
+#include "omDefaultConfig.h"
+
+/*******************************************************************
+ *  
+ * Local declarations  
+ *  
+ *******************************************************************/
+
+/* define if you want to keep regions approximately in order */
+#define OM_KEEP_REGIONS_ORDER
+
+struct omBinPageRegion_s
+{
+  void* current;        /* linked list of free pages */
+  int   used_pages;     /* number of used pages */
+  omBinPageRegion next; /* nex/prev pointer in ring of regions */
+  omBinPageRegion prev;
+  void* init_addr;      /* pointer portion of inital chunk which is still free */
+  int   init_pages;   /* number of pages still available in init_chunk */  
+  void* addr;         /* addr returned by alloc */
+  int pages;          /* total size of region */
+};
+
+/* globale variable holding pointing int regions ring */
+static omBinPageRegion om_CurrentBinPageRegion = NULL;
+unsigned long om_MaxBinPageIndex = 0;
+unsigned long om_MinBinPageIndex = ULONG_MAX;
+unsigned long *om_BinPageIndicies = NULL;
+
+/* declaration of local procs */
+static void* omTakeOutConsecutivePages(omBinPageRegion region, int how_many);
+static omBinPageRegion omAllocNewBinPagesRegion(int min_pages);
+static void omFreeBinPagesRegion(omBinPageRegion region);
+
+static void omBinPageIndexFault(unsigned long low_index, unsigned long high_index);
+static void omRegisterBinPages(void* low_addr, int pages);
+static void omUnregisterBinPages(void* low_addr, int pages);
+
+OM_INLINE_LOCAL void omTakeOutRegion(omBinPageRegion region)
+{
+  omAssume(region != NULL);
+  
+  if (region->prev != NULL)
+  {
+    omAssume(region->prev != region && region->prev != region->next);
+    region->prev->next = region->next;
+  }
+  
+  if (region->next != NULL) 
+  {
+    omAssume(region->next != region && region->prev != region->next);
+    region->next->prev = region->prev;
+  }
+}
+
+OM_INLINE_LOCAL void omInsertRegionAfter(omBinPageRegion insert, omBinPageRegion after)
+{
+  omAssume(insert != NULL && after != NULL && insert != after);
+  insert->next = after->next;
+  insert->prev = after;
+  after->next = insert;
+  if (insert->next != NULL)
+  {
+    omAssume(insert->next != insert && insert->next != after);
+    insert->next->prev = insert;
+  }
+}
+
+OM_INLINE_LOCAL void omInsertRegionBefore(omBinPageRegion insert, omBinPageRegion before)
+{
+  omAssume(insert != NULL && before != NULL && insert != before);
+  insert->prev = before->prev;
+  insert->next = before;
+  before->prev = insert;
+  if (insert->prev != NULL)
+    insert->prev->next = insert;
+}
+    
+
+/*******************************************************************
+ *  
+ * Alloc/Free of BinPages
+ *  
+ *******************************************************************/
+#define NEXT_PAGE(page) *((void**) page)
+#define OM_IS_EMPTY_REGION(region) ((region)->current == NULL && (region->init_addr == NULL))
+
+omBinPage omAllocBinPage()
+{
+  omBinPage bin_page;
+
+  if (om_CurrentBinPageRegion == NULL)
+    om_CurrentBinPageRegion = omAllocNewBinPagesRegion(1);
+
+  while (1)
+  {
+    if (om_CurrentBinPageRegion->current != NULL)
+    {
+      bin_page = om_CurrentBinPageRegion->current;
+      om_CurrentBinPageRegion->current = NEXT_PAGE(bin_page);
+      goto Found;
+    }
+    if (om_CurrentBinPageRegion->init_pages)
+    {
+      bin_page = om_CurrentBinPageRegion->init_addr;
+      om_CurrentBinPageRegion->init_pages--;
+      if (om_CurrentBinPageRegion->init_pages) 
+        om_CurrentBinPageRegion->init_addr += SIZEOF_SYSTEM_PAGE;
+      else
+        om_CurrentBinPageRegion->init_addr = NULL;
+      goto Found;
+    }
+    if (om_CurrentBinPageRegion->next != NULL)
+    {
+      om_CurrentBinPageRegion = om_CurrentBinPageRegion->next;
+    }
+    else
+    {
+      omBinPageRegion new_region = omAllocNewBinPagesRegion(1);
+      new_region->prev = om_CurrentBinPageRegion;
+      om_CurrentBinPageRegion->next = new_region;
+      om_CurrentBinPageRegion = new_region;
+    }
+  }
+  while (1);
+        
+  Found:
+  bin_page->region = om_CurrentBinPageRegion;
+  om_CurrentBinPageRegion->used_pages++;
+  
+  om_Info.UsedPages++;
+  om_Info.AvailPages--;
+  if (om_Info.UsedPages > om_Info.MaxPages)
+    om_Info.MaxPages = om_Info.UsedPages;
+  
+  OM_ALLOC_BINPAGE_HOOK;
+  return bin_page;
+}
+
+omBinPage omAllocBinPages(int how_many)
+{
+  omBinPage bin_page;
+  omBinPageRegion region;
+
+  if (om_CurrentBinPageRegion == NULL)
+    om_CurrentBinPageRegion = omAllocNewBinPagesRegion(how_many);
+
+  region = om_CurrentBinPageRegion;
+  while (1)
+  {
+    if (region->init_pages >= how_many)
+    {
+      bin_page = region->init_addr;
+      region->init_pages -= how_many;
+      if (region->init_pages) 
+        region->init_addr += how_many*SIZEOF_SYSTEM_PAGE;
+      else
+        region->init_addr = NULL;
+      goto Found;
+    }
+    if ((bin_page = omTakeOutConsecutivePages(region, how_many)) != NULL)
+    {
+      goto Found;
+    }
+    if (region->next != NULL)
+    {
+      region = region->next;
+    }
+    else
+    {
+      omBinPageRegion new_region = omAllocNewBinPagesRegion(how_many);
+      region->next = new_region;
+      new_region->prev = region;
+      region = new_region;
+    }
+  }
+  while (1);
+        
+  Found:
+  bin_page->region = region;
+  region->used_pages += how_many;
+
+  if (region != om_CurrentBinPageRegion && OM_IS_EMPTY_REGION(region))
+  {
+    omTakeOutRegion(region);
+    omInsertRegionBefore(region, om_CurrentBinPageRegion);
+  }
+  om_Info.UsedPages += how_many;
+  om_Info.AvailPages -= how_many;
+  if (om_Info.UsedPages > om_Info.MaxPages)
+    om_Info.MaxPages = om_Info.UsedPages;
+
+  OM_ALLOC_BINPAGE_HOOK;
+  return bin_page;
+}
+  
+void omFreeBinPages(omBinPage bin_page, int how_many)
+{
+  omBinPageRegion region = bin_page->region;
+
+  region->used_pages -= how_many;
+  if (region->used_pages == 0)
+  {
+    if (region == om_CurrentBinPageRegion) 
+    {
+      if (region->next != NULL) 
+        om_CurrentBinPageRegion = region->next;
+      else
+        om_CurrentBinPageRegion = region->prev;
+    }
+    omTakeOutRegion(region);
+    omFreeBinPagesRegion(region);
+  }
+  else
+  {
+    if (region != om_CurrentBinPageRegion && OM_IS_EMPTY_REGION(region))
+    {
+      omTakeOutRegion(region);
+      omInsertRegionAfter(region, om_CurrentBinPageRegion);
+    }
+    if (how_many > 1)
+    {
+      int i = how_many;
+      void* page = bin_page;
+      
+      while (i > 1)
+      {
+        NEXT_PAGE(page) = page + SIZEOF_SYSTEM_PAGE;
+        page = NEXT_PAGE(page);
+        i--;
+      }
+      NEXT_PAGE(page) = region->current;
+    }
+    else
+    {
+      NEXT_PAGE(bin_page) = region->current;
+    }
+    region->current = (void*) bin_page;
+  }
+  om_Info.AvailPages += how_many;
+  om_Info.UsedPages -= how_many;
+  OM_FREE_BINPAGE_HOOK;
+}
+  
+static void* omTakeOutConsecutivePages(omBinPageRegion region, int pages)
+{
+  void* current;
+  void* iter;
+  void* prev = NULL;
+  void* bin_page;
+  int found;
+  current = region->current;
+  while (current != NULL)
+  {
+    found = 1;
+    iter = current;
+    while (NEXT_PAGE(iter) == iter + SIZEOF_SYSTEM_PAGE)
+    {
+      iter = NEXT_PAGE(iter);
+      /* handle pathological case that iter + SIZEOF_SYSTEM_PAGE == 0 */
+      if (iter == NULL) return NULL;
+      found++;
+      if (found == pages)
+      {
+        bin_page = current;
+        if (current == region->current)
+        {
+          region->current = NEXT_PAGE(iter);
+        }
+        else
+        {
+          omAssume(prev != NULL);
+          NEXT_PAGE(prev) = NEXT_PAGE(iter);
+        }
+        return bin_page;
+      }
+    }
+    prev = iter;
+    current = NEXT_PAGE(iter);
+  }
+  return NULL;
+}
+
+/* Alloc a new region and insert into regions ring, set current to new region */
+static omBinPageRegion omAllocNewBinPagesRegion(int min_pages)
+{
+  omBinPageRegion region = omAllocFromSystem(sizeof(omBinPageRegion_t));
+  void* addr;
+  int pages = (min_pages>om_Opts.PagesPerRegion ? min_pages : om_Opts.PagesPerRegion);
+  size_t size = pages*SIZEOF_SYSTEM_PAGE;
+  
+  addr = _omVallocFromSystem(size, 1);
+  if (addr == NULL) 
+  {
+    pages = min_pages;
+    size = min_pages*SIZEOF_SYSTEM_PAGE;
+    addr = omVallocFromSystem(size);
+  }
+  
+  omRegisterBinPages(addr, pages);
+  region->addr = addr;
+  region->pages = pages;
+  region->used_pages = 0;
+  region->init_addr = addr;
+  region->init_pages = pages;
+  region->current = NULL;
+  region->next = NULL;
+  region->prev = NULL;
+
+  om_Info.AvailPages += pages;
+
+  om_Info.CurrentRegionsAlloc++;
+  if (om_Info.CurrentRegionsAlloc > om_Info.MaxRegionsAlloc)
+    om_Info.MaxRegionsAlloc = om_Info.CurrentRegionsAlloc;
+
+  /* Update info so that max fields can be updated */
+  omUpdateInfo();
+
+  return region;
+}
+
+/* Free region */
+static void omFreeBinPagesRegion(omBinPageRegion region)
+{
+  omAssume(region != NULL && region->used_pages == 0);
+
+  om_Info.AvailPages -= region->pages;
+  om_Info.CurrentRegionsAlloc--;
+
+  omUnregisterBinPages(region->addr, region->pages);
+  omVfreeToSystem(region->addr, region->pages*SIZEOF_SYSTEM_PAGE);
+  omFreeSizeToSystem(region, sizeof(omBinPageRegion_t));
+}
+
+/*******************************************************************
+ *  
+ * BinPage registration
+ *  
+ *******************************************************************/
+
+static void omBinPageIndexFault(unsigned long low_index, unsigned long high_index)
+{
+  unsigned long index_diff = high_index - low_index;
+  long i;
+  omAssume(low_index <= high_index &&
+           (high_index > om_MaxBinPageIndex || low_index < om_MinBinPageIndex));
+  
+  if (om_BinPageIndicies == NULL)
+  {
+    om_BinPageIndicies = (unsigned long*) omAllocFromSystem((index_diff + 1)*SIZEOF_LONG);
+    om_MaxBinPageIndex = high_index;
+    om_MinBinPageIndex = low_index;
+    for (i=0; i<=index_diff; i++) om_BinPageIndicies[i] = 0;
+  }
+  else
+  {
+    unsigned long old_length = om_MaxBinPageIndex - om_MinBinPageIndex + 1;
+    unsigned long new_length = (low_index < om_MinBinPageIndex ? 
+                                om_MaxBinPageIndex - low_index : 
+                                high_index - om_MinBinPageIndex) + 1;
+    om_BinPageIndicies  = (unsigned long*) omReallocSizeFromSystem(om_BinPageIndicies, old_length*SIZEOF_LONG,
+                                                                   new_length*SIZEOF_LONG);
+    if (low_index < om_MinBinPageIndex)
+    {
+      unsigned long offset = new_length - old_length;
+      for (i=old_length - 1; i >= 0; i--) om_BinPageIndicies[i+offset] = om_BinPageIndicies[i];
+      for (i=0; i<offset; i++)  om_BinPageIndicies[i] = 0;
+      om_MinBinPageIndex = low_index;
+    }
+    else
+    {
+      for (i=old_length; i<new_length; i++) om_BinPageIndicies[i] = 0;
+      om_MaxBinPageIndex = high_index;
+    }
+  }
+}
+
+static void omRegisterBinPages(void* low_addr, int pages)
+{
+  unsigned long low_index = omGetPageIndexOfAddr(low_addr);
+  void* high_addr = low_addr + (pages-1)*SIZEOF_SYSTEM_PAGE;
+  unsigned long high_index = omGetPageIndexOfAddr(high_addr);
+  unsigned long shift;
+   
+  if (low_index < om_MinBinPageIndex || high_index > om_MaxBinPageIndex)
+    omBinPageIndexFault(low_index, high_index);
+
+  shift = omGetPageShiftOfAddr(low_addr);
+  if (low_index < high_index)
+  {
+    if (shift == 0)
+    {
+      om_BinPageIndicies[low_index-om_MinBinPageIndex] = ULONG_MAX;
+    }
+    else
+    {
+      om_BinPageIndicies[low_index-om_MinBinPageIndex] |= ~ (( 1<< shift) - 1);
+    }
+    for (shift = low_index+1; shift < high_index; shift++)
+    {
+      om_BinPageIndicies[shift-om_MinBinPageIndex] = ULONG_MAX;
+    }
+    shift = omGetPageShiftOfAddr(high_addr);
+    if (shift == BIT_SIZEOF_LONG - 1)
+    {
+      om_BinPageIndicies[high_index - om_MinBinPageIndex] = ULONG_MAX;
+    }
+    else
+    {
+      om_BinPageIndicies[high_index-om_MinBinPageIndex] |= ((1 << (shift + 1)) - 1);
+    }
+  }
+  else
+  {
+    high_index = omGetPageShiftOfAddr(high_addr);
+    while (high_index > shift)
+    {
+      om_BinPageIndicies[low_index-om_MinBinPageIndex] |= (1 << high_index);
+      high_index--;
+    }
+    om_BinPageIndicies[low_index-om_MinBinPageIndex] |= (1 << shift);
+  }
+}
+
+static void omUnregisterBinPages(void* low_addr, int pages)
+{
+  unsigned long low_index = omGetPageIndexOfAddr(low_addr);
+  void* high_addr = low_addr + (pages-1)*SIZEOF_SYSTEM_PAGE;
+  unsigned long high_index = omGetPageIndexOfAddr(high_addr);
+  unsigned long shift;
+  
+  shift = omGetPageShiftOfAddr(low_addr);
+  if (low_index < high_index)
+  {
+    if (shift == 0)
+    {
+      om_BinPageIndicies[low_index-om_MinBinPageIndex] = 0;
+    }
+    else
+    {
+      om_BinPageIndicies[low_index-om_MinBinPageIndex] &= (( 1<< shift) - 1);
+    }
+    for (shift = low_index+1; shift < high_index; shift++)
+    {
+      om_BinPageIndicies[shift-om_MinBinPageIndex] = 0;
+    }
+    shift = omGetPageShiftOfAddr(high_addr);
+    if (shift == BIT_SIZEOF_LONG - 1)
+    {
+      om_BinPageIndicies[high_index - om_MinBinPageIndex] = 0;
+    }
+    else
+    {
+      om_BinPageIndicies[high_index-om_MinBinPageIndex] &= ~ ((1 << (shift + 1)) - 1);
+    }
+  }
+  else
+  {
+     high_index = omGetPageShiftOfAddr(high_addr);
+     while (high_index > shift)
+     {
+       om_BinPageIndicies[low_index-om_MinBinPageIndex] &= ~(1 << high_index);
+       high_index--;
+     }
+     om_BinPageIndicies[low_index-om_MinBinPageIndex] &= ~(1 << shift);
+  }
+}
+   
+/***********************************************************************
+ *
+ * checking routines
+ *
+ *******************************************************************/
+#ifndef OM_NDEBUG
+#include "omDebug.h"
+
+int omIsKnownMemoryRegion(omBinPageRegion region)
+{
+  omBinPageRegion iter = om_CurrentBinPageRegion;
+  
+  if (region == NULL || iter == NULL) return 0;
+  iter = omGListLast(om_CurrentBinPageRegion, prev);
+  do
+  {
+    if (region == iter) return 1;
+    iter = iter->next;
+  }
+  while (iter != NULL);
+  return 0;
+}
+  
+
+omError_t omCheckBinPageRegion(omBinPageRegion region, int level, omError_t report, OM_FLR_DECL)
+{
+  if (level <= 0) return omError_NoError;
+  
+  omCheckReturn(omCheckPtr(region, report, OM_FLR_VAL));
+  omCheckReturnCorrupted(! omIsKnownMemoryRegion(region));
+  omCheckReturnCorrupted(! omIsAddrPageAligned(region->addr) || ! omIsAddrPageAligned(region->current));
+  omCheckReturnCorrupted(region->used_pages < 0);
+  omCheckReturnCorrupted(region->init_pages < 0 || region->init_pages > region->pages);
+  
+  if (region->init_pages)
+  {
+    omCheckReturnCorrupted(! omIsAddrPageAligned(region->init_addr));
+    omCheckReturnCorrupted(! (region->init_addr >= region->addr 
+                              && region->init_addr <= region->addr + (region->pages -1)*SIZEOF_SYSTEM_PAGE));
+    omCheckReturnCorrupted(region->init_addr != 
+                           region->addr + (region->pages - region->init_pages)*SIZEOF_SYSTEM_PAGE);
+  }
+   
+  omCheckReturn(omCheckList(region->current, level, report, OM_FLR_VAL));
+  omCheckReturnCorrupted(region->current == NULL && region->used_pages + region->init_pages != region->pages);
+  omCheckReturnCorrupted(level > 1 && 
+                         omListLength(region->current)+region->used_pages+region->init_pages != region->pages);
+  return omError_NoError;
+}
+
+omError_t omCheckBinPageRegions(int level, omError_t report, OM_FLR_DECL)
+{
+  omBinPageRegion iter = om_CurrentBinPageRegion;
+
+  if (level <= 0) return omError_NoError;
+  if (iter == NULL) return omError_NoError;
+
+  omCheckReturnError(om_CurrentBinPageRegion->next != NULL && OM_IS_EMPTY_REGION(om_CurrentBinPageRegion->next),
+                     omError_InternalBug);
+  omCheckReturnError(om_CurrentBinPageRegion->prev != NULL && ! OM_IS_EMPTY_REGION(om_CurrentBinPageRegion->prev),
+                     omError_InternalBug);
+
+
+  if (level > 1)
+  {
+    omBinPageRegion prev_last = (omBinPageRegion) omGListLast(om_CurrentBinPageRegion, prev);
+    omBinPageRegion next_last = (omBinPageRegion) omGListLast(om_CurrentBinPageRegion, next);
+    
+    omCheckReturn(omCheckGList(iter, next, level, report, OM_FLR_VAL));
+    omCheckReturn(omCheckGList(iter, prev, level, report, OM_FLR_VAL));
+
+    omCheckReturnCorrupted(omGListLength(prev_last, next)
+                          != 
+                          omGListLength(next_last, prev));
+    
+    omCheckReturn(omCheckBinPageRegion(om_CurrentBinPageRegion, level - 1, report, OM_FLR_VAL));
+
+    iter = om_CurrentBinPageRegion->next;
+    while (iter)
+    {
+      omCheckReturnError(OM_IS_EMPTY_REGION(iter), omError_InternalBug);
+
+      omCheckReturn(omCheckBinPageRegion(iter, level - 1, report, OM_FLR_VAL));
+      iter = iter->next;
+    }
+
+    iter = om_CurrentBinPageRegion->prev;
+    while (iter)
+    {
+      omCheckReturnError( !OM_IS_EMPTY_REGION(iter), omError_InternalBug);
+      omCheckReturn(omCheckBinPageRegion(iter, level - 1, report, OM_FLR_VAL));
+      iter = iter->prev;
+    }
+  }
+  return omError_NoError;
+}
+
+omBinPageRegion omFindRegionOfAddr(void* addr)
+{
+  omBinPageRegion region = om_CurrentBinPageRegion;
+  
+  if (region == NULL) return 0;
+  region = omGListLast(region, prev);
+  do
+  {
+    if (addr >= region->addr && addr < region->addr + (region->pages)*SIZEOF_SYSTEM_PAGE)
+      return region;
+    region = region->next;
+  }
+  while (region != NULL);
+  return NULL;
+}
+
+int omIsAddrOnFreeBinPage(void* addr)
+{
+  omBinPageRegion region = om_CurrentBinPageRegion;
+  
+  if (region == NULL) return 0;
+  do
+  {
+    if (addr > region->addr && addr < region->addr + (region->pages)*SIZEOF_SYSTEM_PAGE)
+    {
+      if (omIsOnList(region->current, omGetPageOfAddr(addr))) return 1;
+      return 0;
+    }
+    region = region->next;
+  }
+  while (region != NULL);
+  return 0;
+}
+  
+#endif /* ! OM_NDEBUG */
Index: omalloc/omBinPage.h
===================================================================
--- omalloc/omBinPage.h	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
+++ omalloc/omBinPage.h	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
@@ -0,0 +1,93 @@
+/*******************************************************************
+ *  File:    omBinPage.h
+ *  Purpose: declaration of routines for primitve BinPage managment
+ *  Author:  obachman (Olaf Bachmann)
+ *  Created: 11/99
+ *  Version: $Id: omBinPage.h,v 1.1 2000-08-14 12:18:27 obachman Exp $
+ *******************************************************************/
+#ifndef OM_BIN_PAGE_H
+#define OM_BIN_PAGE_H
+
+/***********************************************************************
+ *
+ * Macros for page manipulations
+ *
+ **********************************************************************/
+
+#define omIsAddrPageAligned(addr) \
+  (((long) (addr) & (SIZEOF_SYSTEM_PAGE -1)) == 0)
+
+#define omGetPageOfAddr(addr) \
+  ((void*) ((long) (addr) & ~(SIZEOF_SYSTEM_PAGE -1)))
+
+#define omGetBinPageOfAddr(addr) \
+  ((omBinPage) ((long) (addr) & ~(SIZEOF_SYSTEM_PAGE -1)))
+
+#define omIsAddrOnPage(addr, page) (omGetPageOfAddr(addr) == (void*) (page))
+
+#define omAreAddrOnSamePage(a1, a2) \
+  (omGetPageOfAddr(a1) == omGetPageOfAddr(a2))
+
+/***********************************************************************
+ *
+ * Identifying whether an address is a BinPageAddr:
+ *
+ *******************************************************************/
+
+/* Here is how it works (assume SIZEOF_LONG == 4, SIZEOF_SYSTEM_PAGE = 2^12):
+   Let
+   Addr: |    15               |  5       |    12        |
+          PAGE_INDEX            PAGE_SHIFT PAGE_OFFSET
+
+                                      PAGE_BASE
+
+   om_PageIndicies is an array of bit-fields which is indexed by
+                  PAGE_INDEX - om_MinBinPageIndex. Its maximal length
+                  is 2^15. PAGE_SHIFT is used as index into the bit-field.
+                  If it's value is 1, then addr is from omBinPage, else
+                  not.
+
+   om_MinPageIndex is minimal page index of registered BinPageAddr
+
+   In other words: omIsBinPageAddr iff PAGE_INDEX >= om_MinBinPageIndex && PAGE_INDEX <=  om_MaxBinPageIndex
+   && om_PageIndicies[PAGE_INDEX - om_MinPageIndex] & (1 << PAGE_SHIFT) */
+
+extern unsigned long om_MaxBinPageIndex;
+extern unsigned long om_MinBinPageIndex;
+extern unsigned long *om_BinPageIndicies;
+
+#define OM_SIZEOF_INDEX_PAGE (SIZEOF_SYSTEM_PAGE << LOG_BIT_SIZEOF_LONG)
+
+#define omGetPageShiftOfAddr(addr) \
+  ((((unsigned long) addr) & (OM_SIZEOF_INDEX_PAGE -1)) >> LOG_BIT_SIZEOF_SYSTEM_PAGE)
+
+#define omGetPageIndexOfAddr(addr) \
+  (((unsigned long) addr) >> (LOG_BIT_SIZEOF_LONG + LOG_BIT_SIZEOF_SYSTEM_PAGE))
+
+
+#if defined(OM_INLINE) || defined(OM_INTERNAL_DEBUG)
+#define omIsBinPageAddr(addr) _omIsBinPageAddr(addr)
+#else
+/* let's hope the compiler can eliminate common subexpressions well */      \
+#define omIsBinPageAddr(addr)                                               \
+  ((omGetPageIndexOfAddr(addr) >= om_MinBinPageIndex) &&                    \
+   (omGetPageIndexOfAddr(addr) <= om_MaxBinPageIndex) &&                    \
+   (om_BinPageIndicies[omGetPageIndexOfAddr(addr) - om_MinBinPageIndex] &   \
+    (1 << omGetPageShiftOfAddr(addr))))
+#endif
+
+/*BEGINPRIVATE*/
+/*******************************************************************
+ *  
+ * Alloc/Free of BinPages
+ *  
+ *******************************************************************/
+extern omBinPage omAllocBinPages(int how_many);
+extern omBinPage omAllocBinPage();
+
+extern void omFreeBinPages(omBinPage page, int how_many);
+#define omFreeBinPage(addr) omFreeBinPages(addr, 1)
+/*ENDPRIVATE*/
+
+#endif /* OM_BIN_PAGE_H */
+
Index: omalloc/omConfig.h
===================================================================
--- omalloc/omConfig.h	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
+++ omalloc/omConfig.h	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
@@ -0,0 +1,175 @@
+/* omConfig.h.  Generated automatically by configure.  */
+/* -*-c++-*- */
+/*******************************************************************
+ *  File:    omConfig.h.in
+ *  Purpose: configuration for omalloc  
+ *  Author:  obachman (Olaf Bachmann)
+ *  Created: 11/99
+ *  Version: $Id: omConfig.h,v 1.1 2000-08-14 12:18:27 obachman Exp $
+ *******************************************************************/
+#ifndef OM_CONFIG_H
+#define OM_CONFIG_H
+
+/*******************************************************************
+ * Defines which are set by configure
+ ******************************************************************/
+/* define if you provide an external config file to be included
+   by omDefaultConfig.h */
+#ifndef OM_HAVE_EXTERNAL_CONFIG_H
+#define OM_HAVE_EXTERNAL_CONFIG_H
+#endif
+/* define if you can inline */
+#ifndef OM_INLINE
+#define OM_INLINE static inline
+#endif
+/* define for inline decl in headers */
+#ifndef OM_INLINE_DECL
+#define OM_INLINE_DECL static inline
+#endif
+/* define for inline implementation in Include*/
+#ifndef OM_INLINE_IMPL
+#define OM_INLINE_IMPL static inline
+#endif
+/* define for local inline */
+#ifndef OM_INLINE_LOCAL
+#define OM_INLINE_LOCAL static inline
+#endif
+/* defint to nothing if you do not understand const */
+#ifndef const
+/* #undef const */
+#endif
+/* define to the name of addr2line program, undef otherwise */
+#ifndef OM_PROG_ADDR2LINE
+#define OM_PROG_ADDR2LINE "addr2line"
+#endif
+/* define to the name of nm program, undef otherwise */
+#ifndef OM_PROG_NM
+#define OM_PROG_NM "nm"
+#endif
+/* define if you have popen */
+#ifndef HAVE_POPEN
+#define HAVE_POPEN 1
+#endif
+/* define if you have readlink */
+#ifndef HAVE_READLINK
+#define HAVE_READLINK 1
+#endif
+/* define if you have sbrk */
+#ifndef HAVE_SBRK
+#define HAVE_SBRK 1
+#endif
+/* define if you have getcwd */
+#ifndef HAVE_GETCWD
+#define HAVE_GETCWD 1
+#endif
+/* define if you have getwd */
+#ifndef HAVE_GETWD
+#define HAVE_GETWD 1
+#endif
+/* define if you have a working mmap */
+#ifndef HAVE_WORKING_MMAP
+#define HAVE_WORKING_MMAP 1
+#endif
+/* define if you have STDC_HEADERS */
+#ifndef STDC_HEADERS
+#define STDC_HEADERS 1
+#endif
+/* define if you have unistd.h */
+#ifndef HAVE_UNISTD_H
+#define HAVE_UNISTD_H 1
+#endif
+/* define if you have fcntl.h */
+#ifndef HAVE_FCNTL_H
+#define HAVE_FCNTL_H
+#endif
+/* define if you have sys/mman.h */
+#ifndef HAVE_SYS_MMAN_H
+#define HAVE_SYS_MMAN_H
+#endif
+/* define if GET_RETURN_ADDR works */
+#ifndef OM_GET_RETURN_ADDR_WORK
+#define OM_GET_RETURN_ADDR_WORKS 1
+#endif
+/* define if GET_RETURN_ADDR works */
+#ifndef OM_GET_BACKTRACE_WORK
+#define OM_GET_BACKTRACE_WORKS 1
+#endif
+/* Define sizeof(long) */
+#ifndef SIZEOF_LONG
+#define SIZEOF_LONG 4
+#endif
+/* Define sizeof(double) */
+#ifndef SIZEOF_DOUBLE
+#define SIZEOF_DOUBLE 8
+#endif
+/* Define sizeof(size_t) */
+#ifndef SIZEOF_SIZE_T
+#define SIZEOF_SIZE_T 4
+#endif
+#ifndef SIZEOF_SYSTEM_PAGE
+/* Define pagesize of your system */
+#define SIZEOF_SYSTEM_PAGE 4096
+#endif
+#ifndef SIZEOF_OM_PAGE
+/* size of page as we can use it */
+#define SIZEOF_OM_PAGE SIZEOF_SYSTEM_PAGE
+#endif
+/* define if you want to use mmap for valloc */
+#ifndef OM_HAVE_VALLOC_MMAP
+#define OM_HAVE_VALLOC_MMAP 1
+#endif
+/* define if you want to use malloc-provided valloc */
+#ifndef HAVE_VALLOC_MALLOC
+/* #undef OM_HAVE_VALLOC_MALLOC */
+#endif
+#ifndef OM_MALLOC_PROVIDES_SIZEOF_ADDR
+/* define if your malloc provides a working OM_MALLOC_SIZEOF_ADDR */
+#define OM_MALLOC_PROVIDES_SIZEOF_ADDR 1
+#endif
+#ifndef OM_EMULATE_OMALLOC
+/* define if you only want to emulate omalloc, but not actually use it */
+/* #undef OM_EMULATE_OMALLOC */
+#endif
+#ifndef OM_ALIGN_8
+/* define if you want your memory to be 8-aligned */
+/* #undef OM_ALIGN_8 */
+#endif
+#ifndef OM_ALIGNMENT_NEEDS_WORK
+/* define if you insist on AllocAligned returnes 8-aligned */
+/* #undef OM_ALIGNMENT_NEEDS_WORK */
+#endif
+/* define if you want to have a dense distribution of bins */
+#ifndef OM_HAVE_DENSE_BIN_DISTRIBUTION
+/* #undef OM_HAVE_DENSE_BIN_DISTRIBUTION */
+#endif
+/* define to disable all debugging stuff */
+#ifndef OM_NDEBUG
+/* #undef OM_NDEBUG */
+#endif
+/* define to enable debug tracking */
+#ifndef OM_HAVE_TRACK
+#define OM_HAVE_TRACK 1
+#endif
+/* define to enable tracking of files/line numbers */
+#ifndef OM_TRACK_FILE_LINE
+/* #undef OM_TRACK_FILE_LINE */
+#endif
+/* define to enable tracking of return addresses */
+#ifndef OM_TRACK_RETURN
+#define OM_TRACK_RETURN 1
+#endif
+/* define to enable tracking of stack backtraces */
+#ifndef OM_TRACK_BACKTRACE
+#define OM_TRACK_BACKTRACE 1
+#endif
+/* define to enable internal debugging */
+#ifndef OM_INTERNAL_DEBUG
+/* #undef OM_INTERNAL_DEBUG */
+#endif
+/* define to -1/0/1/2/3 if you want omalloc to provide 
+   "underlying malloc"/no/normal/debug ANSI-C conforming  
+   malloc/calloc/realloc/free funcs */
+#ifndef OM_PROVIDE_MALLOC
+#define OM_PROVIDE_MALLOC 0
+#endif
+#endif /* OM_CONFIG_H  */
Index: omalloc/omDebugCheck.c
===================================================================
--- omalloc/omDebugCheck.c	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
+++ omalloc/omDebugCheck.c	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
@@ -0,0 +1,564 @@
+/*******************************************************************
+ *  File:    omDebugCheck.c
+ *  Purpose: implementation of omCheck functions
+ *  Author:  obachman@mathematik.uni-kl.de (Olaf Bachmann)
+ *  Created: 11/99
+ *  Version: $Id: omDebugCheck.c,v 1.1 2000-08-14 12:18:27 obachman Exp $
+ *******************************************************************/
+#include <limits.h>
+#include <stdarg.h>
+
+#include "omAlloc.h"
+#include "omDebug.h"
+
+#ifndef OM_NDEBUG
+/*******************************************************************
+ *  
+ *   Declarations: Static function
+ *  
+ *******************************************************************/
+unsigned long om_MaxAddr = 0;
+unsigned long om_MinAddr = ULONG_MAX;
+static omError_t omDoCheckLargeAddr(void* addr, void* bin_size, omTrackFlags_t flags, char level,
+                                    omError_t report, OM_FLR_DECL);
+omError_t omDoCheckBin(omBin bin, int normal_bin, char level, 
+                       omError_t report, OM_FLR_DECL);
+static omError_t omDoCheckBinPage(omBinPage page, int normal_page, int level, 
+                                  omError_t report, OM_FLR_DECL);
+static void omPrintAddrInfo(FILE* fd, omError_t error, void* addr, void* bin_size, omTrackFlags_t flags, char* s);
+
+
+/*******************************************************************
+ *  
+ * First level omCheck routines: dispatch to lower-level omDoCheck 
+ * routines which do the actual tests
+ *  
+ *******************************************************************/
+omError_t _omCheckAddr(void* addr, void* size_bin, 
+                       omTrackFlags_t flags, char check, omError_t report, OM_FLR_DECL)
+{
+  if (check <= 0) return omError_NoError;
+  if (check > 1)
+  {
+    omCheckReturn(check > 2 && _omCheckMemory(check - 2, (report ? report : omError_MemoryCorrupted), OM_FLR_VAL));
+    omCheckReturn(omIsBinPageAddr(addr) && omDoCheckBin(omGetBinOfAddr(addr), !omIsBinAddrTrackAddr(addr), check-1, 
+                                                        (report ? report : omError_MemoryCorrupted), OM_FLR_VAL));
+  }
+  return omDoCheckAddr(addr, size_bin, flags, check, report, OM_FLR_VAL);
+}
+
+omError_t _omCheckBin(omBin bin, int what_bin, char check, omError_t report, OM_FLR_DECL)
+{
+  if (check <= 0) return omError_NoError;
+
+  omCheckReturn(check > 1 && _omCheckMemory(check - 1, (report ? report : omError_MemoryCorrupted), OM_FLR_VAL));
+
+  return omDoCheckBin(bin, what_bin, check, report, OM_FLR_VAL);
+}
+
+omError_t _omCheckMemory(char check, omError_t report, OM_FLR_DECL)
+{
+  int i = 0;
+  omSpecBin s_bin;
+  
+  if (check <= 0) return omError_NoError;
+  
+  omCheckReturn(omCheckBinPageRegions(check, report, OM_FLR_VAL));
+  
+  for (i=0; i<= OM_MAX_BIN_INDEX; i++)
+  {
+    omCheckReturn(omDoCheckBin(&om_StaticBin[i], 1, check, report, OM_FLR_VAL));
+  }
+
+  s_bin = om_SpecBin;
+  omCheckReturn(omCheckGList(s_bin, next, check, omError_MemoryCorrupted, OM_FLR_VAL));
+  while (s_bin != NULL)
+  {
+    omCheckReturn(omDoCheckBin(s_bin->bin, 1, check, report, OM_FLR_VAL));
+    s_bin = s_bin->next;
+  }
+
+#ifdef OM_HAVE_TRACK
+  for (i=0; i<= OM_MAX_BIN_INDEX; i++)
+  {
+    omCheckReturn(omDoCheckBin(&om_StaticTrackBin[i], 0, check, report, OM_FLR_VAL));
+  }
+  s_bin = om_SpecTrackBin;
+  omCheckReturn(omCheckGList(s_bin, next, check, omError_MemoryCorrupted, OM_FLR_VAL));
+  while (s_bin != NULL)
+  {
+    omCheckReturn(omDoCheckBin(s_bin->bin, 0, check, report, OM_FLR_VAL));
+    s_bin = s_bin->next;
+  }
+#endif
+  
+  if (check > 1 && om_KeptAddr != NULL)
+  {
+    void* addr = om_KeptAddr;
+    omCheckReturn(omCheckList(om_KeptAddr, check, (report ? report :  omError_KeptAddrListCorrupted), OM_FLR_VAL));
+    while (addr != NULL)
+    {
+      omCheckReturn(omDoCheckAddr(addr, NULL, OM_FKEPT, check, report, OM_FLR_VAL));
+      addr = *((void**) addr);
+    }
+  }
+  return omError_NoError;
+}
+
+/*******************************************************************
+ *  
+ * Second level omCheck routines: do the actual checks
+ *  
+ *******************************************************************/
+
+omError_t omCheckPtr(void* ptr, omError_t report, OM_FLR_DECL)
+{
+  omCheckReturnError(ptr == NULL, omError_NullAddr);
+  omCheckReturnError(!OM_IS_ALIGNED(ptr), omError_UnalignedAddr);
+  omCheckReturnError(((unsigned long) ptr) < om_MinAddr || 
+                     ((unsigned long) ptr) >= om_MaxAddr, omError_InvalidRangeAddr);
+  return omError_NoError;
+}
+  
+
+omError_t omDoCheckAddr(void* addr, void* bin_size, omTrackFlags_t flags, char level, 
+                        omError_t report, OM_FLR_DECL)
+{
+  omAssume(! ((flags & OM_FSIZE) && (flags & OM_FBIN)));
+
+  if (addr == NULL)
+  {
+    omCheckReturnError(!(flags & OM_FSLOPPY), omError_NullAddr);
+    return omError_NoError;
+  }
+  if ((flags & OM_FSIZE) && bin_size == NULL) return omError_NoError;
+  omAddrCheckReturn(omCheckPtr(addr, report, OM_FLR_VAL));
+  omAddrCheckReturnError((flags & OM_FALIGN) &&  !OM_IS_STRICT_ALIGNED(addr), omError_UnalignedAddr);
+  omAddrCheckReturnError((flags & OM_FBIN) && ! omIsKnownTopBin((omBin) bin_size, 1), omError_UnknownBin);
+  
+  if (omIsBinPageAddr(addr))
+  {
+#ifdef OM_HAVE_TRACK
+    if (omIsBinAddrTrackAddr(addr))
+      return omCheckTrackAddr(addr, bin_size, flags, level, report, OM_FLR_VAL);
+    else
+#endif
+      return omDoCheckBinAddr(addr, bin_size, flags, level, report, OM_FLR_VAL);
+  }
+  else
+  {
+    return omDoCheckLargeAddr(addr, bin_size, flags, level, report, OM_FLR_VAL);
+  }
+}
+
+static int omIsInKeptAddrList(void* addr)
+{
+  void* ptr = om_KeptAddr;
+  
+  while (ptr != NULL)
+  {
+    if (ptr == addr) return 1;
+    if ((unsigned long) addr > (unsigned long)ptr && 
+        (unsigned long) addr < (unsigned long) ptr + omSizeOfAddr(ptr))
+      return 1;
+    ptr = *((void**) ptr);
+  }
+  return 0;
+}
+
+
+static omError_t omDoCheckLargeAddr(void* addr, void* bin_size, omTrackFlags_t flags, char level, 
+                                    omError_t report, OM_FLR_DECL)
+{
+  size_t r_size;
+  
+  omAssume(! omIsBinPageAddr(addr));
+  omAssume(! omCheckPtr(addr, omError_NoError, OM_FLR));
+  
+  omAddrCheckReturnError(flags & OM_FBIN, omError_WrongBin);
+  omAddrCheckReturnError(level > 1 && omFindRegionOfAddr(addr) != NULL, omError_FreedAddrOrMemoryCorrupted);
+  r_size = omSizeOfLargeAddr(addr);
+  omAddrCheckReturnError(! OM_IS_ALIGNED(r_size), omError_FalseAddrOrMemoryCorrupted);
+  omAddrCheckReturnError(r_size <= OM_MAX_BLOCK_SIZE, omError_FalseAddrOrMemoryCorrupted);
+  omAddrCheckReturnError((flags & OM_FSIZE) && r_size < OM_ALIGN_SIZE((size_t) bin_size),
+                         omError_WrongSize);
+  omAddrCheckReturnError((level > 1) && (flags & OM_FUSED) && omIsInKeptAddrList(addr), omError_FreedAddr);
+  return omError_NoError;
+}
+
+omError_t omDoCheckBinAddr(void* addr, void* bin_size, omTrackFlags_t flags, char level, 
+                           omError_t report, OM_FLR_DECL)
+{
+  omBinPage page = omGetBinPageOfAddr(addr);
+  omBinPageRegion region = page->region;
+  omBin bin = omGetBinOfPage(page);
+  
+  omAssume(omIsBinPageAddr(addr));
+  omAssume(! omCheckPtr(addr, 0, OM_FLR));
+  
+  omAddrCheckReturnCorrupted(! omIsKnownTopBin(bin, ! omIsBinAddrTrackAddr(addr)));
+
+  if (level > 1)
+  {
+    omAddrCheckReturnError(omIsAddrOnFreeBinPage(addr), omError_FreedAddr);
+    omAddrCheckReturnError(omFindRegionOfAddr(addr) != region, omError_FreedAddrOrMemoryCorrupted);
+    omAddrCheckReturnError(!omIsOnGList(bin->last_page, prev, page), omError_FreedAddrOrMemoryCorrupted);
+
+    if (flags & OM_FUSED)
+    {
+      omAddrCheckReturnError(omIsOnList(page->current, addr), omError_FreedAddr);
+      omAddrCheckReturnError((level > 1) && omIsInKeptAddrList(addr), omError_FreedAddr);
+    }
+  }
+  else
+  {
+    omAddrCheckReturnError(omCheckPtr(region, omError_MaxError, OM_FLR_VAL), omError_FreedAddrOrMemoryCorrupted);
+  }
+  
+  
+  /* Check that addr is aligned within page of bin */
+  omAddrCheckReturnError((bin->max_blocks >= 1) &&
+                         ( ( ( (unsigned long) addr) 
+                             - ((unsigned long) page) 
+                             - SIZEOF_OM_BIN_PAGE_HEADER) 
+                           % (bin->sizeW * SIZEOF_VOIDP)
+                           != 0), omError_FalseAddr);
+
+  /* Check that specified bin or size is correct */
+  omAddrCheckReturnError((flags & OM_FBIN) 
+                         && ((omBin) bin_size) != omGetTopBinOfAddr(addr), omError_WrongBin);
+
+  if (flags & OM_FSIZE && (!(flags & OM_FSLOPPY)  || (size_t) bin_size > 0))
+  {
+    size_t size = (size_t) bin_size;
+    omAssume(!omIsBinAddrTrackAddr(addr));
+    omAddrCheckReturnError((bin->sizeW << LOG_SIZEOF_LONG) < OM_ALIGN_SIZE(size), omError_WrongSize);
+  }
+
+  return omError_NoError;
+}
+
+omError_t omDoCheckBin(omBin bin, int normal_bin, char level, 
+                       omError_t report, OM_FLR_DECL)
+{
+  omBin top_bin = bin;
+  
+  omCheckReturnError(!omIsKnownTopBin(bin, normal_bin), omError_UnknownBin);
+  omCheckReturn(omCheckGList(bin->next, next, level, report, OM_FLR_VAL));
+  
+  do
+  {
+    int where;
+    omBinPage page;
+
+    if (bin->last_page == NULL || bin->current_page == om_ZeroPage)
+    {
+      omCheckReturnCorrupted(! (bin->current_page == om_ZeroPage && bin->last_page == NULL));
+      continue;
+    }
+    omCheckReturn(omDoCheckBinPage(bin->current_page, normal_bin, level, report, OM_FLR_VAL));
+    omCheckReturn(bin->current_page != bin->last_page  && 
+                  omDoCheckBinPage(bin->last_page, normal_bin, level, report, OM_FLR_VAL));
+    omCheckReturnCorrupted(bin->last_page->next != NULL);
+
+    if (bin != top_bin)
+    {
+      omCheckReturnCorrupted(bin->sizeW != top_bin->sizeW ||
+                             bin->max_blocks != top_bin->max_blocks);
+    }
+    if (level <= 1) continue;
+    
+    omCheckReturnCorrupted(omFindInGList(bin->next, next, sticky, bin->sticky));
+    omCheckReturn(omCheckGList(bin->last_page, prev, level-1, report, OM_FLR_VAL));
+    page = omGListLast(bin->last_page, prev);
+    omCheckReturn(omCheckGList(page, next, level-1, report, OM_FLR_VAL));
+    omCheckReturnCorrupted(omGListLength(bin->last_page, prev) != omGListLength(page, next));
+    
+    omCheckReturnCorrupted(! omIsOnGList(bin->last_page, prev, bin->current_page));
+    
+    page = bin->last_page;
+    where = 1;
+    while (page != NULL)
+    {
+      omCheckReturnCorrupted(omGetTopBinOfPage(page) != top_bin);
+      omCheckReturn(page != bin->last_page && page != bin->current_page &&
+                    omDoCheckBinPage(page, normal_bin, level - 1, report, OM_FLR_VAL));
+
+      omCheckReturnCorrupted(page != bin->last_page && 
+                             (page->next == NULL || page->next->prev != page));
+      omCheckReturnCorrupted(page->prev != NULL && page->prev->next != page);
+      
+      omCheckReturnCorrupted(omGetStickyOfPage(page) != bin->sticky);
+      omCheckReturnCorrupted(omGetBinOfPage(page) != bin);
+      
+      if (! bin->sticky)
+      {
+        if (where == -1)
+        {
+          /* we are at the left of current_page,
+             i.e., page is empty */
+          omCheckReturnCorrupted(omGetUsedBlocksOfPage(page) != 0 || page->current != NULL);
+        }
+        else
+        {
+          if (page == bin->current_page)
+          {
+            where = -1;
+          }
+          else
+          {
+            /* we are at the right of current_page, 
+               i.e., page is neither full nor empty */
+            omCheckReturnCorrupted(page->current == NULL ||
+                                   omGetUsedBlocksOfPage(page) == bin->max_blocks - 1);
+          }
+        }
+      }
+      page = page->prev;
+    }   /* while (page != NULL) */
+  } while ((bin = bin->next) != NULL);
+  
+  return omError_NoError;
+}
+  
+int omIsKnownTopBin(omBin bin, int normal_bin)
+{
+  omBin to_check;
+  omSpecBin s_bin;
+  int i;
+  
+  omAssume(normal_bin == 1 || normal_bin == 0);
+  
+#ifdef OM_HAVE_TRACK
+  if (! normal_bin) 
+  {
+    to_check = om_StaticTrackBin;
+    s_bin = om_SpecTrackBin;
+  }
+  else 
+#endif
+  {
+    omAssume(normal_bin);
+    to_check = om_StaticBin;
+    s_bin = om_SpecBin;
+  }
+
+  for (i=0; i<= OM_MAX_BIN_INDEX; i++)
+  {
+    if (bin == &(to_check[i])) 
+      return 1;
+  }
+  
+  while (s_bin != NULL)
+  {
+    if (bin == s_bin->bin) return 1;
+    s_bin = s_bin->next;
+  }
+  return 0;
+}
+
+static omError_t omDoCheckBinPage(omBinPage page, int normal_page, int level, 
+                                  omError_t report, OM_FLR_DECL)
+{
+  omBin bin;
+  
+  omCheckReturn(omCheckPtr(page, report, OM_FLR_VAL));
+  omCheckReturnCorrupted(! omIsAddrPageAligned(page));
+
+  omCheckReturn(omCheckPtr(page->region, report, OM_FLR_VAL));
+  omCheckReturnCorrupted(level > 1 && omFindRegionOfAddr(page) != page->region);
+
+  
+#ifdef OM_HAVE_TRACK
+  if (! normal_page)
+  {
+    omCheckReturnCorrupted(! omIsSetTrackOfUsedBlocks(page->used_blocks));
+  }
+  else
+#endif
+    omAssume(normal_page);
+  
+  bin = omGetTopBinOfPage(page);
+  if (bin->max_blocks > 1)
+  {
+    omCheckReturnCorrupted(omGetUsedBlocksOfPage(page) > bin->max_blocks - 1);
+    omCheckReturnCorrupted(omGetUsedBlocksOfPage(page) == bin->max_blocks - 1 && 
+                           page->current != NULL);
+    omCheckReturnCorrupted(omGetUsedBlocksOfPage(page) < 0);
+  }
+  else
+  {
+    omCheckReturnCorrupted(omGetUsedBlocksOfPage(page) != 0);
+  }
+  
+  omCheckReturn(omCheckList(page->current, level, report, OM_FLR_VAL));
+
+  if (level > 1)
+  {
+    void* current = page->current;
+
+    omCheckReturnCorrupted(current != NULL &&
+                           omListLength(current) != bin->max_blocks - omGetUsedBlocksOfPage(page) - 1);
+    
+    while (current != NULL)
+    {
+      omCheckReturnCorrupted(omGetPageOfAddr(current) != page);
+      
+      omCheckReturnCorrupted( ( ( (unsigned long) current) 
+                                - ((unsigned long) page) 
+                                - SIZEOF_OM_BIN_PAGE_HEADER) 
+                              % (bin->sizeW * SIZEOF_LONG)
+                              != 0);
+      current = *((void**) current);
+    }
+  }
+  return omError_NoError;
+}
+
+omError_t omReportAddrError(omError_t error, omError_t report_error, void* addr, void* bin_size, omTrackFlags_t flags, 
+                            OM_FLR_DECL, const char* fmt, ...) 
+{
+  va_list ap;
+  va_start(ap, fmt);
+  omReportError(error, report_error, OM_FLR_VAL, fmt, ap);
+  
+  omPrintAddrInfo(stderr, error, addr, bin_size, flags, " occured for");
+  return om_ErrorStatus;
+}
+
+void omPrintAddrInfo(FILE* fd, omError_t error, void* addr, void* bin_size, omTrackFlags_t flags, char* s)
+{
+  if (! omCheckPtr(addr, omError_MaxError, OM_FLR))
+  {
+    fprintf(fd, "%s addr:%p size:%d", s, addr, omSizeOfAddr(addr));
+  
+  if (error == omError_WrongSize && (flags & OM_FSIZE))
+    fprintf(fd, " specified size:%d", (size_t) bin_size);
+  
+  if (error == omError_WrongBin && (flags & OM_FBIN))
+    fprintf(fd, " specified bin is of size:%d", ((omBin) bin_size)->sizeW << LOG_SIZEOF_LONG);
+  
+  if (omIsTrackAddr(addr)) 
+    omPrintTrackAddrInfo(fd, addr);
+  else
+    fprintf(fd, "\n");
+  }
+  else
+  {
+    fprintf(fd, "%s (invalid) addr: %p\n", s, addr);
+  }
+}
+
+/*******************************************************************
+ *  
+ * Misc for iterating, etc.
+ *  
+ *******************************************************************/
+
+void omIterateTroughBinAddrs(omBin bin, void (*CallBackUsed)(void*), void (*CallBackFree)(void*))
+{
+  omBinPage page;
+  void* addr;
+  void* is_free;
+  int i;
+  
+  do
+  {
+    page = bin->last_page;
+    while (page != NULL)
+    {
+      addr = (void*) page + SIZEOF_OM_BIN_PAGE_HEADER;
+      i = 0;
+      do
+      {
+        is_free = omIsOnList(page->current, addr);
+        if (is_free)
+        {
+          if (CallBackFree != NULL) CallBackFree(addr);
+        }
+        else 
+        {
+          if (CallBackUsed != NULL) CallBackUsed(addr);
+        }
+        addr = (void**) addr + bin->sizeW;
+        i++;
+      } while (i < bin->max_blocks);
+      page = page->prev;
+    }
+    bin = bin->next;
+  } while (bin != NULL);
+  
+}
+
+void omIterateTroughAddrs(int normal, int track, void (*CallBackUsed)(void*), void (*CallBackFree)(void*))
+{
+  int i;
+  omSpecBin s_bin;
+
+  if (normal)
+  {
+    for (i=0; i<=OM_MAX_BIN_INDEX; i++)
+    {
+      omIterateTroughBinAddrs(&om_StaticBin[i], CallBackUsed, CallBackFree);
+    }
+    s_bin = om_SpecBin;
+    while (s_bin != NULL)
+    {
+      omIterateTroughBinAddrs(s_bin->bin, CallBackUsed, CallBackFree);
+      s_bin = s_bin->next;
+    }
+  }
+  
+#ifdef OM_HAVE_TRACK
+  if (track)
+  {
+    for (i=0; i<=OM_MAX_BIN_INDEX; i++)
+    {
+      omIterateTroughBinAddrs(&om_StaticTrackBin[i], CallBackUsed, CallBackFree);
+    }
+    s_bin = om_SpecTrackBin;
+    while (s_bin != NULL)
+    {
+      omIterateTroughBinAddrs(s_bin->bin, CallBackUsed, CallBackFree);
+      s_bin = s_bin->next;
+    }
+  }
+#endif
+}
+
+static FILE* om_print_used_addr_fd;
+static size_t om_total_used_size;
+static unsigned int om_total_used_blocks;
+
+static void _omPrintUsedAddr(void* addr)
+{
+  if (!omIsTrackAddr(addr) || !omIsStaticTrackAddr(addr))
+  {
+    om_total_used_blocks++;
+    om_total_used_size += omSizeOfAddr(addr);
+    omPrintAddrInfo(om_print_used_addr_fd, omError_NoError, addr, NULL, 0, "");
+    fprintf(om_print_used_addr_fd, "\n");
+  }
+}
+
+void omPrintUsedAddrs(FILE* fd)
+{
+  om_total_used_size = 0;
+  om_total_used_blocks = 0;
+  om_print_used_addr_fd = (fd == NULL ? stdout : fd);
+  omIterateTroughAddrs(1, 1, _omPrintUsedAddr, NULL);
+  fprintf(fd, "UsedAddrs Summary: UsedBlocks:%d  TotalSize:%d\n", 
+          om_total_used_blocks, om_total_used_size);
+}
+
+void omPrintUsedTrackAddrs(FILE* fd)
+{
+  om_total_used_size = 0;
+  om_total_used_blocks = 0;
+  om_print_used_addr_fd = (fd == NULL ? stdout : fd);
+  omIterateTroughAddrs(0, 1 ,  _omPrintUsedAddr, NULL);
+  fprintf(fd, "UsedTrackAddrs Summary: UsedBlocks:%d  TotalSize:%d\n", 
+          om_total_used_blocks, om_total_used_size);
+}
+
+#endif /* ! OM_NDEBUG */
Index: omalloc/omDebugTrack.c
===================================================================
--- omalloc/omDebugTrack.c	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
+++ omalloc/omDebugTrack.c	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
@@ -0,0 +1,644 @@
+/*******************************************************************
+ *  File:    omDebug.c
+ *  Purpose: implementation of main omDebug functions
+ *  Author:  obachman@mathematik.uni-kl.de (Olaf Bachmann)
+ *  Created: 11/99
+ *  Version: $Id: omDebugTrack.c,v 1.1 2000-08-14 12:18:28 obachman Exp $
+ *******************************************************************/
+#include <limits.h>
+#include "omConfig.h"
+#include "omDerivedConfig.h"
+
+#ifdef OM_HAVE_TRACK
+#include "omDefaultConfig.h"
+#include "omAlloc.h"
+
+/*******************************************************************
+ *  
+ * Declarations
+ *  
+ *******************************************************************/
+omBinPage om_JustFreedPage = NULL;
+omSpecBin om_SpecTrackBin = NULL;
+
+/* number of bytes for padding before addr: needs to > 0 and a multiple of OM_SIZEOF_STRICT_ALIGNMENT */
+#ifndef OM_MIN_SIZEOF_FRONT_PATTERN
+#define OM_MIN_SIZEOF_FRONT_PATTERN (OM_MIN_SIZEWOF_FRONT_PATTERN*SIZEOF_STRICT_ALIGNMENT)
+#endif
+/* number of bytes for padding after addr: needs to be a multiple of OM_SIZEOF_STRICT_ALIGNMENT */ 
+#ifndef OM_MIN_SIZEOF_BACK_PATTERN
+#define OM_MIN_SIZEOF_BACK_PATTERN (OM_MIN_SIZEWOF_BACK_PATTERN*SIZEOF_STRICT_ALIGNMENT)
+#endif
+
+struct omTrackAddr_s;
+typedef struct omTrackAddr_s omTrackAddr_t;
+typedef omTrackAddr_t * omTrackAddr;
+struct omTrackAddr_s
+{
+  void*             next;   /* reserved for page->current queue */
+  char              track;  /* > 0; determines size of header */
+  omTrackFlags_t    flags;
+    #ifdef OM_TRACK_FILE_LINE     
+  short             alloc_line; 
+  const char*       alloc_file;
+    #endif
+    #ifdef OM_TRACK_RETURN
+  const void*       alloc_r;
+    #endif
+    #ifdef OM_TRACK_BACKTRACE
+      #define OM_TRACK_ADDR_MEM_1 alloc_frames
+
+  /* track > 1 */
+  void*             alloc_frames[OM_MAX_KEPT_FRAMES];
+    #else
+      #define OM_TRACK_ADDR_MEM_1 bin_size
+    #endif
+    #define OM_TRACK_ADDR_MEM_2 bin_size
+
+  /* track > 2 */
+  void*             bin_size;
+    #ifdef OM_TRACK_FILE_LINE 
+      #define OM_TRACK_ADDR_MEM_3 free_line
+
+  /* track > 3 */
+  short             free_line;
+  const char*       free_file;
+    #endif
+    #ifdef OM_TRACK_RETURN
+       #ifndef OM_TRACK_ADDR_MEM_3 
+       #define OM_TRACK_ADDR_MEM_3 free_r
+       #endif
+  const void*       free_r;
+    #endif
+    #ifdef OM_TRACK_BACKTRACE
+      #define OM_TRACK_ADDR_MEM_4 free_frames
+
+  /* track > 4 */
+  void*             free_frames[OM_MAX_KEPT_FRAMES];
+    #endif
+};
+
+static omError_t omDoCheckTrackAddr(omTrackAddr d_addr, void* addr, void* bin_size, omTrackFlags_t flags, char level, 
+                                    omError_t report_error, OM_FLR_DECL);
+static int omCheckFlags(omTrackFlags_t flag);
+static int omCheckPattern(char* s, char p, size_t size);
+
+#define OM_TRACK_MAX 5
+static struct omTrackAddr_s track_addr; /* this is only needed to determine OM_SIZEOF_TRACK_ADDR(i) */
+#if 0
+#define OM_SIZEOF_TRACK_ADDR_1  OM_STRICT_ALIGN_SIZE(((void*)&track_addr.alloc_frames-(void*)&track_addr))
+#define OM_SIZEOF_TRACK_ADDR_2  OM_STRICT_ALIGN_SIZE(((void*)&track_addr.bin_size-(void*)&track_addr))
+#define OM_SIZEOF_TRACK_ADDR_3  OM_STRICT_ALIGN_SIZE(((void*)&track_addr.free_line-(void*)&track_addr)+OM_MIN_SIZEOF_FRONT_PATTERN)
+#define OM_SIZEOF_TRACK_ADDR_4  OM_STRICT_ALIGN_SIZE(((void*)&track_addr.free_frames-(void*)&track_addr)+OM_MIN_SIZEOF_FRONT_PATTERN)
+#define OM_SIZEOF_TRACK_ADDR_5  OM_STRICT_ALIGN_SIZE(sizeof(struct omTrackAddr_s)+OM_MIN_SIZEOF_FRONT_PATTERN)
+#endif
+
+#define OM_SIZEOF_TRACK_ADDR_1  OM_STRICT_ALIGN_SIZE(((void*)&track_addr.OM_TRACK_ADDR_MEM_1-(void*)&track_addr))
+#define OM_SIZEOF_TRACK_ADDR_2  OM_STRICT_ALIGN_SIZE(((void*)&track_addr.OM_TRACK_ADDR_MEM_2-(void*)&track_addr))
+#define OM_SIZEOF_TRACK_ADDR_3  OM_STRICT_ALIGN_SIZE(((void*)&track_addr.OM_TRACK_ADDR_MEM_3-(void*)&track_addr)+OM_MIN_SIZEOF_FRONT_PATTERN)
+#ifdef OM_TRACK_ADDR_MEM_4
+#define OM_SIZEOF_TRACK_ADDR_4  OM_STRICT_ALIGN_SIZE(((void*)&track_addr.OM_TRACK_ADDR_MEM_4-(void*)&track_addr)+OM_MIN_SIZEOF_FRONT_PATTERN)
+#else
+#define OM_SIZEOF_TRACK_ADDR_4 OM_SIZEOF_TRACK_ADDR_5
+#endif
+#define OM_SIZEOF_TRACK_ADDR_5  OM_STRICT_ALIGN_SIZE(sizeof(struct omTrackAddr_s)+OM_MIN_SIZEOF_FRONT_PATTERN)
+
+#define OM_SIZEOF_TRACK_ADDR(i)                                                                     \
+(i > 3 ?                                                                                            \
+ (i == 4 ? OM_SIZEOF_TRACK_ADDR_4 : OM_SIZEOF_TRACK_ADDR_5) :                                       \
+  (i == 3 ? OM_SIZEOF_TRACK_ADDR_3 :  (i == 2 ? OM_SIZEOF_TRACK_ADDR_2 : OM_SIZEOF_TRACK_ADDR_1)))
+
+OM_INLINE_LOCAL omTrackAddr omOutAddr_2_TrackAddr(void* addr);
+
+#define _omOutSize_2_TrackAddrSize(size, track)                                                     \
+  (size + OM_SIZEOF_TRACK_ADDR(track) + (track > 2 ? OM_MIN_SIZEOF_BACK_PATTERN : 0))
+
+#define _omTrackAddr_2_SizeOfTrackAddrHeader(d_addr) ((size_t) OM_SIZEOF_TRACK_ADDR(((omTrackAddr) (d_addr))->track))
+#define _omTrackAddr_2_OutSize(d_addr)                                                                      \
+  (((omTrackAddr) (d_addr))->track > 2 ?                                                                    \
+   omTrack3Addr_2_OutSize(d_addr) : omSizeOfBinAddr(d_addr) - omTrackAddr_2_SizeOfTrackAddrHeader(d_addr))
+#define _omTrack3Addr_2_OutSize(d_addr)                                         \
+  ((((omTrackAddr) (d_addr))->flags & OM_FBIN) ?                            \
+   (((omBin)((omTrackAddr) (d_addr))->bin_size)->sizeW) << LOG_SIZEOF_LONG :    \
+   ((size_t)((omTrackAddr) (d_addr))->bin_size))
+
+/* assume track > 2 */
+#define _omTrackAddr_2_FrontPattern(d_addr) \
+          ((void*)((unsigned long)d_addr + omTrackAddr_2_SizeOfTrackAddrHeader(d_addr) - OM_MIN_SIZEOF_FRONT_PATTERN))
+#define _omTrackAddr_2_SizeOfFrontPattern(d_addr) \
+  ((void*) omTrackAddr_2_OutAddr(d_addr) - (void*) omTrackAddr_2_FrontPattern(d_addr)) 
+#define _omTrackAddr_2_BackPattern(d_addr) \
+  ((void*) ((unsigned long)d_addr + omTrackAddr_2_SizeOfTrackAddrHeader(d_addr) + _omTrack3Addr_2_OutSize(d_addr)))
+#define _omTrackAddr_2_SizeOfBackPattern(d_addr) \
+  ((void*) d_addr + omSizeOfBinAddr(d_addr) - omTrackAddr_2_BackPattern(d_addr))
+#define omTrackAddr_2_OutAddr(d_addr) ((void*)((unsigned long)d_addr + omTrackAddr_2_SizeOfTrackAddrHeader(d_addr)))
+
+
+#ifdef OM_INTERNAL_DEBUG
+static size_t omTrackAddr_2_SizeOfTrackAddrHeader(omTrackAddr d_addr)
+{
+  size_t size;
+  omAssume(omIsTrackAddr(d_addr) && omOutAddr_2_TrackAddr(d_addr) == d_addr && 
+           d_addr->track > 0 && d_addr->track <= 5);
+  size = _omTrackAddr_2_SizeOfTrackAddrHeader(d_addr);
+  return size;
+}
+static void* omTrackAddr_2_FrontPattern(omTrackAddr d_addr)
+{
+  void* addr;
+  omAssume(omIsTrackAddr(d_addr) && omOutAddr_2_TrackAddr(d_addr) == d_addr && 
+           d_addr->track > 2 && d_addr->track <= 5);
+  addr = _omTrackAddr_2_FrontPattern(d_addr);
+  return addr;
+}
+static size_t omTrackAddr_2_SizeOfFrontPattern(omTrackAddr d_addr)
+{
+  size_t size;
+  omAssume(omIsTrackAddr(d_addr) && omOutAddr_2_TrackAddr(d_addr) == d_addr && 
+           d_addr->track > 2 && d_addr->track <= 5);
+  omAssume((unsigned long) omTrackAddr_2_OutAddr(d_addr) > (unsigned long) omTrackAddr_2_FrontPattern(d_addr));
+  size = _omTrackAddr_2_SizeOfFrontPattern(d_addr);
+  omAssume(size > 0);
+  return size;
+}
+static void* omTrackAddr_2_BackPattern(omTrackAddr d_addr)
+{
+  void* addr;
+  omAssume(omIsTrackAddr(d_addr) && omOutAddr_2_TrackAddr(d_addr) == d_addr && 
+           d_addr->track > 2 && d_addr->track <= 5);
+  addr = _omTrackAddr_2_BackPattern(d_addr);
+  omAssume(OM_ALIGN_SIZE((unsigned long) addr) == (unsigned long) addr);
+  return addr;
+}
+static size_t omTrackAddr_2_SizeOfBackPattern(omTrackAddr d_addr)
+{
+  size_t size;
+  omAssume(omIsTrackAddr(d_addr) && omOutAddr_2_TrackAddr(d_addr) == d_addr && 
+           d_addr->track > 2 && d_addr->track <= 5);
+  size = _omTrackAddr_2_SizeOfBackPattern(d_addr);
+  omAssume(size > 0 && OM_ALIGN_SIZE(size) == size);
+  return size;
+}
+static size_t omTrack3Addr_2_OutSize(omTrackAddr d_addr)
+{
+  size_t size;
+  omAssume(omIsTrackAddr(d_addr) && omOutAddr_2_TrackAddr(d_addr) == d_addr && 
+           d_addr->track > 2 && d_addr->track <= 5);
+  omAssume(d_addr->flags > 0 && d_addr->flags < OM_FMAX &&
+           ! ((d_addr->flags & OM_FBIN) && (d_addr->flags & OM_FSIZE)));
+  
+  size = _omTrack3Addr_2_OutSize(d_addr);
+  return size;
+}
+static size_t omTrackAddr_2_OutSize(omTrackAddr d_addr)
+{
+  size_t size;
+  omAssume(omIsTrackAddr(d_addr) && omOutAddr_2_TrackAddr(d_addr) == d_addr && 
+           d_addr->track > 0 && d_addr->track <= 5);
+  
+  size = _omTrackAddr_2_OutSize(d_addr);
+  return size;
+}
+static size_t omOutSize_2_TrackAddrSize(size_t size, char track)
+{
+  size_t da_size;
+  omAssume(track > 0 && track <= 5);
+  da_size = _omOutSize_2_TrackAddrSize(size, track);
+  return da_size;
+}
+#else
+#define omTrackAddr_2_SizeOfTrackAddrHeader _omTrackAddr_2_SizeOfTrackAddrHeader
+#define omTrackAddr_2_FrontPattern          _omTrackAddr_2_FrontPattern
+#define omTrackAddr_2_BackPattern           _omTrackAddr_2_BackPattern
+#define omTrack3Addr_2_OutSize              _omTrack3Addr_2_OutSize
+#define omTrackAddr_2_OutSize               _omTrackAddr_2_OutSize
+#define omOutSize_2_TrackAddrSize           _omOutSize_2_TrackAddrSize
+#define omTrackAddr_2_SizeOfFrontPattern     _omTrackAddr_2_SizeOfFrontPattern
+#define omTrackAddr_2_SizeOfBackPattern     _omTrackAddr_2_SizeOfBackPattern
+#endif
+
+OM_INLINE_LOCAL omTrackAddr omOutAddr_2_TrackAddr(void* addr)
+{
+  omTrackAddr d_addr;
+  void* page = omGetPageOfAddr(addr);
+  size_t size = omGetTopBinOfPage((omBinPage) page)->sizeW << LOG_SIZEOF_LONG;
+
+  omAssume(omIsBinPageAddr(addr));
+
+  page += SIZEOF_OM_BIN_PAGE_HEADER;
+  d_addr = (omTrackAddr) ((unsigned long) page + (unsigned long) ((((unsigned long)addr - (unsigned long)page) / size)*size));
+  return d_addr;
+}
+ 
+size_t omOutSizeOfTrackAddr(void* addr)
+{
+  omTrackAddr d_addr = omOutAddr_2_TrackAddr(addr);
+  omAssume(omIsTrackAddr(addr));
+  return omTrackAddr_2_OutSize(d_addr);
+}
+
+/*******************************************************************
+ *  
+ * Low level allocation/free routines: do the actual work, 
+ * no checks/tests, assume that everything in
+ * environment is ok
+ *  
+ *******************************************************************/
+
+static omTrackAddr _omAllocTrackAddr(size_t d_size)
+{
+  omTrackAddr d_addr;
+  omBin bin;
+  
+  if (d_size <= OM_MAX_BLOCK_SIZE)
+    bin = omSmallSize2TrackBin(d_size);
+  else
+    bin = omGetSpecTrackBin(d_size);
+  
+  __omTypeAllocBin(omTrackAddr, d_addr, bin);
+  
+  omAssume(bin->current_page == omGetPageOfAddr(d_addr));
+
+  omSetTrackOfUsedBlocks(bin->current_page->used_blocks);
+  
+  return d_addr;
+}
+void* omAllocTrackAddr(void* bin_size, 
+                       omTrackFlags_t flags, char track, OM_FLR_DECL)
+{
+  void* o_addr;
+  size_t o_size = (flags & OM_FBIN ? ((omBin)bin_size)->sizeW << LOG_SIZEOF_LONG : 
+                   (bin_size != NULL ? OM_ALIGN_SIZE((size_t) bin_size) : OM_ALIGN_SIZE(1)));
+  omTrackAddr d_addr;
+  size_t d_size;
+  if (track <= 0) track = 1;
+  if (track >  5) track = 5;
+  
+  if ((flags & OM_FBIN) && !omIsStaticNormalBin((omBin)bin_size))
+    /* Need to set track >= 3 such that bin_size is kept: Needed
+       for om_KeptAddr */
+    track = (track > 3 ? track : 3);
+  d_size = omOutSize_2_TrackAddrSize(o_size, track);
+    
+  d_addr = _omAllocTrackAddr(d_size);
+  d_addr->next = (void*)-1;
+  d_addr->track = track;
+  d_addr->flags = flags | OM_FUSED;
+  if (om_Opts.MarkAsStatic) 
+    d_addr->flags |= OM_FSTATIC;
+
+#ifdef OM_TRACK_FILE_LINE
+  d_addr->alloc_file = f;
+  d_addr->alloc_line = (l > SHRT_MAX || l < 0 ? 0 : l);
+#endif
+#ifdef OM_TRACK_RETURN
+  d_addr->alloc_r = r;
+#endif  
+    
+  o_addr = omTrackAddr_2_OutAddr(d_addr);
+  if (track > 1)
+  {
+#ifdef OM_INTERNAL_DEBUG 
+#define FROM_FRAMES 0
+#else
+#define FROM_FRAMES 2
+#endif
+
+#ifdef OM_TRACK_BACKTRACE
+    omGetBackTrace(d_addr->alloc_frames,  FROM_FRAMES, OM_MAX_KEPT_FRAMES);
+#endif  
+      
+    if (track > 2)
+    {
+      d_addr->bin_size = (flags & OM_FBIN ? bin_size : (void*) o_size);
+      omAssume(OM_ALIGN_SIZE((size_t)d_addr->bin_size) == (size_t) d_addr->bin_size);
+
+      memset(omTrackAddr_2_FrontPattern(d_addr), OM_FRONT_PATTERN, omTrackAddr_2_SizeOfFrontPattern(d_addr));
+      if (! (flags & OM_FZERO)) memset(o_addr, OM_INIT_PATTERN, o_size);
+      memset(omTrackAddr_2_BackPattern(d_addr), OM_BACK_PATTERN, omTrackAddr_2_SizeOfBackPattern(d_addr));
+
+      if (track > 3)
+      {
+#ifdef OM_TRACK_FILE_LINE
+        d_addr->free_line = -1;
+        d_addr->free_file = (char*) -1;
+#endif
+#ifdef OM_TRACK_RETURN
+        d_addr->free_r = (void*) -1;
+#endif        
+
+#ifdef OM_TRACK_BACKTRACE          
+        if (track > 4)
+          memset(&d_addr->free_frames, 0, OM_MAX_KEPT_FRAMES*SIZEOF_VOIDP);
+#endif
+      }
+    }
+  }
+  if (flags & OM_FZERO) omMemsetW(o_addr, 0, o_size >> LOG_SIZEOF_LONG);
+  return o_addr;
+}
+
+
+void* omMarkAsFreeTrackAddr(void* addr, int keep, OM_FLR_DECL)
+{
+  omTrackAddr d_addr = omOutAddr_2_TrackAddr(addr);
+  omAssume(omIsTrackAddr(addr));
+    
+  d_addr->next = (void*) -1;
+  if (d_addr->track > 2)
+  {
+    if (d_addr->flags & OM_FUSED)
+    {
+      memset(omTrackAddr_2_OutAddr(d_addr), OM_FREE_PATTERN, omTrackAddr_2_OutSize(d_addr));
+      if (d_addr->track > 3)
+      {
+#ifdef OM_TRACK_FILE_LINE
+        d_addr->free_line = l;
+        d_addr->free_file = f;
+#endif
+#ifdef OM_TRACK_RETURN
+        d_addr->free_r = r;
+#endif        
+        
+#ifdef OM_TRACK_BACKTRACE     
+        if (d_addr->track > 4)
+          omGetBackTrace(d_addr->free_frames,  FROM_FRAMES, OM_MAX_KEPT_FRAMES);
+#endif  
+      }
+    }
+    else
+    {
+      omAssume(d_addr->flags & OM_FKEPT);
+    }
+  }
+  d_addr->flags &= ~OM_FUSED;
+  if (keep) d_addr->flags |= OM_FKEPT;
+  else d_addr->flags &= ~OM_FKEPT;
+  
+  return(void*) d_addr;
+}
+
+void omFreeTrackAddr(void* d_addr)
+{
+  omBinPage page;
+  omBin bin;
+  
+  omAssume(omIsBinPageAddr(d_addr));
+  omAssume(d_addr != NULL && omIsTrackAddr(d_addr));
+  d_addr = omOutAddr_2_TrackAddr(d_addr);
+  
+  page = omGetBinPageOfAddr((void*) d_addr);
+  bin = omGetTopBinOfPage(page);
+  /* Ok, here is how it works: 
+    1. we unset the first bit of used_blocks
+       ==> used_blocks >= 0
+    2. we do a normal free 
+    3. if page of addr was freed, then om_JustFreedPage
+          is != NULL ==> nothing to be done by us
+       else 
+          page is still active ==> reset first bit of used_blocks
+  */
+
+  omUnsetTrackOfUsedBlocks(page->used_blocks);
+
+  om_JustFreedPage = NULL;
+
+  ___omFreeBin(d_addr);
+
+  if (page != om_JustFreedPage)
+    omSetTrackOfUsedBlocks(page->used_blocks);
+  else
+  {
+    /* Still need to check wheter we need to get rid of SpecBin */
+    if (bin->last_page == NULL && ! omIsStaticTrackBin(bin))
+      omDeleteSpecBin(&bin);
+  }
+}
+
+/*******************************************************************
+ *  
+ * Checking a Track Addr
+ * 
+ *  
+ *******************************************************************/
+
+omError_t omCheckTrackAddr(void* addr, void* bin_size, omTrackFlags_t flags, char level, 
+                           omError_t report, OM_FLR_DECL)
+{
+  omTrackAddr d_addr = omOutAddr_2_TrackAddr(addr);
+  omAssume(omIsTrackAddr(addr));
+  omAssume(! omCheckPtr(addr, 0, OM_FLR));
+
+  omAddrCheckReturnCorrupted(d_addr->track < 1 || d_addr->track > OM_TRACK_MAX);
+  omAddrCheckReturnError((flags & OM_FUSED) && omTrackAddr_2_OutAddr(d_addr) != addr, omError_FalseAddrOrMemoryCorrupted);
+
+  omCheckReturn(omDoCheckBinAddr(d_addr, 0, (flags & OM_FUSED ? OM_FUSED : (flags & OM_FKEPT ? OM_FKEPT: 0)), 
+                                 level, report, OM_FLR_VAL));
+  return omDoCheckTrackAddr(d_addr, addr, bin_size, flags, level, report, OM_FLR_VAL);
+}
+
+
+static omError_t omDoCheckTrackAddr(omTrackAddr d_addr, void* addr, void* bin_size, omTrackFlags_t flags, char level, 
+                                    omError_t report, OM_FLR_DECL)  
+{
+  if (flags & OM_FUSED)
+    omAddrCheckReturnError(d_addr->next != ((void*) -1), omError_FreedAddrOrMemoryCorrupted);
+  else
+    omAddrCheckReturnError(d_addr->next != NULL && omCheckPtr(d_addr->next, omError_MaxError, OM_FLR_VAL), 
+                           omError_FreedAddrOrMemoryCorrupted);
+  omAddrCheckReturnCorrupted(omCheckFlags(d_addr->flags));
+  omAddrCheckReturnError((d_addr->flags & OM_FUSED) ^ (flags & OM_FUSED), omError_FreedAddrOrMemoryCorrupted);
+
+  if (d_addr->track > 2)
+  {
+    if (d_addr->flags & OM_FBIN)
+    {
+      omAddrCheckReturnCorrupted(!omIsKnownTopBin((omBin) d_addr->bin_size, 1));
+    }
+    else
+    {
+      omAssume(d_addr->flags & OM_FSIZE);
+        
+      omAddrCheckReturnCorrupted(!OM_IS_ALIGNED(d_addr->bin_size));
+      omAddrCheckReturnCorrupted((size_t) d_addr->bin_size >
+                                 omSizeOfBinAddr(d_addr) 
+                                 - omTrackAddr_2_SizeOfTrackAddrHeader(d_addr)
+                                 - OM_MIN_SIZEOF_BACK_PATTERN);
+      /* Hmm .. here I'd love to have a stricter bound */
+      omAddrCheckReturnCorrupted((size_t) d_addr->bin_size < SIZEOF_OM_ALIGNMENT);
+    }
+      
+
+    omAddrCheckReturnError((flags & OM_FBIN) && ( !(d_addr->flags & OM_FBIN) || d_addr->bin_size != bin_size),omError_WrongBin);
+    if (flags & OM_FSIZE)
+    {
+      if (d_addr->flags & OM_FSIZE)
+        omAddrCheckReturnError((size_t) d_addr->bin_size != OM_ALIGN_SIZE((size_t) bin_size), omError_WrongSize);
+      else
+        omAddrCheckReturnError(omTrackAddr_2_OutSize(d_addr) < (size_t) bin_size, omError_WrongSize);
+    }
+
+    omAddrCheckReturnError(omCheckPattern(omTrackAddr_2_FrontPattern(d_addr), OM_FRONT_PATTERN,omTrackAddr_2_SizeOfFrontPattern(d_addr)),omError_FrontPattern);
+    omAddrCheckReturnError(omCheckPattern(omTrackAddr_2_BackPattern(d_addr), OM_BACK_PATTERN,omTrackAddr_2_SizeOfBackPattern(d_addr)),omError_BackPattern);
+    if (! (d_addr->flags & OM_FUSED))
+      omAddrCheckReturnError(omCheckPattern(omTrackAddr_2_OutAddr(addr), OM_FREE_PATTERN, omTrackAddr_2_OutSize(d_addr)),omError_FreePattern);
+
+    if (d_addr->track > 3)
+    {
+#ifdef OM_TRACK_FILE_LINE
+      if (d_addr->flags & OM_FUSED)
+      {
+        omAddrCheckReturnCorrupted(d_addr->free_line != -1);
+        omAddrCheckReturnCorrupted(d_addr->free_file != (void*) -1);
+      }
+      else
+      {
+        omAddrCheckReturnCorrupted(d_addr->free_line < 0);
+        omAddrCheckReturnCorrupted(d_addr->free_file == (void*) -1);
+      }
+#endif
+#ifdef OM_TRACK_RETURN
+      omAddrCheckReturnCorrupted(d_addr->flags & OM_FUSED && d_addr->free_r != (void*) -1);
+#endif        
+    }
+  }
+  else
+  {
+      if (flags & OM_FBIN)
+      {
+        size_t size = omTrackAddr_2_OutSize(d_addr);
+        omAddrCheckReturnError(!omIsKnownTopBin((omBin) bin_size, 1), omError_UnknownBin);
+        omAddrCheckReturnError(size < (((omBin)bin_size)->sizeW<<LOG_SIZEOF_LONG), omError_WrongBin);
+      }
+      else if (flags & OM_FSIZE && (!(flags & OM_FSLOPPY)  || bin_size > 0))
+      {
+        omAddrCheckReturnError(omTrackAddr_2_OutSize(d_addr) < (size_t) bin_size, omError_WrongSize);
+      }
+  }
+  return omError_NoError;
+}
+      
+static int omCheckFlags(omTrackFlags_t flag)
+{
+  if (flag > OM_FMAX) return 1;
+  if (! ((flag & OM_FBIN) ^ (flag & OM_FSIZE))) return 1;
+  if (flag & OM_FUSED && flag & OM_FKEPT) return 1;
+  return 0;
+}
+
+static int omCheckPattern(char* s, char p, size_t size)
+{
+  int i;
+  for (i=0; i<size; i++)
+  {
+    if (s[i] != p) 
+      return 1;
+  }
+  return 0;
+}
+
+#ifdef OM_TRACK_BACKTRACE
+#define OM_ALLOC_FRAMES(d_addr) d_addr->alloc_frames
+#define OM_FREE_FRAMES(d_addr)  d_addr->free_frames
+#else
+#define OM_ALLOC_FRAMES(d) NULL
+#define OM_FREE_FRAMES(d)  NULL
+#endif
+
+void omPrintTrackAddrInfo(FILE* fd, void* addr)
+{
+  omTrackAddr d_addr = omOutAddr_2_TrackAddr(addr);
+  omAssume(d_addr->track > 0);
+  
+  fprintf(fd, " allocated at ");
+  if (! _omPrintBackTrace(OM_ALLOC_FRAMES(d_addr), 
+                          (d_addr->track > 1 ? OM_MAX_KEPT_FRAMES : 0), 
+                          fd, 
+                          OM_FLR_ARG(d_addr->alloc_file, d_addr->alloc_line, d_addr->alloc_r)))
+    fprintf(fd," ??");
+  if (d_addr->track > 1) 
+  {
+    if (d_addr->track > 3 && ! (d_addr->flags & OM_FUSED))
+    {
+      fprintf(fd, "\n freed at ");
+      if (! _omPrintBackTrace(OM_FREE_FRAMES(d_addr), 
+                          (d_addr->track > 4 ? OM_MAX_KEPT_FRAMES : 0), 
+                          fd, 
+                          OM_FLR_ARG(d_addr->free_file, d_addr->free_line, d_addr->free_r)))
+        fprintf(fd," ??");
+    }
+  }
+  fprintf(fd, "\n");
+  fflush(fd);
+}
+
+/*******************************************************************
+ *  
+ * Misc routines for marking, etc.
+ *  
+ *******************************************************************/
+int omIsStaticTrackAddr(void* addr)
+{
+  omTrackAddr d_addr = omOutAddr_2_TrackAddr(addr);
+  omAssume(omIsTrackAddr(addr));
+
+  return (d_addr->flags & OM_FSTATIC);
+}
+
+omBin omGetOrigSpecBinOfTrackAddr(void* addr)
+{
+  omTrackAddr d_addr = omOutAddr_2_TrackAddr(addr);
+  omAssume(omIsTrackAddr(addr));
+  
+  if (d_addr->track > 2 && (d_addr->flags & OM_FBIN))
+  {
+    omBin bin = (omBin) d_addr->bin_size;
+    if (! omIsStaticNormalBin(bin)) 
+      return bin;
+  }
+  return NULL;
+}
+
+void omMarkAsStaticAddr(void* addr)
+{
+  if (omIsTrackAddr(addr))
+  {
+    omTrackAddr d_addr = omOutAddr_2_TrackAddr(addr);
+    d_addr->flags |= OM_FSTATIC;
+  }
+}
+
+void omUnMarkAsStaticAddr(void* addr)
+{
+  if (omIsTrackAddr(addr))
+  {
+    omTrackAddr d_addr = omOutAddr_2_TrackAddr(addr);
+    d_addr->flags &= ~OM_FSTATIC;
+  }
+}
+
+static void _omMarkAsStatic(void* addr)
+{
+  omTrackAddr d_addr = (omTrackAddr) addr;
+  omAssume(omIsTrackAddr(addr) && omOutAddr_2_TrackAddr(addr) == d_addr);
+  d_addr->flags |= OM_FSTATIC;
+}
+
+static void _omUnMarkAsStatic(void* addr)
+{
+  omTrackAddr d_addr = (omTrackAddr) addr;
+  omAssume(omIsTrackAddr(addr) && omOutAddr_2_TrackAddr(addr) == d_addr);
+  d_addr->flags &= ~OM_FSTATIC;
+}
+
+void omUnMarkMemoryAsStatic()
+{
+  omIterateTroughAddrs(0, 1, _omUnMarkAsStatic, NULL);
+}
+
+void omMarkMemoryAsStatic()
+{
+  omIterateTroughAddrs(0, 1, _omMarkAsStatic, NULL);
+}
+
+#endif /* OM_HAVE_TRACK */
Index: omalloc/omDefaultConfig.h
===================================================================
--- omalloc/omDefaultConfig.h	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
+++ omalloc/omDefaultConfig.h	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
@@ -0,0 +1,186 @@
+/*******************************************************************
+ *  File:    omDefaultConfig.h
+ *  Purpose: default declaration of of configurable stuff
+ *  Author:  obachman (Olaf Bachmann)
+ *  Created: 11/99
+ *  Version: $Id: omDefaultConfig.h,v 1.1 2000-08-14 12:18:28 obachman Exp $
+ *******************************************************************/
+
+/********************************************************************
+  If you want to make changes to any of these defines, create a file,
+  say, MyOmConfig.h, define your particular stuff there, and run configure with 
+  --external-config-h=MyOmConfig.h.
+
+  If you also need to implement something, then implement it in, say,
+  MyOmConfig.c, and run configure with
+  --external-config-h=MyOmConfig.h --external-config-c=MyOmConfig.c
+
+  For omTest to link, you need to make sure that your implementation can also be 
+  used when not linked with your application. I.e. you should also provide a 
+  stand-alone implementation if OM_STANDALONE is defined.
+
+  Notice that some of these parameters can also be set at run-time, using 
+  the global om_Opts struct.
+********************************************************************/
+#include <limits.h>
+#include "omConfig.h"
+/* if external config was provided, 'make' makes links from it to omExternalConfig.h */
+#ifdef OM_HAVE_EXTERNAL_CONFIG_H
+#include "omExternalConfig.h"
+#endif
+
+/* If this is larger than the track parameter given to the omDebug routines,
+   then this is used as TrackLevel: om_Opts.MinTrack is initalized with this */
+#ifndef OM_DEFAULT_MIN_TRACK
+#define OM_DEFAULT_MIN_TRACK 0
+#endif
+
+/* If this is larger than the check parameter given to the omDebug routines,
+   then this is used as CheckLevel: om_Opts.MinCheck is initalized with this */
+#ifndef OM_DEFAULT_MIN_CHECK
+#define OM_DEFAULT_MIN_CHECK 0
+#endif
+
+/* If this is greater than 0, then the omDebugFree omDebugRealloc delay freeing memory 
+   by that many blocks: Initalizes omOpts.Keep 
+   Setting this to LONG_MAX never frees memory */
+#ifndef OM_DEFAULT_KEEP
+#define OM_DEFAULT_KEEP 0
+#endif
+
+/* If this is set to 
+   0: errors are not reported, only the global variable om_ErrorStatus is set
+   1: short error description, i.e. omError2String(om_ErrorStatus), is reported to stderr 
+   2: backtrace of current stack is printed to stderr
+   3: more detailed error description is printed -- this might not make too much sense if
+      you are not familiar with omalloc
+   Initializes om_Opts.HowToReprotErrors
+*/
+#ifndef OM_DEFAULT_HOW_TO_REPORT_ERRORS
+#if defined(OM_INTERNAL_DEBUG) 
+#define OM_DEFAULT_HOW_TO_REPORT_ERRORS 3
+#else
+#define OM_DEFAULT_HOW_TO_REPORT_ERRORS 2
+#endif
+#endif
+
+/* if this is set, then all memory allocated with track >= 1 is marked as 
+   static, i.e. it is not mention in omPrintUsedAddrs */
+#ifndef OM_DEFAULT_MARK_AS_STATIC
+#define OM_DEFAULT_MARK_AS_STATIC 0
+#endif
+
+/* Number of pages per region, i.e., how many pages are allocated at once, after we
+   run out of pages: Initalizes om_Opts.PagesPerRegion
+   The higher this value is, the fewer calls to valloc (resp. mmap) need to be make,
+   but the more unused memory the application might have allocated from the operating system
+*/
+#ifndef OM_DEFAULT_PAGES_PER_REGION
+#define OM_DEFAULT_PAGES_PER_REGION 128
+#endif
+
+/* This is called if nothing goes any more, i.e., if
+   memory request can not be serviced. If set, this function should never return.*/
+#ifndef OM_DEFAULT_OUT_OF_MEMORY_FUNC
+/* This initalizes om_Opts.OutOfMemoryFunc which is declared as
+   void (*OutOfMemoryFunc)(); */
+#define OM_DEFAULT_OUT_OF_MEMORY_FUNC NULL
+#endif
+#ifndef OM_OUT_OF_MEMORY_HOOK
+#define OM_OUT_OF_MEMORY_HOOK()                             \
+do                                                          \
+{                                                           \
+  if (om_Opts.OutOfMemoryFunc != NULL)                      \
+    om_Opts.OutOfMemoryFunc();                              \
+   fprintf(stderr, "***Emergency Exit: Out of Memory\n");   \
+   exit(1);                                                 \
+}                                                           \
+while (0)
+#endif
+  
+/* This is called whenever no more memory could be obtained from the system.
+   It should trigger the release of as much memory by the application as possible */
+#ifndef OM_DEFAULT_MEMORY_LOW_FUNC
+/* This initalizes om_Opts.MemoryLowFunc which is declared as
+   void (*MemoryLowFunc)(); */
+#define OM_DEFAULT_MEMORY_LOW_FUNC NULL
+#endif
+#ifndef OM_DEFAULT_MEMORY_LOW_HOOK
+#define OM_MEMORY_LOW_HOOK()                    \
+do                                              \
+{                                               \
+  if (om_Opts.MemoryLowFunc != NULL)            \
+    om_Opts.MemoryLowFunc();                    \
+}                                               \
+while(0)
+#endif
+
+
+/********************************************************************
+ * 
+ * The following can NOT be set at run time
+ *
+ ********************************************************************/
+/* The following hooks are called after the respective 
+   system routine was called, and the Stats struct was updated 
+   Not settable at run-time (makes no sense for thise to be functions, for they would 
+   be called each time the underlying malloc/valloc is called !) */
+#ifndef OM_MALLOC_HOOK
+#define OM_MALLOC_HOOK(size) ((void)0)
+#endif
+#ifndef OM_REALLOC_HOOK
+#define OM_REALLOC_HOOK(oldsize, newsize) ((void)0)
+#endif
+#ifndef OM_VALLOC_HOOK
+#define OM_VALLOC_HOOK(size) ((void)0)
+#endif
+#ifndef OM_FREE_HOOK
+#define OM_FREE_HOOK(size) ((void)0)
+#endif
+#ifndef OM_VFREE_HOOK
+#define OM_VFREE_HOOK(size) ((void)0)
+#endif
+#ifndef OM_ALLOC_BINPAGE_HOOK
+#define OM_ALLOC_BINPAGE_HOOK ((void)0)
+#endif
+#ifndef OM_FREE_BINPAGE_HOOK
+#define OM_FREE_BINPAGE_HOOK ((void)0)
+#endif
+
+/* 
+ * Some stuff related to tracking of addresses 
+ */
+
+/* minimal number of WORDS for padding before addr: needs to > 0: only relevant for track >= 3 */
+#ifndef OM_MIN_SIZEWOF_FRONT_PATTERN
+#define OM_MIN_SIZEWOF_FRONT_PATTERN 1
+#endif
+
+/* minimal number of WORDS for padding before addr: needs to > 0: only relevant for track >= 3 */
+#ifndef OM_MIN_SIZEWOF_BACK_PATTERN
+#define OM_MIN_SIZEWOF_BACK_PATTERN 1
+#endif
+
+/* maximal number of stack frames kept for stack at the allocation time of addr (track >= 2)
+   and free time of addr (track >= 5) */
+#ifndef OM_MAX_KEPT_FRAMES 
+#define OM_MAX_KEPT_FRAMES 5
+#endif
+
+/* pattern with which memory is initalized, for front and back padding,
+   and for free memory: only relevant if track >= 3*/
+#ifndef OM_INIT_PATTERN
+#define OM_INIT_PATTERN    0xfe
+#endif
+#ifndef OM_FRONT_PATTERN
+#define OM_FRONT_PATTERN   0xfd
+#endif
+#ifndef OM_BACK_PATTERN
+#define OM_BACK_PATTERN    0xfc
+#endif
+#ifndef OM_FREE_PATTERN 
+#define OM_FREE_PATTERN    0xfb
+#endif
+
+
+
Index: omalloc/omDerivedConfig.h
===================================================================
--- omalloc/omDerivedConfig.h	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
+++ omalloc/omDerivedConfig.h	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
@@ -0,0 +1,137 @@
+/*******************************************************************
+ *  File:    omDerivedConfig.h.in
+ *  Purpose: configuration which are derived from omConfig.h
+ *  Author:  obachman (Olaf Bachmann)
+ *  Created: 11/99
+ *  Version: $Id: omDerivedConfig.h,v 1.1 2000-08-14 12:18:28 obachman Exp $
+ *******************************************************************/
+#ifndef OM_DERIVED_CONFIG_H
+#define OM_DERIVED_CONFIG_H
+
+#ifndef SIZEOF_VOIDP
+/* configure makes sure that SIZEOF_VOIDP == SIZEOF_LONG */
+#define SIZEOF_VOIDP SIZEOF_LONG
+#endif
+
+/* SIZEOF_VOIDP == 8 || SIZEOF_VOIDP == 4 checked by configure */
+#if SIZEOF_VOIDP == 8
+#define LOG_SIZEOF_LONG  3
+#define LOG_SIZEOF_VOIDP 3
+#define LOG_BIT_SIZEOF_LONG 6
+#else
+#define LOG_SIZEOF_LONG  2
+#define LOG_SIZEOF_VOIDP 2
+#define LOG_BIT_SIZEOF_LONG 5
+#endif
+
+/* SIZEOF_SYSTEM_PAGE == 4096 || SIZEOF_SYSTEM_PAGE == 8192 checked by configure */
+#if SIZEOF_SYSTEM_PAGE == 8192
+#define LOG_BIT_SIZEOF_SYSTEM_PAGE 13
+#else
+#define LOG_BIT_SIZEOF_SYSTEM_PAGE 12
+#endif
+
+#ifndef CHAR_BIT
+#define CHAR_BIT 8
+#endif
+
+#ifndef BIT_SIZEOF_LONG
+#define BIT_SIZEOF_LONG (CHAR_BIT << LOG_SIZEOF_LONG)
+#endif
+
+#ifdef OM_ALIGN_8
+#define SIZEOF_OM_ALIGNMENT 8
+#define SIZEOF_OM_ALIGNMENT_1 7
+#define LOG_SIZEOF_OM_ALIGNMENT 3 
+#define SIZEOF_STRICT_ALIGNMENT 8
+#else
+#define SIZEOF_OM_ALIGNMENT 4
+#define SIZEOF_OM_ALIGNMENT_1 3
+#define LOG_SIZEOF_OM_ALIGNMENT 2
+#ifdef OM_ALIGNMENT_NEEDS_WORK
+#define SIZEOF_STRICT_ALIGNMENT 8
+#else
+#define SIZEOF_STRICT_ALIGNMENT 4
+#endif
+#endif
+
+#define OM_ALIGN_SIZE(size) \
+   ((((unsigned long) size) + SIZEOF_OM_ALIGNMENT_1) & (~SIZEOF_OM_ALIGNMENT_1))
+
+#define OM_IS_ALIGNED(what) \
+   ((((unsigned long) what) & SIZEOF_OM_ALIGNMENT_1) == 0)
+
+#define OM_STRICT_ALIGN_SIZE(size)                                          \
+   ((((size_t) (size)) + SIZEOF_STRICT_ALIGNMENT - 1) & (~ (SIZEOF_STRICT_ALIGNMENT - 1)))
+
+#define OM_IS_STRICT_ALIGNED(what) \
+   ((((unsigned long) what) & (SIZEOF_STRICT_ALIGNMENT -1)) == 0)
+
+#if defined(OM_NDEBUG) && defined(OM_HAVE_TRACK)
+#undef OM_HAVE_TRACK
+#endif
+
+/* define to enable assume */
+#ifndef HAVE_OM_ASSUME
+#if defined(OM_INTERNAL_DEBUG) 
+#define HAVE_OM_ASSUME
+#endif
+#endif
+
+/* set to 0 to disable aso memory mamagent */
+#ifndef HAVE_ASO
+#define HAVE_ASO 1
+#endif
+#if defined(HAVE_ASO) && HAVE_ASO == 1
+/* define to enable ASO debugging */
+#undef ASO_DEBUG
+#endif
+
+#ifndef NULL
+#define NULL ((void*)0)
+#endif
+
+/* The following macros save a lot of typing */
+#ifdef OM_TRACK_FILE_LINE
+#define OM_FL_DECL      const char* f, const int l
+#define OM_FL_VAL       f, l
+#define OM_FL           __FILE__,__LINE__
+#define OM_FL_KOMMA     ,
+#else
+#define OM_FL_DECL 
+#define OM_FL_VAL
+#define OM_FL
+#define OM_FL_KOMMA
+#endif
+
+#define OM_CFL_DECL     char check OM_FL_KOMMA OM_FL_DECL
+#define OM_CFL_VAL      check OM_FL_KOMMA OM_FL_VAL
+#define OM_CFL          OM_CHECK OM_FL_KOMMA OM_FL
+
+#define OM_TFL_DECL     char track OM_FL_KOMMA OM_FL_DECL
+#define OM_TFL_VAL      track OM_FL_KOMMA OM_FL_VAL
+#define OM_TFL          OM_TRACK OM_FL_KOMMA OM_FL
+
+#define OM_CTFL_DECL    char check, char track OM_FL_KOMMA OM_FL_DECL
+#define OM_CTFL_VAL     check,track OM_FL_KOMMA OM_FL_VAL
+#define OM_CTFL         OM_CHECK,OM_TRACK OM_FL_KOMMA OM_FL
+
+#ifdef OM_TRACK_RETURN
+#define OM_FLR_DECL         OM_FL_DECL OM_FL_KOMMA void* r
+#define OM_FLR_VAL          OM_FL_VAL OM_FL_KOMMA r
+#define OM_FLR              OM_FL OM_FL_KOMMA 0
+#define OM_R_DEF            void* r; GET_RET_ADDR(r)
+#ifdef OM_TRACK_FILE_LINE
+#define OM_FLR_ARG(f,l,r)   f,l,r
+#else
+#define OM_FLR_ARG(f,l,r)   r      
+#endif
+#else
+#define OM_FLR_DECL OM_FL_DECL
+#define OM_FLR_VAL  OM_FL_VAL
+#define OM_FLR      OM_FL
+#define OM_R_DEF    ((void)0)
+#define OM_FLR_ARG(f,l,r)   f,l
+#endif
+
+#endif /* OM_DERIVED_CONFIG_H  */
Index: omalloc/omError.c
===================================================================
--- omalloc/omError.c	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
+++ omalloc/omError.c	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
@@ -0,0 +1,133 @@
+/*******************************************************************
+ *  File:    omError.c
+ *  Purpose: implementation of Error handling routines 
+ *  Author:  obachman (Olaf Bachmann)
+ *  Created: 11/99
+ *  Version: $Id: omError.c,v 1.1 2000-08-14 12:18:28 obachman Exp $
+ *******************************************************************/
+
+#include <stdarg.h>
+#include "omAlloc.h"
+
+omError_t om_ErrorStatus = omError_NoError;
+omError_t om_InternalErrorStatus = omError_NoError;
+
+struct omErrorString_s
+{
+  omError_t error;
+  char* s_error;
+  char* string;
+};
+
+/* strings describing omErrors */
+static struct omErrorString_s om_ErrorStrings[] =
+{
+  {omError_NoError,                     "omError_NoError",                     "no error"},
+  {omError_Unknown,                     "omError_Unknown",                     "unknown error" },
+  {omError_MemoryCorrupted,             "omError_MemoryCorrupted",             "memory corrupted"},
+  {omError_InternalBug,                 "omError_InternalBug",                 "internal omalloc bug"},
+  {omError_NullAddr,                    "omError_NullAddr",                    "addr is NULL"},
+  {omError_InvalidRangeAddr,            "omError_InvalidRangeAddr",            "addr not in valid range"},
+  {omError_FalseAddr,                   "omError_FalseAddr",                   "addr not as returned by omalloc"},
+  {omError_FalseAddrOrMemoryCorrupted,  "omError_FalseAddrOrMemoryCorrupted",  "addr not as returned by omalloc or memory corrupted", },
+  {omError_WrongSize,                   "omError_WrongSize",                   "wrong size specification of addr"},
+  {omError_FreedAddr,                   "omError_FreedAddr",                   "addr had previosuly been freed"},
+  {omError_FreedAddrOrMemoryCorrupted,  "omError_FreedAddrOrMemoryCorrupted",  "addr had previosuly been freed  or memory corrupted"},
+  {omError_WrongBin,                    "omError_WrongBin",                    "wrong Bin specification for addr"},
+  {omError_UnknownBin,                  "omError_UnknownBin",                  "given Bin is unknown"},
+  {omError_UnalignedAddr,               "omError_UnalignedAddr",               "addr is unaligned"},
+  {omError_NullSizeAlloc,               "omError_NullSizeAlloc",               "alloc of size 0"},
+  {omError_ListCycleError,              "omError_ListCycleError",              "list has cycles"},
+  {omError_SortedListError,             "omError_SortedListError",             "sorted list is unsorted"},
+  {omError_KeptAddrListCorrupted,       "omError_KeptAddrListCorrupted",       "list of kept addresses are corrupted"},
+  {omError_FrontPattern,                "omError_FrontPattern",                "written to front of addr"},
+  {omError_BackPattern,                 "omError_BackPattern",                 "written after end of addr"},
+  {omError_FreePattern,                 "omError_FreePattern",                 "written into freed memory"},
+  {omError_NotString,                   "omError_NotString",                   "string not null terminated"},
+  
+  {omError_MaxError, NULL} /* this needs to be the last entry */
+};
+
+const char* omError2String(omError_t error)
+{
+  int i = 0;
+  while (! (om_ErrorStrings[i].string == NULL && om_ErrorStrings[i].error == omError_MaxError))
+  {
+    if (om_ErrorStrings[i].error == error) return om_ErrorStrings[i].string;
+    i++;
+  }
+  return "undocumented error";
+}
+
+const char* omError2Serror(omError_t error)
+{
+  int i = 0;
+  while (! (om_ErrorStrings[i].string == NULL && om_ErrorStrings[i].error == omError_MaxError))
+  {
+    if (om_ErrorStrings[i].error == error) return om_ErrorStrings[i].s_error;
+    i++;
+  }
+  return "omError_UnKnown";
+}
+
+omError_t omReportError(omError_t error, omError_t report_error, OM_FLR_DECL,  
+                        const char* fmt, ...)
+{
+  if (report_error == omError_MaxError) return error;
+  om_InternalErrorStatus = error;
+  om_ErrorStatus = (report_error == omError_NoError ? error : report_error);
+
+  if (om_Opts.HowToReportErrors && om_ErrorStatus != omError_NoError)
+  {
+    fprintf(stderr, "***%s: %s", omError2Serror(om_ErrorStatus), omError2String(om_ErrorStatus));
+    
+#ifdef OM_INTERNAL_DEBUG
+    if (om_ErrorStatus != error)
+      fprintf(stderr, "\n___%s: %s", omError2Serror(error), omError2String(error));
+#endif
+
+    if (om_Opts.HowToReportErrors > 2 && fmt != NULL && *fmt != '\0')
+    {
+      va_list ap;
+      va_start(ap, fmt);
+      fprintf(stderr, ": ");
+      vfprintf(stderr, fmt, ap);
+      va_end(ap);
+    }
+
+    if (om_Opts.HowToReportErrors > 1)
+    {
+#ifndef OM_NDEBUG
+      fprintf(stderr, "\n occured at: ");
+      if (! _omPrintCurrentBackTrace(stderr, OM_FLR_VAL)) 
+        fprintf(stderr, " ??");
+#endif
+    }
+    fprintf(stderr, "\n");
+    fflush(stderr);
+  }
+  return error;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+                
Index: omalloc/omError.h
===================================================================
--- omalloc/omError.h	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
+++ omalloc/omError.h	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
@@ -0,0 +1,80 @@
+/*******************************************************************
+ *  File:    omError.h
+ *  Purpose: Error handling of omalloc
+ *  Author:  obachman (Olaf Bachmann)
+ *  Created: 11/99
+ *  Version: $Id: omError.h,v 1.1 2000-08-14 12:18:28 obachman Exp $
+ *******************************************************************/
+#ifndef OM_ERROR_H
+#define OM_ERROR_H
+
+/*******************************************************************
+ *  
+ *  error codes
+ *  
+ *******************************************************************/
+enum omError_e
+{
+  omError_NoError = 0,
+  omError_Unknown,
+  omError_InternalBug,
+  omError_MemoryCorrupted,
+  omError_NullAddr,
+  omError_InvalidRangeAddr,
+  omError_FalseAddr,
+  omError_FalseAddrOrMemoryCorrupted,
+  omError_WrongSize,
+  omError_FreedAddr,
+  omError_FreedAddrOrMemoryCorrupted,
+  omError_WrongBin,
+  omError_UnknownBin,
+  omError_UnalignedAddr,
+  omError_NullSizeAlloc,
+  omError_ListCycleError,
+  omError_SortedListError,
+  omError_KeptAddrListCorrupted,
+  omError_FreePattern,
+  omError_BackPattern,
+  omError_FrontPattern,
+  omError_NotString,
+  omError_MaxError
+};
+typedef enum omError_e omError_t;
+
+/* global variable holding last omError */
+extern omError_t om_ErrorStatus;
+/* globale variable holding last low-level omError */
+extern omError_t om_InternalErrorStatus;
+/* returns description of error */
+const char* omError2String(omError_t error);
+/* returns error as string */
+const char* omError2Serror(omError_t error);
+extern omError_t omReportError(omError_t error, omError_t report_error, OM_FLR_DECL,  
+                               const char* fmt, ...);
+
+/*BEGINPRIVATE*/
+/*******************************************************************
+ *
+ * om_assume(x) -- a handy macro for assumptions
+ *
+ ******************************************************************/
+#ifndef HAVE_OM_ASSUME
+
+#define omAssume(x) ((void) 0)
+
+#else /* ! HAVE_OM_ASSUME */
+
+#define omAssume(x)                                             \
+do                                                              \
+{                                                               \
+  if (! (x))                                                    \
+  {                                                             \
+    omReportError(omError_InternalBug, omError_InternalBug, OM_FLR, "omAssume violation");   \
+  }                                                             \
+}                                                               \
+while (0)
+
+#endif /* HAVE_OM_ASSUME */
+/*ENDPRIVATE*/
+
+#endif /* OM_LOCAL_H */
Index: omalloc/omGetBackTrace.c
===================================================================
--- omalloc/omGetBackTrace.c	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
+++ omalloc/omGetBackTrace.c	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
@@ -0,0 +1,74 @@
+/*******************************************************************
+ *  File:    omGetBackTrace.c
+ *  Purpose: routines for getting Backtraces of stack
+ *  Author:  obachman (Olaf Bachmann)
+ *  Created: 11/99
+ *  Version: $Id: omGetBackTrace.c,v 1.1 2000-08-14 12:18:29 obachman Exp $
+ *******************************************************************/
+#ifndef OM_NDEBUG
+
+#if __GNUC__ > 1
+
+static void* om_this_main_frame_addr = 0;
+
+void omInitGetBackTrace()
+{
+  if (__builtin_frame_address(0) != 0 && 
+      __builtin_frame_address(1) > __builtin_frame_address(0))
+    om_this_main_frame_addr = __builtin_frame_address(1);
+}
+
+#define OM_GET_BACK_TRACE(j)                                    \
+case j:                                                         \
+{                                                               \
+  f_addr = __builtin_frame_address(j);                          \
+  if (f_addr  > this_frame && f_addr < om_this_main_frame_addr) \
+  {                                                             \
+    r_addr = __builtin_return_address(j);                       \
+    if (r_addr)                                                 \
+    {                                                           \
+      bt[i] = r_addr;                                           \
+      i++;                                                      \
+      if (i >= max) break;                                      \
+    }                                                           \
+    else break;                                                 \
+  }                                                             \
+  else break;                                                   \
+}
+    
+int omGetBackTrace(void** bt, int start, int max)
+{
+  int i = 0;
+  void* this_frame = __builtin_frame_address(0);
+  void* f_addr;
+  void* r_addr;
+  
+  start++;
+  
+  switch(start)
+  {
+    OM_GET_BACK_TRACE(1)
+    OM_GET_BACK_TRACE(2)
+    OM_GET_BACK_TRACE(3)
+    OM_GET_BACK_TRACE(4)
+    OM_GET_BACK_TRACE(5)
+    OM_GET_BACK_TRACE(6)
+    OM_GET_BACK_TRACE(7)
+    OM_GET_BACK_TRACE(8)
+    OM_GET_BACK_TRACE(9)
+    OM_GET_BACK_TRACE(10)
+    OM_GET_BACK_TRACE(11)
+    OM_GET_BACK_TRACE(12)
+    OM_GET_BACK_TRACE(13)
+    OM_GET_BACK_TRACE(14)
+    OM_GET_BACK_TRACE(15)
+    OM_GET_BACK_TRACE(16)
+    OM_GET_BACK_TRACE(17)
+  }
+  if (i < max) bt[i] = 0;
+  return i;
+}
+
+#endif /* __GNUC__ > 1 */
+
+#endif /* ! OM_NDEBUG */
Index: omalloc/omGetBackTrace.h
===================================================================
--- omalloc/omGetBackTrace.h	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
+++ omalloc/omGetBackTrace.h	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
@@ -0,0 +1,19 @@
+/*******************************************************************
+ *  File:    omGetBackTrace.h
+ *  Purpose: routines for getting Backtraces of stack
+ *  Author:  obachman (Olaf Bachmann)
+ *  Created: 11/99
+ *  Version: $Id: omGetBackTrace.h,v 1.1 2000-08-14 12:18:29 obachman Exp $
+ *******************************************************************/
+#ifndef OM_GET_BACKTRACE_H
+#define OM_GET_BACKTRACE_H
+
+#if defined(OM_GET_BACKTRACE_WORKS) && !defined(OM_NDEBUG)
+void omInitGetBackTrace();
+int omGetBackTrace(void** bt, int start, int max);
+#else
+#define omInitGetBackTrace() ((void)0)
+#define omGetBackTrace(bt, s, max) ((void)0)
+#endif
+
+#endif 
Index: omalloc/omInline.h
===================================================================
--- omalloc/omInline.h	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
+++ omalloc/omInline.h	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
@@ -0,0 +1,262 @@
+/*******************************************************************
+ *  File:    omInline.c
+ *  Purpose: implementation of omalloc functions which could
+ *           be inlined
+ *  Author:  obachman@mathematik.uni-kl.de (Olaf Bachmann)
+ *  Created: 11/99
+ *  Version: $Id: omInline.h,v 1.1 2000-08-14 12:18:29 obachman Exp $
+ *******************************************************************/
+#if defined(OM_INLINE) || defined(OM_ALLOC_C)
+
+#ifndef OM_INLINE_H
+#define OM_INLINE_H
+
+OM_INLINE_IMPL omBin omGetBinOfPage(omBinPage page)
+{
+  unsigned long sticky = omGetStickyOfPage(page);
+  omBin bin = omGetTopBinOfPage(page);
+  
+  while (bin->sticky != sticky && bin->next != NULL) 
+  {
+    bin = bin->next;
+  }
+  return bin;
+}
+
+OM_INLINE_IMPL int _omIsBinPageAddr(void* addr)
+{
+  unsigned long index = omGetPageIndexOfAddr(addr);
+  if (index >= om_MinBinPageIndex && index <= om_MaxBinPageIndex)
+  {
+    unsigned long shift = omGetPageShiftOfAddr(addr);
+    return om_BinPageIndicies[index - om_MinBinPageIndex] & (1 << shift);
+  }
+  return 0;
+}
+
+OM_INLINE_IMPL void* _omAllocBin(omBin bin)
+{
+  void* addr;
+  __omTypeAllocBin(void*, addr, bin);
+  return addr;
+}
+OM_INLINE_IMPL void* _omAlloc0Bin(omBin bin)
+{
+  void* addr;
+  __omTypeAlloc0Bin(void*, addr, bin);
+  return addr;
+}
+OM_INLINE_IMPL void* _omReallocBin(void* addr, omBin old_bin, omBin new_bin)
+{
+  void* new_addr; 
+  __omTypeReallocBin(addr, old_bin, void*, new_addr, new_bin);
+  return new_addr;
+}
+OM_INLINE_IMPL void* _omRealloc0Bin(void* addr, omBin old_bin, omBin new_bin)
+{
+  void* new_addr; 
+  __omTypeRealloc0Bin(addr, old_bin, void*, new_addr, new_bin);
+  return new_addr;
+}
+  
+
+OM_INLINE_IMPL void* _omAlloc(size_t size)
+{
+  void* addr;
+  __omTypeAlloc(void*, addr, size);
+  return addr;
+}
+OM_INLINE_IMPL void* _omAlloc0(size_t size)
+{
+  void* addr;
+  __omTypeAlloc0(void*, addr, size);
+  return addr;
+}
+OM_INLINE_IMPL void* _omReallocSize(void* addr, size_t old_size, size_t new_size)
+{
+  void* new_addr;
+  __omTypeReallocSize(addr, old_size, void*, new_addr, new_size);
+  return new_addr;
+}
+OM_INLINE_IMPL void* _omRealloc0Size(void* addr, size_t old_size, size_t new_size)
+{
+  void* new_addr;
+  __omTypeRealloc0Size(addr, old_size, void*, new_addr, new_size);
+  return new_addr;
+}
+OM_INLINE_IMPL void* _omRealloc(void* addr, size_t size)
+{
+  void* new_addr;
+  __omTypeRealloc(addr, void*, new_addr, size);
+  return new_addr;
+}
+OM_INLINE_IMPL void* _omRealloc0(void* addr, size_t size)
+{
+  void* new_addr;
+  __omTypeRealloc0(addr, void*, new_addr, size);
+  return new_addr;
+}
+
+#ifdef OM_ALIGNMENT_NEEDS_WORK
+OM_INLINE_IMPL void* _omAllocAligned(size_t size)
+{
+  void* addr;
+  __omTypeAllocAligned(void*, addr, size);
+  return addr;
+}
+OM_INLINE_IMPL void* _omAlloc0Aligned(size_t size)
+{
+  void* addr;
+  __omTypeAlloc0Aligned(void*, addr, size);
+  return addr;
+}
+OM_INLINE_IMPL void* _omReallocAlignedSize(void* addr, size_t old_size, size_t new_size)
+{
+  void* new_addr;
+  __omTypeReallocAlignedSize(addr, old_size, void*, new_addr, new_size);
+  return new_addr;
+}
+OM_INLINE_IMPL void* _omRealloc0AlignedSize(void* addr, size_t old_size, size_t new_size)
+{
+  void* new_addr;
+  __omTypeRealloc0AlignedSize(addr, old_size, void*, new_addr, new_size);
+  return new_addr;
+}
+OM_INLINE_IMPL void* _omReallocAligned(void* addr, size_t size)
+{
+  void* new_addr;
+  __omTypeReallocAligned(addr, void*, new_addr, size);
+  return new_addr;
+}
+OM_INLINE_IMPL void* _omRealloc0Aligned(void* addr, size_t size)
+{
+  void* new_addr;
+  __omTypeRealloc0Aligned(addr, void*, new_addr, size);
+  return new_addr;
+}
+
+OM_INLINE_IMPL void* _omMemDupAligned(void* addr)
+{
+  void* r;
+  size_t sizeW = omSizeWOfAddr(addr);
+  __omTypeAllocAligned(void*, r, sizeW << LOG_SIZEOF_LONG);
+  omMemcpyW(r, addr, sizeW);
+  return r;
+}
+
+#endif /* OM_ALIGNMENT_NEEDS_WORK */
+
+OM_INLINE_IMPL char* _omStrDup(const char* s)
+{
+  char* r;
+  int i=0;
+  
+  while (s[i]) i++;
+  i++;
+  __omTypeAlloc(char*, r, i);
+  i = OM_ALIGN_SIZE(i) >> LOG_SIZEOF_LONG;
+  omMemcpyW(r, s, i);
+  return r;
+}
+
+OM_INLINE_IMPL void* _omMemDup(void* addr)
+{
+  void* r;
+  if (omIsNormalBinPageAddr(addr))
+  {
+    omBin bin = omGetTopBinOfAddr(addr);
+    __omTypeAllocBin(void*, r, bin);
+    omMemcpyW(r, addr, bin->sizeW);
+  }
+  else
+  {
+    size_t size = omSizeWOfAddr(addr);
+    __omTypeAlloc(void*, r, size << LOG_SIZEOF_LONG);
+    omMemcpyW(r, addr, size);
+  }
+  return r;
+}
+
+OM_INLINE_IMPL void* _omalloc(size_t size)
+{
+  void* addr;
+  if (! size) size = 1;
+  __omTypeAllocAligned(void*, addr,size);
+  return addr;
+}
+
+OM_INLINE_IMPL void* _omalloc0(size_t size)
+{
+  void* addr;
+  if (! size) size = 1;
+  __omTypeAlloc0Aligned(void*,addr, size);
+  return addr;
+}
+
+OM_INLINE_IMPL void* _omreallocSize(void* addr, size_t old_size, size_t new_size)
+{
+  void* new_addr;
+  
+  if (!new_size) new_size = 1;
+  if (addr != NULL)
+  {
+    __omTypeReallocAlignedSize(addr, old_size, void* , new_addr, new_size);
+  }
+  else
+  {
+    __omTypeAllocAligned(void* , new_addr, new_size);
+  }
+  return new_addr;
+}
+  
+OM_INLINE_IMPL void* _omrealloc0Size(void* addr, size_t old_size, size_t new_size)
+{
+  void* new_addr;
+  
+  if (!new_size) new_size = 1;
+  if (addr != NULL && old_size > 0)
+  {
+    __omTypeRealloc0AlignedSize(addr, old_size, void* , new_addr, new_size);
+  }
+  else
+  {
+    __omTypeAlloc0(void* , new_addr, new_size);
+  }
+  return new_addr;
+}
+  
+OM_INLINE_IMPL void* _omrealloc(void* addr, size_t size)
+{
+  void* new_addr;
+  
+  if (!size) size = 1;
+  if (addr != NULL)
+  {
+    __omTypeReallocAligned(addr, void* , new_addr, size);
+  }
+  else
+  {
+    __omTypeAlloc(void* , new_addr, size);
+  }
+  return new_addr;
+}
+  
+OM_INLINE_IMPL void* _omrealloc0(void* addr, size_t size)
+{
+  void* new_addr;
+  
+  if (!size) size = 1;
+  if (addr != NULL)
+  {
+    __omTypeRealloc0Aligned(addr, void* , new_addr, size);
+  }
+  else
+  {
+    __omTypeAlloc0(void* , new_addr, size);
+  }
+  return new_addr;
+}
+#endif /* OM_INLINE_H */
+
+#endif /* defined(OM_INLINE) || defined(OM_ALLOC_C) */
+
Index: omalloc/omInlineDecl.h
===================================================================
--- omalloc/omInlineDecl.h	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
+++ omalloc/omInlineDecl.h	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
@@ -0,0 +1,49 @@
+/*******************************************************************
+ *  File:    omInlineDecl.h
+ *  Purpose: declarations of omalloc functions which could
+ *           be inlined
+ *  Author:  obachman@mathematik.uni-kl.de (Olaf Bachmann)
+ *  Created: 11/99
+ *  Version: $Id: omInlineDecl.h,v 1.1 2000-08-14 12:18:29 obachman Exp $
+ *******************************************************************/
+#ifndef OM_INLINE_DECL_H
+#define OM_INLINE_DECL_H
+
+OM_INLINE_DECL omBin omGetBinOfPage(omBinPage page);
+OM_INLINE_DECL int _omIsBinPageAddr(void* addr);
+
+OM_INLINE_DECL void* _omAllocBin(omBin bin);
+OM_INLINE_DECL void* _omAlloc0Bin(omBin bin);
+OM_INLINE_DECL void* _omReallocBin(void* addr, omBin old_bin, omBin new_bin);
+OM_INLINE_DECL void* _omRealloc0Bin(void* addr, omBin old_bin, omBin new_bin);
+
+OM_INLINE_DECL void* _omAlloc(size_t size);
+OM_INLINE_DECL void* _omAlloc0(size_t size);
+OM_INLINE_DECL void* _omReallocSize(void* addr, size_t old_size, size_t new_size);
+OM_INLINE_DECL void* _omRealloc0Size(void* addr, size_t old_size, size_t new_size);
+OM_INLINE_DECL void* _omRealloc(void* addr, size_t size);
+OM_INLINE_DECL void* _omRealloc0(void* addr, size_t size);
+
+OM_INLINE_DECL void* _omalloc(size_t size);
+OM_INLINE_DECL void* _omalloc0(size_t size);
+OM_INLINE_DECL void* _omreallocSize(void* addr, size_t old_size, size_t new_size);
+OM_INLINE_DECL void* _omrealloc0Size(void* addr, size_t old_size, size_t new_size);
+OM_INLINE_DECL void* _omrealloc(void* addr, size_t size);
+OM_INLINE_DECL void* _omrealloc0(void* addr, size_t size);
+
+OM_INLINE_DECL char* _omStrDup(const char* s);
+OM_INLINE_DECL void* _omMemDup(void* addr);
+
+#ifdef OM_ALIGNMENT_NEEDS_WORK
+OM_INLINE_DECL void* _omAllocAligned(size_t size);
+OM_INLINE_DECL void* _omAlloc0Aligned(size_t size);
+OM_INLINE_DECL void* _omReallocAlignedSize(void* addr, size_t old_size, size_t new_size);
+OM_INLINE_DECL void* _omRealloc0AlignedSize(void* addr, size_t old_size, size_t new_size);
+OM_INLINE_DECL void* _omReallocAligned(void* addr, size_t size);
+OM_INLINE_DECL void* _omRealloc0Aligned(void* addr, size_t size);
+OM_INLINE_DECL void* _omMemDupAligned(void* addr);
+#endif
+
+#endif /* OM_INLINE_DECL_H */
+
+
Index: omalloc/omMallocSystem.h
===================================================================
--- omalloc/omMallocSystem.h	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
+++ omalloc/omMallocSystem.h	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
@@ -0,0 +1,19 @@
+/*******************************************************************
+ *  File:    omMallocSystem.h
+ *  Purpose: declaration of macros for malloc to be used from the system
+ *  Author:  obachman (Olaf Bachmann)
+ *  Created: 11/99
+ *  Version: $Id: omMallocSystem.h,v 1.1 2000-08-14 12:18:29 obachman Exp $
+ *******************************************************************/
+#ifndef OM_MALLOC_SYSTEM_H
+#define OM_MALLOC_SYSTEM_H
+
+/* this is the minimal set of OM_MALLOC_* macros which must be defined */
+#define OM_MALLOC_MALLOC   malloc
+#define OM_MALLOC_REALLOC  realloc
+#define OM_MALLOC_FREE     free
+#define OM_MALLOC_VALLOC   valloc
+#define OM_MALLOC_VFREE(addr, size) OM_MALLOC_FREE(addr)
+
+#endif /* OM_MALLOC_SYSTEM_H */
+
Index: omalloc/omMmap.c
===================================================================
--- omalloc/omMmap.c	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
+++ omalloc/omMmap.c	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
@@ -0,0 +1,43 @@
+/*******************************************************************
+ *  File:    omMmap.c
+ *  Purpose: implementing valloc via mmap
+ *  Author:  obachman (Olaf Bachmann)
+ *  Created: 11/99
+ *  Version: $Id: omMmap.c,v 1.1 2000-08-14 12:18:29 obachman Exp $
+ *******************************************************************/
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+
+#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
+#define MAP_ANONYMOUS MAP_ANON
+#endif
+
+static void* omVallocMmap(size_t size)
+{
+  void* addr;
+#ifndef MAP_ANONYMOUS
+  static int fd = -1;
+#endif
+
+#ifdef MAP_ANONYMOUS
+  addr = mmap(0, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
+#else /* !MAP_ANONYMOUS */
+  if (fd < 0) 
+  {
+    fd = open("/dev/zero", O_RDWR);
+    if (fd < 0) return NULL;
+  }
+  addr = mmap(0, size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
+#endif
+  
+  if (addr == (void*) -1) return NULL;
+  return addr;
+}
+
+static int omVfreeMmap(void* addr, size_t size)
+{
+  return munmap(addr, size);
+}
+
+
Index: omalloc/omOpts.c
===================================================================
--- omalloc/omOpts.c	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
+++ omalloc/omOpts.c	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
@@ -0,0 +1,26 @@
+/*******************************************************************
+ *  File:    omStats.c
+ *  Purpose: definitions of stats related stuff
+ *  Author:  obachman (Olaf Bachmann)
+ *  Created: 11/99
+ *  Version: $Id: omOpts.c,v 1.1 2000-08-14 12:18:30 obachman Exp $
+ *******************************************************************/
+
+#include "omAlloc.h"
+#include "omDefaultConfig.h"
+
+omOpts_t om_Opts = 
+{
+  OM_DEFAULT_MIN_TRACK,
+  OM_DEFAULT_MIN_CHECK,
+  OM_DEFAULT_KEEP,
+  OM_DEFAULT_HOW_TO_REPORT_ERRORS,
+  OM_DEFAULT_MARK_AS_STATIC,
+  OM_DEFAULT_PAGES_PER_REGION,
+  OM_DEFAULT_OUT_OF_MEMORY_FUNC,
+  OM_DEFAULT_MEMORY_LOW_FUNC
+};
+
+
+
+
Index: omalloc/omOpts.h
===================================================================
--- omalloc/omOpts.h	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
+++ omalloc/omOpts.h	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
@@ -0,0 +1,26 @@
+/*******************************************************************
+ *  File:    omOpts.h
+ *  Purpose: declaration of options for omalloc
+ *  Author:  obachman (Olaf Bachmann)
+ *  Created: 11/99
+ *  Version: $Id: omOpts.h,v 1.1 2000-08-14 12:18:30 obachman Exp $
+ *******************************************************************/
+#ifndef OM_OPTS_H
+#define OM_OPTS_H
+
+/* Default values for these options are defined in omDefaultConfig.h */
+struct omOpts_s
+{
+  int MinTrack;
+  int MinCheck;
+  int Keep;
+  int HowToReportErrors;
+  int MarkAsStatic;
+  unsigned int PagesPerRegion;
+  void (*OutOfMemoryFunc)();
+  void (*MemoryLowFunc)();
+};
+extern omOpts_t om_Opts;
+
+#endif /* OM_OPTS_H */
+
Index: omalloc/omRet2Info.c
===================================================================
--- omalloc/omRet2Info.c	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
+++ omalloc/omRet2Info.c	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
@@ -0,0 +1,239 @@
+/*******************************************************************
+ *  File:    omRetur2Info.c
+ *  Purpose: translation of return addr to RetInfo
+ *  Author:  obachman (Olaf Bachmann)
+ *  Created: 11/99
+ *  Version: $Id: omRet2Info.c,v 1.1 2000-08-14 12:18:30 obachman Exp $
+ *******************************************************************/
+#include <stdio.h>
+
+#include "omConfig.h"
+
+#ifndef OM_NDEBUG
+#include "omAlloc.h"
+
+#ifndef MAXPATHLEN
+#define MAXPATHLEN 1024
+#endif
+
+static char om_this_prog[MAXPATHLEN] = "";
+
+#ifndef OM_MAX_BACKTRACE_DEPTH
+#define OM_MAX_BACKTRACE_DEPTH 16
+#endif
+
+void omInitRet_2_Info(const char* argv0)
+{
+  char buf[MAXPATHLEN];
+
+  if (argv0 != NULL && omFindExec(argv0, buf))
+  {
+    strcpy(om_this_prog, buf);
+  }
+}
+
+int omBackTrace_2_RetInfo(void** bt, omRetInfo info, int max)
+{
+  int i=0, j=0, filled = 0;
+  if (max <= 0 || bt == NULL || info == NULL) return 0;
+  if (max > OM_MAX_BACKTRACE_DEPTH) max = OM_MAX_BACKTRACE_DEPTH;
+  memset(info, 0, max*sizeof(omRetInfo_t));
+  while (i<max)
+  {
+    if (bt[i])
+    {
+      info[j].addr = bt[i];
+      j++;
+    }
+    i++;
+  }
+  if (j == 0) return 0;
+  
+#if defined(HAVE_POPEN) && defined(OM_PROG_ADDR2LINE)
+  if (*om_this_prog != '\0')
+  {
+    char command[2*MAXPATHLEN + 15 + OM_MAX_BACKTRACE_DEPTH*(2*SIZEOF_VOIDP + 4)];
+    FILE *pipe;
+    int l;
+    l = sprintf(command, "%s -s -C -f -e %s", 
+                OM_PROG_ADDR2LINE, om_this_prog);
+    i=0;
+    while (i<j)
+    {
+      l+=sprintf(&command[l], " %p", info[i].addr);
+      i++;
+    }
+    pipe = popen(command, "r");
+    if (pipe != NULL)
+    {
+        /* An output entry of addr2line looks as follows:
+FunctionName
+File:Line
+        */
+      while ((filled < j) && 
+             (fscanf(pipe, "%100[^\n]\n%100[^:]:%d\n", info[filled].func, info[filled].file, &(info[filled].line)) == 3))
+      {
+        if (*info[filled].func != '?' && *info[filled].file != '?' && info[filled].line > 0)
+          filled++;
+      }
+      pclose(pipe);
+    }
+  }
+#endif  
+  return filled;
+}
+
+int omPrintRetInfo(omRetInfo info, int max, FILE* fd, const char* fmt)
+{
+  int i = 0;
+  if (max <= 0 || info == NULL || fmt == NULL || fd == NULL) return 0;
+  while (i < max && info[i].addr != NULL)
+  {
+    int l = 0;
+    while (fmt[l] != 0)
+    {
+      if (fmt[l] == '%')
+      {
+        l++;
+        if (fmt[l] == 'p') fprintf(fd, "%p", info[i].addr);
+        else if (fmt[l] == 'f') fprintf(fd, "%-20s", (*info[i].file != '\0' ? info[i].file : "??"));
+        else if (fmt[l] == 'F') fprintf(fd, "%-20s", (*info[i].func != '\0' ? info[i].func : "??"));
+        else if (fmt[l] == 'l') fprintf(fd, "%d", info[i].line);
+        else if (fmt[l] == 'L') 
+        {
+          int n = fprintf(fd, "%s:%d", (*info[i].func != '\0' ? info[i].file : "??"), info[i].line);
+          if (n < 20) fprintf(fd, "%*s", 20-n, " ");
+        }
+        else if (fmt[l] == 'i') fprintf(fd, "%d", i);
+        else
+        {
+          fputc('%', fd);
+          l--;
+        }
+      }
+      else
+      {
+        fputc(fmt[l], fd);
+      }
+      l++;
+    }
+    i++;
+  }
+  return i;
+}
+
+int omPrintBackTrace(void** bt, int max, FILE* fd)
+{
+  int i;
+  
+  omRetInfo_t info[OM_MAX_BACKTRACE_DEPTH];
+  if (max > OM_MAX_BACKTRACE_DEPTH) max = OM_MAX_BACKTRACE_DEPTH;
+  
+  i = omBackTrace_2_RetInfo(bt, info, max);
+  return omPrintRetInfo(info, i, fd, "  #%i %L in %F\n");
+}
+
+int omPrintCurrentBackTrace(FILE* fd)
+{
+  int i;
+  void* bt[OM_MAX_BACKTRACE_DEPTH];
+  
+  i = omGetBackTrace(bt, 1, OM_MAX_BACKTRACE_DEPTH);
+  return omPrintBackTrace(bt, i, fd);
+}
+
+/*************************************************************
+ *                                                              
+ * Various Filters
+ *
+ *************************************************************/
+int omFilterRetInfo_i(omRetInfo info, int max, int i)
+{
+  int j=0, k=i;
+  
+  while (k < max)
+  {
+    info[j] = info[k];
+    j++;
+    k++;
+  }
+  return j;
+}
+
+/*************************************************************
+ *                                                              
+ * Low level routines 
+ *
+ *************************************************************/
+
+int _omPrintBackTrace(void** bt, int max, FILE* fd, OM_FLR_DECL)
+{
+  int i;
+  
+  omRetInfo_t info[OM_MAX_BACKTRACE_DEPTH];
+  if (max > OM_MAX_BACKTRACE_DEPTH) max = OM_MAX_BACKTRACE_DEPTH;
+  
+  i = omBackTrace_2_RetInfo(bt, info, max);
+#ifdef OM_TRACK_RETURN
+  if (i == 0)
+    i = omBackTrace_2_RetInfo(&r,info, 1);
+#endif
+#ifndef OM_INTERNAL_DEBUG
+  if (i > 1)
+  {
+#ifdef OM_TRACK_RETURN
+    if (r != NULL)
+      omFilterRetInfo(info, i, addr_i == r);
+#endif
+#ifdef OM_TRACK_FILE_LINE
+    if (f != NULL && l > 0)
+      omFilterRetInfo(info, i, strcmp(f, file_i) == 0 && l + 2 >= line_i && l - 2 <= line_i);
+#endif
+    /* if we have both, use overwrite what we got from return addressse --
+       they sometimes are wrong */
+#if defined(OM_TRACK_RETURN) && defined(OM_TRACK_FILE_LINE)
+    if (r != NULL && info[0].addr == r && l > 0 && f != 0)
+    {
+      strcpy(info[0].file, f);
+      info[0].line = l;
+    }
+#endif  
+  }
+  if (i == 0)
+  {
+#endif /* ! OM_INTERNAL_DEBUG */
+
+#ifdef OM_TRACK_FILE_LINE
+    fprintf(fd, " %s:%d", f, l);
+#endif
+#ifdef OM_TRACK_RETURN
+    fprintf(fd," ra=%p");
+#endif
+
+#ifndef OM_INTERNAL_DEBUG
+    return 1;
+  }
+  else
+#endif /* ! OM_INTERNAL_DEBUG */
+    return omPrintRetInfo(info, i, fd, "\n  #%i at %L in %F ra=%p");
+}
+
+int _omPrintCurrentBackTrace(FILE* fd, OM_FLR_DECL)
+{
+  int i;
+  void* bt[OM_MAX_BACKTRACE_DEPTH];
+  
+  i = omGetBackTrace(bt, 1, OM_MAX_BACKTRACE_DEPTH);
+  return _omPrintBackTrace(bt, i, fd, OM_FLR_VAL);
+}
+
+#endif /* ! OM_NDEBUG */
+  
+  
+
+
+    
+    
+      
+    
+
Index: omalloc/omRet2Info.h
===================================================================
--- omalloc/omRet2Info.h	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
+++ omalloc/omRet2Info.h	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
@@ -0,0 +1,78 @@
+/*******************************************************************
+ *  File:    omAddr2Info.h
+ *  Purpose: translation of return addr to RetInfo
+ *  Author:  obachman (Olaf Bachmann)
+ *  Created: 11/99
+ *  Version: $Id: omRet2Info.h,v 1.1 2000-08-14 12:18:30 obachman Exp $
+ *******************************************************************/
+#ifndef OM_RET_2_INFO_H
+#define OM_RET_2_INFO_H
+
+
+struct omRetInfo_s
+{
+  void* addr;
+  char  func[100]; /* if you change these numbers, alos change */
+  char  file[100]; /* the fscanf statement in BackTrace_2_RetInfo */
+  int   line;
+};
+
+/* print to fd array of max RetInfo's and use fmt as format string for one RetInfo. 
+   The following conversions are recognized:
+    %i -- number of return addr
+    %p -- address (in hex)
+    %F -- functions
+    %f -- file
+    %l -- line
+    %L -- file:line
+   return how many lines were printed */
+#ifndef OM_NDEBUG
+int omPrintRetInfo(omRetInfo info, int max, FILE *fd, const char* fmt);
+/* translate array of max BackTrace addresses into array of max RetInfos 
+   return how many were translated */
+int omBackTrace_2_RetInfo(void** bt, omRetInfo info, int max);
+
+/* call with argv[0] to enable RetInfo translations */
+void omInitRet_2_Info(const char* argv0);
+
+int omPrintBackTrace(void** bt, int max, FILE* fd);
+int omPrintCurrentBackTrace(FILE* fd);
+
+int omFilterRetInfo_i(omRetInfo info, int max, int i);
+
+#define omFilterRetInfo(info, max, cond)        \
+do                                              \
+{                                               \
+  int _max = max;                               \
+  int _i = max -1;                              \
+  while (_i > 0)                                \
+  {                                             \
+    void* addr_i = info[_i].addr;               \
+    char* file_i = info[_i].file;               \
+    char* func_i = info[_i].func;               \
+    int   line_i = info[_i].line;               \
+                                                \
+    if (cond)                                   \
+      max = omFilterRetInfo_i(info, max, _i);   \
+    _i--;                                       \
+  }                                             \
+}                                               \
+while (0)
+
+
+/*BEGINPRIVATE*/
+int _omPrintBackTrace(void** bt, int max, FILE* fd, OM_FLR_DECL);
+int _omPrintCurrentBackTrace(FILE* fd, OM_FLR_DECL);
+/*ENDPRIVATE*/
+
+#else /* OM_NDEBUG */
+#define omPrintRetInfo(i, max, fd, fmt) ((void)0)
+#define omBackTrace_2_RetInfo(bt, i, m) ((void)0)
+#define omInitRet_2_Info(a)             ((void)0)
+#define omPrintBackTrace(bt,max,fd)     ((void)0)
+#define omPrintCurrentBackTrace(fd)     ((void)0)
+#define omFilterRetInfo_i(info,max,i)   ((void)0)
+#define omFilterRetInfo(info, max, cond)((void)0)
+#endif /* ! OM_NDEBUG */
+
+#endif /* OM_RET_2_INFO_H */
Index: omalloc/omReturn.h
===================================================================
--- omalloc/omReturn.h	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
+++ omalloc/omReturn.h	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
@@ -0,0 +1,277 @@
+/* slightly changed for use by omalloc.h */
+/*
+ * defines to get the return-address for non-dmalloc_lp malloc calls.
+ *
+ * Copyright 2000 by Gray Watson
+ *
+ * This file is part of the dmalloc package.
+ *
+ * Permission to use, copy, modify, and distribute this software for
+ * any purpose and without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies, and that the name of Gray Watson not be used in advertising
+ * or publicity pertaining to distribution of the document or software
+ * without specific, written prior permission.
+ *
+ * Gray Watson makes no representations about the suitability of the
+ * software described herein for any purpose.  It is provided "as is"
+ * without express or implied warranty.
+ *
+ * The author may be contacted via http://dmalloc.com/
+ *
+ * $Id: omReturn.h,v 1.1 2000-08-14 12:18:30 obachman Exp $
+ */
+
+/*
+ * This file contains the definition of the SET_RET_ADDR macro which
+ * is designed to contain the archecture/compiler specific hacks to
+ * determine the return-address from inside the malloc library.  With
+ * this information, the library can display caller information from
+ * calls that do not use the malloc_lp functions.
+ *
+ * Most of the archectures here have been contributed by other
+ * individuals and may need to be toggled a bit to remove local
+ * configuration differences.
+ *
+ * PLEASE send all submissions, comments, problems to the author.
+ *
+ * NOTE: examining the assembly code for x =
+ * __builtin_return_address(0); with gcc version 2+ should give you a
+ * good start on building a hack for your box.
+ */
+
+#ifndef __OM_RETURN_H__
+#define __OM_RETURN_H__
+
+/*************************************/
+
+/* for Sun SparcStations with GCC */
+#if __sparc && __GNUC__ > 1
+
+/*
+ * NOTE: %i7 seems to be more reliable than the [%fp+4] used by
+ * __builtin_return_address.  [%fp+4] is on the stack however, meaning
+ * it may be better -- less prone to be erased.  However, it produces
+ * some bogus data -- it seems to return the last return-address or
+ * something like that.
+ *
+ * Alexandre Oliva <oliva@dcc.unicamp.br> recently advised to change
+ * the "=g" to a "=m".  If you are having problems, you may want to
+ * return to the =g to see if it works.
+ */
+#define GET_RET_ADDR(file)	asm("st %%i7,%0" : \
+				    "=m" (file) : \
+				    /* no inputs */ )
+
+#if 0
+
+/* this was the default however =g was recommended to be changed to =m */
+#define GET_RET_ADDR(file)	asm("st %%i7,%0" : \
+				    "=g" (file) : \
+				    /* no inputs */ )
+
+/*
+ * This was what the gcc __builtin_return_address returned.  The above
+ * versions worked better.  It is here for reference purposes only.
+ */
+#define GET_RET_ADDR(file)	asm("ld [%%fp+4],%%o0; st %%o0,%0" : \
+					"=g" (file) : \
+					/* no inputs */ : \
+					"o0")
+#endif
+
+#endif /* __sparc */
+
+/*************************************/
+
+/* for i[34]86 machines with GCC */
+#if __i386 && __GNUC__ > 1
+
+#define GET_RET_ADDR(file)	asm("movl 4(%%ebp),%%eax ; movl %%eax,%0" : \
+				    "=g" (file) : \
+				    /* no inputs */ : \
+				    "eax")
+
+#endif /* __i386 */
+
+/*************************************/
+
+/*
+ * For DEC Mips machines running Ultrix
+ */
+#if __mips
+
+/*
+ * I have no idea how to get inline assembly with the default cc.
+ * Anyone know how?
+ */
+
+#if 0
+
+/*
+ * NOTE: we assume here that file is global.
+ *
+ * $31 is the frame pointer.  $2 looks to be the return address but maybe
+ * not consistently.
+ */
+#define GET_RET_ADDR(file)	asm("sw $2, file")
+
+#endif
+
+#endif /* __mips */
+
+/******************************* contributions *******************************/
+
+/*
+ * For DEC Alphas running OSF.  from Dave Hill <ddhill@zk3.dec.com>
+ * and Alexandre Oliva <oliva@dcc.unicamp.br>.  Thanks guys.
+ */
+#if __alpha
+
+#ifdef __GNUC__
+
+#define GET_RET_ADDR(file)	asm("bis $26, $26, %0" : "=r" (file))
+
+#else /* __GNUC__ */
+
+#include <c_asm.h>
+
+#define GET_RET_ADDR(file)	file = (char *)asm("bis %ra,%ra,%v0")
+
+#endif /* __GNUC__ */
+
+#endif /* __alpha */
+
+/*************************************/
+
+/*
+ * For Data General workstations running DG/UX 5.4R3.00 from Joerg
+ * Wunsch <joerg_wunsch@julia.tcd-dresden.de>.
+ */
+#ifdef __m88k__
+
+/*
+ * I have no ideas about the syntax of Motorola SVR[34] assemblers.
+ * Also, there may be occasions where gcc does not set up a stack
+ * frame for some function, so the returned value should be taken with
+ * a grain of salt. For the ``average'' function calls it proved to be
+ * correct anyway -- jw
+ */
+#if !__DGUX__ || _DGUXCOFF_TARGET
+# define M88K_RET_ADDR	"ld %0,r30,4"
+#else  /* __DGUX__ && !_DGUXCOFF_TARGET: DG/UX ELF with version 3 assembler */
+# define M88K_RET_ADDR	"ld %0,#r30,4"
+#endif
+
+#define GET_RET_ADDR(file)	asm(M88K_RET_ADDR : \
+				    "=r" (file) : \
+				    /* no inputs */)
+
+#endif /* m88k */
+
+/*************************************/
+
+/*
+ * SGI compilers implement a C level method of accessing the return
+ * address by simply referencing the __return_address symbol. -- James
+ * Bonfield <jkb@mrc-lmb.cam.ac.uk>
+ */
+#if defined(__sgi)
+
+#define GET_RET_ADDR(file)	file = (void *)__return_address
+
+#endif /* __sgi */
+
+/*************************************/
+
+/*
+ * Stratus FTX system (UNIX_System_V 4.0 FTX release 2.3.1.1 XA/R
+ * Model 310 Intel i860XP processor)
+ *
+ * I ended up with compiling according to full-ANSI rules (using the
+ * -Xa compiler option).  This I could only do after modifying the
+ * "dmalloc.h.3" in such a way that the malloc/calloc/realloc/free
+ * definitions would no longer cause the compiler to bark with
+ * 'identifier redeclared' (I just put an #ifdef _STDLIB_H ... #endif
+ * around those functions).  -- Wim_van_Duuren@stratus.com
+ */
+#if defined(_FTX) && defined(i860)
+
+/*
+ * we first have the define the little assembly code function
+ */
+asm void ASM_GET_RET_ADDR(file)
+{
+%       reg     file;
+        mov     %r1, file
+%       mem     file;
+        st.l    %r31,-40(%fp)
+        orh     file@ha, %r0, %r31
+        st.l    %r1, file@l(%r31)
+        ld.l    -40(%fp),%r31
+%       error
+}
+#define GET_RET_ADDR(file)	ASM_GET_RET_ADDR(file)
+
+#endif /* _FTX & i860 */
+
+/*************************************/
+
+/*
+ * For HP-UX PA-RISC with gcc/g++ from Jack Perdue
+ * <j-perdue@tamu.edu>.
+ */
+#if __hpux && __hppa && __GNUC__ > 1
+
+/*
+ * This is my very first line of PA-RISC assembly ever.  I have no
+ * idea if is correct, but it seems to work.  Register 2 (%r2)
+ * contains the return address.  The code generated by x =
+ * __builtin_return_address() was considerably longer and without a
+ * PA-RISC Instruction Set guide available (not even on the web), I
+ * just put togther little tidbits of knowledge I found while looking
+ * for one to take a stab with this.  Like I said, it seems to work on
+ * my g++ code under HPUX11 on a HP V-class system.  YMMV. -- Jack
+ * Perdue (j-perdue@tamu.edu)
+ */
+#define GET_RET_ADDR(file)  asm("stw %%r2, %0" : "=m" (file) :  );
+
+#endif
+
+/*************************************/
+
+/*
+ * For Powerpc 603 based system running LynxOS 2.3.1 using gcc/gas.
+ * From Shawn Carey <smc@questra.com>.
+ */
+#if defined(__powerpc__) && defined(__GNUC__) && !defined(__OPTIMIZE__)
+
+/*
+ * This won't compile if "-O2" is used, but it seems to work fine with
+ * "-O0".  I'm no assembler expert; I was happy enough to come up with
+ * something that works at all...  :-)
+ */
+
+#define GET_RET_ADDR(file) \
+do { \
+  asm("mflr 0"); \
+  asm("stw 0,%0" : "=g" (file)); \
+} while(0)
+
+#endif /* __powerpc__ && __GNUC__ && !__OPTIMIZE__ */
+
+/*************************************/
+
+/********************************** default **********************************/
+
+/* for all others, do nothing */
+#ifndef GET_RET_ADDR
+
+#if __GNUC__ > 1
+#define GET_RET_ADDR(file) (file = __builtin_return_address(0))
+#else
+#define GET_RET_ADDR(file)	(file = 0)
+#endif
+#endif /* __GNUC__ > 1 */
+
+#endif /* ! __OM_RETURN_H__ */
Index: omalloc/omStats.c
===================================================================
--- omalloc/omStats.c	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
+++ omalloc/omStats.c	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
@@ -0,0 +1,142 @@
+/*******************************************************************
+ *  File:    omStats.c
+ *  Purpose: definitions of stats related stuff
+ *  Author:  obachman (Olaf Bachmann)
+ *  Created: 11/99
+ *  Version: $Id: omStats.c,v 1.1 2000-08-14 12:18:31 obachman Exp $
+ *******************************************************************/
+#include <unistd.h>
+#include "omAlloc.h"
+#include "omMalloc.h"
+
+omInfo_t om_Info = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+unsigned long om_SbrkInit = 0;
+
+void omInitInfo()
+{
+#ifdef HAVE_SBRK
+  om_SbrkInit = (unsigned long) sbrk(0);
+#endif
+}
+
+void omUpdateInfo()
+{
+#ifdef OM_MALLOC_UPDATE_INFO
+  OM_MALLOC_UPDATE_INFO;
+#endif  
+
+  /* this can happen, since sizes are added as requested, and
+     subtracted as the real size of the memory */
+  if (om_Info.CurrentBytesFromMalloc < 0)
+    om_Info.CurrentBytesFromMalloc = 0;
+  
+  om_Info.UsedBytesFromValloc = omGetUsedBinBytes();
+  om_Info.AvailBytesFromValloc = om_Info.CurrentBytesFromValloc - om_Info.UsedBytesFromValloc;
+
+#ifdef OM_MALLOC_USED_BYTES
+  om_Info.UsedBytesMalloc = OM_MALLOC_USED_BYTES;
+#else
+  om_Info.UsedBytesMalloc = om_Info.CurrentBytesFromMalloc;
+#endif
+#ifdef OM_MALLOC_AVAIL_BYTES
+  om_Info.AvailBytesMalloc = OM_MALLOC_AVAIL_BYTES;
+#endif
+  
+  om_Info.UsedBytes = om_Info.UsedBytesMalloc + om_Info.UsedBytesFromValloc;
+  om_Info.AvailBytes = om_Info.AvailBytesMalloc + om_Info.AvailBytesFromValloc;
+
+#ifdef OM_HAVE_VALLOC_MMAP
+  om_Info.CurrentBytesMmap = om_Info.CurrentBytesFromValloc;
+  om_Info.MaxBytesMmap = om_Info.MaxBytesFromValloc;
+#endif
+#ifdef OM_MALLOC_CURRENT_BYTES_MMAP
+  om_Info.CurrentBytesMmap += OM_MALLOC_CURRENT_BYTES_MMAP;
+#endif
+#ifdef OM_MALLOC_MAX_BYTES_MMAP
+  om_Info.MaxBytesMmap += OM_MALLOC_MAX_BYTES_MMAP;
+#endif
+
+#ifndef OM_MALLOC_CURRENT_BYTES_SBRK
+#ifdef HAVE_SBRK  
+  if (om_SbrkInit)
+  {
+    om_Info.CurrentBytesSbrk = (unsigned long) sbrk(0) - om_SbrkInit;
+    if (om_Info.CurrentBytesSbrk > om_Info.MaxBytesSbrk)
+      om_Info.MaxBytesSbrk = om_Info.CurrentBytesSbrk;
+  }
+  else
+  {
+    om_SbrkInit = (unsigned long) sbrk(0);
+  }
+#endif
+#else
+  om_Info.CurrentBytesSbrk = OM_MALLOC_CURRENT_BYTES_SBRK;
+#ifdef OM_MALLOC_MAX_BYTES_SBRK
+  om_Info.MaxBytesSbrk = OM_MALLOC_MAX_BYTES_SBRK;
+#else
+    if (om_Info.CurrentBytesSbrk > om_Info.MaxBytesSbrk) 
+      om_Info.MaxBytesSbrk = om_Info.CurrentBytesSbrk;
+#endif  
+#endif
+
+#ifdef OM_MALLOC_CURRENT_BYTES_SYSTEM
+  om_Info.CurrentBytesSystem = OM_MALLOC_CURRENT_BYTES_SYSTEM;
+#else
+  om_Info.CurrentBytesSystem = 
+    (om_Info.CurrentBytesSbrk > om_Info.UsedBytesMalloc ? 
+     om_Info.CurrentBytesSbrk : om_Info.UsedBytesMalloc);
+#endif
+#ifdef OM_HAVE_VALLOC_MMAP
+  om_Info.CurrentBytesSystem += om_Info.CurrentBytesFromValloc;
+#endif
+
+#if ! (defined(OM_HAVE_VALLOC_MMAP) && defined(OM_MALLOC_MAX_BYTES_SYSTEM))
+#ifdef OM_MALLOC_MAX_BYTES_SYSTEM
+  om_Info.MaxBytesSystem = OM_MALLOC_MAX_BYTES_SYSTEM;
+#else
+  om_Info.MaxBytesSystem = 
+    (om_Info.MaxBytesSbrk + om_Info.MaxBytesMmap > 
+     om_Info.MaxBytesFromMalloc + om_Info.MaxBytesFromValloc ?
+     om_Info.MaxBytesSbrk + om_Info.MaxBytesMmap :
+     om_Info.MaxBytesFromMalloc + om_Info.MaxBytesFromValloc);
+#endif
+#endif  
+}
+
+omInfo_t omGetInfo()
+{
+  omUpdateInfo();
+  return om_Info;
+}
+
+void omPrintStats(FILE* fd)
+{
+  omUpdateInfo();
+  fprintf(fd, "System %ldk:%ldk Appl %ldk/%ldk Malloc %ldk/%ldk Valloc %ldk/%ldk Pages %ld/%ld Regions %ld:%ld\n",
+          om_Info.CurrentBytesSystem/1024, om_Info.MaxBytesSystem/1024,
+          om_Info.UsedBytes/1024, om_Info.AvailBytes/1024,
+          om_Info.UsedBytesMalloc/1024, om_Info.AvailBytesMalloc/1024,
+          om_Info.CurrentBytesFromValloc/1024, om_Info.AvailBytesFromValloc/1024,
+          om_Info.UsedPages, om_Info.AvailPages,
+          om_Info.CurrentRegionsAlloc, om_Info.MaxRegionsAlloc);
+}
+
+
+void omPrintInfo(FILE* fd)
+{
+  omUpdateInfo();
+  fprintf(fd, "                  Current:       Max:\n");
+  fprintf(fd, "BytesSystem:     %8ldk  %8ldk\n", om_Info.CurrentBytesSystem/1024, om_Info.MaxBytesSystem/1024);
+  fprintf(fd, "BytesSbrk:       %8ldk  %8ldk\n", om_Info.CurrentBytesSbrk/1024, om_Info.MaxBytesSbrk/1024);
+  fprintf(fd, "BytesMmap:       %8ldk  %8ldk\n", om_Info.CurrentBytesMmap/1024, om_Info.MaxBytesMmap/1024);
+  fprintf(fd, "BytesFromMalloc: %8ldk  %8ldk\n", om_Info.CurrentBytesFromMalloc/1024, om_Info.MaxBytesFromMalloc/1024);
+  fprintf(fd, "BytesFromValloc: %8ldk  %8ldk\n", om_Info.CurrentBytesFromValloc/1024, om_Info.MaxBytesFromValloc/1024);
+  fprintf(fd, "PagesAlloc:      %8ld   %8ld \n", om_Info.UsedPages, om_Info.MaxPages);
+  fprintf(fd, "RegionsAlloc:    %8ld   %8ld \n", om_Info.CurrentRegionsAlloc, om_Info.MaxRegionsAlloc);
+  fprintf(fd, "                     Used:     Avail:\n");
+  fprintf(fd, "BytesAppl:       %8ldk  %8ldk\n", om_Info.UsedBytes/1024, om_Info.AvailBytes/1024);
+  fprintf(fd, "BytesMalloc:     %8ldk  %8ldk\n", om_Info.UsedBytesMalloc/1024, om_Info.AvailBytesMalloc/1024);
+  fprintf(fd, "BytesValloc:     %8ldk  %8ldk\n", om_Info.UsedBytesFromValloc/1024, om_Info.AvailBytesFromValloc/1024);
+  fprintf(fd, "Pages:           %8ld   %8ld\n", om_Info.UsedPages, om_Info.AvailPages);
+}
Index: omalloc/omStats.h
===================================================================
--- omalloc/omStats.h	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
+++ omalloc/omStats.h	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
@@ -0,0 +1,53 @@
+/*******************************************************************
+ *  File:    omStats.h
+ *  Purpose: declaration of statistics related stuff
+ *  Author:  obachman (Olaf Bachmann)
+ *  Created: 11/99
+ *  Version: $Id: omStats.h,v 1.1 2000-08-14 12:18:31 obachman Exp $
+ *******************************************************************/
+#ifndef OM_STATS_H
+#define OM_STATS_H
+
+struct omInfo_s
+{
+  long MaxBytesSystem;      /* set in omUpdateInfo(), is more accurate with malloc support   */
+  long CurrentBytesSystem;  /* set in omUpdateInfo(), is more accurate with malloc support */
+  long MaxBytesSbrk;        /* always up-to-date, not very accurate, needs omInintInfo() */
+  long CurrentBytesSbrk;    /* set in omUpdateInfo(), needs omInintInfo() */
+  long MaxBytesMmap;        /* set in omUpdateInfo(), not very accurate */
+  long CurrentBytesMmap;    /* set in omUpdateInfo(), not very accurate */
+  long UsedBytes;           /* set in omUpdateInfo() */ 
+  long AvailBytes;          /* set in omUpdateInfo() */ 
+  long UsedBytesMalloc;     /* set in omUpdateInfo(), needs malloc support */ 
+  long AvailBytesMalloc;    /* set in omUpdateInfo(), needs malloc support */ 
+  long MaxBytesFromMalloc;      /* always kept up-to-date */
+  long CurrentBytesFromMalloc;  /* always kept up-to-date */
+  long MaxBytesFromValloc;      /* always kept up-to-date */
+  long CurrentBytesFromValloc;  /* always kept up-to-date */
+  long UsedBytesFromValloc; /* set in omUpdateInfo()  */
+  long AvailBytesFromValloc;/* set in omUpdateInfo()  */
+  long MaxPages;            /* always kept up-to-date */
+  long UsedPages;           /* always kept up-to-date */
+  long AvailPages;          /* always kept up-to-date */
+  long MaxRegionsAlloc;     /* always kept up-to-date */
+  long CurrentRegionsAlloc; /* always kept up-to-date */
+};
+
+/* returns a copy of omallinfo struct */
+extern struct omInfo_s omGetInfo();
+/* the struct itself which is always up-to-date */
+/* use read-only */
+extern struct omInfo_s om_Info;
+/* update the global info struct */
+extern void omUpdateInfo();
+/* initialize such that sbrk can be measured */
+extern void omInitInfo();
+extern void omPrintStats(FILE* fd);
+extern void omPrintInfo(FILE* fd);
+
+/*BEGINPRIVATE*/
+/* used internally to keep track of sbrk */
+extern unsigned long om_SbrkInit;
+/*ENDPRIVATE*/
+#endif /* OM_STATS_H */
+
Index: omalloc/omStructs.h
===================================================================
--- omalloc/omStructs.h	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
+++ omalloc/omStructs.h	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
@@ -0,0 +1,38 @@
+/*******************************************************************
+ *  File:    omStructs.h
+ *  Purpose: declaration of structs and typedefs of omalloc
+ *  Author:  obachman (Olaf Bachmann)
+ *  Created: 11/99
+ *  Version: $Id: omStructs.h,v 1.1 2000-08-14 12:18:31 obachman Exp $
+ *******************************************************************/
+#ifndef OM_STRUCTS_H
+#define OM_STRUCTS_H
+
+struct omBin_s;
+typedef struct omBin_s      omBin_t;
+typedef omBin_t*            omBin;
+
+struct omBinPage_s;
+typedef struct omBinPage_s  omBinPage_t;
+typedef omBinPage_t*        omBinPage;
+
+struct omBinPageRegion_s;
+typedef struct omBinPageRegion_s omBinPageRegion_t;
+typedef omBinPageRegion_t* omBinPageRegion;
+
+struct omOpts_s;
+typedef struct omOpts_s omOpts_t;
+
+struct omInfo_s;
+typedef struct omInfo_s omInfo_t;
+
+struct omSpecBin_s;
+typedef struct omSpecBin_s omSpecBin_t;
+typedef omSpecBin_t*        omSpecBin;
+
+struct omRetInfo_s;
+typedef struct omRetInfo_s omRetInfo_t;
+typedef omRetInfo_t*        omRetInfo;
+
+#endif /* OM_STRUCTS_H */
+
Index: omalloc/omalloc.c
===================================================================
--- omalloc/omalloc.c	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
+++ omalloc/omalloc.c	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
@@ -0,0 +1,113 @@
+/*******************************************************************
+ *  File:    omalloc.c
+ *  Purpose: implementation of ANSI-C conforming malloc functions
+ *           -- the real version
+ *  Author:  obachman@mathematik.uni-kl.de (Olaf Bachmann)
+ *  Created: 11/99
+ *  Version: $Id: omalloc.c,v 1.1 2000-08-14 12:18:31 obachman Exp $
+ *******************************************************************/
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#ifndef OMALLOC_C
+#define OMALLOC_C
+
+#include <omalloc.h>
+
+#ifdef OM_MALLOC_MARK_AS_STATIC
+#define OM_MARK_AS_STATIC(addr) omMarkAsStaticAddr(addr)
+#else
+#define OM_MARK_AS_STATIC(addr) ((void)0)
+#endif
+
+void* calloc(size_t nmemb, size_t size)
+{
+  void* addr;
+  if (size == 0) size = 1;
+  if (nmemb == 0) nmemb = 1;
+  
+  size = size*nmemb;
+  omTypeAlloc0Aligned(void*, addr, size);
+  OM_MARK_AS_STATIC(addr);
+  return addr;
+}
+  
+void* malloc(size_t size)
+{
+  void* addr;
+  if (size == 0) size = 1;
+  
+  omTypeAllocAligned(void*, addr, size);
+  OM_MARK_AS_STATIC(addr);
+  return addr;
+}
+
+void free(void* addr)
+{
+  omfree(addr);
+}
+
+void* valloc(size_t size)
+{
+  fprintf(stderr, "omalloc Warning: valloc not yet implemented\n");
+  fflush(NULL);
+  return NULL;
+}
+
+void* memalign(void* alignment, size_t size)
+{
+  fprintf(stderr, "omalloc Warning: memalign not yet implemented\n");
+  fflush(NULL);
+  return NULL;
+}
+
+void* realloc(void* old_addr, size_t new_size)
+{
+  if (old_addr && new_size)
+  {
+    void* new_addr;
+    omTypeReallocAligned(old_addr, void*, new_addr, new_size);
+    OM_MARK_AS_STATIC(new_addr);
+    return new_addr;
+  }
+  else 
+  {
+    free(old_addr);
+    return malloc(new_size);
+  }
+}
+
+char* strdup(const char* addr)
+{
+  char* n_s;
+  if (addr)
+  {
+    n_s = omStrDup(addr);
+    OM_MARK_AS_STATIC(n_s);
+    return n_s;
+  }
+  return NULL;
+}
+
+void freeSize(void* addr, size_t size)
+{
+  if (addr) omFreeSize(addr, size);
+}
+
+void* reallocSize(void* old_addr, size_t old_size, size_t new_size)
+{
+  if (old_addr && new_size)
+  {
+   void* new_addr;
+    omTypeReallocAlignedSize(old_addr, old_size, void*, new_addr, new_size);
+    OM_MARK_AS_STATIC(new_addr);
+    return new_addr;
+  }
+  else 
+  {
+    freeSize(old_addr, old_size);
+    return malloc(new_size);
+  }
+}
+#endif
Index: omalloc/omalloc_debug.c
===================================================================
--- omalloc/omalloc_debug.c	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
+++ omalloc/omalloc_debug.c	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
@@ -0,0 +1,20 @@
+/*******************************************************************
+ *  File:    omalloc_debug.c
+ *  Purpose: implementation of ANSI-C conforming malloc functions
+ *           -- debug versions
+ *  Author:  obachman@mathematik.uni-kl.de (Olaf Bachmann)
+ *  Created: 11/99
+ *  Version: $Id: omalloc_debug.c,v 1.1 2000-08-14 12:18:31 obachman Exp $
+ *******************************************************************/
+#include "omDefaultConfig.h"
+
+#define OM_TRACK OM_DEFAULT_MIN_TRACK
+#define OM_CHECK OM_DEFAULT_MIN_CHECK
+
+#if OM_CHECK <= 0
+#undef OM_CHECK
+#define OM_CHECK 1
+#endif
+
+#include "omalloc.c"
+
Index: omalloc/omalloc_provide.c
===================================================================
--- omalloc/omalloc_provide.c	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
+++ omalloc/omalloc_provide.c	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
@@ -0,0 +1,18 @@
+/*******************************************************************
+ *  File:    omalloc_provide.c
+ *  Purpose: implementation of ANSI-C conforming which are to be provided
+ *           by omalloc library
+ *  Author:  obachman@mathematik.uni-kl.de (Olaf Bachmann)
+ *  Created: 11/99
+ *  Version: $Id: omalloc_provide.c,v 1.1 2000-08-14 12:18:31 obachman Exp $
+ *******************************************************************/
+#include "omConfig.h"
+
+#if OM_PROVIDE_MALLOC > 0
+#if OM_PROVIDE_MALLOC > 1
+#include "omalloc_debug.c"
+#else
+#include "omalloc.c"
+#endif
+#endif
+
Index: omalloc/pmalloc.c
===================================================================
--- omalloc/pmalloc.c	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
+++ omalloc/pmalloc.c	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
@@ -0,0 +1,1677 @@
+/*******************************************************************
+ *  File:    pmalloc.h
+ *  Purpose: implementation of malloc from Perl's 5.005 distribution
+ *
+ *  Version: $Id: pmalloc.c,v 1.1 2000-08-14 12:18:32 obachman Exp $
+ *******************************************************************/
+
+#include "omMalloc.h"
+
+
+/*    malloc.c
+ *
+ */
+
+/*
+  Here are some notes on configuring Perl's malloc.
+ 
+  There are two macros which serve as bulk disablers of advanced
+  features of this malloc: NO_FANCY_MALLOC, PLAIN_MALLOC (undef by
+  default).  Look in the list of default values below to understand
+  their exact effect.  Defining NO_FANCY_MALLOC returns malloc.c to the
+  state of the malloc in Perl 5.004.  Additionally defining PLAIN_MALLOC
+  returns it to the state as of Perl 5.000.
+
+  Note that some of the settings below may be ignored in the code based
+  on values of other macros.  The PERL_CORE symbol is only defined when
+  perl itself is being compiled (so malloc can make some assumptions
+  about perl's facilities being available to it).
+
+  Each config option has a short description, followed by its name,
+  default value, and a comment about the default (if applicable).  Some
+  options take a precise value, while the others are just boolean.
+  The boolean ones are listed first.
+
+    # Enable code for an emergency memory pool in $^M.  See perlvar.pod
+    # for a description of $^M.
+    PERL_EMERGENCY_SBRK		(!PLAIN_MALLOC && PERL_CORE)
+
+    # Enable code for printing memory statistics.
+    DEBUGGING_MSTATS		(!PLAIN_MALLOC && PERL_CORE)
+
+    # Move allocation info for small buckets into separate areas.
+    # Memory optimization (especially for small allocations, of the
+    # less than 64 bytes).  Since perl usually makes a large number
+    # of small allocations, this is usually a win.
+    PACK_MALLOC			(!PLAIN_MALLOC && !RCHECK)
+
+    # Add one page to big powers of two when calculating bucket size.
+    # This is targeted at big allocations, as are common in image
+    # processing.
+    TWO_POT_OPTIMIZE		!PLAIN_MALLOC
+ 
+    # Use intermediate bucket sizes between powers-of-two.  This is
+    # generally a memory optimization, and a (small) speed pessimization.
+    BUCKETS_ROOT2		!NO_FANCY_MALLOC
+
+    # Do not check small deallocations for bad free().  Memory
+    # and speed optimization, error reporting pessimization.
+    IGNORE_SMALL_BAD_FREE	(!NO_FANCY_MALLOC && !RCHECK)
+
+    # Use table lookup to decide in which bucket a given allocation will go.
+    SMALL_BUCKET_VIA_TABLE	!NO_FANCY_MALLOC
+
+    # Use a perl-defined sbrk() instead of the (presumably broken or
+    # missing) system-supplied sbrk().
+    USE_PERL_SBRK		undef
+
+    # Use system malloc() (or calloc() etc.) to emulate sbrk(). Normally
+    # only used with broken sbrk()s.
+    PERL_SBRK_VIA_MALLOC	undef
+
+    # Which allocator to use if PERL_SBRK_VIA_MALLOC
+    SYSTEM_ALLOC(a) 		malloc(a)
+
+    # Disable memory overwrite checking with DEBUGGING.  Memory and speed
+    # optimization, error reporting pessimization.
+    NO_RCHECK			undef
+
+    # Enable memory overwrite checking with DEBUGGING.  Memory and speed
+    # pessimization, error reporting optimization
+    RCHECK			(DEBUGGING && !NO_RCHECK)
+
+    # Failed allocations bigger than this size croak (if
+    # PERL_EMERGENCY_SBRK is enabled) without touching $^M.  See
+    # perlvar.pod for a description of $^M.
+    BIG_SIZE			 (1<<16)	# 64K
+
+    # Starting from this power of two, add an extra page to the
+    # size of the bucket. This enables optimized allocations of sizes
+    # close to powers of 2.  Note that the value is indexed at 0.
+    FIRST_BIG_POW2 		15		# 32K, 16K is used too often
+
+    # Estimate of minimal memory footprint.  malloc uses this value to
+    # request the most reasonable largest blocks of memory from the system.
+    FIRST_SBRK 			(48*1024)
+
+    # Round up sbrk()s to multiples of this.
+    MIN_SBRK 			2048
+
+    # Round up sbrk()s to multiples of this percent of footprint.
+    MIN_SBRK_FRAC 		3
+
+    # Add this much memory to big powers of two to get the bucket size.
+    PERL_PAGESIZE 		4096
+
+    # This many sbrk() discontinuities should be tolerated even
+    # from the start without deciding that sbrk() is usually
+    # discontinuous.
+    SBRK_ALLOW_FAILURES		3
+
+    # This many continuous sbrk()s compensate for one discontinuous one.
+    SBRK_FAILURE_PRICE		50
+
+    # Some configurations may ask for 12-byte-or-so allocations which
+    # require 8-byte alignment (?!).  In such situation one needs to
+    # define this to disable 12-byte bucket (will increase memory footprint)
+    STRICT_ALIGNMENT		undef
+
+  This implementation assumes that calling PerlIO_printf() does not
+  result in any memory allocation calls (used during a panic).
+
+ */
+
+#ifndef NO_FANCY_MALLOC
+#  ifndef SMALL_BUCKET_VIA_TABLE
+#    define SMALL_BUCKET_VIA_TABLE
+#  endif 
+#  ifndef BUCKETS_ROOT2
+#    define BUCKETS_ROOT2
+#  endif 
+#  ifndef IGNORE_SMALL_BAD_FREE
+#    define IGNORE_SMALL_BAD_FREE
+#  endif 
+#endif 
+
+#ifndef PLAIN_MALLOC			/* Bulk enable features */
+#  ifndef PACK_MALLOC
+#      define PACK_MALLOC
+#  endif 
+#  ifndef TWO_POT_OPTIMIZE
+#    define TWO_POT_OPTIMIZE
+#  endif 
+#  if defined(PERL_CORE) && !defined(PERL_EMERGENCY_SBRK)
+#    define PERL_EMERGENCY_SBRK
+#  endif 
+#  if defined(PERL_CORE) && !defined(DEBUGGING_MSTATS)
+#    define DEBUGGING_MSTATS
+#  endif 
+#endif
+
+#define MIN_BUC_POW2 (sizeof(void*) > 4 ? 3 : 2) /* Allow for 4-byte arena. */
+#define MIN_BUCKET (MIN_BUC_POW2 * BUCKETS_PER_POW2)
+
+#if !(defined(I286) || defined(atarist) || defined(__MINT__))
+	/* take 2k unless the block is bigger than that */
+#  define LOG_OF_MIN_ARENA 11
+#else
+	/* take 16k unless the block is bigger than that 
+	   (80286s like large segments!), probably good on the atari too */
+#  define LOG_OF_MIN_ARENA 14
+#endif
+
+#ifndef lint
+#  if defined(DEBUGGING) && !defined(NO_RCHECK)
+#    define RCHECK
+#  endif
+#  if defined(RCHECK) && defined(IGNORE_SMALL_BAD_FREE)
+#    undef IGNORE_SMALL_BAD_FREE
+#  endif 
+/*
+ * malloc.c (Caltech) 2/21/82
+ * Chris Kingsley, kingsley@cit-20.
+ *
+ * This is a very fast storage allocator.  It allocates blocks of a small 
+ * number of different sizes, and keeps free lists of each size.  Blocks that
+ * don't exactly fit are passed up to the next larger size.  In this 
+ * implementation, the available sizes are 2^n-4 (or 2^n-12) bytes long.
+ * If PACK_MALLOC is defined, small blocks are 2^n bytes long.
+ * This is designed for use in a program that uses vast quantities of memory,
+ * but bombs when it runs out. 
+ */
+
+#ifdef PERL_CORE
+#  include "EXTERN.h"
+#  include "perl.h"
+#else
+#  ifdef PERL_FOR_X2P
+#    include "../EXTERN.h"
+#    include "../perl.h"
+#  else
+#    include <stdlib.h>
+#    include <stdio.h>
+#    include <memory.h>
+#    define _(arg) arg
+#    ifndef Malloc_t
+#      define Malloc_t void *
+#    endif
+#    ifndef MEM_SIZE
+#      define MEM_SIZE unsigned long
+#    endif
+#    ifndef LONG_MAX
+#      define LONG_MAX 0x7FFFFFFF
+#    endif
+#    ifndef UV
+#      define UV unsigned long
+#    endif
+#    ifndef caddr_t
+#      define caddr_t char *
+#    endif
+#    ifndef Free_t
+#      define Free_t void
+#    endif
+#    define Copy(s,d,n,t) (void)memcpy((char*)(d),(char*)(s), (n) * sizeof(t))
+#    define PerlEnv_getenv getenv
+#    define PerlIO_printf fprintf
+#    define PerlIO_stderr() stderr
+#  endif
+#  ifndef croak				/* make depend */
+#    define croak(mess, arg) do {warn((mess), (arg)); exit(1);} while(0)
+#  endif 
+#  ifndef warn
+#    define warn(mess, arg) do {fprintf(stderr, (mess), (arg));} while(0)
+#  endif 
+#  ifdef DEBUG_m
+#    undef DEBUG_m
+#  endif 
+#  define DEBUG_m(a)
+#  ifdef DEBUGGING
+#     undef DEBUGGING
+#  endif
+#endif
+
+#ifndef MUTEX_LOCK
+#  define MUTEX_LOCK(l)
+#endif 
+
+#ifndef MUTEX_UNLOCK
+#  define MUTEX_UNLOCK(l)
+#endif 
+
+#ifdef DEBUGGING
+#  undef DEBUG_m
+#  define DEBUG_m(a)  if (PL_debug & 128)   a
+#endif
+
+/* I don't much care whether these are defined in sys/types.h--LAW */
+
+#define u_char unsigned char
+#define u_int unsigned int
+
+#ifdef HAS_QUAD
+#  define u_bigint UV			/* Needs to eat *void. */
+#else  /* needed? */
+#  define u_bigint unsigned long	/* Needs to eat *void. */
+#endif
+
+#define u_short unsigned short
+
+/* 286 and atarist like big chunks, which gives too much overhead. */
+#if (defined(RCHECK) || defined(I286) || defined(atarist) || defined(__MINT__)) && defined(PACK_MALLOC)
+#  undef PACK_MALLOC
+#endif 
+
+/*
+ * The description below is applicable if PACK_MALLOC is not defined.
+ *
+ * The overhead on a block is at least 4 bytes.  When free, this space
+ * contains a pointer to the next free block, and the bottom two bits must
+ * be zero.  When in use, the first byte is set to MAGIC, and the second
+ * byte is the size index.  The remaining bytes are for alignment.
+ * If range checking is enabled and the size of the block fits
+ * in two bytes, then the top two bytes hold the size of the requested block
+ * plus the range checking words, and the header word MINUS ONE.
+ */
+union	overhead {
+	union	overhead *ov_next;	/* when free */
+#if MEM_ALIGNBYTES > 4
+	double	strut;			/* alignment problems */
+#endif
+	struct {
+		u_char	ovu_magic;	/* magic number */
+		u_char	ovu_index;	/* bucket # */
+#ifdef RCHECK
+		u_short	ovu_size;	/* actual block size */
+		u_int	ovu_rmagic;	/* range magic number */
+#endif
+	} ovu;
+#define	ov_magic	ovu.ovu_magic
+#define	ov_index	ovu.ovu_index
+#define	ov_size		ovu.ovu_size
+#define	ov_rmagic	ovu.ovu_rmagic
+};
+
+#ifdef DEBUGGING
+static void botch _((char *diag, char *s));
+#endif
+static void morecore _((int bucket));
+static int findbucket _((union overhead *freep, int srchlen));
+static void add_to_chain(void *p, MEM_SIZE size, MEM_SIZE chip);
+
+#define	MAGIC		0xff		/* magic # on accounting info */
+#define RMAGIC		0x55555555	/* magic # on range info */
+#define RMAGIC_C	0x55		/* magic # on range info */
+
+#ifdef RCHECK
+#  define	RSLOP		sizeof (u_int)
+#  ifdef TWO_POT_OPTIMIZE
+#    define MAX_SHORT_BUCKET (12 * BUCKETS_PER_POW2)
+#  else
+#    define MAX_SHORT_BUCKET (13 * BUCKETS_PER_POW2)
+#  endif 
+#else
+#  define	RSLOP		0
+#endif
+
+#if !defined(PACK_MALLOC) && defined(BUCKETS_ROOT2)
+#  undef BUCKETS_ROOT2
+#endif 
+
+#ifdef BUCKETS_ROOT2
+#  define BUCKET_TABLE_SHIFT 2
+#  define BUCKET_POW2_SHIFT 1
+#  define BUCKETS_PER_POW2 2
+#else
+#  define BUCKET_TABLE_SHIFT MIN_BUC_POW2
+#  define BUCKET_POW2_SHIFT 0
+#  define BUCKETS_PER_POW2 1
+#endif 
+
+#if !defined(MEM_ALIGNBYTES) || ((MEM_ALIGNBYTES > 4) && !defined(STRICT_ALIGNMENT))
+/* Figure out the alignment of void*. */
+struct aligner {
+  char c;
+  void *p;
+};
+#  define ALIGN_SMALL ((int)((caddr_t)&(((struct aligner*)0)->p)))
+#else
+#  define ALIGN_SMALL MEM_ALIGNBYTES
+#endif
+
+#define IF_ALIGN_8(yes,no)	((ALIGN_SMALL>4) ? (yes) : (no))
+
+#ifdef BUCKETS_ROOT2
+#  define MAX_BUCKET_BY_TABLE 13
+static u_short buck_size[MAX_BUCKET_BY_TABLE + 1] = 
+  { 
+      0, 0, 0, 0, 4, 4, 8, 12, 16, 24, 32, 48, 64, 80,
+  };
+#  define BUCKET_SIZE(i) ((i) % 2 ? buck_size[i] : (1 << ((i) >> BUCKET_POW2_SHIFT)))
+#  define BUCKET_SIZE_REAL(i) ((i) <= MAX_BUCKET_BY_TABLE		\
+			       ? buck_size[i] 				\
+			       : ((1 << ((i) >> BUCKET_POW2_SHIFT))	\
+				  - MEM_OVERHEAD(i)			\
+				  + POW2_OPTIMIZE_SURPLUS(i)))
+#else
+#  define BUCKET_SIZE(i) (1 << ((i) >> BUCKET_POW2_SHIFT))
+#  define BUCKET_SIZE_REAL(i) (BUCKET_SIZE(i) - MEM_OVERHEAD(i) + POW2_OPTIMIZE_SURPLUS(i))
+#endif 
+
+
+#ifdef PACK_MALLOC
+/* In this case it is assumed that if we do sbrk() in 2K units, we
+ * will get 2K aligned arenas (at least after some initial
+ * alignment). The bucket number of the given subblock is on the start
+ * of 2K arena which contains the subblock.  Several following bytes
+ * contain the magic numbers for the subblocks in the block.
+ *
+ * Sizes of chunks are powers of 2 for chunks in buckets <=
+ * MAX_PACKED, after this they are (2^n - sizeof(union overhead)) (to
+ * get alignment right).
+ *
+ * Consider an arena for 2^n with n>MAX_PACKED.  We suppose that
+ * starts of all the chunks in a 2K arena are in different
+ * 2^n-byte-long chunks.  If the top of the last chunk is aligned on a
+ * boundary of 2K block, this means that sizeof(union
+ * overhead)*"number of chunks" < 2^n, or sizeof(union overhead)*2K <
+ * 4^n, or n > 6 + log2(sizeof()/2)/2, since a chunk of size 2^n -
+ * overhead is used.  Since this rules out n = 7 for 8 byte alignment,
+ * we specialcase allocation of the first of 16 128-byte-long chunks.
+ *
+ * Note that with the above assumption we automatically have enough
+ * place for MAGIC at the start of 2K block.  Note also that we
+ * overlay union overhead over the chunk, thus the start of small chunks
+ * is immediately overwritten after freeing.  */
+#  define MAX_PACKED_POW2 6
+#  define MAX_PACKED (MAX_PACKED_POW2 * BUCKETS_PER_POW2 + BUCKET_POW2_SHIFT)
+#  define MAX_POW2_ALGO ((1<<(MAX_PACKED_POW2 + 1)) - M_OVERHEAD)
+#  define TWOK_MASK ((1<<LOG_OF_MIN_ARENA) - 1)
+#  define TWOK_MASKED(x) ((u_bigint)(x) & ~TWOK_MASK)
+#  define TWOK_SHIFT(x) ((u_bigint)(x) & TWOK_MASK)
+#  define OV_INDEXp(block) ((u_char*)(TWOK_MASKED(block)))
+#  define OV_INDEX(block) (*OV_INDEXp(block))
+#  define OV_MAGIC(block,bucket) (*(OV_INDEXp(block) +			\
+				    (TWOK_SHIFT(block)>>		\
+				     (bucket>>BUCKET_POW2_SHIFT)) +	\
+				    (bucket >= MIN_NEEDS_SHIFT ? 1 : 0)))
+    /* A bucket can have a shift smaller than it size, we need to
+       shift its magic number so it will not overwrite index: */
+#  ifdef BUCKETS_ROOT2
+#    define MIN_NEEDS_SHIFT (7*BUCKETS_PER_POW2 - 1) /* Shift 80 greater than chunk 64. */
+#  else
+#    define MIN_NEEDS_SHIFT (7*BUCKETS_PER_POW2) /* Shift 128 greater than chunk 32. */
+#  endif 
+#  define CHUNK_SHIFT 0
+
+/* Number of active buckets of given ordinal. */
+#ifdef IGNORE_SMALL_BAD_FREE
+#define FIRST_BUCKET_WITH_CHECK (6 * BUCKETS_PER_POW2) /* 64 */
+#  define N_BLKS(bucket) ( (bucket) < FIRST_BUCKET_WITH_CHECK 		\
+			 ? ((1<<LOG_OF_MIN_ARENA) - 1)/BUCKET_SIZE(bucket) \
+			 : n_blks[bucket] )
+#else
+#  define N_BLKS(bucket) n_blks[bucket]
+#endif 
+
+static u_short n_blks[LOG_OF_MIN_ARENA * BUCKETS_PER_POW2] = 
+  {
+#  if BUCKETS_PER_POW2==1
+      0, 0,
+      (MIN_BUC_POW2==2 ? 384 : 0),
+      224, 120, 62, 31, 16, 8, 4, 2
+#  else
+      0, 0, 0, 0,
+      (MIN_BUC_POW2==2 ? 384 : 0), (MIN_BUC_POW2==2 ? 384 : 0),	/* 4, 4 */
+      224, 149, 120, 80, 62, 41, 31, 25, 16, 16, 8, 8, 4, 4, 2, 2
+#  endif
+  };
+
+/* Shift of the first bucket with the given ordinal inside 2K chunk. */
+#ifdef IGNORE_SMALL_BAD_FREE
+#  define BLK_SHIFT(bucket) ( (bucket) < FIRST_BUCKET_WITH_CHECK 	\
+			      ? ((1<<LOG_OF_MIN_ARENA)			\
+				 - BUCKET_SIZE(bucket) * N_BLKS(bucket)) \
+			      : blk_shift[bucket])
+#else
+#  define BLK_SHIFT(bucket) blk_shift[bucket]
+#endif 
+
+static u_short blk_shift[LOG_OF_MIN_ARENA * BUCKETS_PER_POW2] = 
+  { 
+#  if BUCKETS_PER_POW2==1
+      0, 0,
+      (MIN_BUC_POW2==2 ? 512 : 0),
+      256, 128, 64, 64,			/* 8 to 64 */
+      16*sizeof(union overhead), 
+      8*sizeof(union overhead), 
+      4*sizeof(union overhead), 
+      2*sizeof(union overhead), 
+#  else
+      0, 0, 0, 0,
+      (MIN_BUC_POW2==2 ? 512 : 0), (MIN_BUC_POW2==2 ? 512 : 0),
+      256, 260, 128, 128, 64, 80, 64, 48, /* 8 to 96 */
+      16*sizeof(union overhead), 16*sizeof(union overhead), 
+      8*sizeof(union overhead), 8*sizeof(union overhead), 
+      4*sizeof(union overhead), 4*sizeof(union overhead), 
+      2*sizeof(union overhead), 2*sizeof(union overhead), 
+#  endif 
+  };
+
+#else  /* !PACK_MALLOC */
+
+#  define OV_MAGIC(block,bucket) (block)->ov_magic
+#  define OV_INDEX(block) (block)->ov_index
+#  define CHUNK_SHIFT 1
+#  define MAX_PACKED -1
+#endif /* !PACK_MALLOC */
+
+#define M_OVERHEAD (sizeof(union overhead) + RSLOP)
+
+#ifdef PACK_MALLOC
+#  define MEM_OVERHEAD(bucket) \
+  (bucket <= MAX_PACKED ? 0 : M_OVERHEAD)
+#  ifdef SMALL_BUCKET_VIA_TABLE
+#    define START_SHIFTS_BUCKET ((MAX_PACKED_POW2 + 1) * BUCKETS_PER_POW2)
+#    define START_SHIFT MAX_PACKED_POW2
+#    ifdef BUCKETS_ROOT2		/* Chunks of size 3*2^n. */
+#      define SIZE_TABLE_MAX 80
+#    else
+#      define SIZE_TABLE_MAX 64
+#    endif 
+static char bucket_of[] =
+  {
+#    ifdef BUCKETS_ROOT2		/* Chunks of size 3*2^n. */
+      /* 0 to 15 in 4-byte increments. */
+      (sizeof(void*) > 4 ? 6 : 5),	/* 4/8, 5-th bucket for better reports */
+      6,				/* 8 */
+      IF_ALIGN_8(8,7), 8,		/* 16/12, 16 */
+      9, 9, 10, 10,			/* 24, 32 */
+      11, 11, 11, 11,			/* 48 */
+      12, 12, 12, 12,			/* 64 */
+      13, 13, 13, 13,			/* 80 */
+      13, 13, 13, 13			/* 80 */
+#    else /* !BUCKETS_ROOT2 */
+      /* 0 to 15 in 4-byte increments. */
+      (sizeof(void*) > 4 ? 3 : 2),
+      3, 
+      4, 4, 
+      5, 5, 5, 5,
+      6, 6, 6, 6,
+      6, 6, 6, 6
+#    endif /* !BUCKETS_ROOT2 */
+  };
+#  else  /* !SMALL_BUCKET_VIA_TABLE */
+#    define START_SHIFTS_BUCKET MIN_BUCKET
+#    define START_SHIFT (MIN_BUC_POW2 - 1)
+#  endif /* !SMALL_BUCKET_VIA_TABLE */
+#else  /* !PACK_MALLOC */
+#  define MEM_OVERHEAD(bucket) M_OVERHEAD
+#  ifdef SMALL_BUCKET_VIA_TABLE
+#    undef SMALL_BUCKET_VIA_TABLE
+#  endif 
+#  define START_SHIFTS_BUCKET MIN_BUCKET
+#  define START_SHIFT (MIN_BUC_POW2 - 1)
+#endif /* !PACK_MALLOC */
+
+/*
+ * Big allocations are often of the size 2^n bytes. To make them a
+ * little bit better, make blocks of size 2^n+pagesize for big n.
+ */
+
+#ifdef TWO_POT_OPTIMIZE
+
+#  ifndef PERL_PAGESIZE
+#    define PERL_PAGESIZE 4096
+#  endif 
+#  ifndef FIRST_BIG_POW2
+#    define FIRST_BIG_POW2 15	/* 32K, 16K is used too often. */
+#  endif
+#  define FIRST_BIG_BLOCK (1<<FIRST_BIG_POW2)
+/* If this value or more, check against bigger blocks. */
+#  define FIRST_BIG_BOUND (FIRST_BIG_BLOCK - M_OVERHEAD)
+/* If less than this value, goes into 2^n-overhead-block. */
+#  define LAST_SMALL_BOUND ((FIRST_BIG_BLOCK>>1) - M_OVERHEAD)
+
+#  define POW2_OPTIMIZE_ADJUST(nbytes)				\
+   ((nbytes >= FIRST_BIG_BOUND) ? nbytes -= PERL_PAGESIZE : 0)
+#  define POW2_OPTIMIZE_SURPLUS(bucket)				\
+   ((bucket >= FIRST_BIG_POW2 * BUCKETS_PER_POW2) ? PERL_PAGESIZE : 0)
+
+#else  /* !TWO_POT_OPTIMIZE */
+#  define POW2_OPTIMIZE_ADJUST(nbytes)
+#  define POW2_OPTIMIZE_SURPLUS(bucket) 0
+#endif /* !TWO_POT_OPTIMIZE */
+
+#if defined(HAS_64K_LIMIT) && defined(PERL_CORE)
+#  define BARK_64K_LIMIT(what,nbytes,size)				\
+	if (nbytes > 0xffff) {						\
+		PerlIO_printf(PerlIO_stderr(),				\
+			      "%s too large: %lx\n", what, size);	\
+		my_exit(1);						\
+	}
+#else /* !HAS_64K_LIMIT || !PERL_CORE */
+#  define BARK_64K_LIMIT(what,nbytes,size)
+#endif /* !HAS_64K_LIMIT || !PERL_CORE */
+
+#ifndef MIN_SBRK
+#  define MIN_SBRK 2048
+#endif 
+
+#ifndef FIRST_SBRK
+#  define FIRST_SBRK (48*1024)
+#endif 
+
+/* Minimal sbrk in percents of what is already alloced. */
+#ifndef MIN_SBRK_FRAC
+#  define MIN_SBRK_FRAC 3
+#endif 
+
+#ifndef SBRK_ALLOW_FAILURES
+#  define SBRK_ALLOW_FAILURES 3
+#endif 
+
+#ifndef SBRK_FAILURE_PRICE
+#  define SBRK_FAILURE_PRICE 50
+#endif 
+
+#if defined(PERL_EMERGENCY_SBRK) && defined(PERL_CORE)
+
+#  ifndef BIG_SIZE
+#    define BIG_SIZE (1<<16)		/* 64K */
+#  endif 
+
+#ifdef MUTEX_INIT_CALLS_MALLOC
+#  undef      MUTEX_LOCK
+#  define MUTEX_LOCK(m)       STMT_START { if (*m) mutex_lock(*m); } STMT_END
+#  undef      MUTEX_UNLOCK
+#  define MUTEX_UNLOCK(m)     STMT_START { if (*m) mutex_unlock(*m); } STMT_END
+#endif
+
+static char *emergency_buffer;
+static MEM_SIZE emergency_buffer_size;
+static Malloc_t emergency_sbrk(MEM_SIZE size);
+
+static Malloc_t
+emergency_sbrk(MEM_SIZE size)
+{
+    MEM_SIZE rsize = (((size - 1)>>LOG_OF_MIN_ARENA) + 1)<<LOG_OF_MIN_ARENA;
+
+    if (size >= BIG_SIZE) {
+	/* Give the possibility to recover: */
+	MUTEX_UNLOCK(&PL_malloc_mutex);
+	croak("Out of memory during \"large\" request for %i bytes", size);
+    }
+
+    if (emergency_buffer_size >= rsize) {
+	char *old = emergency_buffer;
+	
+	emergency_buffer_size -= rsize;
+	emergency_buffer += rsize;
+	return old;
+    } else {		
+	dTHR;
+	/* First offense, give a possibility to recover by dieing. */
+	/* No malloc involved here: */
+	GV **gvp = (GV**)hv_fetch(PL_defstash, "^M", 2, 0);
+	SV *sv;
+	char *pv;
+	int have = 0;
+	STRLEN n_a;
+
+	if (emergency_buffer_size) {
+	    add_to_chain(emergency_buffer, emergency_buffer_size, 0);
+	    emergency_buffer_size = 0;
+	    emergency_buffer = Nullch;
+	    have = 1;
+	}
+	if (!gvp) gvp = (GV**)hv_fetch(PL_defstash, "\015", 1, 0);
+	if (!gvp || !(sv = GvSV(*gvp)) || !SvPOK(sv) 
+	    || (SvLEN(sv) < (1<<LOG_OF_MIN_ARENA) - M_OVERHEAD)) {
+	    if (have)
+		goto do_croak;
+	    return (char *)-1;		/* Now die die die... */
+	}
+	/* Got it, now detach SvPV: */
+	pv = SvPV(sv, n_a);
+	/* Check alignment: */
+	if (((UV)(pv - sizeof(union overhead))) & ((1<<LOG_OF_MIN_ARENA) - 1)) {
+	    PerlIO_puts(PerlIO_stderr(),"Bad alignment of $^M!\n");
+	    return (char *)-1;		/* die die die */
+	}
+
+	emergency_buffer = pv - sizeof(union overhead);
+	emergency_buffer_size = malloced_size(pv) + M_OVERHEAD;
+	SvPOK_off(sv);
+	SvPVX(sv) = Nullch;
+	SvCUR(sv) = SvLEN(sv) = 0;
+    }
+  do_croak:
+    MUTEX_UNLOCK(&PL_malloc_mutex);
+    croak("Out of memory during request for %i bytes", size);
+}
+
+#else /* !(defined(PERL_EMERGENCY_SBRK) && defined(PERL_CORE)) */
+#  define emergency_sbrk(size)	-1
+#endif /* !(defined(PERL_EMERGENCY_SBRK) && defined(PERL_CORE)) */
+
+/*
+ * nextf[i] is the pointer to the next free block of size 2^i.  The
+ * smallest allocatable block is 8 bytes.  The overhead information
+ * precedes the data area returned to the user.
+ */
+#define	NBUCKETS (32*BUCKETS_PER_POW2 + 1)
+static	union overhead *nextf[NBUCKETS];
+
+#ifdef USE_PERL_SBRK
+#define sbrk(a) Perl_sbrk(a)
+Malloc_t Perl_sbrk _((int size));
+#else 
+#ifdef DONT_DECLARE_STD
+#ifdef I_UNISTD
+#include <unistd.h>
+#endif
+#else
+extern	Malloc_t sbrk(int);
+#endif
+#endif
+
+#ifdef DEBUGGING_MSTATS
+/*
+ * nmalloc[i] is the difference between the number of mallocs and frees
+ * for a given block size.
+ */
+static	u_int nmalloc[NBUCKETS];
+static  u_int sbrk_slack;
+static  u_int start_slack;
+#endif
+
+static	u_int goodsbrk;
+
+#ifdef DEBUGGING
+#undef ASSERT
+#define	ASSERT(p,diag)   if (!(p)) botch(diag,STRINGIFY(p));  else
+static void
+botch(char *diag, char *s)
+{
+	PerlIO_printf(PerlIO_stderr(), "assertion botched (%s?): %s\n", diag, s);
+	PerlProc_abort();
+}
+#else
+#define	ASSERT(p, diag)
+#endif
+
+Malloc_t
+malloc(register size_t nbytes)
+{
+  	register union overhead *p;
+  	register int bucket;
+  	register MEM_SIZE shiftr;
+
+#if defined(DEBUGGING) || defined(RCHECK)
+	MEM_SIZE size = nbytes;
+#endif
+
+	BARK_64K_LIMIT("Allocation",nbytes,nbytes);
+#ifdef DEBUGGING
+	if ((long)nbytes < 0)
+		croak("%s", "panic: malloc");
+#endif
+
+	MUTEX_LOCK(&PL_malloc_mutex);
+	/*
+	 * Convert amount of memory requested into
+	 * closest block size stored in hash buckets
+	 * which satisfies request.  Account for
+	 * space used per block for accounting.
+	 */
+#ifdef PACK_MALLOC
+#  ifdef SMALL_BUCKET_VIA_TABLE
+	if (nbytes == 0)
+	    bucket = MIN_BUCKET;
+	else if (nbytes <= SIZE_TABLE_MAX) {
+	    bucket = bucket_of[(nbytes - 1) >> BUCKET_TABLE_SHIFT];
+	} else
+#  else
+	if (nbytes == 0)
+	    nbytes = 1;
+	if (nbytes <= MAX_POW2_ALGO) goto do_shifts;
+	else
+#  endif
+#endif 
+	{
+	    POW2_OPTIMIZE_ADJUST(nbytes);
+	    nbytes += M_OVERHEAD;
+	    nbytes = (nbytes + 3) &~ 3; 
+	  do_shifts:
+	    shiftr = (nbytes - 1) >> START_SHIFT;
+	    bucket = START_SHIFTS_BUCKET;
+	    /* apart from this loop, this is O(1) */
+	    while (shiftr >>= 1)
+  		bucket += BUCKETS_PER_POW2;
+	}
+	/*
+	 * If nothing in hash bucket right now,
+	 * request more memory from the system.
+	 */
+  	if (nextf[bucket] == NULL)    
+  		morecore(bucket);
+  	if ((p = nextf[bucket]) == NULL) {
+		MUTEX_UNLOCK(&PL_malloc_mutex);
+#ifdef PERL_CORE
+		if (!PL_nomemok) {
+		    PerlIO_puts(PerlIO_stderr(),"Out of memory!\n");
+		    my_exit(1);
+		}
+#else
+  		return (NULL);
+#endif
+	}
+
+	DEBUG_m(PerlIO_printf(Perl_debug_log,
+			      "0x%lx: (%05lu) malloc %ld bytes\n",
+			      (unsigned long)(p+1), (unsigned long)(PL_an++),
+			      (long)size));
+
+	/* remove from linked list */
+#if defined(RCHECK)
+	if (((UV)p) & (MEM_ALIGNBYTES - 1))
+	    PerlIO_printf(PerlIO_stderr(), "Corrupt malloc ptr 0x%lx at 0x%lx\n",
+		(unsigned long)*((int*)p),(unsigned long)p);
+#endif
+  	nextf[bucket] = p->ov_next;
+#ifdef IGNORE_SMALL_BAD_FREE
+	if (bucket >= FIRST_BUCKET_WITH_CHECK)
+#endif 
+	    OV_MAGIC(p, bucket) = MAGIC;
+#ifndef PACK_MALLOC
+	OV_INDEX(p) = bucket;
+#endif
+#ifdef RCHECK
+	/*
+	 * Record allocated size of block and
+	 * bound space with magic numbers.
+	 */
+	p->ov_rmagic = RMAGIC;
+	if (bucket <= MAX_SHORT_BUCKET) {
+	    int i;
+	    
+	    nbytes = size + M_OVERHEAD; 
+	    p->ov_size = nbytes - 1;
+	    if ((i = nbytes & 3)) {
+		i = 4 - i;
+		while (i--)
+		    *((char *)((caddr_t)p + nbytes - RSLOP + i)) = RMAGIC_C;
+	    }
+	    nbytes = (nbytes + 3) &~ 3; 
+	    *((u_int *)((caddr_t)p + nbytes - RSLOP)) = RMAGIC;
+	}
+#endif
+	MUTEX_UNLOCK(&PL_malloc_mutex);
+  	return ((Malloc_t)(p + CHUNK_SHIFT));
+}
+
+static char *last_sbrk_top;
+static char *last_op;			/* This arena can be easily extended. */
+static int sbrked_remains;
+static int sbrk_good = SBRK_ALLOW_FAILURES * SBRK_FAILURE_PRICE;
+
+#ifdef DEBUGGING_MSTATS
+static int sbrks;
+#endif 
+
+struct chunk_chain_s {
+    struct chunk_chain_s *next;
+    MEM_SIZE size;
+};
+static struct chunk_chain_s *chunk_chain;
+static int n_chunks;
+static char max_bucket;
+
+/* Cutoff a piece of one of the chunks in the chain.  Prefer smaller chunk. */
+static void *
+get_from_chain(MEM_SIZE size)
+{
+    struct chunk_chain_s *elt = chunk_chain, **oldp = &chunk_chain;
+    struct chunk_chain_s **oldgoodp = NULL;
+    long min_remain = LONG_MAX;
+
+    while (elt) {
+	if (elt->size >= size) {
+	    long remains = elt->size - size;
+	    if (remains >= 0 && remains < min_remain) {
+		oldgoodp = oldp;
+		min_remain = remains;
+	    }
+	    if (remains == 0) {
+		break;
+	    }
+	}
+	oldp = &( elt->next );
+	elt = elt->next;
+    }
+    if (!oldgoodp) return NULL;
+    if (min_remain) {
+	void *ret = *oldgoodp;
+	struct chunk_chain_s *next = (*oldgoodp)->next;
+	
+	*oldgoodp = (struct chunk_chain_s *)((char*)ret + size);
+	(*oldgoodp)->size = min_remain;
+	(*oldgoodp)->next = next;
+	return ret;
+    } else {
+	void *ret = *oldgoodp;
+	*oldgoodp = (*oldgoodp)->next;
+	n_chunks--;
+	return ret;
+    }
+}
+
+static void
+add_to_chain(void *p, MEM_SIZE size, MEM_SIZE chip)
+{
+    struct chunk_chain_s *next = chunk_chain;
+    char *cp = (char*)p;
+    
+    cp += chip;
+    chunk_chain = (struct chunk_chain_s *)cp;
+    chunk_chain->size = size - chip;
+    chunk_chain->next = next;
+    n_chunks++;
+}
+
+static void *
+get_from_bigger_buckets(int bucket, MEM_SIZE size)
+{
+    int price = 1;
+    static int bucketprice[NBUCKETS];
+    while (bucket <= max_bucket) {
+	/* We postpone stealing from bigger buckets until we want it
+	   often enough. */
+	if (nextf[bucket] && bucketprice[bucket]++ >= price) {
+	    /* Steal it! */
+	    void *ret = (void*)(nextf[bucket] - 1 + CHUNK_SHIFT);
+	    bucketprice[bucket] = 0;
+	    if (((char*)nextf[bucket]) - M_OVERHEAD == last_op) {
+		last_op = NULL;		/* Disable optimization */
+	    }
+	    nextf[bucket] = nextf[bucket]->ov_next;
+#ifdef DEBUGGING_MSTATS
+	    nmalloc[bucket]--;
+	    start_slack -= M_OVERHEAD;
+#endif 
+	    add_to_chain(ret, (BUCKET_SIZE(bucket) +
+			       POW2_OPTIMIZE_SURPLUS(bucket)), 
+			 size);
+	    return ret;
+	}
+	bucket++;
+    }
+    return NULL;
+}
+
+static union overhead *
+getpages(int needed, int *nblksp, int bucket)
+{
+    /* Need to do (possibly expensive) system call. Try to
+       optimize it for rare calling. */
+    MEM_SIZE require = needed - sbrked_remains;
+    char *cp;
+    union overhead *ovp;
+    int slack = 0;
+
+    if (sbrk_good > 0) {
+	if (!last_sbrk_top && require < FIRST_SBRK) 
+	    require = FIRST_SBRK;
+	else if (require < MIN_SBRK) require = MIN_SBRK;
+
+	if (require < goodsbrk * MIN_SBRK_FRAC / 100)
+	    require = goodsbrk * MIN_SBRK_FRAC / 100;
+	require = ((require - 1 + MIN_SBRK) / MIN_SBRK) * MIN_SBRK;
+    } else {
+	require = needed;
+	last_sbrk_top = 0;
+	sbrked_remains = 0;
+    }
+
+    DEBUG_m(PerlIO_printf(Perl_debug_log, 
+			  "sbrk(%ld) for %ld-byte-long arena\n",
+			  (long)require, (long) needed));
+    cp = (char *)sbrk(require);
+#ifdef DEBUGGING_MSTATS
+    sbrks++;
+#endif 
+    if (cp == last_sbrk_top) {
+	/* Common case, anything is fine. */
+	sbrk_good++;
+	ovp = (union overhead *) (cp - sbrked_remains);
+	sbrked_remains = require - (needed - sbrked_remains);
+    } else if (cp == (char *)-1) { /* no more room! */
+	ovp = (union overhead *)emergency_sbrk(needed);
+	if (ovp == (union overhead *)-1)
+	    return 0;
+	return ovp;
+    } else {			/* Non-continuous or first sbrk(). */
+	long add = sbrked_remains;
+	char *newcp;
+
+	if (sbrked_remains) {	/* Put rest into chain, we
+				   cannot use it right now. */
+	    add_to_chain((void*)(last_sbrk_top - sbrked_remains),
+			 sbrked_remains, 0);
+	}
+
+	/* Second, check alignment. */
+	slack = 0;
+
+#if !defined(atarist) && !defined(__MINT__) /* on the atari we dont have to worry about this */
+#  ifndef I286 	/* The sbrk(0) call on the I286 always returns the next segment */
+
+	/* CHUNK_SHIFT is 1 for PACK_MALLOC, 0 otherwise. */
+	if ((UV)cp & (0x7FF >> CHUNK_SHIFT)) { /* Not aligned. */
+	    slack = (0x800 >> CHUNK_SHIFT)
+		- ((UV)cp & (0x7FF >> CHUNK_SHIFT));
+	    add += slack;
+	}
+#  endif
+#endif /* !atarist && !MINT */
+		
+	if (add) {
+	    DEBUG_m(PerlIO_printf(Perl_debug_log, 
+				  "sbrk(%ld) to fix non-continuous/off-page sbrk:\n\t%ld for alignement,\t%ld were assumed to come from the tail of the previous sbrk\n",
+				  (long)add, (long) slack,
+				  (long) sbrked_remains));
+	    newcp = (char *)sbrk(add);
+#if defined(DEBUGGING_MSTATS)
+	    sbrks++;
+	    sbrk_slack += add;
+#endif
+	    if (newcp != cp + require) {
+		/* Too bad: even rounding sbrk() is not continuous.*/
+		DEBUG_m(PerlIO_printf(Perl_debug_log, 
+				      "failed to fix bad sbrk()\n"));
+#ifdef PACK_MALLOC
+		if (slack) {
+		    MUTEX_UNLOCK(&PL_malloc_mutex);
+		    croak("%s", "panic: Off-page sbrk");
+		}
+#endif
+		if (sbrked_remains) {
+		    /* Try again. */
+#if defined(DEBUGGING_MSTATS)
+		    sbrk_slack += require;
+#endif
+		    require = needed;
+		    DEBUG_m(PerlIO_printf(Perl_debug_log, 
+					  "straight sbrk(%ld)\n",
+					  (long)require));
+		    cp = (char *)sbrk(require);
+#ifdef DEBUGGING_MSTATS
+		    sbrks++;
+#endif 
+		    if (cp == (char *)-1)
+			return 0;
+		}
+		sbrk_good = -1;	/* Disable optimization!
+				   Continue with not-aligned... */
+	    } else {
+		cp += slack;
+		require += sbrked_remains;
+	    }
+	}
+
+	if (last_sbrk_top) {
+	    sbrk_good -= SBRK_FAILURE_PRICE;
+	}
+
+	ovp = (union overhead *) cp;
+	/*
+	 * Round up to minimum allocation size boundary
+	 * and deduct from block count to reflect.
+	 */
+
+#ifndef I286	/* Again, this should always be ok on an 80286 */
+	if ((UV)ovp & 7) {
+	    ovp = (union overhead *)(((UV)ovp + 8) & ~7);
+	    DEBUG_m(PerlIO_printf(Perl_debug_log, 
+				  "fixing sbrk(): %d bytes off machine alignement\n",
+				  (int)((UV)ovp & 7)));
+	    (*nblksp)--;
+# if defined(DEBUGGING_MSTATS)
+	    /* This is only approx. if TWO_POT_OPTIMIZE: */
+	    sbrk_slack += (1 << bucket);
+# endif
+	}
+#endif
+	sbrked_remains = require - needed;
+    }
+    last_sbrk_top = cp + require;
+    last_op = (char*) cp;
+#ifdef DEBUGGING_MSTATS
+    goodsbrk += require;
+#endif	
+    return ovp;
+}
+
+static int
+getpages_adjacent(int require)
+{	    
+    if (require <= sbrked_remains) {
+	sbrked_remains -= require;
+    } else {
+	char *cp;
+
+	require -= sbrked_remains;
+	/* We do not try to optimize sbrks here, we go for place. */
+	cp = (char*) sbrk(require);
+#ifdef DEBUGGING_MSTATS
+	sbrks++;
+	goodsbrk += require;
+#endif 
+	if (cp == last_sbrk_top) {
+	    sbrked_remains = 0;
+	    last_sbrk_top = cp + require;
+	} else {
+	    if (cp == (char*)-1) {	/* Out of memory */
+#ifdef DEBUGGING_MSTATS
+		goodsbrk -= require;
+#endif
+		return 0;
+	    }
+	    /* Report the failure: */
+	    if (sbrked_remains)
+		add_to_chain((void*)(last_sbrk_top - sbrked_remains),
+			     sbrked_remains, 0);
+	    add_to_chain((void*)cp, require, 0);
+	    sbrk_good -= SBRK_FAILURE_PRICE;
+	    sbrked_remains = 0;
+	    last_sbrk_top = 0;
+	    last_op = 0;
+	    return 0;
+	}
+    }
+	    
+    return 1;
+}
+
+/*
+ * Allocate more memory to the indicated bucket.
+ */
+static void
+morecore(register int bucket)
+{
+  	register union overhead *ovp;
+  	register int rnu;       /* 2^rnu bytes will be requested */
+  	int nblks;		/* become nblks blocks of the desired size */
+	register MEM_SIZE siz, needed;
+
+  	if (nextf[bucket])
+  		return;
+	if (bucket == sizeof(MEM_SIZE)*8*BUCKETS_PER_POW2) {
+	    MUTEX_UNLOCK(&PL_malloc_mutex);
+	    croak("%s", "Out of memory during ridiculously large request");
+	}
+	if (bucket > max_bucket)
+	    max_bucket = bucket;
+
+  	rnu = ( (bucket <= (LOG_OF_MIN_ARENA << BUCKET_POW2_SHIFT)) 
+		? LOG_OF_MIN_ARENA 
+		: (bucket >> BUCKET_POW2_SHIFT) );
+	/* This may be overwritten later: */
+  	nblks = 1 << (rnu - (bucket >> BUCKET_POW2_SHIFT)); /* how many blocks to get */
+	needed = ((MEM_SIZE)1 << rnu) + POW2_OPTIMIZE_SURPLUS(bucket);
+	if (nextf[rnu << BUCKET_POW2_SHIFT]) { /* 2048b bucket. */
+	    ovp = nextf[rnu << BUCKET_POW2_SHIFT] - 1 + CHUNK_SHIFT;
+	    nextf[rnu << BUCKET_POW2_SHIFT]
+		= nextf[rnu << BUCKET_POW2_SHIFT]->ov_next;
+#ifdef DEBUGGING_MSTATS
+	    nmalloc[rnu << BUCKET_POW2_SHIFT]--;
+	    start_slack -= M_OVERHEAD;
+#endif 
+	    DEBUG_m(PerlIO_printf(Perl_debug_log, 
+				  "stealing %ld bytes from %ld arena\n",
+				  (long) needed, (long) rnu << BUCKET_POW2_SHIFT));
+	} else if (chunk_chain 
+		   && (ovp = (union overhead*) get_from_chain(needed))) {
+	    DEBUG_m(PerlIO_printf(Perl_debug_log, 
+				  "stealing %ld bytes from chain\n",
+				  (long) needed));
+	} else if ( (ovp = (union overhead*)
+		     get_from_bigger_buckets((rnu << BUCKET_POW2_SHIFT) + 1,
+					     needed)) ) {
+	    DEBUG_m(PerlIO_printf(Perl_debug_log, 
+				  "stealing %ld bytes from bigger buckets\n",
+				  (long) needed));
+	} else if (needed <= sbrked_remains) {
+	    ovp = (union overhead *)(last_sbrk_top - sbrked_remains);
+	    sbrked_remains -= needed;
+	    last_op = (char*)ovp;
+	} else 
+	    ovp = getpages(needed, &nblks, bucket);
+
+	if (!ovp)
+	    return;
+
+	/*
+	 * Add new memory allocated to that on
+	 * free list for this hash bucket.
+	 */
+  	siz = BUCKET_SIZE(bucket);
+#ifdef PACK_MALLOC
+	*(u_char*)ovp = bucket;	/* Fill index. */
+	if (bucket <= MAX_PACKED) {
+	    ovp = (union overhead *) ((char*)ovp + BLK_SHIFT(bucket));
+	    nblks = N_BLKS(bucket);
+#  ifdef DEBUGGING_MSTATS
+	    start_slack += BLK_SHIFT(bucket);
+#  endif
+	} else if (bucket < LOG_OF_MIN_ARENA * BUCKETS_PER_POW2) {
+	    ovp = (union overhead *) ((char*)ovp + BLK_SHIFT(bucket));
+	    siz -= sizeof(union overhead);
+	} else ovp++;		/* One chunk per block. */
+#endif /* PACK_MALLOC */
+  	nextf[bucket] = ovp;
+#ifdef DEBUGGING_MSTATS
+	nmalloc[bucket] += nblks;
+	if (bucket > MAX_PACKED) {
+	    start_slack += M_OVERHEAD * nblks;
+	}
+#endif 
+  	while (--nblks > 0) {
+		ovp->ov_next = (union overhead *)((caddr_t)ovp + siz);
+		ovp = (union overhead *)((caddr_t)ovp + siz);
+  	}
+	/* Not all sbrks return zeroed memory.*/
+	ovp->ov_next = (union overhead *)NULL;
+#ifdef PACK_MALLOC
+	if (bucket == 7*BUCKETS_PER_POW2) { /* Special case, explanation is above. */
+	    union overhead *n_op = nextf[7*BUCKETS_PER_POW2]->ov_next;
+	    nextf[7*BUCKETS_PER_POW2] = 
+		(union overhead *)((caddr_t)nextf[7*BUCKETS_PER_POW2] 
+				   - sizeof(union overhead));
+	    nextf[7*BUCKETS_PER_POW2]->ov_next = n_op;
+	}
+#endif /* !PACK_MALLOC */
+}
+
+Free_t
+free(void *mp)
+{   
+  	register MEM_SIZE size;
+	register union overhead *ovp;
+	char *cp = (char*)mp;
+#ifdef PACK_MALLOC
+	u_char bucket;
+#endif 
+
+	DEBUG_m(PerlIO_printf(Perl_debug_log, 
+			      "0x%lx: (%05lu) free\n",
+			      (unsigned long)cp, (unsigned long)(PL_an++)));
+
+	if (cp == NULL)
+		return;
+	ovp = (union overhead *)((caddr_t)cp 
+				- sizeof (union overhead) * CHUNK_SHIFT);
+#ifdef PACK_MALLOC
+	bucket = OV_INDEX(ovp);
+#endif 
+#ifdef IGNORE_SMALL_BAD_FREE
+	if ((bucket >= FIRST_BUCKET_WITH_CHECK) 
+	    && (OV_MAGIC(ovp, bucket) != MAGIC))
+#else
+	if (OV_MAGIC(ovp, bucket) != MAGIC)
+#endif 
+	    {
+		static int bad_free_warn = -1;
+		if (bad_free_warn == -1) {
+		    char *pbf = PerlEnv_getenv("PERL_BADFREE");
+		    bad_free_warn = (pbf) ? atoi(pbf) : 1;
+		}
+		if (!bad_free_warn)
+		    return;
+#ifdef RCHECK
+		warn("%s free() ignored",
+		    ovp->ov_rmagic == RMAGIC - 1 ? "Duplicate" : "Bad");
+#else
+		warn("%s", "Bad free() ignored");
+#endif
+		return;				/* sanity */
+	    }
+	MUTEX_LOCK(&PL_malloc_mutex);
+#ifdef RCHECK
+  	ASSERT(ovp->ov_rmagic == RMAGIC, "chunk's head overwrite");
+	if (OV_INDEX(ovp) <= MAX_SHORT_BUCKET) {
+	    int i;
+	    MEM_SIZE nbytes = ovp->ov_size + 1;
+
+	    if ((i = nbytes & 3)) {
+		i = 4 - i;
+		while (i--) {
+		    ASSERT(*((char *)((caddr_t)ovp + nbytes - RSLOP + i))
+			   == RMAGIC_C, "chunk's tail overwrite");
+		}
+	    }
+	    nbytes = (nbytes + 3) &~ 3; 
+	    ASSERT(*(u_int *)((caddr_t)ovp + nbytes - RSLOP) == RMAGIC, "chunk's tail overwrite");	    
+	}
+	ovp->ov_rmagic = RMAGIC - 1;
+#endif
+  	ASSERT(OV_INDEX(ovp) < NBUCKETS, "chunk's head overwrite");
+  	size = OV_INDEX(ovp);
+	ovp->ov_next = nextf[size];
+  	nextf[size] = ovp;
+	MUTEX_UNLOCK(&PL_malloc_mutex);
+}
+
+/*
+ * When a program attempts "storage compaction" as mentioned in the
+ * old malloc man page, it realloc's an already freed block.  Usually
+ * this is the last block it freed; occasionally it might be farther
+ * back.  We have to search all the free lists for the block in order
+ * to determine its bucket: 1st we make one pass thru the lists
+ * checking only the first block in each; if that fails we search
+ * ``reall_srchlen'' blocks in each list for a match (the variable
+ * is extern so the caller can modify it).  If that fails we just copy
+ * however many bytes was given to realloc() and hope it's not huge.
+ */
+int reall_srchlen = 4;  /* 4 should be plenty, -1 =>'s whole list */
+
+Malloc_t
+realloc(void *mp, size_t nbytes)
+{   
+  	register MEM_SIZE onb;
+	union overhead *ovp;
+  	char *res;
+	int prev_bucket;
+	register int bucket;
+	int was_alloced = 0, incr;
+	char *cp = (char*)mp;
+
+#if defined(DEBUGGING) || !defined(PERL_CORE)
+	MEM_SIZE size = nbytes;
+
+	if ((long)nbytes < 0)
+		croak("%s", "panic: realloc");
+#endif
+
+	BARK_64K_LIMIT("Reallocation",nbytes,size);
+	if (!cp)
+		return malloc(nbytes);
+
+	MUTEX_LOCK(&PL_malloc_mutex);
+	ovp = (union overhead *)((caddr_t)cp 
+				- sizeof (union overhead) * CHUNK_SHIFT);
+	bucket = OV_INDEX(ovp);
+#ifdef IGNORE_SMALL_BAD_FREE
+	if ((bucket < FIRST_BUCKET_WITH_CHECK) 
+	    || (OV_MAGIC(ovp, bucket) == MAGIC))
+#else
+	if (OV_MAGIC(ovp, bucket) == MAGIC) 
+#endif 
+	{
+		was_alloced = 1;
+	} else {
+		/*
+		 * Already free, doing "compaction".
+		 *
+		 * Search for the old block of memory on the
+		 * free list.  First, check the most common
+		 * case (last element free'd), then (this failing)
+		 * the last ``reall_srchlen'' items free'd.
+		 * If all lookups fail, then assume the size of
+		 * the memory block being realloc'd is the
+		 * smallest possible.
+		 */
+		if ((bucket = findbucket(ovp, 1)) < 0 &&
+		    (bucket = findbucket(ovp, reall_srchlen)) < 0)
+			bucket = 0;
+	}
+	onb = BUCKET_SIZE_REAL(bucket);
+	/* 
+	 *  avoid the copy if same size block.
+	 *  We are not agressive with boundary cases. Note that it might
+	 *  (for a small number of cases) give false negative if
+	 *  both new size and old one are in the bucket for
+	 *  FIRST_BIG_POW2, but the new one is near the lower end.
+	 *
+	 *  We do not try to go to 1.5 times smaller bucket so far.
+	 */
+	if (nbytes > onb) incr = 1;
+	else {
+#ifdef DO_NOT_TRY_HARDER_WHEN_SHRINKING
+	    if ( /* This is a little bit pessimal if PACK_MALLOC: */
+		nbytes > ( (onb >> 1) - M_OVERHEAD )
+#  ifdef TWO_POT_OPTIMIZE
+		|| (bucket == FIRST_BIG_POW2 && nbytes >= LAST_SMALL_BOUND )
+#  endif	
+		)
+#else  /* !DO_NOT_TRY_HARDER_WHEN_SHRINKING */
+		prev_bucket = ( (bucket > MAX_PACKED + 1) 
+				? bucket - BUCKETS_PER_POW2
+				: bucket - 1);
+	     if (nbytes > BUCKET_SIZE_REAL(prev_bucket))
+#endif /* !DO_NOT_TRY_HARDER_WHEN_SHRINKING */
+		 incr = 0;
+	     else incr = -1;
+	}
+	if (!was_alloced
+#ifdef STRESS_REALLOC
+	    || 1 /* always do it the hard way */
+#endif
+	    ) goto hard_way;
+	else if (incr == 0) {
+	  inplace_label:
+#ifdef RCHECK
+		/*
+		 * Record new allocated size of block and
+		 * bound space with magic numbers.
+		 */
+		if (OV_INDEX(ovp) <= MAX_SHORT_BUCKET) {
+		       int i, nb = ovp->ov_size + 1;
+
+		       if ((i = nb & 3)) {
+			   i = 4 - i;
+			   while (i--) {
+			       ASSERT(*((char *)((caddr_t)ovp + nb - RSLOP + i)) == RMAGIC_C, "chunk's tail overwrite");
+			   }
+		       }
+		       nb = (nb + 3) &~ 3; 
+		       ASSERT(*(u_int *)((caddr_t)ovp + nb - RSLOP) == RMAGIC, "chunk's tail overwrite");
+			/*
+			 * Convert amount of memory requested into
+			 * closest block size stored in hash buckets
+			 * which satisfies request.  Account for
+			 * space used per block for accounting.
+			 */
+			nbytes += M_OVERHEAD;
+			ovp->ov_size = nbytes - 1;
+			if ((i = nbytes & 3)) {
+			    i = 4 - i;
+			    while (i--)
+				*((char *)((caddr_t)ovp + nbytes - RSLOP + i))
+				    = RMAGIC_C;
+			}
+			nbytes = (nbytes + 3) &~ 3; 
+			*((u_int *)((caddr_t)ovp + nbytes - RSLOP)) = RMAGIC;
+		}
+#endif
+		res = cp;
+		MUTEX_UNLOCK(&PL_malloc_mutex);
+		DEBUG_m(PerlIO_printf(Perl_debug_log, 
+			      "0x%lx: (%05lu) realloc %ld bytes inplace\n",
+			      (unsigned long)res,(unsigned long)(PL_an++),
+			      (long)size));
+	} else if (incr == 1 && (cp - M_OVERHEAD == last_op) 
+		   && (onb > (1 << LOG_OF_MIN_ARENA))) {
+	    MEM_SIZE require, newarena = nbytes, pow;
+	    int shiftr;
+
+	    POW2_OPTIMIZE_ADJUST(newarena);
+	    newarena = newarena + M_OVERHEAD;
+	    /* newarena = (newarena + 3) &~ 3; */
+	    shiftr = (newarena - 1) >> LOG_OF_MIN_ARENA;
+	    pow = LOG_OF_MIN_ARENA + 1;
+	    /* apart from this loop, this is O(1) */
+	    while (shiftr >>= 1)
+  		pow++;
+	    newarena = (1 << pow) + POW2_OPTIMIZE_SURPLUS(pow * BUCKETS_PER_POW2);
+	    require = newarena - onb - M_OVERHEAD;
+	    
+	    if (getpages_adjacent(require)) {
+#ifdef DEBUGGING_MSTATS
+		nmalloc[bucket]--;
+		nmalloc[pow * BUCKETS_PER_POW2]++;
+#endif 	    
+		*(cp - M_OVERHEAD) = pow * BUCKETS_PER_POW2; /* Fill index. */
+		goto inplace_label;
+	    } else
+		goto hard_way;
+	} else {
+	  hard_way:
+	    MUTEX_UNLOCK(&PL_malloc_mutex);
+	    DEBUG_m(PerlIO_printf(Perl_debug_log, 
+			      "0x%lx: (%05lu) realloc %ld bytes the hard way\n",
+			      (unsigned long)cp,(unsigned long)(PL_an++),
+			      (long)size));
+	    if ((res = (char*)malloc(nbytes)) == NULL)
+		return (NULL);
+	    if (cp != res)			/* common optimization */
+		Copy(cp, res, (MEM_SIZE)(nbytes<onb?nbytes:onb), char);
+	    if (was_alloced)
+		free(cp);
+	}
+  	return ((Malloc_t)res);
+}
+
+/*
+ * Search ``srchlen'' elements of each free list for a block whose
+ * header starts at ``freep''.  If srchlen is -1 search the whole list.
+ * Return bucket number, or -1 if not found.
+ */
+static int
+findbucket(union overhead *freep, int srchlen)
+{
+	register union overhead *p;
+	register int i, j;
+
+	for (i = 0; i < NBUCKETS; i++) {
+		j = 0;
+		for (p = nextf[i]; p && j != srchlen; p = p->ov_next) {
+			if (p == freep)
+				return (i);
+			j++;
+		}
+	}
+	return (-1);
+}
+
+Malloc_t
+calloc(register size_t elements, register size_t size)
+{
+    long sz = elements * size;
+    Malloc_t p = malloc(sz);
+
+    if (p) {
+	memset((void*)p, 0, sz);
+    }
+    return p;
+}
+
+MEM_SIZE
+malloced_size(void *p)
+{
+    union overhead *ovp = (union overhead *)
+	((caddr_t)p - sizeof (union overhead) * CHUNK_SHIFT);
+    int bucket = OV_INDEX(ovp);
+#ifdef RCHECK
+    /* The caller wants to have a complete control over the chunk,
+       disable the memory checking inside the chunk.  */
+    if (bucket <= MAX_SHORT_BUCKET) {
+	MEM_SIZE size = BUCKET_SIZE_REAL(bucket);
+	ovp->ov_size = size + M_OVERHEAD - 1;
+	*((u_int *)((caddr_t)ovp + size + M_OVERHEAD - RSLOP)) = RMAGIC;
+    }
+#endif
+    return BUCKET_SIZE_REAL(bucket);
+}
+
+#ifdef DEBUGGING_MSTATS
+
+#  ifdef BUCKETS_ROOT2
+#    define MIN_EVEN_REPORT 6
+#  else
+#    define MIN_EVEN_REPORT MIN_BUCKET
+#  endif 
+/*
+ * mstats - print out statistics about malloc
+ * 
+ * Prints two lines of numbers, one showing the length of the free list
+ * for each size category, the second showing the number of mallocs -
+ * frees for each size category.
+ */
+void
+dump_mstats(char *s)
+{
+  	register int i, j;
+  	register union overhead *p;
+  	int topbucket=0, topbucket_ev=0, topbucket_odd=0, totfree=0, total=0;
+	u_int nfree[NBUCKETS];
+	int total_chain = 0;
+	struct chunk_chain_s* nextchain = chunk_chain;
+
+  	for (i = MIN_BUCKET ; i < NBUCKETS; i++) {
+  		for (j = 0, p = nextf[i]; p; p = p->ov_next, j++)
+  			;
+		nfree[i] = j;
+  		totfree += nfree[i] * BUCKET_SIZE_REAL(i);
+  		total += nmalloc[i] * BUCKET_SIZE_REAL(i);
+		if (nmalloc[i]) {
+		    i % 2 ? (topbucket_odd = i) : (topbucket_ev = i);
+		    topbucket = i;
+		}
+  	}
+  	if (s)
+	    PerlIO_printf(PerlIO_stderr(),
+			  "Memory allocation statistics %s (buckets %ld(%ld)..%ld(%ld)\n",
+			  s, 
+			  (long)BUCKET_SIZE_REAL(MIN_BUCKET), 
+			  (long)BUCKET_SIZE(MIN_BUCKET),
+			  (long)BUCKET_SIZE_REAL(topbucket), (long)BUCKET_SIZE(topbucket));
+  	PerlIO_printf(PerlIO_stderr(), "%8d free:", totfree);
+  	for (i = MIN_EVEN_REPORT; i <= topbucket; i += BUCKETS_PER_POW2) {
+  		PerlIO_printf(PerlIO_stderr(), 
+			      ((i < 8*BUCKETS_PER_POW2 || i == 10*BUCKETS_PER_POW2)
+			       ? " %5d" 
+			       : ((i < 12*BUCKETS_PER_POW2) ? " %3d" : " %d")),
+			      nfree[i]);
+  	}
+#ifdef BUCKETS_ROOT2
+	PerlIO_printf(PerlIO_stderr(), "\n\t   ");
+  	for (i = MIN_BUCKET + 1; i <= topbucket_odd; i += BUCKETS_PER_POW2) {
+  		PerlIO_printf(PerlIO_stderr(), 
+			      ((i < 8*BUCKETS_PER_POW2 || i == 10*BUCKETS_PER_POW2)
+			       ? " %5d" 
+			       : ((i < 12*BUCKETS_PER_POW2) ? " %3d" : " %d")),
+			      nfree[i]);
+  	}
+#endif 
+  	PerlIO_printf(PerlIO_stderr(), "\n%8d used:", total - totfree);
+  	for (i = MIN_EVEN_REPORT; i <= topbucket; i += BUCKETS_PER_POW2) {
+  		PerlIO_printf(PerlIO_stderr(), 
+			      ((i < 8*BUCKETS_PER_POW2 || i == 10*BUCKETS_PER_POW2)
+			       ? " %5d" 
+			       : ((i < 12*BUCKETS_PER_POW2) ? " %3d" : " %d")), 
+			      nmalloc[i] - nfree[i]);
+  	}
+#ifdef BUCKETS_ROOT2
+	PerlIO_printf(PerlIO_stderr(), "\n\t   ");
+  	for (i = MIN_BUCKET + 1; i <= topbucket_odd; i += BUCKETS_PER_POW2) {
+  		PerlIO_printf(PerlIO_stderr(), 
+			      ((i < 8*BUCKETS_PER_POW2 || i == 10*BUCKETS_PER_POW2)
+			       ? " %5d" 
+			       : ((i < 12*BUCKETS_PER_POW2) ? " %3d" : " %d")),
+			      nmalloc[i] - nfree[i]);
+  	}
+#endif 
+	while (nextchain) {
+	    total_chain += nextchain->size;
+	    nextchain = nextchain->next;
+	}
+	PerlIO_printf(PerlIO_stderr(), "\nTotal sbrk(): %d/%d:%d. Odd ends: pad+heads+chain+tail: %d+%d+%d+%d.\n",
+		      goodsbrk + sbrk_slack, sbrks, sbrk_good, sbrk_slack,
+		      start_slack, total_chain, sbrked_remains);
+}
+#else
+void
+dump_mstats(char *s)
+{
+}
+#endif
+#endif /* lint */
+
+
+#ifdef USE_PERL_SBRK
+
+#   if defined(__MACHTEN_PPC__) || defined(__NeXT__)
+#      define PERL_SBRK_VIA_MALLOC
+/*
+ * MachTen's malloc() returns a buffer aligned on a two-byte boundary.
+ * While this is adequate, it may slow down access to longer data
+ * types by forcing multiple memory accesses.  It also causes
+ * complaints when RCHECK is in force.  So we allocate six bytes
+ * more than we need to, and return an address rounded up to an
+ * eight-byte boundary.
+ *
+ * 980701 Dominic Dunlop <domo@computer.org>
+ */
+#      define SYSTEM_ALLOC(a) ((void *)(((unsigned)malloc((a)+6)+6)&~7))
+#   endif
+
+#   ifdef PERL_SBRK_VIA_MALLOC
+#      if defined(HIDEMYMALLOC) || defined(EMBEDMYMALLOC)
+#         undef malloc		/* Expose names that  */
+#         undef calloc		/* HIDEMYMALLOC hides */
+#         undef realloc
+#         undef free
+#      else
+#         include "Error: -DPERL_SBRK_VIA_MALLOC needs -D(HIDE|EMBED)MYMALLOC"
+#      endif
+
+/* it may seem schizophrenic to use perl's malloc and let it call system */
+/* malloc, the reason for that is only the 3.2 version of the OS that had */
+/* frequent core dumps within nxzonefreenolock. This sbrk routine put an */
+/* end to the cores */
+
+#      ifndef SYSTEM_ALLOC
+#         define SYSTEM_ALLOC(a) malloc(a)
+#      endif
+
+#   endif  /* PERL_SBRK_VIA_MALLOC */
+
+static IV Perl_sbrk_oldchunk;
+static long Perl_sbrk_oldsize;
+
+#   define PERLSBRK_32_K (1<<15)
+#   define PERLSBRK_64_K (1<<16)
+
+Malloc_t
+Perl_sbrk(int size)
+{
+    IV got;
+    int small, reqsize;
+
+    if (!size) return 0;
+#ifdef PERL_CORE
+    reqsize = size; /* just for the DEBUG_m statement */
+#endif
+#ifdef PACK_MALLOC
+    size = (size + 0x7ff) & ~0x7ff;
+#endif
+    if (size <= Perl_sbrk_oldsize) {
+	got = Perl_sbrk_oldchunk;
+	Perl_sbrk_oldchunk += size;
+	Perl_sbrk_oldsize -= size;
+    } else {
+      if (size >= PERLSBRK_32_K) {
+	small = 0;
+      } else {
+	size = PERLSBRK_64_K;
+	small = 1;
+      }
+      got = (IV)SYSTEM_ALLOC(size);
+#ifdef PACK_MALLOC
+      got = (got + 0x7ff) & ~0x7ff;
+#endif
+      if (small) {
+	/* Chunk is small, register the rest for future allocs. */
+	Perl_sbrk_oldchunk = got + reqsize;
+	Perl_sbrk_oldsize = size - reqsize;
+      }
+    }
+
+    DEBUG_m(PerlIO_printf(Perl_debug_log, "sbrk malloc size %ld (reqsize %ld), left size %ld, give addr 0x%lx\n",
+		    size, reqsize, Perl_sbrk_oldsize, got));
+
+    return (void *)got;
+}
+
+#endif /* ! defined USE_PERL_SBRK */
Index: omalloc/pmalloc.h
===================================================================
--- omalloc/pmalloc.h	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
+++ omalloc/pmalloc.h	(revision b6e0394c78cf946226e16e683127acf5d8b489ae)
@@ -0,0 +1,33 @@
+/*******************************************************************
+ *  File:    omMallocSystem.h
+ *  Purpose: declaration of macros for malloc to be used from the system
+ *  Author:  obachman (Olaf Bachmann)
+ *  Created: 11/99
+ *  Version: $Id: pmalloc.h,v 1.1 2000-08-14 12:18:32 obachman Exp $
+ *******************************************************************/
+#ifndef OM_MALLOC_SYSTEM_H
+#define OM_MALLOC_SYSTEM_H
+
+#include "omConfig.h"
+
+/* define to -1 if you want that this implementation provides
+   malloc/calloc/realloc/free funcs */
+#ifndef OM_PROVIDE_MALLOC
+#define OM_PROVIDE_MALLOC 0
+#endif
+
+#if OM_PROVIDE_MALLOC != -1
+#define calloc  cALLOc		
+#define free    fREe		
+#define malloc  mALLOc		
+#define realloc rEALLOc
+#endif
+
+/* this is the minimal set of OM_MALLOC_* macros which must be defined */
+#define OM_MALLOC_MALLOC   malloc
+#define OM_MALLOC_REALLOC  realloc
+#define OM_MALLOC_FREE     free
+#define OM_MALLOC_VFREE(addr, size) OM_MALLOC_FREE(addr)
+
+#endif /* OM_MALLOC_SYSTEM_H */
+
