X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?p=rmac;a=blobdiff_plain;f=expr.c;h=063066ede1dd58ba9265ae1bba965d5789d4593e;hp=deeea40a893300bba19bf3b587b18b78ad47a072;hb=71cec8e7896b200c6ae63ebc428339bef147240a;hpb=a48737de123e304866212f5382d6fa4174d496a0 diff --git a/expr.c b/expr.c index deeea40..063066e 100644 --- a/expr.c +++ b/expr.c @@ -3,7 +3,7 @@ // EXPR.C - Expression Analyzer // Copyright (C) 199x Landon Dyer, 2011 Reboot and Friends // RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986 -// Source Utilised with the Kind Permission of Landon Dyer +// Source utilised with the kind permission of Landon Dyer // #include "expr.h" @@ -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)); @@ -278,7 +286,8 @@ int expr2(void) // pcloc == location at start of line *evalTokenBuffer++ = (orgactive ? orgaddr : pcloc); - *evalTokenBuffer++ = ABS | DEFINED; // Store attribs + // '*' takes attributes of current section, not ABS! + *evalTokenBuffer++ = cursect | DEFINED; break; default: return error("bad expression"); @@ -310,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))) { @@ -347,7 +357,8 @@ int expr(TOKEN * otk, VALUE * a_value, WORD * a_attr, SYM ** a_esym) else *evalTokenBuffer++ = *a_value = pcloc; - *a_attr = ABS | DEFINED; + // '*' takes attributes of current section, not ABS! + *a_attr = cursect | DEFINED; if (a_esym != NULL) *a_esym = NULL; @@ -416,9 +427,11 @@ thrown away right here. What the hell is it for? */ if (symbol->sattre & EQUATEDREG) *a_value &= 0x1F; + *a_attr = (WORD)(symbol->sattr & ~GLOBAL); - if ((symbol->sattr & (GLOBAL | DEFINED)) == GLOBAL && a_esym != NULL) + if ((symbol->sattr & (GLOBAL | DEFINED)) == GLOBAL + && a_esym != NULL) *a_esym = symbol; tok += 2; @@ -499,7 +512,7 @@ int evexpr(TOKEN * tk, VALUE * a_value, WORD * a_attr, SYM ** a_esym) } *++sattr = (WORD)(sy->sattr & ~GLOBAL); // Push attribs - sym_seg = (WORD)(sy->sattr & (TEXT | DATA | BSS)); + sym_seg = (WORD)(sy->sattr & TDB); break; case CONST: //printf("evexpr(): CONST = %i\n", *tk); @@ -527,11 +540,13 @@ 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 & (TEXT | DATA | BSS))) + if (!(*sattr & TDB)) *sattr = sattr[1]; - else if (sattr[1] & (TEXT | DATA | BSS)) + else if (sattr[1] & TDB) return error(seg_error); break; @@ -539,25 +554,26 @@ 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 & (TEXT | DATA | BSS)); - + attr = (WORD)(*sattr & TDB); +#if 0 +printf("EVEXPR (-): sym1 = %X, sym2 = %X\n", attr, sattr[1]); +#endif + // If symbol1 is ABS, take attributes from symbol2 if (!attr) *sattr = sattr[1]; - else if (sattr[1] & (TEXT | DATA | BSS)) - { - if (!(attr & sattr[1])) - return error(seg_error); - else - *sattr &= ~(TEXT | DATA | BSS); - } + // Otherwise, they're both TDB and so attributes cancel out + else if (sattr[1] & TDB) + *sattr &= ~TDB; break; // Unary operators only work on ABS items case UNMINUS: //printf("evexpr(): UNMINUS\n"); - if (*sattr & (TEXT | DATA | BSS)) + if (*sattr & TDB) error(seg_error); *sval = -(int)*sval; @@ -565,7 +581,7 @@ int evexpr(TOKEN * tk, VALUE * a_value, WORD * a_attr, SYM ** a_esym) break; case '!': //printf("evexpr(): !\n"); - if (*sattr & (TEXT | DATA | BSS)) + if (*sattr & TDB) error(seg_error); *sval = !*sval; @@ -573,7 +589,7 @@ int evexpr(TOKEN * tk, VALUE * a_value, WORD * a_attr, SYM ** a_esym) break; case '~': //printf("evexpr(): ~\n"); - if (*sattr & (TEXT | DATA | BSS)) + if (*sattr & TDB) error(seg_error); *sval = ~*sval; @@ -661,7 +677,9 @@ int evexpr(TOKEN * tk, VALUE * a_value, WORD * a_attr, SYM ** a_esym) case '*': --sval; --sattr; // Pop attrib +//printf("--> NxN: %i x %i = ", *sval, sval[1]); *sval *= sval[1]; +//printf("%i\n", *sval); break; case '/': --sval; @@ -670,7 +688,13 @@ int evexpr(TOKEN * tk, VALUE * a_value, WORD * a_attr, SYM ** a_esym) 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;