• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
yasm_ea_set_implicit_size_segment(yasm_parser_nasm * parser_nasm,yasm_effaddr * ea,yasm_expr * e)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
get_peek_token(yasm_parser_nasm * parser_nasm)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
destroy_curtok_(yasm_parser_nasm * parser_nasm)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
demand_eol_(yasm_parser_nasm * parser_nasm)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 *
describe_token(int token)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
expect_(yasm_parser_nasm * parser_nasm,int token)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
nasm_parser_parse(yasm_parser_nasm * parser_nasm)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 *
parse_line(yasm_parser_nasm * parser_nasm)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
parse_directive_valparams(yasm_parser_nasm * parser_nasm,yasm_valparamhead * vps)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 *
parse_times(yasm_parser_nasm * parser_nasm)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 *
parse_exp(yasm_parser_nasm * parser_nasm)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 *
parse_instr(yasm_parser_nasm * parser_nasm)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 *
parse_operand(yasm_parser_nasm * parser_nasm)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 *
parse_memaddr(yasm_parser_nasm * parser_nasm)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 *
parse_expr(yasm_parser_nasm * parser_nasm,expr_type type)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 *
parse_bexpr(yasm_parser_nasm * parser_nasm,expr_type type)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 *
parse_expr0(yasm_parser_nasm * parser_nasm,expr_type type)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 *
parse_expr1(yasm_parser_nasm * parser_nasm,expr_type type)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 *
parse_expr2(yasm_parser_nasm * parser_nasm,expr_type type)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 *
parse_expr3(yasm_parser_nasm * parser_nasm,expr_type type)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 *
parse_expr4(yasm_parser_nasm * parser_nasm,expr_type type)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 *
parse_expr5(yasm_parser_nasm * parser_nasm,expr_type type)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 *
parse_expr6(yasm_parser_nasm * parser_nasm,expr_type type)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
set_nonlocal_label(yasm_parser_nasm * parser_nasm,const char * name)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
define_label(yasm_parser_nasm * parser_nasm,char * name,unsigned int size)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
dir_align(yasm_object * object,yasm_valparamhead * valparams,yasm_valparamhead * objext_valparams,unsigned long line)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
nasm_parser_directive(yasm_parser_nasm * parser_nasm,const char * name,yasm_valparamhead * valparams,yasm_valparamhead * objext_valparams)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 *
gas_intel_syntax_parse_instr(yasm_parser_nasm * parser_nasm,unsigned char * instr)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