]> Shamusworld >> Repos - rmac/blob - expr.c
Small cleanups + version bump for last commit.
[rmac] / expr.c
1 //
2 // RMAC - Reboot's Macro Assembler for all Atari computers
3 // EXPR.C - Expression Analyzer
4 // Copyright (C) 199x Landon Dyer, 2011-2017 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
7 //
8
9 #include "expr.h"
10 #include "direct.h"
11 #include "error.h"
12 #include "listing.h"
13 #include "mach.h"
14 #include "procln.h"
15 #include "riscasm.h"
16 #include "sect.h"
17 #include "symbol.h"
18 #include "token.h"
19
20 #define DEF_KW                                          // Declare keyword values
21 #include "kwtab.h"                                      // Incl generated keyword tables & defs
22
23 // N.B.: The size of tokenClass should be identical to the largest value of
24 //       a token; we're assuming 256 but not 100% sure!
25 static char tokenClass[256];            // Generated table of token classes
26 static uint64_t evstk[EVSTACKSIZE];     // Evaluator value stack
27 static WORD evattr[EVSTACKSIZE];        // Evaluator attribute stack
28
29 // Token-class initialization list
30 char itokcl[] = {
31         0,                                                              // END
32         CONST, FCONST, SYMBOL, 0,               // ID
33         '(', '[', '{', 0,                               // OPAR
34         ')', ']', '}', 0,                               // CPAR
35         CR_DEFINED, CR_REFERENCED,              // SUNARY (special unary)
36         CR_STREQ, CR_MACDEF,
37         CR_DATE, CR_TIME,
38         CR_ABSCOUNT, 0,
39         '!', '~', UNMINUS, 0,                   // UNARY
40         '*', '/', '%', 0,                               // MULT
41         '+', '-', 0,                                    // ADD
42         SHL, SHR, 0,                                    // SHIFT
43         LE, GE, '<', '>', NE, '=', 0,   // REL
44         '&', 0,                                                 // AND
45         '^', 0,                                                 // XOR
46         '|', 0,                                                 // OR
47         1                                                               // (the end)
48 };
49
50 const char missym_error[] = "missing symbol";
51 const char str_error[] = "missing symbol or string";
52
53 // Convert expression to postfix
54 static PTR evalTokenBuffer;             // Deposit tokens here (this is really a
55                                                                 // pointer to exprbuf from direct.c)
56                                                                 // (Can also be from others, like
57                                                                 // riscasm.c)
58 static int symbolNum;                   // Pointer to the entry in symbolPtr[]
59
60
61 //
62 // Obtain a string value
63 //
64 static uint32_t str_value(char * p)
65 {
66         uint32_t v;
67
68         for(v=0; *p; p++)
69                 v = (v << 8) | (*p & 0xFF);
70
71         return v;
72 }
73
74
75 //
76 // Initialize expression analyzer
77 //
78 void InitExpression(void)
79 {
80         // Initialize token-class table (all set to END)
81         for(int i=0; i<256; i++)
82                 tokenClass[i] = END;
83
84         int i = 0;
85
86         for(char * p=itokcl; *p!=1; p++)
87         {
88                 if (*p == 0)
89                         i++;
90                 else
91                         tokenClass[(int)(*p)] = (char)i;
92         }
93
94         symbolNum = 0;
95 }
96
97
98 //
99 // Binary operators (all the same precedence)
100 //
101 int expr0(void)
102 {
103         if (expr1() != OK)
104                 return ERROR;
105
106         while (tokenClass[*tok] >= MULT)
107         {
108                 TOKEN t = *tok++;
109
110                 if (expr1() != OK)
111                         return ERROR;
112
113                 *evalTokenBuffer.u32++ = t;
114         }
115
116         return OK;
117 }
118
119
120 //
121 // Unary operators (detect unary '-')
122 // ggn: If expression starts with a plus then also eat it up. For some reason
123 //      the parser gets confused when this happens and emits a "bad
124 //      expression".
125 //
126 int expr1(void)
127 {
128         TOKEN t;
129         SYM * sy;
130         char * p, * p2;
131         WORD w;
132         int j;
133
134         int class = tokenClass[*tok];
135
136         if (*tok == '-' || *tok == '+' || class == UNARY)
137         {
138                 t = *tok++;
139
140                 if (expr2() != OK)
141                         return ERROR;
142
143                 if (t == '-')
144                         t = UNMINUS;
145
146                 // With leading + we don't have to deposit anything to the buffer
147                 // because there's no unary '+' nor we have to do anything about it
148                 if (t != '+')
149                         *evalTokenBuffer.u32++ = t;
150         }
151         else if (class == SUNARY)
152         {
153                 switch (*tok++)
154                 {
155                 case CR_ABSCOUNT:
156                         *evalTokenBuffer.u32++ = CONST;
157                         *evalTokenBuffer.u64++ = (uint64_t)sect[ABS].sloc;
158                         break;
159                 case CR_TIME:
160                         *evalTokenBuffer.u32++ = CONST;
161                         *evalTokenBuffer.u64++ = dos_time();
162                         break;
163                 case CR_DATE:
164                         *evalTokenBuffer.u32++ = CONST;
165                         *evalTokenBuffer.u64++ = dos_date();
166                         break;
167                 case CR_MACDEF: // ^^macdef <macro-name>
168                         if (*tok++ != SYMBOL)
169                                 return error(missym_error);
170
171                         p = string[*tok++];
172                         w = (lookup(p, MACRO, 0) == NULL ? 0 : 1);
173                         *evalTokenBuffer.u32++ = CONST;
174                         *evalTokenBuffer.u64++ = (uint64_t)w;
175                         break;
176                 case CR_DEFINED:
177                         w = DEFINED;
178                         goto getsym;
179                 case CR_REFERENCED:
180                         w = REFERENCED;
181 getsym:
182                         if (*tok++ != SYMBOL)
183                                 return error(missym_error);
184
185                         p = string[*tok++];
186                         j = (*p == '.' ? curenv : 0);
187                         w = ((sy = lookup(p, LABEL, j)) != NULL && (sy->sattr & w) ? 1 : 0);
188                         *evalTokenBuffer.u32++ = CONST;
189                         *evalTokenBuffer.u64++ = (uint64_t)w;
190                         break;
191                 case CR_STREQ:
192                         if (*tok != SYMBOL && *tok != STRING)
193                                 return error(str_error);
194
195                         p = string[tok[1]];
196                         tok +=2;
197
198                         if (*tok++ != ',')
199                                 return error(comma_error);
200
201                         if (*tok != SYMBOL && *tok != STRING)
202                                 return error(str_error);
203
204                         p2 = string[tok[1]];
205                         tok += 2;
206
207                         w = (WORD)(!strcmp(p, p2));
208                         *evalTokenBuffer.u32++ = CONST;
209                         *evalTokenBuffer.u64++ = (uint64_t)w;
210                         break;
211                 }
212         }
213         else
214                 return expr2();
215
216         return OK;
217 }
218
219
220 //
221 // Terminals (CONSTs) and parenthesis grouping
222 //
223 int expr2(void)
224 {
225         char * p;
226         SYM * sy;
227         int j;
228         PTR ptk;
229
230         switch (*tok++)
231         {
232         case CONST:
233                 ptk.u32 = tok;
234                 *evalTokenBuffer.u32++ = CONST;
235                 *evalTokenBuffer.u64++ = *ptk.u64++;
236                 tok = ptk.u32;
237                 break;
238         case FCONST:
239                 ptk.u32 = tok;
240                 *evalTokenBuffer.u32++ = CONST;
241                 *evalTokenBuffer.u64++ = *ptk.u64++;
242                 tok = ptk.u32;
243                 break;
244         case SYMBOL:
245                 p = string[*tok++];
246                 j = (*p == '.' ? curenv : 0);
247                 sy = lookup(p, LABEL, j);
248
249                 if (sy == NULL)
250                         sy = NewSymbol(p, LABEL, j);
251
252                 // Check register bank usage
253                 if (sy->sattre & EQUATEDREG)
254                 {
255                         if ((regbank == BANK_0) && (sy->sattre & BANK_1) && !altbankok)
256                                 warn("equated symbol \'%s\' cannot be used in register bank 0", sy->sname);
257
258                         if ((regbank == BANK_1) && (sy->sattre & BANK_0) && !altbankok)
259                                 warn("equated symbol \'%s\' cannot be used in register bank 1", sy->sname);
260                 }
261
262                 *evalTokenBuffer.u32++ = SYMBOL;
263                 *evalTokenBuffer.u32++ = symbolNum;
264                 symbolPtr[symbolNum] = sy;
265                 symbolNum++;
266                 break;
267         case STRING:
268                 *evalTokenBuffer.u32++ = CONST;
269                 *evalTokenBuffer.u64++ = str_value(string[*tok++]);
270                 break;
271         case '(':
272                 if (expr0() != OK)
273                         return ERROR;
274
275                 if (*tok++ != ')')
276                         return error("missing closing parenthesis ')'");
277
278                 break;
279         case '[':
280                 if (expr0() != OK)
281                         return ERROR;
282
283                 if (*tok++ != ']')
284                         return error("missing closing bracket ']'");
285
286                 break;
287         case '{':
288                 if (expr0() != OK)      // Eat up first parameter (register or immediate)
289                         return ERROR;
290
291                 if (*tok++ != ':')      // Demand a ':' there
292                         return error("missing colon ':'");
293
294                 if (expr0() != OK)      // Eat up second parameter (register or immediate)
295                         return ERROR;
296
297                 if (*tok++ != '}')
298                         return error("missing closing brace '}'");
299
300                 break;
301         case '$':
302                 *evalTokenBuffer.u32++ = ACONST;                        // Attributed const
303                 *evalTokenBuffer.u32++ = sloc;                          // Current location
304                 *evalTokenBuffer.u32++ = cursect | DEFINED;     // Store attribs
305                 break;
306         case '*':
307                 *evalTokenBuffer.u32++ = ACONST;                        // Attributed const
308
309                 // pcloc == location at start of line
310                 *evalTokenBuffer.u32++ = (orgactive ? orgaddr : pcloc);
311                 // '*' takes attributes of current section, not ABS!
312                 *evalTokenBuffer.u32++ = cursect | DEFINED;
313                 break;
314         default:
315                 return error("bad expression");
316         }
317
318         return OK;
319 }
320
321
322 //
323 // Recursive-descent expression analyzer (with some simple speed hacks)
324 //
325 int expr(TOKEN * otk, uint64_t * a_value, WORD * a_attr, SYM ** a_esym)
326 {
327         // Passed in values (once derefenced, that is) can all be zero. They are
328         // there so that the expression analyzer can fill them in as needed. The
329         // expression analyzer gets its input from the global token pointer "tok",
330         // and not from anything passed in by the user.
331         SYM * symbol;
332         char * p;
333         int j;
334         PTR ptk;
335
336         evalTokenBuffer.u32 = otk;      // Set token pointer to 'exprbuf' (direct.c)
337                                                         // Also set in various other places too (riscasm.c,
338                                                         // e.g.)
339
340 //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]]);
341         // Optimize for single constant or single symbol.
342         // Shamus: Subtle bug here. EOL token is 101; if you have a constant token
343         //         followed by the value 101, it will trigger a bad evaluation here.
344         //         This is probably a really bad assumption to be making here...!
345         //         (assuming tok[1] == EOL is a single token that is)
346         //         Seems that even other tokens (SUNARY type) can fuck this up too.
347 #if 0
348 //      if ((tok[1] == EOL)
349         if ((tok[1] == EOL && ((tok[0] != CONST || tok[0] != FCONST) && tokenClass[tok[0]] != SUNARY))
350 //              || (((*tok == CONST || *tok == FCONST || *tok == SYMBOL) || (*tok >= KW_R0 && *tok <= KW_R31))
351 //              && (tokenClass[tok[2]] < UNARY)))
352                 || (((tok[0] == SYMBOL) || (tok[0] >= KW_R0 && tok[0] <= KW_R31))
353                         && (tokenClass[tok[2]] < UNARY))
354                 || ((tok[0] == CONST || tok[0] == FCONST) && (tokenClass[tok[3]] < UNARY))
355                 )
356 #else
357 // 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:
358         if ((tok[1] == EOL
359                         && (tok[0] != CONST && tokenClass[tok[0]] != SUNARY))
360                 || (((tok[0] == SYMBOL)
361                                 || (tok[0] >= KW_R0 && tok[0] <= KW_R31))
362                         && (tokenClass[tok[2]] < UNARY))
363                 || ((tok[0] == CONST) && (tokenClass[tok[3]] < UNARY))
364                 )
365 // 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
366 #endif
367         {
368                 if (*tok >= KW_R0 && *tok <= KW_R31)
369                 {
370                         *evalTokenBuffer.u32++ = CONST;
371                         *evalTokenBuffer.u64++ = *a_value = (*tok - KW_R0);
372                         *a_attr = ABS | DEFINED;
373
374                         if (a_esym != NULL)
375                                 *a_esym = NULL;
376
377                         tok++;
378                 }
379                 else if (*tok == CONST)
380                 {
381                         ptk.u32 = tok;
382                         *evalTokenBuffer.u32++ = *ptk.u32++;
383                         *evalTokenBuffer.u64++ = *a_value = *ptk.u64++;
384                         *a_attr = ABS | DEFINED;
385                         tok = ptk.u32;
386
387                         if (a_esym != NULL)
388                                 *a_esym = NULL;
389
390 //printf("Quick eval in expr(): CONST = %i, tokenClass[tok[2]] = %i\n", *a_value, tokenClass[*tok]);
391                 }
392 // Not sure that removing float constant here is going to break anything and/or
393 // make things significantly slower, but having this here seems to cause the
394 // complexity of the check to get to this part of the parse to go through the
395 // roof, and dammit, I just don't feel like fighting that fight ATM. :-P
396 #if 0
397                 else if (*tok == FCONST)
398                 {
399                         *evalTokenBuffer.u32++ = *tok++;
400                         *evalTokenBuffer.u64++ = *a_value = *tok.u64++;
401                         *a_attr = ABS | DEFINED | FLOAT;
402
403                         if (a_esym != NULL)
404                                 *a_esym = NULL;
405
406 //printf("Quick eval in expr(): CONST = %i, tokenClass[tok[2]] = %i\n", *a_value, tokenClass[*tok]);
407                 }
408 #endif
409                 else if (*tok == '*')
410                 {
411                         *evalTokenBuffer.u32++ = CONST;
412
413                         if (orgactive)
414                                 *evalTokenBuffer.u64++ = *a_value = orgaddr;
415                         else
416                                 *evalTokenBuffer.u64++ = *a_value = pcloc;
417
418                         // '*' takes attributes of current section, not ABS!
419                         *a_attr = cursect | DEFINED;
420
421                         if (a_esym != NULL)
422                                 *a_esym = NULL;
423
424                         tok++;
425                 }
426                 else if (*tok == STRING || *tok == SYMBOL)
427                 {
428                         p = string[tok[1]];
429                         j = (*p == '.' ? curenv : 0);
430                         symbol = lookup(p, LABEL, j);
431 #if 0
432 printf("eval: Looking up symbol (%s) [=%08X]\n", p, symbol);
433 if (symbol)
434         printf("      attr=%04X, attre=%08X, val=%i, name=%s\n", symbol->sattr, symbol->sattre, symbol->svalue, symbol->sname);
435 #endif
436
437                         if (symbol == NULL)
438                                 symbol = NewSymbol(p, LABEL, j);
439
440                         symbol->sattr |= REFERENCED;
441
442                         // Check for undefined register equates, but only if it's not part
443                         // of a #<SYMBOL> construct, as it could be that the label that's
444                         // been undefined may later be used as an address label--which
445                         // means it will be fixed up later, and thus, not an error.
446                         if ((symbol->sattre & UNDEF_EQUR) && !riscImmTokenSeen)
447                         {
448                                 error("undefined register equate '%s'", symbol->sname);
449 //if we return right away, it returns some spurious errors...
450 //                              return ERROR;
451                         }
452
453                         // Check register bank usage
454                         if (symbol->sattre & EQUATEDREG)
455                         {
456                                 if ((regbank == BANK_0) && (symbol->sattre & BANK_1) && !altbankok)
457                                         warn("equated symbol '%s' cannot be used in register bank 0", symbol->sname);
458
459                                 if ((regbank == BANK_1) && (symbol->sattre & BANK_0) && !altbankok)
460                                         warn("equated symbol '%s' cannot be used in register bank 1", symbol->sname);
461                         }
462
463                         *evalTokenBuffer.u32++ = SYMBOL;
464 #if 0
465                         *evalTokenBuffer++ = (TOKEN)symbol;
466 #else
467 /*
468 While this approach works, it's wasteful. It would be better to use something
469 that's already available, like the symbol "order defined" table (which needs to
470 be converted from a linked list into an array).
471 */
472                         *evalTokenBuffer.u32++ = symbolNum;
473                         symbolPtr[symbolNum] = symbol;
474                         symbolNum++;
475 #endif
476
477                         if (symbol->sattr & DEFINED)
478                                 *a_value = symbol->svalue;
479                         else
480                                 *a_value = 0;
481
482 /*
483 All that extra crap that was put into the svalue when doing the equr stuff is
484 thrown away right here. What the hell is it for?
485 */
486                         if (symbol->sattre & EQUATEDREG)
487                                 *a_value &= 0x1F;
488
489                         *a_attr = (WORD)(symbol->sattr & ~GLOBAL);
490
491                         if ((symbol->sattr & (GLOBAL | DEFINED)) == GLOBAL
492                                 && a_esym != NULL)
493                                 *a_esym = symbol;
494
495                         tok += 2;
496                 }
497                 else
498                 {
499                         // Unknown type here... Alert the user!,
500                         error("undefined RISC register in expression");
501                         // Prevent spurious error reporting...
502                         tok++;
503                         return ERROR;
504                 }
505
506                 *evalTokenBuffer.u32++ = ENDEXPR;
507                 return OK;
508         }
509
510         if (expr0() != OK)
511                 return ERROR;
512
513         *evalTokenBuffer.u32++ = ENDEXPR;
514         return evexpr(otk, a_value, a_attr, a_esym);
515 }
516
517
518 //
519 // Evaluate expression.
520 // If the expression involves only ONE external symbol, the expression is
521 // UNDEFINED, but it's value includes everything but the symbol value, and
522 // 'a_esym' is set to the external symbol.
523 //
524 int evexpr(TOKEN * _tk, uint64_t * a_value, WORD * a_attr, SYM ** a_esym)
525 {
526         WORD attr, attr2;
527         SYM * sy;
528         uint64_t * sval = evstk;                                // (Empty) initial stack
529         WORD * sattr = evattr;
530         SYM * esym = NULL;                                              // No external symbol involved
531         WORD sym_seg = 0;
532         PTR tk;
533         tk.u32 = _tk;
534
535         while (*tk.u32 != ENDEXPR)
536         {
537                 switch ((int)*tk.u32++)
538                 {
539                 case SYMBOL:
540 //printf("evexpr(): SYMBOL\n");
541                         sy = symbolPtr[*tk.u32++];
542                         sy->sattr |= REFERENCED;                // Set "referenced" bit
543
544                         if (!(sy->sattr & DEFINED))
545                         {
546                                 // Reference to undefined symbol
547                                 if (!(sy->sattr & GLOBAL))
548                                 {
549                                         *a_attr = 0;
550                                         *a_value = 0;
551                                         return OK;
552                                 }
553
554                                 if (esym != NULL)                       // Check for multiple externals
555                                         return error(seg_error);
556
557                                 esym = sy;
558                         }
559
560                         if (sy->sattr & DEFINED)
561                         {
562                                 *++sval = sy->svalue;           // Push symbol's value
563                         }
564                         else
565                         {
566                                 *++sval = 0;                            // 0 for undefined symbols
567                         }
568
569                         *++sattr = (WORD)(sy->sattr & ~GLOBAL); // Push attribs
570                         sym_seg = (WORD)(sy->sattr & TDB);
571                         break;
572                 case CONST:
573                         *++sval = *tk.u64++;
574 //printf("evexpr(): CONST = %lX\n", *sval);
575                         *++sattr = ABS | DEFINED;               // Push simple attribs
576                         break;
577                 case FCONST:
578 //printf("evexpr(): FCONST = %i\n", *tk.u32);
579                         *((double *)sval) = *((double *)tk.u32);
580                         tk.u32 += 2;
581                         *++sattr = ABS | DEFINED | FLOAT; // Push simple attribs
582                         break;
583                 case ACONST:
584 //printf("evexpr(): ACONST = %i\n", *tk.u32);
585                         *++sval = *tk.u32++;                            // Push value
586                         *++sattr = (WORD)*tk.u32++;                     // Push attribs
587                         break;
588
589                         // Binary "+" and "-" matrix:
590                         //
591                         //                ABS    Sect     Other
592                         //     ----------------------------
593                         //   ABS     |  ABS   |  Sect  |  Other |
594                         //   Sect    |  Sect  |  [1]   |  Error |
595                         //   Other   |  Other |  Error |  [1]   |
596                         //      ----------------------------
597                         //
598                         //   [1] + : Error
599                         //       - : ABS
600                 case '+':
601 //printf("evexpr(): +\n");
602                         --sval;                                                 // Pop value
603                         --sattr;                                                // Pop attrib
604 //printf("--> N+N: %i + %i = ", *sval, sval[1]);
605                         // Extract float attributes from both terms and pack them
606                         // into a single value
607                         attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
608                         attr2 = sattr[0] | sattr[1] & FLOAT; // Returns FLOAT if either of the two numbers are FLOAT
609
610                         if (attr == (FLOAT | (FLOAT >> 1)))
611                         {
612                                 // Float + Float
613                                 double * dst = (double *)sval;
614                                 double * src = (double *)(sval + 1);
615                                 *dst += *src;
616                         }
617                         else if (attr == FLOAT)
618                         {
619                                 // Float + Int
620                                 double * dst = (double *)sval;
621                                 uint64_t * src = (uint64_t *)(sval + 1);
622                                 *dst += *src;
623                         }
624                         else if (attr == FLOAT >> 1)
625                         {
626                                 // Int + Float
627                                 uint64_t * dst = (uint64_t *)sval;
628                                 double * src = (double *)(sval + 1);
629                                 *(double *)dst = *src + *dst;
630                         }
631                         else
632                         {
633                                 *sval += sval[1];                               // Compute value
634                         }
635 //printf("%i\n", *sval);
636
637                         if (!(*sattr & TDB))
638                                 *sattr = sattr[1] | attr2;
639                         else if (sattr[1] & TDB)
640                                 return error(seg_error);
641
642                         break;
643                 case '-':
644 //printf("evexpr(): -\n");
645                         --sval;                                                 // Pop value
646                         --sattr;                                                // Pop attrib
647 //printf("--> N-N: %i - %i = ", *sval, sval[1]);
648                         // Extract float attributes from both terms and pack them
649                         // into a single value
650                         attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
651                         attr2 = sattr[0] | sattr[1] & FLOAT; // Returns FLOAT if either of the two numbers are FLOAT
652
653                         if (attr == (FLOAT | (FLOAT >> 1)))
654                         {
655                                 // Float - Float
656                                 double * dst = (double *)sval;
657                                 double * src = (double *)(sval + 1);
658                                 *dst -= *src;
659                         }
660                         else if (attr == FLOAT)
661                         {
662                                 // Float - Int
663                                 double * dst = (double *)sval;
664                                 uint64_t * src = (uint64_t *)(sval + 1);
665                                 *dst -= *src;
666                         }
667                         else if (attr == FLOAT >> 1)
668                         {
669                                 // Int - Float
670                                 uint64_t * dst = (uint64_t *)sval;
671                                 double * src = (double *)(sval + 1);
672                                 *(double *)dst = *dst - *src;
673                         }
674                         else
675                         {
676                                 *sval -= sval[1];                               // Compute value
677                         }
678
679 //printf("%i\n", *sval);
680
681                         attr = (WORD)(*sattr & TDB);
682 #if 0
683 printf("EVEXPR (-): sym1 = %X, sym2 = %X\n", attr, sattr[1]);
684 #endif
685                         *sattr |= attr2;                // Inherit FLOAT attribute
686                         // If symbol1 is ABS, take attributes from symbol2
687                         if (!attr)
688                                 *sattr = sattr[1];
689                         // Otherwise, they're both TDB and so attributes cancel out
690                         else if (sattr[1] & TDB)
691                                 *sattr &= ~TDB;
692
693                         break;
694                 // Unary operators only work on ABS items
695                 case UNMINUS:
696 //printf("evexpr(): UNMINUS\n");
697                         if (*sattr & TDB)
698                                 return error(seg_error);
699
700                         if (*sattr & FLOAT)
701                         {
702                                 double *dst = (double *)sval;
703                                 *dst = -*dst;
704                                 *sattr = ABS | DEFINED | FLOAT; // Expr becomes absolute
705                         }
706                         else
707                         {
708                                 *sval = -(int)*sval;
709                                 *sattr = ABS | DEFINED;                 // Expr becomes absolute
710                         }
711                         break;
712                 case '!':
713 //printf("evexpr(): !\n");
714                         if (*sattr & TDB)
715                                 return error(seg_error);
716
717                         if (*sattr & FLOAT)
718                                 return error("floating point numbers not allowed with operator '!'.");
719
720                         *sval = !*sval;
721                         *sattr = ABS | DEFINED;                 // Expr becomes absolute
722                         break;
723                 case '~':
724 //printf("evexpr(): ~\n");
725                         if (*sattr & TDB)
726                                 return error(seg_error);
727
728                         if (*sattr & FLOAT)
729                                 return error("floating point numbers not allowed with operator '~'.");
730
731                         *sval = ~*sval;
732                         *sattr = ABS | DEFINED;                 // Expr becomes absolute
733                         break;
734                 // Comparison operators must have two values that
735                 // are in the same segment, but that's the only requirement.
736                 case LE:
737 //printf("evexpr(): LE\n");
738                         sattr--;
739                         sval--;
740
741                         if ((*sattr & TDB) != (sattr[1] & TDB))
742                                 return error(seg_error);
743
744                         // Extract float attributes from both terms and pack them
745                         // into a single value
746                         attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
747
748                         if (attr == (FLOAT | (FLOAT >> 1)))
749                         {
750                                 // Float <= Float
751                                 double * dst = (double *)sval;
752                                 double * src = (double *)(sval + 1);
753                                 *sval = *dst <= *src;
754                         }
755                         else if (attr == FLOAT)
756                         {
757                                 // Float <= Int
758                                 double * dst = (double *)sval;
759                                 uint64_t * src = (uint64_t *)(sval + 1);
760                                 *sval = *dst <= *src;
761                         }
762                         else if (attr == FLOAT >> 1)
763                         {
764                                 // Int <= Float
765                                 uint64_t * dst = (uint64_t *)sval;
766                                 double * src = (double *)(sval + 1);
767                                 *sval = *dst <= *src;
768                         }
769                         else
770                         {
771                                 *sval = *sval <= sval[1];
772                         }
773
774                         *sattr = ABS | DEFINED;
775                         break;
776                 case GE:
777 //printf("evexpr(): GE\n");
778                         sattr--;
779                         sval--;
780
781                         if ((*sattr & TDB) != (sattr[1] & TDB))
782                                 return error(seg_error);
783
784                         // Extract float attributes from both terms and pack them
785                         // into a single value
786                         attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
787
788                         if (attr == (FLOAT | (FLOAT >> 1)))
789                         {
790                                 // Float >= Float
791                                 double * dst = (double *)sval;
792                                 double * src = (double *)(sval + 1);
793                                 *sval = *dst >= *src;
794                         }
795                         else if (attr == FLOAT)
796                         {
797                                 // Float >= Int
798                                 double * dst = (double *)sval;
799                                 uint64_t * src = (uint64_t *)(sval + 1);
800                                 *sval = *dst >= *src;
801                         }
802                         else if (attr == FLOAT >> 1)
803                         {
804                                 // Int >= Float
805                                 uint64_t * dst = (uint64_t *)sval;
806                                 double * src = (double *)(sval + 1);
807                                 *sval = *dst >= *src;
808                         }
809                         else if (attr == 0)
810                         {
811                                 *sval = *sval >= sval[1];
812                         }
813                         else
814                                 *sattr = ABS | DEFINED;
815
816                         break;
817                 case '>':
818 //printf("evexpr(): >\n");
819                         sattr--;
820                         sval--;
821
822                         if ((*sattr & TDB) != (sattr[1] & TDB))
823                                 return error(seg_error);
824
825                         // Extract float attributes from both terms and pack them
826                         // into a single value
827                         attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
828
829                         if (attr == (FLOAT | (FLOAT >> 1)))
830                         {
831                                 // Float > Float
832                                 double * dst = (double *)sval;
833                                 double * src = (double *)(sval + 1);
834                                 *sval = *dst > *src;
835                         }
836                         else if (attr == FLOAT)
837                         {
838                                 // Float > Int
839                                 double * dst = (double *)sval;
840                                 uint64_t * src = (uint64_t *)(sval + 1);
841                                 *sval = *dst > *src;
842                         }
843                         else if (attr == FLOAT >> 1)
844                         {
845                                 // Int > Float
846                                 uint64_t * dst = (uint64_t *)sval;
847                                 double * src = (double *)(sval + 1);
848                                 *sval = *dst > *src;
849                         }
850                         else
851                         {
852                                 *sval = *sval > sval[1];
853                         }
854
855                         *sattr = ABS | DEFINED;
856
857                         break;
858                 case '<':
859 //printf("evexpr(): <\n");
860                         sattr--;
861                         sval--;
862
863                         if ((*sattr & TDB) != (sattr[1] & TDB))
864                                 return error(seg_error);
865
866                         // Extract float attributes from both terms and pack them
867                         // into a single value
868                         attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
869
870                         if (attr == (FLOAT | (FLOAT >> 1)))
871                         {
872                                 // Float < Float
873                                 double * dst = (double *)sval;
874                                 double * src = (double *)(sval + 1);
875                                 *sval = *dst < *src;
876                         }
877                         else if (attr == FLOAT)
878                         {
879                                 // Float < Int
880                                 double * dst = (double *)sval;
881                                 uint64_t * src = (uint64_t *)(sval + 1);
882                                 *sval = *dst < *src;
883                         }
884                         else if (attr == FLOAT >> 1)
885                         {
886                                 // Int < Float
887                                 uint64_t * dst = (uint64_t *)sval;
888                                 double * src = (double *)(sval + 1);
889                                 *sval = *dst < *src;
890                         }
891                         else
892                         {
893                                 *sval = *sval < sval[1];
894                         }
895
896                         *sattr = ABS | DEFINED;
897
898                         break;
899                 case NE:
900 //printf("evexpr(): NE\n");
901                         sattr--;
902                         sval--;
903
904                         if ((*sattr & TDB) != (sattr[1] & TDB))
905                                 return error(seg_error);
906
907                         // Extract float attributes from both terms and pack them
908                         // into a single value
909                         attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
910
911                         if (attr == (FLOAT | (FLOAT >> 1)))
912                         {
913                                 // Float <> Float
914                                 return error("comparison for equality with float types not allowed.");
915                         }
916                         else if (attr == FLOAT)
917                         {
918                                 // Float <> Int
919                                 return error("comparison for equality with float types not allowed.");
920                         }
921                         else if (attr == FLOAT >> 1)
922                         {
923                                 // Int != Float
924                                 return error("comparison for equality with float types not allowed.");
925                         }
926                         else
927                         {
928                                 *sval = *sval != sval[1];
929                         }
930
931                         *sattr = ABS | DEFINED;
932
933                         break;
934                 case '=':
935 //printf("evexpr(): =\n");
936                         sattr--;
937                         sval--;
938
939                         if ((*sattr & TDB) != (sattr[1] & TDB))
940                                 return error(seg_error);
941
942                         // Extract float attributes from both terms and pack them
943                         // into a single value
944                         attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
945
946                         if (attr == (FLOAT | (FLOAT >> 1)))
947                         {
948                                 // Float = Float
949                                 double * dst = (double *)sval;
950                                 double * src = (double *)(sval + 1);
951                                 *sval = *src == *dst;
952                         }
953                         else if (attr == FLOAT)
954                         {
955                                 // Float = Int
956                                 return error("equality with float ");
957                         }
958                         else if (attr == FLOAT >> 1)
959                         {
960                                 // Int == Float
961                                 uint64_t * dst = (uint64_t *)sval;
962                                 double * src = (double *)(sval + 1);
963                                 *sval = *src == *dst;
964                         }
965                         else
966                         {
967                                 *sval = *sval == sval[1];
968                         }
969
970                         *sattr = ABS | DEFINED;
971
972                         break;
973                 // All other binary operators must have two ABS items to work with.
974                 // They all produce an ABS value.
975                 default:
976 //printf("evexpr(): default\n");
977                         // GH - Removed for v1.0.15 as part of the fix for indexed loads.
978                         //if ((*sattr & (TEXT|DATA|BSS)) || (*--sattr & (TEXT|DATA|BSS)))
979                         //error(seg_error);
980
981                         switch ((int)tk.u32[-1])
982                         {
983                         case '*':
984                                 sval--;
985                                 sattr--;                                        // Pop attrib
986 //printf("--> NxN: %i x %i = ", *sval, sval[1]);
987                                 // Extract float attributes from both terms and pack them
988                                 // into a single value
989                                 attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
990                                 attr2 = sattr[0] | sattr[1] & FLOAT; // Returns FLOAT if either of the two numbers are FLOAT
991
992                                 if (attr == (FLOAT | (FLOAT >> 1)))
993                                 {
994                                         // Float * Float
995                                         double * dst = (double *)sval;
996                                         double * src = (double *)(sval + 1);
997                                         *dst *= *src;
998                                 }
999                                 else if (attr == FLOAT)
1000                                 {
1001                                         // Float * Int
1002                                         double * dst = (double *)sval;
1003                                         uint64_t * src = (uint64_t *)(sval + 1);
1004                                         *dst *= *src;
1005                                 }
1006                                 else if (attr == FLOAT >> 1)
1007                                 {
1008                                         // Int * Float
1009                                         uint64_t * dst = (uint64_t *)sval;
1010                                         double * src = (double *)(sval + 1);
1011                                         *(double *)dst = *src * *dst;
1012                                 }
1013                                 else
1014                                 {
1015                                         *sval *= sval[1];
1016                                 }
1017 //printf("%i\n", *sval);
1018
1019                                 *sattr = ABS | DEFINED;                 // Expr becomes absolute
1020                                 *sattr |= attr2;
1021
1022                                 break;
1023                         case '/':
1024                                 sval--;
1025                                 sattr--;                                        // Pop attrib
1026
1027
1028 //printf("--> N/N: %i / %i = ", sval[0], sval[1]);
1029                                 // Extract float attributes from both terms and pack them
1030                                 // into a single value
1031                                 attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
1032                                 attr2 = sattr[0] | sattr[1] & FLOAT; // Returns FLOAT if either of the two numbers are FLOAT
1033
1034                                 if (attr == (FLOAT | (FLOAT >> 1)))
1035                                 {
1036                                         // Float / Float
1037                                         double * dst = (double *)sval;
1038                                         double * src = (double *)(sval + 1);
1039
1040                                         if (*src == 0)
1041                                                 return error("divide by zero");
1042
1043                                         *dst = *dst / *src;
1044                                 }
1045                                 else if (attr == FLOAT)
1046                                 {
1047                                         // Float / Int
1048                                         double * dst = (double *)sval;
1049                                         uint64_t * src = (uint64_t *)(sval + 1);
1050
1051                                         if (*src == 0)
1052                                                 return error("divide by zero");
1053
1054                                         *dst = *dst / *src;
1055                                 }
1056                                 else if (attr == FLOAT >> 1)
1057                                 {
1058                                         // Int / Float
1059                                         uint64_t * dst=(uint64_t *)sval;
1060                                         double * src=(double *)(sval + 1);
1061
1062                                         if (*src == 0)
1063                                                 return error("divide by zero");
1064
1065                                         *(double *)dst = *dst / *src;
1066                                 }
1067                                 else
1068                                 {
1069                                         if (sval[1] == 0)
1070                                                 return error("divide by zero");
1071 //printf("--> N/N: %i / %i = ", sval[0], sval[1]);
1072
1073                                         // Compiler is picky here: Without casting these, it
1074                                         // discards the sign if dividing a negative # by a
1075                                         // positive one, creating a bad result. :-/
1076                                         // Definitely a side effect of using uint32_ts intead of
1077                                         // ints.
1078                                         *sval = (int32_t)sval[0] / (int32_t)sval[1];
1079                                 }
1080
1081                                 *sattr = ABS | DEFINED;                 // Expr becomes absolute
1082                                 *sattr |= attr2;
1083
1084 //printf("%i\n", *sval);
1085                                 break;
1086                         case '%':
1087                                 sval--;
1088                                 sattr--;                                        // Pop attrib
1089
1090                                 if ((*sattr | sattr[1]) & FLOAT)
1091                                         return error("floating point numbers not allowed with operator '%'.");
1092
1093                                 if (sval[1] == 0)
1094                                         return error("mod (%) by zero");
1095
1096                                 *sattr = ABS | DEFINED;                 // Expr becomes absolute
1097                                 *sval %= sval[1];
1098                                 break;
1099                         case SHL:
1100                                 sval--;
1101                                 sattr--;                                        // Pop attrib
1102
1103                                 if ((*sattr | sattr[1]) & FLOAT)
1104                                         return error("floating point numbers not allowed with operator '<<'.");
1105
1106                                 *sattr = ABS | DEFINED;                 // Expr becomes absolute
1107                                 *sval <<= sval[1];
1108                                 break;
1109                         case SHR:
1110                                 sval--;
1111                                 sattr--;                                        // Pop attrib
1112
1113                                 if ((*sattr | sattr[1]) & FLOAT)
1114                                         return error("floating point numbers not allowed with operator '>>'.");
1115
1116                                 *sattr = ABS | DEFINED;                 // Expr becomes absolute
1117                                 *sval >>= sval[1];
1118                                 break;
1119                         case '&':
1120                                 sval--;
1121                                 sattr--;                                        // Pop attrib
1122
1123                                 if ((*sattr | sattr[1]) & FLOAT)
1124                                         return error("floating point numbers not allowed with operator '&'.");
1125
1126                                 *sattr = ABS | DEFINED;                 // Expr becomes absolute
1127                                 *sval &= sval[1];
1128                                 break;
1129                         case '^':
1130                                 sval--;
1131                                 sattr--;                                        // Pop attrib
1132
1133                                 if ((*sattr | sattr[1]) & FLOAT)
1134                                         return error("floating point numbers not allowed with operator '^'.");
1135
1136                                 *sattr = ABS | DEFINED;                 // Expr becomes absolute
1137                                 *sval ^= sval[1];
1138                                 break;
1139                         case '|':
1140                                 sval--;
1141                                 sattr--;                                        // Pop attrib
1142
1143                                 if ((*sattr | sattr[1]) & FLOAT)
1144                                         return error("floating point numbers not allowed with operator '|'.");
1145
1146                                 *sattr = ABS | DEFINED;                 // Expr becomes absolute
1147                                 *sval |= sval[1];
1148                                 break;
1149                         default:
1150                                 interror(5);                            // Bad operator in expression stream
1151                         }
1152                 }
1153         }
1154
1155         if (esym != NULL)
1156                 *sattr &= ~DEFINED;
1157
1158         if (a_esym != NULL)
1159                 *a_esym = esym;
1160
1161         // sym_seg added in 1.0.16 to solve a problem with forward symbols in
1162         // expressions where absolute values also existed. The absolutes were
1163         // overiding the symbol segments and not being included :(
1164         //*a_attr = *sattr | sym_seg;           // Copy value + attrib
1165
1166         *a_attr = *sattr;                                               // Copy value + attrib
1167         *a_value = *sval;
1168
1169         return OK;
1170 }
1171