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 (risca.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;
399 sy = lookup(p, LABEL, j);
402 sy = NewSymbol(p, LABEL, j);
404 sy->sattr |= REFERENCED;
406 // Check register bank usage
407 if (sy->sattre & EQUATEDREG)
409 if ((regbank == BANK_0) && (sy->sattre & BANK_1) && !altbankok)
410 warns("equated symbol \'%s\' cannot be used in register bank 0", sy->sname);
412 if ((regbank == BANK_1) && (sy->sattre & BANK_0) && !altbankok)
413 warns("equated symbol \'%s\' cannot be used in register bank 1", sy->sname);
421 symbolPtr[symbolNum] = sy;
425 if (sy->sattr & DEFINED)
426 *a_value = sy->svalue;
430 if (sy->sattre & EQUATEDREG)
433 *a_attr = (WORD)(sy->sattr & ~GLOBAL);
435 if ((sy->sattr & (GLOBAL | DEFINED)) == GLOBAL && a_esym != NULL)
448 return evexpr(otk, a_value, a_attr, a_esym);
453 // Evaluate expression.
454 // If the expression involves only ONE external symbol, the expression is
455 // UNDEFINED, but it's value includes everything but the symbol value, and
456 // `a_esym' is set to the external symbol.
458 int evexpr(TOKEN * tk, VALUE * a_value, WORD * a_attr, SYM ** a_esym)
467 sval = evstk; // (Empty) initial stack
469 esym = NULL; // No external symbol involved
472 while (*tk != ENDEXPR)
477 // sy = (SYM *)*tk++;
478 sy = symbolPtr[*tk++];
479 sy->sattr |= REFERENCED; // Set "referenced" bit
481 if (!(sy->sattr & DEFINED))
483 // Reference to undefined symbol
484 if (!(sy->sattr & GLOBAL))
491 if (esym != NULL) // Check for multiple externals
492 return error(seg_error);
497 if (sy->sattr & DEFINED)
499 *++sval = sy->svalue; // Push symbol's value
503 *++sval = 0; // 0 for undefined symbols
506 *++sattr = (WORD)(sy->sattr & ~GLOBAL); // Push attribs
507 sym_seg = (WORD)(sy->sattr & (TEXT | DATA | BSS));
510 *++sval = *tk++; // Push value
511 *++sattr = ABS | DEFINED; // Push simple attribs
514 *++sval = *tk++; // Push value
515 *++sattr = (WORD)*tk++; // Push attribs
518 // Binary "+" and "-" matrix:
521 // ----------------------------
522 // ABS | ABS | Sect | Other |
523 // Sect | Sect | [1] | Error |
524 // Other | Other | Error | [1] |
525 // ----------------------------
531 --sattr; // Pop attrib
532 *sval += sval[1]; // Compute value
534 if (!(*sattr & (TEXT | DATA | BSS)))
536 else if (sattr[1] & (TEXT | DATA | BSS))
537 return error(seg_error);
542 --sattr; // Pop attrib
543 *sval -= sval[1]; // Compute value
545 attr = (WORD)(*sattr & (TEXT | DATA | BSS));
549 else if (sattr[1] & (TEXT | DATA | BSS))
551 if (!(attr & sattr[1]))
552 return error(seg_error);
554 *sattr &= ~(TEXT | DATA | BSS);
558 // Unary operators only work on ABS items
560 if (*sattr & (TEXT | DATA | BSS))
564 *sattr = ABS | DEFINED; // Expr becomes absolute
567 if (*sattr & (TEXT | DATA | BSS))
571 *sattr = ABS | DEFINED; // Expr becomes absolute
574 if (*sattr & (TEXT | DATA | BSS))
578 *sattr = ABS | DEFINED; // Expr becomes absolute
580 // Comparison operators must have two values that
581 // are in the same segment, but that's the only requirement.
586 if ((*sattr & TDB) != (sattr[1] & TDB))
589 *sattr = ABS | DEFINED;
590 *sval = *sval <= sval[1];
596 if ((*sattr & TDB) != (sattr[1] & TDB))
599 *sattr = ABS | DEFINED;
600 *sval = *sval >= sval[1];
606 if ((*sattr & TDB) != (sattr[1] & TDB))
609 *sattr = ABS | DEFINED;
610 *sval = *sval > sval[1];
616 if ((*sattr & TDB) != (sattr[1] & TDB))
619 *sattr = ABS | DEFINED;
620 *sval = *sval < sval[1];
626 if ((*sattr & TDB) != (sattr[1] & TDB))
629 *sattr = ABS | DEFINED;
630 *sval = *sval != sval[1];
636 if ((*sattr & TDB) != (sattr[1] & TDB))
639 *sattr = ABS | DEFINED;
640 *sval = *sval == sval[1];
642 // All other binary operators must have two ABS items
643 // to work with. They all produce an ABS value.
645 // GH - Removed for v1.0.15 as part of the fix for indexed loads.
646 //if ((*sattr & (TEXT|DATA|BSS)) || (*--sattr & (TEXT|DATA|BSS)))
648 *sattr = ABS | DEFINED; // Expr becomes absolute
654 --sattr; // Pop attrib
659 --sattr; // Pop attrib
662 return error("divide by zero");
668 --sattr; // Pop attrib
671 return error("mod (%) by zero");
677 --sattr; // Pop attrib
682 --sattr; // Pop attrib
687 --sattr; // Pop attrib
692 --sattr; // Pop attrib
697 --sattr; // Pop attrib
701 interror(5); // Bad operator in expression stream
712 // sym_seg added in 1.0.16 to solve a problem with forward symbols in
713 // expressions where absolute values also existed. The absolutes were
714 // overiding the symbol segments and not being included :(
715 //*a_attr = *sattr | sym_seg; // Copy value + attrib
717 *a_attr = *sattr; // Copy value + attrib