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 PTR 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)
106 while (tokenClass[*tok] >= MULT)
113 *evalTokenBuffer.u32++ = t;
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
134 int class = tokenClass[*tok];
136 if (*tok == '-' || *tok == '+' || class == UNARY)
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
149 *evalTokenBuffer.u32++ = t;
151 else if (class == SUNARY)
156 *evalTokenBuffer.u32++ = CONST;
157 *evalTokenBuffer.u64++ = (uint64_t)sect[ABS].sloc;
160 *evalTokenBuffer.u32++ = CONST;
161 *evalTokenBuffer.u64++ = dos_time();
164 *evalTokenBuffer.u32++ = CONST;
165 *evalTokenBuffer.u64++ = dos_date();
167 case CR_MACDEF: // ^^macdef <macro-name>
168 if (*tok++ != SYMBOL)
169 return error(missym_error);
172 w = (lookup(p, MACRO, 0) == NULL ? 0 : 1);
173 *evalTokenBuffer.u32++ = CONST;
174 *evalTokenBuffer.u64++ = (uint64_t)w;
182 if (*tok++ != SYMBOL)
183 return error(missym_error);
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;
192 if (*tok != SYMBOL && *tok != STRING)
193 return error(str_error);
199 return error(comma_error);
201 if (*tok != SYMBOL && *tok != STRING)
202 return error(str_error);
207 w = (WORD)(!strcmp(p, p2));
208 *evalTokenBuffer.u32++ = CONST;
209 *evalTokenBuffer.u64++ = (uint64_t)w;
221 // Terminals (CONSTs) and parenthesis grouping
234 *evalTokenBuffer.u32++ = CONST;
235 *evalTokenBuffer.u64++ = *ptk.u64++;
240 *evalTokenBuffer.u32++ = CONST;
241 *evalTokenBuffer.u64++ = *ptk.u64++;
246 j = (*p == '.' ? curenv : 0);
247 sy = lookup(p, LABEL, j);
250 sy = NewSymbol(p, LABEL, j);
252 // Check register bank usage
253 if (sy->sattre & EQUATEDREG)
255 if ((regbank == BANK_0) && (sy->sattre & BANK_1) && !altbankok)
256 warn("equated symbol \'%s\' cannot be used in register bank 0", sy->sname);
258 if ((regbank == BANK_1) && (sy->sattre & BANK_0) && !altbankok)
259 warn("equated symbol \'%s\' cannot be used in register bank 1", sy->sname);
262 *evalTokenBuffer.u32++ = SYMBOL;
263 *evalTokenBuffer.u32++ = symbolNum;
264 symbolPtr[symbolNum] = sy;
268 *evalTokenBuffer.u32++ = CONST;
269 *evalTokenBuffer.u64++ = str_value(string[*tok++]);
276 return error("missing closing parenthesis ')'");
284 return error("missing closing bracket ']'");
288 if (expr0() != OK) // Eat up first parameter (register or immediate)
291 if (*tok++ != ':') // Demand a ':' there
292 return error("missing colon ':'");
294 if (expr0() != OK) // Eat up second parameter (register or immediate)
298 return error("missing closing brace '}'");
302 *evalTokenBuffer.u32++ = ACONST; // Attributed const
303 *evalTokenBuffer.u32++ = sloc; // Current location
304 *evalTokenBuffer.u32++ = cursect | DEFINED; // Store attribs
307 *evalTokenBuffer.u32++ = ACONST; // Attributed const
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;
315 return error("bad expression");
323 // Recursive-descent expression analyzer (with some simple speed hacks)
325 int expr(TOKEN * otk, uint64_t * a_value, WORD * a_attr, SYM ** a_esym)
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.
336 evalTokenBuffer.u32 = otk; // Set token pointer to 'exprbuf' (direct.c)
337 // Also set in various other places too (riscasm.c,
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.
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))
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:
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))
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
368 if (*tok >= KW_R0 && *tok <= KW_R31)
370 *evalTokenBuffer.u32++ = CONST;
371 *evalTokenBuffer.u64++ = *a_value = (*tok - KW_R0);
372 *a_attr = ABS | DEFINED;
379 else if (*tok == CONST)
382 *evalTokenBuffer.u32++ = *ptk.u32++;
383 *evalTokenBuffer.u64++ = *a_value = *ptk.u64++;
384 *a_attr = ABS | DEFINED;
390 //printf("Quick eval in expr(): CONST = %i, tokenClass[tok[2]] = %i\n", *a_value, tokenClass[*tok]);
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
397 else if (*tok == FCONST)
399 *evalTokenBuffer.u32++ = *tok++;
400 *evalTokenBuffer.u64++ = *a_value = *tok.u64++;
401 *a_attr = ABS | DEFINED | FLOAT;
406 //printf("Quick eval in expr(): CONST = %i, tokenClass[tok[2]] = %i\n", *a_value, tokenClass[*tok]);
409 else if (*tok == '*')
411 *evalTokenBuffer.u32++ = CONST;
414 *evalTokenBuffer.u64++ = *a_value = orgaddr;
416 *evalTokenBuffer.u64++ = *a_value = pcloc;
418 // '*' takes attributes of current section, not ABS!
419 *a_attr = cursect | DEFINED;
426 else if (*tok == STRING || *tok == SYMBOL)
429 j = (*p == '.' ? curenv : 0);
430 symbol = lookup(p, LABEL, j);
432 printf("eval: Looking up symbol (%s) [=%08X]\n", p, symbol);
434 printf(" attr=%04X, attre=%08X, val=%i, name=%s\n", symbol->sattr, symbol->sattre, symbol->svalue, symbol->sname);
438 symbol = NewSymbol(p, LABEL, j);
440 symbol->sattr |= REFERENCED;
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)
448 error("undefined register equate '%s'", symbol->sname);
449 //if we return right away, it returns some spurious errors...
453 // Check register bank usage
454 if (symbol->sattre & EQUATEDREG)
456 if ((regbank == BANK_0) && (symbol->sattre & BANK_1) && !altbankok)
457 warn("equated symbol '%s' cannot be used in register bank 0", symbol->sname);
459 if ((regbank == BANK_1) && (symbol->sattre & BANK_0) && !altbankok)
460 warn("equated symbol '%s' cannot be used in register bank 1", symbol->sname);
463 *evalTokenBuffer.u32++ = SYMBOL;
465 *evalTokenBuffer++ = (TOKEN)symbol;
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).
472 *evalTokenBuffer.u32++ = symbolNum;
473 symbolPtr[symbolNum] = symbol;
477 if (symbol->sattr & DEFINED)
478 *a_value = symbol->svalue;
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?
486 if (symbol->sattre & EQUATEDREG)
489 *a_attr = (WORD)(symbol->sattr & ~GLOBAL);
491 if ((symbol->sattr & (GLOBAL | DEFINED)) == GLOBAL
499 // Unknown type here... Alert the user!,
500 error("undefined RISC register in expression");
501 // Prevent spurious error reporting...
506 *evalTokenBuffer.u32++ = ENDEXPR;
513 *evalTokenBuffer.u32++ = ENDEXPR;
514 return evexpr(otk, a_value, a_attr, a_esym);
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.
524 int evexpr(TOKEN * _tk, uint64_t * a_value, WORD * a_attr, SYM ** a_esym)
528 uint64_t * sval = evstk; // (Empty) initial stack
529 WORD * sattr = evattr;
530 SYM * esym = NULL; // No external symbol involved
535 while (*tk.u32 != ENDEXPR)
537 switch ((int)*tk.u32++)
540 //printf("evexpr(): SYMBOL\n");
541 sy = symbolPtr[*tk.u32++];
542 sy->sattr |= REFERENCED; // Set "referenced" bit
544 if (!(sy->sattr & DEFINED))
546 // Reference to undefined symbol
547 if (!(sy->sattr & GLOBAL))
554 if (esym != NULL) // Check for multiple externals
555 return error(seg_error);
560 if (sy->sattr & DEFINED)
562 *++sval = sy->svalue; // Push symbol's value
566 *++sval = 0; // 0 for undefined symbols
569 *++sattr = (WORD)(sy->sattr & ~GLOBAL); // Push attribs
570 sym_seg = (WORD)(sy->sattr & TDB);
574 //printf("evexpr(): CONST = %lX\n", *sval);
575 *++sattr = ABS | DEFINED; // Push simple attribs
578 //printf("evexpr(): FCONST = %i\n", *tk.u32);
579 *((double *)sval) = *((double *)tk.u32);
581 *++sattr = ABS | DEFINED | FLOAT; // Push simple attribs
584 //printf("evexpr(): ACONST = %i\n", *tk.u32);
585 *++sval = *tk.u32++; // Push value
586 *++sattr = (WORD)*tk.u32++; // Push attribs
589 // Binary "+" and "-" matrix:
592 // ----------------------------
593 // ABS | ABS | Sect | Other |
594 // Sect | Sect | [1] | Error |
595 // Other | Other | Error | [1] |
596 // ----------------------------
601 //printf("evexpr(): +\n");
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
610 if (attr == (FLOAT | (FLOAT >> 1)))
613 double * dst = (double *)sval;
614 double * src = (double *)(sval + 1);
617 else if (attr == FLOAT)
620 double * dst = (double *)sval;
621 uint64_t * src = (uint64_t *)(sval + 1);
624 else if (attr == FLOAT >> 1)
627 uint64_t * dst = (uint64_t *)sval;
628 double * src = (double *)(sval + 1);
629 *(double *)dst = *src + *dst;
633 *sval += sval[1]; // Compute value
635 //printf("%i\n", *sval);
638 *sattr = sattr[1] | attr2;
639 else if (sattr[1] & TDB)
640 return error(seg_error);
644 //printf("evexpr(): -\n");
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
653 if (attr == (FLOAT | (FLOAT >> 1)))
656 double * dst = (double *)sval;
657 double * src = (double *)(sval + 1);
660 else if (attr == FLOAT)
663 double * dst = (double *)sval;
664 uint64_t * src = (uint64_t *)(sval + 1);
667 else if (attr == FLOAT >> 1)
670 uint64_t * dst = (uint64_t *)sval;
671 double * src = (double *)(sval + 1);
672 *(double *)dst = *dst - *src;
676 *sval -= sval[1]; // Compute value
679 //printf("%i\n", *sval);
681 attr = (WORD)(*sattr & TDB);
683 printf("EVEXPR (-): sym1 = %X, sym2 = %X\n", attr, sattr[1]);
685 *sattr |= attr2; // Inherit FLOAT attribute
686 // If symbol1 is ABS, take attributes from symbol2
689 // Otherwise, they're both TDB and so attributes cancel out
690 else if (sattr[1] & TDB)
694 // Unary operators only work on ABS items
696 //printf("evexpr(): UNMINUS\n");
698 return error(seg_error);
702 double *dst = (double *)sval;
704 *sattr = ABS | DEFINED | FLOAT; // Expr becomes absolute
709 *sattr = ABS | DEFINED; // Expr becomes absolute
713 //printf("evexpr(): !\n");
715 return error(seg_error);
718 return error("floating point numbers not allowed with operator '!'.");
721 *sattr = ABS | DEFINED; // Expr becomes absolute
724 //printf("evexpr(): ~\n");
726 return error(seg_error);
729 return error("floating point numbers not allowed with operator '~'.");
732 *sattr = ABS | DEFINED; // Expr becomes absolute
734 // Comparison operators must have two values that
735 // are in the same segment, but that's the only requirement.
737 //printf("evexpr(): LE\n");
741 if ((*sattr & TDB) != (sattr[1] & TDB))
742 return error(seg_error);
744 // Extract float attributes from both terms and pack them
745 // into a single value
746 attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
748 if (attr == (FLOAT | (FLOAT >> 1)))
751 double * dst = (double *)sval;
752 double * src = (double *)(sval + 1);
753 *sval = *dst <= *src;
755 else if (attr == FLOAT)
758 double * dst = (double *)sval;
759 uint64_t * src = (uint64_t *)(sval + 1);
760 *sval = *dst <= *src;
762 else if (attr == FLOAT >> 1)
765 uint64_t * dst = (uint64_t *)sval;
766 double * src = (double *)(sval + 1);
767 *sval = *dst <= *src;
771 *sval = *sval <= sval[1];
774 *sattr = ABS | DEFINED;
777 //printf("evexpr(): GE\n");
781 if ((*sattr & TDB) != (sattr[1] & TDB))
782 return error(seg_error);
784 // Extract float attributes from both terms and pack them
785 // into a single value
786 attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
788 if (attr == (FLOAT | (FLOAT >> 1)))
791 double * dst = (double *)sval;
792 double * src = (double *)(sval + 1);
793 *sval = *dst >= *src;
795 else if (attr == FLOAT)
798 double * dst = (double *)sval;
799 uint64_t * src = (uint64_t *)(sval + 1);
800 *sval = *dst >= *src;
802 else if (attr == FLOAT >> 1)
805 uint64_t * dst = (uint64_t *)sval;
806 double * src = (double *)(sval + 1);
807 *sval = *dst >= *src;
811 *sval = *sval >= sval[1];
814 *sattr = ABS | DEFINED;
818 //printf("evexpr(): >\n");
822 if ((*sattr & TDB) != (sattr[1] & TDB))
823 return error(seg_error);
825 // Extract float attributes from both terms and pack them
826 // into a single value
827 attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
829 if (attr == (FLOAT | (FLOAT >> 1)))
832 double * dst = (double *)sval;
833 double * src = (double *)(sval + 1);
836 else if (attr == FLOAT)
839 double * dst = (double *)sval;
840 uint64_t * src = (uint64_t *)(sval + 1);
843 else if (attr == FLOAT >> 1)
846 uint64_t * dst = (uint64_t *)sval;
847 double * src = (double *)(sval + 1);
852 *sval = *sval > sval[1];
855 *sattr = ABS | DEFINED;
859 //printf("evexpr(): <\n");
863 if ((*sattr & TDB) != (sattr[1] & TDB))
864 return error(seg_error);
866 // Extract float attributes from both terms and pack them
867 // into a single value
868 attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
870 if (attr == (FLOAT | (FLOAT >> 1)))
873 double * dst = (double *)sval;
874 double * src = (double *)(sval + 1);
877 else if (attr == FLOAT)
880 double * dst = (double *)sval;
881 uint64_t * src = (uint64_t *)(sval + 1);
884 else if (attr == FLOAT >> 1)
887 uint64_t * dst = (uint64_t *)sval;
888 double * src = (double *)(sval + 1);
893 *sval = *sval < sval[1];
896 *sattr = ABS | DEFINED;
900 //printf("evexpr(): NE\n");
904 if ((*sattr & TDB) != (sattr[1] & TDB))
905 return error(seg_error);
907 // Extract float attributes from both terms and pack them
908 // into a single value
909 attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
911 if (attr == (FLOAT | (FLOAT >> 1)))
914 return error("comparison for equality with float types not allowed.");
916 else if (attr == FLOAT)
919 return error("comparison for equality with float types not allowed.");
921 else if (attr == FLOAT >> 1)
924 return error("comparison for equality with float types not allowed.");
928 *sval = *sval != sval[1];
931 *sattr = ABS | DEFINED;
935 //printf("evexpr(): =\n");
939 if ((*sattr & TDB) != (sattr[1] & TDB))
940 return error(seg_error);
942 // Extract float attributes from both terms and pack them
943 // into a single value
944 attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
946 if (attr == (FLOAT | (FLOAT >> 1)))
949 double * dst = (double *)sval;
950 double * src = (double *)(sval + 1);
951 *sval = *src == *dst;
953 else if (attr == FLOAT)
956 return error("equality with float ");
958 else if (attr == FLOAT >> 1)
961 uint64_t * dst = (uint64_t *)sval;
962 double * src = (double *)(sval + 1);
963 *sval = *src == *dst;
967 *sval = *sval == sval[1];
970 *sattr = ABS | DEFINED;
973 // All other binary operators must have two ABS items to work with.
974 // They all produce an ABS value.
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)))
981 switch ((int)tk.u32[-1])
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
992 if (attr == (FLOAT | (FLOAT >> 1)))
995 double * dst = (double *)sval;
996 double * src = (double *)(sval + 1);
999 else if (attr == FLOAT)
1002 double * dst = (double *)sval;
1003 uint64_t * src = (uint64_t *)(sval + 1);
1006 else if (attr == FLOAT >> 1)
1009 uint64_t * dst = (uint64_t *)sval;
1010 double * src = (double *)(sval + 1);
1011 *(double *)dst = *src * *dst;
1017 //printf("%i\n", *sval);
1019 *sattr = ABS | DEFINED; // Expr becomes absolute
1025 sattr--; // Pop attrib
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
1034 if (attr == (FLOAT | (FLOAT >> 1)))
1037 double * dst = (double *)sval;
1038 double * src = (double *)(sval + 1);
1041 return error("divide by zero");
1045 else if (attr == FLOAT)
1048 double * dst = (double *)sval;
1049 uint64_t * src = (uint64_t *)(sval + 1);
1052 return error("divide by zero");
1056 else if (attr == FLOAT >> 1)
1059 uint64_t * dst=(uint64_t *)sval;
1060 double * src=(double *)(sval + 1);
1063 return error("divide by zero");
1065 *(double *)dst = *dst / *src;
1070 return error("divide by zero");
1071 //printf("--> N/N: %i / %i = ", sval[0], sval[1]);
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
1078 *sval = (int32_t)sval[0] / (int32_t)sval[1];
1081 *sattr = ABS | DEFINED; // Expr becomes absolute
1084 //printf("%i\n", *sval);
1088 sattr--; // Pop attrib
1090 if ((*sattr | sattr[1]) & FLOAT)
1091 return error("floating point numbers not allowed with operator '%'.");
1094 return error("mod (%) by zero");
1096 *sattr = ABS | DEFINED; // Expr becomes absolute
1101 sattr--; // Pop attrib
1103 if ((*sattr | sattr[1]) & FLOAT)
1104 return error("floating point numbers not allowed with operator '<<'.");
1106 *sattr = ABS | DEFINED; // Expr becomes absolute
1111 sattr--; // Pop attrib
1113 if ((*sattr | sattr[1]) & FLOAT)
1114 return error("floating point numbers not allowed with operator '>>'.");
1116 *sattr = ABS | DEFINED; // Expr becomes absolute
1121 sattr--; // Pop attrib
1123 if ((*sattr | sattr[1]) & FLOAT)
1124 return error("floating point numbers not allowed with operator '&'.");
1126 *sattr = ABS | DEFINED; // Expr becomes absolute
1131 sattr--; // Pop attrib
1133 if ((*sattr | sattr[1]) & FLOAT)
1134 return error("floating point numbers not allowed with operator '^'.");
1136 *sattr = ABS | DEFINED; // Expr becomes absolute
1141 sattr--; // Pop attrib
1143 if ((*sattr | sattr[1]) & FLOAT)
1144 return error("floating point numbers not allowed with operator '|'.");
1146 *sattr = ABS | DEFINED; // Expr becomes absolute
1150 interror(5); // Bad operator in expression stream
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
1166 *a_attr = *sattr; // Copy value + attrib