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