54fde7f92f09bfaf164d51317ed4a42e9528df98
[fw/sdcc] / device / lib / realloc.c
1 #include <sdcc-lib.h>
2 #include <malloc.h>
3 #include <string.h>
4
5 //--------------------------------------------------------------------
6 //Written by Maarten Brock, 2004
7 //--------------------------------------------------------------------
8 //realloc function implementation for embedded system
9 //Non-ANSI keywords are C51 specific.
10 // xdata - variable in external memory (just RAM)
11 //--------------------------------------------------------------------
12
13 #if _SDCC_MALLOC_TYPE_MLH
14
15 #define xdata
16
17 typedef struct _MEMHEADER MEMHEADER;
18
19 struct _MEMHEADER
20 {
21   MEMHEADER *   next;
22   MEMHEADER *   prev;
23   unsigned int  len;
24   unsigned char mem;
25 };
26
27 #define HEADER_SIZE (sizeof(MEMHEADER)-sizeof(char))
28
29 #else
30
31 #define HEADER_SIZE sizeof(MEMHEADER)
32
33 #endif
34
35 extern MEMHEADER xdata * _sdcc_prev_memheader;
36
37 // apart from finding the header
38 // this function also finds it's predecessor
39 extern MEMHEADER xdata * _sdcc_find_memheader(void xdata * p);
40
41 void xdata * realloc (void * p, size_t size)
42 {
43   register MEMHEADER xdata * pthis;
44   register MEMHEADER xdata * pnew;
45
46   pthis = _sdcc_find_memheader(p);
47   if (pthis)
48   {
49     if (size>(0xFFFF-HEADER_SIZE)) return (void xdata *) NULL; //To prevent overflow in next line
50     size += HEADER_SIZE; //We need a memory for header too
51
52     if ((((unsigned int)pthis->next) - ((unsigned int)pthis)) >= size)
53     {//if spare is more than need
54       pthis->len = size;
55       return p;
56     }
57
58     if ((_sdcc_prev_memheader) &&
59         ((((unsigned int)pthis->next) -
60           ((unsigned int)_sdcc_prev_memheader) -
61           _sdcc_prev_memheader->len) >= size))
62     {
63       pnew = (MEMHEADER xdata * )((char xdata *)_sdcc_prev_memheader + _sdcc_prev_memheader->len);
64       _sdcc_prev_memheader->next = pnew;
65       memmove(pnew, pthis, pthis->len);
66       pnew->len = size;
67       return pnew->mem;
68     }
69
70     pnew = malloc(size - HEADER_SIZE);
71     if (pnew)
72     {
73       memcpy(pnew, pthis->mem, pthis->len - HEADER_SIZE);
74       free(p);
75     }
76     return pnew;
77   }
78   else
79   {
80         return malloc(size);
81   }
82 }
83 //END OF MODULE