* configure.in: pic16 libraries build 2nd try - enable running
[fw/sdcc] / device / lib / realloc.c
1 /*-------------------------------------------------------------------------
2    realloc.c - reallocate allocated memory.
3
4    Copyright (C) 2004 - Maarten Brock, sourceforge.brock@dse.nl
5
6    This library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Lesser General Public
8    License as published by the Free Software Foundation; either
9    version 2.1 of the License, or (at your option) any later version.
10
11    This library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Lesser General Public License for more details.
15
16    You should have received a copy of the GNU Lesser General Public
17    License along with this library; if not, write to the Free Software
18    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 -------------------------------------------------------------------------*/
20
21 #include <sdcc-lib.h>
22 #include <malloc.h>
23 #include <string.h>
24
25 #if defined(SDCC_STACK_AUTO) || defined(SDCC_z80) || defined(SDCC_gbz80)
26   #define CRITICAL critical
27 #else
28   #define CRITICAL
29 #endif
30
31 //--------------------------------------------------------------------
32 //realloc function implementation for embedded system
33 //Non-ANSI keywords are C51 specific.
34 // xdata - variable in external memory (just RAM)
35 //--------------------------------------------------------------------
36
37 #if _SDCC_MALLOC_TYPE_MLH
38
39 #define xdata
40
41 typedef struct _MEMHEADER MEMHEADER;
42
43 struct _MEMHEADER
44 {
45   MEMHEADER *   next;
46   MEMHEADER *   prev;
47   unsigned int  len;
48   unsigned char mem;
49 };
50
51 #define HEADER_SIZE (sizeof(MEMHEADER)-sizeof(char))
52 #define MEM(x)      (&x->mem)
53
54 #else
55
56 #define HEADER_SIZE sizeof(MEMHEADER)
57 #define MEM(x)      (x->mem)
58
59 #endif
60
61 extern MEMHEADER xdata * _sdcc_prev_memheader;
62
63 // apart from finding the header
64 // this function also finds it's predecessor
65 extern MEMHEADER xdata * _sdcc_find_memheader(void xdata * p);
66
67 void xdata * realloc (void * p, size_t size)
68 {
69   register MEMHEADER xdata * pthis;
70   register MEMHEADER xdata * pnew;
71   register void xdata * ret;
72
73   CRITICAL
74   {
75     pthis = _sdcc_find_memheader(p);
76     if (pthis)
77     {
78       if (size > (0xFFFF-HEADER_SIZE))
79       {
80         ret = (void xdata *) NULL; //To prevent overflow in next line
81       }
82       else
83       {
84         size += HEADER_SIZE; //We need a memory for header too
85
86         if ((((unsigned int)pthis->next) - ((unsigned int)pthis)) >= size)
87         {//if spare is more than needed
88           pthis->len = size;
89           ret = p;
90         }
91         else
92         {
93           if ((_sdcc_prev_memheader) &&
94               ((((unsigned int)pthis->next) -
95                 ((unsigned int)_sdcc_prev_memheader) -
96                 _sdcc_prev_memheader->len) >= size))
97           {
98             pnew = (MEMHEADER xdata * )((char xdata *)_sdcc_prev_memheader + _sdcc_prev_memheader->len);
99             _sdcc_prev_memheader->next = pnew;
100             memmove(pnew, pthis, pthis->len);
101             pnew->len = size;
102             ret = MEM(pnew);
103           }
104           else
105           {
106             ret = malloc(size - HEADER_SIZE);
107             if (ret)
108             {
109               memcpy(ret, MEM(pthis), pthis->len - HEADER_SIZE);
110               free(p);
111             }
112           }
113         }
114       }
115     }
116     else
117     {
118       ret = malloc(size);
119     }
120   }
121   return ret;
122 }
123 //END OF MODULE