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
36typedef 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
42static yasm_bytecode *parse_line(yasm_parser_nasm *parser_nasm);
43static int parse_directive_valparams(yasm_parser_nasm *parser_nasm,
44                                     /*@out@*/ yasm_valparamhead *vps);
45static yasm_bytecode *parse_times(yasm_parser_nasm *parser_nasm);
46static yasm_bytecode *parse_exp(yasm_parser_nasm *parser_nasm);
47static yasm_bytecode *parse_instr(yasm_parser_nasm *parser_nasm);
48static yasm_insn_operand *parse_operand(yasm_parser_nasm *parser_nasm);
49static yasm_insn_operand *parse_memaddr(yasm_parser_nasm *parser_nasm);
50static yasm_expr *parse_expr(yasm_parser_nasm *parser_nasm, expr_type type);
51static yasm_expr *parse_bexpr(yasm_parser_nasm *parser_nasm, expr_type type);
52static yasm_expr *parse_expr0(yasm_parser_nasm *parser_nasm, expr_type type);
53static yasm_expr *parse_expr1(yasm_parser_nasm *parser_nasm, expr_type type);
54static yasm_expr *parse_expr2(yasm_parser_nasm *parser_nasm, expr_type type);
55static yasm_expr *parse_expr3(yasm_parser_nasm *parser_nasm, expr_type type);
56static yasm_expr *parse_expr4(yasm_parser_nasm *parser_nasm, expr_type type);
57static yasm_expr *parse_expr5(yasm_parser_nasm *parser_nasm, expr_type type);
58static yasm_expr *parse_expr6(yasm_parser_nasm *parser_nasm, expr_type type);
59
60static void nasm_parser_directive
61    (yasm_parser_nasm *parser_nasm, const char *name,
62     /*@null@*/ yasm_valparamhead *valparams,
63     /*@null@*/ yasm_valparamhead *objext_valparams);
64static void set_nonlocal_label(yasm_parser_nasm *parser_nasm, const char *name);
65static void define_label(yasm_parser_nasm *parser_nasm, /*@only@*/ char *name,
66                         unsigned int size);
67
68static 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
89static void
90get_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
101static void
102destroy_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 */
137static void
138demand_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
154static const char *
155describe_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
202static int
203expect_(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
214void
215nasm_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
284static yasm_bytecode *
285parse_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
470static int
471parse_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        }
529next:
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
538static yasm_bytecode *
539parse_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
561static yasm_bytecode *
562parse_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"));
650error:
651                        yasm_expr_destroy(e);
652                        yasm_dvs_delete(&dvs);
653                        return NULL;
654                    }
655                } else
656                    dv = yasm_dv_create_expr(e);
657dv_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
724incbin_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
733static yasm_bytecode *
734parse_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
801static yasm_insn_operand *
802parse_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 */
1089static yasm_insn_operand *
1090parse_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
1207static yasm_expr *
1208parse_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
1221static yasm_expr *
1222parse_bexpr(yasm_parser_nasm *parser_nasm, expr_type type)
1223{
1224    parse_expr_common(parse_expr0, WRT, parse_expr6, YASM_EXPR_WRT);
1225}
1226
1227static yasm_expr *
1228parse_expr0(yasm_parser_nasm *parser_nasm, expr_type type)
1229{
1230    parse_expr_common(parse_expr1, '|', parse_expr1, YASM_EXPR_OR);
1231}
1232
1233static yasm_expr *
1234parse_expr1(yasm_parser_nasm *parser_nasm, expr_type type)
1235{
1236    parse_expr_common(parse_expr2, '^', parse_expr2, YASM_EXPR_XOR);
1237}
1238
1239static yasm_expr *
1240parse_expr2(yasm_parser_nasm *parser_nasm, expr_type type)
1241{
1242    parse_expr_common(parse_expr3, '&', parse_expr3, YASM_EXPR_AND);
1243}
1244
1245static yasm_expr *
1246parse_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
1273static yasm_expr *
1274parse_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
1301static yasm_expr *
1302parse_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
1333static yasm_expr *
1334parse_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
1497static void
1498set_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
1510static void
1511define_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
1529static void
1530dir_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
1561static void
1562nasm_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
1660yasm_bytecode *
1661gas_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