9 /* FIXME: make allocation dynamic */
12 #ifdef IMAGER_DEBUG_MALLOC
23 static int malloc_need_init = 1;
31 malloc_entry malloc_pointers[MAXMAL];
36 /* Utility functions */
43 for(i=0; i<MAXMAL; i++) malloc_pointers[i].ptr = NULL;
54 if (malloc_pointers[i].ptr == p)
60 /* Takes a pointer to real start of array,
61 * sets the entries in the table, returns
62 * the offset corrected pointer */
66 set_entry(int i, char *buf, size_t size, char *file, int line) {
67 memset( buf, PADBYTE, UNDRRNVAL );
68 memset( &buf[UNDRRNVAL+size], PADBYTE, OVERRNVAL );
70 malloc_pointers[i].ptr = buf;
71 malloc_pointers[i].size = size;
72 sprintf(malloc_pointers[i].comm,"%s (%d)", file, line);
82 mm_log((0,"malloc_state()\n"));
84 for(i=0; i<MAXMAL; i++) if (malloc_pointers[i].ptr != NULL) {
85 mm_log((0,"%d: %lu (%p) : %s\n", i, (unsigned long)malloc_pointers[i].size, malloc_pointers[i].ptr, malloc_pointers[i].comm));
86 total += malloc_pointers[i].size;
88 if (total == 0) mm_log((0,"No memory currently used!\n"))
89 else mm_log((0,"total: %lu\n", (unsigned long)total));
95 mymalloc_file_line(size_t size, char* file, int line) {
98 if (malloc_need_init) malloc_init();
100 /* bndcheck_all(); Uncomment for LOTS OF THRASHING */
102 if ( (i = find_ptr(NULL)) < 0 ) {
103 mm_log((0,"more than %d segments allocated at %s (%d)\n", MAXMAL, file, line));
107 if ( (buf = malloc(size+UNDRRNVAL+OVERRNVAL)) == NULL ) {
108 mm_log((1,"Unable to allocate %ld for %s (%i)\n", (long)size, file, line));
112 buf = set_entry(i, buf, size, file, line);
113 mm_log((1,"mymalloc_file_line: slot <%d> %ld bytes allocated at %p for %s (%d)\n", i, (long)size, buf, file, line));
118 (mymalloc)(size_t size) {
119 return mymalloc_file_line(size, "unknown", 0);
123 myrealloc_file_line(void *ptr, size_t newsize, char* file, int line) {
127 if (malloc_need_init) malloc_init();
128 /* bndcheck_all(); ACTIVATE FOR LOTS OF THRASHING */
131 mm_log((1, "realloc called with ptr = NULL, sending request to malloc\n"));
132 return mymalloc_file_line(newsize, file, line);
136 mm_log((1, "newsize = 0, sending request to free\n"));
137 myfree_file_line(ptr, file, line);
141 if ( (i = find_ptr(ptr)) == -1) {
142 mm_log((0, "Unable to find %p in realloc for %s (%i)\n", ptr, file, line));
146 if ( (buf = realloc(((char *)ptr)-UNDRRNVAL, UNDRRNVAL+OVERRNVAL+newsize)) == NULL ) {
147 mm_log((1,"Unable to reallocate %ld bytes at %p for %s (%i)\n", (long)
148 newsize, ptr, file, line));
152 buf = set_entry(i, buf, newsize, file, line);
153 mm_log((1,"realloc_file_line: slot <%d> %ld bytes allocated at %p for %s (%d)\n", i, (long)newsize, buf, file, line));
158 (myrealloc)(void *ptr, size_t newsize) {
159 return myrealloc_file_line(ptr, newsize, "unknown", 0);
166 size_t s = malloc_pointers[idx].size;
167 unsigned char *pp = malloc_pointers[idx].ptr;
169 mm_log((1, "bndcheck: No pointer in slot %d\n", idx));
173 for(i=0;i<UNDRRNVAL;i++) {
174 if (pp[-(1+i)] != PADBYTE)
175 mm_log((1,"bndcheck: UNDERRUN OF %d bytes detected: slot = %d, point = %p, size = %ld\n", i+1, idx, pp, (long)s ));
178 for(i=0;i<OVERRNVAL;i++) {
179 if (pp[s+i] != PADBYTE)
180 mm_log((1,"bndcheck: OVERRUN OF %d bytes detected: slot = %d, point = %p, size = %ld\n", i+1, idx, pp, (long)s ));
187 mm_log((1, "bndcheck_all()\n"));
188 for(idx=0; idx<MAXMAL; idx++)
189 if (malloc_pointers[idx].ptr)
194 myfree_file_line(void *p, char *file, int line) {
202 for(i=0; i<MAXMAL; i++) if (malloc_pointers[i].ptr == p) {
203 mm_log((1,"myfree_file_line: pointer %i (%s) freed at %s (%i)\n", i, malloc_pointers[i].comm, file, line));
205 malloc_pointers[i].ptr = NULL;
209 mm_log((1, "myfree_file_line: freeing address %p (real %p)\n", pp, pp-UNDRRNVAL));
212 mm_log((1, "myfree_file_line: INCONSISTENT REFCOUNT %d at %s (%i)\n", match, file, line));
213 fprintf(stderr, "myfree_file_line: INCONSISTENT REFCOUNT %d at %s (%i)\n", match, file, line);
222 (myfree)(void *block) {
223 myfree_file_line(block, "unknown", 0);
233 mymalloc(size_t size) {
237 fprintf(stderr, "Attempt to allocate size %ld\n", (long)size);
241 if ( (buf = malloc(size)) == NULL ) {
242 mm_log((1, "mymalloc: unable to malloc %ld\n", (long)size));
243 fprintf(stderr,"Unable to malloc %ld.\n", (long)size); exit(3);
245 mm_log((1, "mymalloc(size %ld) -> %p\n", (long)size, buf));
250 mymalloc_file_line(size_t size, char *file, int line) {
251 return mymalloc(size);
256 mm_log((1, "myfree(p %p)\n", p));
261 myfree_file_line(void *p, char *file, int line) {
266 myrealloc(void *block, size_t size) {
269 mm_log((1, "myrealloc(block %p, size %ld)\n", block, (long)size));
270 if ((result = realloc(block, size)) == NULL) {
271 mm_log((1, "myrealloc: out of memory\n"));
272 fprintf(stderr, "Out of memory.\n");
279 myrealloc_file_line(void *block, size_t newsize, char *file, int size) {
280 return myrealloc(block, newsize);
283 #endif /* IMAGER_MALLOC_DEBUG */
288 /* memory pool implementation */
291 i_mempool_init(i_mempool *mp) {
294 mp->p = mymalloc(sizeof(void*)*mp->alloc);
298 i_mempool_extend(i_mempool *mp) {
299 mp->p = myrealloc(mp->p, mp->alloc * 2);
304 i_mempool_alloc(i_mempool *mp, size_t size) {
305 if (mp->used == mp->alloc) i_mempool_extend(mp);
306 mp->p[mp->used] = mymalloc(size);
308 return mp->p[mp->used-1];
313 i_mempool_destroy(i_mempool *mp) {
315 for(i=0; i<mp->used; i++) myfree(mp->p[i]);
321 /* Should these really be here? */
327 i_minx(i_img_dim a, i_img_dim b) {
328 if (a<b) return a; else return b;
332 i_maxx(i_img_dim a, i_img_dim b) {
333 if (a>b) return a; else return b;
342 struct utf8_size utf8_sizes[] =
351 =item i_utf8_advance(char **p, size_t *len)
353 Retrieve a C<UTF-8> character from the stream.
355 Modifies *p and *len to indicate the consumed characters.
357 This doesn't support the extended C<UTF-8> encoding used by later
358 versions of Perl. Since this is typically used to implement text
359 output by font drivers, the strings supplied shouldn't have such out
362 This doesn't check that the C<UTF-8> character is using the shortest
363 possible representation.
365 Returns ~0UL on failure.
371 i_utf8_advance(char const **p, size_t *len) {
374 unsigned char codes[3];
379 for (i = 0; i < sizeof(utf8_sizes)/sizeof(*utf8_sizes); ++i) {
380 if ((c & utf8_sizes[i].mask) == utf8_sizes[i].expect) {
381 clen = utf8_sizes[i].size;
385 if (clen == 0 || *len < clen-1) {
390 /* check that each character is well formed */
394 if (((*p)[ci] & 0xC0) != 0x80) {
398 codes[ci] = (*p)[ci];
401 *p += clen-1; *len -= clen-1;
403 if ((c & 0xE0) == 0xC0) {
404 return ((c & 0x1F) << 6) + (codes[0] & 0x3F);
406 else if ((c & 0xF0) == 0xE0) {
407 return ((c & 0x0F) << 12) | ((codes[0] & 0x3F) << 6) | (codes[1] & 0x3f);
409 else if ((c & 0xF8) == 0xF0) {
410 return ((c & 0x07) << 18) | ((codes[0] & 0x3F) << 12)
411 | ((codes[1] & 0x3F) << 6) | (codes[2] & 0x3F);
414 *p -= clen; *len += clen;