]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/vasprintf.c
Inital import
[l4.git] / l4 / pkg / uclibc / lib / contrib / uclibc / libc / stdio / vasprintf.c
1 /* Copyright (C) 2004       Manuel Novoa III    <mjn3@codepoet.org>
2  *
3  * GNU Library General Public License (LGPL) version 2 or later.
4  *
5  * Dedicated to Toni.  See uClibc/DEDICATION.mjn3 for details.
6  */
7
8 #include <features.h>
9
10 #ifdef __USE_GNU
11 #include "_stdio.h"
12 #include <stdarg.h>
13 #include <bits/uClibc_va_copy.h>
14
15
16 #ifdef __UCLIBC_MJN3_ONLY__
17 /* Do the memstream stuff inline to avoid fclose and the openlist? */
18 #warning CONSIDER: avoid open_memstream call?
19 #endif
20
21 #ifndef __STDIO_HAS_VSNPRINTF
22 #warning Skipping vasprintf since no vsnprintf!
23 #else
24
25 int vasprintf(char **__restrict buf, const char * __restrict format,
26                          va_list arg)
27 {
28 #ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__
29
30         FILE *f;
31         size_t size;
32         int rv = -1;
33
34         *buf = NULL;
35
36         if ((f = open_memstream(buf, &size)) != NULL) {
37                 rv = vfprintf(f, format, arg);
38                 fclose(f);
39                 if (rv < 0) {
40                         free(*buf);
41                         *buf = NULL;
42                 }
43         }
44
45         assert(rv >= -1);
46
47         return rv;
48
49 #else  /* __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ */
50
51         /* This implementation actually calls the printf machinery twice, but
52          * only does one malloc.  This can be a problem though when custom printf
53          * specs or the %m specifier are involved because the results of the
54          * second call might be different from the first. */
55         va_list arg2;
56         int rv;
57
58         va_copy(arg2, arg);
59         rv = vsnprintf(NULL, 0, format, arg2);
60         va_end(arg2);
61
62         *buf = NULL;
63
64         if (rv >= 0) {
65                 if ((*buf = malloc(++rv)) != NULL) {
66                         if ((rv = vsnprintf(*buf, rv, format, arg)) < 0) {
67                                 free(*buf);
68                                 *buf = NULL;
69                         }
70                 }
71         }
72
73         assert(rv >= -1);
74
75         return rv;
76
77 #endif /* __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ */
78 }
79 libc_hidden_def(vasprintf)
80
81 #endif
82 #endif