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
235 *evalTokenBuffer.u32++ = CONST;
236 *evalTokenBuffer.u64++ = *ptk.u64++;
241 j = (*p == '.' ? curenv : 0);
242 sy = lookup(p, LABEL, j);
245 sy = NewSymbol(p, LABEL, j);
247 // Check register bank usage
248 if (sy->sattre & EQUATEDREG)
250 if ((regbank == BANK_0) && (sy->sattre & BANK_1) && !altbankok)
251 warn("equated symbol \'%s\' cannot be used in register bank 0", sy->sname);
253 if ((regbank == BANK_1) && (sy->sattre & BANK_0) && !altbankok)
254 warn("equated symbol \'%s\' cannot be used in register bank 1", sy->sname);
257 *evalTokenBuffer.u32++ = SYMBOL;
258 *evalTokenBuffer.u32++ = symbolNum;
259 symbolPtr[symbolNum] = sy;
263 *evalTokenBuffer.u32++ = CONST;
264 *evalTokenBuffer.u64++ = str_value(string[*tok++]);
271 return error("missing closing parenthesis ')'");
279 return error("missing closing bracket ']'");
283 if (expr0() != OK) // Eat up first parameter (register or immediate)
286 if (*tok++ != ':') // Demand a ':' there
287 return error("missing colon ':'");
289 if (expr0() != OK) // Eat up second parameter (register or immediate)
293 return error("missing closing brace '}'");
297 *evalTokenBuffer.u32++ = ACONST; // Attributed const
298 *evalTokenBuffer.u32++ = sloc; // Current location
299 *evalTokenBuffer.u32++ = cursect | DEFINED; // Store attribs
302 *evalTokenBuffer.u32++ = ACONST; // Attributed const
304 // pcloc == location at start of line
305 *evalTokenBuffer.u32++ = (orgactive ? orgaddr : pcloc);
306 // '*' takes attributes of current section, not ABS!
307 *evalTokenBuffer.u32++ = cursect | DEFINED;
310 return error("bad expression");
318 // Recursive-descent expression analyzer (with some simple speed hacks)
320 int expr(TOKEN * otk, uint64_t * a_value, WORD * a_attr, SYM ** a_esym)
322 // Passed in values (once derefenced, that is) can all be zero. They are
323 // there so that the expression analyzer can fill them in as needed. The
324 // expression analyzer gets its input from the global token pointer "tok",
325 // and not from anything passed in by the user.
331 evalTokenBuffer.u32 = otk; // Set token pointer to 'exprbuf' (direct.c)
332 // Also set in various other places too (riscasm.c,
335 //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]]);
336 // Optimize for single constant or single symbol.
337 // Shamus: Subtle bug here. EOL token is 101; if you have a constant token
338 // followed by the value 101, it will trigger a bad evaluation here.
339 // This is probably a really bad assumption to be making here...!
340 // (assuming tok[1] == EOL is a single token that is)
341 // Seems that even other tokens (SUNARY type) can fuck this up too.
343 // if ((tok[1] == EOL)
344 if ((tok[1] == EOL && ((tok[0] != CONST || tok[0] != FCONST) && tokenClass[tok[0]] != SUNARY))
345 // || (((*tok == CONST || *tok == FCONST || *tok == SYMBOL) || (*tok >= KW_R0 && *tok <= KW_R31))
346 // && (tokenClass[tok[2]] < UNARY)))
347 || (((tok[0] == SYMBOL) || (tok[0] >= KW_R0 && tok[0] <= KW_R31))
348 && (tokenClass[tok[2]] < UNARY))
349 || ((tok[0] == CONST || tok[0] == FCONST) && (tokenClass[tok[3]] < UNARY))
352 // 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:
354 && (tok[0] != CONST && tokenClass[tok[0]] != SUNARY))
355 || (((tok[0] == SYMBOL)
356 || (tok[0] >= KW_R0 && tok[0] <= KW_R31))
357 && (tokenClass[tok[2]] < UNARY))
358 || ((tok[0] == CONST) && (tokenClass[tok[3]] < UNARY))
360 // 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
363 if (*tok >= KW_R0 && *tok <= KW_R31)
365 *evalTokenBuffer.u32++ = CONST;
366 *evalTokenBuffer.u64++ = *a_value = (*tok - KW_R0);
367 *a_attr = ABS | DEFINED;
374 else if (*tok == CONST)
377 *evalTokenBuffer.u32++ = *ptk.u32++;
378 *evalTokenBuffer.u64++ = *a_value = *ptk.u64++;
379 *a_attr = ABS | DEFINED;
385 //printf("Quick eval in expr(): CONST = %i, tokenClass[tok[2]] = %i\n", *a_value, tokenClass[*tok]);
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 == FCONST)
394 *evalTokenBuffer.u32++ = *tok++;
395 *evalTokenBuffer.u64++ = *a_value = *tok.u64++;
396 *a_attr = ABS | DEFINED | FLOAT;
401 //printf("Quick eval in expr(): CONST = %i, tokenClass[tok[2]] = %i\n", *a_value, tokenClass[*tok]);
404 else if (*tok == '*')
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 == STRING || *tok == SYMBOL)
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(TOKEN * _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
530 while (*tk.u32 != ENDEXPR)
532 switch ((int)*tk.u32++)
535 //printf("evexpr(): SYMBOL\n");
536 sy = symbolPtr[*tk.u32++];
537 sy->sattr |= REFERENCED; // Set "referenced" bit
539 if (!(sy->sattr & DEFINED))
541 // Reference to undefined symbol
542 if (!(sy->sattr & GLOBAL))
549 if (esym != NULL) // Check for multiple externals
550 return error(seg_error);
555 if (sy->sattr & DEFINED)
557 *++sval = sy->svalue; // Push symbol's value
561 *++sval = 0; // 0 for undefined symbols
564 *++sattr = (WORD)(sy->sattr & ~GLOBAL); // Push attribs
565 sym_seg = (WORD)(sy->sattr & TDB);
569 //printf("evexpr(): CONST = %lX\n", *sval);
570 *++sattr = ABS | DEFINED; // Push simple attribs
573 //printf("evexpr(): FCONST = %i\n", *tk.u32);
574 *((double *)sval) = *((double *)tk.u32);
576 *++sattr = ABS | DEFINED | FLOAT; // Push simple attribs
579 //printf("evexpr(): ACONST = %i\n", *tk.u32);
580 *++sval = *tk.u32++; // Push value
581 *++sattr = (WORD)*tk.u32++; // Push attribs
584 // Binary "+" and "-" matrix:
587 // ----------------------------
588 // ABS | ABS | Sect | Other |
589 // Sect | Sect | [1] | Error |
590 // Other | Other | Error | [1] |
591 // ----------------------------
596 //printf("evexpr(): +\n");
598 --sattr; // Pop attrib
599 //printf("--> N+N: %i + %i = ", *sval, sval[1]);
600 // Extract float attributes from both terms and pack them
601 // into a single value
602 attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
603 attr2 = sattr[0] | sattr[1] & FLOAT; // Returns FLOAT if either of the two numbers are FLOAT
605 if (attr == (FLOAT | (FLOAT >> 1)))
608 double * dst = (double *)sval;
609 double * src = (double *)(sval + 1);
612 else if (attr == FLOAT)
615 double * dst = (double *)sval;
616 uint64_t * src = (uint64_t *)(sval + 1);
619 else if (attr == FLOAT >> 1)
622 uint64_t * dst = (uint64_t *)sval;
623 double * src = (double *)(sval + 1);
624 *(double *)dst = *src + *dst;
628 *sval += sval[1]; // Compute value
630 //printf("%i\n", *sval);
633 *sattr = sattr[1] | attr2;
634 else if (sattr[1] & TDB)
635 return error(seg_error);
639 //printf("evexpr(): -\n");
641 --sattr; // Pop attrib
642 //printf("--> N-N: %i - %i = ", *sval, sval[1]);
643 // Extract float attributes from both terms and pack them
644 // into a single value
645 attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
646 attr2 = sattr[0] | sattr[1] & FLOAT; // Returns FLOAT if either of the two numbers are FLOAT
648 if (attr == (FLOAT | (FLOAT >> 1)))
651 double * dst = (double *)sval;
652 double * src = (double *)(sval + 1);
655 else if (attr == FLOAT)
658 double * dst = (double *)sval;
659 uint64_t * src = (uint64_t *)(sval + 1);
662 else if (attr == FLOAT >> 1)
665 uint64_t * dst = (uint64_t *)sval;
666 double * src = (double *)(sval + 1);
667 *(double *)dst = *dst - *src;
671 *sval -= sval[1]; // Compute value
674 //printf("%i\n", *sval);
676 attr = (WORD)(*sattr & TDB);
678 printf("EVEXPR (-): sym1 = %X, sym2 = %X\n", attr, sattr[1]);
680 *sattr |= attr2; // Inherit FLOAT attribute
681 // If symbol1 is ABS, take attributes from symbol2
684 // Otherwise, they're both TDB and so attributes cancel out
685 else if (sattr[1] & TDB)
689 // Unary operators only work on ABS items
691 //printf("evexpr(): UNMINUS\n");
693 return error(seg_error);
697 double *dst = (double *)sval;
699 *sattr = ABS | DEFINED | FLOAT; // Expr becomes absolute
704 *sattr = ABS | DEFINED; // Expr becomes absolute
708 //printf("evexpr(): !\n");
710 return error(seg_error);
713 return error("floating point numbers not allowed with operator '!'.");
716 *sattr = ABS | DEFINED; // Expr becomes absolute
719 //printf("evexpr(): ~\n");
721 return error(seg_error);
724 return error("floating point numbers not allowed with operator '~'.");
727 *sattr = ABS | DEFINED; // Expr becomes absolute
729 // Comparison operators must have two values that
730 // are in the same segment, but that's the only requirement.
732 //printf("evexpr(): LE\n");
736 if ((*sattr & TDB) != (sattr[1] & TDB))
737 return error(seg_error);
739 // Extract float attributes from both terms and pack them
740 // into a single value
741 attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
743 if (attr == (FLOAT | (FLOAT >> 1)))
746 double * dst = (double *)sval;
747 double * src = (double *)(sval + 1);
748 *sval = *dst <= *src;
750 else if (attr == FLOAT)
753 double * dst = (double *)sval;
754 uint64_t * src = (uint64_t *)(sval + 1);
755 *sval = *dst <= *src;
757 else if (attr == FLOAT >> 1)
760 uint64_t * dst = (uint64_t *)sval;
761 double * src = (double *)(sval + 1);
762 *sval = *dst <= *src;
766 *sval = *sval <= sval[1];
769 *sattr = ABS | DEFINED;
772 //printf("evexpr(): GE\n");
776 if ((*sattr & TDB) != (sattr[1] & TDB))
777 return error(seg_error);
779 // Extract float attributes from both terms and pack them
780 // into a single value
781 attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
783 if (attr == (FLOAT | (FLOAT >> 1)))
786 double * dst = (double *)sval;
787 double * src = (double *)(sval + 1);
788 *sval = *dst >= *src;
790 else if (attr == FLOAT)
793 double * dst = (double *)sval;
794 uint64_t * src = (uint64_t *)(sval + 1);
795 *sval = *dst >= *src;
797 else if (attr == FLOAT >> 1)
800 uint64_t * dst = (uint64_t *)sval;
801 double * src = (double *)(sval + 1);
802 *sval = *dst >= *src;
806 *sval = *sval >= sval[1];
809 *sattr = ABS | DEFINED;
813 //printf("evexpr(): >\n");
817 if ((*sattr & TDB) != (sattr[1] & TDB))
818 return error(seg_error);
820 // Extract float attributes from both terms and pack them
821 // into a single value
822 attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
824 if (attr == (FLOAT | (FLOAT >> 1)))
827 double * dst = (double *)sval;
828 double * src = (double *)(sval + 1);
831 else if (attr == FLOAT)
834 double * dst = (double *)sval;
835 uint64_t * src = (uint64_t *)(sval + 1);
838 else if (attr == FLOAT >> 1)
841 uint64_t * dst = (uint64_t *)sval;
842 double * src = (double *)(sval + 1);
847 *sval = *sval > sval[1];
850 *sattr = ABS | DEFINED;
854 //printf("evexpr(): <\n");
858 if ((*sattr & TDB) != (sattr[1] & TDB))
859 return error(seg_error);
861 // Extract float attributes from both terms and pack them
862 // into a single value
863 attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
865 if (attr == (FLOAT | (FLOAT >> 1)))
868 double * dst = (double *)sval;
869 double * src = (double *)(sval + 1);
872 else if (attr == FLOAT)
875 double * dst = (double *)sval;
876 uint64_t * src = (uint64_t *)(sval + 1);
879 else if (attr == FLOAT >> 1)
882 uint64_t * dst = (uint64_t *)sval;
883 double * src = (double *)(sval + 1);
888 *sval = *sval < sval[1];
891 *sattr = ABS | DEFINED;
895 //printf("evexpr(): NE\n");
899 if ((*sattr & TDB) != (sattr[1] & TDB))
900 return error(seg_error);
902 // Extract float attributes from both terms and pack them
903 // into a single value
904 attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
906 if (attr == (FLOAT | (FLOAT >> 1)))
909 return error("comparison for equality with float types not allowed.");
911 else if (attr == FLOAT)
914 return error("comparison for equality with float types not allowed.");
916 else if (attr == FLOAT >> 1)
919 return error("comparison for equality with float types not allowed.");
923 *sval = *sval != sval[1];
926 *sattr = ABS | DEFINED;
930 //printf("evexpr(): =\n");
934 if ((*sattr & TDB) != (sattr[1] & TDB))
935 return error(seg_error);
937 // Extract float attributes from both terms and pack them
938 // into a single value
939 attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
941 if (attr == (FLOAT | (FLOAT >> 1)))
944 double * dst = (double *)sval;
945 double * src = (double *)(sval + 1);
946 *sval = *src == *dst;
948 else if (attr == FLOAT)
951 return error("equality with float ");
953 else if (attr == FLOAT >> 1)
956 uint64_t * dst = (uint64_t *)sval;
957 double * src = (double *)(sval + 1);
958 *sval = *src == *dst;
962 *sval = *sval == sval[1];
965 *sattr = ABS | DEFINED;
968 // All other binary operators must have two ABS items to work with.
969 // They all produce an ABS value.
971 //printf("evexpr(): default\n");
972 // GH - Removed for v1.0.15 as part of the fix for indexed loads.
973 //if ((*sattr & (TEXT|DATA|BSS)) || (*--sattr & (TEXT|DATA|BSS)))
976 switch ((int)tk.u32[-1])
980 sattr--; // Pop attrib
981 //printf("--> NxN: %i x %i = ", *sval, sval[1]);
982 // Extract float attributes from both terms and pack them
983 // into a single value
984 attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
985 attr2 = sattr[0] | sattr[1] & FLOAT; // Returns FLOAT if either of the two numbers are FLOAT
987 if (attr == (FLOAT | (FLOAT >> 1)))
990 double * dst = (double *)sval;
991 double * src = (double *)(sval + 1);
994 else if (attr == FLOAT)
997 double * dst = (double *)sval;
998 uint64_t * src = (uint64_t *)(sval + 1);
1001 else if (attr == FLOAT >> 1)
1004 uint64_t * dst = (uint64_t *)sval;
1005 double * src = (double *)(sval + 1);
1006 *(double *)dst = *src * *dst;
1012 //printf("%i\n", *sval);
1014 *sattr = ABS | DEFINED; // Expr becomes absolute
1020 sattr--; // Pop attrib
1023 //printf("--> N/N: %i / %i = ", sval[0], sval[1]);
1024 // Extract float attributes from both terms and pack them
1025 // into a single value
1026 attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
1027 attr2 = sattr[0] | sattr[1] & FLOAT; // Returns FLOAT if either of the two numbers are FLOAT
1029 if (attr == (FLOAT | (FLOAT >> 1)))
1032 double * dst = (double *)sval;
1033 double * src = (double *)(sval + 1);
1036 return error("divide by zero");
1040 else if (attr == FLOAT)
1043 double * dst = (double *)sval;
1044 uint64_t * src = (uint64_t *)(sval + 1);
1047 return error("divide by zero");
1051 else if (attr == FLOAT >> 1)
1054 uint64_t * dst=(uint64_t *)sval;
1055 double * src=(double *)(sval + 1);
1058 return error("divide by zero");
1060 *(double *)dst = *dst / *src;
1065 return error("divide by zero");
1066 //printf("--> N/N: %i / %i = ", sval[0], sval[1]);
1068 // Compiler is picky here: Without casting these, it
1069 // discards the sign if dividing a negative # by a
1070 // positive one, creating a bad result. :-/
1071 // Definitely a side effect of using uint32_ts intead of
1073 *sval = (int32_t)sval[0] / (int32_t)sval[1];
1076 *sattr = ABS | DEFINED; // Expr becomes absolute
1079 //printf("%i\n", *sval);
1083 sattr--; // Pop attrib
1085 if ((*sattr | sattr[1]) & FLOAT)
1086 return error("floating point numbers not allowed with operator '%'.");
1089 return error("mod (%) by zero");
1091 *sattr = ABS | DEFINED; // Expr becomes absolute
1096 sattr--; // Pop attrib
1098 if ((*sattr | sattr[1]) & FLOAT)
1099 return error("floating point numbers not allowed with operator '<<'.");
1101 *sattr = ABS | DEFINED; // Expr becomes absolute
1106 sattr--; // Pop attrib
1108 if ((*sattr | sattr[1]) & FLOAT)
1109 return error("floating point numbers not allowed with operator '>>'.");
1111 *sattr = ABS | DEFINED; // Expr becomes absolute
1116 sattr--; // Pop attrib
1118 if ((*sattr | sattr[1]) & FLOAT)
1119 return error("floating point numbers not allowed with operator '&'.");
1121 *sattr = ABS | DEFINED; // Expr becomes absolute
1126 sattr--; // Pop attrib
1128 if ((*sattr | sattr[1]) & FLOAT)
1129 return error("floating point numbers not allowed with operator '^'.");
1131 *sattr = ABS | DEFINED; // Expr becomes absolute
1136 sattr--; // Pop attrib
1138 if ((*sattr | sattr[1]) & FLOAT)
1139 return error("floating point numbers not allowed with operator '|'.");
1141 *sattr = ABS | DEFINED; // Expr becomes absolute
1145 interror(5); // Bad operator in expression stream
1156 // sym_seg added in 1.0.16 to solve a problem with forward symbols in
1157 // expressions where absolute values also existed. The absolutes were
1158 // overiding the symbol segments and not being included :(
1159 //*a_attr = *sattr | sym_seg; // Copy value + attrib
1161 *a_attr = *sattr; // Copy value + attrib