Bringing apdf from vendor into main branch.
[AROS-Contrib.git] / apdf / goo / gmem.c
blobb97535adf041df019d5e613f72a57db909185fa7
1 /*
2 * gmem.c
4 * Memory routines with out-of-memory checking.
6 * Copyright 1996-2003 Glyph & Cog, LLC
7 */
9 #include <aconf.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <stddef.h>
13 #include <string.h>
14 #include <limits.h>
15 #include "gmem.h"
17 #ifdef DEBUG_MEM
19 typedef struct _GMemHdr {
20 int size;
21 int index;
22 struct _GMemHdr *next;
23 } GMemHdr;
25 #define gMemHdrSize ((sizeof(GMemHdr) + 7) & ~7)
26 #define gMemTrlSize (sizeof(long))
28 #if gmemTrlSize==8
29 #define gMemDeadVal 0xdeadbeefdeadbeefUL
30 #else
31 #define gMemDeadVal 0xdeadbeefUL
32 #endif
34 /* round data size so trailer will be aligned */
35 #define gMemDataSize(size) \
36 ((((size) + gMemTrlSize - 1) / gMemTrlSize) * gMemTrlSize)
38 #define gMemNLists 64
39 #define gMemListShift 4
40 #define gMemListMask (gMemNLists - 1)
41 static GMemHdr *gMemList[gMemNLists] = {
42 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
43 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
44 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
45 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
46 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
47 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
48 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
49 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
52 static int gMemIndex = 0;
53 static int gMemAlloc = 0;
54 static int gMemInUse = 0;
56 #endif /* DEBUG_MEM */
58 void *gmalloc(int size) {
59 #ifdef DEBUG_MEM
60 int size1;
61 char *mem;
62 GMemHdr *hdr;
63 void *data;
64 int lst;
65 unsigned long *trl, *p;
67 if (size <= 0)
68 return NULL;
69 size1 = gMemDataSize(size);
70 if (!(mem = (char *)malloc(size1 + gMemHdrSize + gMemTrlSize))) {
71 fprintf(stderr, "Out of memory\n");
72 exit(1);
74 hdr = (GMemHdr *)mem;
75 data = (void *)(mem + gMemHdrSize);
76 trl = (unsigned long *)(mem + gMemHdrSize + size1);
77 hdr->size = size;
78 hdr->index = gMemIndex++;
79 lst = ((int)hdr >> gMemListShift) & gMemListMask;
80 hdr->next = gMemList[lst];
81 gMemList[lst] = hdr;
82 ++gMemAlloc;
83 gMemInUse += size;
84 for (p = (unsigned long *)data; p <= trl; ++p)
85 *p = gMemDeadVal;
86 return data;
87 #else
88 void *p;
90 if (size <= 0)
91 return NULL;
92 if (!(p = malloc(size))) {
93 fprintf(stderr, "Out of memory\n");
94 exit(1);
96 return p;
97 #endif
100 void *grealloc(void *p, int size) {
101 #ifdef DEBUG_MEM
102 GMemHdr *hdr;
103 void *q;
104 int oldSize;
106 if (size <= 0) {
107 if (p)
108 gfree(p);
109 return NULL;
111 if (p) {
112 hdr = (GMemHdr *)((char *)p - gMemHdrSize);
113 oldSize = hdr->size;
114 q = gmalloc(size);
115 memcpy(q, p, size < oldSize ? size : oldSize);
116 gfree(p);
117 } else {
118 q = gmalloc(size);
120 return q;
121 #else
122 void *q;
124 if (size <= 0) {
125 if (p)
126 free(p);
127 return NULL;
129 if (p)
130 q = realloc(p, size);
131 else
132 q = malloc(size);
133 if (!q) {
134 fprintf(stderr, "Out of memory\n");
135 exit(1);
137 return q;
138 #endif
141 void *gmallocn(int nObjs, int objSize) {
142 int n;
144 if (nObjs == 0) {
145 return NULL;
147 n = nObjs * objSize;
148 if (objSize <= 0 || nObjs < 0 || nObjs >= INT_MAX / objSize) {
149 fprintf(stderr, "Bogus memory allocation size\n");
150 exit(1);
152 return gmalloc(n);
155 void *greallocn(void *p, int nObjs, int objSize) {
156 int n;
158 if (nObjs == 0) {
159 if (p) {
160 gfree(p);
162 return NULL;
164 n = nObjs * objSize;
165 if (objSize <= 0 || nObjs < 0 || nObjs >= INT_MAX / objSize) {
166 fprintf(stderr, "Bogus memory allocation size\n");
167 exit(1);
169 return grealloc(p, n);
172 void gfree(void *p) {
173 #ifdef DEBUG_MEM
174 int size;
175 GMemHdr *hdr;
176 GMemHdr *prevHdr, *q;
177 int lst;
178 unsigned long *trl, *clr;
180 if (p) {
181 hdr = (GMemHdr *)((char *)p - gMemHdrSize);
182 lst = ((int)hdr >> gMemListShift) & gMemListMask;
183 for (prevHdr = NULL, q = gMemList[lst]; q; prevHdr = q, q = q->next) {
184 if (q == hdr)
185 break;
187 if (q) {
188 if (prevHdr)
189 prevHdr->next = hdr->next;
190 else
191 gMemList[lst] = hdr->next;
192 --gMemAlloc;
193 gMemInUse -= hdr->size;
194 size = gMemDataSize(hdr->size);
195 trl = (unsigned long *)((char *)hdr + gMemHdrSize + size);
196 if (*trl != gMemDeadVal) {
197 fprintf(stderr, "Overwrite past end of block %d at address %p\n",
198 hdr->index, p);
200 for (clr = (unsigned long *)hdr; clr <= trl; ++clr)
201 *clr = gMemDeadVal;
202 free(hdr);
203 } else {
204 fprintf(stderr, "Attempted to free bad address %p\n", p);
207 #else
208 if (p)
209 free(p);
210 #endif
213 #ifdef DEBUG_MEM
214 void gMemReport(FILE *f) {
215 GMemHdr *p;
216 int lst;
218 fprintf(f, "%d memory allocations in all\n", gMemIndex);
219 if (gMemAlloc > 0) {
220 fprintf(f, "%d memory blocks left allocated:\n", gMemAlloc);
221 fprintf(f, " index size\n");
222 fprintf(f, "-------- --------\n");
223 for (lst = 0; lst < gMemNLists; ++lst) {
224 for (p = gMemList[lst]; p; p = p->next)
225 fprintf(f, "%8d %8d\n", p->index, p->size);
227 } else {
228 fprintf(f, "No memory blocks left allocated\n");
231 #endif
233 char *copyString(char *s) {
234 char *s1;
236 s1 = (char *)gmalloc(strlen(s) + 1);
237 strcpy(s1, s);
238 return s1;