diff --git a/ChangeLog b/ChangeLog index 563f16f24b..a8e575ffdf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2005-09-27 Ulrich Drepper + + [BZ #1230] + * stdlib/strtod_l.c (STRNCASECMP): Always use C locale object. + (TOLOWER_C): Define. Use it when recognizing inf and nan. + * stdlib/Makefile (tests): Add bug-strtod2. + * stdlib/bug-strtod2.c: New file. + 2005-09-21 Ralf Wildenhues [BZ #1361] diff --git a/stdlib/Depend b/stdlib/Depend new file mode 100644 index 0000000000..f3e1156a4e --- /dev/null +++ b/stdlib/Depend @@ -0,0 +1 @@ +localedata diff --git a/stdlib/Makefile b/stdlib/Makefile index 509a7b2228..9a9ff8bd45 100644 --- a/stdlib/Makefile +++ b/stdlib/Makefile @@ -63,7 +63,7 @@ tests := tst-strtol tst-strtod testmb testrand testsort testdiv \ test-canon test-canon2 tst-strtoll tst-environ \ tst-xpg-basename tst-random tst-random2 tst-bsearch \ tst-limits tst-rand48 bug-strtod tst-setcontext \ - test-a64l tst-qsort tst-system testmb2 + test-a64l tst-qsort tst-system testmb2 bug-strtod2 include ../Makeconfig diff --git a/stdlib/bug-strtod2.c b/stdlib/bug-strtod2.c new file mode 100644 index 0000000000..a1f037cdc8 --- /dev/null +++ b/stdlib/bug-strtod2.c @@ -0,0 +1,46 @@ +#include +#include +#include +#include + +static const char *tests[] = + { + "inf", "Inf", "iNf", "inF", "INf", "iNF", "INF", "InF", + "infinity", "Infinity", "InfInity", "INFINITY" + }; +#define ntests (sizeof (tests) / sizeof (tests[0])) + +static int +do_test (void) +{ + /* The Turkish locale is notorious because tolower() maps 'I' to the + dotless lowercase 'i' and toupper() maps 'i' to an 'I' with a dot + above. */ + if (setlocale (LC_ALL, "tr_TR.UTF-8") == NULL) + { + puts ("cannot set locale"); + return 0; + } + + int res = 0; + for (int i = 0; i < ntests; ++i) + { + char *endp; + double d = strtod (tests[i], &endp); + if (*endp != '\0') + { + printf ("did not consume all of '%s'\n", tests[i]); + res = 1; + } + if (!isinf (d)) + { + printf ("'%s' does not pass isinf\n", tests[i]); + res = 1; + } + } + + return res; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/stdlib/strtod_l.c b/stdlib/strtod_l.c index a656789f4c..3a1c1ebd4b 100644 --- a/stdlib/strtod_l.c +++ b/stdlib/strtod_l.c @@ -1,5 +1,5 @@ /* Convert string representing a number to float value, using given locale. - Copyright (C) 1997,98,2002, 2004 Free Software Foundation, Inc. + Copyright (C) 1997,98,2002,2004,2005 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 1997. @@ -100,7 +100,9 @@ extern unsigned long long int ____strtoull_l_internal (const char *, char **, # define ISDIGIT(Ch) __iswdigit_l ((Ch), loc) # define ISXDIGIT(Ch) __iswxdigit_l ((Ch), loc) # define TOLOWER(Ch) __towlower_l ((Ch), loc) -# define STRNCASECMP(S1, S2, N) __wcsncasecmp_l ((S1), (S2), (N), loc) +# define TOLOWER_C(Ch) __towlower_l ((Ch), &_nl_C_locobj) +# define STRNCASECMP(S1, S2, N) \ + __wcsncasecmp_l ((S1), (S2), (N), &_nl_C_locobj) # define STRTOULL(S, E, B) ____wcstoull_l_internal ((S), (E), (B), 0, loc) #else # define STRING_TYPE char @@ -110,7 +112,9 @@ extern unsigned long long int ____strtoull_l_internal (const char *, char **, # define ISDIGIT(Ch) __isdigit_l ((Ch), loc) # define ISXDIGIT(Ch) __isxdigit_l ((Ch), loc) # define TOLOWER(Ch) __tolower_l ((Ch), loc) -# define STRNCASECMP(S1, S2, N) __strncasecmp_l ((S1), (S2), (N), loc) +# define TOLOWER_C(Ch) __tolower_l ((Ch), &_nl_C_locobj) +# define STRNCASECMP(S1, S2, N) \ + __strncasecmp_l ((S1), (S2), (N), &_nl_C_locobj) # define STRTOULL(S, E, B) ____strtoull_l_internal ((S), (E), (B), 0, loc) #endif @@ -554,7 +558,7 @@ INTERNAL (__STRTOF) (nptr, endptr, group, loc) else if (c < L_('0') || c > L_('9')) { /* Check for `INF' or `INFINITY'. */ - if (TOLOWER (c) == L_('i') && STRNCASECMP (cp, L_("inf"), 3) == 0) + if (TOLOWER_C (c) == L_('i') && STRNCASECMP (cp, L_("inf"), 3) == 0) { /* Return +/- infinity. */ if (endptr != NULL) @@ -565,7 +569,7 @@ INTERNAL (__STRTOF) (nptr, endptr, group, loc) return negative ? -FLOAT_HUGE_VAL : FLOAT_HUGE_VAL; } - if (TOLOWER (c) == L_('n') && STRNCASECMP (cp, L_("nan"), 3) == 0) + if (TOLOWER_C (c) == L_('n') && STRNCASECMP (cp, L_("nan"), 3) == 0) { /* Return NaN. */ FLOAT retval = NAN;