]>
Commit | Line | Data |
---|---|---|
082e680b MNI |
1 | /* Copyright (C) 2004 Manuel Novoa III <[email protected]> |
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 "_stdio.h" | |
9 | #include <stdarg.h> | |
371ca787 | 10 | #include <bits/uClibc_va_copy.h> |
082e680b MNI |
11 | |
12 | #ifdef __UCLIBC_MJN3_ONLY__ | |
13 | /* Do the memstream stuff inline to avoid fclose and the openlist? */ | |
14 | #warning CONSIDER: avoid open_memstream call? | |
15 | #endif | |
16 | ||
17 | #ifndef __STDIO_HAS_VSNPRINTF | |
18 | #warning Skipping vasprintf since no vsnprintf! | |
19 | #else | |
20 | ||
21 | int vasprintf(char **__restrict buf, const char * __restrict format, | |
22 | va_list arg) | |
23 | { | |
24 | #ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ | |
25 | ||
26 | FILE *f; | |
27 | size_t size; | |
28 | int rv = -1; | |
29 | ||
30 | *buf = NULL; | |
31 | ||
32 | if ((f = open_memstream(buf, &size)) != NULL) { | |
33 | rv = vfprintf(f, format, arg); | |
34 | fclose(f); | |
35 | if (rv < 0) { | |
36 | free(*buf); | |
37 | *buf = NULL; | |
38 | } | |
39 | } | |
40 | ||
41 | assert(rv >= -1); | |
42 | ||
43 | return rv; | |
44 | ||
45 | #else /* __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ */ | |
46 | ||
47 | /* This implementation actually calls the printf machinery twice, but only | |
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; | |
53 | ||
54 | va_copy(arg2, arg); | |
55 | rv = vsnprintf(NULL, 0, format, arg2); | |
56 | va_end(arg2); | |
57 | ||
58 | *buf = NULL; | |
59 | ||
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; | |
65 | } | |
66 | } | |
67 | } | |
68 | ||
69 | assert(rv >= -1); | |
70 | ||
71 | return rv; | |
72 | ||
73 | #endif /* __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ */ | |
74 | } | |
75 | ||
76 | #endif |