netinet/in.h: add IPPROTO_MH
[uclibc-ng.git] / libc / stdio / vasprintf.c
blob026d8b2bd1c33d2736680dcfbb150556d9b8bf8c
1 /* Copyright (C) 2004 Manuel Novoa III <mjn3@codepoet.org>
3 * GNU Library General Public License (LGPL) version 2 or later.
5 * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details.
6 */
8 #include <features.h>
10 #ifdef __USE_GNU
11 #include "_stdio.h"
12 #include <stdarg.h>
13 #include <bits/uClibc_va_copy.h>
15 #ifndef __STDIO_HAS_VSNPRINTF
16 #warning Skipping vasprintf since no vsnprintf!
17 #else
19 int vasprintf(char **__restrict buf, const char * __restrict format,
20 va_list arg)
22 #ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__
24 FILE *f;
25 size_t size;
26 int rv = -1;
28 *buf = NULL;
30 if ((f = open_memstream(buf, &size)) != NULL) {
31 rv = vfprintf(f, format, arg);
32 fclose(f);
33 if (rv < 0) {
34 free(*buf);
35 *buf = NULL;
36 } else {
37 *buf = realloc(*buf, rv + 1);
41 assert(rv >= -1);
43 return rv;
45 #else /* __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ */
47 /* This implementation actually calls the printf machinery twice, but
48 * only does one malloc. This can be a problem though when custom printf
49 * specs or the %m specifier are involved because the results of the
50 * second call might be different from the first. */
51 va_list arg2;
52 int rv;
54 va_copy(arg2, arg);
55 rv = vsnprintf(NULL, 0, format, arg2);
56 va_end(arg2);
58 *buf = NULL;
60 if (rv >= 0) {
61 if ((*buf = malloc(++rv)) != NULL) {
62 if ((rv = vsnprintf(*buf, rv, format, arg)) < 0) {
63 free(*buf);
64 *buf = NULL;
69 assert(rv >= -1);
71 return rv;
73 #endif /* __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ */
75 libc_hidden_def(vasprintf)
77 #endif
78 #endif