OLD | NEW |
1 /* | 1 /* |
2 * GAS-compatible parser | 2 * GAS-compatible parser |
3 * | 3 * |
4 * Copyright (C) 2005-2007 Peter Johnson | 4 * Copyright (C) 2005-2007 Peter Johnson |
5 * | 5 * |
6 * Redistribution and use in source and binary forms, with or without | 6 * Redistribution and use in source and binary forms, with or without |
7 * modification, are permitted provided that the following conditions | 7 * modification, are permitted provided that the following conditions |
8 * are met: | 8 * are met: |
9 * 1. Redistributions of source code must retain the above copyright | 9 * 1. Redistributions of source code must retain the above copyright |
10 * notice, this list of conditions and the following disclaimer. | 10 * notice, this list of conditions and the following disclaimer. |
(...skipping 10 matching lines...) Expand all Loading... |
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE | 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE |
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
28 * POSSIBILITY OF SUCH DAMAGE. | 28 * POSSIBILITY OF SUCH DAMAGE. |
29 */ | 29 */ |
30 #include <util.h> | 30 #include <util.h> |
31 RCSID("$Id: gas-parse.c 2169 2009-01-02 20:46:57Z peter $"); | 31 RCSID("$Id: gas-parse.c 2279 2010-01-19 07:57:43Z peter $"); |
32 | 32 |
33 #include <libyasm.h> | 33 #include <libyasm.h> |
34 | 34 |
35 #include <ctype.h> | 35 #include <ctype.h> |
36 #include <limits.h> | 36 #include <limits.h> |
37 #include <math.h> | 37 #include <math.h> |
38 | 38 |
39 #include "modules/parsers/gas/gas-parser.h" | 39 #include "modules/parsers/gas/gas-parser.h" |
40 | 40 |
41 typedef struct dir_lookup { | 41 typedef struct dir_lookup { |
(...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
314 while (curtok != '\n') | 314 while (curtok != '\n') |
315 get_next_token(); | 315 get_next_token(); |
316 | 316 |
317 return; | 317 return; |
318 } | 318 } |
319 | 319 |
320 filename = STRING_val.contents; | 320 filename = STRING_val.contents; |
321 get_next_token(); | 321 get_next_token(); |
322 | 322 |
323 /* Set linemap. */ | 323 /* Set linemap. */ |
324 yasm_linemap_set(parser_gas->linemap, filename, line, 1); | 324 yasm_linemap_set(parser_gas->linemap, filename, 0, line, 1); |
325 | 325 |
326 /* | 326 /* |
327 The first line marker in the file (which should be on the first line | 327 The first line marker in the file (which should be on the first line |
328 of the file) will give us the name of the source file. This information | 328 of the file) will give us the name of the source file. This information |
329 needs to be passed on to the debug format module. | 329 needs to be passed on to the debug format module. |
330 */ | 330 */ |
331 if (parser_gas->seen_line_marker == 0) { | 331 if (parser_gas->seen_line_marker == 0) { |
332 parser_gas->seen_line_marker = 1; | 332 parser_gas->seen_line_marker = 1; |
333 | 333 |
334 yasm_vps_initialize(&vps); | 334 yasm_vps_initialize(&vps); |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
422 parser_gas->state = NASM_FILENAME; | 422 parser_gas->state = NASM_FILENAME; |
423 get_next_token(); /* INTNUM */ | 423 get_next_token(); /* INTNUM */ |
424 if (!expect(STRING)) { | 424 if (!expect(STRING)) { |
425 parser_gas->state = INITIAL; | 425 parser_gas->state = INITIAL; |
426 return; | 426 return; |
427 } | 427 } |
428 | 428 |
429 filename = STRING_val.contents; | 429 filename = STRING_val.contents; |
430 | 430 |
431 /* Set linemap. */ | 431 /* Set linemap. */ |
432 yasm_linemap_set(parser_gas->linemap, filename, line, incr); | 432 yasm_linemap_set(parser_gas->linemap, filename, 0, line, incr); |
433 | 433 |
434 /* | 434 /* |
435 The first line marker in the file (which should be on the first line | 435 The first line marker in the file (which should be on the first line |
436 of the file) will give us the name of the source file. This information | 436 of the file) will give us the name of the source file. This information |
437 needs to be passed on to the debug format module. | 437 needs to be passed on to the debug format module. |
438 */ | 438 */ |
439 if (parser_gas->seen_line_marker == 0) { | 439 if (parser_gas->seen_line_marker == 0) { |
440 parser_gas->seen_line_marker = 1; | 440 parser_gas->seen_line_marker = 1; |
441 | 441 |
442 yasm_vps_initialize(&vps); | 442 yasm_vps_initialize(&vps); |
(...skipping 22 matching lines...) Expand all Loading... |
465 N_("line number is negative")); | 465 N_("line number is negative")); |
466 return NULL; | 466 return NULL; |
467 } | 467 } |
468 | 468 |
469 parser_gas->dir_line = yasm_intnum_get_uint(INTNUM_val); | 469 parser_gas->dir_line = yasm_intnum_get_uint(INTNUM_val); |
470 yasm_intnum_destroy(INTNUM_val); | 470 yasm_intnum_destroy(INTNUM_val); |
471 get_next_token(); /* INTNUM */ | 471 get_next_token(); /* INTNUM */ |
472 | 472 |
473 if (parser_gas->dir_fileline == 3) { | 473 if (parser_gas->dir_fileline == 3) { |
474 /* Have both file and line */ | 474 /* Have both file and line */ |
475 yasm_linemap_set(parser_gas->linemap, NULL, | 475 yasm_linemap_set(parser_gas->linemap, NULL, 0, |
476 parser_gas->dir_line, 1); | 476 parser_gas->dir_line, 1); |
477 } else if (parser_gas->dir_fileline == 1) { | 477 } else if (parser_gas->dir_fileline == 1) { |
478 /* Had previous file directive only */ | 478 /* Had previous file directive only */ |
479 parser_gas->dir_fileline = 3; | 479 parser_gas->dir_fileline = 3; |
480 yasm_linemap_set(parser_gas->linemap, parser_gas->dir_file, | 480 yasm_linemap_set(parser_gas->linemap, parser_gas->dir_file, 0, |
481 parser_gas->dir_line, 1); | 481 parser_gas->dir_line, 1); |
482 } else { | 482 } else { |
483 /* Didn't see file yet */ | 483 /* Didn't see file yet */ |
484 parser_gas->dir_fileline = 2; | 484 parser_gas->dir_fileline = 2; |
485 } | 485 } |
486 return NULL; | 486 return NULL; |
487 } | 487 } |
488 | 488 |
489 /* Macro directives */ | |
490 | |
491 static yasm_bytecode * | |
492 dir_rept(yasm_parser_gas *parser_gas, unsigned int param) | |
493 { | |
494 yasm_intnum *intn; | |
495 yasm_expr *e = parse_expr(parser_gas); | |
496 | |
497 if (!e) { | |
498 yasm_error_set(YASM_ERROR_SYNTAX, | |
499 N_("expression expected after `%s'"), | |
500 ".rept"); | |
501 return NULL; | |
502 } | |
503 intn = yasm_expr_get_intnum(&e, 0); | |
504 | |
505 if (!intn) { | |
506 yasm_error_set(YASM_ERROR_NOT_ABSOLUTE, | |
507 N_("rept expression not absolute")); | |
508 } else if (yasm_intnum_sign(intn) < 0) { | |
509 yasm_error_set(YASM_ERROR_VALUE, | |
510 N_("rept expression is negative")); | |
511 } else { | |
512 gas_rept *rept = yasm_xmalloc(sizeof(gas_rept)); | |
513 STAILQ_INIT(&rept->lines); | |
514 rept->startline = cur_line; | |
515 rept->numrept = yasm_intnum_get_uint(intn); | |
516 rept->numdone = 0; | |
517 rept->line = NULL; | |
518 rept->linepos = 0; | |
519 rept->ended = 0; | |
520 rept->oldbuf = NULL; | |
521 rept->oldbuflen = 0; | |
522 rept->oldbufpos = 0; | |
523 parser_gas->rept = rept; | |
524 } | |
525 return NULL; | |
526 } | |
527 | |
528 static yasm_bytecode * | |
529 dir_endr(yasm_parser_gas *parser_gas, unsigned int param) | |
530 { | |
531 /* Shouldn't ever get here unless we didn't get a DIR_REPT first */ | |
532 yasm_error_set(YASM_ERROR_SYNTAX, N_("endr without matching rept")); | |
533 return NULL; | |
534 } | |
535 | |
536 /* Alignment directives */ | 489 /* Alignment directives */ |
537 | 490 |
538 static yasm_bytecode * | 491 static yasm_bytecode * |
539 dir_align(yasm_parser_gas *parser_gas, unsigned int param) | 492 dir_align(yasm_parser_gas *parser_gas, unsigned int param) |
540 { | 493 { |
541 yasm_expr *bound, *fill=NULL, *maxskip=NULL; | 494 yasm_expr *bound, *fill=NULL, *maxskip=NULL; |
542 | 495 |
543 bound = parse_expr(parser_gas); | 496 bound = parse_expr(parser_gas); |
544 if (!bound) { | 497 if (!bound) { |
545 yasm_error_set(YASM_ERROR_SYNTAX, | 498 yasm_error_set(YASM_ERROR_SYNTAX, |
(...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
870 char *filename = STRING_val.contents; | 823 char *filename = STRING_val.contents; |
871 | 824 |
872 get_next_token(); /* STRING */ | 825 get_next_token(); /* STRING */ |
873 if (parser_gas->dir_fileline == 3) { | 826 if (parser_gas->dir_fileline == 3) { |
874 /* Have both file and line */ | 827 /* Have both file and line */ |
875 const char *old_fn; | 828 const char *old_fn; |
876 unsigned long old_line; | 829 unsigned long old_line; |
877 | 830 |
878 yasm_linemap_lookup(parser_gas->linemap, cur_line, &old_fn, | 831 yasm_linemap_lookup(parser_gas->linemap, cur_line, &old_fn, |
879 &old_line); | 832 &old_line); |
880 yasm_linemap_set(parser_gas->linemap, filename, old_line, | 833 yasm_linemap_set(parser_gas->linemap, filename, 0, old_line, |
881 1); | 834 1); |
882 } else if (parser_gas->dir_fileline == 2) { | 835 } else if (parser_gas->dir_fileline == 2) { |
883 /* Had previous line directive only */ | 836 /* Had previous line directive only */ |
884 parser_gas->dir_fileline = 3; | 837 parser_gas->dir_fileline = 3; |
885 yasm_linemap_set(parser_gas->linemap, filename, | 838 yasm_linemap_set(parser_gas->linemap, filename, 0, |
886 parser_gas->dir_line, 1); | 839 parser_gas->dir_line, 1); |
887 } else { | 840 } else { |
888 /* Didn't see line yet, save file */ | 841 /* Didn't see line yet, save file */ |
889 parser_gas->dir_fileline = 1; | 842 parser_gas->dir_fileline = 1; |
890 if (parser_gas->dir_file) | 843 if (parser_gas->dir_file) |
891 yasm_xfree(parser_gas->dir_file); | 844 yasm_xfree(parser_gas->dir_file); |
892 parser_gas->dir_file = yasm__xstrdup(filename); | 845 parser_gas->dir_file = yasm__xstrdup(filename); |
893 } | 846 } |
894 | 847 |
895 /* Pass change along to debug format */ | 848 /* Pass change along to debug format */ |
(...skipping 25 matching lines...) Expand all Loading... |
921 yasm_vps_append(&vps, vp); | 874 yasm_vps_append(&vps, vp); |
922 get_next_token(); /* STRING */ | 875 get_next_token(); /* STRING */ |
923 | 876 |
924 yasm_object_directive(p_object, ".file", "gas", &vps, NULL, | 877 yasm_object_directive(p_object, ".file", "gas", &vps, NULL, |
925 cur_line); | 878 cur_line); |
926 | 879 |
927 yasm_vps_delete(&vps); | 880 yasm_vps_delete(&vps); |
928 return NULL; | 881 return NULL; |
929 } | 882 } |
930 | 883 |
| 884 |
| 885 static yasm_bytecode * |
| 886 dir_intel_syntax(yasm_parser_gas *parser_gas, unsigned int param) |
| 887 { |
| 888 parser_gas->intel_syntax = 1; |
| 889 |
| 890 do { |
| 891 destroy_curtok(); |
| 892 get_next_token(); |
| 893 } while (!is_eol()); |
| 894 return NULL; |
| 895 } |
| 896 |
| 897 static yasm_bytecode * |
| 898 dir_att_syntax(yasm_parser_gas *parser_gas, unsigned int param) |
| 899 { |
| 900 parser_gas->intel_syntax = 0; |
| 901 return NULL; |
| 902 } |
| 903 |
931 static yasm_bytecode * | 904 static yasm_bytecode * |
932 parse_instr(yasm_parser_gas *parser_gas) | 905 parse_instr(yasm_parser_gas *parser_gas) |
933 { | 906 { |
934 yasm_bytecode *bc; | 907 yasm_bytecode *bc; |
935 char *id; | 908 char *id; |
936 size_t id_len; | 909 size_t id_len; |
937 uintptr_t prefix; | 910 uintptr_t prefix; |
938 | 911 |
| 912 if (parser_gas->intel_syntax) { |
| 913 bc = parse_instr_intel(parser_gas); |
| 914 if (bc) { |
| 915 yasm_warn_disable(YASM_WARN_UNREC_CHAR); |
| 916 do { |
| 917 destroy_curtok(); |
| 918 get_next_token(); |
| 919 } while (!is_eol()); |
| 920 yasm_warn_enable(YASM_WARN_UNREC_CHAR); |
| 921 } |
| 922 return bc; |
| 923 } |
| 924 |
939 if (curtok != ID) | 925 if (curtok != ID) |
940 return NULL; | 926 return NULL; |
941 | 927 |
942 id = ID_val; | 928 id = ID_val; |
943 id_len = ID_len; | 929 id_len = ID_len; |
944 | 930 |
945 /* instructions/prefixes must start with a letter */ | 931 /* instructions/prefixes must start with a letter */ |
946 if (!isalpha(id[0])) | 932 if (!isalpha(id[0])) |
947 return NULL; | 933 return NULL; |
948 | 934 |
(...skipping 759 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1708 /* floating point data declaration directives */ | 1694 /* floating point data declaration directives */ |
1709 {".float", dir_data, 4, INITIAL}, | 1695 {".float", dir_data, 4, INITIAL}, |
1710 {".single", dir_data, 4, INITIAL}, | 1696 {".single", dir_data, 4, INITIAL}, |
1711 {".double", dir_data, 8, INITIAL}, | 1697 {".double", dir_data, 8, INITIAL}, |
1712 {".tfloat", dir_data, 10, INITIAL}, | 1698 {".tfloat", dir_data, 10, INITIAL}, |
1713 /* section directives */ | 1699 /* section directives */ |
1714 {".bss", dir_bss_section, 0, INITIAL}, | 1700 {".bss", dir_bss_section, 0, INITIAL}, |
1715 {".data", dir_data_section, 0, INITIAL}, | 1701 {".data", dir_data_section, 0, INITIAL}, |
1716 {".text", dir_text_section, 0, INITIAL}, | 1702 {".text", dir_text_section, 0, INITIAL}, |
1717 {".section", dir_section, 0, SECTION_DIRECTIVE}, | 1703 {".section", dir_section, 0, SECTION_DIRECTIVE}, |
1718 /* macro directives */ | |
1719 {".rept", dir_rept, 0, INITIAL}, | |
1720 {".endr", dir_endr, 0, INITIAL}, | |
1721 /* empty space/fill directives */ | 1704 /* empty space/fill directives */ |
1722 {".skip", dir_skip, 0, INITIAL}, | 1705 {".skip", dir_skip, 0, INITIAL}, |
1723 {".space", dir_skip, 0, INITIAL}, | 1706 {".space", dir_skip, 0, INITIAL}, |
1724 {".fill", dir_fill, 0, INITIAL}, | 1707 {".fill", dir_fill, 0, INITIAL}, |
1725 {".zero", dir_zero, 0, INITIAL}, | 1708 {".zero", dir_zero, 0, INITIAL}, |
| 1709 /* syntax directives */ |
| 1710 {".intel_syntax", dir_intel_syntax, 0, INITIAL}, |
| 1711 {".att_syntax", dir_att_syntax, 0, INITIAL}, |
1726 /* other directives */ | 1712 /* other directives */ |
1727 {".equ", dir_equ, 0, INITIAL}, | 1713 {".equ", dir_equ, 0, INITIAL}, |
1728 {".file", dir_file, 0, INITIAL}, | 1714 {".file", dir_file, 0, INITIAL}, |
1729 {".line", dir_line, 0, INITIAL}, | 1715 {".line", dir_line, 0, INITIAL}, |
1730 {".set", dir_equ, 0, INITIAL} | 1716 {".set", dir_equ, 0, INITIAL} |
1731 }; | 1717 }; |
1732 | 1718 |
1733 static void | 1719 static void |
1734 no_delete(void *data) | 1720 no_delete(void *data) |
1735 { | 1721 { |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1774 if (parser_gas->save_input) | 1760 if (parser_gas->save_input) |
1775 yasm_linemap_add_source(parser_gas->linemap, | 1761 yasm_linemap_add_source(parser_gas->linemap, |
1776 temp_bc, | 1762 temp_bc, |
1777 (char *)parser_gas->save_line[parser_gas->save_last ^ 1]); | 1763 (char *)parser_gas->save_line[parser_gas->save_last ^ 1]); |
1778 yasm_linemap_goto_next(parser_gas->linemap); | 1764 yasm_linemap_goto_next(parser_gas->linemap); |
1779 parser_gas->dir_line++; /* keep track for .line followed by .file */ | 1765 parser_gas->dir_line++; /* keep track for .line followed by .file */ |
1780 } | 1766 } |
1781 | 1767 |
1782 HAMT_destroy(parser_gas->dirs, no_delete); | 1768 HAMT_destroy(parser_gas->dirs, no_delete); |
1783 } | 1769 } |
OLD | NEW |