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 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 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 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 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 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 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 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 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 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 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 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 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