Browse Source

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.

Denis Vlasenko 16 năm trước cách đây
mục cha
commit
36ac7bee0f

+ 2 - 1
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
 

+ 13 - 0
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>
@@ -430,6 +431,18 @@ extern size_t _wstdio_fwrite(const wchar_t *__restrict ws,
 		size_t n, FILE *__restrict stream) attribute_hidden;
 #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! */

+ 86 - 43
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) */
+
 /**********************************************************************/

+ 9 - 0
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"

+ 9 - 0
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"

+ 1 - 1
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. */

+ 1 - 3
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

+ 2 - 4
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;
 }

+ 1 - 3
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) {