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)
335 tk = otk; // Set token pointer to 'exprbuf' (direct.c)
336 // symbolNum = 0; // Set symbol number in symbolPtr[] to 0
338 // Optimize for single constant or single symbol.
340 || (((*tok == CONST || *tok == SYMBOL) || (*tok >= KW_R0 && *tok <= KW_R31))
341 && (tokcl[tok[2]] < UNARY)))
343 if (*tok >= KW_R0 && *tok <= KW_R31)
346 *tk++ = *a_value = (*tok - KW_R0);
347 *a_attr = ABS | DEFINED;
356 else if (*tok == CONST)
359 *tk++ = *a_value = tok[1];
360 *a_attr = ABS | DEFINED;
365 else if (*tok == '*')
370 *tk++ = *a_value = orgaddr;
372 *tk++ = *a_value = pcloc;
374 *a_attr = ABS | DEFINED;
394 sy = lookup(p, LABEL, j);
397 sy = NewSymbol(p, LABEL, j);
399 sy->sattr |= REFERENCED;
401 // Check register bank usage
402 if (sy->sattre & EQUATEDREG)
404 if ((regbank == BANK_0) && (sy->sattre & BANK_1) && !altbankok)
405 warns("equated symbol \'%s\' cannot be used in register bank 0", sy->sname);
407 if ((regbank == BANK_1) && (sy->sattre & BANK_0) && !altbankok)
408 warns("equated symbol \'%s\' cannot be used in register bank 1", sy->sname);
416 symbolPtr[symbolNum] = sy;
420 if (sy->sattr & DEFINED)
421 *a_value = sy->svalue;
425 if (sy->sattre & EQUATEDREG)
428 *a_attr = (WORD)(sy->sattr & ~GLOBAL);
430 if ((sy->sattr & (GLOBAL | DEFINED)) == GLOBAL && a_esym != NULL)
443 return evexpr(otk, a_value, a_attr, a_esym);
448 // Evaluate expression.
449 // If the expression involves only ONE external symbol, the expression is
450 // UNDEFINED, but it's value includes everything but the symbol value, and
451 // `a_esym' is set to the external symbol.
453 int evexpr(TOKEN * tk, VALUE * a_value, WORD * a_attr, SYM ** a_esym)
462 sval = evstk; // (Empty) initial stack
464 esym = NULL; // No external symbol involved
467 while (*tk != ENDEXPR)
472 // sy = (SYM *)*tk++;
473 sy = symbolPtr[*tk++];
474 sy->sattr |= REFERENCED; // Set "referenced" bit
476 if (!(sy->sattr & DEFINED))
478 // Reference to undefined symbol
479 if (!(sy->sattr & GLOBAL))
486 if (esym != NULL) // Check for multiple externals
487 return error(seg_error);
492 if (sy->sattr & DEFINED)
494 *++sval = sy->svalue; // Push symbol's value
498 *++sval = 0; // 0 for undefined symbols
501 *++sattr = (WORD)(sy->sattr & ~GLOBAL); // Push attribs
502 sym_seg = (WORD)(sy->sattr & (TEXT | DATA | BSS));
505 *++sval = *tk++; // Push value
506 *++sattr = ABS | DEFINED; // Push simple attribs
509 *++sval = *tk++; // Push value
510 *++sattr = (WORD)*tk++; // Push attribs
513 // Binary "+" and "-" matrix:
516 // ----------------------------
517 // ABS | ABS | Sect | Other |
518 // Sect | Sect | [1] | Error |
519 // Other | Other | Error | [1] |
520 // ----------------------------
526 --sattr; // Pop attrib
527 *sval += sval[1]; // Compute value
529 if (!(*sattr & (TEXT | DATA | BSS)))
531 else if (sattr[1] & (TEXT | DATA | BSS))
532 return error(seg_error);
537 --sattr; // Pop attrib
538 *sval -= sval[1]; // Compute value
540 attr = (WORD)(*sattr & (TEXT | DATA | BSS));
544 else if (sattr[1] & (TEXT | DATA | BSS))
546 if (!(attr & sattr[1]))
547 return error(seg_error);
549 *sattr &= ~(TEXT | DATA | BSS);
553 // Unary operators only work on ABS items
555 if (*sattr & (TEXT | DATA | BSS))
559 *sattr = ABS | DEFINED; // Expr becomes absolute
562 if (*sattr & (TEXT | DATA | BSS))
566 *sattr = ABS | DEFINED; // Expr becomes absolute
569 if (*sattr & (TEXT | DATA | BSS))
573 *sattr = ABS | DEFINED; // Expr becomes absolute
575 // Comparison operators must have two values that
576 // are in the same segment, but that's the only requirement.
581 if ((*sattr & TDB) != (sattr[1] & TDB))
584 *sattr = ABS | DEFINED;
585 *sval = *sval <= sval[1];
591 if ((*sattr & TDB) != (sattr[1] & TDB))
594 *sattr = ABS | DEFINED;
595 *sval = *sval >= sval[1];
601 if ((*sattr & TDB) != (sattr[1] & TDB))
604 *sattr = ABS | DEFINED;
605 *sval = *sval > sval[1];
611 if ((*sattr & TDB) != (sattr[1] & TDB))
614 *sattr = ABS | DEFINED;
615 *sval = *sval < sval[1];
621 if ((*sattr & TDB) != (sattr[1] & TDB))
624 *sattr = ABS | DEFINED;
625 *sval = *sval != sval[1];
631 if ((*sattr & TDB) != (sattr[1] & TDB))
634 *sattr = ABS | DEFINED;
635 *sval = *sval == sval[1];
637 // All other binary operators must have two ABS items
638 // to work with. They all produce an ABS value.
640 // GH - Removed for v1.0.15 as part of the fix for indexed loads.
641 //if ((*sattr & (TEXT|DATA|BSS)) || (*--sattr & (TEXT|DATA|BSS)))
643 *sattr = ABS | DEFINED; // Expr becomes absolute
649 --sattr; // Pop attrib
654 --sattr; // Pop attrib
657 return error("divide by zero");
663 --sattr; // Pop attrib
666 return error("mod (%) by zero");
672 --sattr; // Pop attrib
677 --sattr; // Pop attrib
682 --sattr; // Pop attrib
687 --sattr; // Pop attrib
692 --sattr; // Pop attrib
696 interror(5); // Bad operator in expression stream
707 // sym_seg added in 1.0.16 to solve a problem with forward symbols in
708 // expressions where absolute values also existed. The absolutes were
709 // overiding the symbol segments and not being included :(
710 //*a_attr = *sattr | sym_seg; // Copy value + attrib
712 *a_attr = *sattr; // Copy value + attrib