Imported Upstream version 2.9.0
[debian/cc1111] / 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 MEMHEADER   struct MAH// Memory Allocation Header
57
58 MEMHEADER
59 {
60   MEMHEADER __xdata *  next;
61   unsigned int         len;
62   unsigned char        mem[];
63 };
64
65 #define HEADER_SIZE sizeof(MEMHEADER)
66 #define MEM(x)      (x->mem)
67
68 #endif
69
70 extern MEMHEADER __xdata * _sdcc_prev_memheader;
71
72 // apart from finding the header
73 // this function also finds it's predecessor
74 extern MEMHEADER __xdata * _sdcc_find_memheader(void __xdata * p);
75
76 void __xdata * realloc (void * p, size_t size)
77 {
78   register MEMHEADER __xdata * pthis;
79   register MEMHEADER __xdata * pnew;
80   register void __xdata * ret;
81
82   CRITICAL
83   {
84     pthis = _sdcc_find_memheader(p);
85     if (pthis)
86     {
87       if (size > (0xFFFF-HEADER_SIZE))
88       {
89         ret = (void __xdata *) NULL; //To prevent overflow in next line
90       }
91       else
92       {
93         size += HEADER_SIZE; //We need a memory for header too
94
95         if ((((unsigned int)pthis->next) - ((unsigned int)pthis)) >= size)
96         {//if spare is more than needed
97           pthis->len = size;
98           ret = p;
99         }
100         else
101         {
102           if ((_sdcc_prev_memheader) &&
103               ((((unsigned int)pthis->next) -
104                 ((unsigned int)_sdcc_prev_memheader) -
105                 _sdcc_prev_memheader->len) >= size))
106           {
107             pnew = (MEMHEADER __xdata * )((char __xdata *)_sdcc_prev_memheader + _sdcc_prev_memheader->len);
108             _sdcc_prev_memheader->next = pnew;
109
110 #if _SDCC_MALLOC_TYPE_MLH
111             pthis->next->prev = pnew;
112 #endif
113
114             memmove(pnew, pthis, pthis->len);
115             pnew->len = size;
116             ret = MEM(pnew);
117           }
118           else
119           {
120             ret = malloc(size - HEADER_SIZE);
121             if (ret)
122             {
123               memcpy(ret, MEM(pthis), pthis->len - HEADER_SIZE);
124               free(p);
125             }
126           }
127         }
128       }
129     }
130     else
131     {
132       ret = malloc(size);
133     }
134   }
135   return ret;
136 }
137 //END OF MODULE