]> Shamusworld >> Repos - rmac/blobdiff - expr.c
New keyword ^^ABSCOUNT counts bytes defined in current .abs section.
[rmac] / expr.c
diff --git a/expr.c b/expr.c
index f582408c5773be5f90d77c13220ebfefee679a58..0ecaa45316e2e69baa173512a79ab643ecf94b4f 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) 
+       CR_DATE, CR_TIME, 
+       CR_ABSCOUNT, 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) 
 };
 
 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 +73,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++)
@@ -146,6 +150,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();
@@ -191,7 +199,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));
@@ -273,17 +281,10 @@ int expr2(void)
        case '*':
                *evalTokenBuffer++ = ACONST;                            // Attributed const
 
-#if 0
-               if (orgactive)
-                       *evalTokenBuffer++ = orgaddr;
-               else
-                       *evalTokenBuffer++ = pcloc;                             // Location at start of line
-#else
                // pcloc == location at start of line
                *evalTokenBuffer++ = (orgactive ? orgaddr : pcloc);
-#endif
-
-               *evalTokenBuffer++ = ABS | DEFINED;                     // Store attribs
+               // '*' takes attributes of current section, not ABS!
+               *evalTokenBuffer++ = cursect | DEFINED;
                break;
        default:
                return error("bad expression");
@@ -315,8 +316,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)))
        {
@@ -352,7 +354,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;
@@ -364,14 +367,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 #<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...
@@ -416,14 +427,15 @@ 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++;
@@ -497,7 +509,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);
@@ -525,11 +537,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;
@@ -537,25 +551,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;
@@ -563,7 +578,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;
@@ -571,7 +586,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;
@@ -659,7 +674,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;
@@ -668,7 +685,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;
@@ -726,3 +749,4 @@ int evexpr(TOKEN * tk, VALUE * a_value, WORD * a_attr, SYM ** a_esym)
 
        return OK;
 }
+