]> git.imager.perl.org - imager.git/blame - io.c
- added the det() function to the transform2() engine.
[imager.git] / io.c
CommitLineData
e310e5f9 1#include "imager.h"
02d1d628
AMH
2#include <stdlib.h>
3#ifndef _MSC_VER
4#include <unistd.h>
5#endif
6
7
8/* FIXME: make allocation dynamic */
9
10
11#ifdef IMAGER_DEBUG_MALLOC
12
2ff8ed30 13#define MAXMAL 102400
02d1d628
AMH
14#define MAXDESC 65
15
a743c0a6
AMH
16#define UNDRRNVAL 10
17#define OVERRNVAL 10
02d1d628
AMH
18
19#define PADBYTE 0xaa
20
21
22static int malloc_need_init = 1;
23
24typedef struct {
fe6163bf 25 void* ptr;
02d1d628 26 size_t size;
fe6163bf 27 char comm[MAXDESC];
02d1d628
AMH
28} malloc_entry;
29
30malloc_entry malloc_pointers[MAXMAL];
31
fe6163bf
AMH
32
33
34
35/* Utility functions */
36
37
38static
39void
aea697ad 40malloc_init(void) {
fe6163bf
AMH
41 int i;
42 for(i=0; i<MAXMAL; i++) malloc_pointers[i].ptr = NULL;
43 malloc_need_init = 0;
44 atexit(malloc_state);
45}
46
47
48static
49int
50find_ptr(void *p) {
51 int i;
52 for(i=0;i<MAXMAL;i++)
53 if (malloc_pointers[i].ptr == p)
54 return i;
55 return -1;
56}
57
58
59/* Takes a pointer to real start of array,
60 * sets the entries in the table, returns
61 * the offset corrected pointer */
62
63static
64void *
65set_entry(int i, char *buf, size_t size, char *file, int line) {
66 memset( buf, PADBYTE, UNDRRNVAL );
67 memset( &buf[UNDRRNVAL+size], PADBYTE, OVERRNVAL );
68 buf += UNDRRNVAL;
69 malloc_pointers[i].ptr = buf;
70 malloc_pointers[i].size = size;
71 sprintf(malloc_pointers[i].comm,"%s (%d)", file, line);
72 return buf;
73}
74
02d1d628 75void
aea697ad 76malloc_state(void) {
fe6163bf
AMH
77 int i, total = 0;
78
cd4b0b20 79 i_clear_error();
02d1d628
AMH
80 mm_log((0,"malloc_state()\n"));
81 bndcheck_all();
fe6163bf
AMH
82 for(i=0; i<MAXMAL; i++) if (malloc_pointers[i].ptr != NULL) {
83 mm_log((0,"%d: %d (0x%x) : %s\n", i, malloc_pointers[i].size, malloc_pointers[i].ptr, malloc_pointers[i].comm));
84 total += malloc_pointers[i].size;
02d1d628 85 }
fe6163bf
AMH
86 if (total == 0) mm_log((0,"No memory currently used!\n"))
87 else mm_log((0,"total: %d\n",total));
02d1d628
AMH
88}
89
90
fe6163bf 91
02d1d628 92void*
fe6163bf 93mymalloc_file_line(size_t size, char* file, int line) {
02d1d628
AMH
94 char *buf;
95 int i;
fe6163bf
AMH
96 if (malloc_need_init) malloc_init();
97
98 /* bndcheck_all(); Uncomment for LOTS OF THRASHING */
99
100 if ( (i = find_ptr(NULL)) < 0 ) {
101 mm_log((0,"more than %d segments allocated at %s (%d)\n", MAXMAL, file, line));
102 exit(3);
02d1d628
AMH
103 }
104
fe6163bf
AMH
105 if ( (buf = malloc(size+UNDRRNVAL+OVERRNVAL)) == NULL ) {
106 mm_log((1,"Unable to allocate %i for %s (%i)\n", size, file, line));
107 exit(3);
02d1d628
AMH
108 }
109
fe6163bf
AMH
110 buf = set_entry(i, buf, size, file, line);
111 mm_log((1,"mymalloc_file_line: slot <%d> %d bytes allocated at %p for %s (%d)\n", i, size, buf, file, line));
112 return buf;
02d1d628
AMH
113}
114
e310e5f9
TC
115void *
116(mymalloc)(int size) {
117 return mymalloc_file_line(size, "unknown", 0);
118}
119
02d1d628 120void*
fe6163bf
AMH
121myrealloc_file_line(void *ptr, size_t newsize, char* file, int line) {
122 char *buf;
02d1d628 123 int i;
fe6163bf
AMH
124
125 if (malloc_need_init) malloc_init();
126 /* bndcheck_all(); ACTIVATE FOR LOTS OF THRASHING */
127
128 if (!ptr) {
129 mm_log((1, "realloc called with ptr = NULL, sending request to malloc\n"));
130 return mymalloc_file_line(newsize, file, line);
02d1d628
AMH
131 }
132
fe6163bf
AMH
133 if (!newsize) {
134 mm_log((1, "newsize = 0, sending request to free\n"));
135 myfree_file_line(ptr, file, line);
136 return NULL;
137 }
02d1d628 138
fe6163bf
AMH
139 if ( (i = find_ptr(ptr)) == -1) {
140 mm_log((0, "Unable to find %p in realloc for %s (%i)\n", ptr, file, line));
141 exit(3);
142 }
143
aea697ad 144 if ( (buf = realloc(((char *)ptr)-UNDRRNVAL, UNDRRNVAL+OVERRNVAL+newsize)) == NULL ) {
fe6163bf
AMH
145 mm_log((1,"Unable to reallocate %i bytes at %p for %s (%i)\n", newsize, ptr, file, line));
146 exit(3);
02d1d628 147 }
fe6163bf
AMH
148
149 buf = set_entry(i, buf, newsize, file, line);
150 mm_log((1,"realloc_file_line: slot <%d> %d bytes allocated at %p for %s (%d)\n", i, newsize, buf, file, line));
151 return buf;
02d1d628 152}
fe6163bf 153
e310e5f9
TC
154void *
155(myrealloc)(void *ptr, size_t newsize) {
156 return myrealloc_file_line(ptr, newsize, "unknown", 0);
157}
158
02d1d628
AMH
159static
160void
161bndcheck(int idx) {
162 int i;
163 size_t s = malloc_pointers[idx].size;
fe6163bf 164 unsigned char *pp = malloc_pointers[idx].ptr;
02d1d628
AMH
165 if (!pp) {
166 mm_log((1, "bndcheck: No pointer in slot %d\n", idx));
167 return;
168 }
169
170 for(i=0;i<UNDRRNVAL;i++)
fe6163bf
AMH
171 if (pp[-(1+i)] != PADBYTE)
172 mm_log((1,"bndcheck: UNDERRUN OF %d bytes detected: slot = %d, point = %p, size = %d\n", i+1, idx, pp, s ));
02d1d628 173
fe6163bf 174 for(i=0;i<OVERRNVAL;i++)
02d1d628
AMH
175 if (pp[s+i] != PADBYTE)
176 mm_log((1,"bndcheck: OVERRUN OF %d bytes detected: slot = %d, point = %p, size = %d\n", i+1, idx, pp, s ));
177}
178
179void
180bndcheck_all() {
181 int idx;
182 mm_log((1, "bndcheck_all()\n"));
76ff75b8 183 for(idx=0; idx<MAXMAL; idx++)
fe6163bf 184 if (malloc_pointers[idx].ptr)
02d1d628
AMH
185 bndcheck(idx);
186}
187
02d1d628
AMH
188void
189myfree_file_line(void *p, char *file, int line) {
190 char *pp = p;
191 int match = 0;
192 int i;
193
fe6163bf 194 for(i=0; i<MAXMAL; i++) if (malloc_pointers[i].ptr == p) {
02d1d628
AMH
195 mm_log((1,"myfree_file_line: pointer %i (%s) freed at %s (%i)\n", i, malloc_pointers[i].comm, file, line));
196 bndcheck(i);
fe6163bf 197 malloc_pointers[i].ptr = NULL;
02d1d628
AMH
198 match++;
199 }
97c4effc
TC
200
201 mm_log((1, "myfree_file_line: freeing address %p (real %p)\n", pp, pp-UNDRRNVAL));
02d1d628
AMH
202
203 if (match != 1) {
f1ac5027 204 mm_log((1, "myfree_file_line: INCONSISTENT REFCOUNT %d at %s (%i)\n", match, file, line));
aea697ad 205 fprintf(stderr, "myfree_file_line: INCONSISTENT REFCOUNT %d at %s (%i)\n", match, file, line);
a73aeb5f 206 exit(255);
02d1d628
AMH
207 }
208
02d1d628
AMH
209
210 free(pp-UNDRRNVAL);
211}
212
e310e5f9
TC
213void
214(myfree)(void *block) {
215 myfree_file_line(block, "unknown", 0);
216}
217
02d1d628
AMH
218#else
219
220#define malloc_comm(a,b) (mymalloc(a))
221
222void
223malloc_state() {
02d1d628
AMH
224}
225
226void*
227mymalloc(int size) {
228 void *buf;
229
a659442a
TC
230 if (size < 0) {
231 fprintf(stderr, "Attempt to allocate size %d\n", size);
232 exit(3);
233 }
234
a743c0a6 235 if ( (buf = malloc(size)) == NULL ) {
faa9b3e7 236 mm_log((1, "mymalloc: unable to malloc %d\n", size));
cc6483e0 237 fprintf(stderr,"Unable to malloc %d.\n", size); exit(3);
02d1d628 238 }
f1ac5027 239 mm_log((1, "mymalloc(size %d) -> %p\n", size, buf));
02d1d628
AMH
240 return buf;
241}
242
e310e5f9
TC
243void *
244mymalloc_file_line(size_t size, char *file, int line) {
245 return mymalloc(size);
246}
247
02d1d628
AMH
248void
249myfree(void *p) {
dd55acc8 250 mm_log((1, "myfree(p %p)\n", p));
02d1d628
AMH
251 free(p);
252}
253
e310e5f9
TC
254void
255myfree_file_line(void *p, char *file, int line) {
256 myfree(p);
257}
258
faa9b3e7
TC
259void *
260myrealloc(void *block, size_t size) {
261 void *result;
262
263 mm_log((1, "myrealloc(block %p, size %u)\n", block, size));
264 if ((result = realloc(block, size)) == NULL) {
265 mm_log((1, "myrealloc: out of memory\n"));
266 fprintf(stderr, "Out of memory.\n");
267 exit(3);
268 }
269 return result;
270}
271
e310e5f9
TC
272void *
273myrealloc_file_line(void *block, size_t newsize, char *file, int size) {
274 return myrealloc(block, newsize);
275}
276
02d1d628
AMH
277#endif /* IMAGER_MALLOC_DEBUG */
278
279
280
281
8047cbb5
AMH
282/* memory pool implementation */
283
284void
285i_mempool_init(i_mempool *mp) {
286 mp->alloc = 10;
287 mp->used = 0;
288 mp->p = mymalloc(sizeof(void*)*mp->alloc);
289}
290
291void
292i_mempool_extend(i_mempool *mp) {
293 mp->p = myrealloc(mp->p, mp->alloc * 2);
294 mp->alloc *=2;
295}
296
297void *
298i_mempool_alloc(i_mempool *mp, size_t size) {
299 if (mp->used == mp->alloc) i_mempool_extend(mp);
300 mp->p[mp->used] = mymalloc(size);
301 mp->used++;
302 return mp->p[mp->used-1];
303}
304
305
306void
307i_mempool_destroy(i_mempool *mp) {
308 unsigned int i;
309 for(i=0; i<mp->used; i++) myfree(mp->p[i]);
310 myfree(mp->p);
311}
312
02d1d628
AMH
313
314
5473b91d 315/* Should these really be here? */
02d1d628
AMH
316
317#undef min
318#undef max
319
320int
b33c08f8 321i_min(int a,int b) {
02d1d628
AMH
322 if (a<b) return a; else return b;
323}
324
325int
b33c08f8 326i_max(int a,int b) {
02d1d628
AMH
327 if (a>b) return a; else return b;
328}
329
4f68b48f
TC
330
331struct utf8_size {
332 int mask, expect;
333 int size;
334};
335
336struct utf8_size utf8_sizes[] =
337{
338 { 0x80, 0x00, 1 },
339 { 0xE0, 0xC0, 2 },
340 { 0xF0, 0xE0, 3 },
341 { 0xF8, 0xF0, 4 },
342};
343
344/*
345=item utf8_advance(char **p, int *len)
346
347Retreive a UTF8 character from the stream.
348
349Modifies *p and *len to indicate the consumed characters.
350
351This doesn't support the extended UTF8 encoding used by later versions
352of Perl.
353
855fe4d7
TC
354This doesn't check that the UTF8 charecter is using the shortest
355possible representation.
356
4f68b48f
TC
357=cut
358*/
359
855fe4d7
TC
360unsigned long
361i_utf8_advance(char const **p, int *len) {
4f68b48f
TC
362 unsigned char c;
363 int i, ci, clen = 0;
364 unsigned char codes[3];
365 if (*len == 0)
366 return ~0UL;
367 c = *(*p)++; --*len;
368
369 for (i = 0; i < sizeof(utf8_sizes)/sizeof(*utf8_sizes); ++i) {
370 if ((c & utf8_sizes[i].mask) == utf8_sizes[i].expect) {
371 clen = utf8_sizes[i].size;
855fe4d7 372 break;
4f68b48f
TC
373 }
374 }
375 if (clen == 0 || *len < clen-1) {
376 --*p; ++*len;
377 return ~0UL;
378 }
379
380 /* check that each character is well formed */
381 i = 1;
382 ci = 0;
383 while (i < clen) {
384 if (((*p)[ci] & 0xC0) != 0x80) {
385 --*p; ++*len;
386 return ~0UL;
387 }
388 codes[ci] = (*p)[ci];
389 ++ci; ++i;
390 }
391 *p += clen-1; *len -= clen-1;
392 if (c & 0x80) {
393 if ((c & 0xE0) == 0xC0) {
394 return ((c & 0x1F) << 6) + (codes[0] & 0x3F);
395 }
396 else if ((c & 0xF0) == 0xE0) {
397 return ((c & 0x0F) << 12) | ((codes[0] & 0x3F) << 6) | (codes[1] & 0x3f);
398 }
399 else if ((c & 0xF8) == 0xF0) {
400 return ((c & 0x07) << 18) | ((codes[0] & 0x3F) << 12)
401 | ((codes[1] & 0x3F) << 6) | (codes[2] & 0x3F);
402 }
403 else {
404 *p -= clen; *len += clen;
405 return ~0UL;
406 }
407 }
408 else {
409 return c;
410 }
411}
412