]> Shamusworld >> Repos - rmac/blobdiff - expr.c
Fix for "*" getting bad section attributes, reported by A. Seed.
[rmac] / expr.c
diff --git a/expr.c b/expr.c
index 7cedc41350529f3df19e1ccc61752bc75a824d6d..8e2c33aa11f93e37538e13a75a91daa293d5832f 100644 (file)
--- 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"
 #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)
                {
@@ -334,6 +335,9 @@ int expr(TOKEN * otk, VALUE * a_value, WORD * a_attr, SYM ** a_esym)
 
                        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 == '*')
                {
@@ -344,26 +348,35 @@ 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)
                {
                        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 #<SYMBOL> 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...
@@ -408,18 +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;
        }
@@ -457,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 
 
@@ -487,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;
@@ -510,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;
@@ -563,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;
 
@@ -573,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;
 
@@ -583,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;
 
@@ -593,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;
 
@@ -603,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;
 
@@ -613,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;
 
@@ -625,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);
@@ -702,3 +731,4 @@ int evexpr(TOKEN * tk, VALUE * a_value, WORD * a_attr, SYM ** a_esym)
 
        return OK;
 }
+