Home | History | Annotate | Download | only in nasm
      1 /*
      2  * NASM-compatible parser
      3  *
      4  *  Copyright (C) 2001-2007  Peter Johnson, Michael Urman
      5  *
      6  * Redistribution and use in source and binary forms, with or without
      7  * modification, are permitted provided that the following conditions
      8  * are met:
      9  * 1. Redistributions of source code must retain the above copyright
     10  *    notice, this list of conditions and the following disclaimer.
     11  * 2. Redistributions in binary form must reproduce the above copyright
     12  *    notice, this list of conditions and the following disclaimer in the
     13  *    documentation and/or other materials provided with the distribution.
     14  *
     15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
     16  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
     19  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     20  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     21  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     23  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     24  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     25  * POSSIBILITY OF SUCH DAMAGE.
     26  */
     27 #include <util.h>
     28 
     29 #include <libyasm.h>
     30 
     31 #include <math.h>
     32 
     33 #include "modules/parsers/nasm/nasm-parser.h"
     34 #include "modules/preprocs/nasm/nasm.h"
     35 
     36 typedef enum {
     37     NORM_EXPR,
     38     DIR_EXPR,       /* Can't have seg:off or WRT anywhere */
     39     DV_EXPR         /* Can't have registers anywhere */
     40 } expr_type;
     41 
     42 static yasm_bytecode *parse_line(yasm_parser_nasm *parser_nasm);
     43 static int parse_directive_valparams(yasm_parser_nasm *parser_nasm,
     44                                      /*@out@*/ yasm_valparamhead *vps);
     45 static yasm_bytecode *parse_times(yasm_parser_nasm *parser_nasm);
     46 static yasm_bytecode *parse_exp(yasm_parser_nasm *parser_nasm);
     47 static yasm_bytecode *parse_instr(yasm_parser_nasm *parser_nasm);
     48 static yasm_insn_operand *parse_operand(yasm_parser_nasm *parser_nasm);
     49 static yasm_insn_operand *parse_memaddr(yasm_parser_nasm *parser_nasm);
     50 static yasm_expr *parse_expr(yasm_parser_nasm *parser_nasm, expr_type type);
     51 static yasm_expr *parse_bexpr(yasm_parser_nasm *parser_nasm, expr_type type);
     52 static yasm_expr *parse_expr0(yasm_parser_nasm *parser_nasm, expr_type type);
     53 static yasm_expr *parse_expr1(yasm_parser_nasm *parser_nasm, expr_type type);
     54 static yasm_expr *parse_expr2(yasm_parser_nasm *parser_nasm, expr_type type);
     55 static yasm_expr *parse_expr3(yasm_parser_nasm *parser_nasm, expr_type type);
     56 static yasm_expr *parse_expr4(yasm_parser_nasm *parser_nasm, expr_type type);
     57 static yasm_expr *parse_expr5(yasm_parser_nasm *parser_nasm, expr_type type);
     58 static yasm_expr *parse_expr6(yasm_parser_nasm *parser_nasm, expr_type type);
     59 
     60 static void nasm_parser_directive
     61     (yasm_parser_nasm *parser_nasm, const char *name,
     62      /*@null@*/ yasm_valparamhead *valparams,
     63      /*@null@*/ yasm_valparamhead *objext_valparams);
     64 static void set_nonlocal_label(yasm_parser_nasm *parser_nasm, const char *name);
     65 static void define_label(yasm_parser_nasm *parser_nasm, /*@only@*/ char *name,
     66                          unsigned int size);
     67 
     68 static void yasm_ea_set_implicit_size_segment(yasm_parser_nasm *parser_nasm,
     69                                               yasm_effaddr *ea, yasm_expr *e)
     70 {
     71     if (parser_nasm->tasm) {
     72         const char *segment = yasm_expr_segment(e);
     73         ea->data_len = yasm_expr_size(e);
     74         if (segment) {
     75             const char *segreg = tasm_get_segment_register(segment);
     76             if (segreg)
     77                 yasm_arch_parse_check_regtmod(p_object->arch, segreg,
     78                                               strlen(segreg), &ea->segreg);
     79         }
     80     }
     81 }
     82 
     83 
     84 #define is_eol_tok(tok) ((tok) == 0)
     85 #define is_eol()        is_eol_tok(curtok)
     86 
     87 #define get_next_token()    (curtok = nasm_parser_lex(&curval, parser_nasm))
     88 
     89 static void
     90 get_peek_token(yasm_parser_nasm *parser_nasm)
     91 {
     92     char savech = parser_nasm->tokch;
     93     if (parser_nasm->peek_token != NONE)
     94         yasm_internal_error(N_("only can have one token of lookahead"));
     95     parser_nasm->peek_token =
     96         nasm_parser_lex(&parser_nasm->peek_tokval, parser_nasm);
     97     parser_nasm->peek_tokch = parser_nasm->tokch;
     98     parser_nasm->tokch = savech;
     99 }
    100 
    101 static void
    102 destroy_curtok_(yasm_parser_nasm *parser_nasm)
    103 {
    104     if (curtok < 256)
    105         ;
    106     else switch ((enum tokentype)curtok) {
    107         case INTNUM:
    108             yasm_intnum_destroy(curval.intn);
    109             break;
    110         case FLTNUM:
    111             yasm_floatnum_destroy(curval.flt);
    112             break;
    113         case DIRECTIVE_NAME:
    114         case FILENAME:
    115         case ID:
    116         case LOCAL_ID:
    117         case SPECIAL_ID:
    118         case NONLOCAL_ID:
    119             yasm_xfree(curval.str_val);
    120             break;
    121         case STRING:
    122             yasm_xfree(curval.str.contents);
    123             break;
    124         case INSN:
    125             yasm_bc_destroy(curval.bc);
    126             break;
    127         default:
    128             break;
    129     }
    130     curtok = NONE;          /* sanity */
    131 }
    132 #define destroy_curtok()    destroy_curtok_(parser_nasm)
    133 
    134 /* Eat all remaining tokens to EOL, discarding all of them.  If there's any
    135  * intervening tokens, generates an error (junk at end of line).
    136  */
    137 static void
    138 demand_eol_(yasm_parser_nasm *parser_nasm)
    139 {
    140     if (is_eol())
    141         return;
    142 
    143     yasm_error_set(YASM_ERROR_SYNTAX,
    144         N_("junk at end of line, first unrecognized character is `%c'"),
    145         parser_nasm->tokch);
    146 
    147     do {
    148         destroy_curtok();
    149         get_next_token();
    150     } while (!is_eol());
    151 }
    152 #define demand_eol() demand_eol_(parser_nasm)
    153 
    154 static const char *
    155 describe_token(int token)
    156 {
    157     static char strch[] = "` '";
    158     const char *str;
    159 
    160     switch (token) {
    161         case 0:                 str = "end of line"; break;
    162         case INTNUM:            str = "integer"; break;
    163         case FLTNUM:            str = "floating point value"; break;
    164         case DIRECTIVE_NAME:    str = "directive name"; break;
    165         case FILENAME:          str = "filename"; break;
    166         case STRING:            str = "string"; break;
    167         case SIZE_OVERRIDE:     str = "size override"; break;
    168         case DECLARE_DATA:      str = "DB/DW/etc."; break;
    169         case RESERVE_SPACE:     str = "RESB/RESW/etc."; break;
    170         case INCBIN:            str = "INCBIN"; break;
    171         case EQU:               str = "EQU"; break;
    172         case TIMES:             str = "TIMES"; break;
    173         case SEG:               str = "SEG"; break;
    174         case WRT:               str = "WRT"; break;
    175         case NOSPLIT:           str = "NOSPLIT"; break;
    176         case STRICT:            str = "STRICT"; break;
    177         case INSN:              str = "instruction"; break;
    178         case PREFIX:            str = "instruction prefix"; break;
    179         case REG:               str = "register"; break;
    180         case REGGROUP:          str = "register group"; break;
    181         case SEGREG:            str = "segment register"; break;
    182         case TARGETMOD:         str = "target modifier"; break;
    183         case LEFT_OP:           str = "<<"; break;
    184         case RIGHT_OP:          str = ">>"; break;
    185         case SIGNDIV:           str = "//"; break;
    186         case SIGNMOD:           str = "%%"; break;
    187         case START_SECTION_ID:  str = "$$"; break;
    188         case ID:                str = "identifier"; break;
    189         case LOCAL_ID:          str = ".identifier"; break;
    190         case SPECIAL_ID:        str = "..identifier"; break;
    191         case NONLOCAL_ID:       str = "..@identifier"; break;
    192         case LINE:              str = "%line"; break;
    193         default:
    194             strch[1] = token;
    195             str = strch;
    196             break;
    197     }
    198 
    199     return str;
    200 }
    201 
    202 static int
    203 expect_(yasm_parser_nasm *parser_nasm, int token)
    204 {
    205     if (curtok == token)
    206         return 1;
    207 
    208     yasm_error_set(YASM_ERROR_PARSE, "expected %s", describe_token(token));
    209     destroy_curtok();
    210     return 0;
    211 }
    212 #define expect(token) expect_(parser_nasm, token)
    213 
    214 void
    215 nasm_parser_parse(yasm_parser_nasm *parser_nasm)
    216 {
    217     unsigned char *line;
    218     while ((line = (unsigned char *)
    219             yasm_preproc_get_line(parser_nasm->preproc)) != NULL) {
    220         yasm_bytecode *bc = NULL, *temp_bc;
    221 
    222         parser_nasm->s.bot = line;
    223         parser_nasm->s.tok = line;
    224         parser_nasm->s.ptr = line;
    225         parser_nasm->s.cur = line;
    226         parser_nasm->s.lim = line + strlen((char *)line)+1;
    227         parser_nasm->s.top = parser_nasm->s.lim;
    228 
    229         get_next_token();
    230         if (!is_eol()) {
    231             bc = parse_line(parser_nasm);
    232             demand_eol();
    233         }
    234 
    235         if (parser_nasm->abspos) {
    236             /* If we're inside an absolute section, just add to the absolute
    237              * position rather than appending bytecodes to a section.
    238              * Only RES* are allowed in an absolute section, so this is easy.
    239              */
    240             if (bc) {
    241                 /*@null@*/ const yasm_expr *numitems, *multiple;
    242                 unsigned int itemsize;
    243                 numitems = yasm_bc_reserve_numitems(bc, &itemsize);
    244                 if (numitems) {
    245                     yasm_expr *e;
    246                     e = yasm_expr_create(YASM_EXPR_MUL,
    247                         yasm_expr_expr(yasm_expr_copy(numitems)),
    248                         yasm_expr_int(yasm_intnum_create_uint(itemsize)),
    249                         cur_line);
    250                     multiple = yasm_bc_get_multiple_expr(bc);
    251                     if (multiple)
    252                         e = yasm_expr_create_tree(e, YASM_EXPR_MUL,
    253                                                   yasm_expr_copy(multiple),
    254                                                   cur_line);
    255                     parser_nasm->abspos = yasm_expr_create_tree(
    256                         parser_nasm->abspos, YASM_EXPR_ADD, e, cur_line);
    257                 } else
    258                     yasm_error_set(YASM_ERROR_SYNTAX,
    259                         N_("only RES* allowed within absolute section"));
    260                 yasm_bc_destroy(bc);
    261             }
    262             temp_bc = NULL;
    263         } else if (bc) {
    264             temp_bc = yasm_section_bcs_append(cursect, bc);
    265             if (temp_bc)
    266                 parser_nasm->prev_bc = temp_bc;
    267         } else
    268             temp_bc = NULL;
    269         yasm_errwarn_propagate(parser_nasm->errwarns, cur_line);
    270 
    271         if (parser_nasm->save_input)
    272             yasm_linemap_add_source(parser_nasm->linemap, temp_bc,
    273                                     (char *)line);
    274         yasm_linemap_goto_next(parser_nasm->linemap);
    275         yasm_xfree(line);
    276     }
    277 }
    278 
    279 /* All parse_* functions expect to be called with curtok being their first
    280  * token.  They should return with curtok being the token *after* their
    281  * information.
    282  */
    283 
    284 static yasm_bytecode *
    285 parse_line(yasm_parser_nasm *parser_nasm)
    286 {
    287     yasm_bytecode *bc;
    288 
    289     bc = parse_exp(parser_nasm);
    290     if (bc)
    291         return bc;
    292 
    293     switch (curtok) {
    294         case LINE: /* LINE INTNUM '+' INTNUM FILENAME */
    295         {
    296             yasm_intnum *line, *incr;
    297             char *filename;
    298 
    299             get_next_token();
    300 
    301             if (!expect(INTNUM)) return NULL;
    302             line = INTNUM_val;
    303             get_next_token();
    304 
    305             if (!expect('+')) return NULL;
    306             get_next_token();
    307 
    308             if (!expect(INTNUM)) return NULL;
    309             incr = INTNUM_val;
    310             get_next_token();
    311 
    312             if (!expect(FILENAME)) return NULL;
    313             filename = FILENAME_val;
    314             get_next_token();
    315 
    316             /* %line indicates the line number of the *next* line, so subtract
    317              * out the increment when setting the line number.
    318              */
    319             yasm_linemap_set(parser_nasm->linemap, filename, 0,
    320                 yasm_intnum_get_uint(line) - yasm_intnum_get_uint(incr),
    321                 yasm_intnum_get_uint(incr));
    322             yasm_intnum_destroy(line);
    323             yasm_intnum_destroy(incr);
    324             yasm_xfree(filename);
    325             return NULL;
    326         }
    327         case '[': /* [ directive ] */
    328         {
    329             char *dirname;
    330             yasm_valparamhead dir_vps;
    331             int have_vps = 1;
    332 
    333             parser_nasm->state = DIRECTIVE;
    334             get_next_token();
    335 
    336             if (!expect(DIRECTIVE_NAME))
    337                 return NULL;
    338             dirname = DIRECTIVE_NAME_val;
    339             get_next_token();
    340 
    341             /* ignore [warning].  TODO: actually implement */
    342             if (yasm__strcasecmp(dirname, "warning") == 0) {
    343                 yasm_warn_set(YASM_WARN_GENERAL,
    344                     N_("[warning] directive not supported; ignored"));
    345 
    346                 /* throw away the rest of the directive tokens */
    347                 while (!is_eol() && curtok != ']')
    348                 {
    349                     destroy_curtok();
    350                     get_next_token();
    351                 }
    352                 expect(']');
    353                 get_next_token();
    354                 return NULL;
    355             }
    356 
    357             if (curtok == ']' || curtok == ':')
    358                 have_vps = 0;
    359             else if (!parse_directive_valparams(parser_nasm, &dir_vps)) {
    360                 yasm_error_set(YASM_ERROR_SYNTAX,
    361                                N_("invalid arguments to [%s]"), dirname);
    362                 yasm_xfree(dirname);
    363                 return NULL;
    364             }
    365             if (curtok == ':') {
    366                 yasm_valparamhead ext_vps;
    367                 get_next_token();
    368                 if (!parse_directive_valparams(parser_nasm, &ext_vps)) {
    369                     yasm_error_set(YASM_ERROR_SYNTAX,
    370                                    N_("invalid arguments to [%s]"), dirname);
    371                     yasm_xfree(dirname);
    372                     return NULL;
    373                 }
    374                 nasm_parser_directive(parser_nasm, dirname,
    375                                       have_vps ? &dir_vps : NULL, &ext_vps);
    376             } else
    377                 nasm_parser_directive(parser_nasm, dirname,
    378                                       have_vps ? &dir_vps : NULL, NULL);
    379             yasm_xfree(dirname);
    380             expect(']');
    381             get_next_token();
    382             return NULL;
    383         }
    384         case TIMES: /* TIMES expr exp */
    385             get_next_token();
    386             return parse_times(parser_nasm);
    387         case ID:
    388         case SPECIAL_ID:
    389         case NONLOCAL_ID:
    390         case LOCAL_ID:
    391         {
    392             char *name = ID_val;
    393             int local = parser_nasm->tasm
    394                 ? (curtok == ID || curtok == LOCAL_ID ||
    395                         (curtok == SPECIAL_ID && name[0] == '@'))
    396                 : (curtok != ID);
    397             unsigned int size = 0;
    398 
    399             get_next_token();
    400             if (is_eol()) {
    401                 /* label alone on the line */
    402                 yasm_warn_set(YASM_WARN_ORPHAN_LABEL,
    403                     N_("label alone on a line without a colon might be in error"));
    404                 if (!local)
    405                     set_nonlocal_label(parser_nasm, name);
    406                 define_label(parser_nasm, name, 0);
    407                 return NULL;
    408             }
    409             if (curtok == ':')
    410                 get_next_token();
    411 
    412             if (curtok == EQU || (parser_nasm->tasm && curtok == '=')) {
    413                 /* label EQU expr */
    414                 yasm_expr *e;
    415                 get_next_token();
    416 
    417                 if (parser_nasm->tasm && curtok == SIZE_OVERRIDE) {
    418                     size = SIZE_OVERRIDE_val;
    419                     get_next_token();
    420                 }
    421 
    422                 e = parse_expr(parser_nasm, NORM_EXPR);
    423                 if (!e) {
    424                     yasm_error_set(YASM_ERROR_SYNTAX,
    425                                    N_("expression expected after %s"), "EQU");
    426                     yasm_xfree(name);
    427                     return NULL;
    428                 }
    429                 yasm_symtab_define_equ(p_symtab, name, e, cur_line);
    430                 yasm_xfree(name);
    431                 return NULL;
    432             }
    433 
    434             if (parser_nasm->tasm && curtok == LABEL)
    435                 get_next_token();
    436 
    437             if (parser_nasm->tasm && curtok == SIZE_OVERRIDE) {
    438                 size = SIZE_OVERRIDE_val;
    439                 get_next_token();
    440             }
    441 
    442             if (!local)
    443                 set_nonlocal_label(parser_nasm, name);
    444 
    445             if (is_eol()) {
    446                 define_label(parser_nasm, name, size);
    447                 return NULL;
    448             }
    449             if (curtok == TIMES) {
    450                 define_label(parser_nasm, name, size);
    451                 get_next_token();
    452                 return parse_times(parser_nasm);
    453             }
    454             bc = parse_exp(parser_nasm);
    455             if (!parser_nasm->tasm && !bc)
    456                 yasm_error_set(YASM_ERROR_SYNTAX,
    457                                N_("instruction expected after label"));
    458             if (parser_nasm->tasm && bc && !size)
    459                 size = yasm_bc_elem_size(bc);
    460             define_label(parser_nasm, name, size);
    461             return bc;
    462         }
    463         default:
    464             yasm_error_set(YASM_ERROR_SYNTAX,
    465                 N_("label or instruction expected at start of line"));
    466             return NULL;
    467     }
    468 }
    469 
    470 static int
    471 parse_directive_valparams(yasm_parser_nasm *parser_nasm,
    472                           /*@out@*/ yasm_valparamhead *vps)
    473 {
    474     yasm_vps_initialize(vps);
    475     for (;;) {
    476         yasm_valparam *vp;
    477         yasm_expr *e;
    478         char *id = NULL;
    479 
    480         /* Look for value first */
    481         if (curtok == ID) {
    482             get_peek_token(parser_nasm);
    483             if (parser_nasm->peek_token == '=') {
    484                 id = ID_val;
    485                 get_next_token(); /* id */
    486                 get_next_token(); /* '=' */
    487             }
    488         }
    489 
    490         /* Look for parameter */
    491         switch (curtok) {
    492             case STRING:
    493                 vp = yasm_vp_create_string(id, STRING_val.contents);
    494                 get_next_token();
    495                 break;
    496             case ID:
    497                 /* We need a peek token, but avoid error if we have one
    498                  * already; we need to work whether or not we hit the
    499                  * "value=" if test above.
    500                  *
    501                  * We cheat and peek ahead to see if this is just an ID or
    502                  * the ID is part of an expression.  We assume a + or - means
    503                  * that it's part of an expression (e.g. "x+y" is parsed as
    504                  * the expression "x+y" and not as "x", "+y").
    505                  */
    506                 if (parser_nasm->peek_token == NONE)
    507                     get_peek_token(parser_nasm);
    508                 switch (parser_nasm->peek_token) {
    509                     case '|': case '^': case '&': case LEFT_OP: case RIGHT_OP:
    510                     case '+': case '-':
    511                     case '*': case '/': case '%': case SIGNDIV: case SIGNMOD:
    512                         break;
    513                     default:
    514                         /* Just an id */
    515                         vp = yasm_vp_create_id(id, ID_val, '$');
    516                         get_next_token();
    517                         goto next;
    518                 }
    519                 /*@fallthrough@*/
    520             default:
    521                 e = parse_expr(parser_nasm, DIR_EXPR);
    522                 if (!e) {
    523                     yasm_vps_delete(vps);
    524                     return 0;
    525                 }
    526                 vp = yasm_vp_create_expr(id, e);
    527                 break;
    528         }
    529 next:
    530         yasm_vps_append(vps, vp);
    531         if (curtok == ',')
    532             get_next_token();
    533         if (curtok == ']' || curtok == ':' || is_eol())
    534             return 1;
    535     }
    536 }
    537 
    538 static yasm_bytecode *
    539 parse_times(yasm_parser_nasm *parser_nasm)
    540 {
    541     yasm_expr *multiple;
    542     yasm_bytecode *bc;
    543 
    544     multiple = parse_bexpr(parser_nasm, DV_EXPR);
    545     if (!multiple) {
    546         yasm_error_set(YASM_ERROR_SYNTAX, N_("expression expected after %s"),
    547                        "TIMES");
    548         return NULL;
    549     }
    550     bc = parse_exp(parser_nasm);
    551     if (!bc) {
    552         yasm_error_set(YASM_ERROR_SYNTAX,
    553                        N_("instruction expected after TIMES expression"));
    554         yasm_expr_destroy(multiple);
    555         return NULL;
    556     }
    557     yasm_bc_set_multiple(bc, multiple);
    558     return bc;
    559 }
    560 
    561 static yasm_bytecode *
    562 parse_exp(yasm_parser_nasm *parser_nasm)
    563 {
    564     yasm_bytecode *bc;
    565 
    566     bc = parse_instr(parser_nasm);
    567     if (bc)
    568         return bc;
    569 
    570     switch (curtok) {
    571         case DECLARE_DATA:
    572         {
    573             unsigned int size = DECLARE_DATA_val/8;
    574             yasm_datavalhead dvs;
    575             yasm_dataval *dv;
    576             yasm_expr *e, *e2;
    577 
    578             get_next_token();
    579 
    580             yasm_dvs_initialize(&dvs);
    581             for (;;) {
    582                 if (curtok == STRING) {
    583                     /* Peek ahead to see if we're in an expr.  If we're not,
    584                      * then generate a real string dataval.
    585                      */
    586                     get_peek_token(parser_nasm);
    587                     if (parser_nasm->peek_token == ','
    588                         || is_eol_tok(parser_nasm->peek_token)) {
    589                         dv = yasm_dv_create_string(STRING_val.contents,
    590                                                    STRING_val.len);
    591                         get_next_token();
    592                         goto dv_done;
    593                     }
    594                 }
    595                 if (curtok == '?') {
    596                     yasm_dvs_delete(&dvs);
    597                     get_next_token();
    598                     if (! is_eol_tok(curtok)) {
    599                         yasm_error_set(YASM_ERROR_SYNTAX,
    600                                 N_("can not handle more than one '?'"));
    601                         return NULL;
    602                     }
    603                     return yasm_bc_create_reserve(
    604                             p_expr_new_ident(yasm_expr_int(
    605                                 yasm_intnum_create_uint(1))),
    606                             size, cur_line);
    607                 }
    608                 if (!(e = parse_bexpr(parser_nasm, DV_EXPR))) {
    609                     yasm_error_set(YASM_ERROR_SYNTAX,
    610                                    N_("expression or string expected"));
    611                     yasm_dvs_delete(&dvs);
    612                     return NULL;
    613                 }
    614                 if (curtok == DUP) {
    615                     get_next_token();
    616                     if (curtok != '(') {
    617                         yasm_error_set(YASM_ERROR_SYNTAX,
    618                                        N_("expected ( after DUP"));
    619                         goto error;
    620                     }
    621                     get_next_token();
    622                     if (curtok == '?') {
    623                         get_next_token();
    624                         if (curtok != ')') {
    625                             yasm_error_set(YASM_ERROR_SYNTAX,
    626                                 N_("expected ) after DUPlicated expression"));
    627                             goto error;
    628                         }
    629                         get_next_token();
    630                         if (! is_eol_tok(curtok)) {
    631                             yasm_error_set(YASM_ERROR_SYNTAX,
    632                                     N_("can not handle more than one '?'"));
    633                             goto error;
    634                         }
    635                         yasm_dvs_delete(&dvs);
    636                         return yasm_bc_create_reserve(e, size, cur_line);
    637                     } else if ((e2 = parse_bexpr(parser_nasm, DV_EXPR))) {
    638                         if (curtok != ')') {
    639                             yasm_expr_destroy(e2);
    640                             yasm_error_set(YASM_ERROR_SYNTAX,
    641                                 N_("expected ) after DUPlicated expression"));
    642                             goto error;
    643                         }
    644                         get_next_token();
    645                         dv = yasm_dv_create_expr(e2);
    646                         yasm_dv_set_multiple(dv, e);
    647                     } else {
    648                         yasm_error_set(YASM_ERROR_SYNTAX,
    649                                        N_("expression or string expected"));
    650 error:
    651                         yasm_expr_destroy(e);
    652                         yasm_dvs_delete(&dvs);
    653                         return NULL;
    654                     }
    655                 } else
    656                     dv = yasm_dv_create_expr(e);
    657 dv_done:
    658                 yasm_dvs_append(&dvs, dv);
    659                 if (is_eol())
    660                     break;
    661                 if (!expect(',')) {
    662                     yasm_dvs_delete(&dvs);
    663                     return NULL;
    664                 }
    665                 get_next_token();
    666                 if (is_eol())   /* allow trailing , on list */
    667                     break;
    668             }
    669             return yasm_bc_create_data(&dvs, size, 0, p_object->arch,
    670                                        cur_line);
    671         }
    672         case RESERVE_SPACE:
    673         {
    674             unsigned int size = RESERVE_SPACE_val/8;
    675             yasm_expr *e;
    676             get_next_token();
    677             e = parse_bexpr(parser_nasm, DV_EXPR);
    678             if (!e) {
    679                 yasm_error_set(YASM_ERROR_SYNTAX,
    680                                N_("expression expected after %s"), "RESx");
    681                 return NULL;
    682             }
    683             return yasm_bc_create_reserve(e, size, cur_line);
    684         }
    685         case INCBIN:
    686         {
    687             char *filename;
    688             yasm_expr *start = NULL, *maxlen = NULL;
    689 
    690             get_next_token();
    691 
    692             if (!expect(STRING)) {
    693                 yasm_error_set(YASM_ERROR_SYNTAX,
    694                                N_("filename string expected after INCBIN"));
    695                 return NULL;
    696             }
    697             filename = STRING_val.contents;
    698             get_next_token();
    699 
    700             /* optional start expression */
    701             if (curtok == ',')
    702                 get_next_token();
    703             if (is_eol())
    704                 goto incbin_done;
    705             start = parse_bexpr(parser_nasm, DV_EXPR);
    706             if (!start) {
    707                 yasm_error_set(YASM_ERROR_SYNTAX,
    708                                N_("expression expected for INCBIN start"));
    709                 return NULL;
    710             }
    711 
    712             /* optional maxlen expression */
    713             if (curtok == ',')
    714                 get_next_token();
    715             if (is_eol())
    716                 goto incbin_done;
    717             maxlen = parse_bexpr(parser_nasm, DV_EXPR);
    718             if (!maxlen) {
    719                 yasm_error_set(YASM_ERROR_SYNTAX,
    720                     N_("expression expected for INCBIN maximum length"));
    721                 return NULL;
    722             }
    723 
    724 incbin_done:
    725             return yasm_bc_create_incbin(filename, start, maxlen,
    726                                          parser_nasm->linemap, cur_line);
    727         }
    728         default:
    729             return NULL;
    730     }
    731 }
    732 
    733 static yasm_bytecode *
    734 parse_instr(yasm_parser_nasm *parser_nasm)
    735 {
    736     yasm_bytecode *bc;
    737 
    738     switch (curtok) {
    739         case INSN:
    740         {
    741             yasm_insn *insn;
    742             bc = INSN_val;
    743             insn = yasm_bc_get_insn(bc);
    744 
    745             get_next_token();
    746             if (is_eol())
    747                 return bc;      /* no operands */
    748 
    749             /* parse operands */
    750             for (;;) {
    751                 yasm_insn_operand *op = parse_operand(parser_nasm);
    752                 if (!op) {
    753                     if (insn->num_operands == 0)
    754                         yasm_error_set(YASM_ERROR_SYNTAX,
    755                                        N_("unexpected %s after instruction"),
    756                                        describe_token(curtok));
    757                     else
    758                         yasm_error_set(YASM_ERROR_SYNTAX,
    759                                        N_("expected operand, got %s"),
    760                                        describe_token(curtok));
    761                     yasm_bc_destroy(bc);
    762                     return NULL;
    763                 }
    764                 yasm_insn_ops_append(insn, op);
    765 
    766                 if (is_eol())
    767                     break;
    768                 if (!expect(',')) {
    769                     yasm_bc_destroy(bc);
    770                     return NULL;
    771                 }
    772                 get_next_token();
    773             }
    774             return bc;
    775         }
    776         case PREFIX:
    777         {
    778             uintptr_t prefix = PREFIX_val;
    779             get_next_token();
    780             bc = parse_instr(parser_nasm);
    781             if (!bc)
    782                 bc = yasm_arch_create_empty_insn(p_object->arch, cur_line);
    783             yasm_insn_add_prefix(yasm_bc_get_insn(bc), prefix);
    784             return bc;
    785         }
    786         case SEGREG:
    787         {
    788             uintptr_t segreg = SEGREG_val;
    789             get_next_token();
    790             bc = parse_instr(parser_nasm);
    791             if (!bc)
    792                 bc = yasm_arch_create_empty_insn(p_object->arch, cur_line);
    793             yasm_insn_add_seg_prefix(yasm_bc_get_insn(bc), segreg);
    794             return bc;
    795         }
    796         default:
    797             return NULL;
    798     }
    799 }
    800 
    801 static yasm_insn_operand *
    802 parse_operand(yasm_parser_nasm *parser_nasm)
    803 {
    804     yasm_insn_operand *op;
    805     switch (curtok) {
    806         case '[':
    807         {
    808             get_next_token();
    809             op = parse_memaddr(parser_nasm);
    810 
    811             expect(']');
    812             get_next_token();
    813 
    814             if (!op) {
    815                 yasm_error_set(YASM_ERROR_SYNTAX,
    816                                N_("memory address expected"));
    817                 return NULL;
    818             }
    819 
    820             if (parser_nasm->tasm && !is_eol() && curtok != ',') {
    821                 yasm_expr *e = NULL, *f;
    822                 yasm_effaddr *ea;
    823 
    824                 switch (op->type) {
    825                     case YASM_INSN__OPERAND_IMM:
    826                         e = op->data.val;
    827                         break;
    828                     case YASM_INSN__OPERAND_MEMORY:
    829                         if (op->data.ea->disp.rel) {
    830                             yasm_error_set(YASM_ERROR_SYNTAX,
    831                                     N_("relative adressing not supported\n"));
    832                             return NULL;
    833                         }
    834                         e = yasm_expr_copy(op->data.ea->disp.abs);
    835                         yasm_arch_ea_destroy(p_object->arch, op->data.ea);
    836                         break;
    837                     case YASM_INSN__OPERAND_REG:
    838                     case YASM_INSN__OPERAND_SEGREG:
    839                         yasm_error_set(YASM_ERROR_SYNTAX,
    840                                 N_("register adressing not supported\n"));
    841                         return NULL;
    842                 }
    843                 yasm_xfree(op);
    844                 f = parse_bexpr(parser_nasm, NORM_EXPR);
    845                 if (!f) {
    846                     yasm_expr_destroy(e);
    847                     yasm_error_set(YASM_ERROR_SYNTAX,
    848                                    N_("expected expression after ]"));
    849                     return NULL;
    850                 }
    851                 e = p_expr_new_tree(e, YASM_EXPR_ADD, f);
    852                 ea = yasm_arch_ea_create(p_object->arch, e);
    853                 yasm_ea_set_implicit_size_segment(parser_nasm, ea, e);
    854                 op = yasm_operand_create_mem(ea);
    855             }
    856             return op;
    857         }
    858         case OFFSET:
    859         {
    860             yasm_insn_operand *op2;
    861             get_next_token();
    862             if (parser_nasm->masm && curtok == ID && !yasm__strcasecmp(ID_val, "flat")) {
    863                 get_next_token();
    864                 if (curtok == ':') {
    865                     get_next_token();
    866                 }
    867             }
    868             op = parse_operand(parser_nasm);
    869             if (!op) {
    870                 yasm_error_set(YASM_ERROR_SYNTAX,
    871                                N_("memory address expected"));
    872                 return NULL;
    873             }
    874             if (op->type == YASM_INSN__OPERAND_IMM)
    875                 return op;
    876             if (op->type != YASM_INSN__OPERAND_MEMORY) {
    877                 yasm_error_set(YASM_ERROR_SYNTAX,
    878                                N_("OFFSET applied to non-memory operand"));
    879                 return NULL;
    880             }
    881             if (op->data.ea->disp.rel) {
    882                 yasm_error_set(YASM_ERROR_SYNTAX,
    883                                N_("OFFSET applied to non-absolute memory operand"));
    884                 return NULL;
    885             }
    886             if (op->data.ea->disp.abs)
    887                 op2 = yasm_operand_create_imm(op->data.ea->disp.abs);
    888             else
    889                 op2 = yasm_operand_create_imm(p_expr_new_ident(
    890                         yasm_expr_int(yasm_intnum_create_uint(0))));
    891             yasm_xfree(op);
    892             return op2;
    893         }
    894         case SEGREG:
    895         {
    896             uintptr_t segreg = SEGREG_val;
    897             get_next_token();
    898             if (parser_nasm->tasm && curtok == ':') {
    899                 get_next_token();
    900                 op = parse_operand(parser_nasm);
    901                 if (!op)
    902                     return NULL;
    903                 if (op->type == YASM_INSN__OPERAND_IMM) {
    904                     yasm_effaddr *ea = yasm_arch_ea_create(p_object->arch,
    905                                                            op->data.val);
    906                     yasm_insn_operand *op2;
    907                     yasm_ea_set_implicit_size_segment(parser_nasm, ea,
    908                                                       op->data.val);
    909                     op2 = yasm_operand_create_mem(ea);
    910                     op2->size = op->size;
    911                     yasm_xfree(op);
    912                     op = op2;
    913                 }
    914                 if (op->type != YASM_INSN__OPERAND_MEMORY) {
    915                     yasm_error_set(YASM_ERROR_SYNTAX,
    916                                    N_("segment applied to non-memory operand"));
    917                     return NULL;
    918                 }
    919                 yasm_ea_set_segreg(op->data.ea, segreg);
    920                 return op;
    921             }
    922             op = yasm_operand_create_segreg(segreg);
    923             return op;
    924         }
    925         case REG:
    926             op = yasm_operand_create_reg(REG_val);
    927             get_next_token();
    928             return op;
    929         case REGGROUP:
    930         {
    931             unsigned long regindex;
    932             uintptr_t reg = REGGROUP_val;
    933             get_next_token(); /* REGGROUP */
    934             if (curtok != '(')
    935                 return yasm_operand_create_reg(reg);
    936             get_next_token(); /* '(' */
    937             if (!expect(INTNUM)) {
    938                 yasm_error_set(YASM_ERROR_SYNTAX,
    939                                N_("integer register index expected"));
    940                 return NULL;
    941             }
    942             regindex = yasm_intnum_get_uint(INTNUM_val);
    943             get_next_token(); /* INTNUM */
    944             if (!expect(')')) {
    945                 yasm_error_set(YASM_ERROR_SYNTAX,
    946                     N_("missing closing parenthesis for register index"));
    947                 return NULL;
    948             }
    949             get_next_token(); /* ')' */
    950             reg = yasm_arch_reggroup_get_reg(p_object->arch, reg, regindex);
    951             if (reg == 0) {
    952                 yasm_error_set(YASM_ERROR_SYNTAX, N_("bad register index `%u'"),
    953                                regindex);
    954                 return NULL;
    955             }
    956             return yasm_operand_create_reg(reg);
    957         }
    958         case STRICT:
    959             get_next_token();
    960             op = parse_operand(parser_nasm);
    961             if (op)
    962                 op->strict = 1;
    963             return op;
    964         case SIZE_OVERRIDE:
    965         {
    966             unsigned int size = SIZE_OVERRIDE_val;
    967             get_next_token();
    968             if (parser_nasm->masm && curtok == ID && !yasm__strcasecmp(ID_val, "ptr")) {
    969                 get_next_token();
    970             }
    971             op = parse_operand(parser_nasm);
    972             if (!op)
    973                 return NULL;
    974             if (op->type == YASM_INSN__OPERAND_REG &&
    975                 yasm_arch_get_reg_size(p_object->arch, op->data.reg) != size)
    976                 yasm_error_set(YASM_ERROR_TYPE,
    977                                N_("cannot override register size"));
    978             else {
    979                 /* Silently override others unless a warning is turned on.
    980                  * This is to allow overrides such as:
    981                  *   %define arg1 dword [bp+4]
    982                  *   cmp word arg1, 2
    983                  * Which expands to:
    984                  *   cmp word dword [bp+4], 2
    985                  */
    986                 if (op->size != 0) {
    987                     if (op->size != size)
    988                         yasm_warn_set(YASM_WARN_SIZE_OVERRIDE,
    989                             N_("overriding operand size from %u-bit to %u-bit"),
    990                             op->size, size);
    991                     else
    992                         yasm_warn_set(YASM_WARN_SIZE_OVERRIDE,
    993                                       N_("double operand size override"));
    994                 }
    995                 op->size = size;
    996             }
    997             return op;
    998         }
    999         case TARGETMOD:
   1000         {
   1001             uintptr_t tmod = TARGETMOD_val;
   1002             get_next_token();
   1003             op = parse_operand(parser_nasm);
   1004             if (op)
   1005                 op->targetmod = tmod;
   1006             return op;
   1007         }
   1008         case ID:
   1009         case LOCAL_ID:
   1010         case NONLOCAL_ID:
   1011             if (parser_nasm->tasm) {
   1012                 get_peek_token(parser_nasm);
   1013                 if (parser_nasm->peek_token == '[') {
   1014                     yasm_symrec *sym = yasm_symtab_use(p_symtab, ID_val,
   1015                                                        cur_line);
   1016                     yasm_expr *e = p_expr_new_ident(yasm_expr_sym(sym)), *f;
   1017                     yasm_effaddr *ea;
   1018                     yasm_xfree(ID_val);
   1019                     get_next_token();
   1020                     get_next_token();
   1021                     f = parse_bexpr(parser_nasm, NORM_EXPR);
   1022                     if (!f) {
   1023                         yasm_error_set(YASM_ERROR_SYNTAX,
   1024                                        N_("expected expression after ["));
   1025                         return NULL;
   1026                     }
   1027                     e = p_expr_new_tree(e, YASM_EXPR_ADD, f);
   1028                     if (!expect(']')) {
   1029                         yasm_error_set(YASM_ERROR_SYNTAX, N_("missing closing bracket"));
   1030                         return NULL;
   1031                     }
   1032                     get_next_token();
   1033                     ea = yasm_arch_ea_create(p_object->arch, e);
   1034                     yasm_ea_set_implicit_size_segment(parser_nasm, ea, e);
   1035                     op = yasm_operand_create_mem(ea);
   1036                     return op;
   1037                 }
   1038             }
   1039             /* Fallthrough */
   1040         default:
   1041         {
   1042             yasm_expr *e = parse_bexpr(parser_nasm, NORM_EXPR);
   1043             if (!e)
   1044                 return NULL;
   1045             if (curtok != ':') {
   1046                 if (parser_nasm->tasm && yasm_expr_size(e)) {
   1047                     yasm_effaddr *ea = yasm_arch_ea_create(p_object->arch, e);
   1048                     yasm_ea_set_implicit_size_segment(parser_nasm, ea, e);
   1049                     op = yasm_operand_create_mem(ea);
   1050                     return op;
   1051                 } else if (curtok == '[') {
   1052                     yasm_expr *f;
   1053                     yasm_effaddr *ea;
   1054                     yasm_insn_operand *op2;
   1055 
   1056                     op = parse_operand(parser_nasm);
   1057                     if (!op)
   1058                         return NULL;
   1059 
   1060                     f = op->data.ea->disp.abs;
   1061                     e = p_expr_new_tree(e, YASM_EXPR_ADD, f);
   1062                     ea = yasm_arch_ea_create(p_object->arch, e);
   1063                     yasm_ea_set_implicit_size_segment(parser_nasm, ea, e);
   1064                     op2 = yasm_operand_create_mem(ea);
   1065 
   1066                     yasm_xfree(op);
   1067 
   1068                     return op2;
   1069                 } else {
   1070                     return yasm_operand_create_imm(e);
   1071                 }
   1072             } else {
   1073                 yasm_expr *off;
   1074                 get_next_token();
   1075                 off = parse_bexpr(parser_nasm, NORM_EXPR);
   1076                 if (!off) {
   1077                     yasm_expr_destroy(e);
   1078                     return NULL;
   1079                 }
   1080                 op = yasm_operand_create_imm(off);
   1081                 op->seg = e;
   1082                 return op;
   1083             }
   1084         }
   1085     }
   1086 }
   1087 
   1088 /* memory addresses */
   1089 static yasm_insn_operand *
   1090 parse_memaddr(yasm_parser_nasm *parser_nasm)
   1091 {
   1092     yasm_insn_operand *op;
   1093     switch (curtok) {
   1094         case SEGREG:
   1095         {
   1096             uintptr_t segreg = SEGREG_val;
   1097             get_next_token();
   1098             if (!expect(':')) {
   1099                 yasm_error_set(YASM_ERROR_SYNTAX,
   1100                                N_("`:' required after segment register"));
   1101                 return NULL;
   1102             }
   1103             get_next_token();
   1104             op = parse_memaddr(parser_nasm);
   1105             if (op)
   1106                 yasm_ea_set_segreg(op->data.ea, segreg);
   1107             return op;
   1108         }
   1109         case SIZE_OVERRIDE:
   1110         {
   1111             unsigned int size = SIZE_OVERRIDE_val;
   1112             get_next_token();
   1113             op = parse_memaddr(parser_nasm);
   1114             if (op)
   1115                 op->data.ea->disp.size = size;
   1116             return op;
   1117         }
   1118         case NOSPLIT:
   1119             get_next_token();
   1120             op = parse_memaddr(parser_nasm);
   1121             if (op)
   1122                 op->data.ea->nosplit = 1;
   1123             return op;
   1124         case REL:
   1125             get_next_token();
   1126             op = parse_memaddr(parser_nasm);
   1127             if (op) {
   1128                 op->data.ea->pc_rel = 1;
   1129                 op->data.ea->not_pc_rel = 0;
   1130             }
   1131             return op;
   1132         case ABS:
   1133             get_next_token();
   1134             op = parse_memaddr(parser_nasm);
   1135             if (op) {
   1136                 op->data.ea->pc_rel = 0;
   1137                 op->data.ea->not_pc_rel = 1;
   1138             }
   1139             return op;
   1140         default:
   1141         {
   1142             yasm_expr *e = parse_bexpr(parser_nasm, NORM_EXPR);
   1143             if (!e)
   1144                 return NULL;
   1145             if (curtok != ':') {
   1146                 yasm_effaddr *ea = yasm_arch_ea_create(p_object->arch, e);
   1147                 yasm_ea_set_implicit_size_segment(parser_nasm, ea, e);
   1148                 return yasm_operand_create_mem(ea);
   1149             } else {
   1150                 yasm_effaddr *ea;
   1151                 yasm_expr *off;
   1152                 get_next_token();
   1153                 off = parse_bexpr(parser_nasm, NORM_EXPR);
   1154                 if (!off) {
   1155                     yasm_expr_destroy(e);
   1156                     return NULL;
   1157                 }
   1158                 ea = yasm_arch_ea_create(p_object->arch, off);
   1159                 yasm_ea_set_implicit_size_segment(parser_nasm, ea, off);
   1160                 op = yasm_operand_create_mem(ea);
   1161                 op->seg = e;
   1162                 return op;
   1163             }
   1164         }
   1165     }
   1166 }
   1167 
   1168 /* Expression grammar parsed is:
   1169  *
   1170  * expr  : bexpr [ : bexpr ]
   1171  * bexpr : expr0 [ WRT expr6 ]
   1172  * expr0 : expr1 [ {|} expr1...]
   1173  * expr1 : expr2 [ {^} expr2...]
   1174  * expr2 : expr3 [ {&} expr3...]
   1175  * expr3 : expr4 [ {<<,>>} expr4...]
   1176  * expr4 : expr5 [ {+,-} expr5...]
   1177  * expr5 : expr6 [ {*,/,%,//,%%} expr6...]
   1178  * expr6 : { ~,+,-,SEG } expr6
   1179  *       | (expr)
   1180  *       | symbol
   1181  *       | $
   1182  *       | number
   1183  */
   1184 
   1185 #define parse_expr_common(leftfunc, tok, rightfunc, op) \
   1186     do {                                                \
   1187         yasm_expr *e, *f;                               \
   1188         e = leftfunc(parser_nasm, type);                \
   1189         if (!e)                                         \
   1190             return NULL;                                \
   1191                                                         \
   1192         while (curtok == tok) {                         \
   1193             get_next_token();                           \
   1194             f = rightfunc(parser_nasm, type);           \
   1195             if (!f) {                                   \
   1196                 yasm_error_set(YASM_ERROR_SYNTAX,       \
   1197                                N_("expected expression after %s"), \
   1198                                describe_token(op));     \
   1199                 yasm_expr_destroy(e);                   \
   1200                 return NULL;                            \
   1201             }                                           \
   1202             e = p_expr_new_tree(e, op, f);              \
   1203         }                                               \
   1204         return e;                                       \
   1205     } while(0)
   1206 
   1207 static yasm_expr *
   1208 parse_expr(yasm_parser_nasm *parser_nasm, expr_type type)
   1209 {
   1210     switch (type) {
   1211         case DIR_EXPR:
   1212             /* directive expressions can't handle seg:off or WRT */
   1213             return parse_expr0(parser_nasm, type);
   1214         default:
   1215             parse_expr_common(parse_bexpr, ':', parse_bexpr, YASM_EXPR_SEGOFF);
   1216     }
   1217     /*@notreached@*/
   1218     return NULL;
   1219 }
   1220 
   1221 static yasm_expr *
   1222 parse_bexpr(yasm_parser_nasm *parser_nasm, expr_type type)
   1223 {
   1224     parse_expr_common(parse_expr0, WRT, parse_expr6, YASM_EXPR_WRT);
   1225 }
   1226 
   1227 static yasm_expr *
   1228 parse_expr0(yasm_parser_nasm *parser_nasm, expr_type type)
   1229 {
   1230     parse_expr_common(parse_expr1, '|', parse_expr1, YASM_EXPR_OR);
   1231 }
   1232 
   1233 static yasm_expr *
   1234 parse_expr1(yasm_parser_nasm *parser_nasm, expr_type type)
   1235 {
   1236     parse_expr_common(parse_expr2, '^', parse_expr2, YASM_EXPR_XOR);
   1237 }
   1238 
   1239 static yasm_expr *
   1240 parse_expr2(yasm_parser_nasm *parser_nasm, expr_type type)
   1241 {
   1242     parse_expr_common(parse_expr3, '&', parse_expr3, YASM_EXPR_AND);
   1243 }
   1244 
   1245 static yasm_expr *
   1246 parse_expr3(yasm_parser_nasm *parser_nasm, expr_type type)
   1247 {
   1248     yasm_expr *e, *f;
   1249     e = parse_expr4(parser_nasm, type);
   1250     if (!e)
   1251         return NULL;
   1252 
   1253     while (curtok == LEFT_OP || curtok == RIGHT_OP) {
   1254         int op = curtok;
   1255         get_next_token();
   1256         f = parse_expr4(parser_nasm, type);
   1257         if (!f) {
   1258             yasm_error_set(YASM_ERROR_SYNTAX,
   1259                            N_("expected expression after %s"),
   1260                            describe_token(op));
   1261             yasm_expr_destroy(e);
   1262             return NULL;
   1263         }
   1264 
   1265         switch (op) {
   1266             case LEFT_OP: e = p_expr_new_tree(e, YASM_EXPR_SHL, f); break;
   1267             case RIGHT_OP: e = p_expr_new_tree(e, YASM_EXPR_SHR, f); break;
   1268         }
   1269     }
   1270     return e;
   1271 }
   1272 
   1273 static yasm_expr *
   1274 parse_expr4(yasm_parser_nasm *parser_nasm, expr_type type)
   1275 {
   1276     yasm_expr *e, *f;
   1277     e = parse_expr5(parser_nasm, type);
   1278     if (!e)
   1279         return NULL;
   1280 
   1281     while (curtok == '+' || curtok == '-') {
   1282         int op = curtok;
   1283         get_next_token();
   1284         f = parse_expr5(parser_nasm, type);
   1285         if (!f) {
   1286             yasm_error_set(YASM_ERROR_SYNTAX,
   1287                            N_("expected expression after %s"),
   1288                            describe_token(op));
   1289             yasm_expr_destroy(e);
   1290             return NULL;
   1291         }
   1292 
   1293         switch (op) {
   1294             case '+': e = p_expr_new_tree(e, YASM_EXPR_ADD, f); break;
   1295             case '-': e = p_expr_new_tree(e, YASM_EXPR_SUB, f); break;
   1296         }
   1297     }
   1298     return e;
   1299 }
   1300 
   1301 static yasm_expr *
   1302 parse_expr5(yasm_parser_nasm *parser_nasm, expr_type type)
   1303 {
   1304     yasm_expr *e, *f;
   1305     e = parse_expr6(parser_nasm, type);
   1306     if (!e)
   1307         return NULL;
   1308 
   1309     while (curtok == '*' || curtok == '/' || curtok == '%'
   1310            || curtok == SIGNDIV || curtok == SIGNMOD) {
   1311         int op = curtok;
   1312         get_next_token();
   1313         f = parse_expr6(parser_nasm, type);
   1314         if (!f) {
   1315             yasm_error_set(YASM_ERROR_SYNTAX,
   1316                            N_("expected expression after %s"),
   1317                            describe_token(op));
   1318             yasm_expr_destroy(e);
   1319             return NULL;
   1320         }
   1321 
   1322         switch (op) {
   1323             case '*': e = p_expr_new_tree(e, YASM_EXPR_MUL, f); break;
   1324             case '/': e = p_expr_new_tree(e, YASM_EXPR_DIV, f); break;
   1325             case '%': e = p_expr_new_tree(e, YASM_EXPR_MOD, f); break;
   1326             case SIGNDIV: e = p_expr_new_tree(e, YASM_EXPR_SIGNDIV, f); break;
   1327             case SIGNMOD: e = p_expr_new_tree(e, YASM_EXPR_SIGNMOD, f); break;
   1328         }
   1329     }
   1330     return e;
   1331 }
   1332 
   1333 static yasm_expr *
   1334 parse_expr6(yasm_parser_nasm *parser_nasm, expr_type type)
   1335 {
   1336     yasm_expr *e;
   1337     yasm_symrec *sym;
   1338 
   1339     switch (curtok) {
   1340         case '+':
   1341             get_next_token();
   1342             e = parse_expr6(parser_nasm, type);
   1343             if (!e) {
   1344                 yasm_error_set(YASM_ERROR_SYNTAX,
   1345                                N_("expected expression after %s"), "`+'");
   1346             }
   1347             return e;
   1348         case '-':
   1349             get_next_token();
   1350             e = parse_expr6(parser_nasm, type);
   1351             if (!e) {
   1352                 yasm_error_set(YASM_ERROR_SYNTAX,
   1353                                N_("expected expression after %s"), "`-'");
   1354                 return NULL;
   1355             }
   1356             return p_expr_new_branch(YASM_EXPR_NEG, e);
   1357         case '~':
   1358             get_next_token();
   1359             e = parse_expr6(parser_nasm, type);
   1360             if (!e) {
   1361                 yasm_error_set(YASM_ERROR_SYNTAX,
   1362                                N_("expected expression after %s"), "`~'");
   1363                 return NULL;
   1364             }
   1365             return p_expr_new_branch(YASM_EXPR_NOT, e);
   1366         case LOW:
   1367             get_next_token();
   1368             e = parse_expr6(parser_nasm, type);
   1369             if (!e) {
   1370                 yasm_error_set(YASM_ERROR_SYNTAX,
   1371                                N_("expected expression after %s"), "LOW");
   1372                 return NULL;
   1373             }
   1374             return p_expr_new_tree(e, YASM_EXPR_AND,
   1375                 p_expr_new_ident(yasm_expr_int(yasm_intnum_create_uint(0xff))));
   1376         case HIGH:
   1377             get_next_token();
   1378             e = parse_expr6(parser_nasm, type);
   1379             if (!e) {
   1380                 yasm_error_set(YASM_ERROR_SYNTAX,
   1381                                N_("expected expression after %s"), "HIGH");
   1382                 return NULL;
   1383             }
   1384             return p_expr_new_tree(
   1385                 p_expr_new_tree(e, YASM_EXPR_SHR,
   1386                     p_expr_new_ident(yasm_expr_int(
   1387                         yasm_intnum_create_uint(8)))),
   1388                 YASM_EXPR_AND,
   1389                 p_expr_new_ident(yasm_expr_int(yasm_intnum_create_uint(0xff))));
   1390         case SEG:
   1391             get_next_token();
   1392             e = parse_expr6(parser_nasm, type);
   1393             if (!e) {
   1394                 yasm_error_set(YASM_ERROR_SYNTAX,
   1395                                N_("expected expression after %s"), "SEG");
   1396                 return NULL;
   1397             }
   1398             return p_expr_new_branch(YASM_EXPR_SEG, e);
   1399         case '(':
   1400             get_next_token();
   1401             e = parse_expr(parser_nasm, type);
   1402             if (!e) {
   1403                 yasm_error_set(YASM_ERROR_SYNTAX,
   1404                                N_("expected expression after %s"), "`('");
   1405                 return NULL;
   1406             }
   1407             if (!expect(')')) {
   1408                 yasm_error_set(YASM_ERROR_SYNTAX, N_("missing parenthesis"));
   1409                 return NULL;
   1410             }
   1411             get_next_token();
   1412             return e;
   1413         case INTNUM:
   1414             e = p_expr_new_ident(yasm_expr_int(INTNUM_val));
   1415             get_next_token();
   1416             return e;
   1417         case REG:
   1418             if (type == DV_EXPR) {
   1419                 yasm_error_set(YASM_ERROR_SYNTAX,
   1420                                N_("data values can't have registers"));
   1421                 return NULL;
   1422             }
   1423             e = p_expr_new_ident(yasm_expr_reg(REG_val));
   1424             get_next_token();
   1425             return e;
   1426     }
   1427 
   1428     /* directives allow very little and handle IDs specially */
   1429     if (type == DIR_EXPR) {
   1430         switch (curtok) {
   1431         case ID:
   1432             sym = yasm_symtab_use(p_symtab, ID_val, cur_line);
   1433             e = p_expr_new_ident(yasm_expr_sym(sym));
   1434             yasm_xfree(ID_val);
   1435             break;
   1436         default:
   1437             return NULL;
   1438         }
   1439     } else switch (curtok) {
   1440         case FLTNUM:
   1441             e = p_expr_new_ident(yasm_expr_float(FLTNUM_val));
   1442             break;
   1443         case STRING:
   1444         {
   1445             yasm_intnum *intn;
   1446             if (parser_nasm->tasm)
   1447                 intn = yasm_intnum_create_charconst_tasm(STRING_val.contents);
   1448             else
   1449                 intn = yasm_intnum_create_charconst_nasm(STRING_val.contents);
   1450             e = p_expr_new_ident(yasm_expr_int(intn));
   1451             yasm_xfree(STRING_val.contents);
   1452             break;
   1453         }
   1454         case SPECIAL_ID:
   1455             sym = yasm_objfmt_get_special_sym(p_object, ID_val+2, "nasm");
   1456             if (sym) {
   1457                 e = p_expr_new_ident(yasm_expr_sym(sym));
   1458                 yasm_xfree(ID_val);
   1459                 break;
   1460             }
   1461             /*@fallthrough@*/
   1462         case ID:
   1463         case LOCAL_ID:
   1464         case NONLOCAL_ID:
   1465             sym = yasm_symtab_use(p_symtab, ID_val, cur_line);
   1466             e = p_expr_new_ident(yasm_expr_sym(sym));
   1467             yasm_xfree(ID_val);
   1468             break;
   1469         case '$':
   1470             /* "$" references the current assembly position */
   1471             if (parser_nasm->abspos)
   1472                 e = yasm_expr_copy(parser_nasm->abspos);
   1473             else {
   1474                 sym = yasm_symtab_define_curpos(p_symtab, "$",
   1475                     parser_nasm->prev_bc, cur_line);
   1476                 e = p_expr_new_ident(yasm_expr_sym(sym));
   1477             }
   1478             break;
   1479         case START_SECTION_ID:
   1480             /* "$$" references the start of the current section */
   1481             if (parser_nasm->absstart)
   1482                 e = yasm_expr_copy(parser_nasm->absstart);
   1483             else {
   1484                 sym = yasm_symtab_define_label(p_symtab, "$$",
   1485                     yasm_section_bcs_first(cursect), 0, cur_line);
   1486                 e = p_expr_new_ident(yasm_expr_sym(sym));
   1487             }
   1488             break;
   1489         default:
   1490             return NULL;
   1491     }
   1492 
   1493     get_next_token();
   1494     return e;
   1495 }
   1496 
   1497 static void
   1498 set_nonlocal_label(yasm_parser_nasm *parser_nasm, const char *name)
   1499 {
   1500     if (!parser_nasm->tasm || tasm_locals) {
   1501         if (parser_nasm->locallabel_base)
   1502             yasm_xfree(parser_nasm->locallabel_base);
   1503         parser_nasm->locallabel_base_len = strlen(name);
   1504         parser_nasm->locallabel_base =
   1505             yasm_xmalloc(parser_nasm->locallabel_base_len+1);
   1506         strcpy(parser_nasm->locallabel_base, name);
   1507     }
   1508 }
   1509 
   1510 static void
   1511 define_label(yasm_parser_nasm *parser_nasm, char *name, unsigned int size)
   1512 {
   1513     yasm_symrec *symrec;
   1514 
   1515     if (parser_nasm->abspos)
   1516         symrec = yasm_symtab_define_equ(p_symtab, name,
   1517                                         yasm_expr_copy(parser_nasm->abspos),
   1518                                         cur_line);
   1519     else
   1520         symrec = yasm_symtab_define_label(p_symtab, name, parser_nasm->prev_bc,
   1521                                           1, cur_line);
   1522 
   1523     yasm_symrec_set_size(symrec, size);
   1524     yasm_symrec_set_segment(symrec, tasm_segment);
   1525 
   1526     yasm_xfree(name);
   1527 }
   1528 
   1529 static void
   1530 dir_align(yasm_object *object, yasm_valparamhead *valparams,
   1531           yasm_valparamhead *objext_valparams, unsigned long line)
   1532 {
   1533     yasm_valparam *vp = yasm_vps_first(valparams);
   1534     yasm_expr *boundval = yasm_vp_expr(vp, object->symtab, line);
   1535     /*@depedent@*/ yasm_intnum *boundintn;
   1536 
   1537     /* Largest .align in the section specifies section alignment.
   1538      * Note: this doesn't match NASM behavior, but is a lot more
   1539      * intelligent!
   1540      */
   1541     if (boundval && (boundintn = yasm_expr_get_intnum(&boundval, 0))) {
   1542         unsigned long boundint = yasm_intnum_get_uint(boundintn);
   1543 
   1544         /* Alignments must be a power of two. */
   1545         if (is_exp2(boundint)) {
   1546             if (boundint > yasm_section_get_align(object->cur_section))
   1547                 yasm_section_set_align(object->cur_section, boundint, line);
   1548         }
   1549     }
   1550 
   1551     /* As this directive is called only when nop is used as fill, always
   1552      * use arch (nop) fill.
   1553      */
   1554     yasm_section_bcs_append(object->cur_section,
   1555         yasm_bc_create_align(boundval, NULL, NULL,
   1556             /*yasm_section_is_code(object->cur_section) ?*/
   1557             yasm_arch_get_fill(object->arch)/* : NULL*/,
   1558             line));
   1559 }
   1560 
   1561 static void
   1562 nasm_parser_directive(yasm_parser_nasm *parser_nasm, const char *name,
   1563                       yasm_valparamhead *valparams,
   1564                       yasm_valparamhead *objext_valparams)
   1565 {
   1566     unsigned long line = cur_line;
   1567     yasm_valparam *vp;
   1568 
   1569     if (!yasm_object_directive(p_object, name, "nasm", valparams,
   1570                                objext_valparams, line))
   1571         ;
   1572     else if (yasm__strcasecmp(name, "absolute") == 0) {
   1573         if (!valparams) {
   1574             yasm_error_set(YASM_ERROR_SYNTAX,
   1575                            N_("directive `%s' requires an argument"),
   1576                            "absolute");
   1577         } else {
   1578             vp = yasm_vps_first(valparams);
   1579             if (parser_nasm->absstart)
   1580                 yasm_expr_destroy(parser_nasm->absstart);
   1581             if (parser_nasm->abspos)
   1582                 yasm_expr_destroy(parser_nasm->abspos);
   1583             parser_nasm->absstart = yasm_vp_expr(vp, p_object->symtab, line);
   1584             parser_nasm->abspos = yasm_expr_copy(parser_nasm->absstart);
   1585             cursect = NULL;
   1586             parser_nasm->prev_bc = NULL;
   1587         }
   1588     } else if (yasm__strcasecmp(name, "align") == 0) {
   1589         /* Really, we shouldn't end up with an align directive in an absolute
   1590          * section (as it's supposed to be only used for nop fill), but handle
   1591          * it gracefully anyway.
   1592          */
   1593         if (parser_nasm->abspos) {
   1594             yasm_expr *boundval, *e;
   1595             vp = yasm_vps_first(valparams);
   1596             boundval = yasm_vp_expr(vp, p_object->symtab, line);
   1597             e = yasm_expr_create_tree(
   1598                 yasm_expr_create_tree(yasm_expr_copy(parser_nasm->absstart),
   1599                                       YASM_EXPR_SUB,
   1600                                       yasm_expr_copy(parser_nasm->abspos),
   1601                                       cur_line),
   1602                 YASM_EXPR_AND,
   1603                 yasm_expr_create(YASM_EXPR_SUB, yasm_expr_expr(boundval),
   1604                                  yasm_expr_int(yasm_intnum_create_uint(1)),
   1605                                  cur_line),
   1606                 cur_line);
   1607             parser_nasm->abspos = yasm_expr_create_tree(
   1608                 parser_nasm->abspos, YASM_EXPR_ADD, e, cur_line);
   1609         } else if (!valparams) {
   1610             yasm_error_set(YASM_ERROR_SYNTAX,
   1611                            N_("directive `%s' requires an argument"), "align");
   1612         } else
   1613             dir_align(p_object, valparams, objext_valparams, line);
   1614     } else if (yasm__strcasecmp(name, "default") == 0) {
   1615         if (!valparams)
   1616             ;
   1617         else {
   1618             vp = yasm_vps_first(valparams);
   1619             while (vp) {
   1620                 const char *id = yasm_vp_id(vp);
   1621                 if (id) {
   1622                     if (yasm__strcasecmp(id, "rel") == 0)
   1623                         yasm_arch_set_var(p_object->arch, "default_rel", 1);
   1624                     else if (yasm__strcasecmp(id, "abs") == 0)
   1625                         yasm_arch_set_var(p_object->arch, "default_rel", 0);
   1626                     else
   1627                         yasm_error_set(YASM_ERROR_SYNTAX,
   1628                                        N_("unrecognized default `%s'"), id);
   1629                 } else
   1630                     yasm_error_set(YASM_ERROR_SYNTAX,
   1631                                    N_("unrecognized default value"));
   1632                 vp = yasm_vps_next(vp);
   1633             }
   1634         }
   1635     } else
   1636         yasm_error_set(YASM_ERROR_SYNTAX, N_("unrecognized directive `%s'"),
   1637                        name);
   1638 
   1639     if (parser_nasm->absstart && cursect) {
   1640         /* We switched to a new section.  Get out of absolute section mode. */
   1641         yasm_expr_destroy(parser_nasm->absstart);
   1642         parser_nasm->absstart = NULL;
   1643         if (parser_nasm->abspos) {
   1644             yasm_expr_destroy(parser_nasm->abspos);
   1645             parser_nasm->abspos = NULL;
   1646         }
   1647     }
   1648 
   1649     if (cursect) {
   1650         /* In case cursect changed or a bytecode was added, update prev_bc. */
   1651         parser_nasm->prev_bc = yasm_section_bcs_last(cursect);
   1652     }
   1653 
   1654     if (valparams)
   1655         yasm_vps_delete(valparams);
   1656     if (objext_valparams)
   1657         yasm_vps_delete(objext_valparams);
   1658 }
   1659 
   1660 yasm_bytecode *
   1661 gas_intel_syntax_parse_instr(yasm_parser_nasm *parser_nasm, unsigned char *instr)
   1662 {
   1663     yasm_bytecode *bc = NULL;
   1664     char *sinstr = (char *) instr;
   1665 
   1666     parser_nasm->s.bot = instr;
   1667     parser_nasm->s.tok = instr;
   1668     parser_nasm->s.ptr = instr;
   1669     parser_nasm->s.cur = instr;
   1670     parser_nasm->s.lim = instr + strlen(sinstr) + 1;
   1671     parser_nasm->s.top = parser_nasm->s.lim;
   1672     parser_nasm->peek_token = NONE;
   1673 
   1674     get_next_token();
   1675     if (!is_eol()) {
   1676         bc = parse_instr(parser_nasm);
   1677     }
   1678 
   1679     return bc;
   1680 }
   1681