#include "io.h" #include #ifndef _MSC_VER #include #endif /* FIXME: make allocation dynamic */ #ifdef IMAGER_DEBUG_MALLOC #define MAXMAL 102400 #define MAXDESC 65 #define UNDRRNVAL 10 #define OVERRNVAL 10 #define PADBYTE 0xaa static int malloc_need_init = 1; typedef struct { void* ptr; size_t size; char comm[MAXDESC]; } malloc_entry; malloc_entry malloc_pointers[MAXMAL]; /* Utility functions */ static void malloc_init(void) { int i; for(i=0; i %d bytes allocated at %p for %s (%d)\n", i, size, buf, file, line)); return buf; } void* myrealloc_file_line(void *ptr, size_t newsize, char* file, int line) { char *buf; int i; if (malloc_need_init) malloc_init(); /* bndcheck_all(); ACTIVATE FOR LOTS OF THRASHING */ if (!ptr) { mm_log((1, "realloc called with ptr = NULL, sending request to malloc\n")); return mymalloc_file_line(newsize, file, line); } if (!newsize) { mm_log((1, "newsize = 0, sending request to free\n")); myfree_file_line(ptr, file, line); return NULL; } if ( (i = find_ptr(ptr)) == -1) { mm_log((0, "Unable to find %p in realloc for %s (%i)\n", ptr, file, line)); exit(3); } if ( (buf = realloc(((char *)ptr)-UNDRRNVAL, UNDRRNVAL+OVERRNVAL+newsize)) == NULL ) { mm_log((1,"Unable to reallocate %i bytes at %p for %s (%i)\n", newsize, ptr, file, line)); exit(3); } buf = set_entry(i, buf, newsize, file, line); mm_log((1,"realloc_file_line: slot <%d> %d bytes allocated at %p for %s (%d)\n", i, newsize, buf, file, line)); return buf; } static void bndcheck(int idx) { int i; size_t s = malloc_pointers[idx].size; unsigned char *pp = malloc_pointers[idx].ptr; if (!pp) { mm_log((1, "bndcheck: No pointer in slot %d\n", idx)); return; } for(i=0;i %p\n", size, buf)); return buf; } void myfree(void *p) { mm_log((1, "myfree(p %p)\n", p)); free(p); } void * myrealloc(void *block, size_t size) { void *result; mm_log((1, "myrealloc(block %p, size %u)\n", block, size)); if ((result = realloc(block, size)) == NULL) { mm_log((1, "myrealloc: out of memory\n")); fprintf(stderr, "Out of memory.\n"); exit(3); } return result; } #endif /* IMAGER_MALLOC_DEBUG */ /* memory pool implementation */ void i_mempool_init(i_mempool *mp) { mp->alloc = 10; mp->used = 0; mp->p = mymalloc(sizeof(void*)*mp->alloc); } void i_mempool_extend(i_mempool *mp) { mp->p = myrealloc(mp->p, mp->alloc * 2); mp->alloc *=2; } void * i_mempool_alloc(i_mempool *mp, size_t size) { if (mp->used == mp->alloc) i_mempool_extend(mp); mp->p[mp->used] = mymalloc(size); mp->used++; return mp->p[mp->used-1]; } void i_mempool_destroy(i_mempool *mp) { unsigned int i; for(i=0; iused; i++) myfree(mp->p[i]); myfree(mp->p); } /* Should these really be here? */ #undef min #undef max int i_min(int a,int b) { if (ab) return a; else return b; } struct utf8_size { int mask, expect; int size; }; struct utf8_size utf8_sizes[] = { { 0x80, 0x00, 1 }, { 0xE0, 0xC0, 2 }, { 0xF0, 0xE0, 3 }, { 0xF8, 0xF0, 4 }, }; /* =item utf8_advance(char **p, int *len) Retreive a UTF8 character from the stream. Modifies *p and *len to indicate the consumed characters. This doesn't support the extended UTF8 encoding used by later versions of Perl. =cut */ unsigned long i_utf8_advance(char const **p, int *len) { unsigned char c; int i, ci, clen = 0; unsigned char codes[3]; if (*len == 0) return ~0UL; c = *(*p)++; --*len; for (i = 0; i < sizeof(utf8_sizes)/sizeof(*utf8_sizes); ++i) { if ((c & utf8_sizes[i].mask) == utf8_sizes[i].expect) { clen = utf8_sizes[i].size; } } if (clen == 0 || *len < clen-1) { --*p; ++*len; return ~0UL; } /* check that each character is well formed */ i = 1; ci = 0; while (i < clen) { if (((*p)[ci] & 0xC0) != 0x80) { --*p; ++*len; return ~0UL; } codes[ci] = (*p)[ci]; ++ci; ++i; } *p += clen-1; *len -= clen-1; if (c & 0x80) { if ((c & 0xE0) == 0xC0) { return ((c & 0x1F) << 6) + (codes[0] & 0x3F); } else if ((c & 0xF0) == 0xE0) { return ((c & 0x0F) << 12) | ((codes[0] & 0x3F) << 6) | (codes[1] & 0x3f); } else if ((c & 0xF8) == 0xF0) { return ((c & 0x07) << 18) | ((codes[0] & 0x3F) << 12) | ((codes[1] & 0x3F) << 6) | (codes[2] & 0x3F); } else { *p -= clen; *len += clen; return ~0UL; } } else { return c; } }