diff options
author | Manuel Novoa III <mjn3@codepoet.org> | 2004-02-11 23:48:50 +0000 |
---|---|---|
committer | Manuel Novoa III <mjn3@codepoet.org> | 2004-02-11 23:48:50 +0000 |
commit | 082e680bd54e999f2bb4eb77141958938b1e9ee9 (patch) | |
tree | 203c45b85ca608e1550d8ffc459456fc9cf0b30b /libc/stdio/vasprintf.c | |
parent | 17c21765b4a97c6f0b74ba8466073e5a3f97cdee (diff) |
New stdio core. Should be more maintainable. Fixes a couple of bugs.
Codepaths streamlined. Improved performance for nonthreaded apps
when linked with a thread-enabled libc.
Minor iconv bug and some locale/thread related startup issues fixed.
These showed up in getting a gcj-compiled java helloworld app running.
Removed some old extension functions... _stdio_fdout and _stdio_fsfopen.
Diffstat (limited to 'libc/stdio/vasprintf.c')
-rw-r--r-- | libc/stdio/vasprintf.c | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/libc/stdio/vasprintf.c b/libc/stdio/vasprintf.c new file mode 100644 index 000000000..21ef8e145 --- /dev/null +++ b/libc/stdio/vasprintf.c @@ -0,0 +1,75 @@ +/* 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 "_stdio.h" +#include <stdarg.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 + * 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__ */ +} + +#endif |