From 0b7fceb9e0ed2836bae4cb25eb0618064f63af24 Mon Sep 17 00:00:00 2001 From: Matthias Urlichs Date: Sat, 4 Mar 2000 13:48:42 +0100 Subject: BUG: Integer floatifies? +PATCH: reading BIG integers with SMALL floats To: perl5-porters@perl.org Message-ID: <20000304124841.A8090@noris.de> p4raw-id: //depot/cfgperl@5521 --- toke.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/toke.c b/toke.c index 79ee972e02..16e3788b8b 100644 --- a/toke.c +++ b/toke.c @@ -6684,7 +6684,10 @@ Perl_scan_num(pTHX_ char *start) register char *s = start; /* current position in buffer */ register char *d; /* destination in temp buffer */ register char *e; /* end of temp buffer */ +#if (defined(USE_64_BIT_INT) && (!defined(HAS_STRTOLL)|| !defined(HAS_STRTOULL))) || \ + (!defined(USE_64_BIT_INT) && (!defined(HAS_STRTOL) || !defined(HAS_STRTOUL))) IV tryiv; /* used to see if it can be an IV */ +#endif NV value; /* number read, as a double */ SV *sv = Nullsv; /* place to put the converted number */ bool floatit; /* boolean: int or float? */ @@ -6942,6 +6945,14 @@ Perl_scan_num(pTHX_ char *start) /* make an sv from the string */ sv = NEWSV(92,0); +#if (defined(USE_64_BIT_INT) && (!defined(HAS_STRTOLL)|| !defined(HAS_STRTOULL))) || \ + (!defined(USE_64_BIT_INT) && (!defined(HAS_STRTOL) || !defined(HAS_STRTOUL))) + + /* + No working strto[u]l[l]. Since atoi() doesn't do range checks, + we need to do this the hard way. + */ + value = Atof(PL_tokenbuf); /* @@ -6959,12 +6970,55 @@ Perl_scan_num(pTHX_ char *start) sv_setiv(sv, tryiv); else sv_setnv(sv, value); +#else + /* + strtol/strtoll sets errno to ERANGE if the number is too big + for an integer. We try to do an integer conversion first + if no characters indicating "float" have been found. + */ + + if (!floatit) { + char *tp; + IV iv; + UV uv; + errno = 0; +#ifdef USE_64_BIT_INT + iv = (*PL_tokenbuf == '-') ? + strtoll(PL_tokenbuf,&tp,10) : + (IV)strtoull(PL_tokenbuf,&tp,10); +#else + iv = (*PL_tokenbuf == '-') ? + strtol(PL_tokenbuf,&tp,10) : + (IV)strtoul(PL_tokenbuf,&tp,10); +#endif + if (*tp || errno) + floatit = TRUE; /* probably just too large */ + else if (*PL_tokenbuf == '-') + sv_setiv(sv, iv); + else + sv_setuv(sv, (UV)iv); + } + if (floatit) { + char *tp; + errno = 0; +#ifdef USE_LONG_DOUBLE + value = strtold(PL_tokenbuf,&tp); +#else + value = strtod(PL_tokenbuf,&tp); +#endif + if (*tp || errno) + Perl_die(aTHX_ "unparseable float"); + else + sv_setnv(sv, value); + } +#endif if ( floatit ? (PL_hints & HINT_NEW_FLOAT) : (PL_hints & HINT_NEW_INTEGER) ) sv = new_constant(PL_tokenbuf, d - PL_tokenbuf, (floatit ? "float" : "integer"), sv, Nullsv, NULL); break; + /* if it starts with a v, it could be a version number */ case 'v': vstring: -- cgit v1.2.1