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