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 int symbolNum; // Pointer to the entry in symbolPtr[]
+static PTR evalTokenBuffer; // Deposit tokens here (this is really a
+ // pointer to exprbuf from direct.c)
+ // (Can also be from others, like
+ // riscasm.c)
+static int symbolNum; // Pointer to the entry in symbolPtr[]
//
//
int expr0(void)
{
- TOKEN t;
-
if (expr1() != OK)
return ERROR;
while (tokenClass[*tok] >= MULT)
{
- t = *tok++;
+ TOKEN t = *tok++;
if (expr1() != OK)
return ERROR;
- *evalTokenBuffer++ = t;
+ *evalTokenBuffer.u32++ = t;
}
return OK;
//
// 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".
+// 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)
{
- int class;
TOKEN t;
SYM * sy;
char * p, * p2;
WORD w;
int j;
- uint64_t * evalTokenBuffer64;
- class = tokenClass[*tok];
+ int class = tokenClass[*tok];
if (*tok == '-' || *tok == '+' || class == UNARY)
{
if (t == '-')
t = UNMINUS;
- // With leading + we don't have to deposit
- // anything to the buffer because there's
- // no unary '+' nor we have to do anything about it
+ // With leading + we don't have to deposit anything to the buffer
+ // because there's no unary '+' nor we have to do anything about it
if (t != '+')
- *evalTokenBuffer++ = t;
+ *evalTokenBuffer.u32++ = t;
}
else if (class == SUNARY)
{
- switch ((int)*tok++)
+ switch (*tok++)
{
case CR_ABSCOUNT:
- *evalTokenBuffer++ = CONST;
- evalTokenBuffer64 = (uint64_t *)evalTokenBuffer;
- *evalTokenBuffer64++ = (LONG)sect[ABS].sloc;
- evalTokenBuffer = (uint32_t *)evalTokenBuffer64;
+ *evalTokenBuffer.u32++ = CONST;
+ *evalTokenBuffer.u64++ = (uint64_t)sect[ABS].sloc;
break;
case CR_TIME:
- *evalTokenBuffer++ = CONST;
- evalTokenBuffer64 = (uint64_t *)evalTokenBuffer;
- *evalTokenBuffer64++ = dos_time();
- evalTokenBuffer = (uint32_t *)evalTokenBuffer64;
+ *evalTokenBuffer.u32++ = CONST;
+ *evalTokenBuffer.u64++ = dos_time();
break;
case CR_DATE:
- *evalTokenBuffer++ = CONST;
- evalTokenBuffer64 = (uint64_t *)evalTokenBuffer;
- *evalTokenBuffer64++ = dos_date();
- evalTokenBuffer = (uint32_t *)evalTokenBuffer64;
+ *evalTokenBuffer.u32++ = CONST;
+ *evalTokenBuffer.u64++ = dos_date();
break;
- case CR_MACDEF: // ^^macdef <macro-name>
+ case CR_MACDEF: // ^^macdef <macro-name>
if (*tok++ != SYMBOL)
return error(missym_error);
p = string[*tok++];
w = (lookup(p, MACRO, 0) == NULL ? 0 : 1);
- evalTokenBuffer64 = (uint64_t *)evalTokenBuffer;
- *evalTokenBuffer64++ = (TOKEN)w;
- evalTokenBuffer = (uint32_t *)evalTokenBuffer64;
- *evalTokenBuffer++ = (TOKEN)w;
+ *evalTokenBuffer.u32++ = CONST;
+ *evalTokenBuffer.u64++ = (uint64_t)w;
break;
case CR_DEFINED:
w = DEFINED;
p = string[*tok++];
j = (*p == '.' ? curenv : 0);
w = ((sy = lookup(p, LABEL, j)) != NULL && (sy->sattr & w) ? 1 : 0);
- *evalTokenBuffer++ = CONST;
- uint64_t *evalTokenBuffer64 = (uint64_t *)evalTokenBuffer;
- *evalTokenBuffer64++ = (TOKEN)w;
- evalTokenBuffer = (uint32_t *)evalTokenBuffer64;
+ *evalTokenBuffer.u32++ = CONST;
+ *evalTokenBuffer.u64++ = (uint64_t)w;
break;
case CR_STREQ:
if (*tok != SYMBOL && *tok != STRING)
tok += 2;
w = (WORD)(!strcmp(p, p2));
- *evalTokenBuffer++ = CONST;
- evalTokenBuffer64 = (uint64_t *)evalTokenBuffer;
- *evalTokenBuffer64++ = (TOKEN)w;
- evalTokenBuffer = (uint32_t *)evalTokenBuffer64;
+ *evalTokenBuffer.u32++ = CONST;
+ *evalTokenBuffer.u64++ = (uint64_t)w;
break;
}
}
char * p;
SYM * sy;
int j;
- uint64_t * evalTokenBuffer64;
- uint64_t * tok64;
+ PTR ptk;
- switch ((int)*tok++)
+ switch (*tok++)
{
case CONST:
- *evalTokenBuffer++ = CONST;
- evalTokenBuffer64 = (uint64_t *)evalTokenBuffer;
- tok64 = (uint64_t *)tok;
- *evalTokenBuffer64++ = *tok64++;
- tok = (TOKEN *)tok64;
- evalTokenBuffer = (TOKEN *)evalTokenBuffer64;
- break;
case FCONST:
- *evalTokenBuffer++ = FCONST;
- evalTokenBuffer64 = (uint64_t *)evalTokenBuffer;
- tok64 = (uint64_t *)tok;
- *evalTokenBuffer64++ = *tok64++;
- tok = (TOKEN *)tok64;
- evalTokenBuffer = (TOKEN *)evalTokenBuffer64;
+ ptk.u32 = tok;
+ *evalTokenBuffer.u32++ = CONST;
+ *evalTokenBuffer.u64++ = *ptk.u64++;
+ tok = ptk.u32;
break;
case SYMBOL:
p = string[*tok++];
warn("equated symbol \'%s\' cannot be used in register bank 1", sy->sname);
}
- *evalTokenBuffer++ = SYMBOL;
- *evalTokenBuffer++ = symbolNum;
+ *evalTokenBuffer.u32++ = SYMBOL;
+ *evalTokenBuffer.u32++ = symbolNum;
symbolPtr[symbolNum] = sy;
symbolNum++;
break;
case STRING:
- *evalTokenBuffer++ = CONST;
- uint64_t *evalTokenBuffer64 = (uint64_t *)evalTokenBuffer;
- *evalTokenBuffer64++ = str_value(string[*tok++]);
- evalTokenBuffer = (uint32_t *)evalTokenBuffer64;
+ *evalTokenBuffer.u32++ = CONST;
+ *evalTokenBuffer.u64++ = str_value(string[*tok++]);
break;
case '(':
if (expr0() != OK)
if (*tok++ != ']')
return error("missing closing bracket ']'");
- break;
- case '$':
- *evalTokenBuffer++ = ACONST; // Attributed const
- *evalTokenBuffer++ = sloc; // Current location
- *evalTokenBuffer++ = cursect | DEFINED; // Store attribs
- break;
- case '*':
- *evalTokenBuffer++ = ACONST; // Attributed const
-
- // pcloc == location at start of line
- *evalTokenBuffer++ = (orgactive ? orgaddr : pcloc);
- // '*' takes attributes of current section, not ABS!
- *evalTokenBuffer++ = cursect | DEFINED;
break;
case '{':
- if (expr0() != OK) // Eat up first parameter (register or immediate)
+ if (expr0() != OK) // Eat up first parameter (register or immediate)
return ERROR;
- if (*tok++ != ':') // Demand a ':' there
+ if (*tok++ != ':') // Demand a ':' there
return error("missing colon ':'");
- if (expr0() != OK) // Eat up second parameter (register or immediate)
+ if (expr0() != OK) // Eat up second parameter (register or immediate)
return ERROR;
if (*tok++ != '}')
return error("missing closing brace '}'");
+ break;
+ case '$':
+ *evalTokenBuffer.u32++ = ACONST; // Attributed const
+ *evalTokenBuffer.u32++ = sloc; // Current location
+ *evalTokenBuffer.u32++ = cursect | DEFINED; // Store attribs
+ break;
+ case '*':
+ *evalTokenBuffer.u32++ = ACONST; // Attributed const
+
+ // pcloc == location at start of line
+ *evalTokenBuffer.u32++ = (orgactive ? orgaddr : pcloc);
+ // '*' takes attributes of current section, not ABS!
+ *evalTokenBuffer.u32++ = cursect | DEFINED;
break;
default:
return error("bad expression");
SYM * symbol;
char * p;
int j;
+ PTR ptk;
- evalTokenBuffer = otk; // Set token pointer to 'exprbuf' (direct.c)
+ evalTokenBuffer.u32 = otk; // Set token pointer to 'exprbuf' (direct.c)
// Also set in various other places too (riscasm.c,
// e.g.)
// 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 0
// if ((tok[1] == EOL)
if ((tok[1] == EOL && ((tok[0] != CONST || tok[0] != FCONST) && tokenClass[tok[0]] != SUNARY))
// || (((*tok == CONST || *tok == FCONST || *tok == SYMBOL) || (*tok >= KW_R0 && *tok <= KW_R31))
// && (tokenClass[tok[2]] < UNARY)))
|| (((tok[0] == SYMBOL) || (tok[0] >= KW_R0 && tok[0] <= KW_R31))
- && (tokenClass[tok[2]] < UNARY))
+ && (tokenClass[tok[2]] < UNARY))
|| ((tok[0] == CONST || tok[0] == FCONST) && (tokenClass[tok[3]] < UNARY))
)
+#else
+// Shamus: Seems to me that this could be greatly simplified by 1st checking if the first token is a multibyte token, *then* checking if there's an EOL after it depending on the actual length of the token (multiple vs. single). Otherwise, we have the horror show that is the following:
+ if ((tok[1] == EOL
+ && (tok[0] != CONST && tokenClass[tok[0]] != SUNARY))
+ || (((tok[0] == SYMBOL)
+ || (tok[0] >= KW_R0 && tok[0] <= KW_R31))
+ && (tokenClass[tok[2]] < UNARY))
+ || ((tok[0] == CONST) && (tokenClass[tok[3]] < UNARY))
+ )
+// Shamus: Yes, you can parse that out and make some kind of sense of it, but damn, it takes a while to get it and understand the subtle bugs that result from not being careful about what you're checking; especially vis-a-vis niavely checking tok[1] for an EOL. O_o
+#endif
{
if (*tok >= KW_R0 && *tok <= KW_R31)
{
- *evalTokenBuffer++ = CONST;
- uint64_t *evalTokenBuffer64 = (uint64_t *)evalTokenBuffer;
- *evalTokenBuffer64++ = *a_value = (*tok - KW_R0);
- evalTokenBuffer = (uint32_t *)evalTokenBuffer64;
+ *evalTokenBuffer.u32++ = CONST;
+ *evalTokenBuffer.u64++ = *a_value = (*tok - KW_R0);
*a_attr = ABS | DEFINED;
if (a_esym != NULL)
}
else if (*tok == CONST)
{
- *evalTokenBuffer++ = CONST;
- uint64_t *evalTokenBuffer64 = (uint64_t *)evalTokenBuffer;
- uint64_t *tok64 = (uint64_t *)&tok[1];
- *evalTokenBuffer64++ = *tok64++;
- evalTokenBuffer = (TOKEN *)evalTokenBuffer64;
- *a_value = tok[1];
+ ptk.u32 = tok;
+ *evalTokenBuffer.u32++ = *ptk.u32++;
+ *evalTokenBuffer.u64++ = *a_value = *ptk.u64++;
*a_attr = ABS | DEFINED;
+ tok = ptk.u32;
if (a_esym != NULL)
*a_esym = NULL;
- tok += 3;
//printf("Quick eval in expr(): CONST = %i, tokenClass[tok[2]] = %i\n", *a_value, tokenClass[*tok]);
}
+// Not sure that removing float constant here is going to break anything and/or
+// make things significantly slower, but having this here seems to cause the
+// complexity of the check to get to this part of the parse to go through the
+// roof, and dammit, I just don't feel like fighting that fight ATM. :-P
+#if 0
else if (*tok == FCONST)
{
- *evalTokenBuffer++ = FCONST;
- *((double *)evalTokenBuffer) = *((double *)&tok[1]);
- evalTokenBuffer += 2;
- //*(double *)evalTokenBuffer++ = tok[2];
- *a_value = *((uint64_t *)&tok[1]);
+ *evalTokenBuffer.u32++ = *tok++;
+ *evalTokenBuffer.u64++ = *a_value = *tok.u64++;
*a_attr = ABS | DEFINED | FLOAT;
if (a_esym != NULL)
*a_esym = NULL;
- tok += 3;
//printf("Quick eval in expr(): CONST = %i, tokenClass[tok[2]] = %i\n", *a_value, tokenClass[*tok]);
}
+#endif
else if (*tok == '*')
{
- *evalTokenBuffer++ = CONST;
- uint64_t *evalTokenBuffer64 = (uint64_t *)evalTokenBuffer;
+ *evalTokenBuffer.u32++ = CONST;
if (orgactive)
- *evalTokenBuffer64++ = *a_value = orgaddr;
+ *evalTokenBuffer.u64++ = *a_value = orgaddr;
else
- *evalTokenBuffer64++ = *a_value = pcloc;
- evalTokenBuffer = (uint32_t *)evalTokenBuffer64;
+ *evalTokenBuffer.u64++ = *a_value = pcloc;
// '*' takes attributes of current section, not ABS!
*a_attr = cursect | DEFINED;
warn("equated symbol '%s' cannot be used in register bank 1", symbol->sname);
}
- *evalTokenBuffer++ = SYMBOL;
+ *evalTokenBuffer.u32++ = SYMBOL;
#if 0
*evalTokenBuffer++ = (TOKEN)symbol;
#else
that's already available, like the symbol "order defined" table (which needs to
be converted from a linked list into an array).
*/
- *evalTokenBuffer++ = symbolNum;
+ *evalTokenBuffer.u32++ = symbolNum;
symbolPtr[symbolNum] = symbol;
symbolNum++;
#endif
return ERROR;
}
- *evalTokenBuffer++ = ENDEXPR;
+ *evalTokenBuffer.u32++ = ENDEXPR;
return OK;
}
if (expr0() != OK)
return ERROR;
- *evalTokenBuffer++ = ENDEXPR;
+ *evalTokenBuffer.u32++ = ENDEXPR;
return evexpr(otk, a_value, a_attr, a_esym);
}
// Evaluate expression.
// If the expression involves only ONE external symbol, the expression is
// UNDEFINED, but it's value includes everything but the symbol value, and
-// `a_esym' is set to the external symbol.
+// 'a_esym' is set to the external symbol.
//
-int evexpr(TOKEN * tk, uint64_t * a_value, WORD * a_attr, SYM ** a_esym)
+int evexpr(TOKEN * _tk, uint64_t * a_value, WORD * a_attr, SYM ** a_esym)
{
WORD attr, attr2;
SYM * sy;
WORD * sattr = evattr;
SYM * esym = NULL; // No external symbol involved
WORD sym_seg = 0;
- uint64_t *tk64;
+ PTR tk;
+ tk.u32 = _tk;
- while (*tk != ENDEXPR)
+ while (*tk.u32 != ENDEXPR)
{
- switch ((int)*tk++)
+ switch ((int)*tk.u32++)
{
case SYMBOL:
//printf("evexpr(): SYMBOL\n");
- sy = symbolPtr[*tk++];
+ sy = symbolPtr[*tk.u32++];
sy->sattr |= REFERENCED; // Set "referenced" bit
if (!(sy->sattr & DEFINED))
sym_seg = (WORD)(sy->sattr & TDB);
break;
case CONST:
- tk64 = (uint64_t *)tk;
- *++sval = *tk64++;
- tk = (TOKEN *)tk64;
+ *++sval = *tk.u64++;
//printf("evexpr(): CONST = %lX\n", *sval);
*++sattr = ABS | DEFINED; // Push simple attribs
break;
case FCONST:
-//printf("evexpr(): CONST = %i\n", *tk);
- *((double *)sval) = *((double *)tk);
- tk += 2;
+//printf("evexpr(): FCONST = %i\n", *tk.u32);
+ *((double *)sval) = *((double *)tk.u32);
+ tk.u32 += 2;
*++sattr = ABS | DEFINED | FLOAT; // Push simple attribs
break;
case ACONST:
-//printf("evexpr(): ACONST = %i\n", *tk);
- *++sval = *tk++; // Push value
- *++sattr = (WORD)*tk++; // Push attribs
+//printf("evexpr(): ACONST = %i\n", *tk.u32);
+ *++sval = *tk.u32++; // Push value
+ *++sattr = (WORD)*tk.u32++; // Push attribs
break;
// Binary "+" and "-" matrix:
}
else
{
- *sval += sval[1]; // Compute value
+ *sval += sval[1]; // Compute value
}
//printf("%i\n", *sval);
}
else
{
- *sval -= sval[1]; // Compute value
+ *sval -= sval[1]; // Compute value
}
//printf("%i\n", *sval);
}
else
{
- *sval = -(int)*sval;
- *sattr = ABS | DEFINED; // Expr becomes absolute
+ *sval = -(int)*sval;
+ *sattr = ABS | DEFINED; // Expr becomes absolute
}
break;
case '!':
}
else
{
- *sval = *sval <= sval[1];
+ *sval = *sval <= sval[1];
}
*sattr = ABS | DEFINED;
}
else if (attr == 0)
{
- *sval = *sval >= sval[1];
+ *sval = *sval >= sval[1];
}
else
-
- *sattr = ABS | DEFINED;
+ *sattr = ABS | DEFINED;
break;
case '>':
*sval = *dst > *src;
}
else
-= {
- *sval = *sval > sval[1];
+ {
+ *sval = *sval > sval[1];
}
*sattr = ABS | DEFINED;
// Extract float attributes from both terms and pack them
// into a single value
- attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) > >1);
+ attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
if (attr == (FLOAT | (FLOAT >> 1)))
{
}
else
{
- *sval = *sval < sval[1];
+ *sval = *sval < sval[1];
}
*sattr = ABS | DEFINED;
}
else
{
- *sval = *sval != sval[1];
+ *sval = *sval != sval[1];
}
*sattr = ABS | DEFINED;
}
else
{
- *sval = *sval == sval[1];
+ *sval = *sval == sval[1];
}
*sattr = ABS | DEFINED;
break;
- // All other binary operators must have two ABS items
- // to work with. They all produce an ABS value.
+ // 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);
- switch ((int)tk[-1])
+ switch ((int)tk.u32[-1])
{
case '*':
sval--;
}
else
{
- *sval *= sval[1];
+ *sval *= sval[1];
}
//printf("%i\n", *sval);
// Float / Float
double * dst = (double *)sval;
double * src = (double *)(sval + 1);
+
if (*src == 0)
return error("divide by zero");
+
*dst = *dst / *src;
}
else if (attr == FLOAT)
// Float / Int
double * dst = (double *)sval;
uint64_t * src = (uint64_t *)(sval + 1);
+
if (*src == 0)
return error("divide by zero");
+
*dst = *dst / *src;
}
else if (attr == FLOAT >> 1)
// Int / Float
uint64_t * dst=(uint64_t *)sval;
double * src=(double *)(sval + 1);
+
if (*src == 0)
return error("divide by zero");
+
*(double *)dst = *dst / *src;
}
else
if (sval[1] == 0)
return error("divide by zero");
//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. :-/
- // Definitely a side effect of using uint32_ts intead of ints.
- *sval = (int32_t)sval[0] / (int32_t)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. :-/
+ // Definitely a side effect of using uint32_ts intead of
+ // ints.
+ *sval = (int32_t)sval[0] / (int32_t)sval[1];
}
*sattr = ABS | DEFINED; // Expr becomes absolute
case '%':
sval--;
sattr--; // Pop attrib
+
if ((*sattr | sattr[1]) & FLOAT)
return error("floating point numbers not allowed with operator '%'.");
case SHL:
sval--;
sattr--; // Pop attrib
+
if ((*sattr | sattr[1]) & FLOAT)
return error("floating point numbers not allowed with operator '<<'.");
+
*sattr = ABS | DEFINED; // Expr becomes absolute
*sval <<= sval[1];
break;
case SHR:
sval--;
sattr--; // Pop attrib
+
if ((*sattr | sattr[1]) & FLOAT)
return error("floating point numbers not allowed with operator '>>'.");
+
*sattr = ABS | DEFINED; // Expr becomes absolute
*sval >>= sval[1];
break;
case '&':
sval--;
sattr--; // Pop attrib
+
if ((*sattr | sattr[1]) & FLOAT)
return error("floating point numbers not allowed with operator '&'.");
+
*sattr = ABS | DEFINED; // Expr becomes absolute
*sval &= sval[1];
break;
case '^':
sval--;
sattr--; // Pop attrib
+
if ((*sattr | sattr[1]) & FLOAT)
return error("floating point numbers not allowed with operator '^'.");
+
*sattr = ABS | DEFINED; // Expr becomes absolute
*sval ^= sval[1];
break;
case '|':
sval--;
sattr--; // Pop attrib
+
if ((*sattr | sattr[1]) & FLOAT)
return error("floating point numbers not allowed with operator '|'.");
+
*sattr = ABS | DEFINED; // Expr becomes absolute
*sval |= sval[1];
break;