+#include <sdcc-lib.h>
+#if _SDCC_MALLOC_TYPE_MLH
+#include <malloc.h>
+
+typedef struct _MEMHEADER MEMHEADER;
+
+struct _MEMHEADER
+{
+ MEMHEADER * next;
+ MEMHEADER * prev;
+ unsigned int len;
+ unsigned char mem;
+};
+
+#define HEADER_SIZE (sizeof(MEMHEADER)-sizeof(char))
+#define NULL 0
+
+/* These veriables are defined through the crt0 functions. */
+/* Base of this variable is the first byte of the heap. */
+extern MEMHEADER _sdcc_heap_start;
+/* Address of this variable is the last byte of the heap. */
+extern char _sdcc_heap_end;
+
+void
+_sdcc_heap_init(void)
+{
+ MEMHEADER *pbase = &_sdcc_heap_start;
+ unsigned int size = &_sdcc_heap_end - (char *)pbase;
+
+ pbase->next = (MEMHEADER *)((char *)pbase + size - HEADER_SIZE);
+ pbase->next->next = NULL; //And mark it as last
+ pbase->prev = NULL; //and mark first as first
+ pbase->len = 0; //Empty and ready.
+}
+
+void *
+malloc (unsigned int size)
+{
+ MEMHEADER * current_header;
+ MEMHEADER * new_header;
+
+ if (size>(0xFFFF-HEADER_SIZE))
+ {
+ return NULL; //To prevent overflow in next line
+ }
+
+ size += HEADER_SIZE; //We need a memory for header too
+ current_header = &_sdcc_heap_start;
+
+ while (1)
+ {
+ // current
+ // | len next
+ // v v v
+ //....*****.........******....
+ // ^^^^^^^^^
+ // spare
+
+ if ((((unsigned int)current_header->next) -
+ ((unsigned int)current_header) -
+ current_header->len) >= size)
+ {
+ break; //if spare is more than need
+ }
+ current_header = current_header->next; //else try next
+ if (!current_header->next)
+ {
+ return NULL; //if end_of_list reached
+ }
+ }
+
+ if (!current_header->len)
+ { //This code works only for first_header in the list and only
+ current_header->len = size; //for first allocation
+ return ¤t_header->mem;
+ }
+ else
+ {
+ //else create new header at the begin of spare
+ new_header = (MEMHEADER * )((char *)current_header + current_header->len);
+ new_header->next = current_header->next; //and plug it into the chain
+ new_header->prev = current_header;
+ current_header->next = new_header;
+ if (new_header->next)
+ {
+ new_header->next->prev = new_header;
+ }
+ new_header->len = size; //mark as used
+ return &new_header->mem;
+ }
+}
+
+void
+free (void *p)
+{
+ MEMHEADER *prev_header, *pthis;
+
+ if ( p ) //For allocated pointers only!
+ {
+ pthis = (MEMHEADER * )((char *) p - HEADER_SIZE); //to start of header
+ if ( pthis->prev ) // For the regular header
+ {
+ prev_header = pthis->prev;
+ prev_header->next = pthis->next;
+ if (pthis->next)
+ {
+ pthis->next->prev = prev_header;
+ }
+ }
+ else
+ {
+ pthis->len = 0; //For the first header
+ }
+ }
+}
+
+#else
//--------------------------------------------------------------------
//Written by Dmitry S. Obukhov, 1997
MEMHEADER xdata * next;
MEMHEADER xdata * prev;
unsigned int len;
- unsigned char mem[1];
+ unsigned char mem;
};
#define HEADER_SIZE (sizeof(MEMHEADER)-1)
if (!current_header->len)
{ //This code works only for first_header in the list and only
current_header->len = size; //for first allocation
- return (current_header->mem);
+ return ((xdata *)&(current_header->mem));
} //else create new header at the begin of spare
new_header = (MEMHEADER xdata * )((char xdata *)current_header + current_header->len);
new_header->next = current_header->next; //and plug it into the chain
current_header->next = new_header;
if (new_header->next) new_header->next->prev = new_header;
new_header->len = size; //mark as used
- return (new_header->mem);
+ return ((xdata *)&(new_header->mem));
}
void free (MEMHEADER xdata * p)
}
//END OF MODULE
+#endif