- tk = otk;
-
- // Optimize for single constant or single symbol.
- if((tok[1] == EOL) ||
- (((*tok == CONST || *tok == SYMBOL) || (*tok >= KW_R0 && *tok <= KW_R31)) &&
- (tokcl[tok[2]] < UNARY))) {
-
- if(*tok >= KW_R0 && *tok <= KW_R31) {
- *tk++ = CONST;
- *tk++ = *a_value = (*tok - KW_R0);
- *a_attr = ABS | DEFINED;
- if(a_esym != NULL)
- *a_esym = NULL;
- tok++;
- *tk++ = ENDEXPR;
- return(OK);
- } else if(*tok == CONST) {
- *tk++ = CONST;
- *tk++ = *a_value = tok[1];
- *a_attr = ABS | DEFINED;
- if(a_esym != NULL)
- *a_esym = NULL;
- } else if(*tok == '*') {
- *tk++ = CONST;
- if(orgactive)
- *tk++ = *a_value = orgaddr;
- else
- *tk++ = *a_value = pcloc;
- *a_attr = ABS | DEFINED;
- //*tk++ =
- if(a_esym != NULL)
- *a_esym = NULL;
- tok--;
- } else {
- p = (char *)tok[1];
- j = 0;
- if(*p == '.')
- j = curenv;
- sy = lookup(p, LABEL, j);
-
- if(sy == NULL)
- sy = newsym(p, LABEL, j);
- sy->sattr |= REFERENCED;
-
- if(sy->sattre & EQUATEDREG) { // Check register bank usage
- 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)
- warns("equated symbol \'%s\' cannot be used in register bank 1", sy->sname);
- }
-
- *tk++ = SYMBOL;
- *tk++ = (TOKEN)sy;
-
- if(sy->sattr & DEFINED)
- *a_value = sy->svalue;
- else *a_value = 0;
-
- if(sy->sattre & EQUATEDREG)
- *a_value &= 0x1F;
-
- *a_attr = (WORD)(sy->sattr & ~GLOBAL);
-
- if((sy->sattr & (GLOBAL|DEFINED)) == GLOBAL && a_esym != NULL) {
- *a_esym = sy;
- }
- }
- tok += 2;
- *tk++ = ENDEXPR;
- return(OK);
- }
-
- if(expr0() != OK)
- return(ERROR);
- *tk++ = ENDEXPR;
- return(evexpr(otk, a_value, a_attr, a_esym));
+//
+// Recursive-descent expression analyzer (with some simple speed hacks)
+//
+int expr(TOKEN * otk, VALUE * a_value, WORD * a_attr, SYM ** a_esym)
+{
+ // Passed in values (once derefenced, that is) can all be zero. They are
+ // there so that the expression analyzer can fill them in as needed. The
+ // expression analyzer gets its input from the global token pointer "tok",
+ // and not from anything passed in by the user.
+ SYM * symbol;
+ char * p;
+ int j;
+
+ 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.
+ // 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)))
+ {
+ if (*tok >= KW_R0 && *tok <= KW_R31)
+ {
+ *evalTokenBuffer++ = CONST;
+ *evalTokenBuffer++ = *a_value = (*tok - KW_R0);
+ *a_attr = ABS | DEFINED;
+
+ if (a_esym != NULL)
+ *a_esym = NULL;
+
+ tok++;
+ }
+ else if (*tok == CONST)
+ {
+ *evalTokenBuffer++ = CONST;
+ *evalTokenBuffer++ = *a_value = tok[1];
+ *a_attr = ABS | DEFINED;
+
+ if (a_esym != NULL)
+ *a_esym = NULL;
+
+ tok += 2;
+//printf("Quick eval in expr(): CONST = %i, tokenClass[tok[2]] = %i\n", *a_value, tokenClass[*tok]);
+ }
+ else if (*tok == '*')
+ {
+ *evalTokenBuffer++ = CONST;
+
+ if (orgactive)
+ *evalTokenBuffer++ = *a_value = orgaddr;
+ else
+ *evalTokenBuffer++ = *a_value = pcloc;
+
+ // '*' takes attributes of current section, not ABS!
+ *a_attr = cursect | DEFINED;
+
+ if (a_esym != NULL)
+ *a_esym = NULL;
+
+ tok++;
+ }
+ else if (*tok == STRING || *tok == SYMBOL)
+ {
+ p = string[tok[1]];
+ j = (*p == '.' ? curenv : 0);
+ symbol = lookup(p, LABEL, j);
+#if 0
+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
+
+ if (symbol == NULL)
+ symbol = NewSymbol(p, LABEL, j);
+
+ symbol->sattr |= REFERENCED;
+
+ // 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...
+// return ERROR;
+ }
+
+ // Check register bank usage
+ if (symbol->sattre & EQUATEDREG)
+ {
+ 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)
+ warns("equated symbol '%s' cannot be used in register bank 1", symbol->sname);
+ }
+
+ *evalTokenBuffer++ = SYMBOL;
+#if 0
+ *evalTokenBuffer++ = (TOKEN)symbol;
+#else
+/*
+While this approach works, it's wasteful. It would be better to use something
+that's already available, like the symbol "order defined" table (which needs to
+be converted from a linked list into an array).
+*/
+ *evalTokenBuffer++ = symbolNum;
+ symbolPtr[symbolNum] = symbol;
+ symbolNum++;
+#endif
+
+ if (symbol->sattr & DEFINED)
+ *a_value = symbol->svalue;
+ else
+ *a_value = 0;
+
+/*
+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)
+ *a_value &= 0x1F;
+
+ *a_attr = (WORD)(symbol->sattr & ~GLOBAL);
+
+ if ((symbol->sattr & (GLOBAL | DEFINED)) == GLOBAL
+ && a_esym != NULL)
+ *a_esym = symbol;
+
+ tok += 2;
+ }
+ else
+ {
+ // Unknown type here... Alert the user!,
+ error("undefined RISC register in expression");
+ // Prevent spurious error reporting...
+ tok++;
+ return ERROR;
+ }
+
+ *evalTokenBuffer++ = ENDEXPR;
+ return OK;
+ }
+
+ if (expr0() != OK)
+ return ERROR;
+
+ *evalTokenBuffer++ = ENDEXPR;
+ return evexpr(otk, a_value, a_attr, a_esym);