X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?p=rmac;a=blobdiff_plain;f=expr.c;h=f582408c5773be5f90d77c13220ebfefee679a58;hp=1747c8441666c4d79815b9b11dd20609d027dbf8;hb=75969398d9b8a9f82ea76fc4e4cbfb97b11160a4;hpb=daf2f61a3664329ae7f9609e1e14da2b8780fd10 diff --git a/expr.c b/expr.c index 1747c84..f582408 100644 --- a/expr.c +++ b/expr.c @@ -12,7 +12,7 @@ #include "listing.h" #include "mach.h" #include "procln.h" -#include "risca.h" +#include "riscasm.h" #include "sect.h" #include "symbol.h" #include "token.h" @@ -20,7 +20,7 @@ #define DEF_KW // Declare keyword values #include "kwtab.h" // Incl generated keyword tables & defs -static char tokcl[128]; // Generated table of token classes +static char tokenClass[128]; // Generated table of token classes static VALUE evstk[EVSTACKSIZE]; // Evaluator value stack static WORD evattr[EVSTACKSIZE]; // Evaluator attribute stack @@ -48,8 +48,9 @@ const char missym_error[] = "missing symbol"; const char str_error[] = "missing symbol or string"; // Convert expression to postfix -static TOKEN * tk; // Deposit tokens here (this is really a +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[] @@ -70,21 +71,21 @@ static VALUE str_value(char * p) // // Initialize Expression Analyzer // -void init_expr(void) +void InitExpression(void) { int i; // Iterator char * p; // Token pointer - // Initialize token-class table - for(i=0; i<128; i++) // Mark all entries END - tokcl[i] = END; + // Initialize token-class table (all set to END) + for(i=0; i<128; i++) + tokenClass[i] = END; for(i=0, p=itokcl; *p!=1; p++) { if (*p == 0) i++; else - tokcl[(int)(*p)] = (char)i; + tokenClass[(int)(*p)] = (char)i; } symbolNum = 0; @@ -101,14 +102,14 @@ int expr0(void) if (expr1() != OK) return ERROR; - while (tokcl[*tok] >= MULT) + while (tokenClass[*tok] >= MULT) { t = *tok++; if (expr1() != OK) return ERROR; - *tk++ = t; + *evalTokenBuffer++ = t; } return OK; @@ -127,7 +128,7 @@ int expr1(void) WORD w; int j; - class = tokcl[*tok]; + class = tokenClass[*tok]; if (*tok == '-' || class == UNARY) { @@ -139,32 +140,28 @@ int expr1(void) if (t == '-') t = UNMINUS; - *tk++ = t; + *evalTokenBuffer++ = t; } else if (class == SUNARY) { switch ((int)*tok++) { case CR_TIME: - *tk++ = CONST; - *tk++ = dos_time(); + *evalTokenBuffer++ = CONST; + *evalTokenBuffer++ = dos_time(); break; case CR_DATE: - *tk++ = CONST; - *tk++ = dos_date(); + *evalTokenBuffer++ = CONST; + *evalTokenBuffer++ = dos_date(); break; case CR_MACDEF: // ^^macdef if (*tok++ != SYMBOL) return error(missym_error); -#if 0 - p = (char *)*tok++; -#else p = string[*tok++]; -#endif w = (lookup(p, MACRO, 0) == NULL ? 0 : 1); - *tk++ = CONST; - *tk++ = (TOKEN)w; + *evalTokenBuffer++ = CONST; + *evalTokenBuffer++ = (TOKEN)w; break; case CR_DEFINED: w = DEFINED; @@ -175,29 +172,17 @@ getsym: if (*tok++ != SYMBOL) return error(missym_error); -#if 0 - p = (char *)*tok++; -#else p = string[*tok++]; -#endif - j = 0; - - if (*p == '.') - j = curenv; - + j = (*p == '.' ? curenv : 0); w = ((sy = lookup(p, LABEL, j)) != NULL && (sy->sattr & w) ? 1 : 0); - *tk++ = CONST; - *tk++ = (TOKEN)w; + *evalTokenBuffer++ = CONST; + *evalTokenBuffer++ = (TOKEN)w; break; case CR_STREQ: if (*tok != SYMBOL && *tok != STRING) return error(str_error); -#if 0 - p = (char *)tok[1]; -#else p = string[tok[1]]; -#endif tok +=2; if (*tok++ != ',') @@ -206,16 +191,12 @@ getsym: if (*tok != SYMBOL && *tok != STRING) return error(str_error); -#if 0 - p2 = (char *)tok[1]; -#else p = string[tok[1]]; -#endif tok += 2; w = (WORD)(!strcmp(p, p2)); - *tk++ = CONST; - *tk++ = (TOKEN)w; + *evalTokenBuffer++ = CONST; + *evalTokenBuffer++ = (TOKEN)w; break; } } @@ -238,20 +219,12 @@ int expr2(void) switch ((int)*tok++) { case CONST: - *tk++ = CONST; - *tk++ = *tok++; + *evalTokenBuffer++ = CONST; + *evalTokenBuffer++ = *tok++; break; case SYMBOL: -#if 0 - p = (char *)*tok++; -#else p = string[*tok++]; -#endif - j = 0; - - if (*p == '.') - j = curenv; - + j = (*p == '.' ? curenv : 0); sy = lookup(p, LABEL, j); if (sy == NULL) @@ -267,22 +240,14 @@ int expr2(void) warns("equated symbol \'%s\' cannot be used in register bank 1", sy->sname); } - *tk++ = SYMBOL; -#if 0 - *tk++ = (TOKEN)sy; -#else - *tk++ = symbolNum; + *evalTokenBuffer++ = SYMBOL; + *evalTokenBuffer++ = symbolNum; symbolPtr[symbolNum] = sy; symbolNum++; -#endif break; case STRING: - *tk++ = CONST; -#if 0 - *tk++ = str_value((char *)*tok++); -#else - *tk++ = str_value(string[*tok++]); -#endif + *evalTokenBuffer++ = CONST; + *evalTokenBuffer++ = str_value(string[*tok++]); break; case '(': if (expr0() != OK) @@ -301,19 +266,24 @@ int expr2(void) break; case '$': - *tk++ = ACONST; // Attributed const - *tk++ = sloc; // Current location - *tk++ = cursect | DEFINED; // Store attribs + *evalTokenBuffer++ = ACONST; // Attributed const + *evalTokenBuffer++ = sloc; // Current location + *evalTokenBuffer++ = cursect | DEFINED; // Store attribs break; case '*': - *tk++ = ACONST; // Attributed const + *evalTokenBuffer++ = ACONST; // Attributed const +#if 0 if (orgactive) - *tk++ = orgaddr; + *evalTokenBuffer++ = orgaddr; else - *tk++ = pcloc; // Location at start of line + *evalTokenBuffer++ = pcloc; // Location at start of line +#else + // pcloc == location at start of line + *evalTokenBuffer++ = (orgactive ? orgaddr : pcloc); +#endif - *tk++ = ABS | DEFINED; // Store attribs + *evalTokenBuffer++ = ABS | DEFINED; // Store attribs break; default: return error("bad expression"); @@ -328,118 +298,146 @@ int expr2(void) // int expr(TOKEN * otk, VALUE * a_value, WORD * a_attr, SYM ** a_esym) { - SYM * sy; + // Passed in values (once derefenced, that is) can all be zero. They are + // there so that the expression analyzer can fill them in as needed. The + // expression analyzer gets its input from the global token pointer "tok", + // and not from anything passed in by the user. + SYM * symbol; char * p; int j; - tk = otk; // Set token pointer to 'exprbuf' (direct.c) -// symbolNum = 0; // Set symbol number in symbolPtr[] to 0 + 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)) - && (tokcl[tok[2]] < UNARY))) + && (tokenClass[tok[2]] < UNARY))) { if (*tok >= KW_R0 && *tok <= KW_R31) { - *tk++ = CONST; - *tk++ = *a_value = (*tok - KW_R0); + *evalTokenBuffer++ = CONST; + *evalTokenBuffer++ = *a_value = (*tok - KW_R0); *a_attr = ABS | DEFINED; if (a_esym != NULL) *a_esym = NULL; tok++; - *tk++ = ENDEXPR; - return OK; } else if (*tok == CONST) { - *tk++ = CONST; - *tk++ = *a_value = tok[1]; + *evalTokenBuffer++ = CONST; + *evalTokenBuffer++ = *a_value = tok[1]; *a_attr = ABS | DEFINED; if (a_esym != NULL) *a_esym = NULL; + + tok += 2; +//printf("Quick eval in expr(): CONST = %i, tokenClass[tok[2]] = %i\n", *a_value, tokenClass[*tok]); } else if (*tok == '*') { - *tk++ = CONST; + *evalTokenBuffer++ = CONST; if (orgactive) - *tk++ = *a_value = orgaddr; + *evalTokenBuffer++ = *a_value = orgaddr; else - *tk++ = *a_value = pcloc; + *evalTokenBuffer++ = *a_value = pcloc; *a_attr = ABS | DEFINED; - //*tk++ = if (a_esym != NULL) *a_esym = NULL; - tok--; + tok++; } - else + else if (*tok == STRING || *tok == SYMBOL) { -#if 0 - p = (char *)tok[1]; -#else p = string[tok[1]]; -#endif - j = 0; + j = (*p == '.' ? curenv : 0); + symbol = lookup(p, LABEL, j); - if (*p == '.') - j = curenv; + if (symbol == NULL) + symbol = NewSymbol(p, LABEL, j); - sy = lookup(p, LABEL, j); + symbol->sattr |= REFERENCED; - if (sy == NULL) - sy = NewSymbol(p, LABEL, j); - - sy->sattr |= REFERENCED; + // Check for undefined register equates + if (symbol->sattre & UNDEF_EQUR) + { + errors("undefined register equate '%s'", symbol->sname); +//if we return right away, it returns some spurious errors... +// return ERROR; + } // Check register bank usage - if (sy->sattre & EQUATEDREG) + if (symbol->sattre & EQUATEDREG) { - if ((regbank == BANK_0) && (sy->sattre & BANK_1) && !altbankok) - warns("equated symbol \'%s\' cannot be used in register bank 0", sy->sname); + if ((regbank == BANK_0) && (symbol->sattre & BANK_1) && !altbankok) + warns("equated symbol '%s' cannot be used in register bank 0", symbol->sname); - if ((regbank == BANK_1) && (sy->sattre & BANK_0) && !altbankok) - warns("equated symbol \'%s\' cannot be used in register bank 1", sy->sname); + if ((regbank == BANK_1) && (symbol->sattre & BANK_0) && !altbankok) + warns("equated symbol '%s' cannot be used in register bank 1", symbol->sname); } - *tk++ = SYMBOL; + *evalTokenBuffer++ = SYMBOL; #if 0 - *tk++ = (TOKEN)sy; + *evalTokenBuffer++ = (TOKEN)symbol; #else - *tk++ = symbolNum; - symbolPtr[symbolNum] = sy; +/* +While this approach works, it's wasteful. It would be better to use something +that's already available, like the symbol "order defined" table (which needs to +be converted from a linked list into an array). +*/ + *evalTokenBuffer++ = symbolNum; + symbolPtr[symbolNum] = symbol; symbolNum++; #endif - if (sy->sattr & DEFINED) - *a_value = sy->svalue; + if (symbol->sattr & DEFINED) + *a_value = symbol->svalue; else *a_value = 0; - if (sy->sattre & EQUATEDREG) +/* +All that extra crap that was put into the svalue when doing the equr stuff is +thrown away right here. What the hell is it for? +*/ + if (symbol->sattre & EQUATEDREG) *a_value &= 0x1F; - *a_attr = (WORD)(sy->sattr & ~GLOBAL); + *a_attr = (WORD)(symbol->sattr & ~GLOBAL); + + if ((symbol->sattr & (GLOBAL | DEFINED)) == GLOBAL && a_esym != NULL) + *a_esym = symbol; - if ((sy->sattr & (GLOBAL | DEFINED)) == GLOBAL && a_esym != NULL) - *a_esym = sy; + tok += 2; + } + else + { + // Unknown type here... Alert the user! + error("undefined RISC register in expression"); + // Prevent spurious error reporting... + tok++; + return ERROR; } - tok += 2; - *tk++ = ENDEXPR; + *evalTokenBuffer++ = ENDEXPR; return OK; } if (expr0() != OK) return ERROR; - *tk++ = ENDEXPR; + *evalTokenBuffer++ = ENDEXPR; return evexpr(otk, a_value, a_attr, a_esym); } @@ -469,7 +467,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 @@ -502,10 +500,12 @@ int evexpr(TOKEN * tk, VALUE * a_value, WORD * a_attr, SYM ** a_esym) sym_seg = (WORD)(sy->sattr & (TEXT | DATA | BSS)); 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; @@ -522,6 +522,7 @@ 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 @@ -533,6 +534,7 @@ int evexpr(TOKEN * tk, VALUE * a_value, WORD * a_attr, SYM ** a_esym) break; case '-': +//printf("evexpr(): -\n"); --sval; // Pop value --sattr; // Pop attrib *sval -= sval[1]; // Compute value @@ -552,6 +554,7 @@ int evexpr(TOKEN * tk, VALUE * a_value, WORD * a_attr, SYM ** a_esym) break; // Unary operators only work on ABS items case UNMINUS: +//printf("evexpr(): UNMINUS\n"); if (*sattr & (TEXT | DATA | BSS)) error(seg_error); @@ -559,6 +562,7 @@ int evexpr(TOKEN * tk, VALUE * a_value, WORD * a_attr, SYM ** a_esym) *sattr = ABS | DEFINED; // Expr becomes absolute break; case '!': +//printf("evexpr(): !\n"); if (*sattr & (TEXT | DATA | BSS)) error(seg_error); @@ -566,6 +570,7 @@ int evexpr(TOKEN * tk, VALUE * a_value, WORD * a_attr, SYM ** a_esym) *sattr = ABS | DEFINED; // Expr becomes absolute break; case '~': +//printf("evexpr(): ~\n"); if (*sattr & (TEXT | DATA | BSS)) error(seg_error); @@ -575,6 +580,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; @@ -585,6 +591,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; @@ -595,6 +602,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; @@ -605,6 +613,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; @@ -615,6 +624,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; @@ -625,6 +635,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; @@ -637,6 +648,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);