123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778 |
- /* Copyright (C) 2004 Manuel Novoa III <mjn3@codepoet.org>
- *
- * GNU Library General Public License (LGPL) version 2 or later.
- *
- * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details.
- */
- #include <features.h>
- #ifdef __USE_GNU
- #include "_stdio.h"
- #include <stdarg.h>
- #include <bits/uClibc_va_copy.h>
- #ifndef __STDIO_HAS_VSNPRINTF
- #warning Skipping vasprintf since no vsnprintf!
- #else
- int vasprintf(char **__restrict buf, const char * __restrict format,
- va_list arg)
- {
- #ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__
- FILE *f;
- size_t size;
- int rv = -1;
- *buf = NULL;
- if ((f = open_memstream(buf, &size)) != NULL) {
- rv = vfprintf(f, format, arg);
- fclose(f);
- if (rv < 0) {
- free(*buf);
- *buf = NULL;
- } else {
- *buf = realloc(*buf, rv + 1);
- }
- }
- assert(rv >= -1);
- return rv;
- #else /* __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ */
- /* This implementation actually calls the printf machinery twice, but
- * only does one malloc. This can be a problem though when custom printf
- * specs or the %m specifier are involved because the results of the
- * second call might be different from the first. */
- va_list arg2;
- int rv;
- va_copy(arg2, arg);
- rv = vsnprintf(NULL, 0, format, arg2);
- va_end(arg2);
- *buf = NULL;
- if (rv >= 0) {
- if ((*buf = malloc(++rv)) != NULL) {
- if ((rv = vsnprintf(*buf, rv, format, arg)) < 0) {
- free(*buf);
- *buf = NULL;
- }
- }
- }
- assert(rv >= -1);
- return rv;
- #endif /* __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ */
- }
- libc_hidden_def(vasprintf)
- #endif
- #endif
|