diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2025-08-27 16:05:20 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2025-08-28 18:30:57 -0700 |
| commit | 8d80d67693fe8b9ec99bdd9335172cfc0d9019ec (patch) | |
| tree | a862c92c5b43d632c10b89b02cbb903b053a464d /lib | |
| parent | f7884961c230367cefd3dfbf730ac5277297dc63 (diff) | |
| download | zig-8d80d67693fe8b9ec99bdd9335172cfc0d9019ec.tar.gz zig-8d80d67693fe8b9ec99bdd9335172cfc0d9019ec.zip | |
resinator: some updates to avoid GenericWriter
These are some hastily made, untested changes to get things compiling
again, since Ryan is working on a better upgrade patchset in the
meantime.
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/compiler/aro/aro/Compilation.zig | 11 | ||||
| -rw-r--r-- | lib/compiler/resinator/cli.zig | 189 | ||||
| -rw-r--r-- | lib/compiler/resinator/compile.zig | 170 | ||||
| -rw-r--r-- | lib/compiler/resinator/errors.zig | 14 | ||||
| -rw-r--r-- | lib/compiler/resinator/main.zig | 102 | ||||
| -rw-r--r-- | lib/compiler/resinator/preprocess.zig | 13 |
6 files changed, 199 insertions, 300 deletions
diff --git a/lib/compiler/aro/aro/Compilation.zig b/lib/compiler/aro/aro/Compilation.zig index f7fc4f038f..1ba3af2628 100644 --- a/lib/compiler/aro/aro/Compilation.zig +++ b/lib/compiler/aro/aro/Compilation.zig @@ -537,8 +537,15 @@ pub fn generateBuiltinMacros(comp: *Compilation, system_defines_mode: SystemDefi var allocating: std.Io.Writer.Allocating = .init(comp.gpa); defer allocating.deinit(); - const buf = &allocating.writer; + generateBuiltinMacrosWriter(comp, system_defines_mode, &allocating.writer) catch |err| switch (err) { + error.WriteFailed => return error.OutOfMemory, + else => |e| return e, + }; + return comp.addSourceFromBuffer("<builtin>", allocating.written()); +} + +pub fn generateBuiltinMacrosWriter(comp: *Compilation, system_defines_mode: SystemDefinesMode, buf: *Writer) !void { if (system_defines_mode == .include_system_defines) { try buf.writeAll( \\#define __VERSION__ "Aro @@ -576,8 +583,6 @@ pub fn generateBuiltinMacros(comp: *Compilation, system_defines_mode: SystemDefi if (system_defines_mode == .include_system_defines) { try comp.generateSystemDefines(buf); } - - return comp.addSourceFromBuffer("<builtin>", allocating.written()); } fn generateFloatMacros(w: *Writer, prefix: []const u8, semantics: target_util.FPSemantics, ext: []const u8) !void { diff --git a/lib/compiler/resinator/cli.zig b/lib/compiler/resinator/cli.zig index 1527c60105..36f8fa4bce 100644 --- a/lib/compiler/resinator/cli.zig +++ b/lib/compiler/resinator/cli.zig @@ -520,8 +520,7 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn // - or / on its own is an error else => { var err_details = Diagnostics.ErrorDetails{ .arg_index = arg_i, .arg_span = arg.optionAndAfterSpan() }; - var msg_writer = err_details.msg.writer(allocator); - try msg_writer.print("invalid option: {s}", .{arg.prefixSlice()}); + try err_details.msg.print(allocator, "invalid option: {s}", .{arg.prefixSlice()}); try diagnostics.append(err_details); arg_i += 1; continue :next_arg; @@ -532,8 +531,7 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn const args_remaining = args.len - arg_i; if (args_remaining <= 2 and arg.looksLikeFilepath()) { var err_details = Diagnostics.ErrorDetails{ .type = .note, .print_args = true, .arg_index = arg_i }; - var msg_writer = err_details.msg.writer(allocator); - try msg_writer.writeAll("this argument was inferred to be a filepath, so argument parsing was terminated"); + try err_details.msg.appendSlice(allocator, "this argument was inferred to be a filepath, so argument parsing was terminated"); try diagnostics.append(err_details); break; @@ -550,16 +548,14 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn } else if (std.ascii.startsWithIgnoreCase(arg_name, ":output-format")) { const value = arg.value(":output-format".len, arg_i, args) catch { var err_details = Diagnostics.ErrorDetails{ .arg_index = arg_i, .arg_span = arg.missingSpan() }; - var msg_writer = err_details.msg.writer(allocator); - try msg_writer.print("missing value after {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(":output-format".len) }); + try err_details.msg.print(allocator, "missing value after {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(":output-format".len) }); try diagnostics.append(err_details); arg_i += 1; break :next_arg; }; output_format = std.meta.stringToEnum(Options.OutputFormat, value.slice) orelse blk: { var err_details = Diagnostics.ErrorDetails{ .arg_index = arg_i, .arg_span = value.argSpan(arg) }; - var msg_writer = err_details.msg.writer(allocator); - try msg_writer.print("invalid output format setting: {s} ", .{value.slice}); + try err_details.msg.print(allocator, "invalid output format setting: {s} ", .{value.slice}); try diagnostics.append(err_details); break :blk output_format; }; @@ -569,16 +565,14 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn } else if (std.ascii.startsWithIgnoreCase(arg_name, ":auto-includes")) { const value = arg.value(":auto-includes".len, arg_i, args) catch { var err_details = Diagnostics.ErrorDetails{ .arg_index = arg_i, .arg_span = arg.missingSpan() }; - var msg_writer = err_details.msg.writer(allocator); - try msg_writer.print("missing value after {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(":auto-includes".len) }); + try err_details.msg.print(allocator, "missing value after {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(":auto-includes".len) }); try diagnostics.append(err_details); arg_i += 1; break :next_arg; }; options.auto_includes = std.meta.stringToEnum(Options.AutoIncludes, value.slice) orelse blk: { var err_details = Diagnostics.ErrorDetails{ .arg_index = arg_i, .arg_span = value.argSpan(arg) }; - var msg_writer = err_details.msg.writer(allocator); - try msg_writer.print("invalid auto includes setting: {s} ", .{value.slice}); + try err_details.msg.print(allocator, "invalid auto includes setting: {s} ", .{value.slice}); try diagnostics.append(err_details); break :blk options.auto_includes; }; @@ -587,16 +581,14 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn } else if (std.ascii.startsWithIgnoreCase(arg_name, ":input-format")) { const value = arg.value(":input-format".len, arg_i, args) catch { var err_details = Diagnostics.ErrorDetails{ .arg_index = arg_i, .arg_span = arg.missingSpan() }; - var msg_writer = err_details.msg.writer(allocator); - try msg_writer.print("missing value after {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(":input-format".len) }); + try err_details.msg.print(allocator, "missing value after {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(":input-format".len) }); try diagnostics.append(err_details); arg_i += 1; break :next_arg; }; input_format = std.meta.stringToEnum(Options.InputFormat, value.slice) orelse blk: { var err_details = Diagnostics.ErrorDetails{ .arg_index = arg_i, .arg_span = value.argSpan(arg) }; - var msg_writer = err_details.msg.writer(allocator); - try msg_writer.print("invalid input format setting: {s} ", .{value.slice}); + try err_details.msg.print(allocator, "invalid input format setting: {s} ", .{value.slice}); try diagnostics.append(err_details); break :blk input_format; }; @@ -606,16 +598,14 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn } else if (std.ascii.startsWithIgnoreCase(arg_name, ":depfile-fmt")) { const value = arg.value(":depfile-fmt".len, arg_i, args) catch { var err_details = Diagnostics.ErrorDetails{ .arg_index = arg_i, .arg_span = arg.missingSpan() }; - var msg_writer = err_details.msg.writer(allocator); - try msg_writer.print("missing value after {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(":depfile-fmt".len) }); + try err_details.msg.print(allocator, "missing value after {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(":depfile-fmt".len) }); try diagnostics.append(err_details); arg_i += 1; break :next_arg; }; options.depfile_fmt = std.meta.stringToEnum(Options.DepfileFormat, value.slice) orelse blk: { var err_details = Diagnostics.ErrorDetails{ .arg_index = arg_i, .arg_span = value.argSpan(arg) }; - var msg_writer = err_details.msg.writer(allocator); - try msg_writer.print("invalid depfile format setting: {s} ", .{value.slice}); + try err_details.msg.print(allocator, "invalid depfile format setting: {s} ", .{value.slice}); try diagnostics.append(err_details); break :blk options.depfile_fmt; }; @@ -624,8 +614,7 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn } else if (std.ascii.startsWithIgnoreCase(arg_name, ":depfile")) { const value = arg.value(":depfile".len, arg_i, args) catch { var err_details = Diagnostics.ErrorDetails{ .arg_index = arg_i, .arg_span = arg.missingSpan() }; - var msg_writer = err_details.msg.writer(allocator); - try msg_writer.print("missing value after {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(":depfile".len) }); + try err_details.msg.print(allocator, "missing value after {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(":depfile".len) }); try diagnostics.append(err_details); arg_i += 1; break :next_arg; @@ -643,8 +632,7 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn } else if (std.ascii.startsWithIgnoreCase(arg_name, ":target")) { const value = arg.value(":target".len, arg_i, args) catch { var err_details = Diagnostics.ErrorDetails{ .arg_index = arg_i, .arg_span = arg.missingSpan() }; - var msg_writer = err_details.msg.writer(allocator); - try msg_writer.print("missing value after {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(":target".len) }); + try err_details.msg.print(allocator, "missing value after {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(":target".len) }); try diagnostics.append(err_details); arg_i += 1; break :next_arg; @@ -655,8 +643,7 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn const arch_str = target_it.first(); const arch = cvtres.supported_targets.Arch.fromStringIgnoreCase(arch_str) orelse { var err_details = Diagnostics.ErrorDetails{ .arg_index = arg_i, .arg_span = value.argSpan(arg) }; - var msg_writer = err_details.msg.writer(allocator); - try msg_writer.print("invalid or unsupported target architecture: {s}", .{arch_str}); + try err_details.msg.print(allocator, "invalid or unsupported target architecture: {s}", .{arch_str}); try diagnostics.append(err_details); arg_i += value.index_increment; continue :next_arg; @@ -680,13 +667,11 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn .prefix_len = arg.prefixSlice().len, .value_offset = arg.name_offset + 3, } }; - var msg_writer = err_details.msg.writer(allocator); - try msg_writer.print("missing value for {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(3) }); + try err_details.msg.print(allocator, "missing value for {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(3) }); try diagnostics.append(err_details); } var err_details = Diagnostics.ErrorDetails{ .type = .err, .arg_index = arg_i, .arg_span = arg.optionAndAfterSpan() }; - var msg_writer = err_details.msg.writer(allocator); - try msg_writer.print("the {s}{s} option is unsupported", .{ arg.prefixSlice(), arg.optionWithoutPrefix(3) }); + try err_details.msg.print(allocator, "the {s}{s} option is unsupported", .{ arg.prefixSlice(), arg.optionWithoutPrefix(3) }); try diagnostics.append(err_details); arg_i += 1; continue :next_arg; @@ -695,16 +680,14 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn else if (std.ascii.startsWithIgnoreCase(arg_name, "tn")) { const value = arg.value(2, arg_i, args) catch no_value: { var err_details = Diagnostics.ErrorDetails{ .arg_index = arg_i, .arg_span = arg.missingSpan() }; - var msg_writer = err_details.msg.writer(allocator); - try msg_writer.print("missing value after {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(2) }); + try err_details.msg.print(allocator, "missing value after {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(2) }); try diagnostics.append(err_details); // dummy zero-length slice starting where the value would have been const value_start = arg.name_offset + 2; break :no_value Arg.Value{ .slice = arg.full[value_start..value_start] }; }; var err_details = Diagnostics.ErrorDetails{ .type = .err, .arg_index = arg_i, .arg_span = arg.optionAndAfterSpan() }; - var msg_writer = err_details.msg.writer(allocator); - try msg_writer.print("the {s}{s} option is unsupported", .{ arg.prefixSlice(), arg.optionWithoutPrefix(2) }); + try err_details.msg.print(allocator, "the {s}{s} option is unsupported", .{ arg.prefixSlice(), arg.optionWithoutPrefix(2) }); try diagnostics.append(err_details); arg_i += value.index_increment; continue :next_arg; @@ -716,16 +699,14 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn { const value = arg.value(2, arg_i, args) catch no_value: { var err_details = Diagnostics.ErrorDetails{ .arg_index = arg_i, .arg_span = arg.missingSpan() }; - var msg_writer = err_details.msg.writer(allocator); - try msg_writer.print("missing value after {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(2) }); + try err_details.msg.print(allocator, "missing value after {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(2) }); try diagnostics.append(err_details); // dummy zero-length slice starting where the value would have been const value_start = arg.name_offset + 2; break :no_value Arg.Value{ .slice = arg.full[value_start..value_start] }; }; var err_details = Diagnostics.ErrorDetails{ .type = .err, .arg_index = arg_i, .arg_span = arg.optionAndAfterSpan() }; - var msg_writer = err_details.msg.writer(allocator); - try msg_writer.print("the {s}{s} option is unsupported", .{ arg.prefixSlice(), arg.optionWithoutPrefix(2) }); + try err_details.msg.print(allocator, "the {s}{s} option is unsupported", .{ arg.prefixSlice(), arg.optionWithoutPrefix(2) }); try diagnostics.append(err_details); arg_i += value.index_increment; continue :next_arg; @@ -733,8 +714,7 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn // Unsupported MUI options that do not need a value else if (std.ascii.startsWithIgnoreCase(arg_name, "g1")) { var err_details = Diagnostics.ErrorDetails{ .type = .err, .arg_index = arg_i, .arg_span = arg.optionSpan(2) }; - var msg_writer = err_details.msg.writer(allocator); - try msg_writer.print("the {s}{s} option is unsupported", .{ arg.prefixSlice(), arg.optionWithoutPrefix(2) }); + try err_details.msg.print(allocator, "the {s}{s} option is unsupported", .{ arg.prefixSlice(), arg.optionWithoutPrefix(2) }); try diagnostics.append(err_details); arg.name_offset += 2; } @@ -747,15 +727,13 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn std.ascii.startsWithIgnoreCase(arg_name, "ta")) { var err_details = Diagnostics.ErrorDetails{ .type = .err, .arg_index = arg_i, .arg_span = arg.optionSpan(2) }; - var msg_writer = err_details.msg.writer(allocator); - try msg_writer.print("the {s}{s} option is unsupported", .{ arg.prefixSlice(), arg.optionWithoutPrefix(2) }); + try err_details.msg.print(allocator, "the {s}{s} option is unsupported", .{ arg.prefixSlice(), arg.optionWithoutPrefix(2) }); try diagnostics.append(err_details); arg.name_offset += 2; } else if (std.ascii.startsWithIgnoreCase(arg_name, "fo")) { const value = arg.value(2, arg_i, args) catch { var err_details = Diagnostics.ErrorDetails{ .arg_index = arg_i, .arg_span = arg.missingSpan() }; - var msg_writer = err_details.msg.writer(allocator); - try msg_writer.print("missing output path after {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(2) }); + try err_details.msg.print(allocator, "missing output path after {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(2) }); try diagnostics.append(err_details); arg_i += 1; break :next_arg; @@ -767,8 +745,7 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn } else if (std.ascii.startsWithIgnoreCase(arg_name, "sl")) { const value = arg.value(2, arg_i, args) catch { var err_details = Diagnostics.ErrorDetails{ .arg_index = arg_i, .arg_span = arg.missingSpan() }; - var msg_writer = err_details.msg.writer(allocator); - try msg_writer.print("missing language tag after {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(2) }); + try err_details.msg.print(allocator, "missing language tag after {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(2) }); try diagnostics.append(err_details); arg_i += 1; break :next_arg; @@ -776,24 +753,20 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn const percent_str = value.slice; const percent: u32 = parsePercent(percent_str) catch { var err_details = Diagnostics.ErrorDetails{ .arg_index = arg_i, .arg_span = value.argSpan(arg) }; - var msg_writer = err_details.msg.writer(allocator); - try msg_writer.print("invalid percent format '{s}'", .{percent_str}); + try err_details.msg.print(allocator, "invalid percent format '{s}'", .{percent_str}); try diagnostics.append(err_details); var note_details = Diagnostics.ErrorDetails{ .type = .note, .print_args = false, .arg_index = arg_i }; - var note_writer = note_details.msg.writer(allocator); - try note_writer.writeAll("string length percent must be an integer between 1 and 100 (inclusive)"); + try note_details.msg.appendSlice(allocator, "string length percent must be an integer between 1 and 100 (inclusive)"); try diagnostics.append(note_details); arg_i += value.index_increment; continue :next_arg; }; if (percent == 0 or percent > 100) { var err_details = Diagnostics.ErrorDetails{ .arg_index = arg_i, .arg_span = value.argSpan(arg) }; - var msg_writer = err_details.msg.writer(allocator); - try msg_writer.print("percent out of range: {} (parsed from '{s}')", .{ percent, percent_str }); + try err_details.msg.print(allocator, "percent out of range: {} (parsed from '{s}')", .{ percent, percent_str }); try diagnostics.append(err_details); var note_details = Diagnostics.ErrorDetails{ .type = .note, .print_args = false, .arg_index = arg_i }; - var note_writer = note_details.msg.writer(allocator); - try note_writer.writeAll("string length percent must be an integer between 1 and 100 (inclusive)"); + try note_details.msg.appendSlice(allocator, "string length percent must be an integer between 1 and 100 (inclusive)"); try diagnostics.append(note_details); arg_i += value.index_increment; continue :next_arg; @@ -805,8 +778,7 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn } else if (std.ascii.startsWithIgnoreCase(arg_name, "ln")) { const value = arg.value(2, arg_i, args) catch { var err_details = Diagnostics.ErrorDetails{ .arg_index = arg_i, .arg_span = arg.missingSpan() }; - var msg_writer = err_details.msg.writer(allocator); - try msg_writer.print("missing language tag after {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(2) }); + try err_details.msg.print(allocator, "missing language tag after {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(2) }); try diagnostics.append(err_details); arg_i += 1; break :next_arg; @@ -814,16 +786,14 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn const tag = value.slice; options.default_language_id = lang.tagToInt(tag) catch { var err_details = Diagnostics.ErrorDetails{ .arg_index = arg_i, .arg_span = value.argSpan(arg) }; - var msg_writer = err_details.msg.writer(allocator); - try msg_writer.print("invalid language tag: {s}", .{tag}); + try err_details.msg.print(allocator, "invalid language tag: {s}", .{tag}); try diagnostics.append(err_details); arg_i += value.index_increment; continue :next_arg; }; if (options.default_language_id.? == lang.LOCALE_CUSTOM_UNSPECIFIED) { var err_details = Diagnostics.ErrorDetails{ .type = .warning, .arg_index = arg_i, .arg_span = value.argSpan(arg) }; - var msg_writer = err_details.msg.writer(allocator); - try msg_writer.print("language tag '{s}' does not have an assigned ID so it will be resolved to LOCALE_CUSTOM_UNSPECIFIED (id=0x{x})", .{ tag, lang.LOCALE_CUSTOM_UNSPECIFIED }); + try err_details.msg.print(allocator, "language tag '{s}' does not have an assigned ID so it will be resolved to LOCALE_CUSTOM_UNSPECIFIED (id=0x{x})", .{ tag, lang.LOCALE_CUSTOM_UNSPECIFIED }); try diagnostics.append(err_details); } arg_i += value.index_increment; @@ -831,8 +801,7 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn } else if (std.ascii.startsWithIgnoreCase(arg_name, "l")) { const value = arg.value(1, arg_i, args) catch { var err_details = Diagnostics.ErrorDetails{ .arg_index = arg_i, .arg_span = arg.missingSpan() }; - var msg_writer = err_details.msg.writer(allocator); - try msg_writer.print("missing language ID after {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(1) }); + try err_details.msg.print(allocator, "missing language ID after {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(1) }); try diagnostics.append(err_details); arg_i += 1; break :next_arg; @@ -840,8 +809,7 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn const num_str = value.slice; options.default_language_id = lang.parseInt(num_str) catch { var err_details = Diagnostics.ErrorDetails{ .arg_index = arg_i, .arg_span = value.argSpan(arg) }; - var msg_writer = err_details.msg.writer(allocator); - try msg_writer.print("invalid language ID: {s}", .{num_str}); + try err_details.msg.print(allocator, "invalid language ID: {s}", .{num_str}); try diagnostics.append(err_details); arg_i += value.index_increment; continue :next_arg; @@ -860,16 +828,14 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn { const value = arg.value(1, arg_i, args) catch no_value: { var err_details = Diagnostics.ErrorDetails{ .arg_index = arg_i, .arg_span = arg.missingSpan() }; - var msg_writer = err_details.msg.writer(allocator); - try msg_writer.print("missing value after {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(1) }); + try err_details.msg.print(allocator, "missing value after {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(1) }); try diagnostics.append(err_details); // dummy zero-length slice starting where the value would have been const value_start = arg.name_offset + 1; break :no_value Arg.Value{ .slice = arg.full[value_start..value_start] }; }; var err_details = Diagnostics.ErrorDetails{ .type = .err, .arg_index = arg_i, .arg_span = arg.optionAndAfterSpan() }; - var msg_writer = err_details.msg.writer(allocator); - try msg_writer.print("the {s}{s} option is unsupported", .{ arg.prefixSlice(), arg.optionWithoutPrefix(1) }); + try err_details.msg.print(allocator, "the {s}{s} option is unsupported", .{ arg.prefixSlice(), arg.optionWithoutPrefix(1) }); try diagnostics.append(err_details); arg_i += value.index_increment; continue :next_arg; @@ -882,16 +848,14 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn { const value = arg.value(1, arg_i, args) catch no_value: { var err_details = Diagnostics.ErrorDetails{ .arg_index = arg_i, .arg_span = arg.missingSpan() }; - var msg_writer = err_details.msg.writer(allocator); - try msg_writer.print("missing value after {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(1) }); + try err_details.msg.print(allocator, "missing value after {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(1) }); try diagnostics.append(err_details); // dummy zero-length slice starting where the value would have been const value_start = arg.name_offset + 1; break :no_value Arg.Value{ .slice = arg.full[value_start..value_start] }; }; var err_details = Diagnostics.ErrorDetails{ .type = .err, .arg_index = arg_i, .arg_span = arg.optionAndAfterSpan() }; - var msg_writer = err_details.msg.writer(allocator); - try msg_writer.print("the {s}{s} option is unsupported", .{ arg.prefixSlice(), arg.optionWithoutPrefix(1) }); + try err_details.msg.print(allocator, "the {s}{s} option is unsupported", .{ arg.prefixSlice(), arg.optionWithoutPrefix(1) }); try diagnostics.append(err_details); arg_i += value.index_increment; continue :next_arg; @@ -899,15 +863,13 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn // 1 char unsupported LCX/LCE options that do not need a value else if (std.ascii.startsWithIgnoreCase(arg_name, "t")) { var err_details = Diagnostics.ErrorDetails{ .type = .err, .arg_index = arg_i, .arg_span = arg.optionSpan(1) }; - var msg_writer = err_details.msg.writer(allocator); - try msg_writer.print("the {s}{s} option is unsupported", .{ arg.prefixSlice(), arg.optionWithoutPrefix(1) }); + try err_details.msg.print(allocator, "the {s}{s} option is unsupported", .{ arg.prefixSlice(), arg.optionWithoutPrefix(1) }); try diagnostics.append(err_details); arg.name_offset += 1; } else if (std.ascii.startsWithIgnoreCase(arg_name, "c")) { const value = arg.value(1, arg_i, args) catch { var err_details = Diagnostics.ErrorDetails{ .arg_index = arg_i, .arg_span = arg.missingSpan() }; - var msg_writer = err_details.msg.writer(allocator); - try msg_writer.print("missing code page ID after {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(1) }); + try err_details.msg.print(allocator, "missing code page ID after {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(1) }); try diagnostics.append(err_details); arg_i += 1; break :next_arg; @@ -915,8 +877,7 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn const num_str = value.slice; const code_page_id = std.fmt.parseUnsigned(u16, num_str, 10) catch { var err_details = Diagnostics.ErrorDetails{ .arg_index = arg_i, .arg_span = value.argSpan(arg) }; - var msg_writer = err_details.msg.writer(allocator); - try msg_writer.print("invalid code page ID: {s}", .{num_str}); + try err_details.msg.print(allocator, "invalid code page ID: {s}", .{num_str}); try diagnostics.append(err_details); arg_i += value.index_increment; continue :next_arg; @@ -924,16 +885,14 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn options.default_code_page = code_pages.getByIdentifierEnsureSupported(code_page_id) catch |err| switch (err) { error.InvalidCodePage => { var err_details = Diagnostics.ErrorDetails{ .arg_index = arg_i, .arg_span = value.argSpan(arg) }; - var msg_writer = err_details.msg.writer(allocator); - try msg_writer.print("invalid or unknown code page ID: {}", .{code_page_id}); + try err_details.msg.print(allocator, "invalid or unknown code page ID: {}", .{code_page_id}); try diagnostics.append(err_details); arg_i += value.index_increment; continue :next_arg; }, error.UnsupportedCodePage => { var err_details = Diagnostics.ErrorDetails{ .arg_index = arg_i, .arg_span = value.argSpan(arg) }; - var msg_writer = err_details.msg.writer(allocator); - try msg_writer.print("unsupported code page: {s} (id={})", .{ + try err_details.msg.print(allocator, "unsupported code page: {s} (id={})", .{ @tagName(code_pages.getByIdentifier(code_page_id) catch unreachable), code_page_id, }); @@ -957,8 +916,7 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn } else if (std.ascii.startsWithIgnoreCase(arg_name, "i")) { const value = arg.value(1, arg_i, args) catch { var err_details = Diagnostics.ErrorDetails{ .arg_index = arg_i, .arg_span = arg.missingSpan() }; - var msg_writer = err_details.msg.writer(allocator); - try msg_writer.print("missing include path after {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(1) }); + try err_details.msg.print(allocator, "missing include path after {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(1) }); try diagnostics.append(err_details); arg_i += 1; break :next_arg; @@ -986,15 +944,13 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn // Undocumented option with unknown function // TODO: More investigation to figure out what it does (if anything) var err_details = Diagnostics.ErrorDetails{ .type = .warning, .arg_index = arg_i, .arg_span = arg.optionSpan(1) }; - var msg_writer = err_details.msg.writer(allocator); - try msg_writer.print("option {s}{s} has no effect (it is undocumented and its function is unknown in the Win32 RC compiler)", .{ arg.prefixSlice(), arg.optionWithoutPrefix(1) }); + try err_details.msg.print(allocator, "option {s}{s} has no effect (it is undocumented and its function is unknown in the Win32 RC compiler)", .{ arg.prefixSlice(), arg.optionWithoutPrefix(1) }); try diagnostics.append(err_details); arg.name_offset += 1; } else if (std.ascii.startsWithIgnoreCase(arg_name, "d")) { const value = arg.value(1, arg_i, args) catch { var err_details = Diagnostics.ErrorDetails{ .arg_index = arg_i, .arg_span = arg.missingSpan() }; - var msg_writer = err_details.msg.writer(allocator); - try msg_writer.print("missing symbol to define after {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(1) }); + try err_details.msg.print(allocator, "missing symbol to define after {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(1) }); try diagnostics.append(err_details); arg_i += 1; break :next_arg; @@ -1009,8 +965,7 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn try options.define(symbol, symbol_value); } else { var err_details = Diagnostics.ErrorDetails{ .type = .warning, .arg_index = arg_i, .arg_span = value.argSpan(arg) }; - var msg_writer = err_details.msg.writer(allocator); - try msg_writer.print("symbol \"{s}\" is not a valid identifier and therefore cannot be defined", .{symbol}); + try err_details.msg.print(allocator, "symbol \"{s}\" is not a valid identifier and therefore cannot be defined", .{symbol}); try diagnostics.append(err_details); } arg_i += value.index_increment; @@ -1018,8 +973,7 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn } else if (std.ascii.startsWithIgnoreCase(arg_name, "u")) { const value = arg.value(1, arg_i, args) catch { var err_details = Diagnostics.ErrorDetails{ .arg_index = arg_i, .arg_span = arg.missingSpan() }; - var msg_writer = err_details.msg.writer(allocator); - try msg_writer.print("missing symbol to undefine after {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(1) }); + try err_details.msg.print(allocator, "missing symbol to undefine after {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(1) }); try diagnostics.append(err_details); arg_i += 1; break :next_arg; @@ -1029,16 +983,14 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn try options.undefine(symbol); } else { var err_details = Diagnostics.ErrorDetails{ .type = .warning, .arg_index = arg_i, .arg_span = value.argSpan(arg) }; - var msg_writer = err_details.msg.writer(allocator); - try msg_writer.print("symbol \"{s}\" is not a valid identifier and therefore cannot be undefined", .{symbol}); + try err_details.msg.print(allocator, "symbol \"{s}\" is not a valid identifier and therefore cannot be undefined", .{symbol}); try diagnostics.append(err_details); } arg_i += value.index_increment; continue :next_arg; } else { var err_details = Diagnostics.ErrorDetails{ .arg_index = arg_i, .arg_span = arg.optionAndAfterSpan() }; - var msg_writer = err_details.msg.writer(allocator); - try msg_writer.print("invalid option: {s}{s}", .{ arg.prefixSlice(), arg.name() }); + try err_details.msg.print(allocator, "invalid option: {s}{s}", .{ arg.prefixSlice(), arg.name() }); try diagnostics.append(err_details); arg_i += 1; continue :next_arg; @@ -1055,16 +1007,14 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn if (positionals.len == 0) { var err_details = Diagnostics.ErrorDetails{ .print_args = false, .arg_index = arg_i }; - var msg_writer = err_details.msg.writer(allocator); - try msg_writer.writeAll("missing input filename"); + try err_details.msg.appendSlice(allocator, "missing input filename"); try diagnostics.append(err_details); if (args.len > 0) { const last_arg = args[args.len - 1]; if (arg_i > 0 and last_arg.len > 0 and last_arg[0] == '/' and isSupportedInputExtension(std.fs.path.extension(last_arg))) { var note_details = Diagnostics.ErrorDetails{ .type = .note, .print_args = true, .arg_index = arg_i - 1 }; - var note_writer = note_details.msg.writer(allocator); - try note_writer.writeAll("if this argument was intended to be the input filename, adding -- in front of it will exclude it from option parsing"); + try note_details.msg.appendSlice(allocator, "if this argument was intended to be the input filename, adding -- in front of it will exclude it from option parsing"); try diagnostics.append(note_details); } } @@ -1099,16 +1049,14 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn if (positionals.len > 1) { if (output_filename != null) { var err_details = Diagnostics.ErrorDetails{ .arg_index = arg_i + 1 }; - var msg_writer = err_details.msg.writer(allocator); - try msg_writer.writeAll("output filename already specified"); + try err_details.msg.appendSlice(allocator, "output filename already specified"); try diagnostics.append(err_details); var note_details = Diagnostics.ErrorDetails{ .type = .note, .arg_index = output_filename_context.arg.index, .arg_span = output_filename_context.arg.value.argSpan(output_filename_context.arg.arg), }; - var note_writer = note_details.msg.writer(allocator); - try note_writer.writeAll("output filename previously specified here"); + try note_details.msg.appendSlice(allocator, "output filename previously specified here"); try diagnostics.append(note_details); } else { output_filename = positionals[1]; @@ -1173,16 +1121,15 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn var print_output_format_source_note: bool = false; if (options.depfile_path != null and (options.input_format == .res or options.output_format == .rcpp)) { var err_details = Diagnostics.ErrorDetails{ .type = .warning, .arg_index = depfile_context.index, .arg_span = depfile_context.value.argSpan(depfile_context.arg) }; - var msg_writer = err_details.msg.writer(allocator); if (options.input_format == .res) { - try msg_writer.print("the {s}{s} option was ignored because the input format is '{s}'", .{ + try err_details.msg.print(allocator, "the {s}{s} option was ignored because the input format is '{s}'", .{ depfile_context.arg.prefixSlice(), depfile_context.arg.optionWithoutPrefix(depfile_context.option_len), @tagName(options.input_format), }); print_input_format_source_note = true; } else if (options.output_format == .rcpp) { - try msg_writer.print("the {s}{s} option was ignored because the output format is '{s}'", .{ + try err_details.msg.print(allocator, "the {s}{s} option was ignored because the output format is '{s}'", .{ depfile_context.arg.prefixSlice(), depfile_context.arg.optionWithoutPrefix(depfile_context.option_len), @tagName(options.output_format), @@ -1193,16 +1140,14 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn } if (!isSupportedTransformation(options.input_format, options.output_format)) { var err_details = Diagnostics.ErrorDetails{ .arg_index = input_filename_arg_i, .print_args = false }; - var msg_writer = err_details.msg.writer(allocator); - try msg_writer.print("input format '{s}' cannot be converted to output format '{s}'", .{ @tagName(options.input_format), @tagName(options.output_format) }); + try err_details.msg.print(allocator, "input format '{s}' cannot be converted to output format '{s}'", .{ @tagName(options.input_format), @tagName(options.output_format) }); try diagnostics.append(err_details); print_input_format_source_note = true; print_output_format_source_note = true; } if (options.preprocess == .only and options.output_format != .rcpp) { var err_details = Diagnostics.ErrorDetails{ .arg_index = preprocess_only_context.index }; - var msg_writer = err_details.msg.writer(allocator); - try msg_writer.print("the {s}{s} option cannot be used with output format '{s}'", .{ + try err_details.msg.print(allocator, "the {s}{s} option cannot be used with output format '{s}'", .{ preprocess_only_context.arg.prefixSlice(), preprocess_only_context.arg.optionWithoutPrefix(preprocess_only_context.option_len), @tagName(options.output_format), @@ -1214,8 +1159,7 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn switch (input_format_source) { .inferred_from_input_filename => { var err_details = Diagnostics.ErrorDetails{ .type = .note, .arg_index = input_filename_arg_i }; - var msg_writer = err_details.msg.writer(allocator); - try msg_writer.writeAll("the input format was inferred from the input filename"); + try err_details.msg.appendSlice(allocator, "the input format was inferred from the input filename"); try diagnostics.append(err_details); }, .input_format_arg => { @@ -1224,8 +1168,7 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn .arg_index = input_format_context.index, .arg_span = input_format_context.value.argSpan(input_format_context.arg), }; - var msg_writer = err_details.msg.writer(allocator); - try msg_writer.writeAll("the input format was specified here"); + try err_details.msg.appendSlice(allocator, "the input format was specified here"); try diagnostics.append(err_details); }, } @@ -1234,11 +1177,10 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn switch (output_format_source) { .inferred_from_input_filename, .unable_to_infer_from_input_filename => { var err_details = Diagnostics.ErrorDetails{ .type = .note, .arg_index = input_filename_arg_i }; - var msg_writer = err_details.msg.writer(allocator); if (output_format_source == .inferred_from_input_filename) { - try msg_writer.writeAll("the output format was inferred from the input filename"); + try err_details.msg.appendSlice(allocator, "the output format was inferred from the input filename"); } else { - try msg_writer.writeAll("the output format was unable to be inferred from the input filename, so the default was used"); + try err_details.msg.appendSlice(allocator, "the output format was unable to be inferred from the input filename, so the default was used"); } try diagnostics.append(err_details); }, @@ -1248,11 +1190,10 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn .arg => |ctx| .{ .type = .note, .arg_index = ctx.index, .arg_span = ctx.value.argSpan(ctx.arg) }, .unspecified => unreachable, }; - var msg_writer = err_details.msg.writer(allocator); if (output_format_source == .inferred_from_output_filename) { - try msg_writer.writeAll("the output format was inferred from the output filename"); + try err_details.msg.appendSlice(allocator, "the output format was inferred from the output filename"); } else { - try msg_writer.writeAll("the output format was unable to be inferred from the output filename, so the default was used"); + try err_details.msg.appendSlice(allocator, "the output format was unable to be inferred from the output filename, so the default was used"); } try diagnostics.append(err_details); }, @@ -1262,14 +1203,12 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn .arg_index = output_format_context.index, .arg_span = output_format_context.value.argSpan(output_format_context.arg), }; - var msg_writer = err_details.msg.writer(allocator); - try msg_writer.writeAll("the output format was specified here"); + try err_details.msg.appendSlice(allocator, "the output format was specified here"); try diagnostics.append(err_details); }, .inferred_from_preprocess_only => { var err_details = Diagnostics.ErrorDetails{ .type = .note, .arg_index = preprocess_only_context.index }; - var msg_writer = err_details.msg.writer(allocator); - try msg_writer.print("the output format was inferred from the usage of the {s}{s} option", .{ + try err_details.msg.print(allocator, "the output format was inferred from the usage of the {s}{s} option", .{ preprocess_only_context.arg.prefixSlice(), preprocess_only_context.arg.optionWithoutPrefix(preprocess_only_context.option_len), }); diff --git a/lib/compiler/resinator/compile.zig b/lib/compiler/resinator/compile.zig index 60d91eeb73..ef82e9b75d 100644 --- a/lib/compiler/resinator/compile.zig +++ b/lib/compiler/resinator/compile.zig @@ -61,7 +61,7 @@ pub const CompileOptions = struct { warn_instead_of_error_on_invalid_code_page: bool = false, }; -pub fn compile(allocator: Allocator, source: []const u8, writer: anytype, options: CompileOptions) !void { +pub fn compile(allocator: Allocator, source: []const u8, writer: *std.Io.Writer, options: CompileOptions) !void { var lexer = lex.Lexer.init(source, .{ .default_code_page = options.default_code_page, .source_mappings = options.source_mappings, @@ -194,7 +194,7 @@ pub const Compiler = struct { characteristics: u32 = 0, }; - pub fn writeRoot(self: *Compiler, root: *Node.Root, writer: anytype) !void { + pub fn writeRoot(self: *Compiler, root: *Node.Root, writer: *std.Io.Writer) !void { try writeEmptyResource(writer); for (root.body) |node| { try self.writeNode(node, writer); @@ -236,7 +236,7 @@ pub const Compiler = struct { } } - pub fn writeNode(self: *Compiler, node: *Node, writer: anytype) !void { + pub fn writeNode(self: *Compiler, node: *Node, writer: *std.Io.Writer) !void { switch (node.id) { .root => unreachable, // writeRoot should be called directly instead .resource_external => try self.writeResourceExternal(@alignCast(@fieldParentPtr("base", node)), writer), @@ -479,7 +479,7 @@ pub const Compiler = struct { return buf.toOwnedSlice(); } - pub fn writeResourceExternal(self: *Compiler, node: *Node.ResourceExternal, writer: anytype) !void { + pub fn writeResourceExternal(self: *Compiler, node: *Node.ResourceExternal, writer: *std.Io.Writer) !void { // Init header with data size zero for now, will need to fill it in later var header = try self.resourceHeader(node.id, node.type, .{}); defer header.deinit(self.allocator); @@ -1226,33 +1226,31 @@ pub const Compiler = struct { } pub fn writeResourceRawData(self: *Compiler, node: *Node.ResourceRawData, writer: anytype) !void { - var data_buffer = std.array_list.Managed(u8).init(self.allocator); + var data_buffer: std.Io.Writer.Allocating = .init(self.allocator); defer data_buffer.deinit(); // The header's data length field is a u32 so limit the resource's data size so that // we know we can always specify the real size. - var limited_writer = limitedWriter(data_buffer.writer(), std.math.maxInt(u32)); - const data_writer = limited_writer.writer(); + const data_writer = &data_buffer.writer; for (node.raw_data) |expression| { const data = try self.evaluateDataExpression(expression); defer data.deinit(self.allocator); data.write(data_writer) catch |err| switch (err) { - error.NoSpaceLeft => { + error.WriteFailed => { return self.addErrorDetailsAndFail(.{ .err = .resource_data_size_exceeds_max, .token = node.id, }); }, - else => |e| return e, }; } // This intCast can't fail because the limitedWriter above guarantees that // we will never write more than maxInt(u32) bytes. - const data_len: u32 = @intCast(data_buffer.items.len); + const data_len: u32 = @intCast(data_buffer.written().len); try self.writeResourceHeader(writer, node.id, node.type, data_len, node.common_resource_attributes, self.state.language); - var data_fbs: std.Io.Reader = .fixed(data_buffer.items); + var data_fbs: std.Io.Reader = .fixed(data_buffer.written()); try writeResourceData(writer, &data_fbs, data_len); } @@ -1306,16 +1304,15 @@ pub const Compiler = struct { } pub fn writeAccelerators(self: *Compiler, node: *Node.Accelerators, writer: anytype) !void { - var data_buffer = std.array_list.Managed(u8).init(self.allocator); + var data_buffer: std.Io.Writer.Allocating = .init(self.allocator); defer data_buffer.deinit(); // The header's data length field is a u32 so limit the resource's data size so that // we know we can always specify the real size. - var limited_writer = limitedWriter(data_buffer.writer(), std.math.maxInt(u32)); - const data_writer = limited_writer.writer(); + const data_writer = &data_buffer.writer; self.writeAcceleratorsData(node, data_writer) catch |err| switch (err) { - error.NoSpaceLeft => { + error.WriteFailed => { return self.addErrorDetailsAndFail(.{ .err = .resource_data_size_exceeds_max, .token = node.id, @@ -1326,7 +1323,7 @@ pub const Compiler = struct { // This intCast can't fail because the limitedWriter above guarantees that // we will never write more than maxInt(u32) bytes. - const data_size: u32 = @intCast(data_buffer.items.len); + const data_size: u32 = @intCast(data_buffer.written().len); var header = try self.resourceHeader(node.id, node.type, .{ .data_size = data_size, }); @@ -1337,7 +1334,7 @@ pub const Compiler = struct { try header.write(writer, self.errContext(node.id)); - var data_fbs: std.Io.Reader = .fixed(data_buffer.items); + var data_fbs: std.Io.Reader = .fixed(data_buffer.written()); try writeResourceData(writer, &data_fbs, data_size); } @@ -1405,12 +1402,11 @@ pub const Compiler = struct { }; pub fn writeDialog(self: *Compiler, node: *Node.Dialog, writer: anytype) !void { - var data_buffer = std.array_list.Managed(u8).init(self.allocator); + var data_buffer: std.Io.Writer.Allocating = .init(self.allocator); defer data_buffer.deinit(); // The header's data length field is a u32 so limit the resource's data size so that // we know we can always specify the real size. - var limited_writer = limitedWriter(data_buffer.writer(), std.math.maxInt(u32)); - const data_writer = limited_writer.writer(); + const data_writer = &data_buffer.writer; const resource = ResourceType.fromString(.{ .slice = node.type.slice(self.source), @@ -1683,7 +1679,7 @@ pub const Compiler = struct { ) catch |err| switch (err) { // Dialog header and menu/class/title strings can never exceed u32 bytes // on their own, so this error is unreachable. - error.NoSpaceLeft => unreachable, + error.WriteFailed => unreachable, else => |e| return e, }; @@ -1700,10 +1696,10 @@ pub const Compiler = struct { data_writer, resource, // We know the data_buffer len is limited to u32 max. - @intCast(data_buffer.items.len), + @intCast(data_buffer.written().len), &controls_by_id, ) catch |err| switch (err) { - error.NoSpaceLeft => { + error.WriteFailed => { try self.addErrorDetails(.{ .err = .resource_data_size_exceeds_max, .token = node.id, @@ -1719,7 +1715,7 @@ pub const Compiler = struct { } // We know the data_buffer len is limited to u32 max. - const data_size: u32 = @intCast(data_buffer.items.len); + const data_size: u32 = @intCast(data_buffer.written().len); var header = try self.resourceHeader(node.id, node.type, .{ .data_size = data_size, }); @@ -1730,7 +1726,7 @@ pub const Compiler = struct { try header.write(writer, self.errContext(node.id)); - var data_fbs: std.Io.Reader = .fixed(data_buffer.items); + var data_fbs: std.Io.Reader = .fixed(data_buffer.written()); try writeResourceData(writer, &data_fbs, data_size); } @@ -1821,7 +1817,7 @@ pub const Compiler = struct { .token = control.type, }); } - try data_writer.writeByteNTimes(0, num_padding); + try data_writer.splatByteAll(0, num_padding); const style = if (control.style) |style_expression| // Certain styles are implied by the control type @@ -1973,16 +1969,15 @@ pub const Compiler = struct { try NameOrOrdinal.writeEmpty(data_writer); } - var extra_data_buf = std.array_list.Managed(u8).init(self.allocator); + var extra_data_buf: std.Io.Writer.Allocating = .init(self.allocator); defer extra_data_buf.deinit(); // The extra data byte length must be able to fit within a u16. - var limited_extra_data_writer = limitedWriter(extra_data_buf.writer(), std.math.maxInt(u16)); - const extra_data_writer = limited_extra_data_writer.writer(); + const extra_data_writer = &extra_data_buf.writer; for (control.extra_data) |data_expression| { const data = try self.evaluateDataExpression(data_expression); defer data.deinit(self.allocator); data.write(extra_data_writer) catch |err| switch (err) { - error.NoSpaceLeft => { + error.WriteFailed => { try self.addErrorDetails(.{ .err = .control_extra_data_size_exceeds_max, .token = control.type, @@ -1998,15 +1993,15 @@ pub const Compiler = struct { }; } // We know the extra_data_buf size fits within a u16. - const extra_data_size: u16 = @intCast(extra_data_buf.items.len); + const extra_data_size: u16 = @intCast(extra_data_buf.written().len); try data_writer.writeInt(u16, extra_data_size, .little); - try data_writer.writeAll(extra_data_buf.items); + try data_writer.writeAll(extra_data_buf.written()); } pub fn writeToolbar(self: *Compiler, node: *Node.Toolbar, writer: anytype) !void { - var data_buffer = std.array_list.Managed(u8).init(self.allocator); + var data_buffer: std.Io.Writer.Allocating = .init(self.allocator); defer data_buffer.deinit(); - const data_writer = data_buffer.writer(); + const data_writer = &data_buffer.writer; const button_width = evaluateNumberExpression(node.button_width, self.source, self.input_code_pages); const button_height = evaluateNumberExpression(node.button_height, self.source, self.input_code_pages); @@ -2034,7 +2029,7 @@ pub const Compiler = struct { } } - const data_size: u32 = @intCast(data_buffer.items.len); + const data_size: u32 = @intCast(data_buffer.written().len); var header = try self.resourceHeader(node.id, node.type, .{ .data_size = data_size, }); @@ -2044,7 +2039,7 @@ pub const Compiler = struct { try header.write(writer, self.errContext(node.id)); - var data_fbs: std.Io.Reader = .fixed(data_buffer.items); + var data_fbs: std.Io.Reader = .fixed(data_buffer.written()); try writeResourceData(writer, &data_fbs, data_size); } @@ -2082,12 +2077,11 @@ pub const Compiler = struct { } pub fn writeMenu(self: *Compiler, node: *Node.Menu, writer: anytype) !void { - var data_buffer = std.array_list.Managed(u8).init(self.allocator); + var data_buffer: std.Io.Writer.Allocating = .init(self.allocator); defer data_buffer.deinit(); // The header's data length field is a u32 so limit the resource's data size so that // we know we can always specify the real size. - var limited_writer = limitedWriter(data_buffer.writer(), std.math.maxInt(u32)); - const data_writer = limited_writer.writer(); + const data_writer = &data_buffer.writer; const type_bytes = SourceBytes{ .slice = node.type.slice(self.source), @@ -2096,9 +2090,7 @@ pub const Compiler = struct { const resource = ResourceType.fromString(type_bytes); std.debug.assert(resource == .menu or resource == .menuex); - var adapted = data_writer.adaptToNewApi(&.{}); - - self.writeMenuData(node, &adapted.new_interface, resource) catch |err| switch (err) { + self.writeMenuData(node, data_writer, resource) catch |err| switch (err) { error.WriteFailed => { return self.addErrorDetailsAndFail(.{ .err = .resource_data_size_exceeds_max, @@ -2110,7 +2102,7 @@ pub const Compiler = struct { // This intCast can't fail because the limitedWriter above guarantees that // we will never write more than maxInt(u32) bytes. - const data_size: u32 = @intCast(data_buffer.items.len); + const data_size: u32 = @intCast(data_buffer.written().len); var header = try self.resourceHeader(node.id, node.type, .{ .data_size = data_size, }); @@ -2121,7 +2113,7 @@ pub const Compiler = struct { try header.write(writer, self.errContext(node.id)); - var data_fbs: std.Io.Reader = .fixed(data_buffer.items); + var data_fbs: std.Io.Reader = .fixed(data_buffer.written()); try writeResourceData(writer, &data_fbs, data_size); } @@ -2265,12 +2257,11 @@ pub const Compiler = struct { } pub fn writeVersionInfo(self: *Compiler, node: *Node.VersionInfo, writer: anytype) !void { - var data_buffer = std.array_list.Managed(u8).init(self.allocator); + var data_buffer: std.Io.Writer.Allocating = .init(self.allocator); defer data_buffer.deinit(); // The node's length field (which is inclusive of the length of all of its children) is a u16 // so limit the node's data size so that we know we can always specify the real size. - var limited_writer = limitedWriter(data_buffer.writer(), std.math.maxInt(u16)); - const data_writer = limited_writer.writer(); + const data_writer = &data_buffer.writer; try data_writer.writeInt(u16, 0, .little); // placeholder size try data_writer.writeInt(u16, res.FixedFileInfo.byte_len, .little); @@ -2354,8 +2345,7 @@ pub const Compiler = struct { try fixed_file_info.write(data_writer); for (node.block_statements) |statement| { - var adapted = data_writer.adaptToNewApi(&.{}); - self.writeVersionNode(statement, &adapted.new_interface, &data_buffer) catch |err| switch (err) { + self.writeVersionNode(statement, data_writer, &data_buffer) catch |err| switch (err) { error.WriteFailed => { try self.addErrorDetails(.{ .err = .version_node_size_exceeds_max, @@ -2374,9 +2364,9 @@ pub const Compiler = struct { // We know that data_buffer.items.len is within the limits of a u16, since we // limited the writer to maxInt(u16) - const data_size: u16 = @intCast(data_buffer.items.len); + const data_size: u16 = @intCast(data_buffer.written().len); // And now that we know the full size of this node (including its children), set its size - std.mem.writeInt(u16, data_buffer.items[0..2], data_size, .little); + std.mem.writeInt(u16, data_buffer.written()[0..2], data_size, .little); var header = try self.resourceHeader(node.id, node.versioninfo, .{ .data_size = data_size, @@ -2387,22 +2377,22 @@ pub const Compiler = struct { try header.write(writer, self.errContext(node.id)); - var data_fbs: std.Io.Reader = .fixed(data_buffer.items); + var data_fbs: std.Io.Reader = .fixed(data_buffer.written()); try writeResourceData(writer, &data_fbs, data_size); } /// Expects writer to be a LimitedWriter limited to u16, meaning all writes to /// the writer within this function could return error.NoSpaceLeft, and that buf.items.len /// will never be able to exceed maxInt(u16). - pub fn writeVersionNode(self: *Compiler, node: *Node, writer: *std.Io.Writer, buf: *std.array_list.Managed(u8)) !void { + pub fn writeVersionNode(self: *Compiler, node: *Node, writer: *std.Io.Writer, buf: *std.Io.Writer.Allocating) !void { // We can assume that buf.items.len will never be able to exceed the limits of a u16 - try writeDataPadding(writer, @as(u16, @intCast(buf.items.len))); + try writeDataPadding(writer, @as(u16, @intCast(buf.written().len))); - const node_and_children_size_offset = buf.items.len; + const node_and_children_size_offset = buf.written().len; try writer.writeInt(u16, 0, .little); // placeholder for size - const data_size_offset = buf.items.len; + const data_size_offset = buf.written().len; try writer.writeInt(u16, 0, .little); // placeholder for data size - const data_type_offset = buf.items.len; + const data_type_offset = buf.written().len; // Data type is string unless the node contains values that are numbers. try writer.writeInt(u16, res.VersionNode.type_string, .little); @@ -2432,7 +2422,7 @@ pub const Compiler = struct { // during parsing, so we can just do the correct thing here. var values_size: usize = 0; - try writeDataPadding(writer, @intCast(buf.items.len)); + try writeDataPadding(writer, @intCast(buf.written().len)); for (block_or_value.values, 0..) |value_value_node_uncasted, i| { const value_value_node = value_value_node_uncasted.cast(.block_value_value).?; @@ -2471,11 +2461,11 @@ pub const Compiler = struct { } } } - var data_size_slice = buf.items[data_size_offset..]; + var data_size_slice = buf.written()[data_size_offset..]; std.mem.writeInt(u16, data_size_slice[0..@sizeOf(u16)], @as(u16, @intCast(values_size)), .little); if (has_number_value) { - const data_type_slice = buf.items[data_type_offset..]; + const data_type_slice = buf.written()[data_type_offset..]; std.mem.writeInt(u16, data_type_slice[0..@sizeOf(u16)], res.VersionNode.type_binary, .little); } @@ -2489,8 +2479,8 @@ pub const Compiler = struct { else => unreachable, } - const node_and_children_size = buf.items.len - node_and_children_size_offset; - const node_and_children_size_slice = buf.items[node_and_children_size_offset..]; + const node_and_children_size = buf.written().len - node_and_children_size_offset; + const node_and_children_size_slice = buf.written()[node_and_children_size_offset..]; std.mem.writeInt(u16, node_and_children_size_slice[0..@sizeOf(u16)], @as(u16, @intCast(node_and_children_size)), .little); } @@ -2973,54 +2963,6 @@ pub fn headerSlurpingReader(comptime size: usize, reader: anytype) HeaderSlurpin return .{ .child_reader = reader }; } -/// Sort of like std.io.LimitedReader, but a Writer. -/// Returns an error if writing the requested number of bytes -/// would ever exceed bytes_left, i.e. it does not always -/// write up to the limit and instead will error if the -/// limit would be breached if the entire slice was written. -pub fn LimitedWriter(comptime WriterType: type) type { - return struct { - inner_writer: WriterType, - bytes_left: u64, - - pub const Error = error{NoSpaceLeft} || WriterType.Error; - pub const Writer = std.io.GenericWriter(*Self, Error, write); - - const Self = @This(); - - pub fn write(self: *Self, bytes: []const u8) Error!usize { - if (bytes.len > self.bytes_left) return error.NoSpaceLeft; - const amt = try self.inner_writer.write(bytes); - self.bytes_left -= amt; - return amt; - } - - pub fn writer(self: *Self) Writer { - return .{ .context = self }; - } - }; -} - -/// Returns an initialised `LimitedWriter` -/// `bytes_left` is a `u64` to be able to take 64 bit file offsets -pub fn limitedWriter(inner_writer: anytype, bytes_left: u64) LimitedWriter(@TypeOf(inner_writer)) { - return .{ .inner_writer = inner_writer, .bytes_left = bytes_left }; -} - -test "limitedWriter basic usage" { - var buf: [4]u8 = undefined; - var fbs = std.io.fixedBufferStream(&buf); - var limited_stream = limitedWriter(fbs.writer(), 4); - var writer = limited_stream.writer(); - - try std.testing.expectEqual(@as(usize, 3), try writer.write("123")); - try std.testing.expectEqualSlices(u8, "123", buf[0..3]); - try std.testing.expectError(error.NoSpaceLeft, writer.write("45")); - try std.testing.expectEqual(@as(usize, 1), try writer.write("4")); - try std.testing.expectEqualSlices(u8, "1234", buf[0..4]); - try std.testing.expectError(error.NoSpaceLeft, writer.write("5")); -} - pub const FontDir = struct { fonts: std.ArrayListUnmanaged(Font) = .empty, /// To keep track of which ids are set and where they were set from @@ -3246,9 +3188,9 @@ pub const StringTable = struct { } pub fn writeResData(self: *Block, compiler: *Compiler, language: res.Language, block_id: u16, writer: anytype) !void { - var data_buffer = std.array_list.Managed(u8).init(compiler.allocator); + var data_buffer: std.Io.Writer.Allocating = .init(compiler.allocator); defer data_buffer.deinit(); - const data_writer = data_buffer.writer(); + const data_writer = &data_buffer.writer; var i: u8 = 0; var string_i: u8 = 0; @@ -3307,7 +3249,7 @@ pub const StringTable = struct { // 16 * (131,070 + 2) = 2,097,152 which is well within the u32 max. // // Note: The string literal maximum length is enforced by the lexer. - const data_size: u32 = @intCast(data_buffer.items.len); + const data_size: u32 = @intCast(data_buffer.written().len); const header = Compiler.ResourceHeader{ .name_value = .{ .ordinal = block_id }, @@ -3322,7 +3264,7 @@ pub const StringTable = struct { // we fully control and know are numbers, so they have a fixed size. try header.writeAssertNoOverflow(writer); - var data_fbs: std.Io.Reader = .fixed(data_buffer.items); + var data_fbs: std.Io.Reader = .fixed(data_buffer.written()); try Compiler.writeResourceData(writer, &data_fbs, data_size); } }; diff --git a/lib/compiler/resinator/errors.zig b/lib/compiler/resinator/errors.zig index 4bc443c4e7..254eb3c31c 100644 --- a/lib/compiler/resinator/errors.zig +++ b/lib/compiler/resinator/errors.zig @@ -1102,11 +1102,10 @@ const CorrespondingLines = struct { corresponding_lines.buffered_reader = corresponding_lines.file.reader(&.{}); errdefer corresponding_lines.deinit(); - var fbs = std.io.fixedBufferStream(&corresponding_lines.line_buf); - const writer = fbs.writer(); + var writer: std.Io.Writer = .fixed(&corresponding_lines.line_buf); try corresponding_lines.writeLineFromStreamVerbatim( - writer, + &writer, corresponding_lines.buffered_reader.interface.adaptToOldInterface(), corresponding_span.start_line, ); @@ -1145,11 +1144,10 @@ const CorrespondingLines = struct { self.line_len = 0; self.visual_line_len = 0; - var fbs = std.io.fixedBufferStream(&self.line_buf); - const writer = fbs.writer(); + var writer: std.Io.Writer = .fixed(&self.line_buf); try self.writeLineFromStreamVerbatim( - writer, + &writer, self.buffered_reader.interface.adaptToOldInterface(), self.line_num, ); @@ -1164,7 +1162,7 @@ const CorrespondingLines = struct { return visual_line; } - fn writeLineFromStreamVerbatim(self: *CorrespondingLines, writer: anytype, input: anytype, line_num: usize) !void { + fn writeLineFromStreamVerbatim(self: *CorrespondingLines, writer: *std.Io.Writer, input: anytype, line_num: usize) !void { while (try readByteOrEof(input)) |byte| { switch (byte) { '\n', '\r' => { @@ -1188,7 +1186,7 @@ const CorrespondingLines = struct { if (writer.writeByte(byte)) { self.line_len += 1; } else |err| switch (err) { - error.NoSpaceLeft => {}, + error.WriteFailed => {}, else => |e| return e, } } diff --git a/lib/compiler/resinator/main.zig b/lib/compiler/resinator/main.zig index 6e7315e771..e7722b7cd5 100644 --- a/lib/compiler/resinator/main.zig +++ b/lib/compiler/resinator/main.zig @@ -43,11 +43,11 @@ pub fn main() !void { cli_args = args[3..]; } - var stdout_writer2 = std.fs.File.stdout().writer(&stdout_buffer); + var stdout_writer = std.fs.File.stdout().writer(&stdout_buffer); var error_handler: ErrorHandler = switch (zig_integration) { true => .{ .server = .{ - .out = &stdout_writer2.interface, + .out = &stdout_writer.interface, .in = undefined, // won't be receiving messages }, }, @@ -83,18 +83,18 @@ pub fn main() !void { defer options.deinit(); if (options.print_help_and_exit) { - const stdout = std.fs.File.stdout(); - try cli.writeUsage(stdout.deprecatedWriter(), "zig rc"); + try cli.writeUsage(&stdout_writer.interface, "zig rc"); + try stdout_writer.interface.flush(); return; } // Don't allow verbose when integrating with Zig via stdout options.verbose = false; - const stdout_writer = std.fs.File.stdout().deprecatedWriter(); if (options.verbose) { - try options.dumpVerbose(stdout_writer); - try stdout_writer.writeByte('\n'); + try options.dumpVerbose(&stdout_writer.interface); + try stdout_writer.interface.writeByte('\n'); + try stdout_writer.interface.flush(); } var dependencies_list = std.array_list.Managed([]const u8).init(allocator); @@ -115,7 +115,7 @@ pub fn main() !void { const full_input = full_input: { if (options.input_format == .rc and options.preprocess != .no) { - var preprocessed_buf = std.array_list.Managed(u8).init(allocator); + var preprocessed_buf: std.Io.Writer.Allocating = .init(allocator); errdefer preprocessed_buf.deinit(); // We're going to throw away everything except the final preprocessed output anyway, @@ -139,14 +139,15 @@ pub fn main() !void { }); if (options.verbose) { - try stdout_writer.writeAll("Preprocessor: arocc (built-in)\n"); + try stdout_writer.interface.writeAll("Preprocessor: arocc (built-in)\n"); for (argv.items[0 .. argv.items.len - 1]) |arg| { - try stdout_writer.print("{s} ", .{arg}); + try stdout_writer.interface.print("{s} ", .{arg}); } - try stdout_writer.print("{s}\n\n", .{argv.items[argv.items.len - 1]}); + try stdout_writer.interface.print("{s}\n\n", .{argv.items[argv.items.len - 1]}); + try stdout_writer.interface.flush(); } - preprocess.preprocess(&comp, preprocessed_buf.writer(), argv.items, maybe_dependencies_list) catch |err| switch (err) { + preprocess.preprocess(&comp, &preprocessed_buf.writer, argv.items, maybe_dependencies_list) catch |err| switch (err) { error.GeneratedSourceError => { try error_handler.emitAroDiagnostics(allocator, "failed during preprocessor setup (this is always a bug):", &comp); std.process.exit(1); @@ -249,8 +250,9 @@ pub fn main() !void { defer diagnostics.deinit(); var output_buffer: [4096]u8 = undefined; - var res_stream_writer = res_stream.source.writer(allocator).adaptToNewApi(&output_buffer); - const output_buffered_stream = &res_stream_writer.new_interface; + var res_stream_writer = res_stream.source.writer(allocator, &output_buffer); + defer res_stream_writer.deinit(&res_stream.source); + const output_buffered_stream = res_stream_writer.interface(); compile(allocator, final_input, output_buffered_stream, .{ .cwd = std.fs.cwd(), @@ -342,10 +344,10 @@ pub fn main() !void { defer coff_stream.deinit(allocator); var coff_output_buffer: [4096]u8 = undefined; - var coff_output_buffered_stream = coff_stream.source.writer(allocator).adaptToNewApi(&coff_output_buffer); + var coff_output_buffered_stream = coff_stream.source.writer(allocator, &coff_output_buffer); var cvtres_diagnostics: cvtres.Diagnostics = .{ .none = {} }; - cvtres.writeCoff(allocator, &coff_output_buffered_stream.new_interface, resources.list.items, options.coff_options, &cvtres_diagnostics) catch |err| { + cvtres.writeCoff(allocator, coff_output_buffered_stream.interface(), resources.list.items, options.coff_options, &cvtres_diagnostics) catch |err| { switch (err) { error.DuplicateResource => { const duplicate_resource = resources.list.items[cvtres_diagnostics.duplicate_resource]; @@ -382,7 +384,7 @@ pub fn main() !void { std.process.exit(1); }; - try coff_output_buffered_stream.new_interface.flush(); + try coff_output_buffered_stream.interface().flush(); } const IoStream = struct { @@ -425,7 +427,7 @@ const IoStream = struct { pub const Source = union(enum) { file: std.fs.File, stdio: std.fs.File, - memory: std.ArrayListUnmanaged(u8), + memory: std.ArrayList(u8), /// The source has been closed and any usage of the Source in this state is illegal (except deinit). closed: void, @@ -472,26 +474,34 @@ const IoStream = struct { }; } - pub const WriterContext = struct { - self: *Source, - allocator: std.mem.Allocator, - }; - pub const WriteError = std.mem.Allocator.Error || std.fs.File.WriteError; - pub const Writer = std.io.GenericWriter(WriterContext, WriteError, write); - - pub fn write(ctx: WriterContext, bytes: []const u8) WriteError!usize { - switch (ctx.self.*) { - inline .file, .stdio => |file| return file.write(bytes), - .memory => |*list| { - try list.appendSlice(ctx.allocator, bytes); - return bytes.len; - }, - .closed => unreachable, + pub const Writer = union(enum) { + file: std.fs.File.Writer, + allocating: std.Io.Writer.Allocating, + + pub const Error = std.mem.Allocator.Error || std.fs.File.WriteError; + + pub fn interface(this: *@This()) *std.Io.Writer { + return switch (this.*) { + .file => |*fw| &fw.interface, + .allocating => |*a| &a.writer, + }; } - } - pub fn writer(self: *Source, allocator: std.mem.Allocator) Writer { - return .{ .context = .{ .self = self, .allocator = allocator } }; + pub fn deinit(this: *@This(), source: *Source) void { + switch (this.*) { + .file => {}, + .allocating => |*a| source.memory = a.toArrayList(), + } + this.* = undefined; + } + }; + + pub fn writer(source: *Source, allocator: std.mem.Allocator, buffer: []u8) Writer { + return switch (source.*) { + .file, .stdio => |file| .{ .file = file.writer(buffer) }, + .memory => |*list| .{ .allocating = .fromArrayList(allocator, list) }, + .closed => unreachable, + }; } }; }; @@ -721,7 +731,7 @@ fn cliDiagnosticsToErrorBundle( }); var cur_err: ?ErrorBundle.ErrorMessage = null; - var cur_notes: std.ArrayListUnmanaged(ErrorBundle.ErrorMessage) = .empty; + var cur_notes: std.ArrayList(ErrorBundle.ErrorMessage) = .empty; defer cur_notes.deinit(gpa); for (diagnostics.errors.items) |err_details| { switch (err_details.type) { @@ -763,10 +773,10 @@ fn diagnosticsToErrorBundle( try bundle.init(gpa); errdefer bundle.deinit(); - var msg_buf: std.ArrayListUnmanaged(u8) = .empty; - defer msg_buf.deinit(gpa); + var msg_buf: std.Io.Writer.Allocating = .init(gpa); + defer msg_buf.deinit(); var cur_err: ?ErrorBundle.ErrorMessage = null; - var cur_notes: std.ArrayListUnmanaged(ErrorBundle.ErrorMessage) = .empty; + var cur_notes: std.ArrayList(ErrorBundle.ErrorMessage) = .empty; defer cur_notes.deinit(gpa); for (diagnostics.errors.items) |err_details| { switch (err_details.type) { @@ -789,7 +799,7 @@ fn diagnosticsToErrorBundle( const column = err_details.token.calculateColumn(source, 1, source_line_start) + 1; msg_buf.clearRetainingCapacity(); - try err_details.render(msg_buf.writer(gpa), source, diagnostics.strings.items); + try err_details.render(&msg_buf.writer, source, diagnostics.strings.items); const src_loc = src_loc: { var src_loc: ErrorBundle.SourceLocation = .{ @@ -817,7 +827,7 @@ fn diagnosticsToErrorBundle( try flushErrorMessageIntoBundle(&bundle, err, cur_notes.items); } cur_err = .{ - .msg = try bundle.addString(msg_buf.items), + .msg = try bundle.addString(msg_buf.written()), .src_loc = src_loc, }; cur_notes.clearRetainingCapacity(); @@ -825,7 +835,7 @@ fn diagnosticsToErrorBundle( .note => { cur_err.?.notes_len += 1; try cur_notes.append(gpa, .{ - .msg = try bundle.addString(msg_buf.items), + .msg = try bundle.addString(msg_buf.written()), .src_loc = src_loc, }); }, @@ -876,7 +886,7 @@ fn aroDiagnosticsToErrorBundle( var msg_writer = MsgWriter.init(gpa); defer msg_writer.deinit(); var cur_err: ?ErrorBundle.ErrorMessage = null; - var cur_notes: std.ArrayListUnmanaged(ErrorBundle.ErrorMessage) = .empty; + var cur_notes: std.ArrayList(ErrorBundle.ErrorMessage) = .empty; defer cur_notes.deinit(gpa); for (comp.diagnostics.list.items) |msg| { switch (msg.kind) { @@ -971,11 +981,11 @@ const MsgWriter = struct { } pub fn print(m: *MsgWriter, comptime fmt: []const u8, args: anytype) void { - m.buf.writer().print(fmt, args) catch {}; + m.buf.print(fmt, args) catch {}; } pub fn write(m: *MsgWriter, msg: []const u8) void { - m.buf.writer().writeAll(msg) catch {}; + m.buf.appendSlice(msg) catch {}; } pub fn setColor(m: *MsgWriter, color: std.io.tty.Color) void { diff --git a/lib/compiler/resinator/preprocess.zig b/lib/compiler/resinator/preprocess.zig index ff6de00461..9988d95f2a 100644 --- a/lib/compiler/resinator/preprocess.zig +++ b/lib/compiler/resinator/preprocess.zig @@ -18,12 +18,15 @@ pub fn preprocess( var driver: aro.Driver = .{ .comp = comp, .aro_name = "arocc" }; defer driver.deinit(); - var macro_buf = std.array_list.Managed(u8).init(comp.gpa); + var macro_buf: std.Io.Writer.Allocating = .init(comp.gpa); defer macro_buf.deinit(); - _ = driver.parseArgs(std.io.null_writer, macro_buf.writer(), argv) catch |err| switch (err) { + var trash: [64]u8 = undefined; + var discarding: std.Io.Writer.Discarding = .init(&trash); + _ = driver.parseArgs(&discarding.writer, ¯o_buf.writer, argv) catch |err| switch (err) { error.FatalError => return error.ArgError, error.OutOfMemory => |e| return e, + error.WriteFailed => return error.OutOfMemory, }; if (hasAnyErrors(comp)) return error.ArgError; @@ -33,7 +36,7 @@ pub fn preprocess( error.FatalError => return error.GeneratedSourceError, else => |e| return e, }; - const user_macros = comp.addSourceFromBuffer("<command line>", macro_buf.items) catch |err| switch (err) { + const user_macros = comp.addSourceFromBuffer("<command line>", macro_buf.written()) catch |err| switch (err) { error.FatalError => return error.GeneratedSourceError, else => |e| return e, }; @@ -59,7 +62,9 @@ pub fn preprocess( if (hasAnyErrors(comp)) return error.PreprocessError; - try pp.prettyPrintTokens(writer, .result_only); + pp.prettyPrintTokens(writer, .result_only) catch |err| switch (err) { + error.WriteFailed => return error.OutOfMemory, + }; if (maybe_dependencies_list) |dependencies_list| { for (comp.sources.values()) |comp_source| { |
