X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?p=rmac;a=blobdiff_plain;f=expr.c;h=8e2c33aa11f93e37538e13a75a91daa293d5832f;hp=6f0b619492824e65031011f6c9317e7e8cfcf5f8;hb=d0c28c349ddfb8393568037f68bddbe8979ce0df;hpb=2e6629b63805b6d205021bf9d822ca78bd9e6548 diff --git a/expr.c b/expr.c index 6f0b619..8e2c33a 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" @@ -17,45 +17,48 @@ #include "symbol.h" #include "token.h" -#define DEF_KW // Declare keyword values -#include "kwtab.h" // Incl generated keyword tables & defs +#define DEF_KW // Declare keyword values +#include "kwtab.h" // Incl generated keyword tables & defs -static char tokenClass[128]; // Generated table of token classes -static VALUE evstk[EVSTACKSIZE]; // Evaluator value stack -static WORD evattr[EVSTACKSIZE]; // Evaluator attribute stack +// N.B.: The size of tokenClass should be identical to the largest value of +// a token; we're assuming 256 but not 100% sure! +static char tokenClass[256]; // Generated table of token classes +static VALUE evstk[EVSTACKSIZE]; // Evaluator value stack +static WORD evattr[EVSTACKSIZE]; // Evaluator attribute stack // Token-class initialization list char itokcl[] = { - 0, // END - CONST, SYMBOL, 0, // ID - '(', '[', '{', 0, // OPAR - ')', ']', '}', 0, // CPAR - CR_DEFINED, CR_REFERENCED, // SUNARY (special unary) + 0, // END + CONST, SYMBOL, 0, // ID + '(', '[', '{', 0, // OPAR + ')', ']', '}', 0, // CPAR + CR_DEFINED, CR_REFERENCED, // SUNARY (special unary) CR_STREQ, CR_MACDEF, CR_DATE, CR_TIME, 0, - '!', '~', UNMINUS, 0, // UNARY - '*', '/', '%', 0, // MULT - '+', '-', 0, // ADD - SHL, SHR, 0, // SHIFT - LE, GE, '<', '>', NE, '=', 0, // REL - '&', 0, // AND - '^', 0, // XOR - '|', 0, // OR - 1 // (the end) + '!', '~', UNMINUS, 0, // UNARY + '*', '/', '%', 0, // MULT + '+', '-', 0, // ADD + SHL, SHR, 0, // SHIFT + LE, GE, '<', '>', NE, '=', 0, // REL + '&', 0, // AND + '^', 0, // XOR + '|', 0, // OR + 1 // (the end) }; const char missym_error[] = "missing symbol"; const char str_error[] = "missing symbol or string"; // Convert expression to postfix -static TOKEN * evalTokenBuffer; // Deposit tokens here (this is really a - // pointer to exprbuf from direct.c) - // (Can also be from others, like riscasm.c) -static symbolNum; // Pointer to the entry in symbolPtr[] +static TOKEN * evalTokenBuffer; // Deposit tokens here (this is really a + // pointer to exprbuf from direct.c) + // (Can also be from others, like + // riscasm.c) +static symbolNum; // Pointer to the entry in symbolPtr[] // -// Obtain a String Value +// Obtain a string value // static VALUE str_value(char * p) { @@ -69,15 +72,15 @@ static VALUE str_value(char * p) // -// Initialize Expression Analyzer +// Initialize expression analyzer // void InitExpression(void) { - int i; // Iterator - char * p; // Token pointer + int i; + char * p; // Initialize token-class table (all set to END) - for(i=0; i<128; i++) + for(i=0; i<256; i++) tokenClass[i] = END; for(i=0, p=itokcl; *p!=1; p++) @@ -241,13 +244,9 @@ int expr2(void) } *evalTokenBuffer++ = SYMBOL; -#if 0 - *evalTokenBuffer++ = (TOKEN)sy; -#else *evalTokenBuffer++ = symbolNum; symbolPtr[symbolNum] = sy; symbolNum++; -#endif break; case STRING: *evalTokenBuffer++ = CONST; @@ -277,12 +276,10 @@ int expr2(void) case '*': *evalTokenBuffer++ = ACONST; // Attributed const - if (orgactive) - *evalTokenBuffer++ = orgaddr; - else - *evalTokenBuffer++ = pcloc; // Location at start of line - - *evalTokenBuffer++ = ABS | DEFINED; // Store attribs + // pcloc == location at start of line + *evalTokenBuffer++ = (orgactive ? orgaddr : pcloc); + // '*' takes attributes of current section, not ABS! + *evalTokenBuffer++ = cursect | DEFINED; break; default: return error("bad expression"); @@ -308,8 +305,14 @@ int expr(TOKEN * otk, VALUE * a_value, WORD * a_attr, SYM ** a_esym) evalTokenBuffer = otk; // Set token pointer to 'exprbuf' (direct.c) // Also set in various other places too (riscasm.c, e.g.) +//printf("expr(): tokens 0-2: %i %i %i (%c %c %c); tc[2] = %i\n", tok[0], tok[1], tok[2], tok[0], tok[1], tok[2], tokenClass[tok[2]]); // Optimize for single constant or single symbol. - if ((tok[1] == EOL) + // Shamus: Subtle bug here. EOL token is 101; if you have a constant token + // 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) +// if ((tok[1] == EOL) + if ((tok[1] == EOL && tok[0] != CONST) || (((*tok == CONST || *tok == SYMBOL) || (*tok >= KW_R0 && *tok <= KW_R31)) && (tokenClass[tok[2]] < UNARY))) { @@ -323,8 +326,6 @@ int expr(TOKEN * otk, VALUE * a_value, WORD * a_attr, SYM ** a_esym) *a_esym = NULL; tok++; -// *evalTokenBuffer++ = ENDEXPR; -// return OK; } else if (*tok == CONST) { @@ -336,6 +337,7 @@ int expr(TOKEN * otk, VALUE * a_value, WORD * a_attr, SYM ** a_esym) *a_esym = NULL; tok += 2; +//printf("Quick eval in expr(): CONST = %i, tokenClass[tok[2]] = %i\n", *a_value, tokenClass[*tok]); } else if (*tok == '*') { @@ -346,12 +348,12 @@ 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; -// tok--; tok++; } else if (*tok == STRING || *tok == SYMBOL) @@ -359,14 +361,22 @@ int expr(TOKEN * otk, VALUE * a_value, WORD * a_attr, SYM ** a_esym) p = string[tok[1]]; j = (*p == '.' ? curenv : 0); symbol = lookup(p, LABEL, j); +#if 0 +printf("eval: Looking up symbol (%s) [=%08X]\n", p, symbol); +if (symbol) + printf(" attr=%04X, attre=%08X, val=%i, name=%s\n", symbol->sattr, symbol->sattre, symbol->svalue, symbol->sname); +#endif if (symbol == NULL) symbol = NewSymbol(p, LABEL, j); symbol->sattr |= REFERENCED; - // Check for undefined register equates - if (symbol->sattre & UNDEF_EQUR) + // Check for undefined register equates, but only if it's not part + // of a # construct, as it could be that the label that's + // been undefined may later be used as an address label--which + // means it will be fixed up later, and thus, not an error. + if ((symbol->sattre & UNDEF_EQUR) && !riscImmTokenSeen) { errors("undefined register equate '%s'", symbol->sname); //if we return right away, it returns some spurious errors... @@ -411,21 +421,21 @@ thrown away right here. What the hell is it for? *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; } else { - // Unknown type here... Alert the user! + // Unknown type here... Alert the user!, error("undefined RISC register in expression"); // Prevent spurious error reporting... tok++; return ERROR; } -// tok += 2; *evalTokenBuffer++ = ENDEXPR; return OK; } @@ -463,7 +473,7 @@ int evexpr(TOKEN * tk, VALUE * a_value, WORD * a_attr, SYM ** a_esym) switch ((int)*tk++) { case SYMBOL: -// sy = (SYM *)*tk++; +//printf("evexpr(): SYMBOL\n"); sy = symbolPtr[*tk++]; sy->sattr |= REFERENCED; // Set "referenced" bit @@ -493,13 +503,15 @@ 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); *++sval = *tk++; // Push value *++sattr = ABS | DEFINED; // Push simple attribs break; case ACONST: +//printf("evexpr(): ACONST = %i\n", *tk); *++sval = *tk++; // Push value *++sattr = (WORD)*tk++; // Push attribs break; @@ -516,51 +528,55 @@ int evexpr(TOKEN * tk, VALUE * a_value, WORD * a_attr, SYM ** a_esym) // [1] + : Error // - : ABS case '+': +//printf("evexpr(): +\n"); --sval; // Pop value --sattr; // Pop attrib *sval += sval[1]; // Compute value - 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; case '-': +//printf("evexpr(): -\n"); --sval; // Pop value --sattr; // Pop attrib *sval -= sval[1]; // Compute value - 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: - if (*sattr & (TEXT | DATA | BSS)) +//printf("evexpr(): UNMINUS\n"); + if (*sattr & TDB) error(seg_error); *sval = -(int)*sval; *sattr = ABS | DEFINED; // Expr becomes absolute break; case '!': - if (*sattr & (TEXT | DATA | BSS)) +//printf("evexpr(): !\n"); + if (*sattr & TDB) error(seg_error); *sval = !*sval; *sattr = ABS | DEFINED; // Expr becomes absolute break; case '~': - if (*sattr & (TEXT | DATA | BSS)) +//printf("evexpr(): ~\n"); + if (*sattr & TDB) error(seg_error); *sval = ~*sval; @@ -569,6 +585,7 @@ int evexpr(TOKEN * tk, VALUE * a_value, WORD * a_attr, SYM ** a_esym) // Comparison operators must have two values that // are in the same segment, but that's the only requirement. case LE: +//printf("evexpr(): LE\n"); --sattr; --sval; @@ -579,6 +596,7 @@ int evexpr(TOKEN * tk, VALUE * a_value, WORD * a_attr, SYM ** a_esym) *sval = *sval <= sval[1]; break; case GE: +//printf("evexpr(): GE\n"); --sattr; --sval; @@ -589,6 +607,7 @@ int evexpr(TOKEN * tk, VALUE * a_value, WORD * a_attr, SYM ** a_esym) *sval = *sval >= sval[1]; break; case '>': +//printf("evexpr(): >\n"); --sattr; --sval; @@ -599,6 +618,7 @@ int evexpr(TOKEN * tk, VALUE * a_value, WORD * a_attr, SYM ** a_esym) *sval = *sval > sval[1]; break; case '<': +//printf("evexpr(): <\n"); --sattr; --sval; @@ -609,6 +629,7 @@ int evexpr(TOKEN * tk, VALUE * a_value, WORD * a_attr, SYM ** a_esym) *sval = *sval < sval[1]; break; case NE: +//printf("evexpr(): NE\n"); --sattr; --sval; @@ -619,6 +640,7 @@ int evexpr(TOKEN * tk, VALUE * a_value, WORD * a_attr, SYM ** a_esym) *sval = *sval != sval[1]; break; case '=': +//printf("evexpr(): =\n"); --sattr; --sval; @@ -631,6 +653,7 @@ int evexpr(TOKEN * tk, VALUE * a_value, WORD * a_attr, SYM ** a_esym) // All other binary operators must have two ABS items // to work with. They all produce an ABS value. default: +//printf("evexpr(): default\n"); // GH - Removed for v1.0.15 as part of the fix for indexed loads. //if ((*sattr & (TEXT|DATA|BSS)) || (*--sattr & (TEXT|DATA|BSS))) //error(seg_error); @@ -708,3 +731,4 @@ int evexpr(TOKEN * tk, VALUE * a_value, WORD * a_attr, SYM ** a_esym) return OK; } +