]> git.ozlabs.org Git - ccan/blob - ccan/asprintf/asprintf.c
ilog: credit Tim Terriberry as author in ccan/ilog/_info
[ccan] / ccan / asprintf / asprintf.c
1 #include <ccan/asprintf/asprintf.h>
2 #include <stdarg.h>
3 #include <stdio.h>
4
5 char *PRINTF_FMT(1, 2) afmt(const char *fmt, ...)
6 {
7         va_list ap;
8         char *ptr;
9
10         va_start(ap, fmt);
11         /* The BSD version apparently sets ptr to NULL on fail.  GNU loses. */
12         if (vasprintf(&ptr, fmt, ap) < 0)
13                 ptr = NULL;
14         va_end(ap);
15         return ptr;
16 }
17
18 #if !HAVE_ASPRINTF
19 #include <stdarg.h>
20 #include <stdlib.h>
21
22 int vasprintf(char **strp, const char *fmt, va_list ap)
23 {
24         int len;
25         va_list ap_copy;
26
27         /* We need to make a copy of ap, since it's a use-once. */
28         va_copy(ap_copy, ap);
29         len = vsnprintf(NULL, 0, fmt, ap_copy);
30         va_end(ap_copy);
31
32         /* Until version 2.0.6 glibc would return -1 on truncated output.
33          * OTOH, they had asprintf. */
34         if (len < 0)
35                 return -1;
36
37         *strp = malloc(len+1);
38         if (!*strp)
39                 return -1;
40
41         return vsprintf(*strp, fmt, ap);
42 }
43
44 int asprintf(char **strp, const char *fmt, ...)
45 {
46         va_list ap;
47         int len;
48
49         va_start(ap, fmt);
50         len = vasprintf(strp, fmt, ap);
51         va_end(ap);
52
53         return len;
54 }
55 #endif /* !HAVE_ASPRINTF */