From 857f7dbfa65179e6690dbee7ab915fb4458cee11 Mon Sep 17 00:00:00 2001 From: jiang <30155751@qq.com> Date: Mon, 28 Apr 2014 12:42:36 +0800 Subject: [PATCH] update static void parse_number(const char *p) for tccpp.c --- tccpp.c | 368 ++++++++++++++++++++++---------------------------------- 1 file changed, 143 insertions(+), 225 deletions(-) diff --git a/tccpp.c b/tccpp.c index 2da65cd2..938699e4 100644 --- a/tccpp.c +++ b/tccpp.c @@ -1817,234 +1817,152 @@ static void bn_zero(unsigned int *bn) current token */ static void parse_number(const char *p) { - int b, t, shift, frac_bits, s, exp_val, ch; - char *q; - unsigned int bn[BN_SIZE]; - double d; + int b, t, c; - /* number */ - q = token_buf; - ch = *p++; - t = ch; - ch = *p++; - *q++ = t; + c = *p++; + t = *p++; b = 10; - if (t == '.') { - goto float_frac_parse; - } else if (t == '0') { - if (ch == 'x' || ch == 'X') { - q--; - ch = *p++; + if(c=='.'){ + --p; + goto float_frac_parse; + } + if(c == '0'){ + if (t == 'x' || t == 'X') { b = 16; - } else if (tcc_ext && (ch == 'b' || ch == 'B')) { - q--; - ch = *p++; + c = *p++; + } else if (tcc_ext && (t == 'b' || t == 'B')) { b = 2; - } - } - /* parse all digits. cannot check octal numbers at this stage - because of floating point constants */ - while (1) { - if (ch >= 'a' && ch <= 'f') - t = ch - 'a' + 10; - else if (ch >= 'A' && ch <= 'F') - t = ch - 'A' + 10; - else if (isnum(ch)) - t = ch - '0'; - else - break; - if (t >= b) - break; - if (q >= token_buf + STRING_MAX_SIZE) { - num_too_long: - tcc_error("number too long"); - } - *q++ = ch; - ch = *p++; - } - if (ch == '.' || - ((ch == 'e' || ch == 'E') && b == 10) || - ((ch == 'p' || ch == 'P') && (b == 16 || b == 2))) { - if (b != 10) { - /* NOTE: strtox should support that for hexa numbers, but - non ISOC99 libcs do not support it, so we prefer to do - it by hand */ - /* hexadecimal or binary floats */ - /* XXX: handle overflows */ - *q = '\0'; - if (b == 16) - shift = 4; - else - shift = 2; - bn_zero(bn); - q = token_buf; - while (1) { - t = *q++; - if (t == '\0') { - break; - } else if (t >= 'a') { - t = t - 'a' + 10; - } else if (t >= 'A') { - t = t - 'A' + 10; - } else { - t = t - '0'; - } - bn_lshift(bn, shift, t); - } - frac_bits = 0; - if (ch == '.') { - ch = *p++; - while (1) { - t = ch; - if (t >= 'a' && t <= 'f') { - t = t - 'a' + 10; - } else if (t >= 'A' && t <= 'F') { - t = t - 'A' + 10; - } else if (t >= '0' && t <= '9') { - 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"); - ch = *p++; - s = 1; - exp_val = 0; - if (ch == '+') { - ch = *p++; - } else if (ch == '-') { - s = -1; - ch = *p++; - } - if (ch < '0' || ch > '9') - expect("exponent digits"); - while (ch >= '0' && ch <= '9') { - exp_val = exp_val * 10 + ch - '0'; - ch = *p++; - } - exp_val = exp_val * s; - - /* now we can generate the number */ - /* XXX: should patch directly float number */ - d = (double)bn[1] * 4294967296.0 + (double)bn[0]; - d = ldexp(d, exp_val - frac_bits); - t = toup(ch); - if (t == 'F') { - ch = *p++; - tok = TOK_CFLOAT; - /* float : should handle overflow */ - tokc.f = (float)d; - } else if (t == 'L') { - ch = *p++; -#ifdef TCC_TARGET_PE - tok = TOK_CDOUBLE; - tokc.d = d; -#else - tok = TOK_CLDOUBLE; - /* XXX: not large enough */ - tokc.ld = (long double)d; -#endif - } else { - tok = TOK_CDOUBLE; - tokc.d = d; - } - } 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 { - unsigned long long n, n1; - int lcount, ucount; + c = *p++; + }else{ + --p; + } + }else + --p; + if(strchr(p , '.') || (b == 10 && (strchr(p,'e') || strchr(p,'E'))) || + ((b == 2 || b == 16)&& (strchr(p,'p') || strchr(p,'P')))){ + long double ld, sh, fb; + int exp; + /* NOTE: strtox should support that for hexa numbers, but + non ISOC99 libcs do not support it, so we prefer to do + it by hand */ + /* hexadecimal or binary floats */ + /* XXX: handle overflows */ +float_frac_parse: + fb = 1.0L/b; + sh = b; + ld = 0.0; - /* integer number */ - *q = '\0'; - q = token_buf; - if (b == 10 && *q == '0') { + while(1){ + if (c == '\0') + break; + if (c >= 'a' && c <= 'f') + t = c - 'a' + 10; + else if (c >= 'A' && c <= 'F') + t = c - 'A' + 10; + else if(isnum(c)) + t = c - '0'; + else + break; + if (t >= b) + tcc_error("invalid digit"); + ld = ld * b + t; + c = *p++; + } + if (c == '.'){ + c = *p++; + sh = fb; + while (1){ + if (c == '\0') + break; + if (c >= 'a' && c <= 'f') + t = c - 'a' + 10; + else if (c >= 'A' && c <= 'F') + t = c - 'A' + 10; + else if (isnum(c)) + t =c - '0'; + else + break; + if (t >= b){ + if(b == 10 && (c == 'e' || c == 'E' || c == 'f' || c == 'F')) + break; + tcc_error("invalid digit"); + } + ld += sh*t; + sh*=fb; + c = *p++; + } + } + if ((b == 16 || b == 2) && c != 'p' && c != 'P') + expect("exponent"); + if(((c == 'e' || c == 'E') && b == 10) || + ((c == 'p' || c == 'P') && (b == 16 || b == 2))){ + c = *p++; + if(c == '+' || c == '-'){ + if (c == '-') + sh = fb; + c = *p++; + }else + sh = b; + if (!isnum(c)) + expect("exponent digits"); + exp = 0; + do{ + exp = exp * 10 + c - '0'; + c = *p++; + }while(isnum(c)); + while (exp != 0){ + if (exp & 1) + ld *= sh; + exp >>= 1; + sh *= sh; + } + } + t = toup(c); + if (t == 'F') { + c = *p++; + tok = TOK_CFLOAT; + tokc.f = (float)ld; + } else if (t == 'L') { + c = *p++; +#ifdef TCC_TARGET_PE + tok = TOK_CDOUBLE; + tokc.d = (double)ld; +#else + tok = TOK_CLDOUBLE; + tokc.ld = ld; +#endif + } else { + tok = TOK_CDOUBLE; + tokc.d = (double)ld; + } + } else { + uint64_t n = 0, n1; + int warn = 1; + int lcount, ucount; + if (b == 10 && c == '0') { b = 8; - q++; } - n = 0; - while(1) { - t = *q++; - /* no need for checks except for base 10 / 8 errors */ - if (t == '\0') { - break; - } else if (t >= 'a') { - t = t - 'a' + 10; - } else if (t >= 'A') { - t = t - 'A' + 10; - } else { - t = t - '0'; - if (t >= b) - tcc_error("invalid digit"); - } - n1 = n; - n = n * b + t; - /* detect overflow */ - /* XXX: this test is not reliable */ - if (n < n1) - tcc_error("integer constant overflow"); - } - + while(1){ + if (c == '\0') + break; + if (c >= 'a' && c <= 'f') + t = c - 'a' + 10; + else if (c >= 'A' && c <= 'F') + t = c - 'A' + 10; + else if(isnum(c)) + t = c - '0'; + else + break; + if (t >= b) + tcc_error("invalid digit"); + n1 = n; + n = n * b + t; + if (n < n1 && warn){ + tcc_warning("integer constant overflow"); + warn = 0; + } + c = *p++; + } /* XXX: not exactly ANSI compliant */ if ((n & 0xffffffff00000000LL) != 0) { if ((n >> 63) != 0) @@ -2059,7 +1977,7 @@ static void parse_number(const char *p) lcount = 0; ucount = 0; for(;;) { - t = toup(ch); + t = toup(c); if (t == 'L') { if (lcount >= 2) 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 } #endif - ch = *p++; + c = *p++; } else if (t == 'U') { if (ucount >= 1) tcc_error("two 'u's in integer constant"); @@ -2083,7 +2001,7 @@ static void parse_number(const char *p) tok = TOK_CUINT; else if (tok == TOK_CLLONG) tok = TOK_CULLONG; - ch = *p++; + c = *p++; } else { break; } @@ -2093,7 +2011,7 @@ static void parse_number(const char *p) else tokc.ull = n; } - if (ch) + if (c) tcc_error("invalid number\n"); }