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 #ifdef IMAGER_SNPRINTF
73 snprintf(malloc_pointers[i].comm, sizeof(malloc_pointers[i].comm),
74 "%s (%d)", file, line);
76 sprintf(malloc_pointers[i].comm,"%s (%d)", file, line);
87 mm_log((0,"malloc_state()\n"));
89 for(i=0; i<MAXMAL; i++) if (malloc_pointers[i].ptr != NULL) {
90 mm_log((0,"%d: %lu (%p) : %s\n", i, (unsigned long)malloc_pointers[i].size, malloc_pointers[i].ptr, malloc_pointers[i].comm));
91 total += malloc_pointers[i].size;
93 if (total == 0) mm_log((0,"No memory currently used!\n"))
94 else mm_log((0,"total: %lu\n", (unsigned long)total));
100 mymalloc_file_line(size_t size, char* file, int line) {
103 if (malloc_need_init) malloc_init();
105 /* bndcheck_all(); Uncomment for LOTS OF THRASHING */
107 if ( (i = find_ptr(NULL)) < 0 ) {
108 mm_log((0,"more than %d segments allocated at %s (%d)\n", MAXMAL, file, line));
112 if ( (buf = malloc(size+UNDRRNVAL+OVERRNVAL)) == NULL ) {
113 mm_log((1,"Unable to allocate %ld for %s (%i)\n", (long)size, file, line));
117 buf = set_entry(i, buf, size, file, line);
118 mm_log((1,"mymalloc_file_line: slot <%d> %ld bytes allocated at %p for %s (%d)\n", i, (long)size, buf, file, line));
123 (mymalloc)(size_t size) {
124 return mymalloc_file_line(size, "unknown", 0);
128 myrealloc_file_line(void *ptr, size_t newsize, char* file, int line) {
132 if (malloc_need_init) malloc_init();
133 /* bndcheck_all(); ACTIVATE FOR LOTS OF THRASHING */
136 mm_log((1, "realloc called with ptr = NULL, sending request to malloc\n"));
137 return mymalloc_file_line(newsize, file, line);
141 mm_log((1, "newsize = 0, sending request to free\n"));
142 myfree_file_line(ptr, file, line);
146 if ( (i = find_ptr(ptr)) == -1) {
147 mm_log((0, "Unable to find %p in realloc for %s (%i)\n", ptr, file, line));
151 if ( (buf = realloc(((char *)ptr)-UNDRRNVAL, UNDRRNVAL+OVERRNVAL+newsize)) == NULL ) {
152 mm_log((1,"Unable to reallocate %ld bytes at %p for %s (%i)\n", (long)
153 newsize, ptr, file, line));
157 buf = set_entry(i, buf, newsize, file, line);
158 mm_log((1,"realloc_file_line: slot <%d> %ld bytes allocated at %p for %s (%d)\n", i, (long)newsize, buf, file, line));
163 (myrealloc)(void *ptr, size_t newsize) {
164 return myrealloc_file_line(ptr, newsize, "unknown", 0);
171 size_t s = malloc_pointers[idx].size;
172 unsigned char *pp = malloc_pointers[idx].ptr;
174 mm_log((1, "bndcheck: No pointer in slot %d\n", idx));
178 for(i=0;i<UNDRRNVAL;i++) {
179 if (pp[-(1+i)] != PADBYTE)
180 mm_log((1,"bndcheck: UNDERRUN OF %d bytes detected: slot = %d, point = %p, size = %ld\n", i+1, idx, pp, (long)s ));
183 for(i=0;i<OVERRNVAL;i++) {
184 if (pp[s+i] != PADBYTE)
185 mm_log((1,"bndcheck: OVERRUN OF %d bytes detected: slot = %d, point = %p, size = %ld\n", i+1, idx, pp, (long)s ));
192 mm_log((1, "bndcheck_all()\n"));
193 for(idx=0; idx<MAXMAL; idx++)
194 if (malloc_pointers[idx].ptr)
199 myfree_file_line(void *p, char *file, int line) {
207 for(i=0; i<MAXMAL; i++) if (malloc_pointers[i].ptr == p) {
208 mm_log((1,"myfree_file_line: pointer %i (%s) freed at %s (%i)\n", i, malloc_pointers[i].comm, file, line));
210 malloc_pointers[i].ptr = NULL;
214 mm_log((1, "myfree_file_line: freeing address %p (real %p)\n", pp, pp-UNDRRNVAL));
217 mm_log((1, "myfree_file_line: INCONSISTENT REFCOUNT %d at %s (%i)\n", match, file, line));
218 fprintf(stderr, "myfree_file_line: INCONSISTENT REFCOUNT %d at %s (%i)\n", match, file, line);
227 (myfree)(void *block) {
228 myfree_file_line(block, "unknown", 0);
238 mymalloc(size_t size) {
242 fprintf(stderr, "Attempt to allocate size %ld\n", (long)size);
246 if ( (buf = malloc(size)) == NULL ) {
247 mm_log((1, "mymalloc: unable to malloc %ld\n", (long)size));
248 fprintf(stderr,"Unable to malloc %ld.\n", (long)size); exit(3);
250 mm_log((1, "mymalloc(size %ld) -> %p\n", (long)size, buf));
255 mymalloc_file_line(size_t size, char *file, int line) {
256 return mymalloc(size);
261 mm_log((1, "myfree(p %p)\n", p));
266 myfree_file_line(void *p, char *file, int line) {
271 myrealloc(void *block, size_t size) {
274 mm_log((1, "myrealloc(block %p, size %ld)\n", block, (long)size));
275 if ((result = realloc(block, size)) == NULL) {
276 mm_log((1, "myrealloc: out of memory\n"));
277 fprintf(stderr, "Out of memory.\n");
284 myrealloc_file_line(void *block, size_t newsize, char *file, int size) {
285 return myrealloc(block, newsize);
288 #endif /* IMAGER_MALLOC_DEBUG */
293 /* memory pool implementation */
296 i_mempool_init(i_mempool *mp) {
299 mp->p = mymalloc(sizeof(void*)*mp->alloc);
303 i_mempool_extend(i_mempool *mp) {
304 mp->p = myrealloc(mp->p, mp->alloc * 2);
309 i_mempool_alloc(i_mempool *mp, size_t size) {
310 if (mp->used == mp->alloc) i_mempool_extend(mp);
311 mp->p[mp->used] = mymalloc(size);
313 return mp->p[mp->used-1];
318 i_mempool_destroy(i_mempool *mp) {
320 for(i=0; i<mp->used; i++) myfree(mp->p[i]);
326 /* Should these really be here? */
332 i_minx(i_img_dim a, i_img_dim b) {
333 if (a<b) return a; else return b;
337 i_maxx(i_img_dim a, i_img_dim b) {
338 if (a>b) return a; else return b;
347 struct utf8_size utf8_sizes[] =
356 =item i_utf8_advance(char **p, size_t *len)
358 Retrieve a C<UTF-8> character from the stream.
360 Modifies *p and *len to indicate the consumed characters.
362 This doesn't support the extended C<UTF-8> encoding used by later
363 versions of Perl. Since this is typically used to implement text
364 output by font drivers, the strings supplied shouldn't have such out
367 This doesn't check that the C<UTF-8> character is using the shortest
368 possible representation.
370 Returns ~0UL on failure.
376 i_utf8_advance(char const **p, size_t *len) {
379 unsigned char codes[3];
384 for (i = 0; i < sizeof(utf8_sizes)/sizeof(*utf8_sizes); ++i) {
385 if ((c & utf8_sizes[i].mask) == utf8_sizes[i].expect) {
386 clen = utf8_sizes[i].size;
390 if (clen == 0 || *len < clen-1) {
395 /* check that each character is well formed */
399 if (((*p)[ci] & 0xC0) != 0x80) {
403 codes[ci] = (*p)[ci];
406 *p += clen-1; *len -= clen-1;
408 if ((c & 0xE0) == 0xC0) {
409 return ((c & 0x1F) << 6) + (codes[0] & 0x3F);
411 else if ((c & 0xF0) == 0xE0) {
412 return ((c & 0x0F) << 12) | ((codes[0] & 0x3F) << 6) | (codes[1] & 0x3f);
414 else if ((c & 0xF8) == 0xF0) {
415 return ((c & 0x07) << 18) | ((codes[0] & 0x3F) << 12)
416 | ((codes[1] & 0x3F) << 6) | (codes[2] & 0x3F);
419 *p -= clen; *len += clen;