* 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>
|
||||
|
||||
* include/stdio.h (feof): Add inlined definition.
|
||||
|
|
|
@ -21,12 +21,13 @@
|
|||
* removing global variables and splitting out strtold
|
||||
* 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>
|
||||
*/
|
||||
|
||||
|
||||
#include "math/cephes_emath.h"
|
||||
|
||||
#if NE == 10
|
||||
|
||||
/* 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)
|
||||
{
|
||||
unsigned short yy[NI], xt[NI], tt[NI];
|
||||
int esign, decflg, sgnflg, nexp, exp, prec, lost;
|
||||
int k, trail, c;
|
||||
int esign, decflg, nexp, exp, lost;
|
||||
int k, c;
|
||||
int valid_lead_string = 0;
|
||||
int have_non_zero_mant = 0;
|
||||
int prec = 0;
|
||||
/* int trail = 0; */
|
||||
long lexp;
|
||||
unsigned short nsign;
|
||||
unsigned short nsign = 0;
|
||||
const unsigned short *p;
|
||||
char *sp, *lstr;
|
||||
char *s;
|
||||
|
||||
char dec_sym = *(localeconv ()->decimal_point);
|
||||
const char dec_sym = *(localeconv ()->decimal_point);
|
||||
|
||||
int lenldstr = 0;
|
||||
|
||||
|
@ -119,23 +124,58 @@ for( k=0; k<c; k++ )
|
|||
*sp = '\0';
|
||||
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;
|
||||
nsign = 0;
|
||||
decflg = 0;
|
||||
sgnflg = 0;
|
||||
nexp = 0;
|
||||
exp = 0;
|
||||
prec = 0;
|
||||
__ecleaz( yy );
|
||||
trail = 0;
|
||||
|
||||
/* Ignore leading zeros */
|
||||
while (*s == '0')
|
||||
{
|
||||
valid_lead_string = 1;
|
||||
s++;
|
||||
}
|
||||
|
||||
nxtcom:
|
||||
|
||||
k = *s - '0';
|
||||
if( (k >= 0) && (k <= 9) )
|
||||
{
|
||||
/* Ignore leading zeros */
|
||||
if( (prec == 0) && (decflg == 0) && (k == 0) )
|
||||
goto donchr;
|
||||
#if 0
|
||||
/* The use of a special char as a flag for trailing zeroes causes problems when input
|
||||
actually contains the char */
|
||||
/* Identify and strip trailing zeros after the decimal point. */
|
||||
if( (trail == 0) && (decflg != 0) )
|
||||
{
|
||||
|
@ -144,11 +184,15 @@ if( (k >= 0) && (k <= 9) )
|
|||
++sp;
|
||||
--sp;
|
||||
while( *sp == '0' )
|
||||
*sp-- = 'z';
|
||||
trail = 1;
|
||||
if( *s == 'z' )
|
||||
{
|
||||
*sp-- = (char)-1;
|
||||
trail++;
|
||||
}
|
||||
if( *s == (char)-1 )
|
||||
goto donchr;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* If enough digits were given to more than fill up the yy register,
|
||||
* continuing until overflow into the high guard word yy[2]
|
||||
* guarantees that there will be a roundoff bit at the top
|
||||
|
@ -175,71 +219,37 @@ if( (k >= 0) && (k <= 9) )
|
|||
if (decflg == 0)
|
||||
nexp -= 1;
|
||||
}
|
||||
prec += 1;
|
||||
goto donchr;
|
||||
have_non_zero_mant |= k;
|
||||
prec ++;
|
||||
/* goto donchr; */
|
||||
}
|
||||
if (*s == dec_sym)
|
||||
else if (*s == dec_sym)
|
||||
{
|
||||
if( decflg )
|
||||
goto daldone;
|
||||
++decflg;
|
||||
}
|
||||
else
|
||||
switch( *s )
|
||||
else if ((*s == 'E') || (*s == 'e') )
|
||||
{
|
||||
case 'z':
|
||||
break;
|
||||
case 'E':
|
||||
case 'e':
|
||||
if (prec || valid_lead_string)
|
||||
goto expnt;
|
||||
case '-':
|
||||
nsign = 0xffff;
|
||||
if( sgnflg )
|
||||
goto daldone;
|
||||
++sgnflg;
|
||||
break;
|
||||
case '+':
|
||||
if( sgnflg )
|
||||
goto daldone;
|
||||
++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:
|
||||
else
|
||||
goto daldone;
|
||||
}
|
||||
donchr:
|
||||
|
||||
#if 0
|
||||
else if (*s == (char)-1)
|
||||
goto donchr;
|
||||
#endif
|
||||
|
||||
else /* an invalid char */
|
||||
goto daldone;
|
||||
|
||||
/* donchr: */
|
||||
++s;
|
||||
goto nxtcom;
|
||||
|
||||
|
||||
/* Exponent interpretation */
|
||||
expnt:
|
||||
|
||||
|
@ -254,31 +264,39 @@ if( *s == '-' )
|
|||
}
|
||||
if( *s == '+' )
|
||||
++s;
|
||||
while( (*s >= '0') && (*s <= '9') && exp < 4978)
|
||||
|
||||
while( (*s >= '0') && (*s <= '9') )
|
||||
{
|
||||
/* Stop modifying exp if we are going to overflow anyway,
|
||||
but keep parsing the string. */
|
||||
if (exp < 4978)
|
||||
{
|
||||
exp *= 10;
|
||||
exp += *s++ - '0';
|
||||
exp += *s - '0';
|
||||
}
|
||||
s++;
|
||||
}
|
||||
|
||||
if( esign < 0 )
|
||||
exp = -exp;
|
||||
if( exp > 4932 )
|
||||
|
||||
if (exp > 4977) /* maybe overflow */
|
||||
{
|
||||
errno = ERANGE;
|
||||
infinite:
|
||||
__ecleaz(yy);
|
||||
yy[E] = 0x7fff; /* infinity */
|
||||
if (have_non_zero_mant)
|
||||
yy[E] = 0x7fff;
|
||||
goto aexit;
|
||||
}
|
||||
if( exp < -4977 )
|
||||
else if (exp < -4977) /* underflow */
|
||||
{
|
||||
errno = ERANGE;
|
||||
zero:
|
||||
__ecleaz(yy);
|
||||
goto aexit;
|
||||
}
|
||||
|
||||
daldone:
|
||||
|
||||
nexp = exp - nexp;
|
||||
|
||||
/* Pad trailing zeros to minimize power of 10, per IEEE spec. */
|
||||
while( (nexp > 0) && (yy[2] == 0) )
|
||||
{
|
||||
|
@ -363,8 +381,17 @@ __emdnorm( yy, k, 0, lexp, 64, 64 );
|
|||
aexit:
|
||||
|
||||
yy[0] = nsign;
|
||||
|
||||
__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);
|
||||
if (se)
|
||||
*se = (char*)s + lenldstr;
|
||||
|
||||
return xx.ld;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue