| author | |
| committer | |
| log | ab60c8e28fb89e33b094e457d477a19d1f015c62 |
| tree | a89d7cd4b54f67fdc71080a0d0a195fb2a2dad6c |
| parent | 9f0e83a5710a85273f12b7e9ecf68c93e0f763e8 |
| signature | Commit is signed but in an unrecognized format. |
4 files changed, 100 insertions(+), 20 deletions(-)
src-self-hosted/c_tokenizer.zig+84-5| ... | @@ -40,12 +40,15 @@ pub const CToken = struct { | ... | @@ -40,12 +40,15 @@ pub const CToken = struct { |
| 40 | }; | 40 | }; |
| 41 | }; | 41 | }; |
| 42 | 42 | ||
| 43 | pub fn tokenizeCMacro(tl: *TokenList, chars: [*]const u8) !void { | 43 | pub fn tokenizeCMacro(tl: *TokenList, chars: [*:0]const u8) !void { |
| 44 | var index: usize = 0; | 44 | var index: usize = 0; |
| 45 | var first = true; | 45 | var first = true; |
| 46 | while (true) { | 46 | while (true) { |
| 47 | const tok = try next(chars, &index); | 47 | const tok = try next(chars, &index); |
| 48 | try tl.push(tok); | 48 | if (tok.id == .StrLit or tok.id == .CharLit) |
| 49 | try tl.push(try zigifyEscapeSequences(tl.allocator, tok)) | ||
| 50 | else | ||
| 51 | try tl.push(tok); | ||
| 49 | if (tok.id == .Eof) | 52 | if (tok.id == .Eof) |
| 50 | return; | 53 | return; |
| 51 | if (first) { | 54 | if (first) { |
| ... | @@ -61,7 +64,83 @@ pub fn tokenizeCMacro(tl: *TokenList, chars: [*]const u8) !void { | ... | @@ -61,7 +64,83 @@ pub fn tokenizeCMacro(tl: *TokenList, chars: [*]const u8) !void { |
| 61 | } | 64 | } |
| 62 | } | 65 | } |
| 63 | 66 | ||
| 64 | fn next(chars: [*]const u8, i: *usize) !CToken { | 67 | fn zigifyEscapeSequences(allocator: *std.mem.Allocator, tok: CToken) !CToken { |
| 68 | for (tok.bytes) |c| { | ||
| 69 | if (c == '\\') { | ||
| 70 | break; | ||
| 71 | } | ||
| 72 | } else return tok; | ||
| 73 | var bytes = try allocator.alloc(u8, tok.bytes.len * 2); | ||
| 74 | var escape = false; | ||
| 75 | var i: usize = 0; | ||
| 76 | for (tok.bytes) |c| { | ||
| 77 | if (escape) { | ||
| 78 | switch (c) { | ||
| 79 | 'n', 'r', 't', '\\', '\'', '\"', 'x' => { | ||
| 80 | bytes[i] = c; | ||
| 81 | }, | ||
| 82 | 'a' => { | ||
| 83 | bytes[i] = 'x'; | ||
| 84 | i += 1; | ||
| 85 | bytes[i] = '0'; | ||
| 86 | i += 1; | ||
| 87 | bytes[i] = '7'; | ||
| 88 | }, | ||
| 89 | 'b' => { | ||
| 90 | bytes[i] = 'x'; | ||
| 91 | i += 1; | ||
| 92 | bytes[i] = '0'; | ||
| 93 | i += 1; | ||
| 94 | bytes[i] = '8'; | ||
| 95 | }, | ||
| 96 | 'f' => { | ||
| 97 | bytes[i] = 'x'; | ||
| 98 | i += 1; | ||
| 99 | bytes[i] = '0'; | ||
| 100 | i += 1; | ||
| 101 | bytes[i] = 'C'; | ||
| 102 | }, | ||
| 103 | 'v' => { | ||
| 104 | bytes[i] = 'x'; | ||
| 105 | i += 1; | ||
| 106 | bytes[i] = '0'; | ||
| 107 | i += 1; | ||
| 108 | bytes[i] = 'B'; | ||
| 109 | }, | ||
| 110 | '?' => { | ||
| 111 | i -= 1; | ||
| 112 | bytes[i] = '?'; | ||
| 113 | }, | ||
| 114 | 'u', 'U' => { | ||
| 115 | // TODO unicode escape sequences | ||
| 116 | return error.TokenizingFailed; | ||
| 117 | }, | ||
| 118 | '0'...'7' => { | ||
| 119 | // TODO octal escape sequences | ||
| 120 | return error.TokenizingFailed; | ||
| 121 | }, | ||
| 122 | else => { | ||
| 123 | // unknown escape sequence | ||
| 124 | return error.TokenizingFailed; | ||
| 125 | }, | ||
| 126 | } | ||
| 127 | i += 1; | ||
| 128 | escape = false; | ||
| 129 | } else { | ||
| 130 | if (c == '\\') { | ||
| 131 | escape = true; | ||
| 132 | } | ||
| 133 | bytes[i] = c; | ||
| 134 | i += 1; | ||
| 135 | } | ||
| 136 | } | ||
| 137 | return CToken{ | ||
| 138 | .id = tok.id, | ||
| 139 | .bytes = bytes[0..i], | ||
| 140 | }; | ||
| 141 | } | ||
| 142 | |||
| 143 | fn next(chars: [*:0]const u8, i: *usize) !CToken { | ||
| 65 | var state: enum { | 144 | var state: enum { |
| 66 | Start, | 145 | Start, |
| 67 | GotLt, | 146 | GotLt, |
| ... | @@ -462,7 +541,7 @@ fn next(chars: [*]const u8, i: *usize) !CToken { | ... | @@ -462,7 +541,7 @@ fn next(chars: [*]const u8, i: *usize) !CToken { |
| 462 | .String => { // TODO char escapes | 541 | .String => { // TODO char escapes |
| 463 | switch (c) { | 542 | switch (c) { |
| 464 | '\"' => { | 543 | '\"' => { |
| 465 | result.bytes = chars[begin_index + 1 .. i.* - 1]; | 544 | result.bytes = chars[begin_index..i.*]; |
| 466 | return result; | 545 | return result; |
| 467 | }, | 546 | }, |
| 468 | else => {}, | 547 | else => {}, |
| ... | @@ -471,7 +550,7 @@ fn next(chars: [*]const u8, i: *usize) !CToken { | ... | @@ -471,7 +550,7 @@ fn next(chars: [*]const u8, i: *usize) !CToken { |
| 471 | .CharLit => { | 550 | .CharLit => { |
| 472 | switch (c) { | 551 | switch (c) { |
| 473 | '\'' => { | 552 | '\'' => { |
| 474 | result.bytes = chars[begin_index + 1 .. i.* - 1]; | 553 | result.bytes = chars[begin_index..i.*]; |
| 475 | return result; | 554 | return result; |
| 476 | }, | 555 | }, |
| 477 | else => {}, | 556 | else => {}, |
src-self-hosted/clang.zig+1-1| ... | @@ -734,7 +734,7 @@ pub extern fn ZigClangSourceManager_getSpellingLoc(self: ?*const struct_ZigClang | ... | @@ -734,7 +734,7 @@ pub extern fn ZigClangSourceManager_getSpellingLoc(self: ?*const struct_ZigClang |
| 734 | pub extern fn ZigClangSourceManager_getFilename(self: *const struct_ZigClangSourceManager, SpellingLoc: struct_ZigClangSourceLocation) ?[*:0]const u8; | 734 | pub extern fn ZigClangSourceManager_getFilename(self: *const struct_ZigClangSourceManager, SpellingLoc: struct_ZigClangSourceLocation) ?[*:0]const u8; |
| 735 | pub extern fn ZigClangSourceManager_getSpellingLineNumber(self: ?*const struct_ZigClangSourceManager, Loc: struct_ZigClangSourceLocation) c_uint; | 735 | pub extern fn ZigClangSourceManager_getSpellingLineNumber(self: ?*const struct_ZigClangSourceManager, Loc: struct_ZigClangSourceLocation) c_uint; |
| 736 | pub extern fn ZigClangSourceManager_getSpellingColumnNumber(self: ?*const struct_ZigClangSourceManager, Loc: struct_ZigClangSourceLocation) c_uint; | 736 | pub extern fn ZigClangSourceManager_getSpellingColumnNumber(self: ?*const struct_ZigClangSourceManager, Loc: struct_ZigClangSourceLocation) c_uint; |
| 737 | pub extern fn ZigClangSourceManager_getCharacterData(self: ?*const struct_ZigClangSourceManager, SL: struct_ZigClangSourceLocation) [*c]const u8; | 737 | pub extern fn ZigClangSourceManager_getCharacterData(self: ?*const struct_ZigClangSourceManager, SL: struct_ZigClangSourceLocation) [*:0]const u8; |
| 738 | pub extern fn ZigClangASTContext_getPointerType(self: ?*const struct_ZigClangASTContext, T: struct_ZigClangQualType) struct_ZigClangQualType; | 738 | pub extern fn ZigClangASTContext_getPointerType(self: ?*const struct_ZigClangASTContext, T: struct_ZigClangQualType) struct_ZigClangQualType; |
| 739 | pub extern fn ZigClangASTUnit_getASTContext(self: ?*struct_ZigClangASTUnit) ?*struct_ZigClangASTContext; | 739 | pub extern fn ZigClangASTUnit_getASTContext(self: ?*struct_ZigClangASTUnit) ?*struct_ZigClangASTContext; |
| 740 | pub extern fn ZigClangASTUnit_getSourceManager(self: *struct_ZigClangASTUnit) *struct_ZigClangSourceManager; | 740 | pub extern fn ZigClangASTUnit_getSourceManager(self: *struct_ZigClangASTUnit) *struct_ZigClangSourceManager; |
src-self-hosted/translate_c.zig+6-14| ... | @@ -2629,9 +2629,9 @@ fn transPreprocessorEntities(c: *Context, unit: *ZigClangASTUnit) Error!void { | ... | @@ -2629,9 +2629,9 @@ fn transPreprocessorEntities(c: *Context, unit: *ZigClangASTUnit) Error!void { |
| 2629 | } else false; | 2629 | } else false; |
| 2630 | 2630 | ||
| 2631 | (if (macro_fn) | 2631 | (if (macro_fn) |
| 2632 | transMacroFnDefine(c, &tok_it, name, begin_c, begin_loc) | 2632 | transMacroFnDefine(c, &tok_it, name, begin_loc) |
| 2633 | else | 2633 | else |
| 2634 | transMacroDefine(c, &tok_it, name, begin_c, begin_loc)) catch |err| switch (err) { | 2634 | transMacroDefine(c, &tok_it, name, begin_loc)) catch |err| switch (err) { |
| 2635 | error.UnsupportedTranslation, | 2635 | error.UnsupportedTranslation, |
| 2636 | error.ParseError, | 2636 | error.ParseError, |
| 2637 | => try failDecl(c, begin_loc, name, "unable to translate macro", .{}), | 2637 | => try failDecl(c, begin_loc, name, "unable to translate macro", .{}), |
| ... | @@ -2643,7 +2643,7 @@ fn transPreprocessorEntities(c: *Context, unit: *ZigClangASTUnit) Error!void { | ... | @@ -2643,7 +2643,7 @@ fn transPreprocessorEntities(c: *Context, unit: *ZigClangASTUnit) Error!void { |
| 2643 | } | 2643 | } |
| 2644 | } | 2644 | } |
| 2645 | 2645 | ||
| 2646 | fn transMacroDefine(c: *Context, it: *ctok.TokenList.Iterator, name: []const u8, char_ptr: [*]const u8, source_loc: ZigClangSourceLocation) ParseError!void { | 2646 | fn transMacroDefine(c: *Context, it: *ctok.TokenList.Iterator, name: []const u8, source_loc: ZigClangSourceLocation) ParseError!void { |
| 2647 | const rp = makeRestorePoint(c); | 2647 | const rp = makeRestorePoint(c); |
| 2648 | 2648 | ||
| 2649 | const visib_tok = try appendToken(c, .Keyword_pub, "pub"); | 2649 | const visib_tok = try appendToken(c, .Keyword_pub, "pub"); |
| ... | @@ -2674,7 +2674,7 @@ fn transMacroDefine(c: *Context, it: *ctok.TokenList.Iterator, name: []const u8, | ... | @@ -2674,7 +2674,7 @@ fn transMacroDefine(c: *Context, it: *ctok.TokenList.Iterator, name: []const u8, |
| 2674 | _ = try c.macro_table.put(name, &node.base); | 2674 | _ = try c.macro_table.put(name, &node.base); |
| 2675 | } | 2675 | } |
| 2676 | 2676 | ||
| 2677 | fn transMacroFnDefine(c: *Context, it: *ctok.TokenList.Iterator, name: []const u8, char_ptr: [*]const u8, source_loc: ZigClangSourceLocation) ParseError!void { | 2677 | fn transMacroFnDefine(c: *Context, it: *ctok.TokenList.Iterator, name: []const u8, source_loc: ZigClangSourceLocation) ParseError!void { |
| 2678 | const rp = makeRestorePoint(c); | 2678 | const rp = makeRestorePoint(c); |
| 2679 | const pub_tok = try appendToken(c, .Keyword_pub, "pub"); | 2679 | const pub_tok = try appendToken(c, .Keyword_pub, "pub"); |
| 2680 | const inline_tok = try appendToken(c, .Keyword_inline, "inline"); | 2680 | const inline_tok = try appendToken(c, .Keyword_inline, "inline"); |
| ... | @@ -2829,11 +2829,7 @@ fn parseCPrimaryExpr(rp: RestorePoint, it: *ctok.TokenList.Iterator, source_loc: | ... | @@ -2829,11 +2829,7 @@ fn parseCPrimaryExpr(rp: RestorePoint, it: *ctok.TokenList.Iterator, source_loc: |
| 2829 | const tok = it.next().?; | 2829 | const tok = it.next().?; |
| 2830 | switch (tok.id) { | 2830 | switch (tok.id) { |
| 2831 | .CharLit => { | 2831 | .CharLit => { |
| 2832 | const buf = try rp.c.a().alloc(u8, tok.bytes.len + "''".len); | 2832 | const token = try appendToken(rp.c, .CharLiteral, tok.bytes); |
| 2833 | buf[0] = '\''; | ||
| 2834 | writeEscapedString(buf[1..], tok.bytes); | ||
| 2835 | buf[buf.len - 1] = '\''; | ||
| 2836 | const token = try appendToken(rp.c, .CharLiteral, buf); | ||
| 2837 | const node = try rp.c.a().create(ast.Node.CharLiteral); | 2833 | const node = try rp.c.a().create(ast.Node.CharLiteral); |
| 2838 | node.* = ast.Node.CharLiteral{ | 2834 | node.* = ast.Node.CharLiteral{ |
| 2839 | .token = token, | 2835 | .token = token, |
| ... | @@ -2841,11 +2837,7 @@ fn parseCPrimaryExpr(rp: RestorePoint, it: *ctok.TokenList.Iterator, source_loc: | ... | @@ -2841,11 +2837,7 @@ fn parseCPrimaryExpr(rp: RestorePoint, it: *ctok.TokenList.Iterator, source_loc: |
| 2841 | return &node.base; | 2837 | return &node.base; |
| 2842 | }, | 2838 | }, |
| 2843 | .StrLit => { | 2839 | .StrLit => { |
| 2844 | const buf = try rp.c.a().alloc(u8, tok.bytes.len + "\"\"".len); | 2840 | const token = try appendToken(rp.c, .StringLiteral, tok.bytes); |
| 2845 | buf[0] = '"'; | ||
| 2846 | writeEscapedString(buf[1..], tok.bytes); | ||
| 2847 | buf[buf.len - 1] = '"'; | ||
| 2848 | const token = try appendToken(rp.c, .StringLiteral, buf); | ||
| 2849 | const node = try rp.c.a().create(ast.Node.StringLiteral); | 2841 | const node = try rp.c.a().create(ast.Node.StringLiteral); |
| 2850 | node.* = ast.Node.StringLiteral{ | 2842 | node.* = ast.Node.StringLiteral{ |
| 2851 | .token = token, | 2843 | .token = token, |
test/translate_c.zig+9| ... | @@ -411,6 +411,15 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -411,6 +411,15 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 411 | \\} | 411 | \\} |
| 412 | }); | 412 | }); |
| 413 | 413 | ||
| 414 | cases.add_2("macro escape sequences", | ||
| 415 | \\#define FOO "aoeu\xab derp" | ||
| 416 | \\#define FOO2 "aoeu\a derp" | ||
| 417 | , &[_][]const u8{ | ||
| 418 | \\pub const FOO = "aoeu\xab derp"; | ||
| 419 | , | ||
| 420 | \\pub const FOO2 = "aoeu\x07 derp"; | ||
| 421 | }); | ||
| 422 | |||
| 414 | /////////////// Cases for only stage1 which are TODO items for stage2 //////////////// | 423 | /////////////// Cases for only stage1 which are TODO items for stage2 //////////////// |
| 415 | 424 | ||
| 416 | cases.add_both("typedef of function in struct field", | 425 | cases.add_both("typedef of function in struct field", |