History

update static void parse_number(const char *p) for tccpp.c

jiang committed 12 years ago

Commit 857f7db1 parent 4b505571 file · +139 −221Browse files

Unified · Split

tccpp.c+139−221
@@ -1817,234 +1817,152 @@ static void bn_zero(unsigned int *bn) · 1816 unmodified lines
18171817 current token */
18181818 static void parse_number(const char *p)
18191819 {
1820− int b, t, shift, frac_bits, s, exp_val, ch;
1821− char *q;
1822− unsigned int bn[BN_SIZE];
1823− double d;
1824−
1825− /* number */
1826− q = token_buf;
1827− ch = *p++;
1828− t = ch;
1829− ch = *p++;
1830− *q++ = t;
1820+ int b, t, c;
1821+
1822+ c = *p++;
1823+ t = *p++;
18311824 b = 10;
1832− if (t == '.') {
1833− goto float_frac_parse;
1834− } else if (t == '0') {
1835− if (ch == 'x' || ch == 'X') {
1836− q--;
1837− ch = *p++;
1825+ if(c=='.'){
1826+ --p;
1827+ goto float_frac_parse;
1828+ }
1829+ if(c == '0'){
1830+ if (t == 'x' || t == 'X') {
18381831 b = 16;
1839− } else if (tcc_ext && (ch == 'b' || ch == 'B')) {
1840− q--;
1841− ch = *p++;
1832+ c = *p++;
1833+ } else if (tcc_ext && (t == 'b' || t == 'B')) {
18421834 b = 2;
1843− }
1844− }
1845− /* parse all digits. cannot check octal numbers at this stage
1846− because of floating point constants */
1847− while (1) {
1848− if (ch >= 'a' && ch <= 'f')
1849− t = ch - 'a' + 10;
1850− else if (ch >= 'A' && ch <= 'F')
1851− t = ch - 'A' + 10;
1852− else if (isnum(ch))
1853− t = ch - '0';
1854− else
1855− break;
1856− if (t >= b)
1857− break;
1858− if (q >= token_buf + STRING_MAX_SIZE) {
1859− num_too_long:
1860− tcc_error("number too long");
1861− }
1862− *q++ = ch;
1863− ch = *p++;
1864− }
1865− if (ch == '.' ||
1866− ((ch == 'e' || ch == 'E') && b == 10) ||
1867− ((ch == 'p' || ch == 'P') && (b == 16 || b == 2))) {
1868− if (b != 10) {
1869− /* NOTE: strtox should support that for hexa numbers, but
1870− non ISOC99 libcs do not support it, so we prefer to do
1871− it by hand */
1872− /* hexadecimal or binary floats */
1873− /* XXX: handle overflows */
1874− *q = '\0';
1875− if (b == 16)
1876− shift = 4;
1877− else
1878− shift = 2;
1879− bn_zero(bn);
1880− q = token_buf;
1881− while (1) {
1882− t = *q++;
1883− if (t == '\0') {
1884− break;
1885− } else if (t >= 'a') {
1886− t = t - 'a' + 10;
1887− } else if (t >= 'A') {
1888− t = t - 'A' + 10;
1889− } else {
1890− t = t - '0';
1891− }
1892− bn_lshift(bn, shift, t);
1893− }
1894− frac_bits = 0;
1895− if (ch == '.') {
1896− ch = *p++;
1897− while (1) {
1898− t = ch;
1899− if (t >= 'a' && t <= 'f') {
1900− t = t - 'a' + 10;
1901− } else if (t >= 'A' && t <= 'F') {
1902− t = t - 'A' + 10;
1903− } else if (t >= '0' && t <= '9') {
1904− t = t - '0';
1905− } else {
1906− break;
1907− }
1908− if (t >= b)
1909− tcc_error("invalid digit");
1910− bn_lshift(bn, shift, t);
1911− frac_bits += shift;
1912− ch = *p++;
1913− }
1914− }
1915− if (ch != 'p' && ch != 'P')
1835+ c = *p++;
1836+ }else{
1837+ --p;
1838+ }
1839+ }else
1840+ --p;
1841+ if(strchr(p , '.') || (b == 10 && (strchr(p,'e') || strchr(p,'E'))) ||
1842+ ((b == 2 || b == 16)&& (strchr(p,'p') || strchr(p,'P')))){
1843+ long double ld, sh, fb;
1844+ int exp;
1845+ /* NOTE: strtox should support that for hexa numbers, but
1846+ non ISOC99 libcs do not support it, so we prefer to do
1847+ it by hand */
1848+ /* hexadecimal or binary floats */
1849+ /* XXX: handle overflows */
1850+float_frac_parse:
1851+ fb = 1.0L/b;
1852+ sh = b;
1853+ ld = 0.0;
1854+
1855+ while(1){
1856+ if (c == '\0')
1857+ break;
1858+ if (c >= 'a' && c <= 'f')
1859+ t = c - 'a' + 10;
1860+ else if (c >= 'A' && c <= 'F')
1861+ t = c - 'A' + 10;
1862+ else if(isnum(c))
1863+ t = c - '0';
1864+ else
1865+ break;
1866+ if (t >= b)
1867+ tcc_error("invalid digit");
1868+ ld = ld * b + t;
1869+ c = *p++;
1870+ }
1871+ if (c == '.'){
1872+ c = *p++;
1873+ sh = fb;
1874+ while (1){
1875+ if (c == '\0')
1876+ break;
1877+ if (c >= 'a' && c <= 'f')
1878+ t = c - 'a' + 10;
1879+ else if (c >= 'A' && c <= 'F')
1880+ t = c - 'A' + 10;
1881+ else if (isnum(c))
1882+ t =c - '0';
1883+ else
1884+ break;
1885+ if (t >= b){
1886+ if(b == 10 && (c == 'e' || c == 'E' || c == 'f' || c == 'F'))
1887+ break;
1888+ tcc_error("invalid digit");
1889+ }
1890+ ld += sh*t;
1891+ sh*=fb;
1892+ c = *p++;
1893+ }
1894+ }
1895+ if ((b == 16 || b == 2) && c != 'p' && c != 'P')
19161896 expect("exponent");
1917− ch = *p++;
1918− s = 1;
1919− exp_val = 0;
1920− if (ch == '+') {
1921− ch = *p++;
1922− } else if (ch == '-') {
1923− s = -1;
1924− ch = *p++;
1925− }
1926− if (ch < '0' || ch > '9')
1927− expect("exponent digits");
1928− while (ch >= '0' && ch <= '9') {
1929− exp_val = exp_val * 10 + ch - '0';
1930− ch = *p++;
1931− }
1932− exp_val = exp_val * s;
1933−
1934− /* now we can generate the number */
1935− /* XXX: should patch directly float number */
1936− d = (double)bn[1] * 4294967296.0 + (double)bn[0];
1937− d = ldexp(d, exp_val - frac_bits);
1938− t = toup(ch);
1939− if (t == 'F') {
1940− ch = *p++;
1941− tok = TOK_CFLOAT;
1942− /* float : should handle overflow */
1943− tokc.f = (float)d;
1944− } else if (t == 'L') {
1945− ch = *p++;
1897+ if(((c == 'e' || c == 'E') && b == 10) ||
1898+ ((c == 'p' || c == 'P') && (b == 16 || b == 2))){
1899+ c = *p++;
1900+ if(c == '+' || c == '-'){
1901+ if (c == '-')
1902+ sh = fb;
1903+ c = *p++;
1904+ }else
1905+ sh = b;
1906+ if (!isnum(c))
1907+ expect("exponent digits");
1908+ exp = 0;
1909+ do{
1910+ exp = exp * 10 + c - '0';
1911+ c = *p++;
1912+ }while(isnum(c));
1913+ while (exp != 0){
1914+ if (exp & 1)
1915+ ld *= sh;
1916+ exp >>= 1;
1917+ sh *= sh;
1918+ }
1919+ }
1920+ t = toup(c);
1921+ if (t == 'F') {
1922+ c = *p++;
1923+ tok = TOK_CFLOAT;
1924+ tokc.f = (float)ld;
1925+ } else if (t == 'L') {
1926+ c = *p++;
19461927 #ifdef TCC_TARGET_PE
1947− tok = TOK_CDOUBLE;
1948− tokc.d = d;
1928+ tok = TOK_CDOUBLE;
1929+ tokc.d = (double)ld;
19491930 #else
1950− tok = TOK_CLDOUBLE;
1951− /* XXX: not large enough */
1952− tokc.ld = (long double)d;
1931+ tok = TOK_CLDOUBLE;
1932+ tokc.ld = ld;
19531933 #endif
1954− } else {
1955− tok = TOK_CDOUBLE;
1956− tokc.d = d;
1957− }
1958− } else {
1959− /* decimal floats */
1960− if (ch == '.') {
1961− if (q >= token_buf + STRING_MAX_SIZE)
1962− goto num_too_long;
1963− *q++ = ch;
1964− ch = *p++;
1965− float_frac_parse:
1966− while (ch >= '0' && ch <= '9') {
1967− if (q >= token_buf + STRING_MAX_SIZE)
1968− goto num_too_long;
1969− *q++ = ch;
1970− ch = *p++;
1971− }
1972− }
1973− if (ch == 'e' || ch == 'E') {
1974− if (q >= token_buf + STRING_MAX_SIZE)
1975− goto num_too_long;
1976− *q++ = ch;
1977− ch = *p++;
1978− if (ch == '-' || ch == '+') {
1979− if (q >= token_buf + STRING_MAX_SIZE)
1980− goto num_too_long;
1981− *q++ = ch;
1982− ch = *p++;
1983− }
1984− if (ch < '0' || ch > '9')
1985− expect("exponent digits");
1986− while (ch >= '0' && ch <= '9') {
1987− if (q >= token_buf + STRING_MAX_SIZE)
1988− goto num_too_long;
1989− *q++ = ch;
1990− ch = *p++;
1991− }
1992− }
1993− *q = '\0';
1994− t = toup(ch);
1995− errno = 0;
1996− if (t == 'F') {
1997− ch = *p++;
1998− tok = TOK_CFLOAT;
1999− tokc.f = strtof(token_buf, NULL);
2000− } else if (t == 'L') {
2001− ch = *p++;
2002−#ifdef TCC_TARGET_PE
2003− tok = TOK_CDOUBLE;
2004− tokc.d = strtod(token_buf, NULL);
2005−#else
2006− tok = TOK_CLDOUBLE;
2007− tokc.ld = strtold(token_buf, NULL);
2008−#endif
2009− } else {
2010− tok = TOK_CDOUBLE;
2011− tokc.d = strtod(token_buf, NULL);
2012− }
2013− }
1934+ } else {
1935+ tok = TOK_CDOUBLE;
1936+ tokc.d = (double)ld;
1937+ }
20141938 } else {
2015− unsigned long long n, n1;
1939+ uint64_t n = 0, n1;
1940+ int warn = 1;
20161941 int lcount, ucount;
2017−
2018− /* integer number */
2019− *q = '\0';
2020− q = token_buf;
2021− if (b == 10 && *q == '0') {
1942+ if (b == 10 && c == '0') {
20221943 b = 8;
2023− q++;
2024− }
2025− n = 0;
2026− while(1) {
2027− t = *q++;
2028− /* no need for checks except for base 10 / 8 errors */
2029− if (t == '\0') {
2030− break;
2031− } else if (t >= 'a') {
2032− t = t - 'a' + 10;
2033− } else if (t >= 'A') {
2034− t = t - 'A' + 10;
2035− } else {
2036− t = t - '0';
2037− if (t >= b)
2038− tcc_error("invalid digit");
2039− }
2040− n1 = n;
2041− n = n * b + t;
2042− /* detect overflow */
2043− /* XXX: this test is not reliable */
2044− if (n < n1)
2045− tcc_error("integer constant overflow");
20461944 }
2047−
1945+ while(1){
1946+ if (c == '\0')
1947+ break;
1948+ if (c >= 'a' && c <= 'f')
1949+ t = c - 'a' + 10;
1950+ else if (c >= 'A' && c <= 'F')
1951+ t = c - 'A' + 10;
1952+ else if(isnum(c))
1953+ t = c - '0';
1954+ else
1955+ break;
1956+ if (t >= b)
1957+ tcc_error("invalid digit");
1958+ n1 = n;
1959+ n = n * b + t;
1960+ if (n < n1 && warn){
1961+ tcc_warning("integer constant overflow");
1962+ warn = 0;
1963+ }
1964+ c = *p++;
1965+ }
20481966 /* XXX: not exactly ANSI compliant */
20491967 if ((n & 0xffffffff00000000LL) != 0) {
20501968 if ((n >> 63) != 0)
@@ -2059,7 +1977,7 @@ static void parse_number(const char *p) · 8 unmodified lines
20591977 lcount = 0;
20601978 ucount = 0;
20611979 for(;;) {
2062− t = toup(ch);
1980+ t = toup(c);
20631981 if (t == 'L') {
20641982 if (lcount >= 2)
20651983 tcc_error("three 'l's in integer constant");
@@ -2074,7 +1992,7 @@ static void parse_number(const char *p) · 8 unmodified lines
20741992 #if !defined TCC_TARGET_X86_64 || defined TCC_TARGET_PE
20751993 }
20761994 #endif
2077− ch = *p++;
1995+ c = *p++;
20781996 } else if (t == 'U') {
20791997 if (ucount >= 1)
20801998 tcc_error("two 'u's in integer constant");
@@ -2083,7 +2001,7 @@ static void parse_number(const char *p) · 2 unmodified lines
20832001 tok = TOK_CUINT;
20842002 else if (tok == TOK_CLLONG)
20852003 tok = TOK_CULLONG;
2086− ch = *p++;
2004+ c = *p++;
20872005 } else {
20882006 break;
20892007 }
@@ -2093,7 +2011,7 @@ static void parse_number(const char *p) · 3 unmodified lines
20932011 else
20942012 tokc.ull = n;
20952013 }
2096− if (ch)
2014+ if (c)
20972015 tcc_error("invalid number\n");
20982016 }
20992017

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t