Support __float*__ for floating-point numbers in expressions
[platform/upstream/nasm.git] / eval.c
1 /* eval.c    expression evaluator for the Netwide Assembler
2  *
3  * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
4  * Julian Hall. All rights reserved. The software is
5  * redistributable under the licence given in the file "Licence"
6  * distributed in the NASM archive.
7  *
8  * initial version 27/iii/95 by Simon Tatham
9  */
10
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <stddef.h>
14 #include <string.h>
15 #include <ctype.h>
16 #include <inttypes.h>
17
18 #include "nasm.h"
19 #include "nasmlib.h"
20 #include "eval.h"
21 #include "labels.h"
22 #include "float.h"
23
24 #define TEMPEXPRS_DELTA 128
25 #define TEMPEXPR_DELTA 8
26
27 static scanner scan;            /* Address of scanner routine */
28 static efunc error;             /* Address of error reporting routine */
29 static lfunc labelfunc;         /* Address of label routine */
30
31 static struct ofmt *outfmt;     /* Structure of addresses of output routines */
32
33 static expr **tempexprs = NULL;
34 static int ntempexprs;
35 static int tempexprs_size = 0;
36
37 static expr *tempexpr;
38 static int ntempexpr;
39 static int tempexpr_size;
40
41 static struct tokenval *tokval; /* The current token */
42 static int i;                   /* The t_type of tokval */
43
44 static void *scpriv;
45 static loc_t *location;         /* Pointer to current line's segment,offset */
46 static int *opflags;
47
48 static struct eval_hints *hint;
49
50 extern int in_abs_seg;          /* ABSOLUTE segment flag */
51 extern int32_t abs_seg;            /* ABSOLUTE segment */
52 extern int32_t abs_offset;         /* ABSOLUTE segment offset */
53
54 /*
55  * Unimportant cleanup is done to avoid confusing people who are trying
56  * to debug real memory leaks
57  */
58 void eval_cleanup(void)
59 {
60     while (ntempexprs)
61         nasm_free(tempexprs[--ntempexprs]);
62     nasm_free(tempexprs);
63 }
64
65 /*
66  * Construct a temporary expression.
67  */
68 static void begintemp(void)
69 {
70     tempexpr = NULL;
71     tempexpr_size = ntempexpr = 0;
72 }
73
74 static void addtotemp(int32_t type, int64_t value)
75 {
76     while (ntempexpr >= tempexpr_size) {
77         tempexpr_size += TEMPEXPR_DELTA;
78         tempexpr = nasm_realloc(tempexpr,
79                                 tempexpr_size * sizeof(*tempexpr));
80     }
81     tempexpr[ntempexpr].type = type;
82     tempexpr[ntempexpr++].value = value;
83 }
84
85 static expr *finishtemp(void)
86 {
87     addtotemp(0L, 0L);          /* terminate */
88     while (ntempexprs >= tempexprs_size) {
89         tempexprs_size += TEMPEXPRS_DELTA;
90         tempexprs = nasm_realloc(tempexprs,
91                                  tempexprs_size * sizeof(*tempexprs));
92     }
93     return tempexprs[ntempexprs++] = tempexpr;
94 }
95
96 /*
97  * Add two vector datatypes. We have some bizarre behaviour on far-
98  * absolute segment types: we preserve them during addition _only_
99  * if one of the segments is a truly pure scalar.
100  */
101 static expr *add_vectors(expr * p, expr * q)
102 {
103     int preserve;
104
105     preserve = is_really_simple(p) || is_really_simple(q);
106
107     begintemp();
108
109     while (p->type && q->type &&
110            p->type < EXPR_SEGBASE + SEG_ABS &&
111            q->type < EXPR_SEGBASE + SEG_ABS) {
112         int lasttype;
113
114         if (p->type > q->type) {
115             addtotemp(q->type, q->value);
116             lasttype = q++->type;
117         } else if (p->type < q->type) {
118             addtotemp(p->type, p->value);
119             lasttype = p++->type;
120         } else {                /* *p and *q have same type */
121             int32_t sum = p->value + q->value;
122             if (sum)
123                 addtotemp(p->type, sum);
124             lasttype = p->type;
125             p++, q++;
126         }
127         if (lasttype == EXPR_UNKNOWN) {
128             return finishtemp();
129         }
130     }
131     while (p->type && (preserve || p->type < EXPR_SEGBASE + SEG_ABS)) {
132         addtotemp(p->type, p->value);
133         p++;
134     }
135     while (q->type && (preserve || q->type < EXPR_SEGBASE + SEG_ABS)) {
136         addtotemp(q->type, q->value);
137         q++;
138     }
139
140     return finishtemp();
141 }
142
143 /*
144  * Multiply a vector by a scalar. Strip far-absolute segment part
145  * if present.
146  *
147  * Explicit treatment of UNKNOWN is not required in this routine,
148  * since it will silently do the Right Thing anyway.
149  *
150  * If `affect_hints' is set, we also change the hint type to
151  * NOTBASE if a MAKEBASE hint points at a register being
152  * multiplied. This allows [eax*1+ebx] to hint EBX rather than EAX
153  * as the base register.
154  */
155 static expr *scalar_mult(expr * vect, int32_t scalar, int affect_hints)
156 {
157     expr *p = vect;
158
159     while (p->type && p->type < EXPR_SEGBASE + SEG_ABS) {
160         p->value = scalar * (p->value);
161         if (hint && hint->type == EAH_MAKEBASE &&
162             p->type == hint->base && affect_hints)
163             hint->type = EAH_NOTBASE;
164         p++;
165     }
166     p->type = 0;
167
168     return vect;
169 }
170
171 static expr *scalarvect(int32_t scalar)
172 {
173     begintemp();
174     addtotemp(EXPR_SIMPLE, scalar);
175     return finishtemp();
176 }
177
178 static expr *unknown_expr(void)
179 {
180     begintemp();
181     addtotemp(EXPR_UNKNOWN, 1L);
182     return finishtemp();
183 }
184
185 /*
186  * The SEG operator: calculate the segment part of a relocatable
187  * value. Return NULL, as usual, if an error occurs. Report the
188  * error too.
189  */
190 static expr *segment_part(expr * e)
191 {
192     int32_t seg;
193
194     if (is_unknown(e))
195         return unknown_expr();
196
197     if (!is_reloc(e)) {
198         error(ERR_NONFATAL, "cannot apply SEG to a non-relocatable value");
199         return NULL;
200     }
201
202     seg = reloc_seg(e);
203     if (seg == NO_SEG) {
204         error(ERR_NONFATAL, "cannot apply SEG to a non-relocatable value");
205         return NULL;
206     } else if (seg & SEG_ABS) {
207         return scalarvect(seg & ~SEG_ABS);
208     } else if (seg & 1) {
209         error(ERR_NONFATAL, "SEG applied to something which"
210               " is already a segment base");
211         return NULL;
212     } else {
213         int32_t base = outfmt->segbase(seg + 1);
214
215         begintemp();
216         addtotemp((base == NO_SEG ? EXPR_UNKNOWN : EXPR_SEGBASE + base),
217                   1L);
218         return finishtemp();
219     }
220 }
221
222 /*
223  * Recursive-descent parser. Called with a single boolean operand,
224  * which is TRUE if the evaluation is critical (i.e. unresolved
225  * symbols are an error condition). Must update the global `i' to
226  * reflect the token after the parsed string. May return NULL.
227  *
228  * evaluate() should report its own errors: on return it is assumed
229  * that if NULL has been returned, the error has already been
230  * reported.
231  */
232
233 /*
234  * Grammar parsed is:
235  *
236  * expr  : bexpr [ WRT expr6 ]
237  * bexpr : rexp0 or expr0 depending on relative-mode setting
238  * rexp0 : rexp1 [ {||} rexp1...]
239  * rexp1 : rexp2 [ {^^} rexp2...]
240  * rexp2 : rexp3 [ {&&} rexp3...]
241  * rexp3 : expr0 [ {=,==,<>,!=,<,>,<=,>=} expr0 ]
242  * expr0 : expr1 [ {|} expr1...]
243  * expr1 : expr2 [ {^} expr2...]
244  * expr2 : expr3 [ {&} expr3...]
245  * expr3 : expr4 [ {<<,>>} expr4...]
246  * expr4 : expr5 [ {+,-} expr5...]
247  * expr5 : expr6 [ {*,/,%,//,%%} expr6...]
248  * expr6 : { ~,+,-,SEG } expr6
249  *       | (bexpr)
250  *       | symbol
251  *       | $
252  *       | number
253  */
254
255 static expr *rexp0(int), *rexp1(int), *rexp2(int), *rexp3(int);
256
257 static expr *expr0(int), *expr1(int), *expr2(int), *expr3(int);
258 static expr *expr4(int), *expr5(int), *expr6(int);
259
260 static expr *(*bexpr) (int);
261
262 static expr *rexp0(int critical)
263 {
264     expr *e, *f;
265
266     e = rexp1(critical);
267     if (!e)
268         return NULL;
269
270     while (i == TOKEN_DBL_OR) {
271         i = scan(scpriv, tokval);
272         f = rexp1(critical);
273         if (!f)
274             return NULL;
275         if (!(is_simple(e) || is_just_unknown(e)) ||
276             !(is_simple(f) || is_just_unknown(f))) {
277             error(ERR_NONFATAL, "`|' operator may only be applied to"
278                   " scalar values");
279         }
280
281         if (is_just_unknown(e) || is_just_unknown(f))
282             e = unknown_expr();
283         else
284             e = scalarvect((int32_t)(reloc_value(e) || reloc_value(f)));
285     }
286     return e;
287 }
288
289 static expr *rexp1(int critical)
290 {
291     expr *e, *f;
292
293     e = rexp2(critical);
294     if (!e)
295         return NULL;
296
297     while (i == TOKEN_DBL_XOR) {
298         i = scan(scpriv, tokval);
299         f = rexp2(critical);
300         if (!f)
301             return NULL;
302         if (!(is_simple(e) || is_just_unknown(e)) ||
303             !(is_simple(f) || is_just_unknown(f))) {
304             error(ERR_NONFATAL, "`^' operator may only be applied to"
305                   " scalar values");
306         }
307
308         if (is_just_unknown(e) || is_just_unknown(f))
309             e = unknown_expr();
310         else
311             e = scalarvect((int32_t)(!reloc_value(e) ^ !reloc_value(f)));
312     }
313     return e;
314 }
315
316 static expr *rexp2(int critical)
317 {
318     expr *e, *f;
319
320     e = rexp3(critical);
321     if (!e)
322         return NULL;
323     while (i == TOKEN_DBL_AND) {
324         i = scan(scpriv, tokval);
325         f = rexp3(critical);
326         if (!f)
327             return NULL;
328         if (!(is_simple(e) || is_just_unknown(e)) ||
329             !(is_simple(f) || is_just_unknown(f))) {
330             error(ERR_NONFATAL, "`&' operator may only be applied to"
331                   " scalar values");
332         }
333         if (is_just_unknown(e) || is_just_unknown(f))
334             e = unknown_expr();
335         else
336             e = scalarvect((int32_t)(reloc_value(e) && reloc_value(f)));
337     }
338     return e;
339 }
340
341 static expr *rexp3(int critical)
342 {
343     expr *e, *f;
344     int32_t v;
345
346     e = expr0(critical);
347     if (!e)
348         return NULL;
349
350     while (i == TOKEN_EQ || i == TOKEN_LT || i == TOKEN_GT ||
351            i == TOKEN_NE || i == TOKEN_LE || i == TOKEN_GE) {
352         int j = i;
353         i = scan(scpriv, tokval);
354         f = expr0(critical);
355         if (!f)
356             return NULL;
357
358         e = add_vectors(e, scalar_mult(f, -1L, FALSE));
359
360         switch (j) {
361         case TOKEN_EQ:
362         case TOKEN_NE:
363             if (is_unknown(e))
364                 v = -1;         /* means unknown */
365             else if (!is_really_simple(e) || reloc_value(e) != 0)
366                 v = (j == TOKEN_NE);    /* unequal, so return TRUE if NE */
367             else
368                 v = (j == TOKEN_EQ);    /* equal, so return TRUE if EQ */
369             break;
370         default:
371             if (is_unknown(e))
372                 v = -1;         /* means unknown */
373             else if (!is_really_simple(e)) {
374                 error(ERR_NONFATAL,
375                       "`%s': operands differ by a non-scalar",
376                       (j == TOKEN_LE ? "<=" : j == TOKEN_LT ? "<" : j ==
377                        TOKEN_GE ? ">=" : ">"));
378                 v = 0;          /* must set it to _something_ */
379             } else {
380                 int vv = reloc_value(e);
381                 if (vv == 0)
382                     v = (j == TOKEN_LE || j == TOKEN_GE);
383                 else if (vv > 0)
384                     v = (j == TOKEN_GE || j == TOKEN_GT);
385                 else            /* vv < 0 */
386                     v = (j == TOKEN_LE || j == TOKEN_LT);
387             }
388             break;
389         }
390
391         if (v == -1)
392             e = unknown_expr();
393         else
394             e = scalarvect(v);
395     }
396     return e;
397 }
398
399 static expr *expr0(int critical)
400 {
401     expr *e, *f;
402
403     e = expr1(critical);
404     if (!e)
405         return NULL;
406
407     while (i == '|') {
408         i = scan(scpriv, tokval);
409         f = expr1(critical);
410         if (!f)
411             return NULL;
412         if (!(is_simple(e) || is_just_unknown(e)) ||
413             !(is_simple(f) || is_just_unknown(f))) {
414             error(ERR_NONFATAL, "`|' operator may only be applied to"
415                   " scalar values");
416         }
417         if (is_just_unknown(e) || is_just_unknown(f))
418             e = unknown_expr();
419         else
420             e = scalarvect(reloc_value(e) | reloc_value(f));
421     }
422     return e;
423 }
424
425 static expr *expr1(int critical)
426 {
427     expr *e, *f;
428
429     e = expr2(critical);
430     if (!e)
431         return NULL;
432
433     while (i == '^') {
434         i = scan(scpriv, tokval);
435         f = expr2(critical);
436         if (!f)
437             return NULL;
438         if (!(is_simple(e) || is_just_unknown(e)) ||
439             !(is_simple(f) || is_just_unknown(f))) {
440             error(ERR_NONFATAL, "`^' operator may only be applied to"
441                   " scalar values");
442         }
443         if (is_just_unknown(e) || is_just_unknown(f))
444             e = unknown_expr();
445         else
446             e = scalarvect(reloc_value(e) ^ reloc_value(f));
447     }
448     return e;
449 }
450
451 static expr *expr2(int critical)
452 {
453     expr *e, *f;
454
455     e = expr3(critical);
456     if (!e)
457         return NULL;
458
459     while (i == '&') {
460         i = scan(scpriv, tokval);
461         f = expr3(critical);
462         if (!f)
463             return NULL;
464         if (!(is_simple(e) || is_just_unknown(e)) ||
465             !(is_simple(f) || is_just_unknown(f))) {
466             error(ERR_NONFATAL, "`&' operator may only be applied to"
467                   " scalar values");
468         }
469         if (is_just_unknown(e) || is_just_unknown(f))
470             e = unknown_expr();
471         else
472             e = scalarvect(reloc_value(e) & reloc_value(f));
473     }
474     return e;
475 }
476
477 static expr *expr3(int critical)
478 {
479     expr *e, *f;
480
481     e = expr4(critical);
482     if (!e)
483         return NULL;
484
485     while (i == TOKEN_SHL || i == TOKEN_SHR) {
486         int j = i;
487         i = scan(scpriv, tokval);
488         f = expr4(critical);
489         if (!f)
490             return NULL;
491         if (!(is_simple(e) || is_just_unknown(e)) ||
492             !(is_simple(f) || is_just_unknown(f))) {
493             error(ERR_NONFATAL, "shift operator may only be applied to"
494                   " scalar values");
495         } else if (is_just_unknown(e) || is_just_unknown(f)) {
496             e = unknown_expr();
497         } else
498             switch (j) {
499             case TOKEN_SHL:
500                 e = scalarvect(reloc_value(e) << reloc_value(f));
501                 break;
502             case TOKEN_SHR:
503                 e = scalarvect(((uint32_t)reloc_value(e)) >>
504                                reloc_value(f));
505                 break;
506             }
507     }
508     return e;
509 }
510
511 static expr *expr4(int critical)
512 {
513     expr *e, *f;
514
515     e = expr5(critical);
516     if (!e)
517         return NULL;
518     while (i == '+' || i == '-') {
519         int j = i;
520         i = scan(scpriv, tokval);
521         f = expr5(critical);
522         if (!f)
523             return NULL;
524         switch (j) {
525         case '+':
526             e = add_vectors(e, f);
527             break;
528         case '-':
529             e = add_vectors(e, scalar_mult(f, -1L, FALSE));
530             break;
531         }
532     }
533     return e;
534 }
535
536 static expr *expr5(int critical)
537 {
538     expr *e, *f;
539
540     e = expr6(critical);
541     if (!e)
542         return NULL;
543     while (i == '*' || i == '/' || i == '%' ||
544            i == TOKEN_SDIV || i == TOKEN_SMOD) {
545         int j = i;
546         i = scan(scpriv, tokval);
547         f = expr6(critical);
548         if (!f)
549             return NULL;
550         if (j != '*' && (!(is_simple(e) || is_just_unknown(e)) ||
551                          !(is_simple(f) || is_just_unknown(f)))) {
552             error(ERR_NONFATAL, "division operator may only be applied to"
553                   " scalar values");
554             return NULL;
555         }
556         if (j != '*' && !is_unknown(f) && reloc_value(f) == 0) {
557             error(ERR_NONFATAL, "division by zero");
558             return NULL;
559         }
560         switch (j) {
561         case '*':
562             if (is_simple(e))
563                 e = scalar_mult(f, reloc_value(e), TRUE);
564             else if (is_simple(f))
565                 e = scalar_mult(e, reloc_value(f), TRUE);
566             else if (is_just_unknown(e) && is_just_unknown(f))
567                 e = unknown_expr();
568             else {
569                 error(ERR_NONFATAL, "unable to multiply two "
570                       "non-scalar objects");
571                 return NULL;
572             }
573             break;
574         case '/':
575             if (is_just_unknown(e) || is_just_unknown(f))
576                 e = unknown_expr();
577             else
578                 e = scalarvect(((uint32_t)reloc_value(e)) /
579                                ((uint32_t)reloc_value(f)));
580             break;
581         case '%':
582             if (is_just_unknown(e) || is_just_unknown(f))
583                 e = unknown_expr();
584             else
585                 e = scalarvect(((uint32_t)reloc_value(e)) %
586                                ((uint32_t)reloc_value(f)));
587             break;
588         case TOKEN_SDIV:
589             if (is_just_unknown(e) || is_just_unknown(f))
590                 e = unknown_expr();
591             else
592                 e = scalarvect(((int32_t)reloc_value(e)) /
593                                ((int32_t)reloc_value(f)));
594             break;
595         case TOKEN_SMOD:
596             if (is_just_unknown(e) || is_just_unknown(f))
597                 e = unknown_expr();
598             else
599                 e = scalarvect(((int32_t)reloc_value(e)) %
600                                ((int32_t)reloc_value(f)));
601             break;
602         }
603     }
604     return e;
605 }
606
607 static expr *eval_floatize(enum floatize type)
608 {
609     uint8_t result[16], *p;     /* Up to 128 bits */
610     static const struct {
611         int bytes, start, len;
612     } formats[] = {
613         {  2, 0, 2 },           /* FLOAT_16 */
614         {  4, 0, 4 },           /* FLOAT_32 */
615         {  8, 0, 8 },           /* FLOAT_64 */
616         { 10, 0, 8 },           /* FLOAT_80M */
617         { 10, 8, 2 },           /* FLOAT_80E */
618         { 16, 0, 8 },           /* FLOAT_128L */
619         { 16, 8, 8 },           /* FLOAT_128H */
620     };
621     int sign = 1;
622     int64_t val;
623     int j;
624         
625     i = scan(scpriv, tokval);
626     if (i != '(') {
627         error(ERR_NONFATAL, "expecting `('");
628         return NULL;
629     }
630     i = scan(scpriv, tokval);
631     if (i == '-' || i == '+') {
632         sign = (i == '-') ? -1 : 1;
633         i = scan(scpriv, tokval);
634     }
635     if (i != TOKEN_FLOAT) {
636         error(ERR_NONFATAL, "expecting floating-point number");
637         return NULL;
638     }
639     if (!float_const(tokval->t_charptr, sign, result,
640                      formats[type].bytes, error))
641         return NULL;
642     i = scan(scpriv, tokval);
643     if (i != ')') {
644         error(ERR_NONFATAL, "expecting `)'");
645         return NULL;
646     }
647
648     p = result+formats[type].start+formats[type].len;
649     val = 0;
650     for (j = formats[type].len; j; j--) {
651         p--;
652         val = (val << 8) + *p;
653     }
654
655     begintemp();
656     addtotemp(EXPR_SIMPLE, val);
657
658     i = scan(scpriv, tokval);
659     return finishtemp();
660 }
661
662 static expr *expr6(int critical)
663 {
664     int32_t type;
665     expr *e;
666     int32_t label_seg, label_ofs;
667
668     switch (i) {
669     case '-':
670         i = scan(scpriv, tokval);
671         e = expr6(critical);
672         if (!e)
673             return NULL;
674         return scalar_mult(e, -1L, FALSE);
675
676
677     case '+':
678         i = scan(scpriv, tokval);
679         return expr6(critical);
680
681     case '~':
682         i = scan(scpriv, tokval);
683         e = expr6(critical);
684         if (!e)
685             return NULL;
686         if (is_just_unknown(e))
687             return unknown_expr();
688         else if (!is_simple(e)) {
689             error(ERR_NONFATAL, "`~' operator may only be applied to"
690                   " scalar values");
691             return NULL;
692         }
693         return scalarvect(~reloc_value(e));
694
695     case '!':
696         i = scan(scpriv, tokval);
697         e = expr6(critical);
698         if (!e)
699             return NULL;
700         if (is_just_unknown(e))
701             return unknown_expr();
702         else if (!is_simple(e)) {
703             error(ERR_NONFATAL, "`!' operator may only be applied to"
704                   " scalar values");
705             return NULL;
706         }
707         return scalarvect(!reloc_value(e));
708
709     case TOKEN_SEG:
710         i = scan(scpriv, tokval);
711         e = expr6(critical);
712         if (!e)
713             return NULL;
714         e = segment_part(e);
715         if (!e)
716             return NULL;
717         if (is_unknown(e) && critical) {
718             error(ERR_NONFATAL, "unable to determine segment base");
719             return NULL;
720         }
721         return e;
722
723     case TOKEN_FLOATIZE:
724         return eval_floatize(tokval->t_integer);
725
726     case '(':
727         i = scan(scpriv, tokval);
728         e = bexpr(critical);
729         if (!e)
730             return NULL;
731         if (i != ')') {
732             error(ERR_NONFATAL, "expecting `)'");
733             return NULL;
734         }
735         i = scan(scpriv, tokval);
736         return e;
737
738     case TOKEN_NUM:
739     case TOKEN_REG:
740     case TOKEN_ID:
741     case TOKEN_HERE:
742     case TOKEN_BASE:
743         begintemp();
744         switch (i) {
745         case TOKEN_NUM:
746             addtotemp(EXPR_SIMPLE, tokval->t_integer);
747             break;
748         case TOKEN_REG:
749             addtotemp(tokval->t_integer, 1L);
750             if (hint && hint->type == EAH_NOHINT)
751                 hint->base = tokval->t_integer, hint->type = EAH_MAKEBASE;
752             break;
753         case TOKEN_ID:
754         case TOKEN_HERE:
755         case TOKEN_BASE:
756             /*
757              * If !location->known, this indicates that no
758              * symbol, Here or Base references are valid because we
759              * are in preprocess-only mode.
760              */
761             if (!location->known) {
762                 error(ERR_NONFATAL,
763                       "%s not supported in preprocess-only mode",
764                       (i == TOKEN_ID ? "symbol references" :
765                        i == TOKEN_HERE ? "`$'" : "`$$'"));
766                 addtotemp(EXPR_UNKNOWN, 1L);
767                 break;
768             }
769
770             type = EXPR_SIMPLE; /* might get overridden by UNKNOWN */
771             if (i == TOKEN_BASE) {
772                 label_seg = in_abs_seg ? abs_seg : location->segment;
773                 label_ofs = 0;
774             } else if (i == TOKEN_HERE) {
775                 label_seg = in_abs_seg ? abs_seg : location->segment;
776                 label_ofs = in_abs_seg ? abs_offset : location->offset;
777             } else {
778                 if (!labelfunc(tokval->t_charptr, &label_seg, &label_ofs)) {
779                     if (critical == 2) {
780                         error(ERR_NONFATAL, "symbol `%s' undefined",
781                               tokval->t_charptr);
782                         return NULL;
783                     } else if (critical == 1) {
784                         error(ERR_NONFATAL,
785                               "symbol `%s' not defined before use",
786                               tokval->t_charptr);
787                         return NULL;
788                     } else {
789                         if (opflags)
790                             *opflags |= 1;
791                         type = EXPR_UNKNOWN;
792                         label_seg = NO_SEG;
793                         label_ofs = 1;
794                     }
795                 }
796                 if (opflags && is_extern(tokval->t_charptr))
797                     *opflags |= OPFLAG_EXTERN;
798             }
799             addtotemp(type, label_ofs);
800             if (label_seg != NO_SEG)
801                 addtotemp(EXPR_SEGBASE + label_seg, 1L);
802             break;
803         }
804         i = scan(scpriv, tokval);
805         return finishtemp();
806
807     default:
808         error(ERR_NONFATAL, "expression syntax error");
809         return NULL;
810     }
811 }
812
813 void eval_global_info(struct ofmt *output, lfunc lookup_label,
814                       loc_t * locp)
815 {
816     outfmt = output;
817     labelfunc = lookup_label;
818     location = locp;
819 }
820
821 expr *evaluate(scanner sc, void *scprivate, struct tokenval *tv,
822                int *fwref, int critical, efunc report_error,
823                struct eval_hints *hints)
824 {
825     expr *e;
826     expr *f = NULL;
827
828     hint = hints;
829     if (hint)
830         hint->type = EAH_NOHINT;
831
832     if (critical & CRITICAL) {
833         critical &= ~CRITICAL;
834         bexpr = rexp0;
835     } else
836         bexpr = expr0;
837
838     scan = sc;
839     scpriv = scprivate;
840     tokval = tv;
841     error = report_error;
842     opflags = fwref;
843
844     if (tokval->t_type == TOKEN_INVALID)
845         i = scan(scpriv, tokval);
846     else
847         i = tokval->t_type;
848
849     while (ntempexprs)          /* initialize temporary storage */
850         nasm_free(tempexprs[--ntempexprs]);
851
852     e = bexpr(critical);
853     if (!e)
854         return NULL;
855
856     if (i == TOKEN_WRT) {
857         i = scan(scpriv, tokval);       /* eat the WRT */
858         f = expr6(critical);
859         if (!f)
860             return NULL;
861     }
862     e = scalar_mult(e, 1L, FALSE);      /* strip far-absolute segment part */
863     if (f) {
864         expr *g;
865         if (is_just_unknown(f))
866             g = unknown_expr();
867         else {
868             int64_t value;
869             begintemp();
870             if (!is_reloc(f)) {
871                 error(ERR_NONFATAL, "invalid right-hand operand to WRT");
872                 return NULL;
873             }
874             value = reloc_seg(f);
875             if (value == NO_SEG)
876                 value = reloc_value(f) | SEG_ABS;
877             else if (!(value & SEG_ABS) && !(value % 2) && critical) {
878                 error(ERR_NONFATAL, "invalid right-hand operand to WRT");
879                 return NULL;
880             }
881             addtotemp(EXPR_WRT, value);
882             g = finishtemp();
883         }
884         e = add_vectors(e, g);
885     }
886     return e;
887 }