mirror of
https://github.com/mirror/tinycc.git
synced 2025-02-10 06:50:10 +08:00
update static void parse_number(const char *p) for tccpp.c
This commit is contained in:
parent
4b50557553
commit
857f7dbfa6
358
tccpp.c
358
tccpp.c
@ -1817,234 +1817,152 @@ static void bn_zero(unsigned int *bn)
|
|||||||
current token */
|
current token */
|
||||||
static void parse_number(const char *p)
|
static void parse_number(const char *p)
|
||||||
{
|
{
|
||||||
int b, t, shift, frac_bits, s, exp_val, ch;
|
int b, t, c;
|
||||||
char *q;
|
|
||||||
unsigned int bn[BN_SIZE];
|
|
||||||
double d;
|
|
||||||
|
|
||||||
/* number */
|
c = *p++;
|
||||||
q = token_buf;
|
t = *p++;
|
||||||
ch = *p++;
|
|
||||||
t = ch;
|
|
||||||
ch = *p++;
|
|
||||||
*q++ = t;
|
|
||||||
b = 10;
|
b = 10;
|
||||||
if (t == '.') {
|
if(c=='.'){
|
||||||
goto float_frac_parse;
|
--p;
|
||||||
} else if (t == '0') {
|
goto float_frac_parse;
|
||||||
if (ch == 'x' || ch == 'X') {
|
}
|
||||||
q--;
|
if(c == '0'){
|
||||||
ch = *p++;
|
if (t == 'x' || t == 'X') {
|
||||||
b = 16;
|
b = 16;
|
||||||
} else if (tcc_ext && (ch == 'b' || ch == 'B')) {
|
c = *p++;
|
||||||
q--;
|
} else if (tcc_ext && (t == 'b' || t == 'B')) {
|
||||||
ch = *p++;
|
|
||||||
b = 2;
|
b = 2;
|
||||||
}
|
c = *p++;
|
||||||
}
|
}else{
|
||||||
/* parse all digits. cannot check octal numbers at this stage
|
--p;
|
||||||
because of floating point constants */
|
}
|
||||||
while (1) {
|
}else
|
||||||
if (ch >= 'a' && ch <= 'f')
|
--p;
|
||||||
t = ch - 'a' + 10;
|
if(strchr(p , '.') || (b == 10 && (strchr(p,'e') || strchr(p,'E'))) ||
|
||||||
else if (ch >= 'A' && ch <= 'F')
|
((b == 2 || b == 16)&& (strchr(p,'p') || strchr(p,'P')))){
|
||||||
t = ch - 'A' + 10;
|
long double ld, sh, fb;
|
||||||
else if (isnum(ch))
|
int exp;
|
||||||
t = ch - '0';
|
/* NOTE: strtox should support that for hexa numbers, but
|
||||||
else
|
non ISOC99 libcs do not support it, so we prefer to do
|
||||||
break;
|
it by hand */
|
||||||
if (t >= b)
|
/* hexadecimal or binary floats */
|
||||||
break;
|
/* XXX: handle overflows */
|
||||||
if (q >= token_buf + STRING_MAX_SIZE) {
|
float_frac_parse:
|
||||||
num_too_long:
|
fb = 1.0L/b;
|
||||||
tcc_error("number too long");
|
sh = b;
|
||||||
}
|
ld = 0.0;
|
||||||
*q++ = ch;
|
|
||||||
ch = *p++;
|
while(1){
|
||||||
}
|
if (c == '\0')
|
||||||
if (ch == '.' ||
|
break;
|
||||||
((ch == 'e' || ch == 'E') && b == 10) ||
|
if (c >= 'a' && c <= 'f')
|
||||||
((ch == 'p' || ch == 'P') && (b == 16 || b == 2))) {
|
t = c - 'a' + 10;
|
||||||
if (b != 10) {
|
else if (c >= 'A' && c <= 'F')
|
||||||
/* NOTE: strtox should support that for hexa numbers, but
|
t = c - 'A' + 10;
|
||||||
non ISOC99 libcs do not support it, so we prefer to do
|
else if(isnum(c))
|
||||||
it by hand */
|
t = c - '0';
|
||||||
/* hexadecimal or binary floats */
|
else
|
||||||
/* XXX: handle overflows */
|
break;
|
||||||
*q = '\0';
|
if (t >= b)
|
||||||
if (b == 16)
|
tcc_error("invalid digit");
|
||||||
shift = 4;
|
ld = ld * b + t;
|
||||||
else
|
c = *p++;
|
||||||
shift = 2;
|
}
|
||||||
bn_zero(bn);
|
if (c == '.'){
|
||||||
q = token_buf;
|
c = *p++;
|
||||||
while (1) {
|
sh = fb;
|
||||||
t = *q++;
|
while (1){
|
||||||
if (t == '\0') {
|
if (c == '\0')
|
||||||
break;
|
break;
|
||||||
} else if (t >= 'a') {
|
if (c >= 'a' && c <= 'f')
|
||||||
t = t - 'a' + 10;
|
t = c - 'a' + 10;
|
||||||
} else if (t >= 'A') {
|
else if (c >= 'A' && c <= 'F')
|
||||||
t = t - 'A' + 10;
|
t = c - 'A' + 10;
|
||||||
} else {
|
else if (isnum(c))
|
||||||
t = t - '0';
|
t =c - '0';
|
||||||
}
|
else
|
||||||
bn_lshift(bn, shift, t);
|
break;
|
||||||
}
|
if (t >= b){
|
||||||
frac_bits = 0;
|
if(b == 10 && (c == 'e' || c == 'E' || c == 'f' || c == 'F'))
|
||||||
if (ch == '.') {
|
break;
|
||||||
ch = *p++;
|
tcc_error("invalid digit");
|
||||||
while (1) {
|
}
|
||||||
t = ch;
|
ld += sh*t;
|
||||||
if (t >= 'a' && t <= 'f') {
|
sh*=fb;
|
||||||
t = t - 'a' + 10;
|
c = *p++;
|
||||||
} else if (t >= 'A' && t <= 'F') {
|
}
|
||||||
t = t - 'A' + 10;
|
}
|
||||||
} else if (t >= '0' && t <= '9') {
|
if ((b == 16 || b == 2) && c != 'p' && c != 'P')
|
||||||
t = t - '0';
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (t >= b)
|
|
||||||
tcc_error("invalid digit");
|
|
||||||
bn_lshift(bn, shift, t);
|
|
||||||
frac_bits += shift;
|
|
||||||
ch = *p++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (ch != 'p' && ch != 'P')
|
|
||||||
expect("exponent");
|
expect("exponent");
|
||||||
ch = *p++;
|
if(((c == 'e' || c == 'E') && b == 10) ||
|
||||||
s = 1;
|
((c == 'p' || c == 'P') && (b == 16 || b == 2))){
|
||||||
exp_val = 0;
|
c = *p++;
|
||||||
if (ch == '+') {
|
if(c == '+' || c == '-'){
|
||||||
ch = *p++;
|
if (c == '-')
|
||||||
} else if (ch == '-') {
|
sh = fb;
|
||||||
s = -1;
|
c = *p++;
|
||||||
ch = *p++;
|
}else
|
||||||
}
|
sh = b;
|
||||||
if (ch < '0' || ch > '9')
|
if (!isnum(c))
|
||||||
expect("exponent digits");
|
expect("exponent digits");
|
||||||
while (ch >= '0' && ch <= '9') {
|
exp = 0;
|
||||||
exp_val = exp_val * 10 + ch - '0';
|
do{
|
||||||
ch = *p++;
|
exp = exp * 10 + c - '0';
|
||||||
}
|
c = *p++;
|
||||||
exp_val = exp_val * s;
|
}while(isnum(c));
|
||||||
|
while (exp != 0){
|
||||||
/* now we can generate the number */
|
if (exp & 1)
|
||||||
/* XXX: should patch directly float number */
|
ld *= sh;
|
||||||
d = (double)bn[1] * 4294967296.0 + (double)bn[0];
|
exp >>= 1;
|
||||||
d = ldexp(d, exp_val - frac_bits);
|
sh *= sh;
|
||||||
t = toup(ch);
|
}
|
||||||
if (t == 'F') {
|
}
|
||||||
ch = *p++;
|
t = toup(c);
|
||||||
tok = TOK_CFLOAT;
|
if (t == 'F') {
|
||||||
/* float : should handle overflow */
|
c = *p++;
|
||||||
tokc.f = (float)d;
|
tok = TOK_CFLOAT;
|
||||||
} else if (t == 'L') {
|
tokc.f = (float)ld;
|
||||||
ch = *p++;
|
} else if (t == 'L') {
|
||||||
|
c = *p++;
|
||||||
#ifdef TCC_TARGET_PE
|
#ifdef TCC_TARGET_PE
|
||||||
tok = TOK_CDOUBLE;
|
tok = TOK_CDOUBLE;
|
||||||
tokc.d = d;
|
tokc.d = (double)ld;
|
||||||
#else
|
#else
|
||||||
tok = TOK_CLDOUBLE;
|
tok = TOK_CLDOUBLE;
|
||||||
/* XXX: not large enough */
|
tokc.ld = ld;
|
||||||
tokc.ld = (long double)d;
|
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
tok = TOK_CDOUBLE;
|
tok = TOK_CDOUBLE;
|
||||||
tokc.d = d;
|
tokc.d = (double)ld;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
/* decimal floats */
|
|
||||||
if (ch == '.') {
|
|
||||||
if (q >= token_buf + STRING_MAX_SIZE)
|
|
||||||
goto num_too_long;
|
|
||||||
*q++ = ch;
|
|
||||||
ch = *p++;
|
|
||||||
float_frac_parse:
|
|
||||||
while (ch >= '0' && ch <= '9') {
|
|
||||||
if (q >= token_buf + STRING_MAX_SIZE)
|
|
||||||
goto num_too_long;
|
|
||||||
*q++ = ch;
|
|
||||||
ch = *p++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (ch == 'e' || ch == 'E') {
|
|
||||||
if (q >= token_buf + STRING_MAX_SIZE)
|
|
||||||
goto num_too_long;
|
|
||||||
*q++ = ch;
|
|
||||||
ch = *p++;
|
|
||||||
if (ch == '-' || ch == '+') {
|
|
||||||
if (q >= token_buf + STRING_MAX_SIZE)
|
|
||||||
goto num_too_long;
|
|
||||||
*q++ = ch;
|
|
||||||
ch = *p++;
|
|
||||||
}
|
|
||||||
if (ch < '0' || ch > '9')
|
|
||||||
expect("exponent digits");
|
|
||||||
while (ch >= '0' && ch <= '9') {
|
|
||||||
if (q >= token_buf + STRING_MAX_SIZE)
|
|
||||||
goto num_too_long;
|
|
||||||
*q++ = ch;
|
|
||||||
ch = *p++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*q = '\0';
|
|
||||||
t = toup(ch);
|
|
||||||
errno = 0;
|
|
||||||
if (t == 'F') {
|
|
||||||
ch = *p++;
|
|
||||||
tok = TOK_CFLOAT;
|
|
||||||
tokc.f = strtof(token_buf, NULL);
|
|
||||||
} else if (t == 'L') {
|
|
||||||
ch = *p++;
|
|
||||||
#ifdef TCC_TARGET_PE
|
|
||||||
tok = TOK_CDOUBLE;
|
|
||||||
tokc.d = strtod(token_buf, NULL);
|
|
||||||
#else
|
|
||||||
tok = TOK_CLDOUBLE;
|
|
||||||
tokc.ld = strtold(token_buf, NULL);
|
|
||||||
#endif
|
|
||||||
} else {
|
|
||||||
tok = TOK_CDOUBLE;
|
|
||||||
tokc.d = strtod(token_buf, NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
unsigned long long n, n1;
|
uint64_t n = 0, n1;
|
||||||
|
int warn = 1;
|
||||||
int lcount, ucount;
|
int lcount, ucount;
|
||||||
|
if (b == 10 && c == '0') {
|
||||||
/* integer number */
|
|
||||||
*q = '\0';
|
|
||||||
q = token_buf;
|
|
||||||
if (b == 10 && *q == '0') {
|
|
||||||
b = 8;
|
b = 8;
|
||||||
q++;
|
|
||||||
}
|
}
|
||||||
n = 0;
|
while(1){
|
||||||
while(1) {
|
if (c == '\0')
|
||||||
t = *q++;
|
break;
|
||||||
/* no need for checks except for base 10 / 8 errors */
|
if (c >= 'a' && c <= 'f')
|
||||||
if (t == '\0') {
|
t = c - 'a' + 10;
|
||||||
break;
|
else if (c >= 'A' && c <= 'F')
|
||||||
} else if (t >= 'a') {
|
t = c - 'A' + 10;
|
||||||
t = t - 'a' + 10;
|
else if(isnum(c))
|
||||||
} else if (t >= 'A') {
|
t = c - '0';
|
||||||
t = t - 'A' + 10;
|
else
|
||||||
} else {
|
break;
|
||||||
t = t - '0';
|
if (t >= b)
|
||||||
if (t >= b)
|
tcc_error("invalid digit");
|
||||||
tcc_error("invalid digit");
|
n1 = n;
|
||||||
}
|
n = n * b + t;
|
||||||
n1 = n;
|
if (n < n1 && warn){
|
||||||
n = n * b + t;
|
tcc_warning("integer constant overflow");
|
||||||
/* detect overflow */
|
warn = 0;
|
||||||
/* XXX: this test is not reliable */
|
}
|
||||||
if (n < n1)
|
c = *p++;
|
||||||
tcc_error("integer constant overflow");
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* XXX: not exactly ANSI compliant */
|
/* XXX: not exactly ANSI compliant */
|
||||||
if ((n & 0xffffffff00000000LL) != 0) {
|
if ((n & 0xffffffff00000000LL) != 0) {
|
||||||
if ((n >> 63) != 0)
|
if ((n >> 63) != 0)
|
||||||
@ -2059,7 +1977,7 @@ static void parse_number(const char *p)
|
|||||||
lcount = 0;
|
lcount = 0;
|
||||||
ucount = 0;
|
ucount = 0;
|
||||||
for(;;) {
|
for(;;) {
|
||||||
t = toup(ch);
|
t = toup(c);
|
||||||
if (t == 'L') {
|
if (t == 'L') {
|
||||||
if (lcount >= 2)
|
if (lcount >= 2)
|
||||||
tcc_error("three 'l's in integer constant");
|
tcc_error("three 'l's in integer constant");
|
||||||
@ -2074,7 +1992,7 @@ static void parse_number(const char *p)
|
|||||||
#if !defined TCC_TARGET_X86_64 || defined TCC_TARGET_PE
|
#if !defined TCC_TARGET_X86_64 || defined TCC_TARGET_PE
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
ch = *p++;
|
c = *p++;
|
||||||
} else if (t == 'U') {
|
} else if (t == 'U') {
|
||||||
if (ucount >= 1)
|
if (ucount >= 1)
|
||||||
tcc_error("two 'u's in integer constant");
|
tcc_error("two 'u's in integer constant");
|
||||||
@ -2083,7 +2001,7 @@ static void parse_number(const char *p)
|
|||||||
tok = TOK_CUINT;
|
tok = TOK_CUINT;
|
||||||
else if (tok == TOK_CLLONG)
|
else if (tok == TOK_CLLONG)
|
||||||
tok = TOK_CULLONG;
|
tok = TOK_CULLONG;
|
||||||
ch = *p++;
|
c = *p++;
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -2093,7 +2011,7 @@ static void parse_number(const char *p)
|
|||||||
else
|
else
|
||||||
tokc.ull = n;
|
tokc.ull = n;
|
||||||
}
|
}
|
||||||
if (ch)
|
if (c)
|
||||||
tcc_error("invalid number\n");
|
tcc_error("invalid number\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user