From 409c27f83478e2962c446be23e104a97b3f5f2e0 Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Wed, 27 Mar 2013 09:38:39 +0000 Subject: [PATCH] * acconfig.h (_FVWRITE_IN_STREAMIO): Undefine. * newlib.hin (_FVWRITE_IN_STREAMIO): Undefine. * configure.in (--disable-newlib-fvwrite-in-streamio): New option. * configure: Regenerated. * libc/stdio/fputs.c (_fputs_r): Use _FVWRITE_IN_STREAMIO to control __sfvwrite_r. Add alternative implementation. * libc/stdio/fputws.c (_fputws_r): Ditto. * libc/stdio/fwrite.c (_fwrite_r): Ditto. * libc/stdio/puts.c (_puts_r): Ditto. * libc/stdio/vfprintf.c (__ssputs_r, __sfputs_r): New function. (_VFPRINTF_R): Use _FVWRITE_IN_STREAMIO to control vector buffer. (__SPRINT): Use _FVWRITE_IN_STREAMIO to control macro definition. * libc/stdio/vfwprintf.c (_VFWPRINTF_R): Use _FVWRITE_IN_STREAMIO to control vector buffer. --- newlib/ChangeLog | 17 ++++ newlib/acconfig.h | 3 + newlib/configure | 22 +++++ newlib/configure.in | 15 ++++ newlib/libc/stdio/fputs.c | 24 ++++++ newlib/libc/stdio/fputws.c | 30 ++++++- newlib/libc/stdio/fwrite.c | 25 ++++++ newlib/libc/stdio/puts.c | 28 +++++++ newlib/libc/stdio/vfprintf.c | 147 +++++++++++++++++++++++++++++++++- newlib/libc/stdio/vfwprintf.c | 51 ++++++++++-- newlib/newlib.hin | 3 + 11 files changed, 354 insertions(+), 11 deletions(-) diff --git a/newlib/ChangeLog b/newlib/ChangeLog index 9b667707c..2bc96c286 100644 --- a/newlib/ChangeLog +++ b/newlib/ChangeLog @@ -1,3 +1,20 @@ +2013-03-27 Bin Cheng + + * acconfig.h (_FVWRITE_IN_STREAMIO): Undefine. + * newlib.hin (_FVWRITE_IN_STREAMIO): Undefine. + * configure.in (--disable-newlib-fvwrite-in-streamio): New option. + * configure: Regenerated. + * libc/stdio/fputs.c (_fputs_r): Use _FVWRITE_IN_STREAMIO to + control __sfvwrite_r. Add alternative implementation. + * libc/stdio/fputws.c (_fputws_r): Ditto. + * libc/stdio/fwrite.c (_fwrite_r): Ditto. + * libc/stdio/puts.c (_puts_r): Ditto. + * libc/stdio/vfprintf.c (__ssputs_r, __sfputs_r): New function. + (_VFPRINTF_R): Use _FVWRITE_IN_STREAMIO to control vector buffer. + (__SPRINT): Use _FVWRITE_IN_STREAMIO to control macro definition. + * libc/stdio/vfwprintf.c (_VFWPRINTF_R): Use _FVWRITE_IN_STREAMIO + to control vector buffer. + 2013-03-26 Sebastian Huber * libc/stdio/local.h (_STDIO_WITH_THREAD_CANCELLATION_SUPPORT): diff --git a/newlib/acconfig.h b/newlib/acconfig.h index 53208811c..42b38d232 100644 --- a/newlib/acconfig.h +++ b/newlib/acconfig.h @@ -54,6 +54,9 @@ /* Define if the platform long double type is equal to double. */ #undef _LDBL_EQ_DBL + +/* Define if ivo supported in streamio. */ +#undef _FVWRITE_IN_STREAMIO @BOTTOM@ /* diff --git a/newlib/configure b/newlib/configure index 7a98e98a7..71499b57f 100755 --- a/newlib/configure +++ b/newlib/configure @@ -789,6 +789,7 @@ enable_newlib_iconv_to_encodings enable_newlib_iconv_external_ccs enable_newlib_atexit_dynamic_alloc enable_newlib_reent_small +enable_newlib_fvwrite_in_streamio enable_multilib enable_target_optspace enable_malloc_debugging @@ -1452,6 +1453,7 @@ Optional Features: --enable-newlib-iconv-external-ccs enable capabilities to load external CCS files for iconv --disable-newlib-atexit-alloc disable dynamic allocation of atexit entries --enable-newlib-reent-small enable small reentrant struct support + --disable-newlib-fvwrite-in-streamio disable iov in streamio --enable-multilib build many library versions (default) --enable-target-optspace optimize for space --enable-malloc-debugging indicate malloc debugging requested @@ -2351,6 +2353,19 @@ else newlib_reent_small= fi +# Check whether --enable-newlib-fvwrite-in-streamio was given. +if test "${enable_newlib_fvwrite_in_streamio+set}" = set; then : + enableval=$enable_newlib_fvwrite_in_streamio; if test "${newlib_fvwrite_in_streamio+set}" != set; then + case "${enableval}" in + yes) newlib_fvwrite_in_streamio=yes ;; + no) newlib_fvwrite_in_streamio=no ;; + *) as_fn_error $? "bad value ${enableval} for newlib-fvwrite-in-streamio option" "$LINENO" 5 ;; + esac + fi +else + newlib_fvwrite_in_streamio=yes +fi + # Make sure we can run config.sub. $SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || @@ -12232,6 +12247,13 @@ _ACEOF fi +if test "${newlib_fvwrite_in_streamio}" = "yes"; then +cat >>confdefs.h <<_ACEOF +#define _FVWRITE_IN_STREAMIO 1 +_ACEOF + +fi + if test "x${iconv_encodings}" != "x" \ || test "x${iconv_to_encodings}" != "x" \ diff --git a/newlib/configure.in b/newlib/configure.in index 35a5d070b..daabcf276 100644 --- a/newlib/configure.in +++ b/newlib/configure.in @@ -123,6 +123,17 @@ AC_ARG_ENABLE(newlib-reent-small, no) newlib_reent_small=no ;; *) AC_MSG_ERROR(bad value ${enableval} for newlib-reent-small option) ;; esac], [newlib_reent_small=])dnl + +dnl Support --disable-newlib-fvwrite-in-streamio +AC_ARG_ENABLE(newlib-fvwrite-in-streamio, +[ --disable-newlib-fvwrite-in-streamio disable iov in streamio], +[if test "${newlib_fvwrite_in_streamio+set}" != set; then + case "${enableval}" in + yes) newlib_fvwrite_in_streamio=yes ;; + no) newlib_fvwrite_in_streamio=no ;; + *) AC_MSG_ERROR(bad value ${enableval} for newlib-fvwrite-in-streamio option) ;; + esac + fi], [newlib_fvwrite_in_streamio=yes])dnl NEWLIB_CONFIGURE(.) @@ -312,6 +323,10 @@ fi if test "${newlib_atexit_dynamic_alloc}" = "yes"; then AC_DEFINE_UNQUOTED(_ATEXIT_DYNAMIC_ALLOC) fi + +if test "${newlib_fvwrite_in_streamio}" = "yes"; then +AC_DEFINE_UNQUOTED(_FVWRITE_IN_STREAMIO) +fi dnl dnl Parse --enable-newlib-iconv-encodings option argument diff --git a/newlib/libc/stdio/fputs.c b/newlib/libc/stdio/fputs.c index 6e623a530..de6357a05 100644 --- a/newlib/libc/stdio/fputs.c +++ b/newlib/libc/stdio/fputs.c @@ -77,6 +77,7 @@ _DEFUN(_fputs_r, (ptr, s, fp), char _CONST * s _AND FILE * fp) { +#ifdef _FVWRITE_IN_STREAMIO int result; struct __suio uio; struct __siov iov; @@ -93,6 +94,29 @@ _DEFUN(_fputs_r, (ptr, s, fp), result = __sfvwrite_r (ptr, fp, &uio); _newlib_flockfile_end (fp); return result; +#else + _CONST char *p = s; + + CHECK_INIT(ptr, fp); + + _newlib_flockfile_start (fp); + ORIENT (fp, -1); + /* Make sure we can write. */ + if (cantwrite (ptr, fp)) + goto error; + + while (*p) + { + if (__sputc_r (ptr, *p++, fp) == EOF) + goto error; + } + _newlib_flockfile_exit (fp); + return 0; + +error: + _newlib_flockfile_end (fp); + return EOF; +#endif } #ifndef _REENT_ONLY diff --git a/newlib/libc/stdio/fputws.c b/newlib/libc/stdio/fputws.c index c88111cb0..0893b3c33 100644 --- a/newlib/libc/stdio/fputws.c +++ b/newlib/libc/stdio/fputws.c @@ -84,6 +84,7 @@ _DEFUN(_fputws_r, (ptr, ws, fp), { size_t nbytes; char buf[BUFSIZ]; +#ifdef _FVWRITE_IN_STREAMIO struct __suio uio; struct __siov iov; @@ -108,8 +109,35 @@ _DEFUN(_fputws_r, (ptr, ws, fp), return (0); error: - _newlib_flockfile_end(fp); + _newlib_flockfile_end (fp); return (-1); +#else + _newlib_flockfile_start (fp); + ORIENT (fp, 1); + if (cantwrite (ptr, fp) != 0) + goto error; + + do + { + size_t i = 0; + nbytes = _wcsrtombs_r (ptr, buf, &ws, sizeof (buf), &fp->_mbstate); + if (nbytes == (size_t) -1) + goto error; + while (i < nbytes) + { + if (__sputc_r (ptr, buf[i], fp) == EOF) + goto error; + i++; + } + } + while (ws != NULL); + _newlib_flockfile_exit (fp); + return (0); + +error: + _newlib_flockfile_end (fp); + return (-1); +#endif } int diff --git a/newlib/libc/stdio/fwrite.c b/newlib/libc/stdio/fwrite.c index dc218050e..595e3ef84 100644 --- a/newlib/libc/stdio/fwrite.c +++ b/newlib/libc/stdio/fwrite.c @@ -103,6 +103,7 @@ _DEFUN(_fwrite_r, (ptr, buf, size, count, fp), FILE * fp) { size_t n; +#ifdef _FVWRITE_IN_STREAMIO struct __suio uio; struct __siov iov; @@ -128,6 +129,30 @@ _DEFUN(_fwrite_r, (ptr, buf, size, count, fp), } _newlib_flockfile_end (fp); return (n - uio.uio_resid) / size; +#else + size_t i = 0; + _CONST char *p = buf; + n = count * size; + CHECK_INIT (ptr, fp); + + _newlib_flockfile_start (fp); + ORIENT (fp, -1); + /* Make sure we can write. */ + if (cantwrite (ptr, fp)) + goto ret; + + while (i < n) + { + if (__sputc_r (ptr, p[i], fp) == EOF) + break; + + i++; + } + +ret: + _newlib_flockfile_end (fp); + return i / size; +#endif } #ifndef _REENT_ONLY diff --git a/newlib/libc/stdio/puts.c b/newlib/libc/stdio/puts.c index 7b8b34b01..4c60aaa4c 100644 --- a/newlib/libc/stdio/puts.c +++ b/newlib/libc/stdio/puts.c @@ -78,6 +78,7 @@ _DEFUN(_puts_r, (ptr, s), struct _reent *ptr _AND _CONST char * s) { +#ifdef _FVWRITE_IN_STREAMIO int result; size_t c = strlen (s); struct __suio uio; @@ -99,6 +100,33 @@ _DEFUN(_puts_r, (ptr, s), result = (__sfvwrite_r (ptr, fp, &uio) ? EOF : '\n'); _newlib_flockfile_end (fp); return result; +#else + int result = EOF; + const char *p = s; + FILE *fp; + _REENT_SMALL_CHECK_INIT (ptr); + + fp = _stdout_r (ptr); + _newlib_flockfile_start (fp); + ORIENT (fp, -1); + /* Make sure we can write. */ + if (cantwrite (ptr, fp)) + goto err; + + while (*p) + { + if (__sputc_r (ptr, *p++, fp) == EOF) + goto err; + } + if (__sputc_r (ptr, '\n', fp) == EOF) + goto err; + + result = '\n'; + +err: + _newlib_flockfile_end (fp); + return result; +#endif } #ifndef _REENT_ONLY diff --git a/newlib/libc/stdio/vfprintf.c b/newlib/libc/stdio/vfprintf.c index 76a445b5f..c6c20ebdb 100644 --- a/newlib/libc/stdio/vfprintf.c +++ b/newlib/libc/stdio/vfprintf.c @@ -178,9 +178,17 @@ static char *rcsid = "$Id$"; #endif #ifdef STRING_ONLY -#define __SPRINT __ssprint_r +# ifdef _FVWRITE_IN_STREAMIO +# define __SPRINT __ssprint_r +# else +# define __SPRINT __ssputs_r +# endif #else -#define __SPRINT __sprint_r +# ifdef _FVWRITE_IN_STREAMIO +# define __SPRINT __sprint_r +# else +# define __SPRINT __sfputs_r +# endif #endif /* The __sprint_r/__ssprint_r functions are shared between all versions of @@ -188,6 +196,76 @@ static char *rcsid = "$Id$"; the INTEGER_ONLY versions here. */ #ifdef STRING_ONLY #ifdef INTEGER_ONLY +#ifndef _FVWRITE_IN_STREAMIO +int +_DEFUN(__ssputs_r, (ptr, fp, buf, len), + struct _reent *ptr _AND + FILE *fp _AND + _CONST char *buf _AND + size_t len) +{ + register int w; + + w = fp->_w; + if (len >= w && fp->_flags & (__SMBF | __SOPT)) { + /* must be asprintf family */ + unsigned char *str; + int curpos = (fp->_p - fp->_bf._base); + /* Choose a geometric growth factor to avoid + * quadratic realloc behavior, but use a rate less + * than (1+sqrt(5))/2 to accomodate malloc + * overhead. asprintf EXPECTS us to overallocate, so + * that it can add a trailing \0 without + * reallocating. The new allocation should thus be + * max(prev_size*1.5, curpos+len+1). */ + int newsize = fp->_bf._size * 3 / 2; + if (newsize < curpos + len + 1) + newsize = curpos + len + 1; + if (fp->_flags & __SOPT) + { + /* asnprintf leaves original buffer alone. */ + str = (unsigned char *)_malloc_r (ptr, newsize); + if (!str) + { + ptr->_errno = ENOMEM; + goto err; + } + memcpy (str, fp->_bf._base, curpos); + fp->_flags = (fp->_flags & ~__SOPT) | __SMBF; + } + else + { + str = (unsigned char *)_realloc_r (ptr, fp->_bf._base, + newsize); + if (!str) { + /* Free unneeded buffer. */ + _free_r (ptr, fp->_bf._base); + /* Ensure correct errno, even if free + * changed it. */ + ptr->_errno = ENOMEM; + goto err; + } + } + fp->_bf._base = str; + fp->_p = str + curpos; + fp->_bf._size = newsize; + w = len; + fp->_w = newsize - curpos; + } + if (len < w) + w = len; + (void)memmove ((_PTR) fp->_p, (_PTR) buf, (size_t) (w)); + fp->_w -= w; + fp->_p += w; + + return 0; + +err: + fp->_flags |= __SERR; + return EOF; +} +#endif + int _DEFUN(__ssprint_r, (ptr, fp, uio), struct _reent *ptr _AND @@ -280,11 +358,42 @@ err: return EOF; } #else /* !INTEGER_ONLY */ +#ifndef _FVWRITE_IN_STREAMIO +int __ssputs_r (struct _reent *, FILE *, _CONST char *, size_t); +#endif int __ssprint_r (struct _reent *, FILE *, register struct __suio *); #endif /* !INTEGER_ONLY */ #else /* !STRING_ONLY */ #ifdef INTEGER_ONLY + +#ifndef _FVWRITE_IN_STREAMIO +int +_DEFUN(__sfputs_r, (ptr, fp, buf, len), + struct _reent *ptr _AND + FILE *fp _AND + _CONST char *buf _AND + size_t len) +{ + register int i; + + if (fp->_flags2 & __SWID) { + wchar_t *p; + + p = (wchar_t *) buf; + for (i = 0; i < (len / sizeof (wchar_t)); i++) { + if (_fputwc_r (ptr, p[i], fp) == WEOF) + return -1; + } + } else { + for (i = 0; i < len; i++) { + if (_fputc_r (ptr, buf[i], fp) == EOF) + return -1; + } + } + return (0); +} +#endif /* * Flush out all the vectors defined by the given uio, * then reset it so that it can be reused. @@ -326,6 +435,9 @@ out: return (err); } #else /* !INTEGER_ONLY */ +#ifndef _FVWRITE_IN_STREAMIO +int __sfputs_r (struct _reent *, FILE *, _CONST char *buf, size_t); +#endif int __sprint_r (struct _reent *, FILE *, register struct __suio *); #endif /* !INTEGER_ONLY */ @@ -550,7 +662,6 @@ _DEFUN(_VFPRINTF_R, (data, fp, fmt0, ap), register int ch; /* character from fmt */ register int n, m; /* handy integers (short term usage) */ register char *cp; /* handy char pointer (short term usage) */ - register struct __siov *iovp;/* for PRINT macro */ register int flags; /* flags as above */ char *fmt_anchor; /* current format spec being processed */ #ifndef _NO_POS_ARGS @@ -597,9 +708,12 @@ _DEFUN(_VFPRINTF_R, (data, fp, fmt0, ap), int realsz; /* field size expanded by dprec */ int size; /* size of converted field or string */ char *xdigs = NULL; /* digits for [xX] conversion */ +#ifdef _FVWRITE_IN_STREAMIO #define NIOV 8 struct __suio uio; /* output information: summary */ struct __siov iov[NIOV];/* ... and individual io vectors */ + register struct __siov *iovp;/* for PRINT macro */ +#endif char buf[BUF]; /* space for %c, %S, %[diouxX], %[aA] */ char ox[2]; /* space for 0x hex-prefix */ #ifdef _MB_CAPABLE @@ -625,6 +739,7 @@ _DEFUN(_VFPRINTF_R, (data, fp, fmt0, ap), /* * BEWARE, these `goto error' on error, and PAD uses `n'. */ +#ifdef _FVWRITE_IN_STREAMIO #define PRINT(ptr, len) { \ iovp->iov_base = (ptr); \ iovp->iov_len = (len); \ @@ -659,6 +774,30 @@ _DEFUN(_VFPRINTF_R, (data, fp, fmt0, ap), uio.uio_iovcnt = 0; \ iovp = iov; \ } +#else +#define PRINT(ptr, len) { \ + if (__SPRINT (data, fp, (ptr), (len)) == EOF) \ + goto error; \ +} +#define PAD(howmany, with) { \ + if ((n = (howmany)) > 0) { \ + while (n > PADSIZE) { \ + PRINT (with, PADSIZE); \ + n -= PADSIZE; \ + } \ + PRINT (with, n); \ + } \ +} +#define PRINTANDPAD(p, ep, len, with) { \ + int n = (ep) - (p); \ + if (n > (len)) \ + n = (len); \ + if (n > 0) \ + PRINT((p), n); \ + PAD((len) - (n > 0 ? n : 0), (with)); \ +} +#define FLUSH() +#endif /* Macros to support positional arguments */ #ifndef _NO_POS_ARGS @@ -741,9 +880,11 @@ _DEFUN(_VFPRINTF_R, (data, fp, fmt0, ap), #endif /* STRING_ONLY */ fmt = (char *)fmt0; +#ifdef _FVWRITE_IN_STREAMIO uio.uio_iov = iovp = iov; uio.uio_resid = 0; uio.uio_iovcnt = 0; +#endif ret = 0; #ifndef _NO_POS_ARGS arg_index = 0; diff --git a/newlib/libc/stdio/vfwprintf.c b/newlib/libc/stdio/vfwprintf.c index dfa8fde2f..5860147ec 100644 --- a/newlib/libc/stdio/vfwprintf.c +++ b/newlib/libc/stdio/vfwprintf.c @@ -150,13 +150,21 @@ SEEALSO int _EXFUN(_VFWPRINTF_R, (struct _reent *, FILE *, _CONST wchar_t *, va_list)); /* Defined in vfprintf.c. */ -#ifdef STRING_ONLY -#define __SPRINT __ssprint_r -#else -#define __SPRINT __sprint_r -#endif +#ifdef _FVWRITE_IN_STREAMIO +# ifdef STRING_ONLY +# define __SPRINT __ssprint_r +# else +# define __SPRINT __sprint_r +# endif int _EXFUN(__SPRINT, (struct _reent *, FILE *, register struct __suio *)); - +#else +# ifdef STRING_ONLY +# define __SPRINT __ssputs_r +# else +# define __SPRINT __sfputs_r +# endif +int _EXFUN(__SPRINT, (struct _reent *, FILE *, _CONST char *, size_t)); +#endif #ifndef STRING_ONLY /* * Helper function for `fprintf to unbuffered unix file': creates a @@ -377,7 +385,6 @@ _DEFUN(_VFWPRINTF_R, (data, fp, fmt0, ap), register wint_t ch; /* character from fmt */ register int n, m; /* handy integers (short term usage) */ register wchar_t *cp; /* handy char pointer (short term usage) */ - register struct __siov *iovp;/* for PRINT macro */ register int flags; /* flags as above */ wchar_t *fmt_anchor; /* current format spec being processed */ #ifndef _NO_POS_ARGS @@ -426,9 +433,12 @@ _DEFUN(_VFWPRINTF_R, (data, fp, fmt0, ap), int realsz; /* field size expanded by dprec */ int size = 0; /* size of converted field or string */ wchar_t *xdigs = NULL; /* digits for [xX] conversion */ +#ifdef _FVWRITE_IN_STREAMIO #define NIOV 8 struct __suio uio; /* output information: summary */ struct __siov iov[NIOV];/* ... and individual io vectors */ + register struct __siov *iovp;/* for PRINT macro */ +#endif wchar_t buf[BUF]; /* space for %c, %ls/%S, %[diouxX], %[aA] */ wchar_t ox[2]; /* space for 0x hex-prefix */ wchar_t *malloc_buf = NULL;/* handy pointer for malloced buffers */ @@ -469,6 +479,7 @@ _DEFUN(_VFWPRINTF_R, (data, fp, fmt0, ap), /* * BEWARE, these `goto error' on error, and PAD uses `n'. */ +#ifdef _FVWRITE_IN_STREAMIO #define PRINT(ptr, len) { \ iovp->iov_base = (char *) (ptr); \ iovp->iov_len = (len) * sizeof (wchar_t); \ @@ -503,6 +514,30 @@ _DEFUN(_VFWPRINTF_R, (data, fp, fmt0, ap), uio.uio_iovcnt = 0; \ iovp = iov; \ } +#else +#define PRINT(ptr, len) { \ + if (__SPRINT (data, fp, (_CONST char *)(ptr), (len) * sizeof (wchar_t)) == EOF) \ + goto error; \ +} +#define PAD(howmany, with) { \ + if ((n = (howmany)) > 0) { \ + while (n > PADSIZE) { \ + PRINT (with, PADSIZE); \ + n -= PADSIZE; \ + } \ + PRINT (with, n); \ + } \ +} +#define PRINTANDPAD(p, ep, len, with) { \ + int n = (ep) - (p); \ + if (n > (len)) \ + n = (len); \ + if (n > 0) \ + PRINT((p), n); \ + PAD((len) - (n > 0 ? n : 0), (with)); \ +} +#define FLUSH() +#endif /* Macros to support positional arguments */ #ifndef _NO_POS_ARGS @@ -585,9 +620,11 @@ _DEFUN(_VFWPRINTF_R, (data, fp, fmt0, ap), #endif /* STRING_ONLY */ fmt = (wchar_t *)fmt0; +#ifdef _FVWRITE_IN_STREAMIO uio.uio_iov = iovp = iov; uio.uio_resid = 0; uio.uio_iovcnt = 0; +#endif ret = 0; #ifndef _NO_POS_ARGS arg_index = 0; diff --git a/newlib/newlib.hin b/newlib/newlib.hin index 3c5338685..74218c73e 100644 --- a/newlib/newlib.hin +++ b/newlib/newlib.hin @@ -57,6 +57,9 @@ /* True if long double supported and it is equal to double. */ #undef _LDBL_EQ_DBL + +/* Define if ivo supported in streamio. */ +#undef _FVWRITE_IN_STREAMIO /* * Iconv encodings enabled ("to" direction)