diff --git a/libacc/acc.cpp b/libacc/acc.cpp index 36f30a149..a84bd9101 100644 --- a/libacc/acc.cpp +++ b/libacc/acc.cpp @@ -3425,6 +3425,17 @@ class Compiler : public ErrorSink { return isalnum(ch) | (ch == '_'); } + int decodeHex(int c) { + if (isdigit(c)) { + c -= '0'; + } else if (c <= 'F') { + c = c - 'A' + 10; + } else { + c =c - 'a' + 10; + } + return c; + } + /* read a character constant, advances ch to after end of constant */ int getq() { int val = ch; @@ -3448,15 +3459,7 @@ class Compiler : public ErrorSink { } else { val = 0; while (isxdigit(ch)) { - int d = ch; - if (isdigit(d)) { - d -= '0'; - } else if (d <= 'F') { - d = d - 'A' + 10; - } else { - d = d - 'a' + 10; - } - val = (val << 4) + d; + val = (val << 4) + decodeHex(ch); inp(); } } @@ -3535,32 +3538,35 @@ class Compiler : public ErrorSink { void parseFloat() { tok = TOK_NUM_DOUBLE; // mTokenString already has the integral part of the number. + if(mTokenString.len() == 0) { + mTokenString.append('0'); + } acceptCh('.'); acceptDigitsCh(); - bool doExp = true; if (acceptCh('e') || acceptCh('E')) { - // Don't need to do any extra work - } else if (ch == 'f' || ch == 'F') { - pdef('e'); // So it can be parsed by strtof. - inp(); - tok = TOK_NUM_FLOAT; - } else { - doExp = false; + acceptCh('-') || acceptCh('+'); + acceptDigitsCh(); } - if (doExp) { - bool digitsRequired = acceptCh('-'); - bool digitsFound = acceptDigitsCh(); - if (digitsRequired && ! digitsFound) { - error("malformed exponent"); - } + if (ch == 'f' || ch == 'F') { + tok = TOK_NUM_FLOAT; + inp(); + } else if (ch == 'l' || ch == 'L') { + inp(); + error("Long floating point constants not supported."); } char* pText = mTokenString.getUnwrapped(); + char* pEnd = pText + strlen(pText); + char* pEndPtr = 0; + errno = 0; if (tok == TOK_NUM_FLOAT) { - tokd = strtof(pText, 0); + tokd = strtof(pText, &pEndPtr); } else { - tokd = strtod(pText, 0); + tokd = strtod(pText, &pEndPtr); } - //fprintf(stderr, "float constant: %s (%d) %g\n", pText, tok, tokd); + if (errno || pEndPtr != pEnd) { + error("Can't parse constant: %s", pText); + } + // fprintf(stderr, "float constant: %s (%d) %g\n", pText, tok, tokd); } void next() { @@ -3584,35 +3590,66 @@ class Compiler : public ErrorSink { tokl = 0; tok = ch; /* encode identifiers & numbers */ - if (isid()) { + if (isdigit(ch) || ch == '.') { + // Start of a numeric constant. Could be integer, float, or + // double, won't know until we look further. + mTokenString.clear(); + pdef(ch); + inp(); + int base = 10; + if (tok == '0') { + if (ch == 'x' || ch == 'X') { + base = 16; + tok = TOK_NUM; + tokc = 0; + inp(); + while ( isxdigit(ch) ) { + tokc = (tokc << 4) + decodeHex(ch); + inp(); + } + } else if (isoctal(ch)){ + base = 8; + tok = TOK_NUM; + tokc = 0; + while ( isoctal(ch) ) { + tokc = (tokc << 3) + (ch - '0'); + inp(); + } + } + } else if (isdigit(tok)){ + acceptDigitsCh(); + } + if (base == 10) { + if (tok == '.' || ch == '.' || ch == 'e' || ch == 'E') { + parseFloat(); + } else { + // It's an integer constant + char* pText = mTokenString.getUnwrapped(); + char* pEnd = pText + strlen(pText); + char* pEndPtr = 0; + errno = 0; + tokc = strtol(pText, &pEndPtr, base); + if (errno || pEndPtr != pEnd) { + error("Can't parse constant: %s %d %d", pText, base, errno); + } + tok = TOK_NUM; + } + } + } else if (isid()) { mTokenString.clear(); while (isid()) { pdef(ch); inp(); } - if (isdigit(tok)) { - // Start of a numeric constant. Could be integer, float, or - // double, won't know until we look further. - if (ch == '.' || ch == 'e' || ch == 'e' - || ch == 'f' || ch == 'F') { - parseFloat(); - } else { - // It's an integer constant - tokc = strtol(mTokenString.getUnwrapped(), 0, 0); - tok = TOK_NUM; - } - } else { - tok = mTokenTable.intern(mTokenString.getUnwrapped(), - mTokenString.len()); - // Is this a macro? - char* pMacroDefinition = mTokenTable[tok].mpMacroDefinition; - if(pMacroDefinition) { - // Yes, it is a macro - dptr = pMacroDefinition; - dch = ch; - inp(); - next(); - } + tok = mTokenTable.intern(mTokenString.getUnwrapped(), mTokenString.len()); + // Is this a macro? + char* pMacroDefinition = mTokenTable[tok].mpMacroDefinition; + if (pMacroDefinition) { + // Yes, it is a macro + dptr = pMacroDefinition; + dch = ch; + inp(); + next(); } } else { inp(); diff --git a/libacc/tests/data/float.c b/libacc/tests/data/float.c index 8625cf1b4..f48b3d1ec 100644 --- a/libacc/tests/data/float.c +++ b/libacc/tests/data/float.c @@ -17,6 +17,11 @@ double itod(int i) { float f0, f1; double d0, d1; +void testParseConsts() { + printf("Constants: %g %g %g %g %g %g %g %g %g\n", 0e1, 0E1, 0.f, .01f, + .01e0f, 1.0e-1, 1.0e1, 1.0e+1, + .1f); +} void testVars(float arg0, float arg1, double arg2, double arg3) { float local0, local1; double local2, local3; @@ -41,6 +46,7 @@ void testVars(float arg0, float arg1, double arg2, double arg3) { } int main() { + testParseConsts(); printf("int: %d float: %g double: %g\n", 1, 2.2f, 3.3); printf(" ftoi(1.4f)=%d\n", ftoi(1.4f)); printf(" dtoi(2.4)=%d\n", dtoi(2.4)); diff --git a/libacc/tests/test.py b/libacc/tests/test.py index bb9ef014a..8e4795fc8 100644 --- a/libacc/tests/test.py +++ b/libacc/tests/test.py @@ -174,7 +174,18 @@ class TestACC(unittest.TestCase): def testRunFloat(self): self.compileCheck(["-R", "data/float.c"], "Executing compiled code:\nresult: 0\n", - "int: 1 float: 2.2 double: 3.3\n ftoi(1.4f)=1\n dtoi(2.4)=2\n itof(3)=3\n itod(4)=4\nglobals: 1 2 3 4\nargs: 1 2 3 4\nlocals: 1 2 3 4\ncast rval: 2 4\ncast lval: 1.1 2 3.3 4\n") + """Constants: 0 0 0 0.01 0.01 0.1 10 10 0.1 +int: 1 float: 2.2 double: 3.3 + ftoi(1.4f)=1 + dtoi(2.4)=2 + itof(3)=3 + itod(4)=4 +globals: 1 2 3 4 +args: 1 2 3 4 +locals: 1 2 3 4 +cast rval: 2 4 +cast lval: 1.1 2 3.3 4 +""") def testRunFlops(self): self.compileCheck(["-R", "data/flops.c"],