Basically, expr() was looking at the token following the one it was
looking at and bypassing the longer parse path if it found an EOL token
there. Problem is, some tokens have follow on values and so can be
considered compound tokens. In this case, the EOL token codes to 101,
having a constant with a value of 101 will not evaluate correctly in
this case as the CONST token is a compound token.
The short of this is that making assumptions is BAD! Don't do it! It
WILL come around to bite you in the ass eventually, in the form of
subtle bugs that are difficult to chase down. Assume nothing!
+// error(syntax_error);
+ error("syntax error; expected symbol");
// Check we are dealing with a symbol
if (*tok != SYMBOL)
{
// Check we are dealing with a symbol
if (*tok != SYMBOL)
{
+// error(syntax_error);
+ error("syntax error; expected symbol");
+// error(syntax_error);
+ error("syntax error; string missing");
+ {
+// error("syntax error");
+ sprintf(msg, "syntax error. expected EOL, found $%X ('%c')", *tok, *tok);
+ error(msg);
+ }
}
*evalTokenBuffer++ = SYMBOL;
}
*evalTokenBuffer++ = SYMBOL;
-#if 0
- *evalTokenBuffer++ = (TOKEN)sy;
-#else
*evalTokenBuffer++ = symbolNum;
symbolPtr[symbolNum] = sy;
symbolNum++;
*evalTokenBuffer++ = symbolNum;
symbolPtr[symbolNum] = sy;
symbolNum++;
break;
case STRING:
*evalTokenBuffer++ = CONST;
break;
case STRING:
*evalTokenBuffer++ = CONST;
case '*':
*evalTokenBuffer++ = ACONST; // Attributed const
case '*':
*evalTokenBuffer++ = ACONST; // Attributed const
if (orgactive)
*evalTokenBuffer++ = orgaddr;
else
*evalTokenBuffer++ = pcloc; // Location at start of line
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
break;
*evalTokenBuffer++ = ABS | DEFINED; // Store attribs
break;
evalTokenBuffer = otk; // Set token pointer to 'exprbuf' (direct.c)
// Also set in various other places too (riscasm.c, e.g.)
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.
// Optimize for single constant or single symbol.
+ // 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)))
{
|| (((*tok == CONST || *tok == SYMBOL) || (*tok >= KW_R0 && *tok <= KW_R31))
&& (tokenClass[tok[2]] < UNARY)))
{
-// *evalTokenBuffer++ = ENDEXPR;
-// return OK;
}
else if (*tok == CONST)
{
}
else if (*tok == CONST)
{
*a_esym = NULL;
tok += 2;
*a_esym = NULL;
tok += 2;
+//printf("Quick eval in expr(): CONST = %i, tokenClass[tok[2]] = %i\n", *a_value, tokenClass[*tok]);
}
else if (*tok == '*')
{
}
else if (*tok == '*')
{
if (a_esym != NULL)
*a_esym = NULL;
if (a_esym != NULL)
*a_esym = NULL;
tok++;
}
else if (*tok == STRING || *tok == SYMBOL)
tok++;
}
else if (*tok == STRING || *tok == SYMBOL)
*evalTokenBuffer++ = ENDEXPR;
return OK;
}
*evalTokenBuffer++ = ENDEXPR;
return OK;
}
switch ((int)*tk++)
{
case SYMBOL:
switch ((int)*tk++)
{
case SYMBOL:
+//printf("evexpr(): SYMBOL\n");
sy = symbolPtr[*tk++];
sy->sattr |= REFERENCED; // Set "referenced" bit
sy = symbolPtr[*tk++];
sy->sattr |= REFERENCED; // Set "referenced" bit
sym_seg = (WORD)(sy->sattr & (TEXT | DATA | BSS));
break;
case CONST:
sym_seg = (WORD)(sy->sattr & (TEXT | DATA | BSS));
break;
case CONST:
+//printf("evexpr(): CONST = %i\n", *tk);
*++sval = *tk++; // Push value
*++sattr = ABS | DEFINED; // Push simple attribs
break;
case ACONST:
*++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;
*++sval = *tk++; // Push value
*++sattr = (WORD)*tk++; // Push attribs
break;
// [1] + : Error
// - : ABS
case '+':
// [1] + : Error
// - : ABS
case '+':
+//printf("evexpr(): +\n");
--sval; // Pop value
--sattr; // Pop attrib
*sval += sval[1]; // Compute value
--sval; // Pop value
--sattr; // Pop attrib
*sval += sval[1]; // Compute value
+//printf("evexpr(): -\n");
--sval; // Pop value
--sattr; // Pop attrib
*sval -= sval[1]; // Compute value
--sval; // Pop value
--sattr; // Pop attrib
*sval -= sval[1]; // Compute value
break;
// Unary operators only work on ABS items
case UNMINUS:
break;
// Unary operators only work on ABS items
case UNMINUS:
+//printf("evexpr(): UNMINUS\n");
if (*sattr & (TEXT | DATA | BSS))
error(seg_error);
if (*sattr & (TEXT | DATA | BSS))
error(seg_error);
*sattr = ABS | DEFINED; // Expr becomes absolute
break;
case '!':
*sattr = ABS | DEFINED; // Expr becomes absolute
break;
case '!':
+//printf("evexpr(): !\n");
if (*sattr & (TEXT | DATA | BSS))
error(seg_error);
if (*sattr & (TEXT | DATA | BSS))
error(seg_error);
*sattr = ABS | DEFINED; // Expr becomes absolute
break;
case '~':
*sattr = ABS | DEFINED; // Expr becomes absolute
break;
case '~':
+//printf("evexpr(): ~\n");
if (*sattr & (TEXT | DATA | BSS))
error(seg_error);
if (*sattr & (TEXT | DATA | BSS))
error(seg_error);
// Comparison operators must have two values that
// are in the same segment, but that's the only requirement.
case LE:
// Comparison operators must have two values that
// are in the same segment, but that's the only requirement.
case LE:
+//printf("evexpr(): LE\n");
*sval = *sval <= sval[1];
break;
case GE:
*sval = *sval <= sval[1];
break;
case GE:
+//printf("evexpr(): GE\n");
*sval = *sval >= sval[1];
break;
case '>':
*sval = *sval >= sval[1];
break;
case '>':
+//printf("evexpr(): >\n");
*sval = *sval > sval[1];
break;
case '<':
*sval = *sval > sval[1];
break;
case '<':
+//printf("evexpr(): <\n");
*sval = *sval < sval[1];
break;
case NE:
*sval = *sval < sval[1];
break;
case NE:
+//printf("evexpr(): NE\n");
*sval = *sval != sval[1];
break;
case '=':
*sval = *sval != sval[1];
break;
case '=':
+//printf("evexpr(): =\n");
// All other binary operators must have two ABS items
// to work with. They all produce an ABS value.
default:
// 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);
// 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);
if (a0exattr & DEFINED)
{
if ((a0exattr & TDB) != cursect)
if (a0exattr & DEFINED)
{
if ((a0exattr & TDB) != cursect)
+//{
+//printf("m_br(): a0exattr = %X, cursect = %X, a0exval = %X, sloc = %X\n", a0exattr, cursect, a0exval, sloc);
v = a0exval - (sloc + 2);
v = a0exval - (sloc + 2);
if ((*tok >= KW_A0) && (*tok <= KW_A7))
{
if ((*tok >= KW_A0) && (*tok <= KW_A7))
{
// First token MUST be a symbol
if (*tok != SYMBOL)
{
// First token MUST be a symbol
if (*tok != SYMBOL)
{
+// error(syntax_error);
+ error("syntax error; expected symbol");
// Next token MUST be a symbol
if (*tok++ != SYMBOL)
{
// Next token MUST be a symbol
if (*tok++ != SYMBOL)
{
+// error(syntax_error);
+ error("syntax error; expected symbol");
- if (tk != NULL) // arg # is in range, so expand it
+ // Argument # is in range, so expand it
+ if (tk != NULL)
*tk++ = CONST;
*tk++ = v;
*tk++ = CONST;
*tk++ = v;
+//printf("CONST: %i\n", v);
#define MAJOR 1 // Major version number
#define MINOR 2 // Minor version number
#define MAJOR 1 // Major version number
#define MINOR 2 // Minor version number
-#define PATCH 7 // Patch release number
+#define PATCH 8 // Patch release number