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 TOKEN * 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] >= MULT)
115 *evalTokenBuffer++ = t;
123 // Unary operators (detect unary '-')
124 // ggn: If expression starts with a plus then also eat it up.
125 // For some reason the parser gets confused when this happens and
126 // emits a "bad expression".
136 uint64_t * evalTokenBuffer64;
138 class = tokenClass[*tok];
140 if (*tok == '-' || *tok == '+' || class == UNARY)
150 // With leading + we don't have to deposit
151 // anything to the buffer because there's
152 // no unary '+' nor we have to do anything about it
154 *evalTokenBuffer++ = t;
156 else if (class == SUNARY)
161 *evalTokenBuffer++ = CONST;
162 evalTokenBuffer64 = (uint64_t *)evalTokenBuffer;
163 *evalTokenBuffer64++ = (LONG)sect[ABS].sloc;
164 evalTokenBuffer = (uint32_t *)evalTokenBuffer64;
167 *evalTokenBuffer++ = CONST;
168 evalTokenBuffer64 = (uint64_t *)evalTokenBuffer;
169 *evalTokenBuffer64++ = dos_time();
170 evalTokenBuffer = (uint32_t *)evalTokenBuffer64;
173 *evalTokenBuffer++ = CONST;
174 evalTokenBuffer64 = (uint64_t *)evalTokenBuffer;
175 *evalTokenBuffer64++ = dos_date();
176 evalTokenBuffer = (uint32_t *)evalTokenBuffer64;
178 case CR_MACDEF: // ^^macdef <macro-name>
179 if (*tok++ != SYMBOL)
180 return error(missym_error);
183 w = (lookup(p, MACRO, 0) == NULL ? 0 : 1);
184 evalTokenBuffer64 = (uint64_t *)evalTokenBuffer;
185 *evalTokenBuffer64++ = (TOKEN)w;
186 evalTokenBuffer = (uint32_t *)evalTokenBuffer64;
187 *evalTokenBuffer++ = (TOKEN)w;
195 if (*tok++ != SYMBOL)
196 return error(missym_error);
199 j = (*p == '.' ? curenv : 0);
200 w = ((sy = lookup(p, LABEL, j)) != NULL && (sy->sattr & w) ? 1 : 0);
201 *evalTokenBuffer++ = CONST;
202 uint64_t *evalTokenBuffer64 = (uint64_t *)evalTokenBuffer;
203 *evalTokenBuffer64++ = (TOKEN)w;
204 evalTokenBuffer = (uint32_t *)evalTokenBuffer64;
207 if (*tok != SYMBOL && *tok != STRING)
208 return error(str_error);
214 return error(comma_error);
216 if (*tok != SYMBOL && *tok != STRING)
217 return error(str_error);
222 w = (WORD)(!strcmp(p, p2));
223 *evalTokenBuffer++ = CONST;
224 evalTokenBuffer64 = (uint64_t *)evalTokenBuffer;
225 *evalTokenBuffer64++ = (TOKEN)w;
226 evalTokenBuffer = (uint32_t *)evalTokenBuffer64;
238 // Terminals (CONSTs) and parenthesis grouping
245 uint64_t * evalTokenBuffer64;
251 *evalTokenBuffer++ = CONST;
252 evalTokenBuffer64 = (uint64_t *)evalTokenBuffer;
253 tok64 = (uint64_t *)tok;
254 *evalTokenBuffer64++ = *tok64++;
255 tok = (TOKEN *)tok64;
256 evalTokenBuffer = (TOKEN *)evalTokenBuffer64;
259 *evalTokenBuffer++ = FCONST;
260 evalTokenBuffer64 = (uint64_t *)evalTokenBuffer;
261 tok64 = (uint64_t *)tok;
262 *evalTokenBuffer64++ = *tok64++;
263 tok = (TOKEN *)tok64;
264 evalTokenBuffer = (TOKEN *)evalTokenBuffer64;
268 j = (*p == '.' ? curenv : 0);
269 sy = lookup(p, LABEL, j);
272 sy = NewSymbol(p, LABEL, j);
274 // Check register bank usage
275 if (sy->sattre & EQUATEDREG)
277 if ((regbank == BANK_0) && (sy->sattre & BANK_1) && !altbankok)
278 warn("equated symbol \'%s\' cannot be used in register bank 0", sy->sname);
280 if ((regbank == BANK_1) && (sy->sattre & BANK_0) && !altbankok)
281 warn("equated symbol \'%s\' cannot be used in register bank 1", sy->sname);
284 *evalTokenBuffer++ = SYMBOL;
285 *evalTokenBuffer++ = symbolNum;
286 symbolPtr[symbolNum] = sy;
290 *evalTokenBuffer++ = CONST;
291 uint64_t *evalTokenBuffer64 = (uint64_t *)evalTokenBuffer;
292 *evalTokenBuffer64++ = str_value(string[*tok++]);
293 evalTokenBuffer = (uint32_t *)evalTokenBuffer64;
300 return error("missing closing parenthesis ')'");
308 return error("missing closing bracket ']'");
312 *evalTokenBuffer++ = ACONST; // Attributed const
313 *evalTokenBuffer++ = sloc; // Current location
314 *evalTokenBuffer++ = cursect | DEFINED; // Store attribs
317 *evalTokenBuffer++ = ACONST; // Attributed const
319 // pcloc == location at start of line
320 *evalTokenBuffer++ = (orgactive ? orgaddr : pcloc);
321 // '*' takes attributes of current section, not ABS!
322 *evalTokenBuffer++ = cursect | DEFINED;
325 if (expr0() != OK) // Eat up first parameter (register or immediate)
328 if (*tok++ != ':') // Demand a ':' there
329 return error("missing colon ':'");
331 if (expr0() != OK) // Eat up second parameter (register or immediate)
335 return error("missing closing brace '}'");
339 return error("bad expression");
347 // Recursive-descent expression analyzer (with some simple speed hacks)
349 int expr(TOKEN * otk, uint64_t * a_value, WORD * a_attr, SYM ** a_esym)
351 // Passed in values (once derefenced, that is) can all be zero. They are
352 // there so that the expression analyzer can fill them in as needed. The
353 // expression analyzer gets its input from the global token pointer "tok",
354 // and not from anything passed in by the user.
359 evalTokenBuffer = otk; // Set token pointer to 'exprbuf' (direct.c)
360 // Also set in various other places too (riscasm.c,
363 //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]]);
364 // Optimize for single constant or single symbol.
365 // Shamus: Subtle bug here. EOL token is 101; if you have a constant token
366 // followed by the value 101, it will trigger a bad evaluation here.
367 // This is probably a really bad assumption to be making here...!
368 // (assuming tok[1] == EOL is a single token that is)
369 // Seems that even other tokens (SUNARY type) can fuck this up too.
370 // if ((tok[1] == EOL)
371 if ((tok[1] == EOL && ((tok[0] != CONST || tok[0] != FCONST) && tokenClass[tok[0]] != SUNARY))
372 // || (((*tok == CONST || *tok == FCONST || *tok == SYMBOL) || (*tok >= KW_R0 && *tok <= KW_R31))
373 // && (tokenClass[tok[2]] < UNARY)))
374 || (((tok[0] == SYMBOL) || (tok[0] >= KW_R0 && tok[0] <= KW_R31))
375 && (tokenClass[tok[2]] < UNARY))
376 || ((tok[0] == CONST || tok[0] == FCONST) && (tokenClass[tok[3]] < UNARY))
379 if (*tok >= KW_R0 && *tok <= KW_R31)
381 *evalTokenBuffer++ = CONST;
382 uint64_t *evalTokenBuffer64 = (uint64_t *)evalTokenBuffer;
383 *evalTokenBuffer64++ = *a_value = (*tok - KW_R0);
384 evalTokenBuffer = (uint32_t *)evalTokenBuffer64;
385 *a_attr = ABS | DEFINED;
392 else if (*tok == CONST)
394 *evalTokenBuffer++ = CONST;
395 uint64_t *evalTokenBuffer64 = (uint64_t *)evalTokenBuffer;
396 uint64_t *tok64 = (uint64_t *)&tok[1];
397 *evalTokenBuffer64++ = *tok64++;
398 evalTokenBuffer = (TOKEN *)evalTokenBuffer64;
400 *a_attr = ABS | DEFINED;
406 //printf("Quick eval in expr(): CONST = %i, tokenClass[tok[2]] = %i\n", *a_value, tokenClass[*tok]);
408 else if (*tok == FCONST)
410 *evalTokenBuffer++ = FCONST;
411 *((double *)evalTokenBuffer) = *((double *)&tok[1]);
412 evalTokenBuffer += 2;
413 //*(double *)evalTokenBuffer++ = tok[2];
414 *a_value = *((uint64_t *)&tok[1]);
415 *a_attr = ABS | DEFINED | FLOAT;
421 //printf("Quick eval in expr(): CONST = %i, tokenClass[tok[2]] = %i\n", *a_value, tokenClass[*tok]);
423 else if (*tok == '*')
425 *evalTokenBuffer++ = CONST;
426 uint64_t *evalTokenBuffer64 = (uint64_t *)evalTokenBuffer;
429 *evalTokenBuffer64++ = *a_value = orgaddr;
431 *evalTokenBuffer64++ = *a_value = pcloc;
432 evalTokenBuffer = (uint32_t *)evalTokenBuffer64;
434 // '*' takes attributes of current section, not ABS!
435 *a_attr = cursect | DEFINED;
442 else if (*tok == STRING || *tok == SYMBOL)
445 j = (*p == '.' ? curenv : 0);
446 symbol = lookup(p, LABEL, j);
448 printf("eval: Looking up symbol (%s) [=%08X]\n", p, symbol);
450 printf(" attr=%04X, attre=%08X, val=%i, name=%s\n", symbol->sattr, symbol->sattre, symbol->svalue, symbol->sname);
454 symbol = NewSymbol(p, LABEL, j);
456 symbol->sattr |= REFERENCED;
458 // Check for undefined register equates, but only if it's not part
459 // of a #<SYMBOL> construct, as it could be that the label that's
460 // been undefined may later be used as an address label--which
461 // means it will be fixed up later, and thus, not an error.
462 if ((symbol->sattre & UNDEF_EQUR) && !riscImmTokenSeen)
464 error("undefined register equate '%s'", symbol->sname);
465 //if we return right away, it returns some spurious errors...
469 // Check register bank usage
470 if (symbol->sattre & EQUATEDREG)
472 if ((regbank == BANK_0) && (symbol->sattre & BANK_1) && !altbankok)
473 warn("equated symbol '%s' cannot be used in register bank 0", symbol->sname);
475 if ((regbank == BANK_1) && (symbol->sattre & BANK_0) && !altbankok)
476 warn("equated symbol '%s' cannot be used in register bank 1", symbol->sname);
479 *evalTokenBuffer++ = SYMBOL;
481 *evalTokenBuffer++ = (TOKEN)symbol;
484 While this approach works, it's wasteful. It would be better to use something
485 that's already available, like the symbol "order defined" table (which needs to
486 be converted from a linked list into an array).
488 *evalTokenBuffer++ = symbolNum;
489 symbolPtr[symbolNum] = symbol;
493 if (symbol->sattr & DEFINED)
494 *a_value = symbol->svalue;
499 All that extra crap that was put into the svalue when doing the equr stuff is
500 thrown away right here. What the hell is it for?
502 if (symbol->sattre & EQUATEDREG)
505 *a_attr = (WORD)(symbol->sattr & ~GLOBAL);
507 if ((symbol->sattr & (GLOBAL | DEFINED)) == GLOBAL
515 // Unknown type here... Alert the user!,
516 error("undefined RISC register in expression");
517 // Prevent spurious error reporting...
522 *evalTokenBuffer++ = ENDEXPR;
529 *evalTokenBuffer++ = ENDEXPR;
530 return evexpr(otk, a_value, a_attr, a_esym);
535 // Evaluate expression.
536 // If the expression involves only ONE external symbol, the expression is
537 // UNDEFINED, but it's value includes everything but the symbol value, and
538 // `a_esym' is set to the external symbol.
540 int evexpr(TOKEN * tk, uint64_t * a_value, WORD * a_attr, SYM ** a_esym)
544 uint64_t * sval = evstk; // (Empty) initial stack
545 WORD * sattr = evattr;
546 SYM * esym = NULL; // No external symbol involved
550 while (*tk != ENDEXPR)
555 //printf("evexpr(): SYMBOL\n");
556 sy = symbolPtr[*tk++];
557 sy->sattr |= REFERENCED; // Set "referenced" bit
559 if (!(sy->sattr & DEFINED))
561 // Reference to undefined symbol
562 if (!(sy->sattr & GLOBAL))
569 if (esym != NULL) // Check for multiple externals
570 return error(seg_error);
575 if (sy->sattr & DEFINED)
577 *++sval = sy->svalue; // Push symbol's value
581 *++sval = 0; // 0 for undefined symbols
584 *++sattr = (WORD)(sy->sattr & ~GLOBAL); // Push attribs
585 sym_seg = (WORD)(sy->sattr & TDB);
588 tk64 = (uint64_t *)tk;
591 //printf("evexpr(): CONST = %lX\n", *sval);
592 *++sattr = ABS | DEFINED; // Push simple attribs
595 //printf("evexpr(): CONST = %i\n", *tk);
596 *((double *)sval) = *((double *)tk);
598 *++sattr = ABS | DEFINED | FLOAT; // Push simple attribs
601 //printf("evexpr(): ACONST = %i\n", *tk);
602 *++sval = *tk++; // Push value
603 *++sattr = (WORD)*tk++; // Push attribs
606 // Binary "+" and "-" matrix:
609 // ----------------------------
610 // ABS | ABS | Sect | Other |
611 // Sect | Sect | [1] | Error |
612 // Other | Other | Error | [1] |
613 // ----------------------------
618 //printf("evexpr(): +\n");
620 --sattr; // Pop attrib
621 //printf("--> N+N: %i + %i = ", *sval, sval[1]);
622 // Extract float attributes from both terms and pack them
623 // into a single value
624 attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
625 attr2 = sattr[0] | sattr[1] & FLOAT; // Returns FLOAT if either of the two numbers are FLOAT
627 if (attr == (FLOAT | (FLOAT >> 1)))
630 double * dst = (double *)sval;
631 double * src = (double *)(sval + 1);
634 else if (attr == FLOAT)
637 double * dst = (double *)sval;
638 uint64_t * src = (uint64_t *)(sval + 1);
641 else if (attr == FLOAT >> 1)
644 uint64_t * dst = (uint64_t *)sval;
645 double * src = (double *)(sval + 1);
646 *(double *)dst = *src + *dst;
650 *sval += sval[1]; // Compute value
652 //printf("%i\n", *sval);
655 *sattr = sattr[1] | attr2;
656 else if (sattr[1] & TDB)
657 return error(seg_error);
661 //printf("evexpr(): -\n");
663 --sattr; // Pop attrib
664 //printf("--> N-N: %i - %i = ", *sval, sval[1]);
665 // Extract float attributes from both terms and pack them
666 // into a single value
667 attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
668 attr2 = sattr[0] | sattr[1] & FLOAT; // Returns FLOAT if either of the two numbers are FLOAT
670 if (attr == (FLOAT | (FLOAT >> 1)))
673 double * dst = (double *)sval;
674 double * src = (double *)(sval + 1);
677 else if (attr == FLOAT)
680 double * dst = (double *)sval;
681 uint64_t * src = (uint64_t *)(sval + 1);
684 else if (attr == FLOAT >> 1)
687 uint64_t * dst = (uint64_t *)sval;
688 double * src = (double *)(sval + 1);
689 *(double *)dst = *dst - *src;
693 *sval -= sval[1]; // Compute value
696 //printf("%i\n", *sval);
698 attr = (WORD)(*sattr & TDB);
700 printf("EVEXPR (-): sym1 = %X, sym2 = %X\n", attr, sattr[1]);
702 *sattr |= attr2; // Inherit FLOAT attribute
703 // If symbol1 is ABS, take attributes from symbol2
706 // Otherwise, they're both TDB and so attributes cancel out
707 else if (sattr[1] & TDB)
711 // Unary operators only work on ABS items
713 //printf("evexpr(): UNMINUS\n");
715 return error(seg_error);
719 double *dst = (double *)sval;
721 *sattr = ABS | DEFINED | FLOAT; // Expr becomes absolute
726 *sattr = ABS | DEFINED; // Expr becomes absolute
730 //printf("evexpr(): !\n");
732 return error(seg_error);
735 return error("floating point numbers not allowed with operator '!'.");
738 *sattr = ABS | DEFINED; // Expr becomes absolute
741 //printf("evexpr(): ~\n");
743 return error(seg_error);
746 return error("floating point numbers not allowed with operator '~'.");
749 *sattr = ABS | DEFINED; // Expr becomes absolute
751 // Comparison operators must have two values that
752 // are in the same segment, but that's the only requirement.
754 //printf("evexpr(): LE\n");
758 if ((*sattr & TDB) != (sattr[1] & TDB))
759 return error(seg_error);
761 // Extract float attributes from both terms and pack them
762 // into a single value
763 attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
765 if (attr == (FLOAT | (FLOAT >> 1)))
768 double * dst = (double *)sval;
769 double * src = (double *)(sval + 1);
770 *sval = *dst <= *src;
772 else if (attr == FLOAT)
775 double * dst = (double *)sval;
776 uint64_t * src = (uint64_t *)(sval + 1);
777 *sval = *dst <= *src;
779 else if (attr == FLOAT >> 1)
782 uint64_t * dst = (uint64_t *)sval;
783 double * src = (double *)(sval + 1);
784 *sval = *dst <= *src;
788 *sval = *sval <= sval[1];
791 *sattr = ABS | DEFINED;
794 //printf("evexpr(): GE\n");
798 if ((*sattr & TDB) != (sattr[1] & TDB))
799 return error(seg_error);
801 // Extract float attributes from both terms and pack them
802 // into a single value
803 attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
805 if (attr == (FLOAT | (FLOAT >> 1)))
808 double * dst = (double *)sval;
809 double * src = (double *)(sval + 1);
810 *sval = *dst >= *src;
812 else if (attr == FLOAT)
815 double * dst = (double *)sval;
816 uint64_t * src = (uint64_t *)(sval + 1);
817 *sval = *dst >= *src;
819 else if (attr == FLOAT >> 1)
822 uint64_t * dst = (uint64_t *)sval;
823 double * src = (double *)(sval + 1);
824 *sval = *dst >= *src;
828 *sval = *sval >= sval[1];
832 *sattr = ABS | DEFINED;
836 //printf("evexpr(): >\n");
840 if ((*sattr & TDB) != (sattr[1] & TDB))
841 return error(seg_error);
843 // Extract float attributes from both terms and pack them
844 // into a single value
845 attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
847 if (attr == (FLOAT | (FLOAT >> 1)))
850 double * dst = (double *)sval;
851 double * src = (double *)(sval + 1);
854 else if (attr == FLOAT)
857 double * dst = (double *)sval;
858 uint64_t * src = (uint64_t *)(sval + 1);
861 else if (attr == FLOAT >> 1)
864 uint64_t * dst = (uint64_t *)sval;
865 double * src = (double *)(sval + 1);
870 *sval = *sval > sval[1];
873 *sattr = ABS | DEFINED;
877 //printf("evexpr(): <\n");
881 if ((*sattr & TDB) != (sattr[1] & TDB))
882 return error(seg_error);
884 // Extract float attributes from both terms and pack them
885 // into a single value
886 attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) > >1);
888 if (attr == (FLOAT | (FLOAT >> 1)))
891 double * dst = (double *)sval;
892 double * src = (double *)(sval + 1);
895 else if (attr == FLOAT)
898 double * dst = (double *)sval;
899 uint64_t * src = (uint64_t *)(sval + 1);
902 else if (attr == FLOAT >> 1)
905 uint64_t * dst = (uint64_t *)sval;
906 double * src = (double *)(sval + 1);
911 *sval = *sval < sval[1];
914 *sattr = ABS | DEFINED;
918 //printf("evexpr(): NE\n");
922 if ((*sattr & TDB) != (sattr[1] & TDB))
923 return error(seg_error);
925 // Extract float attributes from both terms and pack them
926 // into a single value
927 attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
929 if (attr == (FLOAT | (FLOAT >> 1)))
932 return error("comparison for equality with float types not allowed.");
934 else if (attr == FLOAT)
937 return error("comparison for equality with float types not allowed.");
939 else if (attr == FLOAT >> 1)
942 return error("comparison for equality with float types not allowed.");
946 *sval = *sval != sval[1];
949 *sattr = ABS | DEFINED;
953 //printf("evexpr(): =\n");
957 if ((*sattr & TDB) != (sattr[1] & TDB))
958 return error(seg_error);
960 // Extract float attributes from both terms and pack them
961 // into a single value
962 attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
964 if (attr == (FLOAT | (FLOAT >> 1)))
967 double * dst = (double *)sval;
968 double * src = (double *)(sval + 1);
969 *sval = *src == *dst;
971 else if (attr == FLOAT)
974 return error("equality with float ");
976 else if (attr == FLOAT >> 1)
979 uint64_t * dst = (uint64_t *)sval;
980 double * src = (double *)(sval + 1);
981 *sval = *src == *dst;
985 *sval = *sval == sval[1];
988 *sattr = ABS | DEFINED;
991 // All other binary operators must have two ABS items
992 // to work with. They all produce an ABS value.
994 //printf("evexpr(): default\n");
995 // GH - Removed for v1.0.15 as part of the fix for indexed loads.
996 //if ((*sattr & (TEXT|DATA|BSS)) || (*--sattr & (TEXT|DATA|BSS)))
1003 sattr--; // Pop attrib
1004 //printf("--> NxN: %i x %i = ", *sval, sval[1]);
1005 // Extract float attributes from both terms and pack them
1006 // into a single value
1007 attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
1008 attr2 = sattr[0] | sattr[1] & FLOAT; // Returns FLOAT if either of the two numbers are FLOAT
1010 if (attr == (FLOAT | (FLOAT >> 1)))
1013 double * dst = (double *)sval;
1014 double * src = (double *)(sval + 1);
1017 else if (attr == FLOAT)
1020 double * dst = (double *)sval;
1021 uint64_t * src = (uint64_t *)(sval + 1);
1024 else if (attr == FLOAT >> 1)
1027 uint64_t * dst = (uint64_t *)sval;
1028 double * src = (double *)(sval + 1);
1029 *(double *)dst = *src * *dst;
1035 //printf("%i\n", *sval);
1037 *sattr = ABS | DEFINED; // Expr becomes absolute
1043 sattr--; // Pop attrib
1046 //printf("--> N/N: %i / %i = ", sval[0], sval[1]);
1047 // Extract float attributes from both terms and pack them
1048 // into a single value
1049 attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
1050 attr2 = sattr[0] | sattr[1] & FLOAT; // Returns FLOAT if either of the two numbers are FLOAT
1052 if (attr == (FLOAT | (FLOAT >> 1)))
1055 double * dst = (double *)sval;
1056 double * src = (double *)(sval + 1);
1058 return error("divide by zero");
1061 else if (attr == FLOAT)
1064 double * dst = (double *)sval;
1065 uint64_t * src = (uint64_t *)(sval + 1);
1067 return error("divide by zero");
1070 else if (attr == FLOAT >> 1)
1073 uint64_t * dst=(uint64_t *)sval;
1074 double * src=(double *)(sval + 1);
1076 return error("divide by zero");
1077 *(double *)dst = *dst / *src;
1082 return error("divide by zero");
1083 //printf("--> N/N: %i / %i = ", sval[0], sval[1]);
1084 // Compiler is picky here: Without casting these, it discards
1085 // the sign if dividing a negative # by a positive one,
1086 // creating a bad result. :-/
1087 // Definitely a side effect of using uint32_ts intead of ints.
1088 *sval = (int32_t)sval[0] / (int32_t)sval[1];
1091 *sattr = ABS | DEFINED; // Expr becomes absolute
1094 //printf("%i\n", *sval);
1098 sattr--; // Pop attrib
1099 if ((*sattr | sattr[1]) & FLOAT)
1100 return error("floating point numbers not allowed with operator '%'.");
1103 return error("mod (%) by zero");
1105 *sattr = ABS | DEFINED; // Expr becomes absolute
1110 sattr--; // Pop attrib
1111 if ((*sattr | sattr[1]) & FLOAT)
1112 return error("floating point numbers not allowed with operator '<<'.");
1113 *sattr = ABS | DEFINED; // Expr becomes absolute
1118 sattr--; // Pop attrib
1119 if ((*sattr | sattr[1]) & FLOAT)
1120 return error("floating point numbers not allowed with operator '>>'.");
1121 *sattr = ABS | DEFINED; // Expr becomes absolute
1126 sattr--; // Pop attrib
1127 if ((*sattr | sattr[1]) & FLOAT)
1128 return error("floating point numbers not allowed with operator '&'.");
1129 *sattr = ABS | DEFINED; // Expr becomes absolute
1134 sattr--; // Pop attrib
1135 if ((*sattr | sattr[1]) & FLOAT)
1136 return error("floating point numbers not allowed with operator '^'.");
1137 *sattr = ABS | DEFINED; // Expr becomes absolute
1142 sattr--; // Pop attrib
1143 if ((*sattr | sattr[1]) & FLOAT)
1144 return error("floating point numbers not allowed with operator '|'.");
1145 *sattr = ABS | DEFINED; // Expr becomes absolute
1149 interror(5); // Bad operator in expression stream
1160 // sym_seg added in 1.0.16 to solve a problem with forward symbols in
1161 // expressions where absolute values also existed. The absolutes were
1162 // overiding the symbol segments and not being included :(
1163 //*a_attr = *sattr | sym_seg; // Copy value + attrib
1165 *a_attr = *sattr; // Copy value + attrib