1
0
mirror of https://github.com/cc65/cc65.git synced 2024-06-01 13:41:34 +00:00
cc65/libsrc/common/_hadd.c
cuz ca815af077 iscntrl was not mentioned in the Makefile and therefor not built.
Change the isxxx functions to correctly handle values outside of character
range.


git-svn-id: svn://svn.cc65.org/cc65/trunk@33 b7a2c559-68d2-44c3-8de9-860c34a00d81
2000-06-08 18:35:04 +00:00

108 lines
2.7 KiB
C

/*
* _hadd.c
*
* Ullrich von Bassewitz, 19.06.1998
*/
#include <stddef.h>
#include "_heap.h"
void _hadd (void* mem, size_t size)
/* Add an arbitrary memory block to the heap. This function is used by
* free(), but it does also allow usage of otherwise unused memory
* blocks as heap space. The given block is entered in the free list
* without any checks, so beware!
*/
{
struct freeblock* f;
struct freeblock* left;
struct freeblock* right;
if (size >= sizeof (struct freeblock)) {
/* Set the admin data */
f = (struct freeblock*) mem;
f->size = size;
/* Check if the freelist is empty */
if (_hfirst == 0) {
/* The freelist is empty until now, insert the block */
f->prev = 0;
f->next = 0;
_hfirst = f;
_hlast = f;
} else {
/* We have to search the free list. As we are doing so, we check
* if it is possible to combine this block with another already
* existing block. Beware: The block may be the "missing link"
* between *two* other blocks.
*/
left = 0;
right = _hfirst;
while (right && f > right) {
left = right;
right = right->next;
}
/* Ok, the current block must be inserted between left and right (but
* beware: one of the two may be zero!). Also check for the condition
* that we have to merge two or three blocks.
*/
if (right) {
/* Check if we must merge the block with the right one */
if (((unsigned) f) + size == (unsigned) right) {
/* Merge with the right block */
f->size += right->size;
if (f->next = right->next) {
f->next->prev = f;
} else {
/* This is now the last block */
_hlast = f;
}
} else {
/* No merge, just set the link */
f->next = right;
right->prev = f;
}
} else {
f->next = 0;
/* Special case: This is the new freelist end */
_hlast = f;
}
if (left) {
/* Check if we must merge the block with the left one */
if ((unsigned) f == ((unsigned) left) + left->size) {
/* Merge with the left block */
left->size += f->size;
if (left->next = f->next) {
left->next->prev = left;
} else {
/* This is now the last block */
_hlast = left;
}
} else {
/* No merge, just set the link */
left->next = f;
f->prev = left;
}
} else {
f->prev = 0;
/* Special case: This is the new freelist start */
_hfirst = f;
}
}
}
}