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
1817 current token */1817 current token */
1818static void parse_number(const char *p)1818static void parse_number(const char *p)
1819{1819{
1820 int b, t, shift, frac_bits, s, exp_val, ch;1820 int b, t, c;
1821 char *q;1821
1822 unsigned int bn[BN_SIZE];1822 c = *p++;
1823 double d;1823 t = *p++;
1824
1825 /* number */
1826 q = token_buf;
1827 ch = *p++;
1828 t = ch;
1829 ch = *p++;
1830 *q++ = t;
1831 b = 10;1824 b = 10;
1832 if (t == '.') {1825 if(c=='.'){
1833 goto float_frac_parse;1826 --p;
1834 } else if (t == '0') {1827 goto float_frac_parse;
1835 if (ch == 'x' || ch == 'X') {1828 }
1836 q--;1829 if(c == '0'){
1837 ch = *p++;1830 if (t == 'x' || t == 'X') {
1838 b = 16;1831 b = 16;
1839 } else if (tcc_ext && (ch == 'b' || ch == 'B')) {1832 c = *p++;
1840 q--;1833 } else if (tcc_ext && (t == 'b' || t == 'B')) {
1841 ch = *p++;
1842 b = 2;1834 b = 2;
1843 }1835 c = *p++;
1844 }1836 }else{
1845 /* parse all digits. cannot check octal numbers at this stage1837 --p;
1846 because of floating point constants */1838 }
1847 while (1) {1839 }else
1848 if (ch >= 'a' && ch <= 'f')1840 --p;
1849 t = ch - 'a' + 10;1841 if(strchr(p , '.') || (b == 10 && (strchr(p,'e') || strchr(p,'E'))) ||
1850 else if (ch >= 'A' && ch <= 'F')1842 ((b == 2 || b == 16)&& (strchr(p,'p') || strchr(p,'P')))){
1851 t = ch - 'A' + 10;1843 long double ld, sh, fb;
1852 else if (isnum(ch))1844 int exp;
1853 t = ch - '0';1845 /* NOTE: strtox should support that for hexa numbers, but
1854 else1846 non ISOC99 libcs do not support it, so we prefer to do
1855 break;1847 it by hand */
1856 if (t >= b)1848 /* hexadecimal or binary floats */
1857 break;1849 /* XXX: handle overflows */
1858 if (q >= token_buf + STRING_MAX_SIZE) {1850float_frac_parse:
1859 num_too_long:1851 fb = 1.0L/b;
1860 tcc_error("number too long");1852 sh = b;
1861 }1853 ld = 0.0;
1862 *q++ = ch;1854
1863 ch = *p++;1855 while(1){
1864 }1856 if (c == '\0')
1865 if (ch == '.' ||1857 break;
1866 ((ch == 'e' || ch == 'E') && b == 10) ||1858 if (c >= 'a' && c <= 'f')
1867 ((ch == 'p' || ch == 'P') && (b == 16 || b == 2))) {1859 t = c - 'a' + 10;
1868 if (b != 10) {1860 else if (c >= 'A' && c <= 'F')
1869 /* NOTE: strtox should support that for hexa numbers, but1861 t = c - 'A' + 10;
1870 non ISOC99 libcs do not support it, so we prefer to do1862 else if(isnum(c))
1871 it by hand */1863 t = c - '0';
1872 /* hexadecimal or binary floats */1864 else
1873 /* XXX: handle overflows */1865 break;
1874 *q = '\0';1866 if (t >= b)
1875 if (b == 16)1867 tcc_error("invalid digit");
1876 shift = 4;1868 ld = ld * b + t;
1877 else 1869 c = *p++;
1878 shift = 2;1870 }
1879 bn_zero(bn);1871 if (c == '.'){
1880 q = token_buf;1872 c = *p++;
1881 while (1) {1873 sh = fb;
1882 t = *q++;1874 while (1){
1883 if (t == '\0') {1875 if (c == '\0')
1884 break;1876 break;
1885 } else if (t >= 'a') {1877 if (c >= 'a' && c <= 'f')
1886 t = t - 'a' + 10;1878 t = c - 'a' + 10;
1887 } else if (t >= 'A') {1879 else if (c >= 'A' && c <= 'F')
1888 t = t - 'A' + 10;1880 t = c - 'A' + 10;
1889 } else {1881 else if (isnum(c))
1890 t = t - '0';1882 t =c - '0';
1891 }1883 else
1892 bn_lshift(bn, shift, t);1884 break;
1893 }1885 if (t >= b){
1894 frac_bits = 0;1886 if(b == 10 && (c == 'e' || c == 'E' || c == 'f' || c == 'F'))
1895 if (ch == '.') {1887 break;
1896 ch = *p++;1888 tcc_error("invalid digit");
1897 while (1) {1889 }
1898 t = ch;1890 ld += sh*t;
1899 if (t >= 'a' && t <= 'f') {1891 sh*=fb;
1900 t = t - 'a' + 10;1892 c = *p++;
1901 } else if (t >= 'A' && t <= 'F') {1893 }
1902 t = t - 'A' + 10;1894 }
1903 } else if (t >= '0' && t <= '9') {1895 if ((b == 16 || b == 2) && c != 'p' && c != 'P')
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')
1916 expect("exponent");1896 expect("exponent");
1917 ch = *p++;1897 if(((c == 'e' || c == 'E') && b == 10) ||
1918 s = 1;1898 ((c == 'p' || c == 'P') && (b == 16 || b == 2))){
1919 exp_val = 0;1899 c = *p++;
1920 if (ch == '+') {1900 if(c == '+' || c == '-'){
1921 ch = *p++;1901 if (c == '-')
1922 } else if (ch == '-') {1902 sh = fb;
1923 s = -1;1903 c = *p++;
1924 ch = *p++;1904 }else
1925 }1905 sh = b;
1926 if (ch < '0' || ch > '9')1906 if (!isnum(c))
1927 expect("exponent digits");1907 expect("exponent digits");
1928 while (ch >= '0' && ch <= '9') {1908 exp = 0;
1929 exp_val = exp_val * 10 + ch - '0';1909 do{
1930 ch = *p++;1910 exp = exp * 10 + c - '0';
1931 }1911 c = *p++;
1932 exp_val = exp_val * s;1912 }while(isnum(c));
1933 1913 while (exp != 0){
1934 /* now we can generate the number */1914 if (exp & 1)
1935 /* XXX: should patch directly float number */1915 ld *= sh;
1936 d = (double)bn[1] * 4294967296.0 + (double)bn[0];1916 exp >>= 1;
1937 d = ldexp(d, exp_val - frac_bits);1917 sh *= sh;
1938 t = toup(ch);1918 }
1939 if (t == 'F') {1919 }
1940 ch = *p++;1920 t = toup(c);
1941 tok = TOK_CFLOAT;1921 if (t == 'F') {
1942 /* float : should handle overflow */1922 c = *p++;
1943 tokc.f = (float)d;1923 tok = TOK_CFLOAT;
1944 } else if (t == 'L') {1924 tokc.f = (float)ld;
1945 ch = *p++;1925 } else if (t == 'L') {
1926 c = *p++;
1946#ifdef TCC_TARGET_PE1927#ifdef TCC_TARGET_PE
1947 tok = TOK_CDOUBLE;1928 tok = TOK_CDOUBLE;
1948 tokc.d = d;1929 tokc.d = (double)ld;
1949#else1930#else
1950 tok = TOK_CLDOUBLE;1931 tok = TOK_CLDOUBLE;
1951 /* XXX: not large enough */1932 tokc.ld = ld;
1952 tokc.ld = (long double)d;
1953#endif1933#endif
1954 } else {1934 } else {
1955 tok = TOK_CDOUBLE;1935 tok = TOK_CDOUBLE;
1956 tokc.d = d;1936 tokc.d = (double)ld;
1957 }1937 }
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 }
2014 } else {1938 } else {
2015 unsigned long long n, n1;1939 uint64_t n = 0, n1;
1940 int warn = 1;
2016 int lcount, ucount;1941 int lcount, ucount;
2017 1942 if (b == 10 && c == '0') {
2018 /* integer number */
2019 *q = '\0';
2020 q = token_buf;
2021 if (b == 10 && *q == '0') {
2022 b = 8;1943 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");
2046 }1944 }
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 }
2048 /* XXX: not exactly ANSI compliant */1966 /* XXX: not exactly ANSI compliant */
2049 if ((n & 0xffffffff00000000LL) != 0) {1967 if ((n & 0xffffffff00000000LL) != 0) {
2050 if ((n >> 63) != 0)1968 if ((n >> 63) != 0)
@@ -2059,7 +1977,7 @@ static void parse_number(const char *p) · 8 unmodified lines
2059 lcount = 0;1977 lcount = 0;
2060 ucount = 0;1978 ucount = 0;
2061 for(;;) {1979 for(;;) {
2062 t = toup(ch);1980 t = toup(c);
2063 if (t == 'L') {1981 if (t == 'L') {
2064 if (lcount >= 2)1982 if (lcount >= 2)
2065 tcc_error("three 'l's in integer constant");1983 tcc_error("three 'l's in integer constant");
@@ -2074,7 +1992,7 @@ static void parse_number(const char *p) · 8 unmodified lines
2074#if !defined TCC_TARGET_X86_64 || defined TCC_TARGET_PE1992#if !defined TCC_TARGET_X86_64 || defined TCC_TARGET_PE
2075 }1993 }
2076#endif1994#endif
2077 ch = *p++;1995 c = *p++;
2078 } else if (t == 'U') {1996 } else if (t == 'U') {
2079 if (ucount >= 1)1997 if (ucount >= 1)
2080 tcc_error("two 'u's in integer constant");1998 tcc_error("two 'u's in integer constant");
@@ -2083,7 +2001,7 @@ static void parse_number(const char *p) · 2 unmodified lines
2083 tok = TOK_CUINT;2001 tok = TOK_CUINT;
2084 else if (tok == TOK_CLLONG)2002 else if (tok == TOK_CLLONG)
2085 tok = TOK_CULLONG;2003 tok = TOK_CULLONG;
2086 ch = *p++;2004 c = *p++;
2087 } else {2005 } else {
2088 break;2006 break;
2089 }2007 }
@@ -2093,7 +2011,7 @@ static void parse_number(const char *p) · 3 unmodified lines
2093 else2011 else
2094 tokc.ull = n;2012 tokc.ull = n;
2095 }2013 }
2096 if (ch)2014 if (c)
2097 tcc_error("invalid number\n");2015 tcc_error("invalid number\n");
2098}2016}
2099 2017

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