1 /* UtilsRO.c */
2 
3 /* RiscOS implementation of utils.h
4  * (K) All Rites Reversed - Copy What You Like (see file Copying)
5  *
6  * Authors:
7  *      Peter Hartley       <pdh@chaos.org.uk>
8  *
9  * History:
10  *      10-Nov-96 pdh Started
11  *      15-Dec-96 *** Release 5beta1
12  *      27-Jan-97 *** Release 5beta2
13  *      29-Jan-97 *** Release 5beta3
14  *      02-Feb-97 pdh Add Anim_Percent
15  *      03-Feb-97 *** Release 5
16  *      07-Feb-97 *** Release 5.01
17  *      01-Mar-97 pdh Added Reallocate
18  *      07-Apr-97 *** Release 6beta1
19  *      20-May-97 *** Release 6beta2
20  *      24-Aug-97 *** Release 6
21  *      27-Sep-97 *** Release 6.01
22  *      12-Oct-97 pdh Remove last ExtrasLib dependency
23  *      08-Nov-97 *** Release 6.02
24  *      21-Feb-98 *** Release 6.03
25  *      07-Jun-98 *** Release 6.04
26  *      21-Aug-98 *** Release 6.05
27  *      19-Feb-99 *** Release 6.07
28  *      26-Mar-00 *** Release 6.10
29  *
30  */
31 
32 #include <stdlib.h>
33 #include <string.h>
34 #include "kernel.h"
35 
36 #include "DeskLib:File.h"
37 #include "DeskLib:Hourglass.h"
38 
39 #include "utils.h"
40 
41 #if 0
42 #define debugf printf
43 #define DEBUG 1
44 #else
45 #define debugf 1?0:printf
46 #define DEBUG 0
47 #endif
48 
Anim_FileSize(const char * filename)49 int Anim_FileSize( const char *filename )
50 {
51     return File_Size( (char*)filename );
52 }
53 
Anim_LoadFile(const char * filename,void * data)54 BOOL Anim_LoadFile( const char *filename, void *data )
55 {
56     FILE *f = fopen( filename, "rb" );
57     size_t sz;
58 
59     if ( !f )
60         return FALSE;
61 
62     fseek( f, 0, SEEK_END );
63 
64     sz = (size_t)ftell(f);
65 
66     fseek( f, 0, SEEK_SET );
67 
68     fread( data, 1, sz, f );
69 
70     fclose( f );
71 
72     return TRUE;
73 }
74 
Anim_SetFileType(const char * filename,int type)75 void Anim_SetFileType( const char *filename, int type )
76 {
77     File_SetType( (char*)filename, type );
78 }
79 
Anim_Percent(int percent)80 void Anim_Percent( int percent )
81 {
82     /* Rather fortunately, this does nothing if the hourglass isn't showing */
83     Hourglass_Percentage( percent );
84 }
85 
86 #if DEBUG
87 /* Exciting allocation checking */
88 
89 #define MAGICWORD 0x6B637546
90 
91 typedef struct memcheck {
92     struct memcheck *next;
93     struct memcheck *prev;
94     int nSize;
95     int magic;
96     char data[1];       /* or more */
97 } memcheck;
98 
99 memcheck *list = NULL;
100 
101 int inuse = 0;
102 int hwm = 0;
103 
Anim_Allocate(int nSize)104 void *Anim_Allocate( int nSize )
105 {
106     void *res;
107     memcheck *mc;
108 
109     nSize = ( nSize+3 ) & (~3);
110 
111     debugf( "malloc(%d)\n", nSize );
112 
113     res = malloc( nSize + 16 + 4 );
114     mc = (memcheck*) res;
115 
116     if ( !res )
117     {
118         debugf( "malloc fails!\n" );
119         return NULL;
120     }
121 
122     if ( list )
123         list->prev = mc;
124 
125     mc->next = list;
126     mc->prev = NULL;
127     list = mc;
128     mc->magic = MAGICWORD;
129     mc->nSize = nSize;
130     *(int*)(mc->data + nSize) = MAGICWORD;
131 
132     inuse += nSize;
133     if ( inuse > hwm )
134         hwm = inuse;
135 
136     return mc->data;
137 }
138 
ValidateAddress(void * addr)139 static BOOL ValidateAddress( void *addr )
140 {
141     _kernel_swi_regs r;
142     int c;
143 
144     r.r[0] = (int)addr;
145     r.r[1] = 4 + (int)addr;
146     _kernel_swi_c( 0x2003A, &r, &r, &c );
147     return c==0;
148 }
149 
CheckBlock(memcheck * mc)150 static void CheckBlock( memcheck *mc )
151 {
152     int tail;
153 
154     if ( ((int)mc)&3 || !ValidateAddress( mc ) )
155     {
156         debugf( "Invalid address (0x%p) passed to CheckBlock\n", mc );
157         *((int*)-1)=-1;
158     }
159 
160     if ( mc->magic != MAGICWORD )
161     {
162         debugf( "Head magic word corrupt (0x%08x) sz=%d\n", mc->magic, mc->nSize );
163         *((int*)-1)=-1;
164     }
165 
166     tail = *((int*)(mc->data + mc->nSize));
167     if ( tail != MAGICWORD )
168     {
169         debugf( "Tail magic word corrupt (0x%08x) sz=%d\n", tail,
170                  mc->nSize );
171         *((int*)-1)=-1;
172     }
173 }
174 
Anim_CheckHeap(char * file,int line)175 void Anim_CheckHeap( char *file, int line)
176 {
177     memcheck *mc = list;
178 
179     if ( file )
180         debugf( "Checking heap from %s:%d\n", file, line );
181 
182     while ( mc )
183     {
184         CheckBlock( mc );
185         if ( mc == mc->next )
186         {
187             debugf( "Cycle in list! (0x%08p) sz=%d\n", mc, mc->nSize );
188             *((int*)-1)=-1;
189         }
190 
191         mc = mc->next;
192     }
193 }
194 
Anim_Free(void * pp)195 void Anim_Free( void *pp )
196 {
197     void *pBlock = *(void**)pp;
198     if ( pBlock )
199     {
200         memcheck *mc = (memcheck*)( (char*)pBlock - 16 );
201 
202         CheckBlock( mc );
203 
204         if ( mc->prev )
205             mc->prev->next = mc->next;
206         else
207             list = mc->next;
208 
209         if ( mc->next )
210             mc->next->prev = mc->prev;
211 
212         debugf( "free(%d)\n", mc->nSize );
213 
214         inuse -= mc->nSize;
215 
216         free( mc );
217         *(void**)pp = NULL;
218     }
219 }
220 
Anim_Reallocate(void * pBlock,int nSize)221 void *Anim_Reallocate( void *pBlock, int nSize )
222 {
223     memcheck *mc;
224     void *res;
225     int cpy;
226 
227     if ( !pBlock && !nSize )
228         return NULL;
229 
230     if ( !pBlock )
231         return Anim_Allocate( nSize );
232 
233     if ( !nSize )
234     {
235         Anim_Free( &pBlock );
236         return NULL;
237     }
238 
239     mc = (memcheck*)( (char*)pBlock - 16 );
240 
241     CheckBlock( mc );
242 
243     debugf( "realloc(%d->%d)\n", mc->nSize, nSize );
244 
245     res = Anim_Allocate( nSize );
246     if ( !res )
247         return NULL;
248 
249     cpy = nSize > mc->nSize ? mc->nSize : nSize;
250     memcpy( res, pBlock, nSize );
251     Anim_Free( &pBlock );
252     return res;
253 }
254 
Anim_ListHeap(void)255 void Anim_ListHeap( void )
256 {
257     memcheck *mc = list;
258 
259     while ( mc )
260     {
261         CheckBlock(mc);
262         printf( "%p: size %d\n", mc, mc->nSize );
263         mc = mc->next;
264     }
265 
266     printf( "memory in use %d, max was %d\n", inuse, hwm );
267 }
268 
269 #else
270 
Anim_Allocate(int nSize)271 void *Anim_Allocate( int nSize )
272 {
273     return malloc( nSize );
274 }
275 
Anim_Free(void * pp)276 void Anim_Free( void *pp )
277 {
278     void *pBlock = *(void**)pp;
279     if ( pBlock )
280     {
281         free( pBlock );
282         *(void**)pp = NULL;
283     }
284 }
285 
Anim_Reallocate(void * pBlock,int nSize)286 void *Anim_Reallocate( void *pBlock, int nSize )
287 {
288     return realloc( pBlock, nSize );
289 }
290 
291 #endif
292 
293 static anim_flexallocproc *flexalloc = NULL;
294 static anim_flexfreeproc *flexfree = NULL;
295 #if 0
296 static anim_flexreallocproc *flexrealloc = NULL;
297 
298 void Anim_RegisterFlexAllocator( anim_flexallocproc fa,
299                                  anim_flexreallocproc fr,
300                                  anim_flexfreeproc ff )
301 {
302     flexalloc = fa;
303     flexrealloc = fr;
304     flexfree = ff;
305 }
306 #endif
307 
Anim_FlexAllocate(void * pp,int nSize)308 void Anim_FlexAllocate( void *pp, int nSize )
309 {
310     if ( flexalloc )
311         (*flexalloc)(pp,nSize);
312     else
313     {
314         *(void**)pp = Anim_Allocate( nSize );
315     }
316 }
317 
318 #if 0
319 BOOL Anim_FlexReallocate( void *pp, int nNewSize )
320 {
321     if ( flexrealloc )
322         return (*flexrealloc)(pp,nNewSize);
323     else
324     {
325         void *p = *(void**)pp;
326         void *p2 = Anim_Reallocate( p, nNewSize );
327 
328         if ( p2 )
329             *(void**)pp = p2;
330         return ( p2 != NULL );
331     }
332 }
333 #endif
334 
Anim_FlexFree(void * pp)335 void Anim_FlexFree( void *pp )
336 {
337     if ( flexfree )
338         (*flexfree)(pp);
339     else
340     {
341         Anim_Free(pp);
342     }
343 }
344 
345 /* eof */
346