summaryrefslogtreecommitdiffstats
path: root/gnu/usr.bin/perl/numeric.c
diff options
context:
space:
mode:
authorafresh1 <afresh1@openbsd.org>2019-02-13 21:15:00 +0000
committerafresh1 <afresh1@openbsd.org>2019-02-13 21:15:00 +0000
commit9f11ffb7133c203312a01e4b986886bc88c7d74b (patch)
tree6618511204c614b20256e4ef9dea39a7b311d638 /gnu/usr.bin/perl/numeric.c
parentImport perl-5.28.1 (diff)
downloadwireguard-openbsd-9f11ffb7133c203312a01e4b986886bc88c7d74b.tar.xz
wireguard-openbsd-9f11ffb7133c203312a01e4b986886bc88c7d74b.zip
Fix merge issues, remove excess files - match perl-5.28.1 dist
looking good sthen@, Great! bluhm@
Diffstat (limited to 'gnu/usr.bin/perl/numeric.c')
-rw-r--r--gnu/usr.bin/perl/numeric.c138
1 files changed, 89 insertions, 49 deletions
diff --git a/gnu/usr.bin/perl/numeric.c b/gnu/usr.bin/perl/numeric.c
index f6455028e33..8754a9f6498 100644
--- a/gnu/usr.bin/perl/numeric.c
+++ b/gnu/usr.bin/perl/numeric.c
@@ -518,33 +518,44 @@ Scan and skip for a numeric decimal separator (radix).
bool
Perl_grok_numeric_radix(pTHX_ const char **sp, const char *send)
{
-#ifdef USE_LOCALE_NUMERIC
PERL_ARGS_ASSERT_GROK_NUMERIC_RADIX;
+#ifdef USE_LOCALE_NUMERIC
+
if (IN_LC(LC_NUMERIC)) {
+ STRLEN len;
+ char * radix;
+ bool matches_radix = FALSE;
DECLARATION_FOR_LC_NUMERIC_MANIPULATION;
- STORE_LC_NUMERIC_SET_TO_NEEDED();
- if (PL_numeric_radix_sv) {
- STRLEN len;
- const char * const radix = SvPV(PL_numeric_radix_sv, len);
- if (*sp + len <= send && memEQ(*sp, radix, len)) {
- *sp += len;
- RESTORE_LC_NUMERIC();
- return TRUE;
- }
- }
+
+ STORE_LC_NUMERIC_FORCE_TO_UNDERLYING();
+
+ radix = SvPV(PL_numeric_radix_sv, len);
+ radix = savepvn(radix, len);
+
RESTORE_LC_NUMERIC();
+
+ if (*sp + len <= send) {
+ matches_radix = memEQ(*sp, radix, len);
+ }
+
+ Safefree(radix);
+
+ if (matches_radix) {
+ *sp += len;
+ return TRUE;
+ }
}
- /* always try "." if numeric radix didn't match because
- * we may have data from different locales mixed */
-#endif
- PERL_ARGS_ASSERT_GROK_NUMERIC_RADIX;
+#endif
+ /* always try "." if numeric radix didn't match because
+ * we may have data from different locales mixed */
if (*sp < send && **sp == '.') {
++*sp;
return TRUE;
}
+
return FALSE;
}
@@ -574,6 +585,7 @@ Perl_grok_infnan(pTHX_ const char** sp, const char* send)
{
const char* s = *sp;
int flags = 0;
+#if defined(NV_INF) || defined(NV_NAN)
bool odh = FALSE; /* one-dot-hash: 1.#INF */
PERL_ARGS_ASSERT_GROK_INFNAN;
@@ -798,6 +810,9 @@ Perl_grok_infnan(pTHX_ const char** sp, const char* send)
while (s < send && isSPACE(*s))
s++;
+#else
+ PERL_UNUSED_ARG(send);
+#endif /* #if defined(NV_INF) || defined(NV_NAN) */
*sp = s;
return flags;
}
@@ -1009,7 +1024,7 @@ Perl_grok_number_flags(pTHX_ const char *pv, STRLEN len, UV *valuep, U32 flags)
s++;
if (s >= send)
return numtype;
- if (len == 10 && memEQ(pv, "0 but true", 10)) {
+ if (memEQs(pv, len, "0 but true")) {
if (valuep)
*valuep = 0;
return IS_NUMBER_IN_UV;
@@ -1018,7 +1033,7 @@ Perl_grok_number_flags(pTHX_ const char *pv, STRLEN len, UV *valuep, U32 flags)
if ((s + 2 < send) && strchr("inqs#", toFOLD(*s))) {
/* Really detect inf/nan. Start at d, not s, since the above
* code might have already consumed the "1." or "1". */
- int infnan = Perl_grok_infnan(aTHX_ &d, send);
+ const int infnan = Perl_grok_infnan(aTHX_ &d, send);
if ((infnan & IS_NUMBER_INFINITY)) {
return (numtype | infnan); /* Keep sign for infinity. */
}
@@ -1085,7 +1100,7 @@ Perl_grok_atoUV(const char *pv, UV *valptr, const char** endptr)
/* This could be unrolled like in grok_number(), but
* the expected uses of this are not speed-needy, and
* unlikely to need full 64-bitness. */
- U8 digit = *s++ - '0';
+ const U8 digit = *s++ - '0';
if (val < uv_max_div_10 ||
(val == uv_max_div_10 && digit <= uv_max_mod_10)) {
val = val * 10 + digit;
@@ -1138,7 +1153,7 @@ S_mulexp10(NV value, I32 exponent)
* a hammer. Therefore we need to catch potential overflows before
* it's too late. */
-#if ((defined(VMS) && !defined(_IEEE_FP)) || defined(_UNICOS)) && defined(NV_MAX_10_EXP)
+#if ((defined(VMS) && !defined(_IEEE_FP)) || defined(_UNICOS) || defined(DOUBLE_IS_VAX_FLOAT)) && defined(NV_MAX_10_EXP)
STMT_START {
const NV exp_v = log10(value);
if (exponent >= NV_MAX_10_EXP || exponent + exp_v >= NV_MAX_10_EXP)
@@ -1185,7 +1200,11 @@ S_mulexp10(NV value, I32 exponent)
result *= power;
#ifdef FP_OVERFLOWS_TO_ZERO
if (result == 0)
+# ifdef NV_INF
return value < 0 ? -NV_INF : NV_INF;
+# else
+ return value < 0 ? -FLT_MAX : FLT_MAX;
+# endif
#endif
/* Floating point exceptions are supposed to be turned off,
* but if we're obviously done, don't risk another iteration.
@@ -1201,21 +1220,26 @@ S_mulexp10(NV value, I32 exponent)
NV
Perl_my_atof(pTHX_ const char* s)
{
+ /* 's' must be NUL terminated */
+
NV x = 0.0;
+
+ PERL_ARGS_ASSERT_MY_ATOF;
+
#ifdef USE_QUADMATH
+
Perl_my_atof2(aTHX_ s, &x);
- return x;
+
+#elif ! defined(USE_LOCALE_NUMERIC)
+
+ Perl_atof2(s, x);
+
#else
-# ifdef USE_LOCALE_NUMERIC
- PERL_ARGS_ASSERT_MY_ATOF;
{
DECLARATION_FOR_LC_NUMERIC_MANIPULATION;
STORE_LC_NUMERIC_SET_TO_NEEDED();
if (PL_numeric_radix_sv && IN_LC(LC_NUMERIC)) {
- const char *standard = NULL, *local = NULL;
- bool use_standard_radix;
-
/* Look through the string for the first thing that looks like a
* decimal point: either the value in the current locale or the
* standard fallback of '.'. The one which appears earliest in the
@@ -1223,30 +1247,35 @@ Perl_my_atof(pTHX_ const char* s)
* that we have to determine this beforehand because on some
* systems, Perl_atof2 is just a wrapper around the system's atof.
* */
- standard = strchr(s, '.');
- local = strstr(s, SvPV_nolen(PL_numeric_radix_sv));
-
- use_standard_radix = standard && (!local || standard < local);
+ const char * const standard_pos = strchr(s, '.');
+ const char * const local_pos
+ = strstr(s, SvPV_nolen(PL_numeric_radix_sv));
+ const bool use_standard_radix
+ = standard_pos && (!local_pos || standard_pos < local_pos);
- if (use_standard_radix)
+ if (use_standard_radix) {
SET_NUMERIC_STANDARD();
+ LOCK_LC_NUMERIC_STANDARD();
+ }
Perl_atof2(s, x);
- if (use_standard_radix)
+ if (use_standard_radix) {
+ UNLOCK_LC_NUMERIC_STANDARD();
SET_NUMERIC_UNDERLYING();
+ }
}
else
Perl_atof2(s, x);
RESTORE_LC_NUMERIC();
}
-# else
- Perl_atof2(s, x);
-# endif
+
#endif
+
return x;
}
+#if defined(NV_INF) || defined(NV_NAN)
#ifdef USING_MSVC6
# pragma warning(push)
@@ -1257,7 +1286,7 @@ S_my_atof_infnan(pTHX_ const char* s, bool negative, const char* send, NV* value
{
const char *p0 = negative ? s - 1 : s;
const char *p = p0;
- int infnan = grok_infnan(&p, send);
+ const int infnan = grok_infnan(&p, send);
if (infnan && p != p0) {
/* If we can generate inf/nan directly, let's do so. */
#ifdef NV_INF
@@ -1276,8 +1305,6 @@ S_my_atof_infnan(pTHX_ const char* s, bool negative, const char* send, NV* value
/* If still here, we didn't have either NV_INF or NV_NAN,
* and can try falling back to native strtod/strtold.
*
- * (Though, are our NV_INF or NV_NAN ever not defined?)
- *
* The native interface might not recognize all the possible
* inf/nan strings Perl recognizes. What we can try
* is to try faking the input. We will try inf/-inf/nan
@@ -1286,36 +1313,44 @@ S_my_atof_infnan(pTHX_ const char* s, bool negative, const char* send, NV* value
const char* fake = NULL;
char* endp;
NV nv;
+#ifdef NV_INF
if ((infnan & IS_NUMBER_INFINITY)) {
fake = ((infnan & IS_NUMBER_NEG)) ? "-inf" : "inf";
}
- else if ((infnan & IS_NUMBER_NAN)) {
+#endif
+#ifdef NV_NAN
+ if ((infnan & IS_NUMBER_NAN)) {
fake = "nan";
}
+#endif
assert(fake);
nv = Perl_strtod(fake, &endp);
if (fake != endp) {
+#ifdef NV_INF
if ((infnan & IS_NUMBER_INFINITY)) {
-#ifdef Perl_isinf
+# ifdef Perl_isinf
if (Perl_isinf(nv))
*value = nv;
-#else
+# else
/* last resort, may generate SIGFPE */
*value = Perl_exp((NV)1e9);
if ((infnan & IS_NUMBER_NEG))
*value = -*value;
-#endif
+# endif
return (char*)p; /* p, not endp */
}
- else if ((infnan & IS_NUMBER_NAN)) {
-#ifdef Perl_isnan
+#endif
+#ifdef NV_NAN
+ if ((infnan & IS_NUMBER_NAN)) {
+# ifdef Perl_isnan
if (Perl_isnan(nv))
*value = nv;
-#else
+# else
/* last resort, may generate SIGFPE */
*value = Perl_log((NV)-1.0);
-#endif
+# endif
return (char*)p; /* p, not endp */
+#endif
}
}
}
@@ -1327,6 +1362,8 @@ S_my_atof_infnan(pTHX_ const char* s, bool negative, const char* send, NV* value
# pragma warning(pop)
#endif
+#endif /* if defined(NV_INF) || defined(NV_NAN) */
+
char*
Perl_my_atof2(pTHX_ const char* orig, NV* value)
{
@@ -1409,11 +1446,13 @@ Perl_my_atof2(pTHX_ const char* orig, NV* value)
/* the max number we can accumulate in a UV, and still safely do 10*N+9 */
#define MAX_ACCUMULATE ( (UV) ((UV_MAX - 9)/10))
+#if defined(NV_INF) || defined(NV_NAN)
{
- const char* endp;
+ char* endp;
if ((endp = S_my_atof_infnan(aTHX_ s, negative, send, value)))
- return (char*)endp;
+ return endp;
}
+#endif
/* we accumulate digits into an integer; when this becomes too
* large, we add the total to NV and start again */
@@ -1470,9 +1509,9 @@ Perl_my_atof2(pTHX_ const char* orig, NV* value)
else if (!seen_dp && GROK_NUMERIC_RADIX(&s, send)) {
seen_dp = 1;
if (sig_digits > MAX_SIG_DIGITS) {
- do {
+ while (isDIGIT(*s)) {
++s;
- } while (isDIGIT(*s));
+ }
break;
}
}
@@ -1536,6 +1575,7 @@ This is also the logical inverse of Perl_isfinite().
bool
Perl_isinfnan(NV nv)
{
+ PERL_UNUSED_ARG(nv);
#ifdef Perl_isinf
if (Perl_isinf(nv))
return TRUE;