Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2aaf21f1 authored by Jack Palevich's avatar Jack Palevich
Browse files

Improve numerical constant parsing.

parent 8c246a9d
Loading
Loading
Loading
Loading
+85 −48
Original line number Diff line number Diff line
@@ -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,30 +3538,33 @@ 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;
        }
        if (doExp) {
            bool digitsRequired = acceptCh('-');
            bool digitsFound = acceptDigitsCh();
            if (digitsRequired && ! digitsFound) {
                error("malformed exponent");
            acceptCh('-') || acceptCh('+');
            acceptDigitsCh();
        }
        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);
        }
        if (errno || pEndPtr != pEnd) {
            error("Can't parse constant: %s", pText);
        }
        // fprintf(stderr, "float constant: %s (%d) %g\n", pText, tok, tokd);
    }
@@ -3584,26 +3590,58 @@ 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();
            while (isid()) {
            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();
                    }
            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')  {
                } 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
                    tokc = strtol(mTokenString.getUnwrapped(), 0, 0);
                    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 {
                tok = mTokenTable.intern(mTokenString.getUnwrapped(),
                                         mTokenString.len());
            }
        } else if (isid()) {
            mTokenString.clear();
            while (isid()) {
                pdef(ch);
                inp();
            }
            tok = mTokenTable.intern(mTokenString.getUnwrapped(), mTokenString.len());
            // Is this a macro?
            char* pMacroDefinition = mTokenTable[tok].mpMacroDefinition;
            if (pMacroDefinition) {
@@ -3613,7 +3651,6 @@ class Compiler : public ErrorSink {
                inp();
                next();
            }
            }
        } else {
            inp();
            if (tok == '\'') {
+6 −0
Original line number Diff line number Diff line
@@ -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));
+12 −1
Original line number Diff line number Diff line
@@ -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"],