upgraded to xpdf-3.01pl1
[swftools.git] / pdf2swf / xpdf / gmem.c
1 /*
2  * gmem.c
3  *
4  * Memory routines with out-of-memory checking.
5  *
6  * Copyright 1996-2003 Glyph & Cog, LLC
7  */
8
9 #include <aconf.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <stddef.h>
13 #include <string.h>
14 #include "gmem.h"
15
16 #ifdef DEBUG_MEM
17
18 typedef struct _GMemHdr {
19   int size;
20   int index;
21   struct _GMemHdr *next;
22 } GMemHdr;
23
24 #define gMemHdrSize ((sizeof(GMemHdr) + 7) & ~7)
25 #define gMemTrlSize (sizeof(long))
26
27 #if gmemTrlSize==8
28 #define gMemDeadVal 0xdeadbeefdeadbeefUL
29 #else
30 #define gMemDeadVal 0xdeadbeefUL
31 #endif
32
33 /* round data size so trailer will be aligned */
34 #define gMemDataSize(size) \
35   ((((size) + gMemTrlSize - 1) / gMemTrlSize) * gMemTrlSize)
36
37 #define gMemNLists    64
38 #define gMemListShift  4
39 #define gMemListMask  (gMemNLists - 1)
40 static GMemHdr *gMemList[gMemNLists] = {
41   NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
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 };
50
51 static int gMemIndex = 0;
52 static int gMemAlloc = 0;
53 static int gMemInUse = 0;
54
55 #endif /* DEBUG_MEM */
56
57 void *gmalloc(int size) {
58 #ifdef DEBUG_MEM
59   int size1;
60   char *mem;
61   GMemHdr *hdr;
62   void *data;
63   int lst;
64   unsigned long *trl, *p;
65
66   if (size == 0)
67     return NULL;
68   size1 = gMemDataSize(size);
69   if (!(mem = (char *)malloc(size1 + gMemHdrSize + gMemTrlSize))) {
70     fprintf(stderr, "Out of memory\n");
71     exit(1);
72   }
73   hdr = (GMemHdr *)mem;
74   data = (void *)(mem + gMemHdrSize);
75   trl = (unsigned long *)(mem + gMemHdrSize + size1);
76   hdr->size = size;
77   hdr->index = gMemIndex++;
78   lst = ((int)hdr >> gMemListShift) & gMemListMask;
79   hdr->next = gMemList[lst];
80   gMemList[lst] = hdr;
81   ++gMemAlloc;
82   gMemInUse += size;
83   for (p = (unsigned long *)data; p <= trl; ++p)
84     *p = gMemDeadVal;
85   return data;
86 #else
87   void *p;
88
89   if (size == 0)
90     return NULL;
91   if (!(p = malloc(size))) {
92     fprintf(stderr, "Out of memory\n");
93     exit(1);
94   }
95   return p;
96 #endif
97 }
98
99 void *grealloc(void *p, int size) {
100 #ifdef DEBUG_MEM
101   GMemHdr *hdr;
102   void *q;
103   int oldSize;
104
105   if (size == 0) {
106     if (p)
107       gfree(p);
108     return NULL;
109   }
110   if (p) {
111     hdr = (GMemHdr *)((char *)p - gMemHdrSize);
112     oldSize = hdr->size;
113     q = gmalloc(size);
114     memcpy(q, p, size < oldSize ? size : oldSize);
115     gfree(p);
116   } else {
117     q = gmalloc(size);
118   }
119   return q;
120 #else
121   void *q;
122
123   if (size == 0) {
124     if (p)
125       free(p);
126     return NULL;
127   }
128   if (p)
129     q = realloc(p, size);
130   else
131     q = malloc(size);
132   if (!q) {
133     fprintf(stderr, "Out of memory\n");
134     exit(1);
135   }
136   return q;
137 #endif
138 }
139
140 void *gmallocn(int nObjs, int objSize) {
141   int n;
142
143   n = nObjs * objSize;
144   if (objSize == 0 || n / objSize != nObjs) {
145     fprintf(stderr, "Bogus memory allocation size\n");
146     exit(1);
147   }
148   return gmalloc(n);
149 }
150
151 void *greallocn(void *p, int nObjs, int objSize) {
152   int n;
153
154   n = nObjs * objSize;
155   if (objSize == 0 || n / objSize != nObjs) {
156     fprintf(stderr, "Bogus memory allocation size\n");
157     exit(1);
158   }
159   return grealloc(p, n);
160 }
161
162 void gfree(void *p) {
163 #ifdef DEBUG_MEM
164   int size;
165   GMemHdr *hdr;
166   GMemHdr *prevHdr, *q;
167   int lst;
168   unsigned long *trl, *clr;
169
170   if (p) {
171     hdr = (GMemHdr *)((char *)p - gMemHdrSize);
172     lst = ((int)hdr >> gMemListShift) & gMemListMask;
173     for (prevHdr = NULL, q = gMemList[lst]; q; prevHdr = q, q = q->next) {
174       if (q == hdr)
175         break;
176     }
177     if (q) {
178       if (prevHdr)
179         prevHdr->next = hdr->next;
180       else
181         gMemList[lst] = hdr->next;
182       --gMemAlloc;
183       gMemInUse -= hdr->size;
184       size = gMemDataSize(hdr->size);
185       trl = (unsigned long *)((char *)hdr + gMemHdrSize + size);
186       if (*trl != gMemDeadVal) {
187         fprintf(stderr, "Overwrite past end of block %d at address %p\n",
188                 hdr->index, p);
189       }
190       for (clr = (unsigned long *)hdr; clr <= trl; ++clr)
191         *clr = gMemDeadVal;
192       free(hdr);
193     } else {
194       fprintf(stderr, "Attempted to free bad address %p\n", p);
195     }
196   }
197 #else
198   if (p)
199     free(p);
200 #endif
201 }
202
203 #ifdef DEBUG_MEM
204 void gMemReport(FILE *f) {
205   GMemHdr *p;
206   int lst;
207
208   fprintf(f, "%d memory allocations in all\n", gMemIndex);
209   if (gMemAlloc > 0) {
210     fprintf(f, "%d memory blocks left allocated:\n", gMemAlloc);
211     fprintf(f, " index     size\n");
212     fprintf(f, "-------- --------\n");
213     for (lst = 0; lst < gMemNLists; ++lst) {
214       for (p = gMemList[lst]; p; p = p->next)
215         fprintf(f, "%8d %8d\n", p->index, p->size);
216     }
217   } else {
218     fprintf(f, "No memory blocks left allocated\n");
219   }
220 }
221 #endif
222
223 char *copyString(char *s) {
224   char *s1;
225
226   s1 = (char *)gmalloc(strlen(s) + 1);
227   strcpy(s1, s);
228   return s1;
229 }