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