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