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