| ... | @@ -5957,20 +5957,36 @@ fn zigifyEscapeSequences(ctx: *Context, m: *MacroCtx) ![]const u8 { | ... | @@ -5957,20 +5957,36 @@ fn zigifyEscapeSequences(ctx: *Context, m: *MacroCtx) ![]const u8 { |
| 5957 | return bytes[0..i]; | 5957 | return bytes[0..i]; |
| 5958 | } | 5958 | } |
| 5959 | | 5959 | |
| | 5960 | /// non-ASCII characters (c > 127) are also treated as non-printable by fmtSliceEscapeLower. |
| | 5961 | /// If a C string literal or char literal in a macro is not valid UTF-8, we need to escape |
| | 5962 | /// non-ASCII characters so that the Zig source we output will itself be UTF-8. |
| | 5963 | fn escapeUnprintables(ctx: *Context, m: *MacroCtx) ![]const u8 { |
| | 5964 | const zigified = try zigifyEscapeSequences(ctx, m); |
| | 5965 | if (std.unicode.utf8ValidateSlice(zigified)) return zigified; |
| | 5966 | |
| | 5967 | const formatter = std.fmt.fmtSliceEscapeLower(zigified); |
| | 5968 | const encoded_size = @intCast(usize, std.fmt.count("{s}", .{formatter})); |
| | 5969 | var output = try ctx.arena.alloc(u8, encoded_size); |
| | 5970 | return std.fmt.bufPrint(output, "{s}", .{formatter}) catch |err| switch (err) { |
| | 5971 | error.NoSpaceLeft => unreachable, |
| | 5972 | else => |e| return e, |
| | 5973 | }; |
| | 5974 | } |
| | 5975 | |
| 5960 | fn parseCPrimaryExprInner(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { | 5976 | fn parseCPrimaryExprInner(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 5961 | const tok = m.next().?; | 5977 | const tok = m.next().?; |
| 5962 | const slice = m.slice(); | 5978 | const slice = m.slice(); |
| 5963 | switch (tok) { | 5979 | switch (tok) { |
| 5964 | .CharLiteral => { | 5980 | .CharLiteral => { |
| 5965 | if (slice[0] != '\'' or slice[1] == '\\' or slice.len == 3) { | 5981 | if (slice[0] != '\'' or slice[1] == '\\' or slice.len == 3) { |
| 5966 | return Tag.char_literal.create(c.arena, try zigifyEscapeSequences(c, m)); | 5982 | return Tag.char_literal.create(c.arena, try escapeUnprintables(c, m)); |
| 5967 | } else { | 5983 | } else { |
| 5968 | const str = try std.fmt.allocPrint(c.arena, "0x{s}", .{std.fmt.fmtSliceHexLower(slice[1 .. slice.len - 1])}); | 5984 | const str = try std.fmt.allocPrint(c.arena, "0x{s}", .{std.fmt.fmtSliceHexLower(slice[1 .. slice.len - 1])}); |
| 5969 | return Tag.integer_literal.create(c.arena, str); | 5985 | return Tag.integer_literal.create(c.arena, str); |
| 5970 | } | 5986 | } |
| 5971 | }, | 5987 | }, |
| 5972 | .StringLiteral => { | 5988 | .StringLiteral => { |
| 5973 | return Tag.string_literal.create(c.arena, try zigifyEscapeSequences(c, m)); | 5989 | return Tag.string_literal.create(c.arena, try escapeUnprintables(c, m)); |
| 5974 | }, | 5990 | }, |
| 5975 | .IntegerLiteral, .FloatLiteral => { | 5991 | .IntegerLiteral, .FloatLiteral => { |
| 5976 | return parseCNumLit(c, m); | 5992 | return parseCNumLit(c, m); |