// 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"
// pcloc == location at start of line
*evalTokenBuffer++ = (orgactive ? orgaddr : pcloc);
- *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;