mirror of
git://sourceware.org/git/newlib-cygwin.git
synced 2025-02-06 22:40:36 +08:00
* mingwex/strtold.c (__asctoe64) Reorganise. Fix setting error
codes and handling of special chars.
This commit is contained in:
parent
120023b090
commit
d11508dd22
@ -1,3 +1,8 @@
|
|||||||
|
2004-02-05 Danny Smith <dannysmith@users.sourceforge.net>
|
||||||
|
|
||||||
|
* mingwex/strtold.c (__asctoe64) Reorganise. Fix setting error
|
||||||
|
codes and handling of special chars.
|
||||||
|
|
||||||
2004-02-02 Danny Smith <dannysmith@users.sourceforge.net>
|
2004-02-02 Danny Smith <dannysmith@users.sourceforge.net>
|
||||||
|
|
||||||
* include/stdio.h (feof): Add inlined definition.
|
* include/stdio.h (feof): Add inlined definition.
|
||||||
|
@ -20,13 +20,14 @@
|
|||||||
* 6 Oct 02 Modified for MinGW by inlining utility routines,
|
* 6 Oct 02 Modified for MinGW by inlining utility routines,
|
||||||
* removing global variables and splitting out strtold
|
* removing global variables and splitting out strtold
|
||||||
* from _IO_ldtoa and _IO_ldtostr.
|
* from _IO_ldtoa and _IO_ldtostr.
|
||||||
*
|
*
|
||||||
|
* 4 Feb 04 Reorganize __asctoe64 to fix setting error codes,
|
||||||
|
* and handling special chars.
|
||||||
|
*
|
||||||
* Danny Smith <dannysmith@users.sourceforge.net>
|
* Danny Smith <dannysmith@users.sourceforge.net>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "math/cephes_emath.h"
|
#include "math/cephes_emath.h"
|
||||||
|
|
||||||
#if NE == 10
|
#if NE == 10
|
||||||
|
|
||||||
/* 1.0E0 */
|
/* 1.0E0 */
|
||||||
@ -89,15 +90,19 @@ static const unsigned short __etens[NTEN+1][NE] = {
|
|||||||
int __asctoe64(const char * __restrict__ ss, short unsigned int * __restrict__ y)
|
int __asctoe64(const char * __restrict__ ss, short unsigned int * __restrict__ y)
|
||||||
{
|
{
|
||||||
unsigned short yy[NI], xt[NI], tt[NI];
|
unsigned short yy[NI], xt[NI], tt[NI];
|
||||||
int esign, decflg, sgnflg, nexp, exp, prec, lost;
|
int esign, decflg, nexp, exp, lost;
|
||||||
int k, trail, c;
|
int k, c;
|
||||||
|
int valid_lead_string = 0;
|
||||||
|
int have_non_zero_mant = 0;
|
||||||
|
int prec = 0;
|
||||||
|
/* int trail = 0; */
|
||||||
long lexp;
|
long lexp;
|
||||||
unsigned short nsign;
|
unsigned short nsign = 0;
|
||||||
const unsigned short *p;
|
const unsigned short *p;
|
||||||
char *sp, *lstr;
|
char *sp, *lstr;
|
||||||
char *s;
|
char *s;
|
||||||
|
|
||||||
char dec_sym = *(localeconv ()->decimal_point);
|
const char dec_sym = *(localeconv ()->decimal_point);
|
||||||
|
|
||||||
int lenldstr = 0;
|
int lenldstr = 0;
|
||||||
|
|
||||||
@ -119,23 +124,58 @@ for( k=0; k<c; k++ )
|
|||||||
*sp = '\0';
|
*sp = '\0';
|
||||||
s = lstr;
|
s = lstr;
|
||||||
|
|
||||||
|
if (*s == '-')
|
||||||
|
{
|
||||||
|
nsign = 0xffff;
|
||||||
|
++s;
|
||||||
|
}
|
||||||
|
else if (*s == '+')
|
||||||
|
{
|
||||||
|
++s;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_strnicmp("INF", s , 3) == 0)
|
||||||
|
{
|
||||||
|
valid_lead_string = 1;
|
||||||
|
s += 3;
|
||||||
|
if ( _strnicmp ("INITY", s, 5) == 0)
|
||||||
|
s += 5;
|
||||||
|
__ecleaz(yy);
|
||||||
|
yy[E] = 0x7fff; /* infinity */
|
||||||
|
goto aexit;
|
||||||
|
}
|
||||||
|
else if(_strnicmp ("NAN", s, 3) == 0)
|
||||||
|
{
|
||||||
|
valid_lead_string = 1;
|
||||||
|
s += 3;
|
||||||
|
__enan_NI16( yy );
|
||||||
|
goto aexit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FIXME: Handle case of strtold ("NAN(n_char_seq)",endptr) */
|
||||||
|
|
||||||
|
/* Now get some digits. */
|
||||||
lost = 0;
|
lost = 0;
|
||||||
nsign = 0;
|
|
||||||
decflg = 0;
|
decflg = 0;
|
||||||
sgnflg = 0;
|
|
||||||
nexp = 0;
|
nexp = 0;
|
||||||
exp = 0;
|
exp = 0;
|
||||||
prec = 0;
|
|
||||||
__ecleaz( yy );
|
__ecleaz( yy );
|
||||||
trail = 0;
|
|
||||||
|
/* Ignore leading zeros */
|
||||||
|
while (*s == '0')
|
||||||
|
{
|
||||||
|
valid_lead_string = 1;
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
|
||||||
nxtcom:
|
nxtcom:
|
||||||
|
|
||||||
k = *s - '0';
|
k = *s - '0';
|
||||||
if( (k >= 0) && (k <= 9) )
|
if( (k >= 0) && (k <= 9) )
|
||||||
{
|
{
|
||||||
/* Ignore leading zeros */
|
#if 0
|
||||||
if( (prec == 0) && (decflg == 0) && (k == 0) )
|
/* The use of a special char as a flag for trailing zeroes causes problems when input
|
||||||
goto donchr;
|
actually contains the char */
|
||||||
/* Identify and strip trailing zeros after the decimal point. */
|
/* Identify and strip trailing zeros after the decimal point. */
|
||||||
if( (trail == 0) && (decflg != 0) )
|
if( (trail == 0) && (decflg != 0) )
|
||||||
{
|
{
|
||||||
@ -144,11 +184,15 @@ if( (k >= 0) && (k <= 9) )
|
|||||||
++sp;
|
++sp;
|
||||||
--sp;
|
--sp;
|
||||||
while( *sp == '0' )
|
while( *sp == '0' )
|
||||||
*sp-- = 'z';
|
{
|
||||||
trail = 1;
|
*sp-- = (char)-1;
|
||||||
if( *s == 'z' )
|
trail++;
|
||||||
|
}
|
||||||
|
if( *s == (char)-1 )
|
||||||
goto donchr;
|
goto donchr;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* If enough digits were given to more than fill up the yy register,
|
/* If enough digits were given to more than fill up the yy register,
|
||||||
* continuing until overflow into the high guard word yy[2]
|
* continuing until overflow into the high guard word yy[2]
|
||||||
* guarantees that there will be a roundoff bit at the top
|
* guarantees that there will be a roundoff bit at the top
|
||||||
@ -175,71 +219,37 @@ if( (k >= 0) && (k <= 9) )
|
|||||||
if (decflg == 0)
|
if (decflg == 0)
|
||||||
nexp -= 1;
|
nexp -= 1;
|
||||||
}
|
}
|
||||||
prec += 1;
|
have_non_zero_mant |= k;
|
||||||
goto donchr;
|
prec ++;
|
||||||
|
/* goto donchr; */
|
||||||
}
|
}
|
||||||
if (*s == dec_sym)
|
else if (*s == dec_sym)
|
||||||
{
|
{
|
||||||
if( decflg )
|
if( decflg )
|
||||||
goto daldone;
|
goto daldone;
|
||||||
++decflg;
|
++decflg;
|
||||||
}
|
}
|
||||||
else
|
else if ((*s == 'E') || (*s == 'e') )
|
||||||
switch( *s )
|
{
|
||||||
{
|
if (prec || valid_lead_string)
|
||||||
case 'z':
|
goto expnt;
|
||||||
break;
|
else
|
||||||
case 'E':
|
goto daldone;
|
||||||
case 'e':
|
}
|
||||||
goto expnt;
|
|
||||||
case '-':
|
#if 0
|
||||||
nsign = 0xffff;
|
else if (*s == (char)-1)
|
||||||
if( sgnflg )
|
goto donchr;
|
||||||
goto daldone;
|
#endif
|
||||||
++sgnflg;
|
|
||||||
break;
|
else /* an invalid char */
|
||||||
case '+':
|
goto daldone;
|
||||||
if( sgnflg )
|
|
||||||
goto daldone;
|
/* donchr: */
|
||||||
++sgnflg;
|
|
||||||
break;
|
|
||||||
case 'i':
|
|
||||||
case 'I':
|
|
||||||
{
|
|
||||||
s++;
|
|
||||||
if (*s != 'n' && *s != 'N')
|
|
||||||
goto zero;
|
|
||||||
s++;
|
|
||||||
if (*s != 'f' && *s != 'F')
|
|
||||||
goto zero;
|
|
||||||
s++;
|
|
||||||
if ((*s == 'i' || *s == 'I') && (s[1] == 'n' || s[1] == 'N')
|
|
||||||
&& (s[2] == 'i' || s[2] == 'I')
|
|
||||||
&& (s[3] == 't' || s[3] == 'T')
|
|
||||||
&& (s[4] == 'y' || s[4] == 'Y'))
|
|
||||||
s += 5;
|
|
||||||
goto infinite;
|
|
||||||
}
|
|
||||||
case 'n':
|
|
||||||
case 'N':
|
|
||||||
{
|
|
||||||
s++;
|
|
||||||
if (*s != 'a' && *s != 'A')
|
|
||||||
goto zero;
|
|
||||||
s++;
|
|
||||||
if (*s != 'n' && *s != 'N')
|
|
||||||
goto zero;
|
|
||||||
s++;
|
|
||||||
__enan_NI16( yy );
|
|
||||||
goto aexit;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
goto daldone;
|
|
||||||
}
|
|
||||||
donchr:
|
|
||||||
++s;
|
++s;
|
||||||
goto nxtcom;
|
goto nxtcom;
|
||||||
|
|
||||||
|
|
||||||
/* Exponent interpretation */
|
/* Exponent interpretation */
|
||||||
expnt:
|
expnt:
|
||||||
|
|
||||||
@ -254,31 +264,39 @@ if( *s == '-' )
|
|||||||
}
|
}
|
||||||
if( *s == '+' )
|
if( *s == '+' )
|
||||||
++s;
|
++s;
|
||||||
while( (*s >= '0') && (*s <= '9') && exp < 4978)
|
|
||||||
{
|
while( (*s >= '0') && (*s <= '9') )
|
||||||
exp *= 10;
|
{
|
||||||
exp += *s++ - '0';
|
/* Stop modifying exp if we are going to overflow anyway,
|
||||||
}
|
but keep parsing the string. */
|
||||||
|
if (exp < 4978)
|
||||||
|
{
|
||||||
|
exp *= 10;
|
||||||
|
exp += *s - '0';
|
||||||
|
}
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
|
||||||
if( esign < 0 )
|
if( esign < 0 )
|
||||||
exp = -exp;
|
exp = -exp;
|
||||||
if( exp > 4932 )
|
|
||||||
|
if (exp > 4977) /* maybe overflow */
|
||||||
{
|
{
|
||||||
errno = ERANGE;
|
|
||||||
infinite:
|
|
||||||
__ecleaz(yy);
|
__ecleaz(yy);
|
||||||
yy[E] = 0x7fff; /* infinity */
|
if (have_non_zero_mant)
|
||||||
|
yy[E] = 0x7fff;
|
||||||
goto aexit;
|
goto aexit;
|
||||||
}
|
}
|
||||||
if( exp < -4977 )
|
else if (exp < -4977) /* underflow */
|
||||||
{
|
{
|
||||||
errno = ERANGE;
|
|
||||||
zero:
|
|
||||||
__ecleaz(yy);
|
__ecleaz(yy);
|
||||||
goto aexit;
|
goto aexit;
|
||||||
}
|
}
|
||||||
|
|
||||||
daldone:
|
daldone:
|
||||||
|
|
||||||
nexp = exp - nexp;
|
nexp = exp - nexp;
|
||||||
|
|
||||||
/* Pad trailing zeros to minimize power of 10, per IEEE spec. */
|
/* Pad trailing zeros to minimize power of 10, per IEEE spec. */
|
||||||
while( (nexp > 0) && (yy[2] == 0) )
|
while( (nexp > 0) && (yy[2] == 0) )
|
||||||
{
|
{
|
||||||
@ -363,8 +381,17 @@ __emdnorm( yy, k, 0, lexp, 64, 64 );
|
|||||||
aexit:
|
aexit:
|
||||||
|
|
||||||
yy[0] = nsign;
|
yy[0] = nsign;
|
||||||
|
|
||||||
__toe64( yy, y );
|
__toe64( yy, y );
|
||||||
return (lenldstr + s - lstr);
|
|
||||||
|
/* Check for overflow, undeflow */
|
||||||
|
if (have_non_zero_mant &&
|
||||||
|
(*((long double*) y) == 0.0L || isinf (*((long double*) y))))
|
||||||
|
errno = ERANGE;
|
||||||
|
|
||||||
|
if (prec || valid_lead_string)
|
||||||
|
return (lenldstr + (s - lstr));
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -380,5 +407,6 @@ long double strtold (const char * __restrict__ s, char ** __restrict__ se)
|
|||||||
lenldstr = __asctoe64( s, xx.us);
|
lenldstr = __asctoe64( s, xx.us);
|
||||||
if (se)
|
if (se)
|
||||||
*se = (char*)s + lenldstr;
|
*se = (char*)s + lenldstr;
|
||||||
|
|
||||||
return xx.ld;
|
return xx.ld;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user