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