On i386-darwin, some POSIX conformant versions of functions have a
[AROS.git] / tools / cxref / memory.c
blobb263fb8baab202e41e583f3be1f4cd10fae53590
1 /***************************************
2 $Header$
4 C Cross Referencing & Documentation tool. Version 1.5.
6 Memory management functions
7 ******************/ /******************
8 Written by Andrew M. Bishop
10 This file Copyright 1995,96,97 Andrew M. Bishop
11 It may be distributed under the GNU Public License, version 2, or
12 any higher version. See section COPYING of the GNU Public license
13 for conditions under which this file may be redistributed.
14 ***************************************/
16 /*+ The amount of debugging, non-zero for totals, 2 for logging, 4 for printing each call. +*/
17 #define DEBUG 0
19 /* The configure output */
21 #include "autoconfig.h"
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
27 #ifdef USE_STD_ARG
28 #include <stdarg.h>
29 #else
30 #include <varargs.h>
31 #endif
33 #include "memory.h"
35 /*+ A private memory heap is used to reduce the number of malloc calls that are made, the Heap type is a pointer to this. +*/
36 typedef struct _Heap *Heap;
38 /*+ A structure containing all of the information about the private heap in a linked list. +*/
39 struct _Heap
41 char* mem; /*+ The memory that is private to the heap. +*/
42 Heap next; /*+ The next Heap structure. +*/
45 /*+ Local variable to control the usage of the private heap; +*/
46 static Heap first=NULL; /*+ the first segment of memory on the private heap. +*/
47 static int heap_left=0; /*+ the amount of space left in the current heap segment. +*/
49 static char* get_space(unsigned int l);
50 static Heap add_to_heap(unsigned int l);
52 #if DEBUG&2
53 /*+ Variable used for debugging, not a good thing to do. what if more than 16384 mallocs? +*/
54 static void* addresses[16384];
55 static char* files[16384];
56 static int lines[16384];
57 #endif
58 #if DEBUG
59 /*+ Variable used for debugging. +*/
60 static int malloc_count=0;
61 static int realloc_count=0;
62 static int free_count=0;
63 #endif
66 /*++++++++++++++++++++++++++++++++++++++
67 A replacement malloc() function.
69 void* SafeMalloc Returns the address.
71 unsigned int size The size of the memory to allocate.
73 char* file The file that the function is called from.
75 int line The line number that the function is called from.
76 ++++++++++++++++++++++++++++++++++++++*/
78 void* SafeMalloc(unsigned int size,char* file,int line)
80 void* rptr=malloc(size);
82 #if DEBUG&4
83 printf("$$Malloc #%5d of %4d bytes at %08lx (%s:%3d)\n",malloc_count+1,size,(long)rptr,file,line);
84 #endif
85 #if DEBUG&2
86 if(malloc_count==(sizeof(addresses)/sizeof(addresses[0])))
87 {fprintf(stderr,"$$Too many Mallocs to log, edit memory.c\n");exit(3);}
88 addresses[malloc_count]=(void*)rptr;
89 files[malloc_count]=file;
90 lines[malloc_count]=line;
91 #endif
92 #if DEBUG
93 malloc_count++;
94 if(!rptr) printf("$$Warning Malloc() returning NULL (%s:%3d)\n",file,line);
95 #endif
96 #if !DEBUG
97 if(!rptr) printf("Warning Malloc() returning NULL (%s:%3d)\n",file,line);
98 #endif
100 return(rptr);
104 /*++++++++++++++++++++++++++++++++++++++
105 A replacement calloc() function.
107 void* SafeCalloc Returns the address.
109 unsigned int n The number of items to allocate.
111 unsigned int size The size of the memory to allocate.
113 char* file The file that the function is called from.
115 int line The line number that the function is called from.
116 ++++++++++++++++++++++++++++++++++++++*/
118 void* SafeCalloc(unsigned int n,unsigned int size,char* file,int line)
120 void* rptr=calloc(n,size);
122 #if DEBUG&4
123 printf("$$Calloc #%5d of %4d bytes at %08lx (%s:%3d)\n",malloc_count+1,size,(long)rptr,file,line);
124 #endif
125 #if DEBUG&2
126 if(malloc_count==(sizeof(addresses)/sizeof(addresses[0])))
127 {fprintf(stderr,"$$Too many Mallocs to log, edit memory.c\n");exit(3);}
128 addresses[malloc_count]=(void*)rptr;
129 files[malloc_count]=file;
130 lines[malloc_count]=line;
131 #endif
132 #if DEBUG
133 malloc_count++;
134 if(!rptr) printf("$$Warning Calloc() returning NULL (%s:%3d)\n",file,line);
135 #endif
136 #if !DEBUG
137 if(!rptr) printf("Warning Calloc() returning NULL (%s:%3d)\n",file,line);
138 #endif
140 return(rptr);
144 /*++++++++++++++++++++++++++++++++++++++
145 A replacement realloc() function.
147 void* SafeRealloc Returns the address.
149 void* ptr The old pointer.
151 unsigned int size The size of the new memory to allocate.
153 char* file The file that the function is called from.
155 int line The line number that the function is called from.
156 ++++++++++++++++++++++++++++++++++++++*/
158 void* SafeRealloc(void* ptr,unsigned int size,char* file,int line)
160 void* rptr=realloc(ptr,size);
162 #if DEBUG&4
163 printf("$$Realloc #%4d of %4d bytes at %08lx (old %08lx) (%s:%3d)\n",realloc_count+1,size,(long)rptr,(long)ptr,file,line);
164 #endif
165 #if DEBUG&2
167 int i;
168 for(i=0;i<malloc_count;i++)
169 if(addresses[i]==(void*)ptr)
170 {addresses[i]=rptr;break;}
171 if(i==malloc_count)
172 printf("$$Realloc() called for a non Malloced pointer %08lx (%s:%3d)\n",(long)ptr,file,line);
174 #endif
175 #if DEBUG
176 realloc_count++;
177 if(!rptr) printf("$$Warning Realloc() returning NULL (%s:%3d)\n",file,line);
178 #endif
179 #if !DEBUG
180 if(!rptr) printf("Warning Realloc() returning NULL (%s:%3d)\n",file,line);
181 #endif
183 return(rptr);
187 /*++++++++++++++++++++++++++++++++++++++
188 A replacement free() function.
190 void* ptr The pointer that is to be freed up.
192 char* file The file that the function is called from.
194 int line The line number that the function is called from.
195 ++++++++++++++++++++++++++++++++++++++*/
197 void SafeFree(void* ptr,char* file,int line)
199 #if DEBUG&4
200 printf("$$Free #%5d at %08lx (%s:%3d)\n",free_count+1,(long)ptr,file,line);
201 #endif
202 #if DEBUG&2
204 int i;
205 for(i=0;i<malloc_count;i++)
206 if(addresses[i]==(void*)ptr)
207 {addresses[i]=(void*)1;break;}
208 if(i==malloc_count)
209 printf("$$Free() called for a non Malloced pointer %08lx (%s:%3d)\n",(long)ptr,file,line);
211 #endif
212 #if DEBUG
213 free_count++;
214 if(!ptr) printf("$$Calling Free() on NULL (%s:%3d)\n",file,line);
215 else
216 #endif
217 #if !DEBUG
218 if(!ptr) printf("Calling Free() on NULL (%s:%3d)\n",file,line);
219 else
220 #endif
222 free(ptr);
226 /*++++++++++++++++++++++++++++++++++++++
227 A function to copy a string on the public global heap.
229 char* SafeMallocString Returns the copy of the string.
231 char* x The string to be copied.
233 char* file The file that the function is called from.
235 int line The line number that the function is called from.
236 ++++++++++++++++++++++++++++++++++++++*/
238 char* SafeMallocString(char* x,char* file,int line)
240 char* t=NULL;
242 if(x)
244 t=(char*)SafeMalloc(strlen(x)+1,file,line);
245 strcpy(t,x);
248 return(t);
252 /*++++++++++++++++++++++++++++++++++++++
253 A function to copy a string on the local private memory heap.
255 char* CopyString Returns the copy of the string.
257 char* x The string to be copied.
258 ++++++++++++++++++++++++++++++++++++++*/
260 char* CopyString(char* x)
262 char* t=NULL;
264 if(x)
266 t=get_space(strlen(x)+1);
267 strcpy(t,x);
270 return(t);
274 /*++++++++++++++++++++++++++++++++++++++
275 A function to concatenate a number of strings.
277 char* ConcatStrings Returns the a pointer to the new string.
279 int n The number of strings
281 char* s The first string.
283 ... The other strings, 'n' including 's'.
285 Any of the strings that are inputs can be NULL, in this case they are quietly ignored.
286 ++++++++++++++++++++++++++++++++++++++*/
288 char* ConcatStrings(int n,char* s, ...)
290 char* t=NULL,*str;
291 unsigned int l=0;
292 int i;
293 va_list ap;
295 #ifdef USE_STD_ARG
296 va_start(ap,s);
297 #else
298 va_start(ap);
299 #endif
301 for(i=0;i<n;i++)
303 if(i)
304 str=va_arg(ap, char *);
305 else
306 str=s;
308 if(str)
309 l+=strlen(str);
312 va_end(ap);
314 if(l)
316 t=get_space(l+1); t[0]=0;
318 #ifdef USE_STD_ARG
319 va_start(ap,s);
320 #else
321 va_start(ap);
322 #endif
324 for(i=0;i<n;i++)
326 if(i)
327 str=va_arg(ap, char *);
328 else
329 str=s;
331 if(str)
332 strcat(t,str);
335 va_end(ap);
338 return(t);
342 /*++++++++++++++++++++++++++++++++++++++
343 Prints out the number of mallocs / reallocs and frees.
344 ++++++++++++++++++++++++++++++++++++++*/
346 void PrintMemoryStatistics(void)
348 #if DEBUG
349 printf("\n"
350 "$$Memory usage : %5d Malloc()/Calloc() calls\n"
351 "$$ %5d Realloc() calls\n"
352 "$$ %5d Free() calls\n"
353 "$$ %5d Net calls (Malloc-Free)\n",
354 malloc_count,realloc_count,free_count,malloc_count-free_count);
355 #endif
357 #if DEBUG&2
359 int i;
360 for(i=0;i<malloc_count;i++)
361 if(addresses[i]!=(void*)1)
362 printf("$$Malloc #%5d at address %08lx is not freed (%s:%3d) = '%s'\n",i+1,(long)addresses[i],files[i],lines[i],(char*)addresses[i]);
364 #endif
368 /*++++++++++++++++++++++++++++++++++++++
369 Tidies up the local heap of memory.
370 ++++++++++++++++++++++++++++++++++++++*/
372 void TidyMemory(void)
374 if(first)
376 Heap h=first,n;
379 n=h->next;
380 Free(h->mem);
381 Free(h);
382 h=n;
384 while(h);
387 first=NULL;
388 heap_left=0;
391 /*+ The size of each of the heap allocations +*/
392 #define HEAP_INC 8192
394 /*+ The size of a string that is large enough to have it's own mallocation. +*/
395 #define SMALL_STRING 256
397 /*++++++++++++++++++++++++++++++++++++++
398 A function to get some memory for a string, allocate a new heap structure if needed.
400 char* get_space Returns a pointer to enough space.
402 unsigned int l The amount of space that is needed.
403 ++++++++++++++++++++++++++++++++++++++*/
405 static char* get_space(unsigned int l)
407 static Heap current=NULL;
408 char* r=NULL;
410 if(l <= SMALL_STRING)
412 if(heap_left < l)
414 current=add_to_heap(HEAP_INC);
415 heap_left=HEAP_INC;
418 heap_left-=l;
420 r=&current->mem[heap_left]; /* Work downwards */
422 else
424 Heap h=add_to_heap(l);
425 r=h->mem;
428 return(r);
432 /*++++++++++++++++++++++++++++++++++++++
433 Add some bytes to the privately maintained memory heap.
435 Heap add_to_heap Returns a pointer to the required memory.
437 unsigned int l The size of the memory that is required.
438 ++++++++++++++++++++++++++++++++++++++*/
440 static Heap add_to_heap(unsigned int l)
442 Heap* h=&first;
444 while(*h)
445 h=&(*h)->next;
447 *h=(Heap)Malloc(sizeof(struct _Heap));
448 (*h)->next=NULL;
449 (*h)->mem=(char*)Malloc(l);
451 return(*h);