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 #include <util.h>
11 #include <libyasm-stdint.h>
12 #include <libyasm/coretype.h>
13 #include <libyasm/intnum.h>
14 #include <libyasm/expr.h>
15 #include <libyasm/symrec.h>
16 #include <ctype.h>
17
18 #include "nasm.h"
19 #include "nasmlib.h"
20 #include "nasm-eval.h"
21
22 /* The assembler symbol table. */
23 extern yasm_symtab *nasm_symtab;
24
25 static scanner scan; /* Address of scanner routine */
26 static efunc error; /* Address of error reporting routine */
27
28 static struct tokenval *tokval; /* The current token */
29 static int i; /* The t_type of tokval */
30
31 static void *scpriv;
32
33 /*
34 * Recursive-descent parser. Called with a single boolean operand,
35 * which is TRUE if the evaluation is critical (i.e. unresolved
36 * symbols are an error condition). Must update the global `i' to
37 * reflect the token after the parsed string. May return NULL.
38 *
39 * evaluate() should report its own errors: on return it is assumed
40 * that if NULL has been returned, the error has already been
41 * reported.
42 */
43
44 /*
45 * Grammar parsed is:
46 *
47 * expr : bexpr [ WRT expr6 ]
48 * bexpr : rexp0 or expr0 depending on relative-mode setting
49 * rexp0 : rexp1 [ {||} rexp1...]
50 * rexp1 : rexp2 [ {^^} rexp2...]
51 * rexp2 : rexp3 [ {&&} rexp3...]
52 * rexp3 : expr0 [ {=,==,<>,!=,<,>,<=,>=} expr0 ]
53 * expr0 : expr1 [ {|} expr1...]
54 * expr1 : expr2 [ {^} expr2...]
55 * expr2 : expr3 [ {&} expr3...]
56 * expr3 : expr4 [ {<<,>>} expr4...]
57 * expr4 : expr5 [ {+,-} expr5...]
58 * expr5 : expr6 [ {*,/,%,//,%%} expr6...]
59 * expr6 : { ~,+,-,SEG } expr6
60 * | (bexpr)
61 * | symbol
62 * | $
63 * | number
64 */
65
66 static yasm_expr *rexp0(void), *rexp1(void), *rexp2(void), *rexp3(void);
67
68 static yasm_expr *expr0(void), *expr1(void), *expr2(void), *expr3(void);
69 static yasm_expr *expr4(void), *expr5(void), *expr6(void);
70
71 static yasm_expr *(*bexpr)(void);
72
rexp0(void)73 static yasm_expr *rexp0(void)
74 {
75 yasm_expr *e, *f;
76
77 e = rexp1();
78 if (!e)
79 return NULL;
80
81 while (i == TOKEN_DBL_OR)
82 {
83 i = scan(scpriv, tokval);
84 f = rexp1();
85 if (!f) {
86 yasm_expr_destroy(e);
87 return NULL;
88 }
89
90 e = yasm_expr_create_tree(e, YASM_EXPR_LOR, f, 0);
91 }
92 return e;
93 }
94
rexp1(void)95 static yasm_expr *rexp1(void)
96 {
97 yasm_expr *e, *f;
98
99 e = rexp2();
100 if (!e)
101 return NULL;
102
103 while (i == TOKEN_DBL_XOR)
104 {
105 i = scan(scpriv, tokval);
106 f = rexp2();
107 if (!f) {
108 yasm_expr_destroy(e);
109 return NULL;
110 }
111
112 e = yasm_expr_create_tree(e, YASM_EXPR_LXOR, f, 0);
113 }
114 return e;
115 }
116
rexp2(void)117 static yasm_expr *rexp2(void)
118 {
119 yasm_expr *e, *f;
120
121 e = rexp3();
122 if (!e)
123 return NULL;
124 while (i == TOKEN_DBL_AND)
125 {
126 i = scan(scpriv, tokval);
127 f = rexp3();
128 if (!f) {
129 yasm_expr_destroy(e);
130 return NULL;
131 }
132
133 e = yasm_expr_create_tree(e, YASM_EXPR_LAND, f, 0);
134 }
135 return e;
136 }
137
rexp3(void)138 static yasm_expr *rexp3(void)
139 {
140 yasm_expr *e, *f;
141
142 e = expr0();
143 if (!e)
144 return NULL;
145
146 while (i == TOKEN_EQ || i == TOKEN_LT || i == TOKEN_GT ||
147 i == TOKEN_NE || i == TOKEN_LE || i == TOKEN_GE)
148 {
149 int j = i;
150 i = scan(scpriv, tokval);
151 f = expr0();
152 if (!f) {
153 yasm_expr_destroy(e);
154 return NULL;
155 }
156
157 switch (j)
158 {
159 case TOKEN_EQ:
160 e = yasm_expr_create_tree(e, YASM_EXPR_EQ, f, 0);
161 break;
162 case TOKEN_LT:
163 e = yasm_expr_create_tree(e, YASM_EXPR_LT, f, 0);
164 break;
165 case TOKEN_GT:
166 e = yasm_expr_create_tree(e, YASM_EXPR_GT, f, 0);
167 break;
168 case TOKEN_NE:
169 e = yasm_expr_create_tree(e, YASM_EXPR_NE, f, 0);
170 break;
171 case TOKEN_LE:
172 e = yasm_expr_create_tree(e, YASM_EXPR_LE, f, 0);
173 break;
174 case TOKEN_GE:
175 e = yasm_expr_create_tree(e, YASM_EXPR_GE, f, 0);
176 break;
177 }
178 }
179 return e;
180 }
181
expr0(void)182 static yasm_expr *expr0(void)
183 {
184 yasm_expr *e, *f;
185
186 e = expr1();
187 if (!e)
188 return NULL;
189
190 while (i == '|')
191 {
192 i = scan(scpriv, tokval);
193 f = expr1();
194 if (!f) {
195 yasm_expr_destroy(e);
196 return NULL;
197 }
198
199 e = yasm_expr_create_tree(e, YASM_EXPR_OR, f, 0);
200 }
201 return e;
202 }
203
expr1(void)204 static yasm_expr *expr1(void)
205 {
206 yasm_expr *e, *f;
207
208 e = expr2();
209 if (!e)
210 return NULL;
211
212 while (i == '^') {
213 i = scan(scpriv, tokval);
214 f = expr2();
215 if (!f) {
216 yasm_expr_destroy(e);
217 return NULL;
218 }
219
220 e = yasm_expr_create_tree(e, YASM_EXPR_XOR, f, 0);
221 }
222 return e;
223 }
224
expr2(void)225 static yasm_expr *expr2(void)
226 {
227 yasm_expr *e, *f;
228
229 e = expr3();
230 if (!e)
231 return NULL;
232
233 while (i == '&') {
234 i = scan(scpriv, tokval);
235 f = expr3();
236 if (!f) {
237 yasm_expr_destroy(e);
238 return NULL;
239 }
240
241 e = yasm_expr_create_tree(e, YASM_EXPR_AND, f, 0);
242 }
243 return e;
244 }
245
expr3(void)246 static yasm_expr *expr3(void)
247 {
248 yasm_expr *e, *f;
249
250 e = expr4();
251 if (!e)
252 return NULL;
253
254 while (i == TOKEN_SHL || i == TOKEN_SHR)
255 {
256 int j = i;
257 i = scan(scpriv, tokval);
258 f = expr4();
259 if (!f) {
260 yasm_expr_destroy(e);
261 return NULL;
262 }
263
264 switch (j) {
265 case TOKEN_SHL:
266 e = yasm_expr_create_tree(e, YASM_EXPR_SHL, f, 0);
267 break;
268 case TOKEN_SHR:
269 e = yasm_expr_create_tree(e, YASM_EXPR_SHR, f, 0);
270 break;
271 }
272 }
273 return e;
274 }
275
expr4(void)276 static yasm_expr *expr4(void)
277 {
278 yasm_expr *e, *f;
279
280 e = expr5();
281 if (!e)
282 return NULL;
283 while (i == '+' || i == '-')
284 {
285 int j = i;
286 i = scan(scpriv, tokval);
287 f = expr5();
288 if (!f) {
289 yasm_expr_destroy(e);
290 return NULL;
291 }
292 switch (j) {
293 case '+':
294 e = yasm_expr_create_tree(e, YASM_EXPR_ADD, f, 0);
295 break;
296 case '-':
297 e = yasm_expr_create_tree(e, YASM_EXPR_SUB, f, 0);
298 break;
299 }
300 }
301 return e;
302 }
303
expr5(void)304 static yasm_expr *expr5(void)
305 {
306 yasm_expr *e, *f;
307
308 e = expr6();
309 if (!e)
310 return NULL;
311 while (i == '*' || i == '/' || i == '%' ||
312 i == TOKEN_SDIV || i == TOKEN_SMOD)
313 {
314 int j = i;
315 i = scan(scpriv, tokval);
316 f = expr6();
317 if (!f) {
318 yasm_expr_destroy(e);
319 return NULL;
320 }
321 switch (j) {
322 case '*':
323 e = yasm_expr_create_tree(e, YASM_EXPR_MUL, f, 0);
324 break;
325 case '/':
326 e = yasm_expr_create_tree(e, YASM_EXPR_DIV, f, 0);
327 break;
328 case '%':
329 e = yasm_expr_create_tree(e, YASM_EXPR_MOD, f, 0);
330 break;
331 case TOKEN_SDIV:
332 e = yasm_expr_create_tree(e, YASM_EXPR_SIGNDIV, f, 0);
333 break;
334 case TOKEN_SMOD:
335 e = yasm_expr_create_tree(e, YASM_EXPR_SIGNMOD, f, 0);
336 break;
337 }
338 }
339 return e;
340 }
341
expr6(void)342 static yasm_expr *expr6(void)
343 {
344 yasm_expr *e = NULL;
345
346 if (i == '-') {
347 i = scan(scpriv, tokval);
348 e = expr6();
349 if (!e)
350 return NULL;
351 return yasm_expr_create_branch(YASM_EXPR_NEG, e, 0);
352 } else if (i == '+') {
353 i = scan(scpriv, tokval);
354 return expr6();
355 } else if (i == '~') {
356 i = scan(scpriv, tokval);
357 e = expr6();
358 if (!e)
359 return NULL;
360 return yasm_expr_create_branch(YASM_EXPR_NOT, e, 0);
361 } else if (i == TOKEN_SEG) {
362 i = scan(scpriv, tokval);
363 e = expr6();
364 if (!e)
365 return NULL;
366 error(ERR_NONFATAL, "%s not supported", "SEG");
367 return e;
368 } else if (i == '(') {
369 i = scan(scpriv, tokval);
370 e = bexpr();
371 if (!e)
372 return NULL;
373 if (i != ')') {
374 error(ERR_NONFATAL, "expecting `)'");
375 return NULL;
376 }
377 i = scan(scpriv, tokval);
378 return e;
379 }
380 else if (i == TOKEN_NUM || i == TOKEN_ID ||
381 i == TOKEN_HERE || i == TOKEN_BASE)
382 {
383 switch (i) {
384 case TOKEN_NUM:
385 e = yasm_expr_create_ident(yasm_expr_int(tokval->t_integer), 0);
386 break;
387 case TOKEN_ID:
388 if (nasm_symtab) {
389 yasm_symrec *sym =
390 yasm_symtab_get(nasm_symtab, tokval->t_charptr);
391 if (sym) {
392 e = yasm_expr_create_ident(yasm_expr_sym(sym), 0);
393 } else {
394 error(ERR_NONFATAL,
395 "undefined symbol `%s' in preprocessor",
396 tokval->t_charptr);
397 e = yasm_expr_create_ident(yasm_expr_int(
398 yasm_intnum_create_int(1)), 0);
399 }
400 break;
401 }
402 /*fallthrough*/
403 case TOKEN_HERE:
404 case TOKEN_BASE:
405 error(ERR_NONFATAL,
406 "cannot reference symbol `%s' in preprocessor",
407 (i == TOKEN_ID ? tokval->t_charptr :
408 i == TOKEN_HERE ? "$" : "$$"));
409 e = yasm_expr_create_ident(yasm_expr_int(yasm_intnum_create_int(1)),
410 0);
411 break;
412 }
413 i = scan(scpriv, tokval);
414 return e;
415 } else {
416 error(ERR_NONFATAL, "expression syntax error");
417 return NULL;
418 }
419 }
420
nasm_evaluate(scanner sc,void * scprivate,struct tokenval * tv,int critical,efunc report_error)421 yasm_expr *nasm_evaluate (scanner sc, void *scprivate, struct tokenval *tv,
422 int critical, efunc report_error)
423 {
424 if (critical & CRITICAL) {
425 critical &= ~CRITICAL;
426 bexpr = rexp0;
427 } else
428 bexpr = expr0;
429
430 scan = sc;
431 scpriv = scprivate;
432 tokval = tv;
433 error = report_error;
434
435 if (tokval->t_type == TOKEN_INVALID)
436 i = scan(scpriv, tokval);
437 else
438 i = tokval->t_type;
439
440 return bexpr ();
441 }
442