The memory management bases upon the widely used management:
	highest address
		far heap
		stack
		local heap
		local data
		code
		PSP
	lowest address
With near pointer data models (tiny, small, medium) the far heap must be
accessed by the _f*() or _h*() equivalents to the "normal" functions. These
will automatically create any necessary management structures to access the
far memory.
With far pointer data models (compact, far, huge) the local heap does not
exist, except for internal useage, perhaps. All normal functions are mapped
to the associated _f*() or _h*() function.

If the __HEAP_ALIGN macro is defined, the start of an allocated block, the
node's data portion, is aligned on an address dividable by (2^__HEAP_ALIGN).
If __HEAP_ALIGN is undefined or defined to zero, no alignment takes place.
For instance, if __HEAP_ALIGN is 1; all addresses are aligned to the
next address that is a multiple of 2.
Because of the internals of some processors reading multi-byte values
from odd addresses may cost (much) more than from even addresses. One
has to consider the pros (higher access speed) and contras (waste of
memory).

The alignment is achieved by this mechanism:
 Consider (struct HeapNode) the structure of the control block preceeding
each allocated block of memory in the heap;
 page offset is the lowest non-negative number, that satisfies:
	(page offset + sizeof(struct HeapNode)) % (1 << __HEAP_ALIGN) == 0
 When allocating memory at address 'addr' the length of the block is
	incremented by the lowest non-negative number # that satisfies:
		(FP_OFF(addr) + length + #) % (1 << __HEAP_ALIGN) == page offset
Note: This mechanism does neither align the node itself, only its data
portion, nor does it rely on the alignment itself. This will make
the mechanism a bit more robust, thus, possibly somewhat less clever.
Also note: Because currently the alignment takes place when allocating
new blocks at least one node (the very first one) is not necessarily aligned.

The recommended values of __HEAP_ALIGN for the local heap are: 0 and 1.
For the far heap: 0 or 2 or 3.

The far version of the heap functions _f*() and the huge ones _h*()
does not differ much, except in the size one memory object may occupy:
(size_t) [normally 64KB] for "far", (hsize_t) [normally 2GB] for "huge".
Both version can be interchangeable be used within the far heap, or,
so to say, there is no difference between a far or huge heap.

The local heap, the stack, and, in near pointer data models, the local
data are grouped together into the same segment, thus, they cannot
exceed 64KB in size.
The local heap begins at the pointer of the global variable _heap and
ends, where the stack pointer points to, minus a security value.

The far heap do support both brk()/sbrk() and fragmented memory, though,
because of the nature of brk()/sbrk() when the user uses brk()/sbrk()
the normal far heap management cannot be used anymore and the user can
access a single fragment, where the program is located itself, only.
The user may savely use "addr = sbrk(0)" and "brk(addr)" to shrink back
the allocated memory even in fragmented mode. The user may use "brk(anyaddr);
_fheaprebuild();" with "anyaddr < sbrk(0)", though, there is no garantee
that "sbrk(0)" will return "anyaddr" after that.

In fragmented mode malloc() tries each fragment for unused space. If none
is found, each fragment is tried to sbrk(), thus, reallocating the fragment
to have the necessary space. On failure another fragment is created with
the size of the necessary space. On failure, malloc() invokes the function
(*_hnomem)(), which normally simply returns NULL to indicate the "no error"
condition. The user may provide a function that allocates the necessary
space.
The first fragment is the memory area in which the program is located
itself.

#if 0
If the user uses brk()/sbrk() to expand the memory, he alters the first
fragment only. This will also disable the reallocating of the first
fragment and the creation of new fragments. But the user may apply
the _hfrgusrcrt() function to _hnomem in order to create a new fragment
with the first fragment expanded to its maximum and later shrunken back.
#endif

The far heap can hold both blocks smaller than and larger than 64KB.
If a block is smaller, the mechanism is similar to the local heap.
If a block is larger, the machanism aligns at a paragraphe boundary,
thus, the block length is a multiple of 16 now and can be stored into
a (word), too. The huge functions default to the far functions if the
size is less than 64KB.
Note: Due to implementation internals the block boundary is not exactly
64KB, but a little less; approx. 16 bytes less.

To support debugging dynamic memory accesses all heap functions will
support a debug mode (at compile time) that will do this:
a) Fill allocated but uninitialized memory with a character,
b) overwrite free'ed memory with another character.
Note: realloc() and free() are stable in regards of passing invalid
pointers to these functions even without the debug option enabled.
