Home | History | Annotate | Download | only in nasm
      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