2011-07-15 Yufeng Zhang <yufeng.zhang@arm.com>

* libc/stdio/vfwprintf.c (wcvt): Add a new parameter len of type
        int.  *length is set to the value of (rev - digits) regardless
        of whether _MB_CAPABLE is defined or not.  Replace BUF with len
        in calling _mbsnrtowcs_r and also in the loop where _MB_CAPABLE
        is not defined.
        (_VFWPRINTF_R): Call wcvt with an extra argument.  Call wcvt
        again with allocated new buffer if buf is not large enough for
        the conversion.
        * testsuite/newlib.stdio/stdio.exp: New.
        * testsuite/newlib.stdio/swprintf.c: Likewise.
This commit is contained in:
Jeff Johnston 2011-07-15 17:20:16 +00:00
parent c842ff73e7
commit 7890be6e7d
4 changed files with 85 additions and 9 deletions

View File

@ -1,3 +1,16 @@
2011-07-15 Yufeng Zhang <yufeng.zhang@arm.com>
* libc/stdio/vfwprintf.c (wcvt): Add a new parameter len of type
int. *length is set to the value of (rev - digits) regardless
of whether _MB_CAPABLE is defined or not. Replace BUF with len
in calling _mbsnrtowcs_r and also in the loop where _MB_CAPABLE
is not defined.
(_VFWPRINTF_R): Call wcvt with an extra argument. Call wcvt
again with allocated new buffer if buf is not large enough for
the conversion.
* testsuite/newlib.stdio/stdio.exp: New.
* testsuite/newlib.stdio/swprintf.c: Likewise.
2011-07-15 Matt Johnson <johnso87@crhc.illinois.edu> 2011-07-15 Matt Johnson <johnso87@crhc.illinois.edu>
* libc/stdio/fscanf.c (fscanf): Call _vfscanf_r instead of __svfscanf_r * libc/stdio/fscanf.c (fscanf): Call _vfscanf_r instead of __svfscanf_r

View File

@ -240,7 +240,7 @@ extern int _EXFUN(_ldcheck,(_LONG_DOUBLE *));
# endif /* !_NO_LONGDBL */ # endif /* !_NO_LONGDBL */
static wchar_t *wcvt(struct _reent *, _PRINTF_FLOAT_TYPE, int, int, wchar_t *, static wchar_t *wcvt(struct _reent *, _PRINTF_FLOAT_TYPE, int, int, wchar_t *,
int *, int, int *, wchar_t *); int *, int, int *, wchar_t *, int);
static int wexponent(wchar_t *, int, int); static int wexponent(wchar_t *, int, int);
@ -996,7 +996,23 @@ reswitch: switch (ch) {
flags |= FPT; flags |= FPT;
cp = wcvt (data, _fpvalue, prec, flags, &softsign, cp = wcvt (data, _fpvalue, prec, flags, &softsign,
&expt, ch, &ndig, cp); &expt, ch, &ndig, cp, BUF);
/* If buf is not large enough for the converted wchar_t
sequence, call wcvt again with a malloced new buffer.
This should happen fairly rarely.
*/
if (cp == buf && ndig > BUF && malloc_buf == NULL) {
if ((malloc_buf =
(wchar_t *)_malloc_r (data, ndig * sizeof (wchar_t)))
== NULL)
{
fp->_flags |= __SERR;
goto error;
}
cp = wcvt (data, _fpvalue, prec, flags, &softsign,
&expt, ch, &ndig, malloc_buf, ndig);
}
if (ch == L'g' || ch == L'G') { if (ch == L'g' || ch == L'G') {
if (expt <= -4 || expt > prec) if (expt <= -4 || expt > prec)
@ -1450,11 +1466,15 @@ error:
to whether trailing zeros must be included. Set *SIGN to nonzero to whether trailing zeros must be included. Set *SIGN to nonzero
if VALUE was negative. Set *DECPT to the exponent plus one. Set if VALUE was negative. Set *DECPT to the exponent plus one. Set
*LENGTH to the length of the returned string. CH must be one of *LENGTH to the length of the returned string. CH must be one of
[aAeEfFgG]; if it is [aA], then the return string lives in BUF, [aAeEfFgG]; different from vfprintf.c:cvt(), the return string
otherwise the return value shares the mprec reentrant storage. */ lives in BUF regardless of CH. LEN is the length of BUF, except
when CH is [aA], in which case LEN is not in use. If BUF is not
large enough for the converted string, only the first LEN number
of characters will be returned in BUF, but *LENGTH will be set to
the full length of the string before the truncation. */
static wchar_t * static wchar_t *
wcvt(struct _reent *data, _PRINTF_FLOAT_TYPE value, int ndigits, int flags, wcvt(struct _reent *data, _PRINTF_FLOAT_TYPE value, int ndigits, int flags,
wchar_t *sign, int *decpt, int ch, int *length, wchar_t *buf) wchar_t *sign, int *decpt, int ch, int *length, wchar_t *buf, int len)
{ {
int mode, dsgn; int mode, dsgn;
# ifdef _NO_LONGDBL # ifdef _NO_LONGDBL
@ -1548,12 +1568,13 @@ wcvt(struct _reent *data, _PRINTF_FLOAT_TYPE value, int ndigits, int flags,
while (rve < bp) while (rve < bp)
*rve++ = '0'; *rve++ = '0';
} }
*length = rve - digits; /* full length of the string */
#ifdef _MB_CAPABLE #ifdef _MB_CAPABLE
*length = _mbsnrtowcs_r (data, buf, (const char **) &digits, _mbsnrtowcs_r (data, buf, (const char **) &digits, *length,
rve - digits, BUF, NULL); len, NULL);
#else #else
*length = rve - digits; for (i = 0; i < *length && i < len; ++i)
for (i = 0; i < *length && i < BUF; ++i)
buf[i] = (wchar_t) digits[i]; buf[i] = (wchar_t) digits[i];
#endif #endif
return buf; return buf;

View File

@ -0,0 +1,12 @@
# Copyright (C) 2011 by ARM Ltd. All rights reserved.
#
# Permission to use, copy, modify, and distribute this software
# is freely granted, provided that this notice is preserved.
#
load_lib passfail.exp
set exclude_list {
}
newlib_pass_fail_all -x $exclude_list

View File

@ -0,0 +1,30 @@
/*
* Copyright (C) 2011 by ARM Ltd. All rights reserved.
*
* Permission to use, copy, modify, and distribute this software
* is freely granted, provided that this notice is preserved.
*/
#include <stdio.h>
#include <newlib.h>
#include <stdlib.h>
#include <wchar.h>
#include "check.h"
int main()
{
#if defined(INTEGER_ONLY) || defined(NO_FLOATING_POINT)
#else
char cbuf[512];
wchar_t wcbuf[512], wcbuf2[512];
double val = 1E+308;
snprintf(cbuf, 512, "%.*f", 3, val);
swprintf(wcbuf, 512, L"%.*f", 3, val);
mbstowcs(wcbuf2, cbuf, 512);
CHECK (wcscmp(wcbuf, wcbuf2) == 0);
#endif
exit (0);
}