blob: 92d3d691a3596aae8166d95592f892ca7898136a [file] [log] [blame]
H. Peter Anvin9e6747c2009-06-28 17:13:04 -07001/* ----------------------------------------------------------------------- *
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.
H. Peter Anvin76690a12002-04-30 20:52:49 +00006 *
H. Peter Anvin9e6747c2009-06-28 17:13:04 -07007 * 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.
H. Peter Anvin76690a12002-04-30 20:52:49 +000013 *
H. Peter Anvin9e6747c2009-06-28 17:13:04 -070014 * Patches submitted to this file are required to be dual licensed
15 * under the LGPL 2.1+ and the 2-clause BSD license:
16 *
17 * Copyright 1996-2009 the NASM Authors - All rights reserved.
18 *
19 * Redistribution and use in source and binary forms, with or without
20 * modification, are permitted provided that the following
21 * conditions are met:
22 *
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.
29 *
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.
43 *
44 * ----------------------------------------------------------------------- */
45
46/*
47 * eval.c expression evaluator for the Netwide Assembler
H. Peter Anvin76690a12002-04-30 20:52:49 +000048 */
49
H. Peter Anvinfe501952007-10-02 21:53:51 -070050#include "compiler.h"
51
H. Peter Anvin76690a12002-04-30 20:52:49 +000052#include <stdio.h>
53#include <stdlib.h>
54#include <stddef.h>
55#include <string.h>
56#include <ctype.h>
Keith Kaniosb7a89542007-04-12 02:40:54 +000057#include <inttypes.h>
H. Peter Anvin76690a12002-04-30 20:52:49 +000058
59#include "nasm.h"
60#include "nasmlib.h"
61#include "eval.h"
H. Peter Anvineba20a72002-04-30 20:53:55 +000062#include "labels.h"
H. Peter Anvindc467ba2007-09-24 12:30:54 -070063#include "float.h"
H. Peter Anvin76690a12002-04-30 20:52:49 +000064
H. Peter Anvin76690a12002-04-30 20:52:49 +000065#define TEMPEXPRS_DELTA 128
H. Peter Anvin76690a12002-04-30 20:52:49 +000066#define TEMPEXPR_DELTA 8
67
H. Peter Anvine2c80182005-01-15 22:15:51 +000068static scanner scan; /* Address of scanner routine */
69static efunc error; /* Address of error reporting routine */
70static lfunc labelfunc; /* Address of label routine */
H. Peter Anvineba20a72002-04-30 20:53:55 +000071
H. Peter Anvine2c80182005-01-15 22:15:51 +000072static struct ofmt *outfmt; /* Structure of addresses of output routines */
H. Peter Anvineba20a72002-04-30 20:53:55 +000073
74static expr **tempexprs = NULL;
H. Peter Anvine2c80182005-01-15 22:15:51 +000075static int ntempexprs;
76static int tempexprs_size = 0;
H. Peter Anvineba20a72002-04-30 20:53:55 +000077
H. Peter Anvine2c80182005-01-15 22:15:51 +000078static expr *tempexpr;
79static int ntempexpr;
80static int tempexpr_size;
H. Peter Anvineba20a72002-04-30 20:53:55 +000081
H. Peter Anvine2c80182005-01-15 22:15:51 +000082static struct tokenval *tokval; /* The current token */
83static int i; /* The t_type of tokval */
H. Peter Anvineba20a72002-04-30 20:53:55 +000084
H. Peter Anvin76690a12002-04-30 20:52:49 +000085static void *scpriv;
H. Peter Anvin12e46512007-10-03 21:30:57 -070086static struct location *location; /* Pointer to current line's segment,offset */
H. Peter Anvineba20a72002-04-30 20:53:55 +000087static int *opflags;
H. Peter Anvin76690a12002-04-30 20:52:49 +000088
89static struct eval_hints *hint;
90
H. Peter Anvine2c80182005-01-15 22:15:51 +000091extern int in_abs_seg; /* ABSOLUTE segment flag */
Keith Kaniosb7a89542007-04-12 02:40:54 +000092extern int32_t abs_seg; /* ABSOLUTE segment */
93extern int32_t abs_offset; /* ABSOLUTE segment offset */
H. Peter Anvin667dd802002-05-26 19:49:41 +000094
H. Peter Anvin76690a12002-04-30 20:52:49 +000095/*
H. Peter Anvineba20a72002-04-30 20:53:55 +000096 * Unimportant cleanup is done to avoid confusing people who are trying
97 * to debug real memory leaks
98 */
H. Peter Anvine2c80182005-01-15 22:15:51 +000099void eval_cleanup(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000100{
101 while (ntempexprs)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000102 nasm_free(tempexprs[--ntempexprs]);
103 nasm_free(tempexprs);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000104}
105
106/*
H. Peter Anvin76690a12002-04-30 20:52:49 +0000107 * Construct a temporary expression.
108 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000109static void begintemp(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000110{
H. Peter Anvin76690a12002-04-30 20:52:49 +0000111 tempexpr = NULL;
112 tempexpr_size = ntempexpr = 0;
113}
114
Keith Kaniosb7a89542007-04-12 02:40:54 +0000115static void addtotemp(int32_t type, int64_t value)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000116{
H. Peter Anvin76690a12002-04-30 20:52:49 +0000117 while (ntempexpr >= tempexpr_size) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000118 tempexpr_size += TEMPEXPR_DELTA;
119 tempexpr = nasm_realloc(tempexpr,
120 tempexpr_size * sizeof(*tempexpr));
H. Peter Anvin76690a12002-04-30 20:52:49 +0000121 }
122 tempexpr[ntempexpr].type = type;
123 tempexpr[ntempexpr++].value = value;
124}
125
H. Peter Anvine2c80182005-01-15 22:15:51 +0000126static expr *finishtemp(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000127{
H. Peter Anvine2c80182005-01-15 22:15:51 +0000128 addtotemp(0L, 0L); /* terminate */
H. Peter Anvin76690a12002-04-30 20:52:49 +0000129 while (ntempexprs >= tempexprs_size) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000130 tempexprs_size += TEMPEXPRS_DELTA;
131 tempexprs = nasm_realloc(tempexprs,
132 tempexprs_size * sizeof(*tempexprs));
H. Peter Anvin76690a12002-04-30 20:52:49 +0000133 }
134 return tempexprs[ntempexprs++] = tempexpr;
135}
136
137/*
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.
141 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000142static expr *add_vectors(expr * p, expr * q)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000143{
H. Peter Anvin76690a12002-04-30 20:52:49 +0000144 int preserve;
145
146 preserve = is_really_simple(p) || is_really_simple(q);
147
148 begintemp();
149
150 while (p->type && q->type &&
H. Peter Anvine2c80182005-01-15 22:15:51 +0000151 p->type < EXPR_SEGBASE + SEG_ABS &&
152 q->type < EXPR_SEGBASE + SEG_ABS) {
153 int lasttype;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000154
H. Peter Anvine2c80182005-01-15 22:15:51 +0000155 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 */
Keith Kaniosa5fc6462007-10-13 07:09:22 -0700162 int64_t sum = p->value + q->value;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000163 if (sum)
164 addtotemp(p->type, sum);
165 lasttype = p->type;
166 p++, q++;
167 }
168 if (lasttype == EXPR_UNKNOWN) {
169 return finishtemp();
170 }
H. Peter Anvin76690a12002-04-30 20:52:49 +0000171 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000172 while (p->type && (preserve || p->type < EXPR_SEGBASE + SEG_ABS)) {
173 addtotemp(p->type, p->value);
174 p++;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000175 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000176 while (q->type && (preserve || q->type < EXPR_SEGBASE + SEG_ABS)) {
177 addtotemp(q->type, q->value);
178 q++;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000179 }
180
181 return finishtemp();
182}
183
184/*
185 * Multiply a vector by a scalar. Strip far-absolute segment part
186 * if present.
187 *
188 * Explicit treatment of UNKNOWN is not required in this routine,
189 * since it will silently do the Right Thing anyway.
190 *
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.
195 */
Keith Kaniosa5fc6462007-10-13 07:09:22 -0700196static expr *scalar_mult(expr * vect, int64_t scalar, int affect_hints)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000197{
H. Peter Anvin76690a12002-04-30 20:52:49 +0000198 expr *p = vect;
199
H. Peter Anvine2c80182005-01-15 22:15:51 +0000200 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++;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000206 }
207 p->type = 0;
208
209 return vect;
210}
211
Keith Kaniosa5fc6462007-10-13 07:09:22 -0700212static expr *scalarvect(int64_t scalar)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000213{
H. Peter Anvin76690a12002-04-30 20:52:49 +0000214 begintemp();
215 addtotemp(EXPR_SIMPLE, scalar);
216 return finishtemp();
217}
218
H. Peter Anvine2c80182005-01-15 22:15:51 +0000219static expr *unknown_expr(void)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000220{
H. Peter Anvin76690a12002-04-30 20:52:49 +0000221 begintemp();
222 addtotemp(EXPR_UNKNOWN, 1L);
223 return finishtemp();
224}
225
226/*
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.
230 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000231static expr *segment_part(expr * e)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000232{
Keith Kaniosb7a89542007-04-12 02:40:54 +0000233 int32_t seg;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000234
235 if (is_unknown(e))
H. Peter Anvine2c80182005-01-15 22:15:51 +0000236 return unknown_expr();
H. Peter Anvin76690a12002-04-30 20:52:49 +0000237
238 if (!is_reloc(e)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000239 error(ERR_NONFATAL, "cannot apply SEG to a non-relocatable value");
240 return NULL;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000241 }
242
243 seg = reloc_seg(e);
244 if (seg == NO_SEG) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000245 error(ERR_NONFATAL, "cannot apply SEG to a non-relocatable value");
246 return NULL;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000247 } else if (seg & SEG_ABS) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000248 return scalarvect(seg & ~SEG_ABS);
H. Peter Anvin76690a12002-04-30 20:52:49 +0000249 } else if (seg & 1) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000250 error(ERR_NONFATAL, "SEG applied to something which"
251 " is already a segment base");
252 return NULL;
253 } else {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000254 int32_t base = outfmt->segbase(seg + 1);
H. Peter Anvin76690a12002-04-30 20:52:49 +0000255
H. Peter Anvine2c80182005-01-15 22:15:51 +0000256 begintemp();
257 addtotemp((base == NO_SEG ? EXPR_UNKNOWN : EXPR_SEGBASE + base),
258 1L);
259 return finishtemp();
H. Peter Anvin76690a12002-04-30 20:52:49 +0000260 }
261}
262
263/*
264 * Recursive-descent parser. Called with a single boolean operand,
H. Peter Anvin6867acc2007-10-10 14:58:45 -0700265 * which is true if the evaluation is critical (i.e. unresolved
H. Peter Anvin76690a12002-04-30 20:52:49 +0000266 * symbols are an error condition). Must update the global `i' to
267 * reflect the token after the parsed string. May return NULL.
268 *
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.
272 */
273
274/*
275 * Grammar parsed is:
276 *
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
294 */
295
296static expr *rexp0(int), *rexp1(int), *rexp2(int), *rexp3(int);
297
298static expr *expr0(int), *expr1(int), *expr2(int), *expr3(int);
299static expr *expr4(int), *expr5(int), *expr6(int);
300
H. Peter Anvine2c80182005-01-15 22:15:51 +0000301static expr *(*bexpr) (int);
H. Peter Anvin76690a12002-04-30 20:52:49 +0000302
H. Peter Anvine2c80182005-01-15 22:15:51 +0000303static expr *rexp0(int critical)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000304{
H. Peter Anvin76690a12002-04-30 20:52:49 +0000305 expr *e, *f;
306
307 e = rexp1(critical);
308 if (!e)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000309 return NULL;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000310
H. Peter Anvine2c80182005-01-15 22:15:51 +0000311 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");
320 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000321
H. Peter Anvine2c80182005-01-15 22:15:51 +0000322 if (is_just_unknown(e) || is_just_unknown(f))
323 e = unknown_expr();
324 else
Keith Kaniosa5fc6462007-10-13 07:09:22 -0700325 e = scalarvect((int64_t)(reloc_value(e) || reloc_value(f)));
H. Peter Anvin76690a12002-04-30 20:52:49 +0000326 }
327 return e;
328}
329
H. Peter Anvine2c80182005-01-15 22:15:51 +0000330static expr *rexp1(int critical)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000331{
H. Peter Anvin76690a12002-04-30 20:52:49 +0000332 expr *e, *f;
333
334 e = rexp2(critical);
335 if (!e)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000336 return NULL;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000337
H. Peter Anvine2c80182005-01-15 22:15:51 +0000338 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");
347 }
348
349 if (is_just_unknown(e) || is_just_unknown(f))
350 e = unknown_expr();
351 else
Keith Kaniosa5fc6462007-10-13 07:09:22 -0700352 e = scalarvect((int64_t)(!reloc_value(e) ^ !reloc_value(f)));
H. Peter Anvin76690a12002-04-30 20:52:49 +0000353 }
354 return e;
355}
356
H. Peter Anvine2c80182005-01-15 22:15:51 +0000357static expr *rexp2(int critical)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000358{
H. Peter Anvin76690a12002-04-30 20:52:49 +0000359 expr *e, *f;
360
361 e = rexp3(critical);
362 if (!e)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000363 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");
373 }
374 if (is_just_unknown(e) || is_just_unknown(f))
375 e = unknown_expr();
376 else
Keith Kaniosa5fc6462007-10-13 07:09:22 -0700377 e = scalarvect((int64_t)(reloc_value(e) && reloc_value(f)));
H. Peter Anvin76690a12002-04-30 20:52:49 +0000378 }
379 return e;
380}
381
H. Peter Anvine2c80182005-01-15 22:15:51 +0000382static expr *rexp3(int critical)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000383{
H. Peter Anvin76690a12002-04-30 20:52:49 +0000384 expr *e, *f;
Keith Kaniosa5fc6462007-10-13 07:09:22 -0700385 int64_t v;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000386
387 e = expr0(critical);
388 if (!e)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000389 return NULL;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000390
H. Peter Anvin76690a12002-04-30 20:52:49 +0000391 while (i == TOKEN_EQ || i == TOKEN_LT || i == TOKEN_GT ||
H. Peter Anvine2c80182005-01-15 22:15:51 +0000392 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;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000398
H. Peter Anvin6867acc2007-10-10 14:58:45 -0700399 e = add_vectors(e, scalar_mult(f, -1L, false));
H. Peter Anvineba20a72002-04-30 20:53:55 +0000400
H. Peter Anvine2c80182005-01-15 22:15:51 +0000401 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)
H. Peter Anvin6867acc2007-10-10 14:58:45 -0700407 v = (j == TOKEN_NE); /* unequal, so return true if NE */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000408 else
H. Peter Anvin6867acc2007-10-10 14:58:45 -0700409 v = (j == TOKEN_EQ); /* equal, so return true if EQ */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000410 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);
428 }
429 break;
430 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000431
H. Peter Anvine2c80182005-01-15 22:15:51 +0000432 if (v == -1)
433 e = unknown_expr();
434 else
435 e = scalarvect(v);
H. Peter Anvin76690a12002-04-30 20:52:49 +0000436 }
437 return e;
438}
439
H. Peter Anvine2c80182005-01-15 22:15:51 +0000440static expr *expr0(int critical)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000441{
H. Peter Anvin76690a12002-04-30 20:52:49 +0000442 expr *e, *f;
443
444 e = expr1(critical);
445 if (!e)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000446 return NULL;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000447
H. Peter Anvine2c80182005-01-15 22:15:51 +0000448 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");
457 }
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));
H. Peter Anvin76690a12002-04-30 20:52:49 +0000462 }
463 return e;
464}
465
H. Peter Anvine2c80182005-01-15 22:15:51 +0000466static expr *expr1(int critical)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000467{
H. Peter Anvin76690a12002-04-30 20:52:49 +0000468 expr *e, *f;
469
470 e = expr2(critical);
471 if (!e)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000472 return NULL;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000473
H. Peter Anvin76690a12002-04-30 20:52:49 +0000474 while (i == '^') {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000475 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");
483 }
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));
H. Peter Anvin76690a12002-04-30 20:52:49 +0000488 }
489 return e;
490}
491
H. Peter Anvine2c80182005-01-15 22:15:51 +0000492static expr *expr2(int critical)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000493{
H. Peter Anvin76690a12002-04-30 20:52:49 +0000494 expr *e, *f;
495
496 e = expr3(critical);
497 if (!e)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000498 return NULL;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000499
H. Peter Anvin76690a12002-04-30 20:52:49 +0000500 while (i == '&') {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000501 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");
509 }
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));
H. Peter Anvin76690a12002-04-30 20:52:49 +0000514 }
515 return e;
516}
517
H. Peter Anvine2c80182005-01-15 22:15:51 +0000518static expr *expr3(int critical)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000519{
H. Peter Anvin76690a12002-04-30 20:52:49 +0000520 expr *e, *f;
521
522 e = expr4(critical);
523 if (!e)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000524 return NULL;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000525
H. Peter Anvine2c80182005-01-15 22:15:51 +0000526 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:
Keith Kaniosa5fc6462007-10-13 07:09:22 -0700544 e = scalarvect(((uint64_t)reloc_value(e)) >>
H. Peter Anvine2c80182005-01-15 22:15:51 +0000545 reloc_value(f));
546 break;
547 }
H. Peter Anvin76690a12002-04-30 20:52:49 +0000548 }
549 return e;
550}
551
H. Peter Anvine2c80182005-01-15 22:15:51 +0000552static expr *expr4(int critical)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000553{
H. Peter Anvin76690a12002-04-30 20:52:49 +0000554 expr *e, *f;
555
556 e = expr5(critical);
557 if (!e)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000558 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 '-':
H. Peter Anvin6867acc2007-10-10 14:58:45 -0700570 e = add_vectors(e, scalar_mult(f, -1L, false));
H. Peter Anvine2c80182005-01-15 22:15:51 +0000571 break;
572 }
H. Peter Anvin76690a12002-04-30 20:52:49 +0000573 }
574 return e;
575}
576
H. Peter Anvine2c80182005-01-15 22:15:51 +0000577static expr *expr5(int critical)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000578{
H. Peter Anvin76690a12002-04-30 20:52:49 +0000579 expr *e, *f;
580
581 e = expr6(critical);
582 if (!e)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000583 return NULL;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000584 while (i == '*' || i == '/' || i == '%' ||
H. Peter Anvine2c80182005-01-15 22:15:51 +0000585 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;
596 }
597 if (j != '*' && !is_unknown(f) && reloc_value(f) == 0) {
598 error(ERR_NONFATAL, "division by zero");
599 return NULL;
600 }
601 switch (j) {
602 case '*':
603 if (is_simple(e))
H. Peter Anvin6867acc2007-10-10 14:58:45 -0700604 e = scalar_mult(f, reloc_value(e), true);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000605 else if (is_simple(f))
H. Peter Anvin6867acc2007-10-10 14:58:45 -0700606 e = scalar_mult(e, reloc_value(f), true);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000607 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;
613 }
614 break;
615 case '/':
616 if (is_just_unknown(e) || is_just_unknown(f))
617 e = unknown_expr();
618 else
Keith Kaniosa5fc6462007-10-13 07:09:22 -0700619 e = scalarvect(((uint64_t)reloc_value(e)) /
620 ((uint64_t)reloc_value(f)));
H. Peter Anvine2c80182005-01-15 22:15:51 +0000621 break;
622 case '%':
623 if (is_just_unknown(e) || is_just_unknown(f))
624 e = unknown_expr();
625 else
Keith Kaniosa5fc6462007-10-13 07:09:22 -0700626 e = scalarvect(((uint64_t)reloc_value(e)) %
627 ((uint64_t)reloc_value(f)));
H. Peter Anvine2c80182005-01-15 22:15:51 +0000628 break;
629 case TOKEN_SDIV:
630 if (is_just_unknown(e) || is_just_unknown(f))
631 e = unknown_expr();
632 else
Keith Kaniosa5fc6462007-10-13 07:09:22 -0700633 e = scalarvect(((int64_t)reloc_value(e)) /
634 ((int64_t)reloc_value(f)));
H. Peter Anvine2c80182005-01-15 22:15:51 +0000635 break;
636 case TOKEN_SMOD:
637 if (is_just_unknown(e) || is_just_unknown(f))
638 e = unknown_expr();
639 else
Keith Kaniosa5fc6462007-10-13 07:09:22 -0700640 e = scalarvect(((int64_t)reloc_value(e)) %
641 ((int64_t)reloc_value(f)));
H. Peter Anvine2c80182005-01-15 22:15:51 +0000642 break;
643 }
H. Peter Anvin76690a12002-04-30 20:52:49 +0000644 }
645 return e;
646}
647
H. Peter Anvindc467ba2007-09-24 12:30:54 -0700648static expr *eval_floatize(enum floatize type)
649{
650 uint8_t result[16], *p; /* Up to 128 bits */
651 static const struct {
652 int bytes, start, len;
653 } formats[] = {
H. Peter Anvin2ce02742007-10-29 20:20:12 -0700654 { 1, 0, 1 }, /* FLOAT_8 */
H. Peter Anvindc467ba2007-09-24 12:30:54 -0700655 { 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 */
662 };
663 int sign = 1;
664 int64_t val;
665 int j;
H. Peter Anvin70653092007-10-19 14:42:29 -0700666
H. Peter Anvindc467ba2007-09-24 12:30:54 -0700667 i = scan(scpriv, tokval);
668 if (i != '(') {
669 error(ERR_NONFATAL, "expecting `('");
670 return NULL;
671 }
672 i = scan(scpriv, tokval);
673 if (i == '-' || i == '+') {
674 sign = (i == '-') ? -1 : 1;
675 i = scan(scpriv, tokval);
676 }
677 if (i != TOKEN_FLOAT) {
678 error(ERR_NONFATAL, "expecting floating-point number");
679 return NULL;
680 }
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;
688 }
689
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;
695 }
696
697 begintemp();
698 addtotemp(EXPR_SIMPLE, val);
699
700 i = scan(scpriv, tokval);
701 return finishtemp();
702}
703
H. Peter Anvin9c749102008-06-14 21:08:38 -0700704static expr *eval_strfunc(enum strfunc type)
705{
706 char *string;
707 size_t string_len;
708 int64_t val;
709 bool parens, rn_warn;
710
Victor van den Elzenc7deefa2008-06-25 11:41:40 +0200711 parens = false;
H. Peter Anvin9c749102008-06-14 21:08:38 -0700712 i = scan(scpriv, tokval);
713 if (i == '(') {
714 parens = true;
715 i = scan(scpriv, tokval);
716 }
717 if (i != TOKEN_STR) {
718 error(ERR_NONFATAL, "expecting string");
719 return NULL;
720 }
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;
726 }
727
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;
734 }
735 }
736
737 if (rn_warn)
738 error(ERR_WARNING|ERR_PASS1, "character constant too long");
739
740 begintemp();
741 addtotemp(EXPR_SIMPLE, val);
742
743 i = scan(scpriv, tokval);
744 return finishtemp();
745}
746
H. Peter Anvine2c80182005-01-15 22:15:51 +0000747static expr *expr6(int critical)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000748{
Keith Kaniosb7a89542007-04-12 02:40:54 +0000749 int32_t type;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000750 expr *e;
Charles Crayne4e8563d2007-11-05 17:19:32 -0800751 int32_t label_seg;
752 int64_t label_ofs;
H. Peter Anvin11627042008-06-09 20:45:19 -0700753 int64_t tmpval;
754 bool rn_warn;
Charles Crayned60059e2008-03-12 22:39:03 -0700755 char *scope;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000756
H. Peter Anvin5f77c032007-09-24 10:51:07 -0700757 switch (i) {
758 case '-':
H. Peter Anvine2c80182005-01-15 22:15:51 +0000759 i = scan(scpriv, tokval);
760 e = expr6(critical);
761 if (!e)
762 return NULL;
H. Peter Anvin6867acc2007-10-10 14:58:45 -0700763 return scalar_mult(e, -1L, false);
H. Peter Anvin5f77c032007-09-24 10:51:07 -0700764
765
766 case '+':
H. Peter Anvine2c80182005-01-15 22:15:51 +0000767 i = scan(scpriv, tokval);
768 return expr6(critical);
H. Peter Anvin5f77c032007-09-24 10:51:07 -0700769
770 case '~':
H. Peter Anvine2c80182005-01-15 22:15:51 +0000771 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;
781 }
782 return scalarvect(~reloc_value(e));
H. Peter Anvin5f77c032007-09-24 10:51:07 -0700783
784 case '!':
Chuck Craynecb9bc212007-05-02 04:21:26 +0000785 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;
795 }
796 return scalarvect(!reloc_value(e));
H. Peter Anvin5f77c032007-09-24 10:51:07 -0700797
798 case TOKEN_SEG:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000799 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;
809 }
810 return e;
H. Peter Anvin5f77c032007-09-24 10:51:07 -0700811
H. Peter Anvindc467ba2007-09-24 12:30:54 -0700812 case TOKEN_FLOATIZE:
813 return eval_floatize(tokval->t_integer);
814
H. Peter Anvin9c749102008-06-14 21:08:38 -0700815 case TOKEN_STRFUNC:
816 return eval_strfunc(tokval->t_integer);
817
H. Peter Anvin5f77c032007-09-24 10:51:07 -0700818 case '(':
H. Peter Anvine2c80182005-01-15 22:15:51 +0000819 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;
826 }
827 i = scan(scpriv, tokval);
828 return e;
H. Peter Anvin5f77c032007-09-24 10:51:07 -0700829
830 case TOKEN_NUM:
H. Peter Anvin11627042008-06-09 20:45:19 -0700831 case TOKEN_STR:
H. Peter Anvin5f77c032007-09-24 10:51:07 -0700832 case TOKEN_REG:
833 case TOKEN_ID:
H. Peter Anvin9c987692007-11-04 21:09:32 -0800834 case TOKEN_INSN: /* Opcodes that occur here are really labels */
H. Peter Anvin5f77c032007-09-24 10:51:07 -0700835 case TOKEN_HERE:
836 case TOKEN_BASE:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000837 begintemp();
838 switch (i) {
839 case TOKEN_NUM:
840 addtotemp(EXPR_SIMPLE, tokval->t_integer);
841 break;
H. Peter Anvin11627042008-06-09 20:45:19 -0700842 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;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000848 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:
H. Peter Anvin9c987692007-11-04 21:09:32 -0800854 case TOKEN_INSN:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000855 case TOKEN_HERE:
856 case TOKEN_BASE:
857 /*
858 * If !location->known, this indicates that no
859 * symbol, Here or Base references are valid because we
860 * are in preprocess-only mode.
861 */
862 if (!location->known) {
863 error(ERR_NONFATAL,
864 "%s not supported in preprocess-only mode",
H. Peter Anvin9c987692007-11-04 21:09:32 -0800865 (i == TOKEN_HERE ? "`$'" :
866 i == TOKEN_BASE ? "`$$'" :
867 "symbol references"));
H. Peter Anvine2c80182005-01-15 22:15:51 +0000868 addtotemp(EXPR_UNKNOWN, 1L);
869 break;
870 }
H. Peter Anvin76690a12002-04-30 20:52:49 +0000871
H. Peter Anvine2c80182005-01-15 22:15:51 +0000872 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)) {
Charles Crayned60059e2008-03-12 22:39:03 -0700881 scope = local_scope(tokval->t_charptr);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000882 if (critical == 2) {
Charles Crayned60059e2008-03-12 22:39:03 -0700883 error(ERR_NONFATAL, "symbol `%s%s' undefined",
884 scope,tokval->t_charptr);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000885 return NULL;
886 } else if (critical == 1) {
887 error(ERR_NONFATAL,
Charles Crayned60059e2008-03-12 22:39:03 -0700888 "symbol `%s%s' not defined before use",
889 scope,tokval->t_charptr);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000890 return NULL;
891 } else {
892 if (opflags)
893 *opflags |= 1;
894 type = EXPR_UNKNOWN;
895 label_seg = NO_SEG;
896 label_ofs = 1;
897 }
898 }
899 if (opflags && is_extern(tokval->t_charptr))
900 *opflags |= OPFLAG_EXTERN;
901 }
902 addtotemp(type, label_ofs);
903 if (label_seg != NO_SEG)
904 addtotemp(EXPR_SEGBASE + label_seg, 1L);
905 break;
906 }
907 i = scan(scpriv, tokval);
908 return finishtemp();
H. Peter Anvin5f77c032007-09-24 10:51:07 -0700909
910 default:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000911 error(ERR_NONFATAL, "expression syntax error");
912 return NULL;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000913 }
914}
915
H. Peter Anvine2c80182005-01-15 22:15:51 +0000916void eval_global_info(struct ofmt *output, lfunc lookup_label,
H. Peter Anvin12e46512007-10-03 21:30:57 -0700917 struct location * locp)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000918{
H. Peter Anvin76690a12002-04-30 20:52:49 +0000919 outfmt = output;
920 labelfunc = lookup_label;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000921 location = locp;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000922}
923
H. Peter Anvine2c80182005-01-15 22:15:51 +0000924expr *evaluate(scanner sc, void *scprivate, struct tokenval *tv,
925 int *fwref, int critical, efunc report_error,
926 struct eval_hints *hints)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000927{
H. Peter Anvin76690a12002-04-30 20:52:49 +0000928 expr *e;
929 expr *f = NULL;
930
931 hint = hints;
932 if (hint)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000933 hint->type = EAH_NOHINT;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000934
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000935 if (critical & CRITICAL) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000936 critical &= ~CRITICAL;
937 bexpr = rexp0;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000938 } else
H. Peter Anvine2c80182005-01-15 22:15:51 +0000939 bexpr = expr0;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000940
941 scan = sc;
942 scpriv = scprivate;
943 tokval = tv;
944 error = report_error;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000945 opflags = fwref;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000946
947 if (tokval->t_type == TOKEN_INVALID)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000948 i = scan(scpriv, tokval);
H. Peter Anvin76690a12002-04-30 20:52:49 +0000949 else
H. Peter Anvine2c80182005-01-15 22:15:51 +0000950 i = tokval->t_type;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000951
Keith Kaniosb7a89542007-04-12 02:40:54 +0000952 while (ntempexprs) /* initialize temporary storage */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000953 nasm_free(tempexprs[--ntempexprs]);
H. Peter Anvin76690a12002-04-30 20:52:49 +0000954
H. Peter Anvine2c80182005-01-15 22:15:51 +0000955 e = bexpr(critical);
H. Peter Anvin76690a12002-04-30 20:52:49 +0000956 if (!e)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000957 return NULL;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000958
959 if (i == TOKEN_WRT) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000960 i = scan(scpriv, tokval); /* eat the WRT */
961 f = expr6(critical);
962 if (!f)
963 return NULL;
H. Peter Anvin76690a12002-04-30 20:52:49 +0000964 }
H. Peter Anvin6867acc2007-10-10 14:58:45 -0700965 e = scalar_mult(e, 1L, false); /* strip far-absolute segment part */
H. Peter Anvin76690a12002-04-30 20:52:49 +0000966 if (f) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000967 expr *g;
968 if (is_just_unknown(f))
969 g = unknown_expr();
970 else {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000971 int64_t value;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000972 begintemp();
973 if (!is_reloc(f)) {
974 error(ERR_NONFATAL, "invalid right-hand operand to WRT");
975 return NULL;
976 }
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;
983 }
984 addtotemp(EXPR_WRT, value);
985 g = finishtemp();
986 }
987 e = add_vectors(e, g);
H. Peter Anvin76690a12002-04-30 20:52:49 +0000988 }
989 return e;
990}