diff options
| author | hryx <codroid@gmail.com> | 2019-06-24 22:37:19 -0700 |
|---|---|---|
| committer | hryx <codroid@gmail.com> | 2019-06-24 22:37:19 -0700 |
| commit | 84353515817929d694efd22e528e00e8de3d41a1 (patch) | |
| tree | eba2c69f2021ff4eba733003981a63ad2d9174c4 /src-self-hosted | |
| parent | f845994839697315aba7c4d4ce80d04d0d7b8ab0 (diff) | |
| download | zig-84353515817929d694efd22e528e00e8de3d41a1.tar.gz zig-84353515817929d694efd22e528e00e8de3d41a1.zip | |
Escape C string literals
Diffstat (limited to 'src-self-hosted')
| -rw-r--r-- | src-self-hosted/translate_c.zig | 47 |
1 files changed, 44 insertions, 3 deletions
diff --git a/src-self-hosted/translate_c.zig b/src-self-hosted/translate_c.zig index 47914d9e99..be8e7bd664 100644 --- a/src-self-hosted/translate_c.zig +++ b/src-self-hosted/translate_c.zig @@ -678,10 +678,20 @@ fn transStringLiteral( const kind = ZigClangStringLiteral_getKind(stmt); switch (kind) { .Ascii, .UTF8 => { - var len: usize = undefined; - const cstr = ZigClangStringLiteral_getString_bytes_begin_size(stmt, &len); + var clen: usize = undefined; + const cstr = ZigClangStringLiteral_getString_bytes_begin_size(stmt, &clen); const zstr = try rp.c.str(cstr); - const token = try appendTokenFmt(rp.c, .StringLiteral, "c\"{}\"", zstr); // TODO: escape string + + var len: usize = 0; + for (zstr) |c| len += escapeChar(c).len; + + const buf = try rp.c.a().alloc(u8, len + "c\"\"".len); + buf[0] = 'c'; + buf[1] = '"'; + writeEscapedString(buf[2..], zstr); + buf[buf.len - 1] = '"'; + + const token = try appendToken(rp.c, .StringLiteral, buf); const node = try rp.c.a().create(ast.Node.StringLiteral); node.* = ast.Node.StringLiteral{ .base = ast.Node{ .id = .StringLiteral }, @@ -704,6 +714,37 @@ fn transStringLiteral( } } +fn escapedStringLen(s: []const u8) usize { + var len: usize = 0; + for (s) |c| len += escapeChar(c).len; + return len; +} + +fn writeEscapedString(buf: []u8, s: []const u8) void { + var i: usize = 0; + for (s) |c| { + const escaped = escapeChar(c); + std.mem.copy(u8, buf[i..], escaped); + i += escaped.len; + } +} + +fn escapeChar(c: u8) []const u8 { + // TODO: https://github.com/ziglang/zig/issues/2749 + switch (c) { + // Printable ASCII except for ' " \ + ' ', '!', '#'...'&', '('...'[', ']'...'~' => return ([_]u8{c})[0..], + '\'', '\"', '\\' => return ([_]u8{ '\\', c })[0..], + '\n' => return "\\n"[0..], + '\r' => return "\\r"[0..], + '\t' => return "\\t"[0..], + else => { + var buf: [4]u8 = undefined; + return std.fmt.bufPrint(buf[0..], "\\x{x2}", c) catch unreachable; + }, + } +} + fn transCCast( rp: RestorePoint, scope: *Scope, |
