9 /* FIXME: make allocation dynamic */
12 #ifdef IMAGER_DEBUG_MALLOC
23 static int malloc_need_init = 1;
32 malloc_entry malloc_pointers[MAXMAL];
37 /* Utility functions */
44 for(i=0; i<MAXMAL; i++) malloc_pointers[i].ptr = NULL;
55 if (malloc_pointers[i].ptr == p)
61 /* Takes a pointer to real start of array,
62 * sets the entries in the table, returns
63 * the offset corrected pointer */
67 set_entry(int i, char *buf, size_t size, char *file, int line) {
68 memset( buf, PADBYTE, UNDRRNVAL );
69 memset( &buf[UNDRRNVAL+size], PADBYTE, OVERRNVAL );
71 malloc_pointers[i].ptr = buf;
72 malloc_pointers[i].size = size;
73 malloc_pointers[i].file = file;
74 malloc_pointers[i].line = line;
84 mm_log((0,"malloc_state()\n"));
86 for(i=0; i<MAXMAL; i++) if (malloc_pointers[i].ptr != NULL) {
87 mm_log((0,"%d: %lu (%p) : %s (%d)\n", i, (unsigned long)malloc_pointers[i].size, malloc_pointers[i].ptr, malloc_pointers[i].file, malloc_pointers[i].line));
88 total += malloc_pointers[i].size;
90 if (total == 0) mm_log((0,"No memory currently used!\n"))
91 else mm_log((0,"total: %lu\n", (unsigned long)total));
97 mymalloc_file_line(size_t size, char* file, int line) {
100 if (malloc_need_init) malloc_init();
102 /* bndcheck_all(); Uncomment for LOTS OF THRASHING */
104 if ( (i = find_ptr(NULL)) < 0 ) {
105 mm_log((0,"more than %d segments allocated at %s (%d)\n", MAXMAL, file, line));
109 if ( (buf = malloc(size+UNDRRNVAL+OVERRNVAL)) == NULL ) {
110 mm_log((1,"Unable to allocate %ld for %s (%i)\n", (long)size, file, line));
114 buf = set_entry(i, buf, size, file, line);
115 mm_log((1,"mymalloc_file_line: slot <%d> %ld bytes allocated at %p for %s (%d)\n", i, (long)size, buf, file, line));
120 (mymalloc)(size_t size) {
121 return mymalloc_file_line(size, "unknown", 0);
125 myrealloc_file_line(void *ptr, size_t newsize, char* file, int line) {
129 if (malloc_need_init) malloc_init();
130 /* bndcheck_all(); ACTIVATE FOR LOTS OF THRASHING */
133 mm_log((1, "realloc called with ptr = NULL, sending request to malloc\n"));
134 return mymalloc_file_line(newsize, file, line);
138 mm_log((1, "newsize = 0, sending request to free\n"));
139 myfree_file_line(ptr, file, line);
143 if ( (i = find_ptr(ptr)) == -1) {
144 mm_log((0, "Unable to find %p in realloc for %s (%i)\n", ptr, file, line));
148 if ( (buf = realloc(((char *)ptr)-UNDRRNVAL, UNDRRNVAL+OVERRNVAL+newsize)) == NULL ) {
149 mm_log((1,"Unable to reallocate %ld bytes at %p for %s (%i)\n", (long)
150 newsize, ptr, file, line));
154 buf = set_entry(i, buf, newsize, file, line);
155 mm_log((1,"realloc_file_line: slot <%d> %ld bytes allocated at %p for %s (%d)\n", i, (long)newsize, buf, file, line));
160 (myrealloc)(void *ptr, size_t newsize) {
161 return myrealloc_file_line(ptr, newsize, "unknown", 0);
168 size_t s = malloc_pointers[idx].size;
169 unsigned char *pp = malloc_pointers[idx].ptr;
171 mm_log((1, "bndcheck: No pointer in slot %d\n", idx));
175 for(i=0;i<UNDRRNVAL;i++) {
176 if (pp[-(1+i)] != PADBYTE)
177 mm_log((1,"bndcheck: UNDERRUN OF %d bytes detected: slot = %d, point = %p, size = %ld\n", i+1, idx, pp, (long)s ));
180 for(i=0;i<OVERRNVAL;i++) {
181 if (pp[s+i] != PADBYTE)
182 mm_log((1,"bndcheck: OVERRUN OF %d bytes detected: slot = %d, point = %p, size = %ld\n", i+1, idx, pp, (long)s ));
189 mm_log((1, "bndcheck_all()\n"));
190 for(idx=0; idx<MAXMAL; idx++)
191 if (malloc_pointers[idx].ptr)
196 myfree_file_line(void *p, char *file, int line) {
204 for(i=0; i<MAXMAL; i++) if (malloc_pointers[i].ptr == p) {
205 mm_log((1,"myfree_file_line: pointer %i (%s (%d)) freed at %s (%i)\n", i, malloc_pointers[i].file, malloc_pointers[i].line, file, line));
207 malloc_pointers[i].ptr = NULL;
211 mm_log((1, "myfree_file_line: freeing address %p (real %p)\n", pp, pp-UNDRRNVAL));
214 mm_log((1, "myfree_file_line: INCONSISTENT REFCOUNT %d at %s (%i)\n", match, file, line));
215 fprintf(stderr, "myfree_file_line: INCONSISTENT REFCOUNT %d at %s (%i)\n", match, file, line);
224 (myfree)(void *block) {
225 myfree_file_line(block, "unknown", 0);
235 mymalloc(size_t size) {
239 fprintf(stderr, "Attempt to allocate size %ld\n", (long)size);
243 if ( (buf = malloc(size)) == NULL ) {
244 mm_log((1, "mymalloc: unable to malloc %ld\n", (long)size));
245 fprintf(stderr,"Unable to malloc %ld.\n", (long)size); exit(3);
247 mm_log((1, "mymalloc(size %ld) -> %p\n", (long)size, buf));
252 mymalloc_file_line(size_t size, char *file, int line) {
253 return mymalloc(size);
258 mm_log((1, "myfree(p %p)\n", p));
263 myfree_file_line(void *p, char *file, int line) {
268 myrealloc(void *block, size_t size) {
271 mm_log((1, "myrealloc(block %p, size %ld)\n", block, (long)size));
272 if ((result = realloc(block, size)) == NULL) {
273 mm_log((1, "myrealloc: out of memory\n"));
274 fprintf(stderr, "Out of memory.\n");
281 myrealloc_file_line(void *block, size_t newsize, char *file, int size) {
282 return myrealloc(block, newsize);
285 #endif /* IMAGER_MALLOC_DEBUG */
290 /* memory pool implementation */
293 i_mempool_init(i_mempool *mp) {
296 mp->p = mymalloc(sizeof(void*)*mp->alloc);
300 i_mempool_extend(i_mempool *mp) {
301 mp->p = myrealloc(mp->p, mp->alloc * 2);
306 i_mempool_alloc(i_mempool *mp, size_t size) {
307 if (mp->used == mp->alloc) i_mempool_extend(mp);
308 mp->p[mp->used] = mymalloc(size);
310 return mp->p[mp->used-1];
315 i_mempool_destroy(i_mempool *mp) {
317 for(i=0; i<mp->used; i++) myfree(mp->p[i]);
323 /* Should these really be here? */
329 i_minx(i_img_dim a, i_img_dim b) {
330 if (a<b) return a; else return b;
334 i_maxx(i_img_dim a, i_img_dim b) {
335 if (a>b) return a; else return b;
344 struct utf8_size utf8_sizes[] =
353 =item i_utf8_advance(char **p, size_t *len)
355 Retrieve a C<UTF-8> character from the stream.
357 Modifies *p and *len to indicate the consumed characters.
359 This doesn't support the extended C<UTF-8> encoding used by later
360 versions of Perl. Since this is typically used to implement text
361 output by font drivers, the strings supplied shouldn't have such out
364 This doesn't check that the C<UTF-8> character is using the shortest
365 possible representation.
367 Returns ~0UL on failure.
373 i_utf8_advance(char const **p, size_t *len) {
376 unsigned char codes[3];
381 for (i = 0; i < sizeof(utf8_sizes)/sizeof(*utf8_sizes); ++i) {
382 if ((c & utf8_sizes[i].mask) == utf8_sizes[i].expect) {
383 clen = utf8_sizes[i].size;
387 if (clen == 0 || *len < clen-1) {
392 /* check that each character is well formed */
396 if (((*p)[ci] & 0xC0) != 0x80) {
400 codes[ci] = (*p)[ci];
403 *p += clen-1; *len -= clen-1;
405 if ((c & 0xE0) == 0xC0) {
406 return ((c & 0x1F) << 6) + (codes[0] & 0x3F);
408 else if ((c & 0xF0) == 0xE0) {
409 return ((c & 0x0F) << 12) | ((codes[0] & 0x3F) << 6) | (codes[1] & 0x3f);
411 else if ((c & 0xF8) == 0xF0) {
412 return ((c & 0x07) << 18) | ((codes[0] & 0x3F) << 12)
413 | ((codes[1] & 0x3F) << 6) | (codes[2] & 0x3F);
416 *p -= clen; *len += clen;