//
// RMAC - Reboot's Macro Assembler for the Atari Jaguar Console System
// EXPR.C - Expression Analyzer
-// Copyright (C) 199x Landon Dyer, 2011 Reboot and Friends
+// Copyright (C) 199x Landon Dyer, 2017 Reboot and Friends
// RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986
// Source utilised with the kind permission of Landon Dyer
//
#include "symbol.h"
#include "token.h"
-#define DEF_KW // Declare keyword values
+#define DEF_KW // Declare keyword values
#include "kwtab.h" // Incl generated keyword tables & defs
// N.B.: The size of tokenClass should be identical to the largest value of
// Token-class initialization list
char itokcl[] = {
0, // END
- CONST, SYMBOL, 0, // ID
+ CONST, SYMBOL, 0, // ID
'(', '[', '{', 0, // OPAR
- ')', ']', '}', 0, // CPAR
+ ')', ']', '}', 0, // CPAR
CR_DEFINED, CR_REFERENCED, // SUNARY (special unary)
CR_STREQ, CR_MACDEF,
- CR_DATE, CR_TIME, 0,
+ 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)
+ '*', '/', '%', 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";
// pointer to exprbuf from direct.c)
// (Can also be from others, like
// riscasm.c)
-static symbolNum; // Pointer to the entry in symbolPtr[]
+static int symbolNum; // Pointer to the entry in symbolPtr[]
//
{
if (*p == 0)
i++;
- else
+ else
tokenClass[(int)(*p)] = (char)i;
}
if (expr1() != OK)
return ERROR;
-
+
while (tokenClass[*tok] >= MULT)
{
t = *tok++;
//
// Unary operators (detect unary '-')
+// ggn: If expression starts with a plus then also eat it up.
+// For some reason the parser gets confused when this happens and
+// emits a "bad expression".
//
int expr1(void)
{
class = tokenClass[*tok];
- if (*tok == '-' || class == UNARY)
+ if (*tok == '-' || *tok == '+' || class == UNARY)
{
t = *tok++;
{
switch ((int)*tok++)
{
+ case CR_ABSCOUNT:
+ *evalTokenBuffer++ = CONST;
+ *evalTokenBuffer++ = (LONG)sect[ABS].sloc;
+ break;
case CR_TIME:
*evalTokenBuffer++ = CONST;
*evalTokenBuffer++ = dos_time();
if (*tok != SYMBOL && *tok != STRING)
return error(str_error);
- p = string[tok[1]];
+ p2 = string[tok[1]];
tok += 2;
w = (WORD)(!strcmp(p, p2));
break;
}
}
- else
+ else
return expr2();
return OK;
// Check register bank usage
if (sy->sattre & EQUATEDREG)
{
- if ((regbank == BANK_0) && (sy->sattre & BANK_1) && !altbankok)
+ 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_1) && (sy->sattre & BANK_0) && !altbankok)
// 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)))
{
// Check register bank usage
if (symbol->sattre & EQUATEDREG)
{
- if ((regbank == BANK_0) && (symbol->sattre & BANK_1) && !altbankok)
+ 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) && (symbol->sattre & BANK_0) && !altbankok)
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)
+ if (symbol->sattre & EQUATEDREG)
*a_value &= 0x1F;
*a_attr = (WORD)(symbol->sattr & ~GLOBAL);
case SYMBOL:
//printf("evexpr(): SYMBOL\n");
sy = symbolPtr[*tk++];
- sy->sattr |= REFERENCED; // Set "referenced" bit
+ sy->sattr |= REFERENCED; // Set "referenced" bit
if (!(sy->sattr & DEFINED))
{
}
else
{
- *++sval = 0; // 0 for undefined symbols
+ *++sval = 0; // 0 for undefined symbols
}
*++sattr = (WORD)(sy->sattr & ~GLOBAL); // Push attribs
break;
// Binary "+" and "-" matrix:
- //
+ //
// ABS Sect Other
// ----------------------------
// ABS | ABS | Sect | Other |
// Sect | Sect | [1] | Error |
// Other | Other | Error | [1] |
// ----------------------------
- //
+ //
// [1] + : Error
// - : ABS
case '+':
//printf("evexpr(): +\n");
--sval; // Pop value
- --sattr; // Pop attrib
+ --sattr; // Pop attrib
+//printf("--> N+N: %i + %i = ", *sval, sval[1]);
*sval += sval[1]; // Compute value
+//printf("%i\n", *sval);
if (!(*sattr & TDB))
*sattr = sattr[1];
case '-':
//printf("evexpr(): -\n");
--sval; // Pop value
- --sattr; // Pop attrib
+ --sattr; // Pop attrib
+//printf("--> N-N: %i - %i = ", *sval, sval[1]);
*sval -= sval[1]; // Compute value
+//printf("%i\n", *sval);
attr = (WORD)(*sattr & TDB);
#if 0
// are in the same segment, but that's the only requirement.
case LE:
//printf("evexpr(): LE\n");
- --sattr;
- --sval;
+ sattr--;
+ sval--;
if ((*sattr & TDB) != (sattr[1] & TDB))
error(seg_error);
break;
case GE:
//printf("evexpr(): GE\n");
- --sattr;
- --sval;
+ sattr--;
+ sval--;
if ((*sattr & TDB) != (sattr[1] & TDB))
error(seg_error);
break;
case '>':
//printf("evexpr(): >\n");
- --sattr;
- --sval;
+ sattr--;
+ sval--;
if ((*sattr & TDB) != (sattr[1] & TDB))
error(seg_error);
break;
case '<':
//printf("evexpr(): <\n");
- --sattr;
- --sval;
+ sattr--;
+ sval--;
if ((*sattr & TDB) != (sattr[1] & TDB))
error(seg_error);
break;
case NE:
//printf("evexpr(): NE\n");
- --sattr;
- --sval;
+ sattr--;
+ sval--;
if ((*sattr & TDB) != (sattr[1] & TDB))
error(seg_error);
break;
case '=':
//printf("evexpr(): =\n");
- --sattr;
- --sval;
+ sattr--;
+ sval--;
if ((*sattr & TDB) != (sattr[1] & TDB))
error(seg_error);
switch ((int)tk[-1])
{
case '*':
- --sval;
- --sattr; // Pop attrib
+ sval--;
+ sattr--; // Pop attrib
+//printf("--> NxN: %i x %i = ", *sval, sval[1]);
*sval *= sval[1];
+//printf("%i\n", *sval);
break;
case '/':
- --sval;
- --sattr; // Pop attrib
+ sval--;
+ sattr--; // Pop attrib
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;
- --sattr; // Pop attrib
+ sval--;
+ sattr--; // Pop attrib
if (sval[1] == 0)
return error("mod (%) by zero");
*sval %= sval[1];
break;
case SHL:
- --sval;
- --sattr; // Pop attrib
+ sval--;
+ sattr--; // Pop attrib
*sval <<= sval[1];
break;
case SHR:
- --sval;
- --sattr; // Pop attrib
+ sval--;
+ sattr--; // Pop attrib
*sval >>= sval[1];
break;
case '&':
- --sval;
- --sattr; // Pop attrib
+ sval--;
+ sattr--; // Pop attrib
*sval &= sval[1];
break;
case '^':
- --sval;
- --sattr; // Pop attrib
+ sval--;
+ sattr--; // Pop attrib
*sval ^= sval[1];
break;
case '|':
- --sval;
- --sattr; // Pop attrib
+ sval--;
+ sattr--; // Pop attrib
*sval |= sval[1];
break;
default: