strlist.h: move safe_alloc declaration
[nasm.git] / asm / eval.c
blobcd3c526d625deaf40cae3d65a0f2bbbf41fa5cc3
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 "nctype.h"
42 #include "nasm.h"
43 #include "nasmlib.h"
44 #include "ilog2.h"
45 #include "error.h"
46 #include "eval.h"
47 #include "labels.h"
48 #include "floats.h"
49 #include "assemble.h"
51 #define TEMPEXPRS_DELTA 128
52 #define TEMPEXPR_DELTA 8
54 static scanner scanfunc; /* Address of scanner routine */
55 static void *scpriv; /* Scanner private pointer */
57 static expr **tempexprs = NULL;
58 static int ntempexprs;
59 static int tempexprs_size = 0;
61 static expr *tempexpr;
62 static int ntempexpr;
63 static int tempexpr_size;
65 static struct tokenval *tokval; /* The current token */
66 static int tt; /* The t_type of tokval */
68 static bool critical;
69 static int *opflags;
71 static struct eval_hints *hint;
72 static int64_t deadman;
76 * Unimportant cleanup is done to avoid confusing people who are trying
77 * to debug real memory leaks
79 void eval_cleanup(void)
81 while (ntempexprs)
82 nasm_free(tempexprs[--ntempexprs]);
83 nasm_free(tempexprs);
87 * Construct a temporary expression.
89 static void begintemp(void)
91 tempexpr = NULL;
92 tempexpr_size = ntempexpr = 0;
95 static void addtotemp(int32_t type, int64_t value)
97 while (ntempexpr >= tempexpr_size) {
98 tempexpr_size += TEMPEXPR_DELTA;
99 tempexpr = nasm_realloc(tempexpr,
100 tempexpr_size * sizeof(*tempexpr));
102 tempexpr[ntempexpr].type = type;
103 tempexpr[ntempexpr++].value = value;
106 static expr *finishtemp(void)
108 addtotemp(0L, 0L); /* terminate */
109 while (ntempexprs >= tempexprs_size) {
110 tempexprs_size += TEMPEXPRS_DELTA;
111 tempexprs = nasm_realloc(tempexprs,
112 tempexprs_size * sizeof(*tempexprs));
114 return tempexprs[ntempexprs++] = tempexpr;
118 * Add two vector datatypes. We have some bizarre behaviour on far-
119 * absolute segment types: we preserve them during addition _only_
120 * if one of the segments is a truly pure scalar.
122 static expr *add_vectors(expr * p, expr * q)
124 int preserve;
126 preserve = is_really_simple(p) || is_really_simple(q);
128 begintemp();
130 while (p->type && q->type &&
131 p->type < EXPR_SEGBASE + SEG_ABS &&
132 q->type < EXPR_SEGBASE + SEG_ABS) {
133 int lasttype;
135 if (p->type > q->type) {
136 addtotemp(q->type, q->value);
137 lasttype = q++->type;
138 } else if (p->type < q->type) {
139 addtotemp(p->type, p->value);
140 lasttype = p++->type;
141 } else { /* *p and *q have same type */
142 int64_t sum = p->value + q->value;
143 if (sum) {
144 addtotemp(p->type, sum);
145 if (hint)
146 hint->type = EAH_SUMMED;
148 lasttype = p->type;
149 p++, q++;
151 if (lasttype == EXPR_UNKNOWN) {
152 return finishtemp();
155 while (p->type && (preserve || p->type < EXPR_SEGBASE + SEG_ABS)) {
156 addtotemp(p->type, p->value);
157 p++;
159 while (q->type && (preserve || q->type < EXPR_SEGBASE + SEG_ABS)) {
160 addtotemp(q->type, q->value);
161 q++;
164 return finishtemp();
168 * Multiply a vector by a scalar. Strip far-absolute segment part
169 * if present.
171 * Explicit treatment of UNKNOWN is not required in this routine,
172 * since it will silently do the Right Thing anyway.
174 * If `affect_hints' is set, we also change the hint type to
175 * NOTBASE if a MAKEBASE hint points at a register being
176 * multiplied. This allows [eax*1+ebx] to hint EBX rather than EAX
177 * as the base register.
179 static expr *scalar_mult(expr * vect, int64_t scalar, int affect_hints)
181 expr *p = vect;
183 while (p->type && p->type < EXPR_SEGBASE + SEG_ABS) {
184 p->value = scalar * (p->value);
185 if (hint && hint->type == EAH_MAKEBASE &&
186 p->type == hint->base && affect_hints)
187 hint->type = EAH_NOTBASE;
188 p++;
190 p->type = 0;
192 return vect;
195 static expr *scalarvect(int64_t scalar)
197 begintemp();
198 addtotemp(EXPR_SIMPLE, scalar);
199 return finishtemp();
202 static expr *unknown_expr(void)
204 begintemp();
205 addtotemp(EXPR_UNKNOWN, 1L);
206 return finishtemp();
210 * The SEG operator: calculate the segment part of a relocatable
211 * value. Return NULL, as usual, if an error occurs. Report the
212 * error too.
214 static expr *segment_part(expr * e)
216 int32_t seg;
218 if (is_unknown(e))
219 return unknown_expr();
221 if (!is_reloc(e)) {
222 nasm_nonfatal("cannot apply SEG to a non-relocatable value");
223 return NULL;
226 seg = reloc_seg(e);
227 if (seg == NO_SEG) {
228 nasm_nonfatal("cannot apply SEG to a non-relocatable value");
229 return NULL;
230 } else if (seg & SEG_ABS) {
231 return scalarvect(seg & ~SEG_ABS);
232 } else if (seg & 1) {
233 nasm_nonfatal("SEG applied to something which"
234 " is already a segment base");
235 return NULL;
236 } else {
237 int32_t base = ofmt->segbase(seg + 1);
239 begintemp();
240 addtotemp((base == NO_SEG ? EXPR_UNKNOWN : EXPR_SEGBASE + base),
241 1L);
242 return finishtemp();
247 * Recursive-descent parser. Called with a single boolean operand,
248 * which is true if the evaluation is critical (i.e. unresolved
249 * symbols are an error condition). Must update the global `tt' to
250 * reflect the token after the parsed string. May return NULL.
252 * evaluate() should report its own errors: on return it is assumed
253 * that if NULL has been returned, the error has already been
254 * reported.
259 * Wrapper function around the scanner
261 static int scan(void)
263 return tt = scanfunc(scpriv, tokval);
267 * Grammar parsed is:
269 * expr : bexpr [ WRT expr6 ]
270 * bexpr : cexpr
271 * cexpr : rexp0 [ {?} bexpr {:} cexpr ]
272 * rexp0 : rexp1 [ {||} rexp1...]
273 * rexp1 : rexp2 [ {^^} rexp2...]
274 * rexp2 : rexp3 [ {&&} rexp3...]
275 * rexp3 : expr0 [ {=,==,<>,!=,<,>,<=,>=,<=>} expr0... ]
276 * expr0 : expr1 [ {|} expr1...]
277 * expr1 : expr2 [ {^} expr2...]
278 * expr2 : expr3 [ {&} expr3...]
279 * expr3 : expr4 [ {<<,>>,<<<,>>>} expr4...]
280 * expr4 : expr5 [ {+,-} expr5...]
281 * expr5 : expr6 [ {*,/,%,//,%%} expr6...]
282 * expr6 : { ~,+,-,IFUNC,SEG } expr6
283 * | (bexpr)
284 * | symbol
285 * | $
286 * | number
289 static expr *cexpr(void);
290 static expr *rexp0(void), *rexp1(void), *rexp2(void), *rexp3(void);
292 static expr *expr0(void), *expr1(void), *expr2(void), *expr3(void);
293 static expr *expr4(void), *expr5(void), *expr6(void);
295 /* This inline is a placeholder for the root of the basic expression */
296 static inline expr *bexpr(void)
298 return cexpr();
301 static expr *cexpr(void)
303 expr *e, *f, *g;
305 e = rexp0();
306 if (!e)
307 return NULL;
309 if (tt == TOKEN_QMARK) {
310 scan();
311 f = bexpr();
312 if (!f)
313 return NULL;
315 if (tt != ':') {
316 nasm_nonfatal("`?' without matching `:'");
317 return NULL;
320 scan();
321 g = cexpr();
322 if (!g)
323 return NULL;
325 if (is_simple(e)) {
326 e = reloc_value(e) ? f : g;
327 } else if (is_just_unknown(e)) {
328 e = unknown_expr();
329 } else {
330 nasm_nonfatal("the left-hand side of `?' must be "
331 "a scalar value");
335 return e;
338 static expr *rexp0(void)
340 expr *e, *f;
342 e = rexp1();
343 if (!e)
344 return NULL;
346 while (tt == TOKEN_DBL_OR) {
347 scan();
348 f = rexp1();
349 if (!f)
350 return NULL;
351 if (!(is_simple(e) || is_just_unknown(e)) ||
352 !(is_simple(f) || is_just_unknown(f))) {
353 nasm_nonfatal("`|' operator may only be applied to"
354 " scalar values");
357 if (is_just_unknown(e) || is_just_unknown(f))
358 e = unknown_expr();
359 else
360 e = scalarvect((int64_t)(reloc_value(e) || reloc_value(f)));
362 return e;
365 static expr *rexp1(void)
367 expr *e, *f;
369 e = rexp2();
370 if (!e)
371 return NULL;
373 while (tt == TOKEN_DBL_XOR) {
374 scan();
375 f = rexp2();
376 if (!f)
377 return NULL;
378 if (!(is_simple(e) || is_just_unknown(e)) ||
379 !(is_simple(f) || is_just_unknown(f))) {
380 nasm_nonfatal("`^' operator may only be applied to"
381 " scalar values");
384 if (is_just_unknown(e) || is_just_unknown(f))
385 e = unknown_expr();
386 else
387 e = scalarvect((int64_t)(!reloc_value(e) ^ !reloc_value(f)));
389 return e;
392 static expr *rexp2(void)
394 expr *e, *f;
396 e = rexp3();
397 if (!e)
398 return NULL;
399 while (tt == TOKEN_DBL_AND) {
400 scan();
401 f = rexp3();
402 if (!f)
403 return NULL;
404 if (!(is_simple(e) || is_just_unknown(e)) ||
405 !(is_simple(f) || is_just_unknown(f))) {
406 nasm_nonfatal("`&' operator may only be applied to"
407 " scalar values");
409 if (is_just_unknown(e) || is_just_unknown(f))
410 e = unknown_expr();
411 else
412 e = scalarvect((int64_t)(reloc_value(e) && reloc_value(f)));
414 return e;
417 static expr *rexp3(void)
419 expr *e, *f;
420 int64_t v;
422 e = expr0();
423 if (!e)
424 return NULL;
426 while (tt == TOKEN_EQ || tt == TOKEN_LT || tt == TOKEN_GT ||
427 tt == TOKEN_NE || tt == TOKEN_LE || tt == TOKEN_GE ||
428 tt == TOKEN_LEG) {
429 int tto = tt;
430 scan();
431 f = expr0();
432 if (!f)
433 return NULL;
435 e = add_vectors(e, scalar_mult(f, -1L, false));
437 switch (tto) {
438 case TOKEN_EQ:
439 case TOKEN_NE:
440 if (is_unknown(e))
441 v = -1; /* means unknown */
442 else if (!is_really_simple(e) || reloc_value(e) != 0)
443 v = (tto == TOKEN_NE); /* unequal, so return true if NE */
444 else
445 v = (tto == TOKEN_EQ); /* equal, so return true if EQ */
446 break;
447 default:
448 if (is_unknown(e))
449 v = -1; /* means unknown */
450 else if (!is_really_simple(e)) {
451 nasm_nonfatal("`%s': operands differ by a non-scalar",
452 (tto == TOKEN_LE ? "<=" :
453 tto == TOKEN_LT ? "<" :
454 tto == TOKEN_GE ? ">=" :
455 tto == TOKEN_GT ? ">" :
456 tto == TOKEN_LEG ? "<=>" :
457 "<internal error>"));
458 v = 0; /* must set it to _something_ */
459 } else {
460 int64_t vv = reloc_value(e);
461 if (tto == TOKEN_LEG)
462 v = (vv < 0) ? -1 : (vv > 0) ? 1 : 0;
463 else if (vv == 0)
464 v = (tto == TOKEN_LE || tto == TOKEN_GE);
465 else if (vv > 0)
466 v = (tto == TOKEN_GE || tto == TOKEN_GT);
467 else /* vv < 0 */
468 v = (tto == TOKEN_LE || tto == TOKEN_LT);
470 break;
473 if (v == -1)
474 e = unknown_expr();
475 else
476 e = scalarvect(v);
478 return e;
481 static expr *expr0(void)
483 expr *e, *f;
485 e = expr1();
486 if (!e)
487 return NULL;
489 while (tt == '|') {
490 scan();
491 f = expr1();
492 if (!f)
493 return NULL;
494 if (!(is_simple(e) || is_just_unknown(e)) ||
495 !(is_simple(f) || is_just_unknown(f))) {
496 nasm_nonfatal("`|' operator may only be applied to"
497 " scalar values");
499 if (is_just_unknown(e) || is_just_unknown(f))
500 e = unknown_expr();
501 else
502 e = scalarvect(reloc_value(e) | reloc_value(f));
504 return e;
507 static expr *expr1(void)
509 expr *e, *f;
511 e = expr2();
512 if (!e)
513 return NULL;
515 while (tt == '^') {
516 scan();
517 f = expr2();
518 if (!f)
519 return NULL;
520 if (!(is_simple(e) || is_just_unknown(e)) ||
521 !(is_simple(f) || is_just_unknown(f))) {
522 nasm_nonfatal("`^' operator may only be applied to"
523 " scalar values");
525 if (is_just_unknown(e) || is_just_unknown(f))
526 e = unknown_expr();
527 else
528 e = scalarvect(reloc_value(e) ^ reloc_value(f));
530 return e;
533 static expr *expr2(void)
535 expr *e, *f;
537 e = expr3();
538 if (!e)
539 return NULL;
541 while (tt == '&') {
542 scan();
543 f = expr3();
544 if (!f)
545 return NULL;
546 if (!(is_simple(e) || is_just_unknown(e)) ||
547 !(is_simple(f) || is_just_unknown(f))) {
548 nasm_nonfatal("`&' operator may only be applied to"
549 " scalar values");
551 if (is_just_unknown(e) || is_just_unknown(f))
552 e = unknown_expr();
553 else
554 e = scalarvect(reloc_value(e) & reloc_value(f));
556 return e;
559 static expr *expr3(void)
561 expr *e, *f;
563 e = expr4();
564 if (!e)
565 return NULL;
567 while (tt == TOKEN_SHL || tt == TOKEN_SHR || tt == TOKEN_SAR) {
568 int tto = tt;
569 scan();
570 f = expr4();
571 if (!f)
572 return NULL;
573 if (!(is_simple(e) || is_just_unknown(e)) ||
574 !(is_simple(f) || is_just_unknown(f))) {
575 nasm_nonfatal("shift operator may only be applied to"
576 " scalar values");
577 } else if (is_just_unknown(e) || is_just_unknown(f)) {
578 e = unknown_expr();
579 } else {
580 switch (tto) {
581 case TOKEN_SHL:
582 e = scalarvect(reloc_value(e) << reloc_value(f));
583 break;
584 case TOKEN_SHR:
585 e = scalarvect(((uint64_t)reloc_value(e)) >>
586 reloc_value(f));
587 break;
588 case TOKEN_SAR:
589 e = scalarvect(((int64_t)reloc_value(e)) >>
590 reloc_value(f));
591 break;
595 return e;
598 static expr *expr4(void)
600 expr *e, *f;
602 e = expr5();
603 if (!e)
604 return NULL;
605 while (tt == '+' || tt == '-') {
606 int tto = tt;
607 scan();
608 f = expr5();
609 if (!f)
610 return NULL;
611 switch (tto) {
612 case '+':
613 e = add_vectors(e, f);
614 break;
615 case '-':
616 e = add_vectors(e, scalar_mult(f, -1L, false));
617 break;
620 return e;
623 static expr *expr5(void)
625 expr *e, *f;
627 e = expr6();
628 if (!e)
629 return NULL;
630 while (tt == '*' || tt == '/' || tt == '%' ||
631 tt == TOKEN_SDIV || tt == TOKEN_SMOD) {
632 int tto = tt;
633 scan();
634 f = expr6();
635 if (!f)
636 return NULL;
637 if (tto != '*' && (!(is_simple(e) || is_just_unknown(e)) ||
638 !(is_simple(f) || is_just_unknown(f)))) {
639 nasm_nonfatal("division operator may only be applied to"
640 " scalar values");
641 return NULL;
643 if (tto != '*' && !is_just_unknown(f) && reloc_value(f) == 0) {
644 nasm_nonfatal("division by zero");
645 return NULL;
647 switch (tto) {
648 case '*':
649 if (is_simple(e))
650 e = scalar_mult(f, reloc_value(e), true);
651 else if (is_simple(f))
652 e = scalar_mult(e, reloc_value(f), true);
653 else if (is_just_unknown(e) && is_just_unknown(f))
654 e = unknown_expr();
655 else {
656 nasm_nonfatal("unable to multiply two "
657 "non-scalar objects");
658 return NULL;
660 break;
661 case '/':
662 if (is_just_unknown(e) || is_just_unknown(f))
663 e = unknown_expr();
664 else
665 e = scalarvect(((uint64_t)reloc_value(e)) /
666 ((uint64_t)reloc_value(f)));
667 break;
668 case '%':
669 if (is_just_unknown(e) || is_just_unknown(f))
670 e = unknown_expr();
671 else
672 e = scalarvect(((uint64_t)reloc_value(e)) %
673 ((uint64_t)reloc_value(f)));
674 break;
675 case TOKEN_SDIV:
676 if (is_just_unknown(e) || is_just_unknown(f))
677 e = unknown_expr();
678 else
679 e = scalarvect(((int64_t)reloc_value(e)) /
680 ((int64_t)reloc_value(f)));
681 break;
682 case TOKEN_SMOD:
683 if (is_just_unknown(e) || is_just_unknown(f))
684 e = unknown_expr();
685 else
686 e = scalarvect(((int64_t)reloc_value(e)) %
687 ((int64_t)reloc_value(f)));
688 break;
691 return e;
694 static expr *eval_floatize(enum floatize type)
696 uint8_t result[16], *p; /* Up to 128 bits */
697 static const struct {
698 int bytes, start, len;
699 } formats[] = {
700 { 1, 0, 1 }, /* FLOAT_8 */
701 { 2, 0, 2 }, /* FLOAT_16 */
702 { 4, 0, 4 }, /* FLOAT_32 */
703 { 8, 0, 8 }, /* FLOAT_64 */
704 { 10, 0, 8 }, /* FLOAT_80M */
705 { 10, 8, 2 }, /* FLOAT_80E */
706 { 16, 0, 8 }, /* FLOAT_128L */
707 { 16, 8, 8 }, /* FLOAT_128H */
709 int sign = 1;
710 int64_t val;
711 int i;
713 scan();
714 if (tt != '(') {
715 nasm_nonfatal("expecting `('");
716 return NULL;
718 scan();
719 if (tt == '-' || tt == '+') {
720 sign = (tt == '-') ? -1 : 1;
721 scan();
723 if (tt != TOKEN_FLOAT) {
724 nasm_nonfatal("expecting floating-point number");
725 return NULL;
727 if (!float_const(tokval->t_charptr, sign, result, formats[type].bytes))
728 return NULL;
729 scan();
730 if (tt != ')') {
731 nasm_nonfatal("expecting `)'");
732 return NULL;
735 p = result+formats[type].start+formats[type].len;
736 val = 0;
737 for (i = formats[type].len; i; i--) {
738 p--;
739 val = (val << 8) + *p;
742 begintemp();
743 addtotemp(EXPR_SIMPLE, val);
745 scan();
746 return finishtemp();
749 static expr *eval_strfunc(enum strfunc type, const char *name)
751 char *string;
752 size_t string_len;
753 int64_t val;
754 bool parens, rn_warn;
756 parens = false;
757 scan();
758 if (tt == '(') {
759 parens = true;
760 scan();
762 if (tt != TOKEN_STR) {
763 nasm_nonfatal("expecting string as argument to %s", name);
764 return NULL;
766 string_len = string_transform(tokval->t_charptr, tokval->t_inttwo,
767 &string, type);
768 if (string_len == (size_t)-1) {
769 nasm_nonfatal("invalid input string to %s", name);
770 return NULL;
773 val = readstrnum(string, string_len, &rn_warn);
774 if (parens) {
775 scan();
776 if (tt != ')') {
777 nasm_nonfatal("expecting `)'");
778 return NULL;
782 if (rn_warn)
783 nasm_warn(WARN_OTHER, "character constant too long");
785 begintemp();
786 addtotemp(EXPR_SIMPLE, val);
788 scan();
789 return finishtemp();
792 static int64_t eval_ifunc(int64_t val, enum ifunc func)
794 uint64_t uval = (uint64_t)val;
795 int64_t rv;
797 switch (func) {
798 case IFUNC_ILOG2E:
799 case IFUNC_ILOG2W:
800 if (!is_power2(uval))
801 nasm_error((func == IFUNC_ILOG2E) ? ERR_NONFATAL : ERR_WARNING|WARN_OTHER,
802 "ilog2 argument is not a power of two");
803 /* fall through */
804 case IFUNC_ILOG2F:
805 rv = ilog2_64(uval);
806 break;
808 case IFUNC_ILOG2C:
809 rv = (uval < 2) ? 0 : ilog2_64(uval-1) + 1;
810 break;
812 default:
813 nasm_panic("invalid IFUNC token %d", func);
814 rv = 0;
815 break;
818 return rv;
821 static expr *expr6(void)
823 int32_t type;
824 expr *e;
825 int32_t label_seg;
826 int64_t label_ofs;
827 int64_t tmpval;
828 bool rn_warn;
829 const char *scope;
831 if (++deadman > nasm_limit[LIMIT_EVAL]) {
832 nasm_nonfatal("expression too long");
833 return NULL;
836 switch (tt) {
837 case '-':
838 scan();
839 e = expr6();
840 if (!e)
841 return NULL;
842 return scalar_mult(e, -1L, false);
844 case '+':
845 scan();
846 return expr6();
848 case '~':
849 scan();
850 e = expr6();
851 if (!e)
852 return NULL;
853 if (is_just_unknown(e))
854 return unknown_expr();
855 else if (!is_simple(e)) {
856 nasm_nonfatal("`~' operator may only be applied to"
857 " scalar values");
858 return NULL;
860 return scalarvect(~reloc_value(e));
862 case '!':
863 scan();
864 e = expr6();
865 if (!e)
866 return NULL;
867 if (is_just_unknown(e))
868 return unknown_expr();
869 else if (!is_simple(e)) {
870 nasm_nonfatal("`!' operator may only be applied to"
871 " scalar values");
872 return NULL;
874 return scalarvect(!reloc_value(e));
876 case TOKEN_IFUNC:
878 enum ifunc func = tokval->t_integer;
879 scan();
880 e = expr6();
881 if (!e)
882 return NULL;
883 if (is_just_unknown(e))
884 return unknown_expr();
885 else if (!is_simple(e)) {
886 nasm_nonfatal("function may only be applied to"
887 " scalar values");
888 return NULL;
890 return scalarvect(eval_ifunc(reloc_value(e), func));
893 case TOKEN_SEG:
894 scan();
895 e = expr6();
896 if (!e)
897 return NULL;
898 e = segment_part(e);
899 if (!e)
900 return NULL;
901 if (is_unknown(e) && critical) {
902 nasm_nonfatal("unable to determine segment base");
903 return NULL;
905 return e;
907 case TOKEN_FLOATIZE:
908 return eval_floatize(tokval->t_integer);
910 case TOKEN_STRFUNC:
911 return eval_strfunc(tokval->t_integer, tokval->t_charptr);
913 case '(':
914 scan();
915 e = bexpr();
916 if (!e)
917 return NULL;
918 if (tt != ')') {
919 nasm_nonfatal("expecting `)'");
920 return NULL;
922 scan();
923 return e;
925 case TOKEN_NUM:
926 case TOKEN_STR:
927 case TOKEN_REG:
928 case TOKEN_ID:
929 case TOKEN_INSN: /* Opcodes that occur here are really labels */
930 case TOKEN_HERE:
931 case TOKEN_BASE:
932 case TOKEN_DECORATOR:
933 begintemp();
934 switch (tt) {
935 case TOKEN_NUM:
936 addtotemp(EXPR_SIMPLE, tokval->t_integer);
937 break;
938 case TOKEN_STR:
939 tmpval = readstrnum(tokval->t_charptr, tokval->t_inttwo, &rn_warn);
940 if (rn_warn)
941 nasm_warn(WARN_OTHER, "character constant too long");
942 addtotemp(EXPR_SIMPLE, tmpval);
943 break;
944 case TOKEN_REG:
945 addtotemp(tokval->t_integer, 1L);
946 if (hint && hint->type == EAH_NOHINT)
947 hint->base = tokval->t_integer, hint->type = EAH_MAKEBASE;
948 break;
949 case TOKEN_ID:
950 case TOKEN_INSN:
951 case TOKEN_HERE:
952 case TOKEN_BASE:
954 * If !location.known, this indicates that no
955 * symbol, Here or Base references are valid because we
956 * are in preprocess-only mode.
958 if (!location.known) {
959 nasm_nonfatal("%s not supported in preprocess-only mode",
960 (tt == TOKEN_HERE ? "`$'" :
961 tt == TOKEN_BASE ? "`$$'" :
962 "symbol references"));
963 addtotemp(EXPR_UNKNOWN, 1L);
964 break;
967 type = EXPR_SIMPLE; /* might get overridden by UNKNOWN */
968 if (tt == TOKEN_BASE) {
969 label_seg = in_absolute ? absolute.segment : location.segment;
970 label_ofs = 0;
971 } else if (tt == TOKEN_HERE) {
972 label_seg = in_absolute ? absolute.segment : location.segment;
973 label_ofs = in_absolute ? absolute.offset : location.offset;
974 } else {
975 enum label_type ltype;
976 ltype = lookup_label(tokval->t_charptr, &label_seg, &label_ofs);
977 if (ltype == LBL_none) {
978 scope = local_scope(tokval->t_charptr);
979 if (critical) {
980 nasm_nonfatal("symbol `%s%s' not defined%s",
981 scope,tokval->t_charptr,
982 pass_first() ? " before use" : "");
983 return NULL;
985 if (opflags)
986 *opflags |= OPFLAG_FORWARD;
987 type = EXPR_UNKNOWN;
988 label_seg = NO_SEG;
989 label_ofs = 1;
990 } else if (is_extern(ltype)) {
991 if (opflags)
992 *opflags |= OPFLAG_EXTERN;
995 addtotemp(type, label_ofs);
996 if (label_seg != NO_SEG)
997 addtotemp(EXPR_SEGBASE + label_seg, 1L);
998 break;
999 case TOKEN_DECORATOR:
1000 addtotemp(EXPR_RDSAE, tokval->t_integer);
1001 break;
1003 scan();
1004 return finishtemp();
1006 default:
1007 nasm_nonfatal("expression syntax error");
1008 return NULL;
1012 expr *evaluate(scanner sc, void *scprivate, struct tokenval *tv,
1013 int *fwref, bool crit, struct eval_hints *hints)
1015 expr *e;
1016 expr *f = NULL;
1018 deadman = 0;
1020 hint = hints;
1021 if (hint)
1022 hint->type = EAH_NOHINT;
1024 critical = crit;
1025 scanfunc = sc;
1026 scpriv = scprivate;
1027 tokval = tv;
1028 opflags = fwref;
1030 while (ntempexprs) /* initialize temporary storage */
1031 nasm_free(tempexprs[--ntempexprs]);
1033 tt = tokval->t_type;
1034 if (tt == TOKEN_INVALID)
1035 scan();
1037 e = bexpr();
1038 if (!e)
1039 return NULL;
1041 if (tt == TOKEN_WRT) {
1042 scan(); /* eat the WRT */
1043 f = expr6();
1044 if (!f)
1045 return NULL;
1047 e = scalar_mult(e, 1L, false); /* strip far-absolute segment part */
1048 if (f) {
1049 expr *g;
1050 if (is_just_unknown(f))
1051 g = unknown_expr();
1052 else {
1053 int64_t value;
1054 begintemp();
1055 if (!is_reloc(f)) {
1056 nasm_nonfatal("invalid right-hand operand to WRT");
1057 return NULL;
1059 value = reloc_seg(f);
1060 if (value == NO_SEG)
1061 value = reloc_value(f) | SEG_ABS;
1062 else if (!(value & SEG_ABS) && !(value % 2) && critical) {
1063 nasm_nonfatal("invalid right-hand operand to WRT");
1064 return NULL;
1066 addtotemp(EXPR_WRT, value);
1067 g = finishtemp();
1069 e = add_vectors(e, g);
1071 return e;