Make it possible for outputs to be either text or binary
[nasm/sigaren-mirror.git] / eval.c
blob92d3d691a3596aae8166d95592f892ca7898136a
1 /* ----------------------------------------------------------------------- *
2 *
3 * Copyright 1996-2009 The NASM Authors - All Rights Reserved
4 * See the file AUTHORS included with the NASM distribution for
5 * the specific copyright holders.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as
9 * published by the Free Software Foundation, Inc.,
10 * 51 Franklin St, Fifth Floor, Boston MA 02110-1301, USA; version 2.1,
11 * or, at your option, any later version, incorporated herein by
12 * reference.
14 * Patches submitted to this file are required to be dual licensed
15 * under the LGPL 2.1+ and the 2-clause BSD license:
17 * Copyright 1996-2009 the NASM Authors - All rights reserved.
19 * Redistribution and use in source and binary forms, with or without
20 * modification, are permitted provided that the following
21 * conditions are met:
23 * * Redistributions of source code must retain the above copyright
24 * notice, this list of conditions and the following disclaimer.
25 * * Redistributions in binary form must reproduce the above
26 * copyright notice, this list of conditions and the following
27 * disclaimer in the documentation and/or other materials provided
28 * with the distribution.
30 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
31 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
32 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
33 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
34 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
35 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
36 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
37 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
38 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
40 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
41 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
42 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
44 * ----------------------------------------------------------------------- */
47 * eval.c expression evaluator for the Netwide Assembler
50 #include "compiler.h"
52 #include <stdio.h>
53 #include <stdlib.h>
54 #include <stddef.h>
55 #include <string.h>
56 #include <ctype.h>
57 #include <inttypes.h>
59 #include "nasm.h"
60 #include "nasmlib.h"
61 #include "eval.h"
62 #include "labels.h"
63 #include "float.h"
65 #define TEMPEXPRS_DELTA 128
66 #define TEMPEXPR_DELTA 8
68 static scanner scan; /* Address of scanner routine */
69 static efunc error; /* Address of error reporting routine */
70 static lfunc labelfunc; /* Address of label routine */
72 static struct ofmt *outfmt; /* Structure of addresses of output routines */
74 static expr **tempexprs = NULL;
75 static int ntempexprs;
76 static int tempexprs_size = 0;
78 static expr *tempexpr;
79 static int ntempexpr;
80 static int tempexpr_size;
82 static struct tokenval *tokval; /* The current token */
83 static int i; /* The t_type of tokval */
85 static void *scpriv;
86 static struct location *location; /* Pointer to current line's segment,offset */
87 static int *opflags;
89 static struct eval_hints *hint;
91 extern int in_abs_seg; /* ABSOLUTE segment flag */
92 extern int32_t abs_seg; /* ABSOLUTE segment */
93 extern int32_t abs_offset; /* ABSOLUTE segment offset */
96 * Unimportant cleanup is done to avoid confusing people who are trying
97 * to debug real memory leaks
99 void eval_cleanup(void)
101 while (ntempexprs)
102 nasm_free(tempexprs[--ntempexprs]);
103 nasm_free(tempexprs);
107 * Construct a temporary expression.
109 static void begintemp(void)
111 tempexpr = NULL;
112 tempexpr_size = ntempexpr = 0;
115 static void addtotemp(int32_t type, int64_t value)
117 while (ntempexpr >= tempexpr_size) {
118 tempexpr_size += TEMPEXPR_DELTA;
119 tempexpr = nasm_realloc(tempexpr,
120 tempexpr_size * sizeof(*tempexpr));
122 tempexpr[ntempexpr].type = type;
123 tempexpr[ntempexpr++].value = value;
126 static expr *finishtemp(void)
128 addtotemp(0L, 0L); /* terminate */
129 while (ntempexprs >= tempexprs_size) {
130 tempexprs_size += TEMPEXPRS_DELTA;
131 tempexprs = nasm_realloc(tempexprs,
132 tempexprs_size * sizeof(*tempexprs));
134 return tempexprs[ntempexprs++] = tempexpr;
138 * Add two vector datatypes. We have some bizarre behaviour on far-
139 * absolute segment types: we preserve them during addition _only_
140 * if one of the segments is a truly pure scalar.
142 static expr *add_vectors(expr * p, expr * q)
144 int preserve;
146 preserve = is_really_simple(p) || is_really_simple(q);
148 begintemp();
150 while (p->type && q->type &&
151 p->type < EXPR_SEGBASE + SEG_ABS &&
152 q->type < EXPR_SEGBASE + SEG_ABS) {
153 int lasttype;
155 if (p->type > q->type) {
156 addtotemp(q->type, q->value);
157 lasttype = q++->type;
158 } else if (p->type < q->type) {
159 addtotemp(p->type, p->value);
160 lasttype = p++->type;
161 } else { /* *p and *q have same type */
162 int64_t sum = p->value + q->value;
163 if (sum)
164 addtotemp(p->type, sum);
165 lasttype = p->type;
166 p++, q++;
168 if (lasttype == EXPR_UNKNOWN) {
169 return finishtemp();
172 while (p->type && (preserve || p->type < EXPR_SEGBASE + SEG_ABS)) {
173 addtotemp(p->type, p->value);
174 p++;
176 while (q->type && (preserve || q->type < EXPR_SEGBASE + SEG_ABS)) {
177 addtotemp(q->type, q->value);
178 q++;
181 return finishtemp();
185 * Multiply a vector by a scalar. Strip far-absolute segment part
186 * if present.
188 * Explicit treatment of UNKNOWN is not required in this routine,
189 * since it will silently do the Right Thing anyway.
191 * If `affect_hints' is set, we also change the hint type to
192 * NOTBASE if a MAKEBASE hint points at a register being
193 * multiplied. This allows [eax*1+ebx] to hint EBX rather than EAX
194 * as the base register.
196 static expr *scalar_mult(expr * vect, int64_t scalar, int affect_hints)
198 expr *p = vect;
200 while (p->type && p->type < EXPR_SEGBASE + SEG_ABS) {
201 p->value = scalar * (p->value);
202 if (hint && hint->type == EAH_MAKEBASE &&
203 p->type == hint->base && affect_hints)
204 hint->type = EAH_NOTBASE;
205 p++;
207 p->type = 0;
209 return vect;
212 static expr *scalarvect(int64_t scalar)
214 begintemp();
215 addtotemp(EXPR_SIMPLE, scalar);
216 return finishtemp();
219 static expr *unknown_expr(void)
221 begintemp();
222 addtotemp(EXPR_UNKNOWN, 1L);
223 return finishtemp();
227 * The SEG operator: calculate the segment part of a relocatable
228 * value. Return NULL, as usual, if an error occurs. Report the
229 * error too.
231 static expr *segment_part(expr * e)
233 int32_t seg;
235 if (is_unknown(e))
236 return unknown_expr();
238 if (!is_reloc(e)) {
239 error(ERR_NONFATAL, "cannot apply SEG to a non-relocatable value");
240 return NULL;
243 seg = reloc_seg(e);
244 if (seg == NO_SEG) {
245 error(ERR_NONFATAL, "cannot apply SEG to a non-relocatable value");
246 return NULL;
247 } else if (seg & SEG_ABS) {
248 return scalarvect(seg & ~SEG_ABS);
249 } else if (seg & 1) {
250 error(ERR_NONFATAL, "SEG applied to something which"
251 " is already a segment base");
252 return NULL;
253 } else {
254 int32_t base = outfmt->segbase(seg + 1);
256 begintemp();
257 addtotemp((base == NO_SEG ? EXPR_UNKNOWN : EXPR_SEGBASE + base),
258 1L);
259 return finishtemp();
264 * Recursive-descent parser. Called with a single boolean operand,
265 * which is true if the evaluation is critical (i.e. unresolved
266 * symbols are an error condition). Must update the global `i' to
267 * reflect the token after the parsed string. May return NULL.
269 * evaluate() should report its own errors: on return it is assumed
270 * that if NULL has been returned, the error has already been
271 * reported.
275 * Grammar parsed is:
277 * expr : bexpr [ WRT expr6 ]
278 * bexpr : rexp0 or expr0 depending on relative-mode setting
279 * rexp0 : rexp1 [ {||} rexp1...]
280 * rexp1 : rexp2 [ {^^} rexp2...]
281 * rexp2 : rexp3 [ {&&} rexp3...]
282 * rexp3 : expr0 [ {=,==,<>,!=,<,>,<=,>=} expr0 ]
283 * expr0 : expr1 [ {|} expr1...]
284 * expr1 : expr2 [ {^} expr2...]
285 * expr2 : expr3 [ {&} expr3...]
286 * expr3 : expr4 [ {<<,>>} expr4...]
287 * expr4 : expr5 [ {+,-} expr5...]
288 * expr5 : expr6 [ {*,/,%,//,%%} expr6...]
289 * expr6 : { ~,+,-,SEG } expr6
290 * | (bexpr)
291 * | symbol
292 * | $
293 * | number
296 static expr *rexp0(int), *rexp1(int), *rexp2(int), *rexp3(int);
298 static expr *expr0(int), *expr1(int), *expr2(int), *expr3(int);
299 static expr *expr4(int), *expr5(int), *expr6(int);
301 static expr *(*bexpr) (int);
303 static expr *rexp0(int critical)
305 expr *e, *f;
307 e = rexp1(critical);
308 if (!e)
309 return NULL;
311 while (i == TOKEN_DBL_OR) {
312 i = scan(scpriv, tokval);
313 f = rexp1(critical);
314 if (!f)
315 return NULL;
316 if (!(is_simple(e) || is_just_unknown(e)) ||
317 !(is_simple(f) || is_just_unknown(f))) {
318 error(ERR_NONFATAL, "`|' operator may only be applied to"
319 " scalar values");
322 if (is_just_unknown(e) || is_just_unknown(f))
323 e = unknown_expr();
324 else
325 e = scalarvect((int64_t)(reloc_value(e) || reloc_value(f)));
327 return e;
330 static expr *rexp1(int critical)
332 expr *e, *f;
334 e = rexp2(critical);
335 if (!e)
336 return NULL;
338 while (i == TOKEN_DBL_XOR) {
339 i = scan(scpriv, tokval);
340 f = rexp2(critical);
341 if (!f)
342 return NULL;
343 if (!(is_simple(e) || is_just_unknown(e)) ||
344 !(is_simple(f) || is_just_unknown(f))) {
345 error(ERR_NONFATAL, "`^' operator may only be applied to"
346 " scalar values");
349 if (is_just_unknown(e) || is_just_unknown(f))
350 e = unknown_expr();
351 else
352 e = scalarvect((int64_t)(!reloc_value(e) ^ !reloc_value(f)));
354 return e;
357 static expr *rexp2(int critical)
359 expr *e, *f;
361 e = rexp3(critical);
362 if (!e)
363 return NULL;
364 while (i == TOKEN_DBL_AND) {
365 i = scan(scpriv, tokval);
366 f = rexp3(critical);
367 if (!f)
368 return NULL;
369 if (!(is_simple(e) || is_just_unknown(e)) ||
370 !(is_simple(f) || is_just_unknown(f))) {
371 error(ERR_NONFATAL, "`&' operator may only be applied to"
372 " scalar values");
374 if (is_just_unknown(e) || is_just_unknown(f))
375 e = unknown_expr();
376 else
377 e = scalarvect((int64_t)(reloc_value(e) && reloc_value(f)));
379 return e;
382 static expr *rexp3(int critical)
384 expr *e, *f;
385 int64_t v;
387 e = expr0(critical);
388 if (!e)
389 return NULL;
391 while (i == TOKEN_EQ || i == TOKEN_LT || i == TOKEN_GT ||
392 i == TOKEN_NE || i == TOKEN_LE || i == TOKEN_GE) {
393 int j = i;
394 i = scan(scpriv, tokval);
395 f = expr0(critical);
396 if (!f)
397 return NULL;
399 e = add_vectors(e, scalar_mult(f, -1L, false));
401 switch (j) {
402 case TOKEN_EQ:
403 case TOKEN_NE:
404 if (is_unknown(e))
405 v = -1; /* means unknown */
406 else if (!is_really_simple(e) || reloc_value(e) != 0)
407 v = (j == TOKEN_NE); /* unequal, so return true if NE */
408 else
409 v = (j == TOKEN_EQ); /* equal, so return true if EQ */
410 break;
411 default:
412 if (is_unknown(e))
413 v = -1; /* means unknown */
414 else if (!is_really_simple(e)) {
415 error(ERR_NONFATAL,
416 "`%s': operands differ by a non-scalar",
417 (j == TOKEN_LE ? "<=" : j == TOKEN_LT ? "<" : j ==
418 TOKEN_GE ? ">=" : ">"));
419 v = 0; /* must set it to _something_ */
420 } else {
421 int vv = reloc_value(e);
422 if (vv == 0)
423 v = (j == TOKEN_LE || j == TOKEN_GE);
424 else if (vv > 0)
425 v = (j == TOKEN_GE || j == TOKEN_GT);
426 else /* vv < 0 */
427 v = (j == TOKEN_LE || j == TOKEN_LT);
429 break;
432 if (v == -1)
433 e = unknown_expr();
434 else
435 e = scalarvect(v);
437 return e;
440 static expr *expr0(int critical)
442 expr *e, *f;
444 e = expr1(critical);
445 if (!e)
446 return NULL;
448 while (i == '|') {
449 i = scan(scpriv, tokval);
450 f = expr1(critical);
451 if (!f)
452 return NULL;
453 if (!(is_simple(e) || is_just_unknown(e)) ||
454 !(is_simple(f) || is_just_unknown(f))) {
455 error(ERR_NONFATAL, "`|' operator may only be applied to"
456 " scalar values");
458 if (is_just_unknown(e) || is_just_unknown(f))
459 e = unknown_expr();
460 else
461 e = scalarvect(reloc_value(e) | reloc_value(f));
463 return e;
466 static expr *expr1(int critical)
468 expr *e, *f;
470 e = expr2(critical);
471 if (!e)
472 return NULL;
474 while (i == '^') {
475 i = scan(scpriv, tokval);
476 f = expr2(critical);
477 if (!f)
478 return NULL;
479 if (!(is_simple(e) || is_just_unknown(e)) ||
480 !(is_simple(f) || is_just_unknown(f))) {
481 error(ERR_NONFATAL, "`^' operator may only be applied to"
482 " scalar values");
484 if (is_just_unknown(e) || is_just_unknown(f))
485 e = unknown_expr();
486 else
487 e = scalarvect(reloc_value(e) ^ reloc_value(f));
489 return e;
492 static expr *expr2(int critical)
494 expr *e, *f;
496 e = expr3(critical);
497 if (!e)
498 return NULL;
500 while (i == '&') {
501 i = scan(scpriv, tokval);
502 f = expr3(critical);
503 if (!f)
504 return NULL;
505 if (!(is_simple(e) || is_just_unknown(e)) ||
506 !(is_simple(f) || is_just_unknown(f))) {
507 error(ERR_NONFATAL, "`&' operator may only be applied to"
508 " scalar values");
510 if (is_just_unknown(e) || is_just_unknown(f))
511 e = unknown_expr();
512 else
513 e = scalarvect(reloc_value(e) & reloc_value(f));
515 return e;
518 static expr *expr3(int critical)
520 expr *e, *f;
522 e = expr4(critical);
523 if (!e)
524 return NULL;
526 while (i == TOKEN_SHL || i == TOKEN_SHR) {
527 int j = i;
528 i = scan(scpriv, tokval);
529 f = expr4(critical);
530 if (!f)
531 return NULL;
532 if (!(is_simple(e) || is_just_unknown(e)) ||
533 !(is_simple(f) || is_just_unknown(f))) {
534 error(ERR_NONFATAL, "shift operator may only be applied to"
535 " scalar values");
536 } else if (is_just_unknown(e) || is_just_unknown(f)) {
537 e = unknown_expr();
538 } else
539 switch (j) {
540 case TOKEN_SHL:
541 e = scalarvect(reloc_value(e) << reloc_value(f));
542 break;
543 case TOKEN_SHR:
544 e = scalarvect(((uint64_t)reloc_value(e)) >>
545 reloc_value(f));
546 break;
549 return e;
552 static expr *expr4(int critical)
554 expr *e, *f;
556 e = expr5(critical);
557 if (!e)
558 return NULL;
559 while (i == '+' || i == '-') {
560 int j = i;
561 i = scan(scpriv, tokval);
562 f = expr5(critical);
563 if (!f)
564 return NULL;
565 switch (j) {
566 case '+':
567 e = add_vectors(e, f);
568 break;
569 case '-':
570 e = add_vectors(e, scalar_mult(f, -1L, false));
571 break;
574 return e;
577 static expr *expr5(int critical)
579 expr *e, *f;
581 e = expr6(critical);
582 if (!e)
583 return NULL;
584 while (i == '*' || i == '/' || i == '%' ||
585 i == TOKEN_SDIV || i == TOKEN_SMOD) {
586 int j = i;
587 i = scan(scpriv, tokval);
588 f = expr6(critical);
589 if (!f)
590 return NULL;
591 if (j != '*' && (!(is_simple(e) || is_just_unknown(e)) ||
592 !(is_simple(f) || is_just_unknown(f)))) {
593 error(ERR_NONFATAL, "division operator may only be applied to"
594 " scalar values");
595 return NULL;
597 if (j != '*' && !is_unknown(f) && reloc_value(f) == 0) {
598 error(ERR_NONFATAL, "division by zero");
599 return NULL;
601 switch (j) {
602 case '*':
603 if (is_simple(e))
604 e = scalar_mult(f, reloc_value(e), true);
605 else if (is_simple(f))
606 e = scalar_mult(e, reloc_value(f), true);
607 else if (is_just_unknown(e) && is_just_unknown(f))
608 e = unknown_expr();
609 else {
610 error(ERR_NONFATAL, "unable to multiply two "
611 "non-scalar objects");
612 return NULL;
614 break;
615 case '/':
616 if (is_just_unknown(e) || is_just_unknown(f))
617 e = unknown_expr();
618 else
619 e = scalarvect(((uint64_t)reloc_value(e)) /
620 ((uint64_t)reloc_value(f)));
621 break;
622 case '%':
623 if (is_just_unknown(e) || is_just_unknown(f))
624 e = unknown_expr();
625 else
626 e = scalarvect(((uint64_t)reloc_value(e)) %
627 ((uint64_t)reloc_value(f)));
628 break;
629 case TOKEN_SDIV:
630 if (is_just_unknown(e) || is_just_unknown(f))
631 e = unknown_expr();
632 else
633 e = scalarvect(((int64_t)reloc_value(e)) /
634 ((int64_t)reloc_value(f)));
635 break;
636 case TOKEN_SMOD:
637 if (is_just_unknown(e) || is_just_unknown(f))
638 e = unknown_expr();
639 else
640 e = scalarvect(((int64_t)reloc_value(e)) %
641 ((int64_t)reloc_value(f)));
642 break;
645 return e;
648 static expr *eval_floatize(enum floatize type)
650 uint8_t result[16], *p; /* Up to 128 bits */
651 static const struct {
652 int bytes, start, len;
653 } formats[] = {
654 { 1, 0, 1 }, /* FLOAT_8 */
655 { 2, 0, 2 }, /* FLOAT_16 */
656 { 4, 0, 4 }, /* FLOAT_32 */
657 { 8, 0, 8 }, /* FLOAT_64 */
658 { 10, 0, 8 }, /* FLOAT_80M */
659 { 10, 8, 2 }, /* FLOAT_80E */
660 { 16, 0, 8 }, /* FLOAT_128L */
661 { 16, 8, 8 }, /* FLOAT_128H */
663 int sign = 1;
664 int64_t val;
665 int j;
667 i = scan(scpriv, tokval);
668 if (i != '(') {
669 error(ERR_NONFATAL, "expecting `('");
670 return NULL;
672 i = scan(scpriv, tokval);
673 if (i == '-' || i == '+') {
674 sign = (i == '-') ? -1 : 1;
675 i = scan(scpriv, tokval);
677 if (i != TOKEN_FLOAT) {
678 error(ERR_NONFATAL, "expecting floating-point number");
679 return NULL;
681 if (!float_const(tokval->t_charptr, sign, result,
682 formats[type].bytes, error))
683 return NULL;
684 i = scan(scpriv, tokval);
685 if (i != ')') {
686 error(ERR_NONFATAL, "expecting `)'");
687 return NULL;
690 p = result+formats[type].start+formats[type].len;
691 val = 0;
692 for (j = formats[type].len; j; j--) {
693 p--;
694 val = (val << 8) + *p;
697 begintemp();
698 addtotemp(EXPR_SIMPLE, val);
700 i = scan(scpriv, tokval);
701 return finishtemp();
704 static expr *eval_strfunc(enum strfunc type)
706 char *string;
707 size_t string_len;
708 int64_t val;
709 bool parens, rn_warn;
711 parens = false;
712 i = scan(scpriv, tokval);
713 if (i == '(') {
714 parens = true;
715 i = scan(scpriv, tokval);
717 if (i != TOKEN_STR) {
718 error(ERR_NONFATAL, "expecting string");
719 return NULL;
721 string_len = string_transform(tokval->t_charptr, tokval->t_inttwo,
722 &string, type);
723 if (string_len == (size_t)-1) {
724 error(ERR_NONFATAL, "invalid string for transform");
725 return NULL;
728 val = readstrnum(string, string_len, &rn_warn);
729 if (parens) {
730 i = scan(scpriv, tokval);
731 if (i != ')') {
732 error(ERR_NONFATAL, "expecting `)'");
733 return NULL;
737 if (rn_warn)
738 error(ERR_WARNING|ERR_PASS1, "character constant too long");
740 begintemp();
741 addtotemp(EXPR_SIMPLE, val);
743 i = scan(scpriv, tokval);
744 return finishtemp();
747 static expr *expr6(int critical)
749 int32_t type;
750 expr *e;
751 int32_t label_seg;
752 int64_t label_ofs;
753 int64_t tmpval;
754 bool rn_warn;
755 char *scope;
757 switch (i) {
758 case '-':
759 i = scan(scpriv, tokval);
760 e = expr6(critical);
761 if (!e)
762 return NULL;
763 return scalar_mult(e, -1L, false);
766 case '+':
767 i = scan(scpriv, tokval);
768 return expr6(critical);
770 case '~':
771 i = scan(scpriv, tokval);
772 e = expr6(critical);
773 if (!e)
774 return NULL;
775 if (is_just_unknown(e))
776 return unknown_expr();
777 else if (!is_simple(e)) {
778 error(ERR_NONFATAL, "`~' operator may only be applied to"
779 " scalar values");
780 return NULL;
782 return scalarvect(~reloc_value(e));
784 case '!':
785 i = scan(scpriv, tokval);
786 e = expr6(critical);
787 if (!e)
788 return NULL;
789 if (is_just_unknown(e))
790 return unknown_expr();
791 else if (!is_simple(e)) {
792 error(ERR_NONFATAL, "`!' operator may only be applied to"
793 " scalar values");
794 return NULL;
796 return scalarvect(!reloc_value(e));
798 case TOKEN_SEG:
799 i = scan(scpriv, tokval);
800 e = expr6(critical);
801 if (!e)
802 return NULL;
803 e = segment_part(e);
804 if (!e)
805 return NULL;
806 if (is_unknown(e) && critical) {
807 error(ERR_NONFATAL, "unable to determine segment base");
808 return NULL;
810 return e;
812 case TOKEN_FLOATIZE:
813 return eval_floatize(tokval->t_integer);
815 case TOKEN_STRFUNC:
816 return eval_strfunc(tokval->t_integer);
818 case '(':
819 i = scan(scpriv, tokval);
820 e = bexpr(critical);
821 if (!e)
822 return NULL;
823 if (i != ')') {
824 error(ERR_NONFATAL, "expecting `)'");
825 return NULL;
827 i = scan(scpriv, tokval);
828 return e;
830 case TOKEN_NUM:
831 case TOKEN_STR:
832 case TOKEN_REG:
833 case TOKEN_ID:
834 case TOKEN_INSN: /* Opcodes that occur here are really labels */
835 case TOKEN_HERE:
836 case TOKEN_BASE:
837 begintemp();
838 switch (i) {
839 case TOKEN_NUM:
840 addtotemp(EXPR_SIMPLE, tokval->t_integer);
841 break;
842 case TOKEN_STR:
843 tmpval = readstrnum(tokval->t_charptr, tokval->t_inttwo, &rn_warn);
844 if (rn_warn)
845 error(ERR_WARNING|ERR_PASS1, "character constant too long");
846 addtotemp(EXPR_SIMPLE, tmpval);
847 break;
848 case TOKEN_REG:
849 addtotemp(tokval->t_integer, 1L);
850 if (hint && hint->type == EAH_NOHINT)
851 hint->base = tokval->t_integer, hint->type = EAH_MAKEBASE;
852 break;
853 case TOKEN_ID:
854 case TOKEN_INSN:
855 case TOKEN_HERE:
856 case TOKEN_BASE:
858 * If !location->known, this indicates that no
859 * symbol, Here or Base references are valid because we
860 * are in preprocess-only mode.
862 if (!location->known) {
863 error(ERR_NONFATAL,
864 "%s not supported in preprocess-only mode",
865 (i == TOKEN_HERE ? "`$'" :
866 i == TOKEN_BASE ? "`$$'" :
867 "symbol references"));
868 addtotemp(EXPR_UNKNOWN, 1L);
869 break;
872 type = EXPR_SIMPLE; /* might get overridden by UNKNOWN */
873 if (i == TOKEN_BASE) {
874 label_seg = in_abs_seg ? abs_seg : location->segment;
875 label_ofs = 0;
876 } else if (i == TOKEN_HERE) {
877 label_seg = in_abs_seg ? abs_seg : location->segment;
878 label_ofs = in_abs_seg ? abs_offset : location->offset;
879 } else {
880 if (!labelfunc(tokval->t_charptr, &label_seg, &label_ofs)) {
881 scope = local_scope(tokval->t_charptr);
882 if (critical == 2) {
883 error(ERR_NONFATAL, "symbol `%s%s' undefined",
884 scope,tokval->t_charptr);
885 return NULL;
886 } else if (critical == 1) {
887 error(ERR_NONFATAL,
888 "symbol `%s%s' not defined before use",
889 scope,tokval->t_charptr);
890 return NULL;
891 } else {
892 if (opflags)
893 *opflags |= 1;
894 type = EXPR_UNKNOWN;
895 label_seg = NO_SEG;
896 label_ofs = 1;
899 if (opflags && is_extern(tokval->t_charptr))
900 *opflags |= OPFLAG_EXTERN;
902 addtotemp(type, label_ofs);
903 if (label_seg != NO_SEG)
904 addtotemp(EXPR_SEGBASE + label_seg, 1L);
905 break;
907 i = scan(scpriv, tokval);
908 return finishtemp();
910 default:
911 error(ERR_NONFATAL, "expression syntax error");
912 return NULL;
916 void eval_global_info(struct ofmt *output, lfunc lookup_label,
917 struct location * locp)
919 outfmt = output;
920 labelfunc = lookup_label;
921 location = locp;
924 expr *evaluate(scanner sc, void *scprivate, struct tokenval *tv,
925 int *fwref, int critical, efunc report_error,
926 struct eval_hints *hints)
928 expr *e;
929 expr *f = NULL;
931 hint = hints;
932 if (hint)
933 hint->type = EAH_NOHINT;
935 if (critical & CRITICAL) {
936 critical &= ~CRITICAL;
937 bexpr = rexp0;
938 } else
939 bexpr = expr0;
941 scan = sc;
942 scpriv = scprivate;
943 tokval = tv;
944 error = report_error;
945 opflags = fwref;
947 if (tokval->t_type == TOKEN_INVALID)
948 i = scan(scpriv, tokval);
949 else
950 i = tokval->t_type;
952 while (ntempexprs) /* initialize temporary storage */
953 nasm_free(tempexprs[--ntempexprs]);
955 e = bexpr(critical);
956 if (!e)
957 return NULL;
959 if (i == TOKEN_WRT) {
960 i = scan(scpriv, tokval); /* eat the WRT */
961 f = expr6(critical);
962 if (!f)
963 return NULL;
965 e = scalar_mult(e, 1L, false); /* strip far-absolute segment part */
966 if (f) {
967 expr *g;
968 if (is_just_unknown(f))
969 g = unknown_expr();
970 else {
971 int64_t value;
972 begintemp();
973 if (!is_reloc(f)) {
974 error(ERR_NONFATAL, "invalid right-hand operand to WRT");
975 return NULL;
977 value = reloc_seg(f);
978 if (value == NO_SEG)
979 value = reloc_value(f) | SEG_ABS;
980 else if (!(value & SEG_ABS) && !(value % 2) && critical) {
981 error(ERR_NONFATAL, "invalid right-hand operand to WRT");
982 return NULL;
984 addtotemp(EXPR_WRT, value);
985 g = finishtemp();
987 e = add_vectors(e, g);
989 return e;