+#define ALIGNED(addr) (((unsigned long int) (addr) & (page_size - 1)) == 0)
+#define ROUNDUP(size) (((unsigned long int) (size) + page_size - 1) \
+ & ~(page_size - 1))
+#define ROUND_TO_PAGE(addr) (addr & (~(page_size - 1)))
+
+#define MEM_ALIGN sizeof(double)
+#define MEM_ROUNDUP(addr) (((unsigned long int)(addr) + MEM_ALIGN - 1) \
+ & ~(MEM_ALIGN - 1))
+\f
+/* Data structures of heaps and blocs. */
+
+/* The relocatable objects, or blocs, and the malloc data
+ both reside within one or more heaps.
+ Each heap contains malloc data, running from `start' to `bloc_start',
+ and relocatable objects, running from `bloc_start' to `free'.
+
+ Relocatable objects may relocate within the same heap
+ or may move into another heap; the heaps themselves may grow
+ but they never move.
+
+ We try to make just one heap and make it larger as necessary.
+ But sometimes we can't do that, because we can't get contiguous
+ space to add onto the heap. When that happens, we start a new heap. */
+
+typedef struct heap
+{
+ struct heap *next;
+ struct heap *prev;
+ /* Start of memory range of this heap. */
+ POINTER start;
+ /* End of memory range of this heap. */
+ POINTER end;
+ /* Start of relocatable data in this heap. */
+ POINTER bloc_start;
+ /* Start of unused space in this heap. */
+ POINTER free;
+ /* First bloc in this heap. */
+ struct bp *first_bloc;
+ /* Last bloc in this heap. */
+ struct bp *last_bloc;
+} *heap_ptr;
+
+#define NIL_HEAP ((heap_ptr) 0)
+#define HEAP_PTR_SIZE (sizeof (struct heap))
+
+/* This is the first heap object.
+ If we need additional heap objects, each one resides at the beginning of
+ the space it covers. */
+static struct heap heap_base;
+
+/* Head and tail of the list of heaps. */
+static heap_ptr first_heap, last_heap;
+
+/* These structures are allocated in the malloc arena.
+ The linked list is kept in order of increasing '.data' members.
+ The data blocks abut each other; if b->next is non-nil, then
+ b->data + b->size == b->next->data.
+
+ An element with variable==NIL denotes a freed block, which has not yet
+ been collected. They may only appear while r_alloc_freeze > 0, and will be
+ freed when the arena is thawed. Currently, these blocs are not reusable,
+ while the arena is frozen. Very inefficient. */
+
+typedef struct bp
+{
+ struct bp *next;
+ struct bp *prev;
+ POINTER *variable;
+ POINTER data;
+ SIZE size;
+ POINTER new_data; /* temporarily used for relocation */
+ struct heap *heap; /* Heap this bloc is in. */
+} *bloc_ptr;
+
+#define NIL_BLOC ((bloc_ptr) 0)
+#define BLOC_PTR_SIZE (sizeof (struct bp))
+
+/* Head and tail of the list of relocatable blocs. */
+static bloc_ptr first_bloc, last_bloc;
+
+static int use_relocatable_buffers;
+
+/* If >0, no relocation whatsoever takes place. */
+static int r_alloc_freeze_level;
+