// 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)
{
//
-// 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++)
if (*tok != SYMBOL && *tok != STRING)
return error(str_error);
- p = string[tok[1]];
+ p2 = string[tok[1]];
tok += 2;
w = (WORD)(!strcmp(p, p2));
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");
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;
j = (*p == '.' ? curenv : 0);
symbol = lookup(p, LABEL, j);
#if 0
-printf("eval: Looking up symbol [=%08X]\n", symbol);
+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
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...
*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++;
}
*++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);
//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;
//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;
break;
case '!':
//printf("evexpr(): !\n");
- if (*sattr & (TEXT | DATA | BSS))
+ if (*sattr & TDB)
error(seg_error);
*sval = !*sval;
break;
case '~':
//printf("evexpr(): ~\n");
- if (*sattr & (TEXT | DATA | BSS))
+ if (*sattr & TDB)
error(seg_error);
*sval = ~*sval;
case '*':
--sval;
--sattr; // Pop attrib
+//printf("--> NxN: %i x %i = ", *sval, sval[1]);
*sval *= sval[1];
+//printf("%i\n", *sval);
break;
case '/':
--sval;
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;
return OK;
}
+