summaryrefslogtreecommitdiff
path: root/libc/stdio
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2008-04-09 19:51:18 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2008-04-09 19:51:18 +0000
commit36ac7bee0f6b0be35eafd74e0fc865edd2352197 (patch)
treeb557dfbf03da9612bc09906fa3fb7559f556fed8 /libc/stdio
parentf1459b13206cee20f322a53bb659a8735e2c8de0 (diff)
Factor out the core of vprintf() into separate function
vprintf_internal, so that: * vprintf() does locking and __STDIO_STREAM_TRANS_TO_WRITE thing, then calls vprintf_internal * vsnprintf, vdprintf.c, vasprintf.c use vprintf_internal directly This makes sprintf faster (since it doesn't do any locking) and stops it from pulling in fseek in static compile.
Diffstat (limited to 'libc/stdio')
-rw-r--r--libc/stdio/Makefile.in3
-rw-r--r--libc/stdio/_stdio.h13
-rw-r--r--libc/stdio/_vfprintf.c129
-rw-r--r--libc/stdio/_vfprintf_internal.c9
-rw-r--r--libc/stdio/_vfwprintf_internal.c9
-rw-r--r--libc/stdio/vasprintf.c2
-rw-r--r--libc/stdio/vdprintf.c4
-rw-r--r--libc/stdio/vsnprintf.c6
-rw-r--r--libc/stdio/vswprintf.c4
9 files changed, 124 insertions, 55 deletions
diff --git a/libc/stdio/Makefile.in b/libc/stdio/Makefile.in
index d6134cb06..74f6d9aed 100644
--- a/libc/stdio/Makefile.in
+++ b/libc/stdio/Makefile.in
@@ -59,6 +59,7 @@ CUSRC := \
ifneq ($(USE_OLD_VFPRINTF),y)
VF_CSRC := \
vfprintf.c \
+ _vfprintf_internal.c \
_ppfs_init.c _ppfs_prepargs.c _ppfs_setargs.c _ppfs_parsespec.c \
register_printf_function.c parse_printf_format.c
CSRC += $(VF_CSRC)
@@ -77,7 +78,7 @@ CSRC += _wfwrite.c fwprintf.c swprintf.c vswprintf.c vwprintf.c wprintf.c \
CUSRC += fgetwc.c getwchar.c fgetws.c fputwc.c putwchar.c fputws.c
# getwc (fgetwc alias) getwc_unlocked (fgetwc_unlocked alias)
# putwc (fputwc alias) putwc_unlocked (fputwc_unlocked alias)
-CSRC += vfwprintf.c
+CSRC += vfwprintf.c _vfwprintf_internal.c
CSRC += wscanf.c swscanf.c fwscanf.c vwscanf.c vswscanf.c vfwscanf.c
endif
diff --git a/libc/stdio/_stdio.h b/libc/stdio/_stdio.h
index 74b891a03..e1fc26785 100644
--- a/libc/stdio/_stdio.h
+++ b/libc/stdio/_stdio.h
@@ -15,6 +15,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <stdarg.h>
#include <unistd.h>
#ifdef __UCLIBC_HAS_WCHAR__
#include <wchar.h>
@@ -431,6 +432,18 @@ extern size_t _wstdio_fwrite(const wchar_t *__restrict ws,
#endif
/**********************************************************************/
+
+extern int _vfprintf_internal (FILE * __restrict stream,
+ register const char * __restrict format,
+ va_list arg) attribute_hidden;
+
+#ifdef __UCLIBC_HAS_WCHAR__
+extern int _vfwprintf_internal (FILE * __restrict stream,
+ register const wchar_t * __restrict format,
+ va_list arg) attribute_hidden;
+#endif
+
+/**********************************************************************/
/* Only use the macro below if you know fp is a valid FILE for a valid fd.
* This is _not_ true for custom streams! */
#define __FILENO_UNLOCKED(fp) ((fp)->__filedes)
diff --git a/libc/stdio/_vfprintf.c b/libc/stdio/_vfprintf.c
index fd2975aa3..b3deaddb1 100644
--- a/libc/stdio/_vfprintf.c
+++ b/libc/stdio/_vfprintf.c
@@ -1198,7 +1198,7 @@ int register_printf_function(int spec, printf_function handler,
#endif
/**********************************************************************/
-#if defined(L_vfprintf) || defined(L_vfwprintf)
+#if defined(L__vfprintf_internal) || defined(L__vfwprintf_internal)
/* We only support ascii digits (or their USC equivalent codes) in
* precision and width settings in *printf (wide) format strings.
@@ -1207,14 +1207,15 @@ int register_printf_function(int spec, printf_function handler,
static size_t _charpad(FILE * __restrict stream, int padchar, size_t numpad);
-#ifdef L_vfprintf
+#ifdef L__vfprintf_internal
-#define VFPRINTF vfprintf
+#define VFPRINTF_internal _vfprintf_internal
#define FMT_TYPE char
#define OUTNSTR _outnstr
#define STRLEN strlen
#define _PPFS_init _ppfs_init
-#define OUTPUT(F,S) fputs_unlocked(S,F)
+/* Pulls in fseek: #define OUTPUT(F,S) fputs_unlocked(S,F) */
+#define OUTPUT(F,S) __stdio_fwrite((const unsigned char *)(S),strlen(S),(F))
/* #define _outnstr(stream, string, len) __stdio_fwrite(string, len, stream) */
#define _outnstr(stream, string, len) ((len > 0) ? __stdio_fwrite(string, len, stream) : 0)
#define FP_OUT _fp_out_narrow
@@ -1239,14 +1240,16 @@ static size_t _fp_out_narrow(FILE *fp, intptr_t type, intptr_t len, intptr_t buf
#endif /* __STDIO_PRINTF_FLOAT */
-#else /* L_vfprintf */
+#else /* L__vfprintf_internal */
-#define VFPRINTF vfwprintf
+#define VFPRINTF_internal _vfwprintf_internal
#define FMT_TYPE wchar_t
#define OUTNSTR _outnwcs
#define STRLEN wcslen
#define _PPFS_init _ppwfs_init
+/* Pulls in fseek: */
#define OUTPUT(F,S) fputws(S,F)
+/* TODO: #define OUTPUT(F,S) _wstdio_fwrite((S),wcslen(S),(F)) */
#define _outnwcs(stream, wstring, len) _wstdio_fwrite(wstring, len, stream)
#define FP_OUT _fp_out_wide
@@ -1417,7 +1420,8 @@ static int _ppwfs_init(register ppfs_t *ppfs, const wchar_t *fmt0)
return 0;
}
-#endif /* L_vfprintf */
+#endif /* L__vfprintf_internal */
+
static size_t _charpad(FILE * __restrict stream, int padchar, size_t numpad)
{
@@ -1439,12 +1443,12 @@ static int _do_one_spec(FILE * __restrict stream,
register ppfs_t *ppfs, int *count)
{
static const char spec_base[] = SPEC_BASE;
-#ifdef L_vfprintf
+#ifdef L__vfprintf_internal
static const char prefix[] = "+\0-\0 \0000x\0000X";
/* 0 2 4 6 9 11*/
-#else /* L_vfprintf */
+#else /* L__vfprintf_internal */
static const wchar_t prefix[] = L"+\0-\0 \0000x\0000X";
-#endif /* L_vfprintf */
+#endif /* L__vfprintf_internal */
enum {
PREFIX_PLUS = 0,
PREFIX_MINUS = 2,
@@ -1465,7 +1469,7 @@ static int _do_one_spec(FILE * __restrict stream,
mbstate_t mbstate;
#endif /* __UCLIBC_HAS_WCHAR__ */
size_t slen;
-#ifdef L_vfprintf
+#ifdef L__vfprintf_internal
#define SLEN slen
#else
size_t SLEN;
@@ -1532,7 +1536,7 @@ static int _do_one_spec(FILE * __restrict stream,
alphacase = __UIM_LOWER;
#ifdef __UCLIBC_MJN3_ONLY__
-#ifdef L_vfprintf
+#ifdef L__vfprintf_internal
#warning CONSIDER: Should we ignore these flags if stub locale? What about custom specs?
#endif
#endif /* __UCLIBC_MJN3_ONLY__ */
@@ -1560,7 +1564,7 @@ static int _do_one_spec(FILE * __restrict stream,
padchar = ppfs->info.pad;
}
#ifdef __UCLIBC_MJN3_ONLY__
-#ifdef L_vfprintf
+#ifdef L__vfprintf_internal
#warning CONSIDER: If using outdigits and/or grouping, how should we interpret precision?
#endif
#endif /* __UCLIBC_MJN3_ONLY__ */
@@ -1580,7 +1584,7 @@ static int _do_one_spec(FILE * __restrict stream,
}
}
slen = (char *)(buf + sizeof(buf) - 1) - s;
-#ifdef L_vfwprintf
+#ifdef L__vfwprintf_internal
{
const char *q = s;
mbstate.__mask = 0; /* Initialize the mbstate. */
@@ -1605,13 +1609,13 @@ static int _do_one_spec(FILE * __restrict stream,
}
if (ppfs->conv_num == CONV_p) {/* null pointer */
s = "(nil)";
-#ifdef L_vfwprintf
+#ifdef L__vfwprintf_internal
SLEN =
#endif
slen = 5;
numfill = 0;
} else if (numfill == 0) { /* if precision 0, no output */
-#ifdef L_vfwprintf
+#ifdef L__vfwprintf_internal
SLEN =
#endif
slen = 0;
@@ -1637,7 +1641,7 @@ static int _do_one_spec(FILE * __restrict stream,
return -1; /* TODO -- try to continue? */
#endif /* __STDIO_PRINTF_FLOAT */
} else if (ppfs->conv_num <= CONV_S) { /* wide char or string */
-#ifdef L_vfprintf
+#ifdef L__vfprintf_internal
#ifdef __UCLIBC_HAS_WCHAR__
mbstate.__mask = 0; /* Initialize the mbstate. */
@@ -1692,7 +1696,7 @@ static int _do_one_spec(FILE * __restrict stream,
slen = 1;
}
-#else /* L_vfprintf */
+#else /* L__vfprintf_internal */
if (ppfs->conv_num == CONV_S) { /* wide string */
ws = *((wchar_t **) (*argptr));
@@ -1713,7 +1717,7 @@ static int _do_one_spec(FILE * __restrict stream,
if (ppfs->conv_num == CONV_s) { /* string */
#ifdef __UCLIBC_MJN3_ONLY__
-#warning TODO: Fix %s for vfwprintf... output upto illegal sequence?
+#warning TODO: Fix %s for _vfwprintf_internal... output upto illegal sequence?
#endif /* __UCLIBC_MJN3_ONLY__ */
s = *((char **) (*argptr));
if (s) {
@@ -1746,7 +1750,7 @@ static int _do_one_spec(FILE * __restrict stream,
goto CHAR_CASE;
}
-#endif /* L_vfprintf */
+#endif /* L__vfprintf_internal */
#ifdef __UCLIBC_HAS_PRINTF_M_SPEC__
} else if (ppfs->conv_num == CONV_m) {
@@ -1778,7 +1782,7 @@ static int _do_one_spec(FILE * __restrict stream,
}
#ifdef __UCLIBC_MJN3_ONLY__
-#ifdef L_vfprintf
+#ifdef L__vfprintf_internal
#warning CONSIDER: If using outdigits and/or grouping, how should we pad?
#endif
#endif /* __UCLIBC_MJN3_ONLY__ */
@@ -1805,11 +1809,12 @@ static int _do_one_spec(FILE * __restrict stream,
numpad = 0;
}
OUTPUT(stream, prefix + prefix_num);
+
if (_charpad(stream, '0', numfill) != numfill) {
return -1;
}
-#ifdef L_vfprintf
+#ifdef L__vfprintf_internal
#ifdef __UCLIBC_HAS_WCHAR__
if (!ws) {
@@ -1836,7 +1841,7 @@ static int _do_one_spec(FILE * __restrict stream,
}
#endif /* __UCLIBC_HAS_WCHAR__ */
-#else /* L_vfprintf */
+#else /* L__vfprintf_internal */
if (!ws) {
assert(s);
@@ -1849,7 +1854,7 @@ static int _do_one_spec(FILE * __restrict stream,
}
}
-#endif /* L_vfprintf */
+#endif /* L__vfprintf_internal */
if (_charpad(stream, ' ', numpad) != numpad) {
return -1;
}
@@ -1860,35 +1865,21 @@ static int _do_one_spec(FILE * __restrict stream,
libc_hidden_proto(fprintf)
-libc_hidden_proto(VFPRINTF)
-int VFPRINTF (FILE * __restrict stream,
+int VFPRINTF_internal (FILE * __restrict stream,
register const FMT_TYPE * __restrict format,
va_list arg)
{
ppfs_t ppfs;
int count, r;
register const FMT_TYPE *s;
- __STDIO_AUTO_THREADLOCK_VAR;
-
- __STDIO_AUTO_THREADLOCK(stream);
count = 0;
s = format;
- if
-#ifdef L_vfprintf
- (!__STDIO_STREAM_IS_NARROW_WRITING(stream)
- && __STDIO_STREAM_TRANS_TO_WRITE(stream, __FLAG_NARROW))
-#else
- (!__STDIO_STREAM_IS_WIDE_WRITING(stream)
- && __STDIO_STREAM_TRANS_TO_WRITE(stream, __FLAG_WIDE))
-#endif
- {
- count = -1;
- } else if (_PPFS_init(&ppfs, format) < 0) { /* Bad format string. */
+ if (_PPFS_init(&ppfs, format) < 0) { /* Bad format string. */
OUTNSTR(stream, (const unsigned char *) ppfs.fmtpos,
STRLEN((const FMT_TYPE *)(ppfs.fmtpos)));
-#if defined(L_vfprintf) && !defined(NDEBUG)
+#if defined(L__vfprintf_internal) && !defined(NDEBUG)
fprintf(stderr,"\nIMbS: \"%s\"\n\n", format);
#endif
count = -1;
@@ -1930,14 +1921,66 @@ int VFPRINTF (FILE * __restrict stream,
va_end(ppfs.arg); /* Need to clean up after va_copy! */
}
-/* #if defined(L_vfprintf) && defined(__UCLIBC_HAS_WCHAR__) */
+/* #if defined(L__vfprintf_internal) && defined(__UCLIBC_HAS_WCHAR__) */
/* DONE: */
/* #endif */
+ return count;
+}
+#endif /* defined(L__vfprintf_internal) || defined(L__vfwprintf_internal) */
+
+
+/**********************************************************************/
+#if defined(L_vfprintf) || defined(L_vfwprintf)
+
+/* This is just a wrapper around VFPRINTF_internal.
+ * Factoring out vfprintf internals allows:
+ * (1) vdprintf and vsnprintf don't need to setup fake locking,
+ * (2) __STDIO_STREAM_TRANS_TO_WRITE is not used in vfprintf internals,
+ * and thus fseek etc is not pulled in by vdprintf and vsnprintf.
+ *
+ * In order to not pull in fseek through fputs, OUTPUT() macro
+ * is using __stdio_fwrite (TODO: do the same for wide functions).
+ */
+#ifdef L_vfprintf
+#define VFPRINTF vfprintf
+#define VFPRINTF_internal _vfprintf_internal
+#define FMT_TYPE char
+#else
+#define VFPRINTF vfwprintf
+#define VFPRINTF_internal _vfwprintf_internal
+#define FMT_TYPE wchar_t
+#endif
+
+libc_hidden_proto(VFPRINTF)
+int VFPRINTF (FILE * __restrict stream,
+ register const FMT_TYPE * __restrict format,
+ va_list arg)
+{
+ int count;
+ __STDIO_AUTO_THREADLOCK_VAR;
+
+ __STDIO_AUTO_THREADLOCK(stream);
+
+ if
+#ifdef L_vfprintf
+ (!__STDIO_STREAM_IS_NARROW_WRITING(stream)
+ && __STDIO_STREAM_TRANS_TO_WRITE(stream, __FLAG_NARROW))
+#else
+ (!__STDIO_STREAM_IS_WIDE_WRITING(stream)
+ && __STDIO_STREAM_TRANS_TO_WRITE(stream, __FLAG_WIDE))
+#endif
+ {
+ count = -1;
+ } else {
+ count = VFPRINTF_internal(stream, format, arg);
+ }
+
__STDIO_AUTO_THREADUNLOCK(stream);
return count;
}
libc_hidden_def(VFPRINTF)
-#endif
+#endif /* defined(L_vfprintf) || defined(L_vfwprintf) */
+
/**********************************************************************/
diff --git a/libc/stdio/_vfprintf_internal.c b/libc/stdio/_vfprintf_internal.c
new file mode 100644
index 000000000..40bf39e26
--- /dev/null
+++ b/libc/stdio/_vfprintf_internal.c
@@ -0,0 +1,9 @@
+/* Copyright (C) 2004 Manuel Novoa III <mjn3@uclibc.org>
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ *
+ * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details.
+ */
+#define L__vfprintf_internal
+#include "_vfprintf.c"
diff --git a/libc/stdio/_vfwprintf_internal.c b/libc/stdio/_vfwprintf_internal.c
new file mode 100644
index 000000000..8584cf4ae
--- /dev/null
+++ b/libc/stdio/_vfwprintf_internal.c
@@ -0,0 +1,9 @@
+/* Copyright (C) 2004 Manuel Novoa III <mjn3@uclibc.org>
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ *
+ * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details.
+ */
+#define L__vfwprintf_internal
+#include "_vfprintf.c"
diff --git a/libc/stdio/vasprintf.c b/libc/stdio/vasprintf.c
index 7a34f6870..b7e2e0852 100644
--- a/libc/stdio/vasprintf.c
+++ b/libc/stdio/vasprintf.c
@@ -57,7 +57,7 @@ int vasprintf(char **__restrict buf, const char * __restrict format,
#else /* __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ */
- /* This implementation actually calls the printf machinery twice, but only
+ /* 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. */
diff --git a/libc/stdio/vdprintf.c b/libc/stdio/vdprintf.c
index 0c29eb109..9e1b22eaf 100644
--- a/libc/stdio/vdprintf.c
+++ b/libc/stdio/vdprintf.c
@@ -11,7 +11,6 @@
#include "_stdio.h"
#include <stdarg.h>
-libc_hidden_proto(vfprintf)
libc_hidden_proto(fflush_unlocked)
libc_hidden_proto(vdprintf)
@@ -54,7 +53,7 @@ int vdprintf(int filedes, const char * __restrict format, va_list arg)
#endif
f.__nextopen = NULL;
- rv = vfprintf(&f, format, arg);
+ rv = _vfprintf_internal(&f, format, arg);
#ifdef __STDIO_BUFFERS
/* If not buffering, then fflush is unnecessary. */
@@ -67,5 +66,4 @@ int vdprintf(int filedes, const char * __restrict format, va_list arg)
return rv;
}
-libc_hidden_def(vdprintf)
#endif
diff --git a/libc/stdio/vsnprintf.c b/libc/stdio/vsnprintf.c
index 51aaf43d0..4eef2c1a0 100644
--- a/libc/stdio/vsnprintf.c
+++ b/libc/stdio/vsnprintf.c
@@ -10,8 +10,6 @@
libc_hidden_proto(vsnprintf)
-libc_hidden_proto(vfprintf)
-
#ifdef __UCLIBC_MJN3_ONLY__
#warning WISHLIST: Implement vsnprintf for non-buffered and no custom stream case.
#endif /* __UCLIBC_MJN3_ONLY__ */
@@ -61,7 +59,7 @@ int vsnprintf(char *__restrict buf, size_t size,
__STDIO_STREAM_DISABLE_GETC(&f);
__STDIO_STREAM_ENABLE_PUTC(&f);
- rv = vfprintf(&f, format, arg);
+ rv = _vfprintf_internal(&f, format, arg);
if (size) {
if (f.__bufpos == f.__bufend) {
--f.__bufpos;
@@ -203,7 +201,7 @@ int vsnprintf(char *__restrict buf, size_t size,
#endif
f.__nextopen = NULL;
- rv = vfprintf(&f, format, arg);
+ rv = _vfprintf_internal(&f, format, arg);
return rv;
}
diff --git a/libc/stdio/vswprintf.c b/libc/stdio/vswprintf.c
index d09e08ac9..919ac2132 100644
--- a/libc/stdio/vswprintf.c
+++ b/libc/stdio/vswprintf.c
@@ -11,8 +11,6 @@
libc_hidden_proto(vswprintf)
-libc_hidden_proto(vfwprintf)
-
#ifndef __STDIO_BUFFERS
#warning Skipping vswprintf since no buffering!
#else /* __STDIO_BUFFERS */
@@ -56,7 +54,7 @@ int vswprintf(wchar_t *__restrict buf, size_t size,
__STDIO_STREAM_DISABLE_GETC(&f);
__STDIO_STREAM_DISABLE_PUTC(&f);
- rv = vfwprintf(&f, format, arg);
+ rv = _vfwprintf_internal(&f, format, arg);
/* NOTE: Return behaviour differs from snprintf... */
if (f.__bufpos == f.__bufend) {