eval: Use nasm_error helpers
[nasm.git] / asm / eval.c
blob3a87d2c229dc45b0ac0c5bc3f19346a8730ceb7b
1 /* ----------------------------------------------------------------------- *
3 * Copyright 1996-2018 The NASM Authors - All Rights Reserved
4 * See the file AUTHORS included with the NASM distribution for
5 * the specific copyright holders.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following
9 * conditions are met:
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
19 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
20 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 * ----------------------------------------------------------------------- */
35 * eval.c expression evaluator for the Netwide Assembler
38 #include "compiler.h"
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <stddef.h>
43 #include <string.h>
44 #include <ctype.h>
46 #include "nasm.h"
47 #include "nasmlib.h"
48 #include "ilog2.h"
49 #include "error.h"
50 #include "eval.h"
51 #include "labels.h"
52 #include "float.h"
53 #include "assemble.h"
55 #define TEMPEXPRS_DELTA 128
56 #define TEMPEXPR_DELTA 8
58 static scanner scanfunc; /* Address of scanner routine */
59 static void *scpriv; /* Scanner private pointer */
61 static expr **tempexprs = NULL;
62 static int ntempexprs;
63 static int tempexprs_size = 0;
65 static expr *tempexpr;
66 static int ntempexpr;
67 static int tempexpr_size;
69 static struct tokenval *tokval; /* The current token */
70 static int tt; /* The t_type of tokval */
72 static int critical;
73 static int *opflags;
75 static struct eval_hints *hint;
76 static int64_t deadman;
80 * Unimportant cleanup is done to avoid confusing people who are trying
81 * to debug real memory leaks
83 void eval_cleanup(void)
85 while (ntempexprs)
86 nasm_free(tempexprs[--ntempexprs]);
87 nasm_free(tempexprs);
91 * Construct a temporary expression.
93 static void begintemp(void)
95 tempexpr = NULL;
96 tempexpr_size = ntempexpr = 0;
99 static void addtotemp(int32_t type, int64_t value)
101 while (ntempexpr >= tempexpr_size) {
102 tempexpr_size += TEMPEXPR_DELTA;
103 tempexpr = nasm_realloc(tempexpr,
104 tempexpr_size * sizeof(*tempexpr));
106 tempexpr[ntempexpr].type = type;
107 tempexpr[ntempexpr++].value = value;
110 static expr *finishtemp(void)
112 addtotemp(0L, 0L); /* terminate */
113 while (ntempexprs >= tempexprs_size) {
114 tempexprs_size += TEMPEXPRS_DELTA;
115 tempexprs = nasm_realloc(tempexprs,
116 tempexprs_size * sizeof(*tempexprs));
118 return tempexprs[ntempexprs++] = tempexpr;
122 * Add two vector datatypes. We have some bizarre behaviour on far-
123 * absolute segment types: we preserve them during addition _only_
124 * if one of the segments is a truly pure scalar.
126 static expr *add_vectors(expr * p, expr * q)
128 int preserve;
130 preserve = is_really_simple(p) || is_really_simple(q);
132 begintemp();
134 while (p->type && q->type &&
135 p->type < EXPR_SEGBASE + SEG_ABS &&
136 q->type < EXPR_SEGBASE + SEG_ABS) {
137 int lasttype;
139 if (p->type > q->type) {
140 addtotemp(q->type, q->value);
141 lasttype = q++->type;
142 } else if (p->type < q->type) {
143 addtotemp(p->type, p->value);
144 lasttype = p++->type;
145 } else { /* *p and *q have same type */
146 int64_t sum = p->value + q->value;
147 if (sum) {
148 addtotemp(p->type, sum);
149 if (hint)
150 hint->type = EAH_SUMMED;
152 lasttype = p->type;
153 p++, q++;
155 if (lasttype == EXPR_UNKNOWN) {
156 return finishtemp();
159 while (p->type && (preserve || p->type < EXPR_SEGBASE + SEG_ABS)) {
160 addtotemp(p->type, p->value);
161 p++;
163 while (q->type && (preserve || q->type < EXPR_SEGBASE + SEG_ABS)) {
164 addtotemp(q->type, q->value);
165 q++;
168 return finishtemp();
172 * Multiply a vector by a scalar. Strip far-absolute segment part
173 * if present.
175 * Explicit treatment of UNKNOWN is not required in this routine,
176 * since it will silently do the Right Thing anyway.
178 * If `affect_hints' is set, we also change the hint type to
179 * NOTBASE if a MAKEBASE hint points at a register being
180 * multiplied. This allows [eax*1+ebx] to hint EBX rather than EAX
181 * as the base register.
183 static expr *scalar_mult(expr * vect, int64_t scalar, int affect_hints)
185 expr *p = vect;
187 while (p->type && p->type < EXPR_SEGBASE + SEG_ABS) {
188 p->value = scalar * (p->value);
189 if (hint && hint->type == EAH_MAKEBASE &&
190 p->type == hint->base && affect_hints)
191 hint->type = EAH_NOTBASE;
192 p++;
194 p->type = 0;
196 return vect;
199 static expr *scalarvect(int64_t scalar)
201 begintemp();
202 addtotemp(EXPR_SIMPLE, scalar);
203 return finishtemp();
206 static expr *unknown_expr(void)
208 begintemp();
209 addtotemp(EXPR_UNKNOWN, 1L);
210 return finishtemp();
214 * The SEG operator: calculate the segment part of a relocatable
215 * value. Return NULL, as usual, if an error occurs. Report the
216 * error too.
218 static expr *segment_part(expr * e)
220 int32_t seg;
222 if (is_unknown(e))
223 return unknown_expr();
225 if (!is_reloc(e)) {
226 nasm_nonfatal("cannot apply SEG to a non-relocatable value");
227 return NULL;
230 seg = reloc_seg(e);
231 if (seg == NO_SEG) {
232 nasm_nonfatal("cannot apply SEG to a non-relocatable value");
233 return NULL;
234 } else if (seg & SEG_ABS) {
235 return scalarvect(seg & ~SEG_ABS);
236 } else if (seg & 1) {
237 nasm_nonfatal("SEG applied to something which"
238 " is already a segment base");
239 return NULL;
240 } else {
241 int32_t base = ofmt->segbase(seg + 1);
243 begintemp();
244 addtotemp((base == NO_SEG ? EXPR_UNKNOWN : EXPR_SEGBASE + base),
245 1L);
246 return finishtemp();
251 * Recursive-descent parser. Called with a single boolean operand,
252 * which is true if the evaluation is critical (i.e. unresolved
253 * symbols are an error condition). Must update the global `tt' to
254 * reflect the token after the parsed string. May return NULL.
256 * evaluate() should report its own errors: on return it is assumed
257 * that if NULL has been returned, the error has already been
258 * reported.
263 * Wrapper function around the scanner
265 static int scan(void)
267 return tt = scanfunc(scpriv, tokval);
271 * Grammar parsed is:
273 * expr : bexpr [ WRT expr6 ]
274 * bexpr : cexpr
275 * cexpr : rexp0 [ {?} bexpr {:} cexpr ]
276 * rexp0 : rexp1 [ {||} rexp1...]
277 * rexp1 : rexp2 [ {^^} rexp2...]
278 * rexp2 : rexp3 [ {&&} rexp3...]
279 * rexp3 : expr0 [ {=,==,<>,!=,<,>,<=,>=,<=>} expr0... ]
280 * expr0 : expr1 [ {|} expr1...]
281 * expr1 : expr2 [ {^} expr2...]
282 * expr2 : expr3 [ {&} expr3...]
283 * expr3 : expr4 [ {<<,>>,<<<,>>>} expr4...]
284 * expr4 : expr5 [ {+,-} expr5...]
285 * expr5 : expr6 [ {*,/,%,//,%%} expr6...]
286 * expr6 : { ~,+,-,IFUNC,SEG } expr6
287 * | (bexpr)
288 * | symbol
289 * | $
290 * | number
293 static expr *cexpr(void);
294 static expr *rexp0(void), *rexp1(void), *rexp2(void), *rexp3(void);
296 static expr *expr0(void), *expr1(void), *expr2(void), *expr3(void);
297 static expr *expr4(void), *expr5(void), *expr6(void);
299 /* This inline is a placeholder for the root of the basic expression */
300 static inline expr *bexpr(void)
302 return cexpr();
305 static expr *cexpr(void)
307 expr *e, *f, *g;
309 e = rexp0();
310 if (!e)
311 return NULL;
313 if (tt == '?') {
314 scan();
315 f = bexpr();
316 if (!f)
317 return NULL;
319 if (tt != ':') {
320 nasm_nonfatal("`?' without matching `:'");
321 return NULL;
324 scan();
325 g = cexpr();
326 if (!g)
327 return NULL;
329 if (is_simple(e)) {
330 e = reloc_value(e) ? f : g;
331 } else if (is_just_unknown(e)) {
332 e = unknown_expr();
333 } else {
334 nasm_nonfatal("the left-hand side of `?' must be "
335 "a scalar value");
339 return e;
342 static expr *rexp0(void)
344 expr *e, *f;
346 e = rexp1();
347 if (!e)
348 return NULL;
350 while (tt == TOKEN_DBL_OR) {
351 scan();
352 f = rexp1();
353 if (!f)
354 return NULL;
355 if (!(is_simple(e) || is_just_unknown(e)) ||
356 !(is_simple(f) || is_just_unknown(f))) {
357 nasm_nonfatal("`|' operator may only be applied to"
358 " scalar values");
361 if (is_just_unknown(e) || is_just_unknown(f))
362 e = unknown_expr();
363 else
364 e = scalarvect((int64_t)(reloc_value(e) || reloc_value(f)));
366 return e;
369 static expr *rexp1(void)
371 expr *e, *f;
373 e = rexp2();
374 if (!e)
375 return NULL;
377 while (tt == TOKEN_DBL_XOR) {
378 scan();
379 f = rexp2();
380 if (!f)
381 return NULL;
382 if (!(is_simple(e) || is_just_unknown(e)) ||
383 !(is_simple(f) || is_just_unknown(f))) {
384 nasm_nonfatal("`^' operator may only be applied to"
385 " scalar values");
388 if (is_just_unknown(e) || is_just_unknown(f))
389 e = unknown_expr();
390 else
391 e = scalarvect((int64_t)(!reloc_value(e) ^ !reloc_value(f)));
393 return e;
396 static expr *rexp2(void)
398 expr *e, *f;
400 e = rexp3();
401 if (!e)
402 return NULL;
403 while (tt == TOKEN_DBL_AND) {
404 scan();
405 f = rexp3();
406 if (!f)
407 return NULL;
408 if (!(is_simple(e) || is_just_unknown(e)) ||
409 !(is_simple(f) || is_just_unknown(f))) {
410 nasm_nonfatal("`&' operator may only be applied to"
411 " scalar values");
413 if (is_just_unknown(e) || is_just_unknown(f))
414 e = unknown_expr();
415 else
416 e = scalarvect((int64_t)(reloc_value(e) && reloc_value(f)));
418 return e;
421 static expr *rexp3(void)
423 expr *e, *f;
424 int64_t v;
426 e = expr0();
427 if (!e)
428 return NULL;
430 while (tt == TOKEN_EQ || tt == TOKEN_LT || tt == TOKEN_GT ||
431 tt == TOKEN_NE || tt == TOKEN_LE || tt == TOKEN_GE ||
432 tt == TOKEN_LEG) {
433 int tto = tt;
434 scan();
435 f = expr0();
436 if (!f)
437 return NULL;
439 e = add_vectors(e, scalar_mult(f, -1L, false));
441 switch (tto) {
442 case TOKEN_EQ:
443 case TOKEN_NE:
444 if (is_unknown(e))
445 v = -1; /* means unknown */
446 else if (!is_really_simple(e) || reloc_value(e) != 0)
447 v = (tto == TOKEN_NE); /* unequal, so return true if NE */
448 else
449 v = (tto == TOKEN_EQ); /* equal, so return true if EQ */
450 break;
451 default:
452 if (is_unknown(e))
453 v = -1; /* means unknown */
454 else if (!is_really_simple(e)) {
455 nasm_nonfatal("`%s': operands differ by a non-scalar",
456 (tto == TOKEN_LE ? "<=" :
457 tto == TOKEN_LT ? "<" :
458 tto == TOKEN_GE ? ">=" :
459 tto == TOKEN_GT ? ">" :
460 tto == TOKEN_LEG ? "<=>" :
461 "<internal error>"));
462 v = 0; /* must set it to _something_ */
463 } else {
464 int64_t vv = reloc_value(e);
465 if (tto == TOKEN_LEG)
466 v = (vv < 0) ? -1 : (vv > 0) ? 1 : 0;
467 else if (vv == 0)
468 v = (tto == TOKEN_LE || tto == TOKEN_GE);
469 else if (vv > 0)
470 v = (tto == TOKEN_GE || tto == TOKEN_GT);
471 else /* vv < 0 */
472 v = (tto == TOKEN_LE || tto == TOKEN_LT);
474 break;
477 if (v == -1)
478 e = unknown_expr();
479 else
480 e = scalarvect(v);
482 return e;
485 static expr *expr0(void)
487 expr *e, *f;
489 e = expr1();
490 if (!e)
491 return NULL;
493 while (tt == '|') {
494 scan();
495 f = expr1();
496 if (!f)
497 return NULL;
498 if (!(is_simple(e) || is_just_unknown(e)) ||
499 !(is_simple(f) || is_just_unknown(f))) {
500 nasm_nonfatal("`|' operator may only be applied to"
501 " scalar values");
503 if (is_just_unknown(e) || is_just_unknown(f))
504 e = unknown_expr();
505 else
506 e = scalarvect(reloc_value(e) | reloc_value(f));
508 return e;
511 static expr *expr1(void)
513 expr *e, *f;
515 e = expr2();
516 if (!e)
517 return NULL;
519 while (tt == '^') {
520 scan();
521 f = expr2();
522 if (!f)
523 return NULL;
524 if (!(is_simple(e) || is_just_unknown(e)) ||
525 !(is_simple(f) || is_just_unknown(f))) {
526 nasm_nonfatal("`^' operator may only be applied to"
527 " scalar values");
529 if (is_just_unknown(e) || is_just_unknown(f))
530 e = unknown_expr();
531 else
532 e = scalarvect(reloc_value(e) ^ reloc_value(f));
534 return e;
537 static expr *expr2(void)
539 expr *e, *f;
541 e = expr3();
542 if (!e)
543 return NULL;
545 while (tt == '&') {
546 scan();
547 f = expr3();
548 if (!f)
549 return NULL;
550 if (!(is_simple(e) || is_just_unknown(e)) ||
551 !(is_simple(f) || is_just_unknown(f))) {
552 nasm_nonfatal("`&' operator may only be applied to"
553 " scalar values");
555 if (is_just_unknown(e) || is_just_unknown(f))
556 e = unknown_expr();
557 else
558 e = scalarvect(reloc_value(e) & reloc_value(f));
560 return e;
563 static expr *expr3(void)
565 expr *e, *f;
567 e = expr4();
568 if (!e)
569 return NULL;
571 while (tt == TOKEN_SHL || tt == TOKEN_SHR || tt == TOKEN_SAR) {
572 int tto = tt;
573 scan();
574 f = expr4();
575 if (!f)
576 return NULL;
577 if (!(is_simple(e) || is_just_unknown(e)) ||
578 !(is_simple(f) || is_just_unknown(f))) {
579 nasm_nonfatal("shift operator may only be applied to"
580 " scalar values");
581 } else if (is_just_unknown(e) || is_just_unknown(f)) {
582 e = unknown_expr();
583 } else {
584 switch (tto) {
585 case TOKEN_SHL:
586 e = scalarvect(reloc_value(e) << reloc_value(f));
587 break;
588 case TOKEN_SHR:
589 e = scalarvect(((uint64_t)reloc_value(e)) >>
590 reloc_value(f));
591 break;
592 case TOKEN_SAR:
593 e = scalarvect(((int64_t)reloc_value(e)) >>
594 reloc_value(f));
595 break;
599 return e;
602 static expr *expr4(void)
604 expr *e, *f;
606 e = expr5();
607 if (!e)
608 return NULL;
609 while (tt == '+' || tt == '-') {
610 int tto = tt;
611 scan();
612 f = expr5();
613 if (!f)
614 return NULL;
615 switch (tto) {
616 case '+':
617 e = add_vectors(e, f);
618 break;
619 case '-':
620 e = add_vectors(e, scalar_mult(f, -1L, false));
621 break;
624 return e;
627 static expr *expr5(void)
629 expr *e, *f;
631 e = expr6();
632 if (!e)
633 return NULL;
634 while (tt == '*' || tt == '/' || tt == '%' ||
635 tt == TOKEN_SDIV || tt == TOKEN_SMOD) {
636 int tto = tt;
637 scan();
638 f = expr6();
639 if (!f)
640 return NULL;
641 if (tto != '*' && (!(is_simple(e) || is_just_unknown(e)) ||
642 !(is_simple(f) || is_just_unknown(f)))) {
643 nasm_nonfatal("division operator may only be applied to"
644 " scalar values");
645 return NULL;
647 if (tto != '*' && !is_just_unknown(f) && reloc_value(f) == 0) {
648 nasm_nonfatal("division by zero");
649 return NULL;
651 switch (tto) {
652 case '*':
653 if (is_simple(e))
654 e = scalar_mult(f, reloc_value(e), true);
655 else if (is_simple(f))
656 e = scalar_mult(e, reloc_value(f), true);
657 else if (is_just_unknown(e) && is_just_unknown(f))
658 e = unknown_expr();
659 else {
660 nasm_nonfatal("unable to multiply two "
661 "non-scalar objects");
662 return NULL;
664 break;
665 case '/':
666 if (is_just_unknown(e) || is_just_unknown(f))
667 e = unknown_expr();
668 else
669 e = scalarvect(((uint64_t)reloc_value(e)) /
670 ((uint64_t)reloc_value(f)));
671 break;
672 case '%':
673 if (is_just_unknown(e) || is_just_unknown(f))
674 e = unknown_expr();
675 else
676 e = scalarvect(((uint64_t)reloc_value(e)) %
677 ((uint64_t)reloc_value(f)));
678 break;
679 case TOKEN_SDIV:
680 if (is_just_unknown(e) || is_just_unknown(f))
681 e = unknown_expr();
682 else
683 e = scalarvect(((int64_t)reloc_value(e)) /
684 ((int64_t)reloc_value(f)));
685 break;
686 case TOKEN_SMOD:
687 if (is_just_unknown(e) || is_just_unknown(f))
688 e = unknown_expr();
689 else
690 e = scalarvect(((int64_t)reloc_value(e)) %
691 ((int64_t)reloc_value(f)));
692 break;
695 return e;
698 static expr *eval_floatize(enum floatize type)
700 uint8_t result[16], *p; /* Up to 128 bits */
701 static const struct {
702 int bytes, start, len;
703 } formats[] = {
704 { 1, 0, 1 }, /* FLOAT_8 */
705 { 2, 0, 2 }, /* FLOAT_16 */
706 { 4, 0, 4 }, /* FLOAT_32 */
707 { 8, 0, 8 }, /* FLOAT_64 */
708 { 10, 0, 8 }, /* FLOAT_80M */
709 { 10, 8, 2 }, /* FLOAT_80E */
710 { 16, 0, 8 }, /* FLOAT_128L */
711 { 16, 8, 8 }, /* FLOAT_128H */
713 int sign = 1;
714 int64_t val;
715 int i;
717 scan();
718 if (tt != '(') {
719 nasm_nonfatal("expecting `('");
720 return NULL;
722 scan();
723 if (tt == '-' || tt == '+') {
724 sign = (tt == '-') ? -1 : 1;
725 scan();
727 if (tt != TOKEN_FLOAT) {
728 nasm_nonfatal("expecting floating-point number");
729 return NULL;
731 if (!float_const(tokval->t_charptr, sign, result, formats[type].bytes))
732 return NULL;
733 scan();
734 if (tt != ')') {
735 nasm_nonfatal("expecting `)'");
736 return NULL;
739 p = result+formats[type].start+formats[type].len;
740 val = 0;
741 for (i = formats[type].len; i; i--) {
742 p--;
743 val = (val << 8) + *p;
746 begintemp();
747 addtotemp(EXPR_SIMPLE, val);
749 scan();
750 return finishtemp();
753 static expr *eval_strfunc(enum strfunc type)
755 char *string;
756 size_t string_len;
757 int64_t val;
758 bool parens, rn_warn;
760 parens = false;
761 scan();
762 if (tt == '(') {
763 parens = true;
764 scan();
766 if (tt != TOKEN_STR) {
767 nasm_nonfatal("expecting string");
768 return NULL;
770 string_len = string_transform(tokval->t_charptr, tokval->t_inttwo,
771 &string, type);
772 if (string_len == (size_t)-1) {
773 nasm_nonfatal("invalid string for transform");
774 return NULL;
777 val = readstrnum(string, string_len, &rn_warn);
778 if (parens) {
779 scan();
780 if (tt != ')') {
781 nasm_nonfatal("expecting `)'");
782 return NULL;
786 if (rn_warn)
787 nasm_warnf(ERR_PASS1, "character constant too long");
789 begintemp();
790 addtotemp(EXPR_SIMPLE, val);
792 scan();
793 return finishtemp();
796 static int64_t eval_ifunc(int64_t val, enum ifunc func)
798 uint64_t uval = (uint64_t)val;
799 int64_t rv;
801 switch (func) {
802 case IFUNC_ILOG2E:
803 case IFUNC_ILOG2W:
804 if (!is_power2(uval))
805 nasm_error((func == IFUNC_ILOG2E) ? ERR_NONFATAL : ERR_WARNING,
806 "ilog2 argument is not a power of two");
807 /* fall through */
808 case IFUNC_ILOG2F:
809 rv = ilog2_64(uval);
810 break;
812 case IFUNC_ILOG2C:
813 rv = (uval < 2) ? 0 : ilog2_64(uval-1) + 1;
814 break;
816 default:
817 nasm_panic("invalid IFUNC token %d", func);
818 rv = 0;
819 break;
822 return rv;
825 static expr *expr6(void)
827 int32_t type;
828 expr *e;
829 int32_t label_seg;
830 int64_t label_ofs;
831 int64_t tmpval;
832 bool rn_warn;
833 const char *scope;
835 if (++deadman > nasm_limit[LIMIT_EVAL]) {
836 nasm_nonfatal("expression too long");
837 return NULL;
840 switch (tt) {
841 case '-':
842 scan();
843 e = expr6();
844 if (!e)
845 return NULL;
846 return scalar_mult(e, -1L, false);
848 case '+':
849 scan();
850 return expr6();
852 case '~':
853 scan();
854 e = expr6();
855 if (!e)
856 return NULL;
857 if (is_just_unknown(e))
858 return unknown_expr();
859 else if (!is_simple(e)) {
860 nasm_nonfatal("`~' operator may only be applied to"
861 " scalar values");
862 return NULL;
864 return scalarvect(~reloc_value(e));
866 case '!':
867 scan();
868 e = expr6();
869 if (!e)
870 return NULL;
871 if (is_just_unknown(e))
872 return unknown_expr();
873 else if (!is_simple(e)) {
874 nasm_nonfatal("`!' operator may only be applied to"
875 " scalar values");
876 return NULL;
878 return scalarvect(!reloc_value(e));
880 case TOKEN_IFUNC:
882 enum ifunc func = tokval->t_integer;
883 scan();
884 e = expr6();
885 if (!e)
886 return NULL;
887 if (is_just_unknown(e))
888 return unknown_expr();
889 else if (!is_simple(e)) {
890 nasm_nonfatal("function may only be applied to"
891 " scalar values");
892 return NULL;
894 return scalarvect(eval_ifunc(reloc_value(e), func));
897 case TOKEN_SEG:
898 scan();
899 e = expr6();
900 if (!e)
901 return NULL;
902 e = segment_part(e);
903 if (!e)
904 return NULL;
905 if (is_unknown(e) && critical) {
906 nasm_nonfatal("unable to determine segment base");
907 return NULL;
909 return e;
911 case TOKEN_FLOATIZE:
912 return eval_floatize(tokval->t_integer);
914 case TOKEN_STRFUNC:
915 return eval_strfunc(tokval->t_integer);
917 case '(':
918 scan();
919 e = bexpr();
920 if (!e)
921 return NULL;
922 if (tt != ')') {
923 nasm_nonfatal("expecting `)'");
924 return NULL;
926 scan();
927 return e;
929 case TOKEN_NUM:
930 case TOKEN_STR:
931 case TOKEN_REG:
932 case TOKEN_ID:
933 case TOKEN_INSN: /* Opcodes that occur here are really labels */
934 case TOKEN_HERE:
935 case TOKEN_BASE:
936 case TOKEN_DECORATOR:
937 begintemp();
938 switch (tt) {
939 case TOKEN_NUM:
940 addtotemp(EXPR_SIMPLE, tokval->t_integer);
941 break;
942 case TOKEN_STR:
943 tmpval = readstrnum(tokval->t_charptr, tokval->t_inttwo, &rn_warn);
944 if (rn_warn)
945 nasm_warnf(ERR_PASS1, "character constant too long");
946 addtotemp(EXPR_SIMPLE, tmpval);
947 break;
948 case TOKEN_REG:
949 addtotemp(tokval->t_integer, 1L);
950 if (hint && hint->type == EAH_NOHINT)
951 hint->base = tokval->t_integer, hint->type = EAH_MAKEBASE;
952 break;
953 case TOKEN_ID:
954 case TOKEN_INSN:
955 case TOKEN_HERE:
956 case TOKEN_BASE:
958 * If !location.known, this indicates that no
959 * symbol, Here or Base references are valid because we
960 * are in preprocess-only mode.
962 if (!location.known) {
963 nasm_nonfatal("%s not supported in preprocess-only mode",
964 (tt == TOKEN_HERE ? "`$'" :
965 tt == TOKEN_BASE ? "`$$'" :
966 "symbol references"));
967 addtotemp(EXPR_UNKNOWN, 1L);
968 break;
971 type = EXPR_SIMPLE; /* might get overridden by UNKNOWN */
972 if (tt == TOKEN_BASE) {
973 label_seg = in_absolute ? absolute.segment : location.segment;
974 label_ofs = 0;
975 } else if (tt == TOKEN_HERE) {
976 label_seg = in_absolute ? absolute.segment : location.segment;
977 label_ofs = in_absolute ? absolute.offset : location.offset;
978 } else {
979 if (!lookup_label(tokval->t_charptr, &label_seg, &label_ofs)) {
980 scope = local_scope(tokval->t_charptr);
981 if (critical == 2) {
982 nasm_nonfatal("symbol `%s%s' undefined",
983 scope,tokval->t_charptr);
984 return NULL;
985 } else if (critical == 1) {
986 nasm_nonfatal("symbol `%s%s' not defined before use",
987 scope,tokval->t_charptr);
988 return NULL;
989 } else {
990 if (opflags)
991 *opflags |= OPFLAG_FORWARD;
992 type = EXPR_UNKNOWN;
993 label_seg = NO_SEG;
994 label_ofs = 1;
997 if (opflags && is_extern(tokval->t_charptr))
998 *opflags |= OPFLAG_EXTERN;
1000 addtotemp(type, label_ofs);
1001 if (label_seg != NO_SEG)
1002 addtotemp(EXPR_SEGBASE + label_seg, 1L);
1003 break;
1004 case TOKEN_DECORATOR:
1005 addtotemp(EXPR_RDSAE, tokval->t_integer);
1006 break;
1008 scan();
1009 return finishtemp();
1011 default:
1012 nasm_nonfatal("expression syntax error");
1013 return NULL;
1017 expr *evaluate(scanner sc, void *scprivate, struct tokenval *tv,
1018 int *fwref, int crit, struct eval_hints *hints)
1020 expr *e;
1021 expr *f = NULL;
1023 deadman = 0;
1025 hint = hints;
1026 if (hint)
1027 hint->type = EAH_NOHINT;
1029 critical = crit & ~CRITICAL;
1030 scanfunc = sc;
1031 scpriv = scprivate;
1032 tokval = tv;
1033 opflags = fwref;
1035 while (ntempexprs) /* initialize temporary storage */
1036 nasm_free(tempexprs[--ntempexprs]);
1038 tt = tokval->t_type;
1039 if (tt == TOKEN_INVALID)
1040 scan();
1042 e = bexpr();
1043 if (!e)
1044 return NULL;
1046 if (tt == TOKEN_WRT) {
1047 scan(); /* eat the WRT */
1048 f = expr6();
1049 if (!f)
1050 return NULL;
1052 e = scalar_mult(e, 1L, false); /* strip far-absolute segment part */
1053 if (f) {
1054 expr *g;
1055 if (is_just_unknown(f))
1056 g = unknown_expr();
1057 else {
1058 int64_t value;
1059 begintemp();
1060 if (!is_reloc(f)) {
1061 nasm_nonfatal("invalid right-hand operand to WRT");
1062 return NULL;
1064 value = reloc_seg(f);
1065 if (value == NO_SEG)
1066 value = reloc_value(f) | SEG_ABS;
1067 else if (!(value & SEG_ABS) && !(value % 2) && critical) {
1068 nasm_nonfatal("invalid right-hand operand to WRT");
1069 return NULL;
1071 addtotemp(EXPR_WRT, value);
1072 g = finishtemp();
1074 e = add_vectors(e, g);
1076 return e;