mirror of
git://uclibc.org/uClibc.git
synced 2026-01-19 00:08:21 +08:00
83 lines
1.6 KiB
C
83 lines
1.6 KiB
C
/* 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>
|
|
|
|
|
|
#ifdef __UCLIBC_MJN3_ONLY__
|
|
/* Do the memstream stuff inline to avoid fclose and the openlist? */
|
|
#warning CONSIDER: avoid open_memstream call?
|
|
#endif
|
|
|
|
#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;
|
|
}
|
|
}
|
|
|
|
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
|