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
20 #define DEF_KW // Declare keyword values
21 #include "kwtab.h" // Incl generated keyword tables & defs
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
29 // Token-class initialization list
32 CONST, FCONST, SYMBOL, 0, // ID
33 '(', '[', '{', 0, // OPAR
34 ')', ']', '}', 0, // CPAR
35 CR_DEFINED, CR_REFERENCED, // SUNARY (special unary)
39 '!', '~', UNMINUS, 0, // UNARY
40 '*', '/', '%', 0, // MULT
43 LE, GE, '<', '>', NE, '=', 0, // REL
50 const char missym_error[] = "missing symbol";
51 const char str_error[] = "missing symbol or string";
53 // Convert expression to postfix
54 static TOKENPTR evalTokenBuffer; // Deposit tokens here (this is really a
55 // pointer to exprbuf from direct.c)
56 // (Can also be from others, like
58 static int symbolNum; // Pointer to the entry in symbolPtr[]
62 // Obtain a string value
64 static uint32_t str_value(char * p)
69 v = (v << 8) | (*p & 0xFF);
76 // Initialize expression analyzer
78 void InitExpression(void)
80 // Initialize token-class table (all set to END)
81 for(int i=0; i<256; i++)
86 for(char * p=itokcl; *p!=1; p++)
91 tokenClass[(int)(*p)] = (char)i;
99 // Binary operators (all the same precedence)
108 while (tokenClass[*tok.u32] >= MULT)
115 *evalTokenBuffer.u32++ = t;
123 // Unary operators (detect unary '-')
124 // ggn: If expression starts with a plus then also eat it up. For some reason
125 // the parser gets confused when this happens and emits a "bad
137 class = tokenClass[*tok.u32];
139 if (*tok.u32 == '-' || *tok.u32 == '+' || class == UNARY)
149 // With leading + we don't have to deposit anything to the buffer
150 // because there's no unary '+' nor we have to do anything about it
152 *evalTokenBuffer.u32++ = t;
154 else if (class == SUNARY)
159 *evalTokenBuffer.u32++ = CONST;
160 *evalTokenBuffer.u64++ = (uint64_t)sect[ABS].sloc;
163 *evalTokenBuffer.u32++ = CONST;
164 *evalTokenBuffer.u64++ = dos_time();
167 *evalTokenBuffer.u32++ = CONST;
168 *evalTokenBuffer.u64++ = dos_date();
170 case CR_MACDEF: // ^^macdef <macro-name>
171 if (*tok.u32++ != SYMBOL)
172 return error(missym_error);
174 p = string[*tok.u32++];
175 w = (lookup(p, MACRO, 0) == NULL ? 0 : 1);
176 *evalTokenBuffer.u32++ = CONST;
177 *evalTokenBuffer.u64++ = (uint64_t)w;
185 if (*tok.u32++ != SYMBOL)
186 return error(missym_error);
188 p = string[*tok.u32++];
189 j = (*p == '.' ? curenv : 0);
190 w = ((sy = lookup(p, LABEL, j)) != NULL && (sy->sattr & w) ? 1 : 0);
191 *evalTokenBuffer.u32++ = CONST;
192 *evalTokenBuffer.u64++ = (uint64_t)w;
195 if (*tok.u32 != SYMBOL && *tok.u32 != STRING)
196 return error(str_error);
198 p = string[tok.u32[1]];
201 if (*tok.u32++ != ',')
202 return error(comma_error);
204 if (*tok.u32 != SYMBOL && *tok.u32 != STRING)
205 return error(str_error);
207 p2 = string[tok.u32[1]];
210 w = (WORD)(!strcmp(p, p2));
211 *evalTokenBuffer.u32++ = CONST;
212 *evalTokenBuffer.u64++ = (uint64_t)w;
224 // Terminals (CONSTs) and parenthesis grouping
235 *evalTokenBuffer.u32++ = CONST;
236 *evalTokenBuffer.u64++ = *tok.u64++;
239 *evalTokenBuffer.u32++ = FCONST;
240 *evalTokenBuffer.u64++ = *tok.u64++;
243 p = string[*tok.u32++];
244 j = (*p == '.' ? curenv : 0);
245 sy = lookup(p, LABEL, j);
248 sy = NewSymbol(p, LABEL, j);
250 // Check register bank usage
251 if (sy->sattre & EQUATEDREG)
253 if ((regbank == BANK_0) && (sy->sattre & BANK_1) && !altbankok)
254 warn("equated symbol \'%s\' cannot be used in register bank 0", sy->sname);
256 if ((regbank == BANK_1) && (sy->sattre & BANK_0) && !altbankok)
257 warn("equated symbol \'%s\' cannot be used in register bank 1", sy->sname);
260 *evalTokenBuffer.u32++ = SYMBOL;
261 *evalTokenBuffer.u32++ = symbolNum;
262 symbolPtr[symbolNum] = sy;
266 *evalTokenBuffer.u32++ = CONST;
267 *evalTokenBuffer.u64++ = str_value(string[*tok.u32++]);
273 if (*tok.u32++ != ')')
274 return error("missing closing parenthesis ')'");
281 if (*tok.u32++ != ']')
282 return error("missing closing bracket ']'");
286 *evalTokenBuffer.u32++ = ACONST; // Attributed const
287 *evalTokenBuffer.u32++ = sloc; // Current location
288 *evalTokenBuffer.u32++ = cursect | DEFINED; // Store attribs
291 *evalTokenBuffer.u32++ = ACONST; // Attributed const
293 // pcloc == location at start of line
294 *evalTokenBuffer.u32++ = (orgactive ? orgaddr : pcloc);
295 // '*' takes attributes of current section, not ABS!
296 *evalTokenBuffer.u32++ = cursect | DEFINED;
299 if (expr0() != OK) // Eat up first parameter (register or immediate)
302 if (*tok.u32++ != ':') // Demand a ':' there
303 return error("missing colon ':'");
305 if (expr0() != OK) // Eat up second parameter (register or immediate)
308 if (*tok.u32++ != '}')
309 return error("missing closing brace '}'");
313 return error("bad expression");
321 // Recursive-descent expression analyzer (with some simple speed hacks)
323 int expr(TOKENPTR otk, uint64_t * a_value, WORD * a_attr, SYM ** a_esym)
325 // Passed in values (once derefenced, that is) can all be zero. They are
326 // there so that the expression analyzer can fill them in as needed. The
327 // expression analyzer gets its input from the global token pointer "tok",
328 // and not from anything passed in by the user.
333 evalTokenBuffer = otk; // Set token pointer to 'exprbuf' (direct.c)
334 // Also set in various other places too (riscasm.c,
337 //printf("expr(): tokens 0-2: %i %i %i (%c %c %c); tc[2] = %i\n", tok.u32[0], tok.u32[1], tok.u32[2], tok.u32[0], tok.u32[1], tok.u32[2], tokenClass[tok.u32[2]]);
338 // Optimize for single constant or single symbol.
339 // Shamus: Subtle bug here. EOL token is 101; if you have a constant token
340 // followed by the value 101, it will trigger a bad evaluation here.
341 // This is probably a really bad assumption to be making here...!
342 // (assuming tok.u32[1] == EOL is a single token that is)
343 // Seems that even other tokens (SUNARY type) can fuck this up too.
345 // if ((tok.u32[1] == EOL)
346 if ((tok.u32[1] == EOL && ((tok.u32[0] != CONST || tok.u32[0] != FCONST) && tokenClass[tok.u32[0]] != SUNARY))
347 // || (((*tok.u32 == CONST || *tok.u32 == FCONST || *tok.u32 == SYMBOL) || (*tok.u32 >= KW_R0 && *tok.u32 <= KW_R31))
348 // && (tokenClass[tok.u32[2]] < UNARY)))
349 || (((tok.u32[0] == SYMBOL) || (tok.u32[0] >= KW_R0 && tok.u32[0] <= KW_R31))
350 && (tokenClass[tok.u32[2]] < UNARY))
351 || ((tok.u32[0] == CONST || tok.u32[0] == FCONST) && (tokenClass[tok.u32[3]] < UNARY))
354 // 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:
355 if ((tok.u32[1] == EOL
356 && (tok.u32[0] != CONST && tokenClass[tok.u32[0]] != SUNARY))
357 || (((tok.u32[0] == SYMBOL)
358 || (tok.u32[0] >= KW_R0 && tok.u32[0] <= KW_R31))
359 && (tokenClass[tok.u32[2]] < UNARY))
360 || ((tok.u32[0] == CONST) && (tokenClass[tok.u32[3]] < UNARY))
362 // 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.u32[1] for an EOL. O_o
365 if (*tok.u32 >= KW_R0 && *tok.u32 <= KW_R31)
367 *evalTokenBuffer.u32++ = CONST;
368 *evalTokenBuffer.u64++ = *a_value = (*tok.u32 - KW_R0);
369 *a_attr = ABS | DEFINED;
376 else if (*tok.u32 == CONST)
378 *evalTokenBuffer.u32++ = *tok.u32++;
379 *evalTokenBuffer.u64++ = *a_value = *tok.u64++;
380 *a_attr = ABS | DEFINED;
385 //printf("Quick eval in expr(): CONST = %i, tokenClass[tok.u32[2]] = %i\n", *a_value, tokenClass[*tok.u32]);
387 // Not sure that removing float constant here is going to break anything and/or
388 // make things significantly slower, but having this here seems to cause the
389 // complexity of the check to get to this part of the parse to go through the
390 // roof, and dammit, I just don't feel like fighting that fight ATM. :-P
392 else if (*tok.u32 == FCONST)
394 *evalTokenBuffer.u32++ = *tok.u32++;
395 *evalTokenBuffer.u64++ = *a_value = *tok.u64++;
396 *a_attr = ABS | DEFINED | FLOAT;
401 //printf("Quick eval in expr(): CONST = %i, tokenClass[tok.u32[2]] = %i\n", *a_value, tokenClass[*tok.u32]);
404 else if (*tok.u32 == '*')
406 *evalTokenBuffer.u32++ = CONST;
409 *evalTokenBuffer.u64++ = *a_value = orgaddr;
411 *evalTokenBuffer.u64++ = *a_value = pcloc;
413 // '*' takes attributes of current section, not ABS!
414 *a_attr = cursect | DEFINED;
421 else if (*tok.u32 == STRING || *tok.u32 == SYMBOL)
423 p = string[tok.u32[1]];
424 j = (*p == '.' ? curenv : 0);
425 symbol = lookup(p, LABEL, j);
427 printf("eval: Looking up symbol (%s) [=%08X]\n", p, symbol);
429 printf(" attr=%04X, attre=%08X, val=%i, name=%s\n", symbol->sattr, symbol->sattre, symbol->svalue, symbol->sname);
433 symbol = NewSymbol(p, LABEL, j);
435 symbol->sattr |= REFERENCED;
437 // Check for undefined register equates, but only if it's not part
438 // of a #<SYMBOL> construct, as it could be that the label that's
439 // been undefined may later be used as an address label--which
440 // means it will be fixed up later, and thus, not an error.
441 if ((symbol->sattre & UNDEF_EQUR) && !riscImmTokenSeen)
443 error("undefined register equate '%s'", symbol->sname);
444 //if we return right away, it returns some spurious errors...
448 // Check register bank usage
449 if (symbol->sattre & EQUATEDREG)
451 if ((regbank == BANK_0) && (symbol->sattre & BANK_1) && !altbankok)
452 warn("equated symbol '%s' cannot be used in register bank 0", symbol->sname);
454 if ((regbank == BANK_1) && (symbol->sattre & BANK_0) && !altbankok)
455 warn("equated symbol '%s' cannot be used in register bank 1", symbol->sname);
458 *evalTokenBuffer.u32++ = SYMBOL;
460 *evalTokenBuffer++ = (TOKEN)symbol;
463 While this approach works, it's wasteful. It would be better to use something
464 that's already available, like the symbol "order defined" table (which needs to
465 be converted from a linked list into an array).
467 *evalTokenBuffer.u32++ = symbolNum;
468 symbolPtr[symbolNum] = symbol;
472 if (symbol->sattr & DEFINED)
473 *a_value = symbol->svalue;
478 All that extra crap that was put into the svalue when doing the equr stuff is
479 thrown away right here. What the hell is it for?
481 if (symbol->sattre & EQUATEDREG)
484 *a_attr = (WORD)(symbol->sattr & ~GLOBAL);
486 if ((symbol->sattr & (GLOBAL | DEFINED)) == GLOBAL
494 // Unknown type here... Alert the user!,
495 error("undefined RISC register in expression");
496 // Prevent spurious error reporting...
501 *evalTokenBuffer.u32++ = ENDEXPR;
508 *evalTokenBuffer.u32++ = ENDEXPR;
509 return evexpr(otk, a_value, a_attr, a_esym);
514 // Evaluate expression.
515 // If the expression involves only ONE external symbol, the expression is
516 // UNDEFINED, but it's value includes everything but the symbol value, and
517 // 'a_esym' is set to the external symbol.
519 int evexpr(TOKENPTR tk, uint64_t * a_value, WORD * a_attr, SYM ** a_esym)
523 uint64_t * sval = evstk; // (Empty) initial stack
524 WORD * sattr = evattr;
525 SYM * esym = NULL; // No external symbol involved
528 while (*tk.u32 != ENDEXPR)
530 switch ((int)*tk.u32++)
533 //printf("evexpr(): SYMBOL\n");
534 sy = symbolPtr[*tk.u32++];
535 sy->sattr |= REFERENCED; // Set "referenced" bit
537 if (!(sy->sattr & DEFINED))
539 // Reference to undefined symbol
540 if (!(sy->sattr & GLOBAL))
547 if (esym != NULL) // Check for multiple externals
548 return error(seg_error);
553 if (sy->sattr & DEFINED)
555 *++sval = sy->svalue; // Push symbol's value
559 *++sval = 0; // 0 for undefined symbols
562 *++sattr = (WORD)(sy->sattr & ~GLOBAL); // Push attribs
563 sym_seg = (WORD)(sy->sattr & TDB);
567 //printf("evexpr(): CONST = %lX\n", *sval);
568 *++sattr = ABS | DEFINED; // Push simple attribs
571 //printf("evexpr(): FCONST = %i\n", *tk.u32);
572 *((double *)sval) = *((double *)tk.u32);
574 *++sattr = ABS | DEFINED | FLOAT; // Push simple attribs
577 //printf("evexpr(): ACONST = %i\n", *tk.u32);
578 *++sval = *tk.u32++; // Push value
579 *++sattr = (WORD)*tk.u32++; // Push attribs
582 // Binary "+" and "-" matrix:
585 // ----------------------------
586 // ABS | ABS | Sect | Other |
587 // Sect | Sect | [1] | Error |
588 // Other | Other | Error | [1] |
589 // ----------------------------
594 //printf("evexpr(): +\n");
596 --sattr; // Pop attrib
597 //printf("--> N+N: %i + %i = ", *sval, sval[1]);
598 // Extract float attributes from both terms and pack them
599 // into a single value
600 attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
601 attr2 = sattr[0] | sattr[1] & FLOAT; // Returns FLOAT if either of the two numbers are FLOAT
603 if (attr == (FLOAT | (FLOAT >> 1)))
606 double * dst = (double *)sval;
607 double * src = (double *)(sval + 1);
610 else if (attr == FLOAT)
613 double * dst = (double *)sval;
614 uint64_t * src = (uint64_t *)(sval + 1);
617 else if (attr == FLOAT >> 1)
620 uint64_t * dst = (uint64_t *)sval;
621 double * src = (double *)(sval + 1);
622 *(double *)dst = *src + *dst;
626 *sval += sval[1]; // Compute value
628 //printf("%i\n", *sval);
631 *sattr = sattr[1] | attr2;
632 else if (sattr[1] & TDB)
633 return error(seg_error);
637 //printf("evexpr(): -\n");
639 --sattr; // Pop attrib
640 //printf("--> N-N: %i - %i = ", *sval, sval[1]);
641 // Extract float attributes from both terms and pack them
642 // into a single value
643 attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
644 attr2 = sattr[0] | sattr[1] & FLOAT; // Returns FLOAT if either of the two numbers are FLOAT
646 if (attr == (FLOAT | (FLOAT >> 1)))
649 double * dst = (double *)sval;
650 double * src = (double *)(sval + 1);
653 else if (attr == FLOAT)
656 double * dst = (double *)sval;
657 uint64_t * src = (uint64_t *)(sval + 1);
660 else if (attr == FLOAT >> 1)
663 uint64_t * dst = (uint64_t *)sval;
664 double * src = (double *)(sval + 1);
665 *(double *)dst = *dst - *src;
669 *sval -= sval[1]; // Compute value
672 //printf("%i\n", *sval);
674 attr = (WORD)(*sattr & TDB);
676 printf("EVEXPR (-): sym1 = %X, sym2 = %X\n", attr, sattr[1]);
678 *sattr |= attr2; // Inherit FLOAT attribute
679 // If symbol1 is ABS, take attributes from symbol2
682 // Otherwise, they're both TDB and so attributes cancel out
683 else if (sattr[1] & TDB)
687 // Unary operators only work on ABS items
689 //printf("evexpr(): UNMINUS\n");
691 return error(seg_error);
695 double *dst = (double *)sval;
697 *sattr = ABS | DEFINED | FLOAT; // Expr becomes absolute
702 *sattr = ABS | DEFINED; // Expr becomes absolute
706 //printf("evexpr(): !\n");
708 return error(seg_error);
711 return error("floating point numbers not allowed with operator '!'.");
714 *sattr = ABS | DEFINED; // Expr becomes absolute
717 //printf("evexpr(): ~\n");
719 return error(seg_error);
722 return error("floating point numbers not allowed with operator '~'.");
725 *sattr = ABS | DEFINED; // Expr becomes absolute
727 // Comparison operators must have two values that
728 // are in the same segment, but that's the only requirement.
730 //printf("evexpr(): LE\n");
734 if ((*sattr & TDB) != (sattr[1] & TDB))
735 return error(seg_error);
737 // Extract float attributes from both terms and pack them
738 // into a single value
739 attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
741 if (attr == (FLOAT | (FLOAT >> 1)))
744 double * dst = (double *)sval;
745 double * src = (double *)(sval + 1);
746 *sval = *dst <= *src;
748 else if (attr == FLOAT)
751 double * dst = (double *)sval;
752 uint64_t * src = (uint64_t *)(sval + 1);
753 *sval = *dst <= *src;
755 else if (attr == FLOAT >> 1)
758 uint64_t * dst = (uint64_t *)sval;
759 double * src = (double *)(sval + 1);
760 *sval = *dst <= *src;
764 *sval = *sval <= sval[1];
767 *sattr = ABS | DEFINED;
770 //printf("evexpr(): GE\n");
774 if ((*sattr & TDB) != (sattr[1] & TDB))
775 return error(seg_error);
777 // Extract float attributes from both terms and pack them
778 // into a single value
779 attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
781 if (attr == (FLOAT | (FLOAT >> 1)))
784 double * dst = (double *)sval;
785 double * src = (double *)(sval + 1);
786 *sval = *dst >= *src;
788 else if (attr == FLOAT)
791 double * dst = (double *)sval;
792 uint64_t * src = (uint64_t *)(sval + 1);
793 *sval = *dst >= *src;
795 else if (attr == FLOAT >> 1)
798 uint64_t * dst = (uint64_t *)sval;
799 double * src = (double *)(sval + 1);
800 *sval = *dst >= *src;
804 *sval = *sval >= sval[1];
807 *sattr = ABS | DEFINED;
811 //printf("evexpr(): >\n");
815 if ((*sattr & TDB) != (sattr[1] & TDB))
816 return error(seg_error);
818 // Extract float attributes from both terms and pack them
819 // into a single value
820 attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
822 if (attr == (FLOAT | (FLOAT >> 1)))
825 double * dst = (double *)sval;
826 double * src = (double *)(sval + 1);
829 else if (attr == FLOAT)
832 double * dst = (double *)sval;
833 uint64_t * src = (uint64_t *)(sval + 1);
836 else if (attr == FLOAT >> 1)
839 uint64_t * dst = (uint64_t *)sval;
840 double * src = (double *)(sval + 1);
845 *sval = *sval > sval[1];
848 *sattr = ABS | DEFINED;
852 //printf("evexpr(): <\n");
856 if ((*sattr & TDB) != (sattr[1] & TDB))
857 return error(seg_error);
859 // Extract float attributes from both terms and pack them
860 // into a single value
861 attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
863 if (attr == (FLOAT | (FLOAT >> 1)))
866 double * dst = (double *)sval;
867 double * src = (double *)(sval + 1);
870 else if (attr == FLOAT)
873 double * dst = (double *)sval;
874 uint64_t * src = (uint64_t *)(sval + 1);
877 else if (attr == FLOAT >> 1)
880 uint64_t * dst = (uint64_t *)sval;
881 double * src = (double *)(sval + 1);
886 *sval = *sval < sval[1];
889 *sattr = ABS | DEFINED;
893 //printf("evexpr(): NE\n");
897 if ((*sattr & TDB) != (sattr[1] & TDB))
898 return error(seg_error);
900 // Extract float attributes from both terms and pack them
901 // into a single value
902 attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
904 if (attr == (FLOAT | (FLOAT >> 1)))
907 return error("comparison for equality with float types not allowed.");
909 else if (attr == FLOAT)
912 return error("comparison for equality with float types not allowed.");
914 else if (attr == FLOAT >> 1)
917 return error("comparison for equality with float types not allowed.");
921 *sval = *sval != sval[1];
924 *sattr = ABS | DEFINED;
928 //printf("evexpr(): =\n");
932 if ((*sattr & TDB) != (sattr[1] & TDB))
933 return error(seg_error);
935 // Extract float attributes from both terms and pack them
936 // into a single value
937 attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
939 if (attr == (FLOAT | (FLOAT >> 1)))
942 double * dst = (double *)sval;
943 double * src = (double *)(sval + 1);
944 *sval = *src == *dst;
946 else if (attr == FLOAT)
949 return error("equality with float ");
951 else if (attr == FLOAT >> 1)
954 uint64_t * dst = (uint64_t *)sval;
955 double * src = (double *)(sval + 1);
956 *sval = *src == *dst;
960 *sval = *sval == sval[1];
963 *sattr = ABS | DEFINED;
966 // All other binary operators must have two ABS items to work with.
967 // They all produce an ABS value.
969 //printf("evexpr(): default\n");
970 // GH - Removed for v1.0.15 as part of the fix for indexed loads.
971 //if ((*sattr & (TEXT|DATA|BSS)) || (*--sattr & (TEXT|DATA|BSS)))
974 switch ((int)tk.u32[-1])
978 sattr--; // Pop attrib
979 //printf("--> NxN: %i x %i = ", *sval, sval[1]);
980 // Extract float attributes from both terms and pack them
981 // into a single value
982 attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
983 attr2 = sattr[0] | sattr[1] & FLOAT; // Returns FLOAT if either of the two numbers are FLOAT
985 if (attr == (FLOAT | (FLOAT >> 1)))
988 double * dst = (double *)sval;
989 double * src = (double *)(sval + 1);
992 else if (attr == FLOAT)
995 double * dst = (double *)sval;
996 uint64_t * src = (uint64_t *)(sval + 1);
999 else if (attr == FLOAT >> 1)
1002 uint64_t * dst = (uint64_t *)sval;
1003 double * src = (double *)(sval + 1);
1004 *(double *)dst = *src * *dst;
1010 //printf("%i\n", *sval);
1012 *sattr = ABS | DEFINED; // Expr becomes absolute
1018 sattr--; // Pop attrib
1021 //printf("--> N/N: %i / %i = ", sval[0], sval[1]);
1022 // Extract float attributes from both terms and pack them
1023 // into a single value
1024 attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
1025 attr2 = sattr[0] | sattr[1] & FLOAT; // Returns FLOAT if either of the two numbers are FLOAT
1027 if (attr == (FLOAT | (FLOAT >> 1)))
1030 double * dst = (double *)sval;
1031 double * src = (double *)(sval + 1);
1034 return error("divide by zero");
1038 else if (attr == FLOAT)
1041 double * dst = (double *)sval;
1042 uint64_t * src = (uint64_t *)(sval + 1);
1045 return error("divide by zero");
1049 else if (attr == FLOAT >> 1)
1052 uint64_t * dst=(uint64_t *)sval;
1053 double * src=(double *)(sval + 1);
1056 return error("divide by zero");
1058 *(double *)dst = *dst / *src;
1063 return error("divide by zero");
1064 //printf("--> N/N: %i / %i = ", sval[0], sval[1]);
1066 // Compiler is picky here: Without casting these, it
1067 // discards the sign if dividing a negative # by a
1068 // positive one, creating a bad result. :-/
1069 // Definitely a side effect of using uint32_ts intead of
1071 *sval = (int32_t)sval[0] / (int32_t)sval[1];
1074 *sattr = ABS | DEFINED; // Expr becomes absolute
1077 //printf("%i\n", *sval);
1081 sattr--; // Pop attrib
1083 if ((*sattr | sattr[1]) & FLOAT)
1084 return error("floating point numbers not allowed with operator '%'.");
1087 return error("mod (%) by zero");
1089 *sattr = ABS | DEFINED; // Expr becomes absolute
1094 sattr--; // Pop attrib
1096 if ((*sattr | sattr[1]) & FLOAT)
1097 return error("floating point numbers not allowed with operator '<<'.");
1099 *sattr = ABS | DEFINED; // Expr becomes absolute
1104 sattr--; // Pop attrib
1106 if ((*sattr | sattr[1]) & FLOAT)
1107 return error("floating point numbers not allowed with operator '>>'.");
1109 *sattr = ABS | DEFINED; // Expr becomes absolute
1114 sattr--; // Pop attrib
1116 if ((*sattr | sattr[1]) & FLOAT)
1117 return error("floating point numbers not allowed with operator '&'.");
1119 *sattr = ABS | DEFINED; // Expr becomes absolute
1124 sattr--; // Pop attrib
1126 if ((*sattr | sattr[1]) & FLOAT)
1127 return error("floating point numbers not allowed with operator '^'.");
1129 *sattr = ABS | DEFINED; // Expr becomes absolute
1134 sattr--; // Pop attrib
1136 if ((*sattr | sattr[1]) & FLOAT)
1137 return error("floating point numbers not allowed with operator '|'.");
1139 *sattr = ABS | DEFINED; // Expr becomes absolute
1143 interror(5); // Bad operator in expression stream
1154 // sym_seg added in 1.0.16 to solve a problem with forward symbols in
1155 // expressions where absolute values also existed. The absolutes were
1156 // overiding the symbol segments and not being included :(
1157 //*a_attr = *sattr | sym_seg; // Copy value + attrib
1159 *a_attr = *sattr; // Copy value + attrib