diff options
author | Matthias Urlichs <smurf@noris.net> | 2000-03-04 13:48:42 +0100 |
---|---|---|
committer | Jarkko Hietaniemi <jhi@iki.fi> | 2000-03-04 16:35:48 +0000 |
commit | 0b7fceb9e0ed2836bae4cb25eb0618064f63af24 (patch) | |
tree | 76f3221081a17259786460fb6134baf4bc854d14 | |
parent | 90ea4f4d7613f41c4c0e536a45aa1927a77c23d5 (diff) | |
download | perl-0b7fceb9e0ed2836bae4cb25eb0618064f63af24.tar.gz |
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
-rw-r--r-- | toke.c | 54 |
1 files changed, 54 insertions, 0 deletions
@@ -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: |