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