+
+ /* If not found, obtain more space. */
+ if (h == NIL_HEAP)
+ {
+ get += extra_bytes + page_size;
+
+ if (! obtain (address, get))
+ return 0;
+
+ if (first_heap == last_heap)
+ address = (POINTER) ROUNDUP (virtual_break_value);
+ else
+ address = (POINTER) ROUNDUP (last_heap->start);
+ h = last_heap;
+ }
+
+ new_bloc_start = (POINTER) MEM_ROUNDUP ((char *)address + get);
+
+ if (first_heap->bloc_start < new_bloc_start)
+ {
+ /* This is no clean solution - no idea how to do it better. */
+ if (r_alloc_freeze_level)
+ return NIL;
+
+ /* There is a bug here: if the above obtain call succeeded, but the
+ relocate_blocs call below does not succeed, we need to free
+ the memory that we got with obtain. */
+
+ /* Move all blocs upward. */
+ if (! relocate_blocs (first_bloc, h, new_bloc_start))
+ return 0;
+
+ /* Note that (POINTER)(h+1) <= new_bloc_start since
+ get >= page_size, so the following does not destroy the heap
+ header. */
+ for (b = last_bloc; b != NIL_BLOC; b = b->prev)
+ {
+ safe_bcopy (b->data, b->new_data, b->size);
+ *b->variable = b->data = b->new_data;
+ }
+
+ h->bloc_start = new_bloc_start;
+
+ update_heap_bloc_correspondence (first_bloc, h);
+ }
+ if (h != first_heap)
+ {
+ /* Give up managing heaps below the one the new
+ virtual_break_value points to. */
+ first_heap->prev = NIL_HEAP;
+ first_heap->next = h->next;
+ first_heap->start = h->start;
+ first_heap->end = h->end;
+ first_heap->free = h->free;
+ first_heap->first_bloc = h->first_bloc;
+ first_heap->last_bloc = h->last_bloc;
+ first_heap->bloc_start = h->bloc_start;
+
+ if (first_heap->next)
+ first_heap->next->prev = first_heap;
+ else
+ last_heap = first_heap;
+ }
+
+ bzero (address, size);