2 // RMAC - Reboot's Macro Assembler for the Atari Jaguar Console System
3 // EXPR.C - Expression Analyzer
4 // Copyright (C) 199x Landon Dyer, 2011 Reboot and Friends
5 // RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986
6 // Source Utilised with the Kind Permission of Landon Dyer
20 #define DEF_KW // Declare keyword values
21 #include "kwtab.h" // Incl generated keyword tables & defs
23 static char tokcl[128]; // Generated table of token classes
24 static VALUE evstk[EVSTACKSIZE]; // Evaluator value stack
25 static WORD evattr[EVSTACKSIZE]; // Evaluator attribute stack
27 // Token-class initialization list
30 CONST, SYMBOL, 0, // ID
31 '(', '[', '{', 0, // OPAR
32 ')', ']', '}', 0, // CPAR
33 CR_DEFINED, CR_REFERENCED, // SUNARY (special unary)
36 '!', '~', UNMINUS, 0, // UNARY
37 '*', '/', '%', 0, // MULT
40 LE, GE, '<', '>', NE, '=', 0, // REL
47 const char missym_error[] = "missing symbol";
48 const char str_error[] = "missing symbol or string";
50 // Convert expression to postfix
51 static TOKEN * tk; // Deposit tokens here (this is really a
52 // pointer to exprbuf from direct.c)
53 static symbolNum; // Pointer to the entry in symbolPtr[]
57 // Obtain a String Value
59 static VALUE str_value(char * p)
64 v = (v << 8) | (*p & 0xFF);
71 // Initialize Expression Analyzer
76 char * p; // Token pointer
78 // Initialize token-class table
79 for(i=0; i<128; i++) // Mark all entries END
82 for(i=0, p=itokcl; *p!=1; p++)
87 tokcl[(int)(*p)] = (char)i;
95 // Binary operators (all the same precedence)
104 while (tokcl[*tok] >= MULT)
119 // Unary operators (detect unary '-')
132 if (*tok == '-' || class == UNARY)
144 else if (class == SUNARY)
156 case CR_MACDEF: // ^^macdef <macro-name>
157 if (*tok++ != SYMBOL)
158 return error(missym_error);
165 w = (lookup(p, MACRO, 0) == NULL ? 0 : 1);
175 if (*tok++ != SYMBOL)
176 return error(missym_error);
188 w = ((sy = lookup(p, LABEL, j)) != NULL && (sy->sattr & w) ? 1 : 0);
193 if (*tok != SYMBOL && *tok != STRING)
194 return error(str_error);
204 return error(comma_error);
206 if (*tok != SYMBOL && *tok != STRING)
207 return error(str_error);
216 w = (WORD)(!strcmp(p, p2));
230 // Terminals (CONSTs) and parenthesis grouping
255 sy = lookup(p, LABEL, j);
258 sy = NewSymbol(p, LABEL, j);
260 // Check register bank usage
261 if (sy->sattre & EQUATEDREG)
263 if ((regbank == BANK_0) && (sy->sattre & BANK_1) && !altbankok)
264 warns("equated symbol \'%s\' cannot be used in register bank 0", sy->sname);
266 if ((regbank == BANK_1) && (sy->sattre & BANK_0) && !altbankok)
267 warns("equated symbol \'%s\' cannot be used in register bank 1", sy->sname);
275 symbolPtr[symbolNum] = sy;
282 *tk++ = str_value((char *)*tok++);
284 *tk++ = str_value(string[*tok++]);
292 return error("missing close parenthesis ')'");
300 return error("missing close parenthesis ']'");
304 *tk++ = ACONST; // Attributed const
305 *tk++ = sloc; // Current location
306 *tk++ = cursect | DEFINED; // Store attribs
309 *tk++ = ACONST; // Attributed const
314 *tk++ = pcloc; // Location at start of line
316 *tk++ = ABS | DEFINED; // Store attribs
319 return error("bad expression");
327 // Recursive-descent expression analyzer (with some simple speed hacks)
329 int expr(TOKEN * otk, VALUE * a_value, WORD * a_attr, SYM ** a_esym)
331 // Passed in values (once derefenced, that is) can all be zero. They are
332 // there so that the expression analyzer can fill them in as needed. The
333 // expression analyzer gets its input from "tok", and not from anything
334 // passed in by the user.
339 tk = otk; // Set token pointer to 'exprbuf' (direct.c)
340 // Also set in various other places too (riscasm.c, e.g.)
341 // symbolNum = 0; // Set symbol number in symbolPtr[] to 0
343 // Optimize for single constant or single symbol.
345 || (((*tok == CONST || *tok == SYMBOL) || (*tok >= KW_R0 && *tok <= KW_R31))
346 && (tokcl[tok[2]] < UNARY)))
348 if (*tok >= KW_R0 && *tok <= KW_R31)
351 *tk++ = *a_value = (*tok - KW_R0);
352 *a_attr = ABS | DEFINED;
361 else if (*tok == CONST)
364 *tk++ = *a_value = tok[1];
365 *a_attr = ABS | DEFINED;
370 else if (*tok == '*')
375 *tk++ = *a_value = orgaddr;
377 *tk++ = *a_value = pcloc;
379 *a_attr = ABS | DEFINED;
397 j = (*p == '.' ? curenv : 0);
400 sy = lookup(p, LABEL, j);
403 sy = NewSymbol(p, LABEL, j);
405 sy->sattr |= REFERENCED;
407 // Check for undefined register equates
408 if (sy->sattre & UNDEF_EQUR)
410 errors("undefined register equate '%s'", sy->sname);
411 //if we return right away, it returns some spurious errors...
415 // Check register bank usage
416 if (sy->sattre & EQUATEDREG)
418 if ((regbank == BANK_0) && (sy->sattre & BANK_1) && !altbankok)
419 warns("equated symbol '%s' cannot be used in register bank 0", sy->sname);
421 if ((regbank == BANK_1) && (sy->sattre & BANK_0) && !altbankok)
422 warns("equated symbol '%s' cannot be used in register bank 1", sy->sname);
430 symbolPtr[symbolNum] = sy;
434 if (sy->sattr & DEFINED)
435 *a_value = sy->svalue;
439 if (sy->sattre & EQUATEDREG)
442 *a_attr = (WORD)(sy->sattr & ~GLOBAL);
444 if ((sy->sattr & (GLOBAL | DEFINED)) == GLOBAL && a_esym != NULL)
457 return evexpr(otk, a_value, a_attr, a_esym);
462 // Evaluate expression.
463 // If the expression involves only ONE external symbol, the expression is
464 // UNDEFINED, but it's value includes everything but the symbol value, and
465 // `a_esym' is set to the external symbol.
467 int evexpr(TOKEN * tk, VALUE * a_value, WORD * a_attr, SYM ** a_esym)
476 sval = evstk; // (Empty) initial stack
478 esym = NULL; // No external symbol involved
481 while (*tk != ENDEXPR)
486 // sy = (SYM *)*tk++;
487 sy = symbolPtr[*tk++];
488 sy->sattr |= REFERENCED; // Set "referenced" bit
490 if (!(sy->sattr & DEFINED))
492 // Reference to undefined symbol
493 if (!(sy->sattr & GLOBAL))
500 if (esym != NULL) // Check for multiple externals
501 return error(seg_error);
506 if (sy->sattr & DEFINED)
508 *++sval = sy->svalue; // Push symbol's value
512 *++sval = 0; // 0 for undefined symbols
515 *++sattr = (WORD)(sy->sattr & ~GLOBAL); // Push attribs
516 sym_seg = (WORD)(sy->sattr & (TEXT | DATA | BSS));
519 *++sval = *tk++; // Push value
520 *++sattr = ABS | DEFINED; // Push simple attribs
523 *++sval = *tk++; // Push value
524 *++sattr = (WORD)*tk++; // Push attribs
527 // Binary "+" and "-" matrix:
530 // ----------------------------
531 // ABS | ABS | Sect | Other |
532 // Sect | Sect | [1] | Error |
533 // Other | Other | Error | [1] |
534 // ----------------------------
540 --sattr; // Pop attrib
541 *sval += sval[1]; // Compute value
543 if (!(*sattr & (TEXT | DATA | BSS)))
545 else if (sattr[1] & (TEXT | DATA | BSS))
546 return error(seg_error);
551 --sattr; // Pop attrib
552 *sval -= sval[1]; // Compute value
554 attr = (WORD)(*sattr & (TEXT | DATA | BSS));
558 else if (sattr[1] & (TEXT | DATA | BSS))
560 if (!(attr & sattr[1]))
561 return error(seg_error);
563 *sattr &= ~(TEXT | DATA | BSS);
567 // Unary operators only work on ABS items
569 if (*sattr & (TEXT | DATA | BSS))
573 *sattr = ABS | DEFINED; // Expr becomes absolute
576 if (*sattr & (TEXT | DATA | BSS))
580 *sattr = ABS | DEFINED; // Expr becomes absolute
583 if (*sattr & (TEXT | DATA | BSS))
587 *sattr = ABS | DEFINED; // Expr becomes absolute
589 // Comparison operators must have two values that
590 // are in the same segment, but that's the only requirement.
595 if ((*sattr & TDB) != (sattr[1] & TDB))
598 *sattr = ABS | DEFINED;
599 *sval = *sval <= sval[1];
605 if ((*sattr & TDB) != (sattr[1] & TDB))
608 *sattr = ABS | DEFINED;
609 *sval = *sval >= sval[1];
615 if ((*sattr & TDB) != (sattr[1] & TDB))
618 *sattr = ABS | DEFINED;
619 *sval = *sval > sval[1];
625 if ((*sattr & TDB) != (sattr[1] & TDB))
628 *sattr = ABS | DEFINED;
629 *sval = *sval < sval[1];
635 if ((*sattr & TDB) != (sattr[1] & TDB))
638 *sattr = ABS | DEFINED;
639 *sval = *sval != sval[1];
645 if ((*sattr & TDB) != (sattr[1] & TDB))
648 *sattr = ABS | DEFINED;
649 *sval = *sval == sval[1];
651 // All other binary operators must have two ABS items
652 // to work with. They all produce an ABS value.
654 // GH - Removed for v1.0.15 as part of the fix for indexed loads.
655 //if ((*sattr & (TEXT|DATA|BSS)) || (*--sattr & (TEXT|DATA|BSS)))
657 *sattr = ABS | DEFINED; // Expr becomes absolute
663 --sattr; // Pop attrib
668 --sattr; // Pop attrib
671 return error("divide by zero");
677 --sattr; // Pop attrib
680 return error("mod (%) by zero");
686 --sattr; // Pop attrib
691 --sattr; // Pop attrib
696 --sattr; // Pop attrib
701 --sattr; // Pop attrib
706 --sattr; // Pop attrib
710 interror(5); // Bad operator in expression stream
721 // sym_seg added in 1.0.16 to solve a problem with forward symbols in
722 // expressions where absolute values also existed. The absolutes were
723 // overiding the symbol segments and not being included :(
724 //*a_attr = *sattr | sym_seg; // Copy value + attrib
726 *a_attr = *sattr; // Copy value + attrib