+ /* Now see if we can return stuff to the system. */
+ /* blocks = mdp -> heapinfo[block].free.size;
+ if (blocks >= FINAL_FREE_BLOCKS && block + blocks == mdp -> heaplimit
+ && mdp -> morecore (mdp, 0) == ADDRESS (block + blocks))
+ {
+ register size_t bytes = blocks * BLOCKSIZE;
+ mdp -> heaplimit -= blocks;
+ mdp -> morecore (mdp, -bytes);
+ mdp -> heapinfo[mdp -> heapinfo[block].free.prev].free.next
+ = mdp -> heapinfo[block].free.next;
+ mdp -> heapinfo[mdp -> heapinfo[block].free.next].free.prev
+ = mdp -> heapinfo[block].free.prev;
+ block = mdp -> heapinfo[block].free.prev;
+ mdp -> heapstats.chunks_free--;
+ mdp -> heapstats.bytes_free -= bytes;
+ } */
+
+ /* Set the next search to begin at this block. */
+ mdp->heapindex = block;
+ break;
+
+ default:
+ /* Do some of the statistics. */
+ mdp -> heapstats.chunks_used--;
+ mdp -> heapstats.bytes_used -= 1 << type;
+ mdp -> heapstats.chunks_free++;
+ mdp -> heapstats.bytes_free += 1 << type;
+
+
+ /* Get the address of the first free fragment in this block. */
+ prev = (struct list *)
+ ((char *) ADDRESS(block) +
+ (mdp->heapinfo[block].busy_frag.first << type));
+
+ if (mdp->heapinfo[block].busy_frag.nfree ==
+ (BLOCKSIZE >> type) - 1) {
+ /* If all fragments of this block are free, remove them
+ from the fragment list and free the whole block. */
+ next = prev;
+ for (i = 1; i < (size_t) (BLOCKSIZE >> type); ++i) {
+ next = next->next;
+ }
+ prev->prev->next = next;
+ if (next != NULL) {
+ next->prev = prev->prev;
+ }
+ /* pretend that this block is used and free it so that it gets properly coalesced with adjacent free blocks */
+ mdp->heapinfo[block].type = 0;
+ mdp->heapinfo[block].busy_block.size = 1;
+ mdp->heapinfo[block].busy_block.busy_size = 0;
+
+ /* Keep the statistics accurate. */
+ mdp -> heapstats.chunks_used++;
+ mdp -> heapstats.bytes_used += BLOCKSIZE;
+ mdp -> heapstats.chunks_free -= BLOCKSIZE >> type;
+ mdp -> heapstats.bytes_free -= BLOCKSIZE;
+
+ mfree((void *) mdp, (void *) ADDRESS(block));
+ } else if (mdp->heapinfo[block].busy_frag.nfree != 0) {
+ /* If some fragments of this block are free, link this
+ fragment into the fragment list after the first free
+ fragment of this block. */
+ next = (struct list *) ptr;
+ next->next = prev->next;
+ next->prev = prev;
+ prev->next = next;
+ if (next->next != NULL) {
+ next->next->prev = next;
+ }
+ ++mdp->heapinfo[block].busy_frag.nfree;
+ } else {
+ /* No fragments of this block were free before the one we just released,
+ * so link this fragment into the fragment list and announce that
+ it is the first free fragment of this block. */
+ prev = (struct list *) ptr;
+ mdp->heapinfo[block].busy_frag.nfree = 1;
+ mdp->heapinfo[block].busy_frag.first =
+ RESIDUAL(ptr, BLOCKSIZE) >> type;
+ prev->next = mdp->fraghead[type].next;
+ prev->prev = &mdp->fraghead[type];
+ prev->prev->next = prev;
+ if (prev->next != NULL) {
+ prev->next->prev = prev;
+ }
+ }
+ break;
+ }