* 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.
This commit is contained in:
Corinna Vinschen 2009-06-16 17:44:20 +00:00
parent 1a99b6f85a
commit 1c5e84dd08
5 changed files with 58 additions and 28 deletions

View File

@ -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> 2009-06-16 Craig Howland <howland@LGSInnovations.com>
* libc/ctype/local.h (__locale_charset): Add arguments to * libc/ctype/local.h (__locale_charset): Add arguments to

View File

@ -553,6 +553,7 @@ _DEFUN(_VFPRINTF_R, (data, fp, fmt0, ap),
char sign; /* sign prefix (' ', '+', '-', or \0) */ char sign; /* sign prefix (' ', '+', '-', or \0) */
#ifdef FLOATING_POINT #ifdef FLOATING_POINT
char *decimal_point = _localeconv_r (data)->decimal_point; char *decimal_point = _localeconv_r (data)->decimal_point;
size_t decp_len = strlen (decimal_point);
char softsign; /* temporary negative sign for floats */ char softsign; /* temporary negative sign for floats */
union { int i; _PRINTF_FLOAT_TYPE fp; } _double_ = {0}; union { int i; _PRINTF_FLOAT_TYPE fp; } _double_ = {0};
# define _fpvalue (_double_.fp) # define _fpvalue (_double_.fp)
@ -1441,13 +1442,13 @@ number: if ((dprec = prec) >= 0)
/* kludge for __dtoa irregularity */ /* kludge for __dtoa irregularity */
PRINT ("0", 1); PRINT ("0", 1);
if (expt < ndig || flags & ALT) { if (expt < ndig || flags & ALT) {
PRINT (decimal_point, 1); PRINT (decimal_point, decp_len);
PAD (ndig - 1, zeroes); PAD (ndig - 1, zeroes);
} }
} else if (expt <= 0) { } else if (expt <= 0) {
PRINT ("0", 1); PRINT ("0", 1);
if (expt || ndig || flags & ALT) { if (expt || ndig || flags & ALT) {
PRINT (decimal_point, 1); PRINT (decimal_point, decp_len);
PAD (-expt, zeroes); PAD (-expt, zeroes);
PRINT (cp, ndig); PRINT (cp, ndig);
} }
@ -1455,18 +1456,18 @@ number: if ((dprec = prec) >= 0)
PRINT (cp, ndig); PRINT (cp, ndig);
PAD (expt - ndig, zeroes); PAD (expt - ndig, zeroes);
if (flags & ALT) if (flags & ALT)
PRINT (decimal_point, 1); PRINT (decimal_point, decp_len);
} else { } else {
PRINT (cp, expt); PRINT (cp, expt);
cp += expt; cp += expt;
PRINT (decimal_point, 1); PRINT (decimal_point, decp_len);
PRINT (cp, ndig - expt); PRINT (cp, ndig - expt);
} }
} else { /* 'a', 'A', 'e', or 'E' */ } else { /* 'a', 'A', 'e', or 'E' */
if (ndig > 1 || flags & ALT) { if (ndig > 1 || flags & ALT) {
PRINT (cp, 1); PRINT (cp, 1);
cp++; cp++;
PRINT (decimal_point, 1); PRINT (decimal_point, decp_len);
if (_fpvalue) { if (_fpvalue) {
PRINT (cp, ndig - 1); PRINT (cp, ndig - 1);
} else /* 0.[0..] */ } else /* 0.[0..] */

View File

@ -35,10 +35,7 @@ THIS SOFTWARE.
#include "mprec.h" #include "mprec.h"
#include "gdtoa.h" #include "gdtoa.h"
#include "gd_qnan.h" #include "gd_qnan.h"
#ifdef USE_LOCALE
#include "locale.h" #include "locale.h"
#endif
unsigned char hexdig[256]; 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; int esign, havedig, irv, k, n, nbits, up, zret;
__ULong L, lostbits, *x; __ULong L, lostbits, *x;
Long e, e1; Long e, e1;
#ifdef USE_LOCALE unsigned char *decimalpoint = (unsigned char *)
unsigned char decimalpoint = *localeconv()->decimal_point; _localeconv_r (ptr)->decimal_point;
#else size_t decp_len = strlen ((const char *) decimalpoint);
#define decimalpoint '.' unsigned char decp_end = decimalpoint[decp_len - 1];
#endif
if (!hexdig['0']) if (!hexdig['0'])
hexdig_init(); hexdig_init();
@ -170,9 +166,10 @@ _DEFUN(gethex, (ptr, sp, fpi, exp, bp, sign),
e = 0; e = 0;
if (!hexdig[*s]) { if (!hexdig[*s]) {
zret = 1; zret = 1;
if (*s != decimalpoint) if (strncmp ((const char *) s, (const char *) decimalpoint,
decp_len) != 0)
goto pcheck; goto pcheck;
decpt = ++s; decpt = (s += decp_len);
if (!hexdig[*s]) if (!hexdig[*s])
goto pcheck; goto pcheck;
while(*s == '0') while(*s == '0')
@ -184,8 +181,10 @@ _DEFUN(gethex, (ptr, sp, fpi, exp, bp, sign),
} }
while(hexdig[*s]) while(hexdig[*s])
s++; s++;
if (*s == decimalpoint && !decpt) { if (strncmp ((const char *) s, (const char *) decimalpoint,
decpt = ++s; decp_len) == 0
&& !decpt) {
decpt = (s += decp_len);
while(hexdig[*s]) while(hexdig[*s])
s++; s++;
} }
@ -226,8 +225,12 @@ _DEFUN(gethex, (ptr, sp, fpi, exp, bp, sign),
n = 0; n = 0;
L = 0; L = 0;
while(s1 > s0) { 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; continue;
}
if (n == 32) { if (n == 32) {
*x++ = L; *x++ = L;
L = 0; L = 0;

View File

@ -122,9 +122,7 @@ THIS SOFTWARE.
/* #include <fenv.h> */ /* #include <fenv.h> */
/* #endif */ /* #endif */
#ifdef USE_LOCALE
#include "locale.h" #include "locale.h"
#endif
#ifdef IEEE_Arith #ifdef IEEE_Arith
#ifndef NO_IEEE_Scale #ifndef NO_IEEE_Scale
@ -307,14 +305,11 @@ _DEFUN (_strtod_r, (ptr, s00, se),
else if (nd < 16) else if (nd < 16)
z = 10*z + c - '0'; z = 10*z + c - '0';
nd0 = nd; nd0 = nd;
#ifdef USE_LOCALE if (strncmp (s, _localeconv_r (ptr)->decimal_point,
if (c == *localeconv()->decimal_point) strlen (_localeconv_r (ptr)->decimal_point)) == 0)
#else
if (c == '.')
#endif
{ {
decpt = 1; decpt = 1;
c = *++s; c = *(s += strlen (_localeconv_r (ptr)->decimal_point));
if (!nd) { if (!nd) {
for(; c == '0'; c = *++s) for(; c == '0'; c = *++s)
nz++; nz++;

View File

@ -116,8 +116,10 @@ Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>,
#include <_ansi.h> #include <_ansi.h>
#include <errno.h> #include <errno.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
#include <wchar.h> #include <wchar.h>
#include <wctype.h> #include <wctype.h>
#include <locale.h>
#include <math.h> #include <math.h>
double double
@ -167,9 +169,26 @@ _DEFUN (_wcstod_r, (ptr, nptr, endptr),
* where it ended, count multibyte characters to find the * where it ended, count multibyte characters to find the
* corresponding position in the wide char string. * corresponding position in the wide char string.
*/ */
if (endptr != NULL) if (endptr != NULL) {
/* XXX Assume each wide char is one byte. */ /* 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); *endptr = (wchar_t *)nptr + (end - buf);
}
_free_r(ptr, buf); _free_r(ptr, buf);