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) {
238 if ( (buf = malloc(size)) == NULL ) {
239 mm_log((1, "mymalloc: unable to malloc %ld\n", (long)size));
240 fprintf(stderr,"Unable to malloc %ld.\n", (long)size); exit(3);
242 mm_log((1, "mymalloc(size %ld) -> %p\n", (long)size, buf));
247 mymalloc_file_line(size_t size, char *file, int line) {
248 return mymalloc(size);
253 mm_log((1, "myfree(p %p)\n", p));
258 myfree_file_line(void *p, char *file, int line) {
263 myrealloc(void *block, size_t size) {
266 mm_log((1, "myrealloc(block %p, size %ld)\n", block, (long)size));
267 if ((result = realloc(block, size)) == NULL) {
268 mm_log((1, "myrealloc: out of memory\n"));
269 fprintf(stderr, "Out of memory.\n");
276 myrealloc_file_line(void *block, size_t newsize, char *file, int size) {
277 return myrealloc(block, newsize);
280 #endif /* IMAGER_MALLOC_DEBUG */
285 /* memory pool implementation */
288 i_mempool_init(i_mempool *mp) {
291 mp->p = mymalloc(sizeof(void*)*mp->alloc);
295 i_mempool_extend(i_mempool *mp) {
296 mp->p = myrealloc(mp->p, mp->alloc * 2);
301 i_mempool_alloc(i_mempool *mp, size_t size) {
302 if (mp->used == mp->alloc) i_mempool_extend(mp);
303 mp->p[mp->used] = mymalloc(size);
305 return mp->p[mp->used-1];
310 i_mempool_destroy(i_mempool *mp) {
312 for(i=0; i<mp->used; i++) myfree(mp->p[i]);
318 /* Should these really be here? */
324 i_minx(i_img_dim a, i_img_dim b) {
325 if (a<b) return a; else return b;
329 i_maxx(i_img_dim a, i_img_dim b) {
330 if (a>b) return a; else return b;
339 struct utf8_size utf8_sizes[] =
348 =item i_utf8_advance(char **p, size_t *len)
350 Retrieve a C<UTF-8> character from the stream.
352 Modifies *p and *len to indicate the consumed characters.
354 This doesn't support the extended C<UTF-8> encoding used by later
355 versions of Perl. Since this is typically used to implement text
356 output by font drivers, the strings supplied shouldn't have such out
359 This doesn't check that the C<UTF-8> character is using the shortest
360 possible representation.
362 Returns ~0UL on failure.
368 i_utf8_advance(char const **p, size_t *len) {
371 unsigned char codes[3];
376 for (i = 0; i < sizeof(utf8_sizes)/sizeof(*utf8_sizes); ++i) {
377 if ((c & utf8_sizes[i].mask) == utf8_sizes[i].expect) {
378 clen = utf8_sizes[i].size;
382 if (clen == 0 || *len < clen-1) {
387 /* check that each character is well formed */
391 if (((*p)[ci] & 0xC0) != 0x80) {
395 codes[ci] = (*p)[ci];
398 *p += clen-1; *len -= clen-1;
400 if ((c & 0xE0) == 0xC0) {
401 return ((c & 0x1F) << 6) + (codes[0] & 0x3F);
403 else if ((c & 0xF0) == 0xE0) {
404 return ((c & 0x0F) << 12) | ((codes[0] & 0x3F) << 6) | (codes[1] & 0x3f);
406 else if ((c & 0xF8) == 0xF0) {
407 return ((c & 0x07) << 18) | ((codes[0] & 0x3F) << 12)
408 | ((codes[1] & 0x3F) << 6) | (codes[2] & 0x3F);
411 *p -= clen; *len += clen;