make firm compilable with a c++ compiler
[libfirm] / ir / obstack / obstack_printf.c
1 #include <stdarg.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <assert.h>
5 #include "obstack.h"
6
7 #ifdef _WIN32
8 /* win32/C89 has no va_copy function... so we have to use the stupid fixed-length version */
9 int obstack_vprintf(struct obstack *obst, const char *fmt, va_list ap) FIRM_NOTHROW
10 {
11         char buf[16384];
12         int len = _vsnprintf(buf, sizeof(buf), fmt, ap);
13         obstack_grow(obst, buf, len);
14         return len;
15 }
16 #else
17 int obstack_vprintf(struct obstack *obst, const char *fmt, va_list ap) FIRM_NOTHROW
18 {
19         char    buf[128];
20         char   *buffer = buf;
21         size_t  size   = sizeof(buf);
22         int     len;
23
24         for (;;) {
25                 va_list tap;
26                 va_copy(tap, ap);
27                 len = vsnprintf(buffer, size, fmt, tap);
28
29                 /* snprintf should return -1 only in the error case, but older glibcs
30                  * and probably other systems are buggy in this respect and return -1 if
31                  * the buffer was too small. We only abort for LARGE unrealistic buffer
32                  * sizes here */
33                 if (len < 0) {
34                         if (buffer != buf)
35                                 free(buffer);
36                         if (size > 65536)
37                                 return -1;
38                         size *= 2;
39                 } else if ((size_t)len >= size) {
40                         /* If we come here more than once, vsnprintf() returned garbage */
41                         assert(buffer == buf);
42                         size = (size_t)len + 1;
43                 } else {
44                         break;
45                 }
46                 buffer = (char*)malloc(size);
47         }
48
49         obstack_grow(obst, buffer, len);
50         if (buffer != buf)
51                 free(buffer);
52
53         return len;
54 }
55 #endif
56
57 int obstack_printf(struct obstack *obst, const char *fmt, ...) FIRM_NOTHROW
58 {
59         va_list ap;
60         int     res;
61
62         va_start(ap, fmt);
63         res = obstack_vprintf(obst, fmt, ap);
64         va_end(ap);
65
66         return res;
67 }