Index: libc/stdio/vfprintf.c =================================================================== RCS file: /cvs/src/src/newlib/libc/stdio/vfprintf.c,v retrieving revision 1.56 diff -u -p -r1.56 vfprintf.c --- libc/stdio/vfprintf.c 8 May 2007 03:59:13 -0000 1.56 +++ libc/stdio/vfprintf.c 10 May 2007 13:03:14 -0000 @@ -229,34 +229,41 @@ _DEFUN(__sbprintf, (rptr, fp, fmt, ap), #ifdef FLOATING_POINT -#include -#include -#include "floatio.h" +# include +# include -#if ((MAXEXP+MAXFRACT+1) > MB_LEN_MAX) -# define BUF (MAXEXP+MAXFRACT+1) /* + decimal point */ -#else -# define BUF MB_LEN_MAX -#endif - -#define DEFPREC 6 +/* For %La, an exponent of 15 bits occupies the exponent character, a + sign, and up to 5 digits. */ +# define MAXEXP 7 +# define DEFPREC 6 -#ifdef _NO_LONGDBL +# ifdef _NO_LONGDBL static char * _EXFUN(cvt, (struct _reent *, double, int, int, char *, int *, int, int *)); -#else +# else static char * _EXFUN(cvt, (struct _reent *, _LONG_DOUBLE, int, int, char *, int *, int, int *)); extern int _EXFUN(_ldcheck,(_LONG_DOUBLE *)); -#endif +# endif static int _EXFUN(exponent, (char *, int, int)); -#else /* no FLOATING_POINT */ +#endif /* FLOATING_POINT */ +/* BUF must be big enough for the maximum %#llo (assuming long long is + at most 64 bits, this would be 23 characters), the maximum + multibyte character, and the maximum precision of %La (assuming + long double is at most 128 bits with 113 bits of mantissa, this + would be 31 characters). %e, %f, and %g use reentrant storage + shared with mprec. All other formats that use buf get by with + fewer characters. Making BUF slightly bigger reduces the need for + malloc in %a and %S, when large precision or long strings are + processed. */ #define BUF 40 - -#endif /* FLOATING_POINT */ +#if defined _MB_CAPABLE && MB_LEN_MAX > BUF +# undef BUF +# define BUF MB_LEN_MAX +#endif #ifndef _NO_LONGLONG #define quad_t long long @@ -375,20 +382,20 @@ _DEFUN(_VFPRINTF_R, (data, fp, fmt0, ap) int prec; /* precision from format (%.3d), or -1 */ char sign; /* sign prefix (' ', '+', '-', or \0) */ #ifdef FLOATING_POINT - char *decimal_point = localeconv()->decimal_point; + char *decimal_point = _localeconv_r (data)->decimal_point; char softsign; /* temporary negative sign for floats */ -#ifdef _NO_LONGDBL +# ifdef _NO_LONGDBL union { int i; double d; } _double_ = {0}; - #define _fpvalue (_double_.d) -#else +# define _fpvalue (_double_.d) +# else union { int i; _LONG_DOUBLE ld; } _long_double_ = {0}; - #define _fpvalue (_long_double_.ld) - int tmp; -#endif +# define _fpvalue (_long_double_.ld) + int tmp; +# endif int expt; /* integer value of exponent */ int expsize = 0; /* character count for expstr */ int ndig = 0; /* actual number of digits returned by cvt */ - char expstr[7]; /* buffer for exponent string */ + char expstr[MAXEXP]; /* buffer for exponent string */ #endif u_quad_t _uquad; /* integer arguments %[diouxX] */ enum { OCT, DEC, HEX } base;/* base for [diouxX] conversion */ @@ -399,7 +406,7 @@ _DEFUN(_VFPRINTF_R, (data, fp, fmt0, ap) #define NIOV 8 struct __suio uio; /* output information: summary */ struct __siov iov[NIOV];/* ... and individual io vectors */ - char buf[BUF]; /* space for %c, %[diouxX], %[eEfgG] */ + char buf[BUF]; /* space for %c, %S, %[diouxX], %[aA] */ char ox[2]; /* space for 0x hex-prefix */ #ifdef _MB_CAPABLE wchar_t wc; @@ -1006,31 +1013,35 @@ reswitch: switch (ch) { } } else { - if ((size = (int)_wcsrtombs_r (data, + if ((size = (int)_wcsrtombs_r (data, NULL, &wcp, 0, &ps)) == -1) { fp->_flags |= __SERR; goto error; } wcp = (_CONST wchar_t *)cp; } - + if (size == 0) break; - - if ((malloc_buf = - (char *)_malloc_r (data, size + 1)) == NULL) { - fp->_flags |= __SERR; - goto error; - } - + + if (size >= BUF) { + if ((malloc_buf = + (char *)_malloc_r (data, size + 1)) + == NULL) { + fp->_flags |= __SERR; + goto error; + } + cp = malloc_buf; + } else + cp = buf; + /* Convert widechar string to multibyte string. */ memset ((_PTR)&ps, '\0', sizeof (mbstate_t)); - if (_wcsrtombs_r (data, malloc_buf, - &wcp, size, &ps) != size) { + if (_wcsrtombs_r (data, cp, + &wcp, size, &ps) != size) { fp->_flags |= __SERR; goto error; } - cp = malloc_buf; cp[size] = '\0'; } #endif /* _MB_CAPABLE */ @@ -1216,18 +1227,18 @@ number: if ((dprec = prec) >= 0) PRINT (cp, ndig); PAD (expt - ndig, zeroes); if (flags & ALT) - PRINT (".", 1); + PRINT (decimal_point, 1); } else { PRINT (cp, expt); cp += expt; - PRINT (".", 1); + PRINT (decimal_point, 1); PRINT (cp, ndig - expt); } } else { /* 'e' or 'E' */ if (ndig > 1 || flags & ALT) { - ox[0] = *cp++; - ox[1] = '.'; - PRINT (ox, 2); + PRINT (cp, 1); + cp++; + PRINT (decimal_point, 1); if (_fpvalue) { PRINT (cp, ndig - 1); } else /* 0.[0..] */ @@ -1370,7 +1381,7 @@ _DEFUN(exponent, (p0, exp, fmtch), int fmtch) { register char *p, *t; - char expbuf[40]; + char expbuf[MAXEXP]; p = p0; *p++ = fmtch; @@ -1380,13 +1391,13 @@ _DEFUN(exponent, (p0, exp, fmtch), } else *p++ = '+'; - t = expbuf + 40; + t = expbuf + MAXEXP; if (exp > 9) { do { *--t = to_char (exp % 10); } while ((exp /= 10) > 9); *--t = to_char (exp); - for (; t < expbuf + 40; *p++ = *t++); + for (; t < expbuf + MAXEXP; *p++ = *t++); } else { *p++ = '0';