X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fobstack%2Fobstack_printf.c;h=7ade5ef138b363adc88f4b58b7d92addab2b9cce;hb=d5d7159c209a9e5c5fa276f770b5b28a217990a8;hp=65f06dc4f56bdf3747c08f962d5f75c099cfb6ea;hpb=de1b0c8d4f653f534a38740ad7f6803d82f2762e;p=libfirm diff --git a/ir/obstack/obstack_printf.c b/ir/obstack/obstack_printf.c index 65f06dc4f..7ade5ef13 100644 --- a/ir/obstack/obstack_printf.c +++ b/ir/obstack/obstack_printf.c @@ -1,21 +1,67 @@ #include #include +#include +#include #include "obstack.h" #ifdef _WIN32 -#define vsnprintf _vsnprintf +/* win32/C89 has no va_copy function... so we have to use the stupid fixed-length version */ +int obstack_vprintf(struct obstack *obst, const char *fmt, va_list ap) FIRM_NOTHROW +{ + char buf[16384]; + int len = _vsnprintf(buf, sizeof(buf), fmt, ap); + obstack_grow(obst, buf, len); + return len; +} +#else +int obstack_vprintf(struct obstack *obst, const char *fmt, va_list ap) FIRM_NOTHROW +{ + char buf[128]; + char *buffer = buf; + size_t size = sizeof(buf); + int len; + + for (;;) { + va_list tap; + va_copy(tap, ap); + len = vsnprintf(buffer, size, fmt, tap); + + /* snprintf should return -1 only in the error case, but older glibcs + * and probably other systems are buggy in this respect and return -1 if + * the buffer was too small. We only abort for LARGE unrealistic buffer + * sizes here */ + if (len < 0) { + if (buffer != buf) + free(buffer); + if (size > 65536) + return -1; + size *= 2; + } else if ((size_t)len >= size) { + /* If we come here more than once, vsnprintf() returned garbage */ + assert(buffer == buf); + size = (size_t)len + 1; + } else { + break; + } + buffer = (char*)malloc(size); + } + + obstack_grow(obst, buffer, len); + if (buffer != buf) + free(buffer); + + return len; +} #endif -int obstack_printf(struct obstack *obst, const char *fmt, ...) +int obstack_printf(struct obstack *obst, const char *fmt, ...) FIRM_NOTHROW { - char buf[1024]; - va_list ap; - int len; + va_list ap; + int res; - va_start(ap, fmt); - len = vsnprintf(buf, sizeof(buf), fmt, ap); - obstack_grow(obst, buf, len); - va_end(ap); + va_start(ap, fmt); + res = obstack_vprintf(obst, fmt, ap); + va_end(ap); - return len; + return res; }