#define UCASE(c) ((('a' <= c) && (c <= 'z'))? c - 32 : c)
#define NZDIGIT(c) (('1' <= c && c <= '9') || ((int)form < 0 && \
(('a' <= c && c <= 'f') || ('A' <= c && c <= 'F'))))
{
static const char *infstring = "INFINITY";
static const char *nanstring = "NAN";
int sigfound, spacefound = 0;
int ids = 0;
int i, agree;
int nzbp = 0;
int nzap = 0;
char decpt;
int nfast, nfastlimit;
char *pfast;
int e, esign;
int expshift = 0;
enum decimal_string_form form;
if (fortran_conventions > 0)
decpt = '.';
else
decpt = *(localeconv_l(loc)->decimal_point);
pd->fpclass = fp_signaling;
pd->sign = 0;
pd->exponent = 0;
pd->ds[0] = '\0';
pd->more = 0;
pd->ndigits = 0;
*pform = form = invalid_form;
*pechar = NULL;
while (isspace_l(current, loc)) {
spacefound = 1;
NEXT;
}
if (fortran_conventions >= 2 && spacefound) {
pd->fpclass = fp_zero;
form = whitespace_form;
sigfound = 0;
if (current == EOF) {
good = cp;
goto done;
} else {
good = cp - 1;
}
} else {
sigfound = -1;
}
if (current == '+') {
NEXT;
} else if (current == '-') {
pd->sign = 1;
NEXT;
}
if ('1' <= current && current <= '9') {
good = cp;
pd->fpclass = fp_normal;
form = fixed_int_form;
sigfound = 1;
pd->ds[ids++] = (char)current;
NEXT;
} else {
switch (current) {
case ' ':
if (fortran_conventions < 2)
goto done;
case '0':
good = cp;
pd->fpclass = fp_zero;
if (fortran_conventions < 0) {
NEXT;
if (current == 'X' || current == 'x') {
form = (enum decimal_string_form)-1;
expshift = 2;
NEXT;
if (NZDIGIT(current)) {
pd->fpclass = fp_normal;
good = cp;
sigfound = 1;
pd->ds[ids++] = (char)current;
NEXT;
break;
} else if (current == decpt) {
NEXT;
goto afterpoint;
} else if (current != '0') {
form = fixed_int_form;
expshift = 0;
goto done;
}
} else {
form = fixed_int_form;
}
} else {
form = fixed_int_form;
}
while (current == '0' || (current == ' ' &&
fortran_conventions >= 2)) {
NEXT;
}
sigfound = 0;
if (current == EOF) {
good = cp;
goto done;
} else {
good = cp - 1;
}
break;
case 'i':
case 'I':
NEXT;
agree = 1;
while (agree <= 7 &&
UCASE(current) == infstring[agree]) {
NEXT;
agree++;
}
if (agree < 3)
goto done;
pd->fpclass = fp_infinity;
sigfound = 1;
__inf_read = 1;
if (agree < 8) {
good = (current == EOF)? cp + 3 - agree :
cp + 2 - agree;
form = inf_form;
} else {
good = (current == EOF)? cp : cp - 1;
form = infinity_form;
}
if (fortran_conventions >= 2 && (agree == 3 ||
agree == 8)) {
while (current == ' ') {
NEXT;
}
good = (current == EOF)? cp : cp - 1;
}
goto done;
case 'n':
case 'N':
NEXT;
agree = 1;
while (agree <= 2 &&
UCASE(current) == nanstring[agree]) {
NEXT;
agree++;
}
if (agree < 3)
goto done;
good = (current == EOF)? cp : cp - 1;
pd->fpclass = fp_quiet;
form = nan_form;
sigfound = 1;
__nan_read = 1;
if (current == '(') {
NEXT;
if (fortran_conventions < 0) {
while ((isalnum_l(current, loc) ||
current == '_') &&
ids < DECIMAL_STRING_LENGTH - 1) {
pd->ds[ids++] = (char)current;
NEXT;
}
while (isalnum_l(current, loc) ||
current == '_') {
pd->more = 1;
NEXT;
}
} else {
while (current > 0 && current != ')' &&
ids < DECIMAL_STRING_LENGTH - 1) {
pd->ds[ids++] = (char)current;
NEXT;
}
while (current > 0 && current != ')') {
pd->more = 1;
NEXT;
}
}
if (current != ')')
goto done;
good = cp;
form = nanstring_form;
if (fortran_conventions >= 2) {
NEXT;
}
}
if (fortran_conventions >= 2) {
while (current == ' ') {
NEXT;
}
good = (current == EOF)? cp : cp - 1;
}
goto done;
default:
if (current == decpt) {
NEXT;
goto afterpoint;
}
goto done;
}
}
nextnumber:
if (NZDIGIT(current)) {
if (ids + nzbp + 2 < DECIMAL_STRING_LENGTH) {
for (i = 0; i < nzbp; i++)
pd->ds[ids++] = '0';
pd->ds[ids++] = (char)current;
} else {
pd->exponent += (nzbp + 1) << expshift;
pd->more = 1;
if (ids < DECIMAL_STRING_LENGTH) {
pd->ds[ids] = '\0';
pd->ndigits = ids;
ids = DECIMAL_STRING_LENGTH;
}
}
pd->fpclass = fp_normal;
sigfound = 1;
nzbp = 0;
NEXT;
nfastlimit = DECIMAL_STRING_LENGTH - 3 - ids;
for (nfast = 0, pfast = &(pd->ds[ids]);
nfast < nfastlimit && NZDIGIT(current);
nfast++) {
*pfast++ = (char)current;
NEXT;
}
ids += nfast;
if (current == '0')
goto nextnumberzero;
good = (current == EOF)? cp : cp - 1;
goto nextnumber;
} else {
switch (current) {
case ' ':
if (fortran_conventions < 2)
goto done;
if (fortran_conventions == 2) {
while (current == ' ') {
NEXT;
}
good = (current == EOF)? cp : cp - 1;
goto nextnumber;
}
case '0':
nextnumberzero:
while (current == '0' || (current == ' ' &&
fortran_conventions > 2)) {
nzbp++;
NEXT;
}
good = (current == EOF)? cp : cp - 1;
goto nextnumber;
case '+':
case '-':
case 'D':
case 'd':
case 'Q':
case 'q':
if (fortran_conventions <= 0)
goto done;
case 'E':
case 'e':
if ((int)form < 0)
goto done;
goto exponent;
case 'P':
case 'p':
if ((int)form > 0)
goto done;
goto exponent;
default:
if (current == decpt) {
good = cp;
if (form == fixed_int_form)
form = fixed_intdot_form;
NEXT;
goto afterpoint;
}
goto done;
}
}
afterpoint:
if (NZDIGIT(current)) {
if (form == invalid_form || form == whitespace_form)
form = fixed_dotfrac_form;
else if (form == fixed_intdot_form)
form = fixed_intdotfrac_form;
good = cp;
if (sigfound < 1) {
pd->fpclass = fp_normal;
sigfound = 1;
pd->ds[ids++] = (char)current;
pd->exponent = (-(nzap + 1)) << expshift;
} else {
if (ids + nzbp + nzap + 2 < DECIMAL_STRING_LENGTH) {
for (i = 0; i < nzbp + nzap; i++)
pd->ds[ids++] = '0';
pd->ds[ids++] = (char)current;
pd->exponent -= (nzap + 1) << expshift;
} else {
pd->exponent += nzbp << expshift;
pd->more = 1;
if (ids < DECIMAL_STRING_LENGTH) {
pd->ds[ids] = '\0';
pd->ndigits = ids;
ids = DECIMAL_STRING_LENGTH;
}
}
}
nzbp = 0;
nzap = 0;
NEXT;
nfastlimit = DECIMAL_STRING_LENGTH - 3 - ids;
for (nfast = 0, pfast = &(pd->ds[ids]);
nfast < nfastlimit && NZDIGIT(current);
nfast++) {
*pfast++ = (char)current;
NEXT;
}
ids += nfast;
pd->exponent -= nfast << expshift;
if (current == '0')
goto zeroafterpoint;
good = (current == EOF)? cp : cp - 1;
goto afterpoint;
} else {
switch (current) {
case ' ':
if (fortran_conventions < 2)
goto done;
if (fortran_conventions == 2) {
if (sigfound == -1) {
pd->fpclass = fp_zero;
sigfound = 0;
}
while (current == ' ') {
NEXT;
}
good = (current == EOF)? cp : cp - 1;
goto afterpoint;
}
case '0':
if (form == invalid_form || form == whitespace_form)
form = fixed_dotfrac_form;
else if (form == fixed_intdot_form)
form = fixed_intdotfrac_form;
if (sigfound == -1) {
pd->fpclass = fp_zero;
sigfound = 0;
}
zeroafterpoint:
while (current == '0' || (current == ' ' &&
fortran_conventions > 2)) {
nzap++;
NEXT;
}
if (current == EOF) {
good = cp;
goto done;
} else {
good = cp - 1;
}
goto afterpoint;
case '+':
case '-':
case 'D':
case 'd':
case 'Q':
case 'q':
if (fortran_conventions <= 0)
goto done;
case 'E':
case 'e':
if (sigfound == -1 || (int)form < 0)
goto done;
break;
case 'P':
case 'p':
if (sigfound == -1 || (int)form > 0)
goto done;
break;
default:
goto done;
}
}
exponent:
*pechar = cp;
if (current != '+' && current != '-') {
NEXT;
if (fortran_conventions >= 2 && current == ' ') {
while (current == ' ') {
NEXT;
}
if (fortran_conventions > 2)
good = (current == EOF)? cp : cp - 1;
}
}
e = 0;
esign = 0;
if (current == '+') {
NEXT;
} else if (current == '-') {
esign = 1;
NEXT;
}
while (('0' <= current && current <= '9') || current == ' ') {
if (current == ' ') {
if (fortran_conventions < 2)
break;
if (fortran_conventions == 2) {
NEXT;
continue;
}
current = '0';
}
good = cp;
if (e <= 1000000)
e = 10 * e + current - '0';
NEXT;
if (fortran_conventions == 2 && current == ' ') {
while (current == ' ') {
NEXT;
}
good = (current == EOF)? cp : cp - 1;
}
}
if (esign == 1)
pd->exponent -= e;
else
pd->exponent += e;
if (good >= *pechar) {
switch (form) {
case whitespace_form:
case fixed_int_form:
form = floating_int_form;
break;
case fixed_intdot_form:
form = floating_intdot_form;
break;
case fixed_dotfrac_form:
form = floating_dotfrac_form;
break;
case fixed_intdotfrac_form:
form = floating_intdotfrac_form;
break;
}
} else {
*pechar = NULL;
}
done:
pd->exponent += nzbp << expshift;
if (ids < DECIMAL_STRING_LENGTH) {
pd->ds[ids] = '\0';
pd->ndigits = ids;
}
if (good >= *ppc) {
*ppc = good + 1;
} else {
pd->fpclass = fp_signaling;
pd->sign = 0;
form = invalid_form;
}
*pform = form;
}