|
|
fb6d68 |
From 78787052b6a68c0f54cfa983a69c44276de9daa4 Mon Sep 17 00:00:00 2001
|
|
|
fb6d68 |
From: Jesse Luehrs <doy@tozt.net>
|
|
|
fb6d68 |
Date: Tue, 26 Jun 2012 00:13:54 -0500
|
|
|
fb6d68 |
Subject: [PATCH] use a less broken test for locale radix in atof [perl #109318]
|
|
|
fb6d68 |
|
|
|
fb6d68 |
---
|
|
|
fb6d68 |
lib/locale.t | 33 +++++++++++++++++++++++++++++++++
|
|
|
fb6d68 |
numeric.c | 25 +++++++++++++++----------
|
|
|
fb6d68 |
2 files changed, 48 insertions(+), 10 deletions(-)
|
|
|
fb6d68 |
|
|
|
fb6d68 |
diff --git a/lib/locale.t b/lib/locale.t
|
|
|
fb6d68 |
index dfc6d2b..26a7bd4 100644
|
|
|
fb6d68 |
--- a/lib/locale.t
|
|
|
fb6d68 |
+++ b/lib/locale.t
|
|
|
fb6d68 |
@@ -1247,6 +1247,39 @@ foreach $Locale (@Locale) {
|
|
|
fb6d68 |
print "# failed $locales_test_number locale '$Locale' characters @f\n"
|
|
|
fb6d68 |
}
|
|
|
fb6d68 |
}
|
|
|
fb6d68 |
+
|
|
|
fb6d68 |
+ # [perl #109318]
|
|
|
fb6d68 |
+ {
|
|
|
fb6d68 |
+ my @f = ();
|
|
|
fb6d68 |
+ ++$locales_test_number;
|
|
|
fb6d68 |
+ $test_names{$locales_test_number} = 'Verify atof with locale radix and negative exponent';
|
|
|
fb6d68 |
+
|
|
|
fb6d68 |
+ my $radix = POSIX::localeconv()->{decimal_point};
|
|
|
fb6d68 |
+ my @nums = (
|
|
|
fb6d68 |
+ "3.14e+9", "3${radix}14e+9", "3.14e-9", "3${radix}14e-9",
|
|
|
fb6d68 |
+ "-3.14e+9", "-3${radix}14e+9", "-3.14e-9", "-3${radix}14e-9",
|
|
|
fb6d68 |
+ );
|
|
|
fb6d68 |
+
|
|
|
fb6d68 |
+ if (! $is_utf8_locale) {
|
|
|
fb6d68 |
+ use locale;
|
|
|
fb6d68 |
+ for my $num (@nums) {
|
|
|
fb6d68 |
+ push @f, $num
|
|
|
fb6d68 |
+ unless sprintf("%g", $num) =~ /3.+14/;
|
|
|
fb6d68 |
+ }
|
|
|
fb6d68 |
+ }
|
|
|
fb6d68 |
+ else {
|
|
|
fb6d68 |
+ use locale ':not_characters';
|
|
|
fb6d68 |
+ for my $num (@nums) {
|
|
|
fb6d68 |
+ push @f, $num
|
|
|
fb6d68 |
+ unless sprintf("%g", $num) =~ /3.+14/;
|
|
|
fb6d68 |
+ }
|
|
|
fb6d68 |
+ }
|
|
|
fb6d68 |
+
|
|
|
fb6d68 |
+ tryneoalpha($Locale, $locales_test_number, @f == 0);
|
|
|
fb6d68 |
+ if (@f) {
|
|
|
fb6d68 |
+ print "# failed $locales_test_number locale '$Locale' numbers @f\n"
|
|
|
fb6d68 |
+ }
|
|
|
fb6d68 |
+ }
|
|
|
fb6d68 |
}
|
|
|
fb6d68 |
|
|
|
fb6d68 |
my $final_locales_test_number = $locales_test_number;
|
|
|
fb6d68 |
diff --git a/numeric.c b/numeric.c
|
|
|
fb6d68 |
index be86f3a..3eb8a0e 100644
|
|
|
fb6d68 |
--- a/numeric.c
|
|
|
fb6d68 |
+++ b/numeric.c
|
|
|
fb6d68 |
@@ -847,17 +847,22 @@ Perl_my_atof(pTHX_ const char* s)
|
|
|
fb6d68 |
|
|
|
fb6d68 |
PERL_ARGS_ASSERT_MY_ATOF;
|
|
|
fb6d68 |
|
|
|
fb6d68 |
- if (PL_numeric_local && IN_SOME_LOCALE_FORM) {
|
|
|
fb6d68 |
- NV y;
|
|
|
fb6d68 |
+ if (PL_numeric_local && PL_numeric_radix_sv && IN_SOME_LOCALE_FORM) {
|
|
|
fb6d68 |
+ char *standard = NULL, *local = NULL;
|
|
|
fb6d68 |
+ bool use_standard_radix;
|
|
|
fb6d68 |
|
|
|
fb6d68 |
- /* Scan the number twice; once using locale and once without;
|
|
|
fb6d68 |
- * choose the larger result (in absolute value). */
|
|
|
fb6d68 |
- Perl_atof2(s, x);
|
|
|
fb6d68 |
- SET_NUMERIC_STANDARD();
|
|
|
fb6d68 |
- Perl_atof2(s, y);
|
|
|
fb6d68 |
- SET_NUMERIC_LOCAL();
|
|
|
fb6d68 |
- if ((y < 0.0 && y < x) || (y > 0.0 && y > x))
|
|
|
fb6d68 |
- return y;
|
|
|
fb6d68 |
+ standard = strchr(s, '.');
|
|
|
fb6d68 |
+ local = strstr(s, SvPV_nolen(PL_numeric_radix_sv));
|
|
|
fb6d68 |
+
|
|
|
fb6d68 |
+ use_standard_radix = standard && (!local || standard < local);
|
|
|
fb6d68 |
+
|
|
|
fb6d68 |
+ if (use_standard_radix)
|
|
|
fb6d68 |
+ SET_NUMERIC_STANDARD();
|
|
|
fb6d68 |
+
|
|
|
fb6d68 |
+ Perl_atof2(s, x);
|
|
|
fb6d68 |
+
|
|
|
fb6d68 |
+ if (use_standard_radix)
|
|
|
fb6d68 |
+ SET_NUMERIC_LOCAL();
|
|
|
fb6d68 |
}
|
|
|
fb6d68 |
else
|
|
|
fb6d68 |
Perl_atof2(s, x);
|
|
|
fb6d68 |
--
|
|
|
fb6d68 |
1.7.4.1
|
|
|
fb6d68 |
|