| /* 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 |