]> Shamusworld >> Repos - rmac/blobdiff - expr.c
Fix for bug #71 (thanks to ggn for reporting! :-)
[rmac] / expr.c
diff --git a/expr.c b/expr.c
index 8e2c33aa11f93e37538e13a75a91daa293d5832f..063066ede1dd58ba9265ae1bba965d5789d4593e 100644 (file)
--- a/expr.c
+++ b/expr.c
@@ -34,7 +34,8 @@ char itokcl[] = {
        ')', ']', '}', 0,                               // CPAR 
        CR_DEFINED, CR_REFERENCED,              // SUNARY (special unary)
        CR_STREQ, CR_MACDEF,
-       CR_DATE, CR_TIME, 0,
+       CR_DATE, CR_TIME, 
+       CR_ABSCOUNT, 0,
        '!', '~', UNMINUS, 0,                   // UNARY
        '*', '/', '%', 0,                               // MULT 
        '+', '-', 0,                                    // ADD 
@@ -121,6 +122,9 @@ int expr0(void)
 
 //
 // Unary operators (detect unary '-')
+// ggn: If expression starts with a plus then also eat it up.
+//      For some reason the parser gets confused when this happens and
+//      emits a "bad expression".
 //
 int expr1(void)
 {
@@ -133,7 +137,7 @@ int expr1(void)
 
        class = tokenClass[*tok];
 
-       if (*tok == '-' || class == UNARY)
+       if (*tok == '-' || *tok == '+' || class == UNARY)
        {
                t = *tok++;
 
@@ -149,6 +153,10 @@ int expr1(void)
        {
                switch ((int)*tok++)
                {
+               case CR_ABSCOUNT:
+                       *evalTokenBuffer++ = CONST;
+                       *evalTokenBuffer++ = (LONG)sect[ABS].sloc;
+                       break;
                case CR_TIME:
                        *evalTokenBuffer++ = CONST;
                        *evalTokenBuffer++ = dos_time();
@@ -194,7 +202,7 @@ getsym:
                        if (*tok != SYMBOL && *tok != STRING)
                                return error(str_error);
 
-                       p = string[tok[1]];
+                       p2 = string[tok[1]];
                        tok += 2;
 
                        w = (WORD)(!strcmp(p, p2));
@@ -311,8 +319,9 @@ int expr(TOKEN * otk, VALUE * a_value, WORD * a_attr, SYM ** a_esym)
        //         followed by the value 101, it will trigger a bad evaluation here.
        //         This is probably a really bad assumption to be making here...!
        //         (assuming tok[1] == EOL is a single token that is)
+       //         Seems that even other tokens (SUNARY type) can fuck this up too.
 //     if ((tok[1] == EOL)
-       if ((tok[1] == EOL && tok[0] != CONST)
+       if ((tok[1] == EOL && (tok[0] != CONST && tokenClass[tok[0]] != SUNARY))
                || (((*tok == CONST || *tok == SYMBOL) || (*tok >= KW_R0 && *tok <= KW_R31))
                && (tokenClass[tok[2]] < UNARY)))
        {
@@ -531,7 +540,9 @@ int evexpr(TOKEN * tk, VALUE * a_value, WORD * a_attr, SYM ** a_esym)
 //printf("evexpr(): +\n");
                        --sval;                                                 // Pop value
                        --sattr;                                                // Pop attrib 
+//printf("--> N+N: %i + %i = ", *sval, sval[1]);
                        *sval += sval[1];                               // Compute value
+//printf("%i\n", *sval);
 
                        if (!(*sattr & TDB))
                                *sattr = sattr[1];
@@ -543,7 +554,9 @@ int evexpr(TOKEN * tk, VALUE * a_value, WORD * a_attr, SYM ** a_esym)
 //printf("evexpr(): -\n");
                        --sval;                                                 // Pop value
                        --sattr;                                                // Pop attrib 
+//printf("--> N-N: %i - %i = ", *sval, sval[1]);
                        *sval -= sval[1];                               // Compute value
+//printf("%i\n", *sval);
 
                        attr = (WORD)(*sattr & TDB);
 #if 0
@@ -664,7 +677,9 @@ printf("EVEXPR (-): sym1 = %X, sym2 = %X\n", attr, sattr[1]);
                        case '*':
                                --sval;
                                --sattr;                                        // Pop attrib 
+//printf("--> NxN: %i x %i = ", *sval, sval[1]);
                                *sval *= sval[1];
+//printf("%i\n", *sval);
                                break;
                        case '/':
                                --sval;
@@ -673,7 +688,13 @@ printf("EVEXPR (-): sym1 = %X, sym2 = %X\n", attr, sattr[1]);
                                if (sval[1] == 0)
                                        return error("divide by zero");
 
-                               *sval /= sval[1];
+//printf("--> N/N: %i / %i = ", sval[0], sval[1]);
+                               // Compiler is picky here: Without casting these, it discards
+                               // the sign if dividing a negative # by a positive one,
+                               // creating a bad result. :-/
+                               // Probably a side effect of using VALUE intead of ints.
+                               *sval = (int)sval[0] / (int)sval[1];
+//printf("%i\n", *sval);
                                break;
                        case '%':
                                --sval;