Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--newlib/ChangeLog13
-rw-r--r--newlib/libc/stdio/vfwprintf.c39
-rw-r--r--newlib/testsuite/newlib.stdio/stdio.exp12
-rw-r--r--newlib/testsuite/newlib.stdio/swprintf.c30
4 files changed, 85 insertions, 9 deletions
diff --git a/newlib/ChangeLog b/newlib/ChangeLog
index 6cfa9fb27..383b42aa1 100644
--- a/newlib/ChangeLog
+++ b/newlib/ChangeLog
@@ -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>
* libc/stdio/fscanf.c (fscanf): Call _vfscanf_r instead of __svfscanf_r
diff --git a/newlib/libc/stdio/vfwprintf.c b/newlib/libc/stdio/vfwprintf.c
index 7c58d123c..79020f386 100644
--- a/newlib/libc/stdio/vfwprintf.c
+++ b/newlib/libc/stdio/vfwprintf.c
@@ -240,7 +240,7 @@ extern int _EXFUN(_ldcheck,(_LONG_DOUBLE *));
# endif /* !_NO_LONGDBL */
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);
@@ -996,7 +996,23 @@ reswitch: switch (ch) {
flags |= FPT;
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 (expt <= -4 || expt > prec)
@@ -1450,11 +1466,15 @@ error:
to whether trailing zeros must be included. Set *SIGN to nonzero
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
- [aAeEfFgG]; if it is [aA], then the return string lives in BUF,
- otherwise the return value shares the mprec reentrant storage. */
+ [aAeEfFgG]; different from vfprintf.c:cvt(), the return string
+ 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 *
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;
# ifdef _NO_LONGDBL
@@ -1548,12 +1568,13 @@ wcvt(struct _reent *data, _PRINTF_FLOAT_TYPE value, int ndigits, int flags,
while (rve < bp)
*rve++ = '0';
}
+
+ *length = rve - digits; /* full length of the string */
#ifdef _MB_CAPABLE
- *length = _mbsnrtowcs_r (data, buf, (const char **) &digits,
- rve - digits, BUF, NULL);
+ _mbsnrtowcs_r (data, buf, (const char **) &digits, *length,
+ len, NULL);
#else
- *length = rve - digits;
- for (i = 0; i < *length && i < BUF; ++i)
+ for (i = 0; i < *length && i < len; ++i)
buf[i] = (wchar_t) digits[i];
#endif
return buf;
diff --git a/newlib/testsuite/newlib.stdio/stdio.exp b/newlib/testsuite/newlib.stdio/stdio.exp
new file mode 100644
index 000000000..164cbf353
--- /dev/null
+++ b/newlib/testsuite/newlib.stdio/stdio.exp
@@ -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
diff --git a/newlib/testsuite/newlib.stdio/swprintf.c b/newlib/testsuite/newlib.stdio/swprintf.c
new file mode 100644
index 000000000..b925da487
--- /dev/null
+++ b/newlib/testsuite/newlib.stdio/swprintf.c
@@ -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);
+}