summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2009-06-16 17:44:20 +0000
committerCorinna Vinschen <corinna@vinschen.de>2009-06-16 17:44:20 +0000
commit1c5e84dd0870cd463d97f2b9183a807c3f711f2f (patch)
treed85b95c8902bcc48be771c159884be1e4e154713
parent1a99b6f85a123a1430ef41a3b2ae79eef7c0f768 (diff)
downloadcygnal-1c5e84dd0870cd463d97f2b9183a807c3f711f2f.tar.gz
cygnal-1c5e84dd0870cd463d97f2b9183a807c3f711f2f.tar.bz2
cygnal-1c5e84dd0870cd463d97f2b9183a807c3f711f2f.zip
* libc/stdio/vfprintf.c (_VFPRINTF_R): Use actual length of
radix char instead of assuming length 1. * libc/stdlib/gdtoa-gethex.c: Remove use of USE_LOCALE. (gethex): Allow multibyte decimal point. Fix compiler warnings due to different signedness of pointer types. * libc/stdlib/strtod.c: Remove use of USE_LOCALE. (_strtod_r): Allow multibyte decimal point. * libc/stdlib/wcstod.c (_wcstod_r): Evaluate correct wide char endptr position if the decimal point is a multibyte char.
-rw-r--r--newlib/ChangeLog12
-rw-r--r--newlib/libc/stdio/vfprintf.c11
-rw-r--r--newlib/libc/stdlib/gdtoa-gethex.c29
-rw-r--r--newlib/libc/stdlib/strtod.c11
-rw-r--r--newlib/libc/stdlib/wcstod.c23
5 files changed, 58 insertions, 28 deletions
diff --git a/newlib/ChangeLog b/newlib/ChangeLog
index af250d6af..1378cbb76 100644
--- a/newlib/ChangeLog
+++ b/newlib/ChangeLog
@@ -1,3 +1,15 @@
+2009-06-16 Corinna Vinschen <corinna@vinschen.de>
+
+ * libc/stdio/vfprintf.c (_VFPRINTF_R): Use actual length of
+ radix char instead of assuming length 1.
+ * libc/stdlib/gdtoa-gethex.c: Remove use of USE_LOCALE.
+ (gethex): Allow multibyte decimal point.
+ Fix compiler warnings due to different signedness of pointer types.
+ * libc/stdlib/strtod.c: Remove use of USE_LOCALE.
+ (_strtod_r): Allow multibyte decimal point.
+ * libc/stdlib/wcstod.c (_wcstod_r): Evaluate correct wide char
+ endptr position if the decimal point is a multibyte char.
+
2009-06-16 Craig Howland <howland@LGSInnovations.com>
* libc/ctype/local.h (__locale_charset): Add arguments to
diff --git a/newlib/libc/stdio/vfprintf.c b/newlib/libc/stdio/vfprintf.c
index 3497bac80..1d3119b4d 100644
--- a/newlib/libc/stdio/vfprintf.c
+++ b/newlib/libc/stdio/vfprintf.c
@@ -553,6 +553,7 @@ _DEFUN(_VFPRINTF_R, (data, fp, fmt0, ap),
char sign; /* sign prefix (' ', '+', '-', or \0) */
#ifdef FLOATING_POINT
char *decimal_point = _localeconv_r (data)->decimal_point;
+ size_t decp_len = strlen (decimal_point);
char softsign; /* temporary negative sign for floats */
union { int i; _PRINTF_FLOAT_TYPE fp; } _double_ = {0};
# define _fpvalue (_double_.fp)
@@ -1441,13 +1442,13 @@ number: if ((dprec = prec) >= 0)
/* kludge for __dtoa irregularity */
PRINT ("0", 1);
if (expt < ndig || flags & ALT) {
- PRINT (decimal_point, 1);
+ PRINT (decimal_point, decp_len);
PAD (ndig - 1, zeroes);
}
} else if (expt <= 0) {
PRINT ("0", 1);
if (expt || ndig || flags & ALT) {
- PRINT (decimal_point, 1);
+ PRINT (decimal_point, decp_len);
PAD (-expt, zeroes);
PRINT (cp, ndig);
}
@@ -1455,18 +1456,18 @@ number: if ((dprec = prec) >= 0)
PRINT (cp, ndig);
PAD (expt - ndig, zeroes);
if (flags & ALT)
- PRINT (decimal_point, 1);
+ PRINT (decimal_point, decp_len);
} else {
PRINT (cp, expt);
cp += expt;
- PRINT (decimal_point, 1);
+ PRINT (decimal_point, decp_len);
PRINT (cp, ndig - expt);
}
} else { /* 'a', 'A', 'e', or 'E' */
if (ndig > 1 || flags & ALT) {
PRINT (cp, 1);
cp++;
- PRINT (decimal_point, 1);
+ PRINT (decimal_point, decp_len);
if (_fpvalue) {
PRINT (cp, ndig - 1);
} else /* 0.[0..] */
diff --git a/newlib/libc/stdlib/gdtoa-gethex.c b/newlib/libc/stdlib/gdtoa-gethex.c
index 92f30fca0..c73b11c08 100644
--- a/newlib/libc/stdlib/gdtoa-gethex.c
+++ b/newlib/libc/stdlib/gdtoa-gethex.c
@@ -35,10 +35,7 @@ THIS SOFTWARE.
#include "mprec.h"
#include "gdtoa.h"
#include "gd_qnan.h"
-
-#ifdef USE_LOCALE
#include "locale.h"
-#endif
unsigned char hexdig[256];
@@ -151,11 +148,10 @@ _DEFUN(gethex, (ptr, sp, fpi, exp, bp, sign),
int esign, havedig, irv, k, n, nbits, up, zret;
__ULong L, lostbits, *x;
Long e, e1;
-#ifdef USE_LOCALE
- unsigned char decimalpoint = *localeconv()->decimal_point;
-#else
-#define decimalpoint '.'
-#endif
+ unsigned char *decimalpoint = (unsigned char *)
+ _localeconv_r (ptr)->decimal_point;
+ size_t decp_len = strlen ((const char *) decimalpoint);
+ unsigned char decp_end = decimalpoint[decp_len - 1];
if (!hexdig['0'])
hexdig_init();
@@ -170,9 +166,10 @@ _DEFUN(gethex, (ptr, sp, fpi, exp, bp, sign),
e = 0;
if (!hexdig[*s]) {
zret = 1;
- if (*s != decimalpoint)
+ if (strncmp ((const char *) s, (const char *) decimalpoint,
+ decp_len) != 0)
goto pcheck;
- decpt = ++s;
+ decpt = (s += decp_len);
if (!hexdig[*s])
goto pcheck;
while(*s == '0')
@@ -184,8 +181,10 @@ _DEFUN(gethex, (ptr, sp, fpi, exp, bp, sign),
}
while(hexdig[*s])
s++;
- if (*s == decimalpoint && !decpt) {
- decpt = ++s;
+ if (strncmp ((const char *) s, (const char *) decimalpoint,
+ decp_len) == 0
+ && !decpt) {
+ decpt = (s += decp_len);
while(hexdig[*s])
s++;
}
@@ -226,8 +225,12 @@ _DEFUN(gethex, (ptr, sp, fpi, exp, bp, sign),
n = 0;
L = 0;
while(s1 > s0) {
- if (*--s1 == decimalpoint)
+ if (*--s1 == decp_end && s1 - decp_len + 1 >= s0
+ && strncmp ((const char *) s1 - decp_len + 1,
+ (const char *) decimalpoint, decp_len) == 0) {
+ s1 -= decp_len - 1; /* Note the --s1 above! */
continue;
+ }
if (n == 32) {
*x++ = L;
L = 0;
diff --git a/newlib/libc/stdlib/strtod.c b/newlib/libc/stdlib/strtod.c
index fb4caf86f..755e6ec3c 100644
--- a/newlib/libc/stdlib/strtod.c
+++ b/newlib/libc/stdlib/strtod.c
@@ -122,9 +122,7 @@ THIS SOFTWARE.
/* #include <fenv.h> */
/* #endif */
-#ifdef USE_LOCALE
#include "locale.h"
-#endif
#ifdef IEEE_Arith
#ifndef NO_IEEE_Scale
@@ -307,14 +305,11 @@ _DEFUN (_strtod_r, (ptr, s00, se),
else if (nd < 16)
z = 10*z + c - '0';
nd0 = nd;
-#ifdef USE_LOCALE
- if (c == *localeconv()->decimal_point)
-#else
- if (c == '.')
-#endif
+ if (strncmp (s, _localeconv_r (ptr)->decimal_point,
+ strlen (_localeconv_r (ptr)->decimal_point)) == 0)
{
decpt = 1;
- c = *++s;
+ c = *(s += strlen (_localeconv_r (ptr)->decimal_point));
if (!nd) {
for(; c == '0'; c = *++s)
nz++;
diff --git a/newlib/libc/stdlib/wcstod.c b/newlib/libc/stdlib/wcstod.c
index 11fb922b1..6b8be5e73 100644
--- a/newlib/libc/stdlib/wcstod.c
+++ b/newlib/libc/stdlib/wcstod.c
@@ -116,8 +116,10 @@ Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>,
#include <_ansi.h>
#include <errno.h>
#include <stdlib.h>
+#include <string.h>
#include <wchar.h>
#include <wctype.h>
+#include <locale.h>
#include <math.h>
double
@@ -167,9 +169,26 @@ _DEFUN (_wcstod_r, (ptr, nptr, endptr),
* where it ended, count multibyte characters to find the
* corresponding position in the wide char string.
*/
- if (endptr != NULL)
- /* XXX Assume each wide char is one byte. */
+ if (endptr != NULL) {
+ /* The only valid multibyte char in a float converted by
+ strtod/wcstod is the radix char. What we do here is,
+ figure out if the radix char was in the valid leading
+ float sequence in the incoming string. If so, the
+ multibyte float string is strlen(radix char) - 1 bytes
+ longer than the incoming wide char string has characters.
+ To fix endptr, reposition end as if the radix char was
+ just one byte long. The resulting difference (end - buf)
+ is then equivalent to the number of valid wide characters
+ in the input string. */
+ len = strlen (_localeconv_r (ptr)->decimal_point);
+ if (len > 1) {
+ char *d = strstr (buf,
+ _localeconv_r (ptr)->decimal_point);
+ if (d && d < end)
+ end -= len - 1;
+ }
*endptr = (wchar_t *)nptr + (end - buf);
+ }
_free_r(ptr, buf);