1b432e2ec53d424c3b88a1ebed7989406adaef8e
[libfirm] / ir / obstack / obstack_printf.c
1 #include <stdarg.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include "obstack.h"
5
6 #ifdef _WIN32
7 #define vsnprintf _vsnprintf
8 #endif
9
10 int obstack_printf(struct obstack *obst, const char *fmt, ...)
11 {
12         char  buf[128];
13         char *buffer = buf;
14         va_list ap;
15         int len;
16
17         va_start(ap, fmt);
18         len = vsnprintf(buffer, sizeof(buffer), fmt, ap);
19         va_end(ap);
20         if (len < 0 || len >= (int) sizeof(buffer)) {
21                 size_t size   = len >= 0 ? (size_t) len : sizeof(buffer) * 2;
22                 char  *buffer = malloc(size);
23                 do {
24                         if (buffer == NULL)
25                                 return -1;
26
27                         va_start(ap, fmt);
28                         len = vsnprintf(buffer, size, fmt, ap);
29                         va_end(ap);
30
31                         /* snprintf should return -1 only in the error case, but older
32                          * glibcs and probably other systems are buggy in this respect and
33                          * return -1 if the buffer was too small. We only abort for LARGE
34                          * unrealistic buffer sizes here */
35                         if (len < 0) {
36                                 if (size > 65536)
37                                         return -1;
38                                 size *= 2;
39                                 buffer = realloc(buffer, size);
40                         } else if (len >= (int) size) {
41                                 /* this should not happen if snprintf works correctly */
42                                 abort();
43                         }
44                 } while (len < 0);
45                 free(buffer);
46         }
47         obstack_grow(obst, buffer, len);
48
49         return len;
50 }