| ... | ... | @@ -31,6 +31,7 @@ struct Context { |
| 31 | 31 | HashMap<Buf *, bool, buf_hash, buf_eql_buf> struct_type_table; |
| 32 | 32 | HashMap<Buf *, bool, buf_hash, buf_eql_buf> enum_type_table; |
| 33 | 33 | HashMap<Buf *, bool, buf_hash, buf_eql_buf> fn_table; |
| 34 | HashMap<Buf *, bool, buf_hash, buf_eql_buf> macro_table; |
| 34 | 35 | SourceManager *source_manager; |
| 35 | 36 | ZigList<AstNode *> aliases; |
| 36 | 37 | }; |
| ... | ... | @@ -132,12 +133,17 @@ static AstNode *create_param_decl_node(Context *c, const char *name, AstNode *ty |
| 132 | 133 | return node; |
| 133 | 134 | } |
| 134 | 135 | |
| 136 | static AstNode *create_char_lit_node(Context *c, uint8_t value) { |
| 137 | AstNode *node = create_node(c, NodeTypeCharLiteral); |
| 138 | node->data.char_literal.value = value; |
| 139 | return node; |
| 140 | } |
| 141 | |
| 135 | 142 | static AstNode *create_num_lit_unsigned(Context *c, uint64_t x) { |
| 136 | 143 | AstNode *node = create_node(c, NodeTypeNumberLiteral); |
| 137 | 144 | node->data.number_literal.kind = NumLitUInt; |
| 138 | 145 | node->data.number_literal.data.x_uint = x; |
| 139 | 146 | |
| 140 | | normalize_parent_ptrs(node); |
| 141 | 147 | return node; |
| 142 | 148 | } |
| 143 | 149 | |
| ... | ... | @@ -713,6 +719,69 @@ static void render_aliases(Context *c) { |
| 713 | 719 | } |
| 714 | 720 | } |
| 715 | 721 | |
| 722 | static int parse_c_char_lit(Buf *value, uint8_t *out_c) { |
| 723 | enum State { |
| 724 | StateExpectStartQuot, |
| 725 | StateExpectChar, |
| 726 | StateExpectEndQuot, |
| 727 | StateExpectEnd, |
| 728 | }; |
| 729 | State state = StateExpectStartQuot; |
| 730 | for (int i = 0; i < buf_len(value); i += 1) { |
| 731 | uint8_t c = buf_ptr(value)[i]; |
| 732 | switch (state) { |
| 733 | case StateExpectStartQuot: |
| 734 | switch (c) { |
| 735 | case '\'': |
| 736 | state = StateExpectChar; |
| 737 | break; |
| 738 | default: |
| 739 | return -1; |
| 740 | } |
| 741 | break; |
| 742 | case StateExpectChar: |
| 743 | switch (c) { |
| 744 | case '\\': |
| 745 | case '\'': |
| 746 | return -1; |
| 747 | default: |
| 748 | *out_c = c; |
| 749 | state = StateExpectEndQuot; |
| 750 | } |
| 751 | break; |
| 752 | case StateExpectEndQuot: |
| 753 | switch (c) { |
| 754 | case '\'': |
| 755 | state = StateExpectEnd; |
| 756 | break; |
| 757 | default: |
| 758 | return -1; |
| 759 | } |
| 760 | break; |
| 761 | case StateExpectEnd: |
| 762 | return -1; |
| 763 | } |
| 764 | } |
| 765 | return (state == StateExpectEnd) ? 0 : -1; |
| 766 | } |
| 767 | |
| 768 | static void process_macro(Context *c, Buf *name, Buf *value) { |
| 769 | // maybe it's a character literal |
| 770 | uint8_t ch; |
| 771 | if (!parse_c_char_lit(value, &ch)) { |
| 772 | c->macro_table.put(name, true); |
| 773 | AstNode *var_node = create_var_decl_node(c, buf_ptr(name), create_char_lit_node(c, ch)); |
| 774 | c->root->data.root.top_level_decls.append(var_node); |
| 775 | return; |
| 776 | } |
| 777 | // maybe it's a string literal |
| 778 | // TODO |
| 779 | // maybe it's a number literal |
| 780 | // TODO |
| 781 | // maybe it's a symbol |
| 782 | // TODO |
| 783 | } |
| 784 | |
| 716 | 785 | static void process_preprocessor_entities(Context *c, ASTUnit &unit) { |
| 717 | 786 | for (PreprocessedEntity *entity : unit.getLocalPreprocessingEntities()) { |
| 718 | 787 | switch (entity->getKind()) { |
| ... | ... | @@ -724,14 +793,27 @@ static void process_preprocessor_entities(Context *c, ASTUnit &unit) { |
| 724 | 793 | { |
| 725 | 794 | MacroDefinitionRecord *macro = static_cast<MacroDefinitionRecord *>(entity); |
| 726 | 795 | const char *name = macro->getName()->getNameStart(); |
| 727 | | fprintf(stderr, "definition macro: %s\n", name); |
| 728 | 796 | SourceRange range = macro->getSourceRange(); |
| 729 | 797 | SourceLocation begin_loc = range.getBegin(); |
| 730 | 798 | SourceLocation end_loc = range.getEnd(); |
| 731 | 799 | |
| 732 | | const char *start_c = c->source_manager->getCharacterData(begin_loc); |
| 800 | if (begin_loc == end_loc) { |
| 801 | // this means it is a macro without a value |
| 802 | // we don't care about such things |
| 803 | continue; |
| 804 | } |
| 805 | |
| 733 | 806 | const char *end_c = c->source_manager->getCharacterData(end_loc); |
| 734 | | fprintf(stderr, "source: '%.*s'\n", (int)(end_c - start_c), start_c); |
| 807 | Buf *value = buf_alloc(); |
| 808 | while (*end_c && *end_c != '\n') { |
| 809 | buf_append_char(value, *end_c); |
| 810 | if (end_c[0] == '\\' && end_c[1] == '\n') { |
| 811 | end_c += 2; |
| 812 | } else { |
| 813 | end_c += 1; |
| 814 | } |
| 815 | } |
| 816 | process_macro(c, buf_create_from_str(name), value); |
| 735 | 817 | } |
| 736 | 818 | } |
| 737 | 819 | } |
| ... | ... | @@ -771,10 +853,11 @@ int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, |
| 771 | 853 | c->import = import; |
| 772 | 854 | c->errors = errors; |
| 773 | 855 | c->visib_mod = VisibModPub; |
| 774 | | c->root_type_table.init(16); |
| 775 | | c->enum_type_table.init(16); |
| 776 | | c->struct_type_table.init(16); |
| 777 | | c->fn_table.init(16); |
| 856 | c->root_type_table.init(8); |
| 857 | c->enum_type_table.init(8); |
| 858 | c->struct_type_table.init(8); |
| 859 | c->fn_table.init(8); |
| 860 | c->macro_table.init(8); |
| 778 | 861 | |
| 779 | 862 | char *ZIG_PARSEH_CFLAGS = getenv("ZIG_PARSEH_CFLAGS"); |
| 780 | 863 | if (ZIG_PARSEH_CFLAGS) { |