authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-10-20 23:25:57-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-10-29 06:20:50-07:00
log4174ac18e9563c79f723e51db6c3abbb4eb3f73a
tree567c010ecd5f31762ea759d078fe08baa7b5f45d
parent76107e9e655378b7d62c1d5d93ef9e17d241975f

resinator: update for new Io APIs


5 files changed, 147 insertions(+), 94 deletions(-)

lib/compiler/resinator/compile.zig+15-8
......@@ -1,6 +1,12 @@
1const std = @import("std");
21const builtin = @import("builtin");
2const native_endian = builtin.cpu.arch.endian();
3
4const std = @import("std");
5const Io = std.Io;
36const Allocator = std.mem.Allocator;
7const WORD = std.os.windows.WORD;
8const DWORD = std.os.windows.DWORD;
9
410const Node = @import("ast.zig").Node;
511const lex = @import("lex.zig");
612const Parser = @import("parse.zig").Parser;
......@@ -17,8 +23,6 @@ const res = @import("res.zig");
1723const ico = @import("ico.zig");
1824const ani = @import("ani.zig");
1925const bmp = @import("bmp.zig");
20const WORD = std.os.windows.WORD;
21const DWORD = std.os.windows.DWORD;
2226const utils = @import("utils.zig");
2327const NameOrOrdinal = res.NameOrOrdinal;
2428const SupportedCodePage = @import("code_pages.zig").SupportedCodePage;
......@@ -28,7 +32,6 @@ const windows1252 = @import("windows1252.zig");
2832const lang = @import("lang.zig");
2933const code_pages = @import("code_pages.zig");
3034const errors = @import("errors.zig");
31const native_endian = builtin.cpu.arch.endian();
3235
3336pub const CompileOptions = struct {
3437 cwd: std.fs.Dir,
......@@ -77,7 +80,7 @@ pub const Dependencies = struct {
7780 }
7881};
7982
80pub fn compile(allocator: Allocator, source: []const u8, writer: *std.Io.Writer, options: CompileOptions) !void {
83pub fn compile(allocator: Allocator, io: Io, source: []const u8, writer: *std.Io.Writer, options: CompileOptions) !void {
8184 var lexer = lex.Lexer.init(source, .{
8285 .default_code_page = options.default_code_page,
8386 .source_mappings = options.source_mappings,
......@@ -166,10 +169,11 @@ pub fn compile(allocator: Allocator, source: []const u8, writer: *std.Io.Writer,
166169 defer arena_allocator.deinit();
167170 const arena = arena_allocator.allocator();
168171
169 var compiler = Compiler{
172 var compiler: Compiler = .{
170173 .source = source,
171174 .arena = arena,
172175 .allocator = allocator,
176 .io = io,
173177 .cwd = options.cwd,
174178 .diagnostics = options.diagnostics,
175179 .dependencies = options.dependencies,
......@@ -191,6 +195,7 @@ pub const Compiler = struct {
191195 source: []const u8,
192196 arena: Allocator,
193197 allocator: Allocator,
198 io: Io,
194199 cwd: std.fs.Dir,
195200 state: State = .{},
196201 diagnostics: *Diagnostics,
......@@ -409,7 +414,7 @@ pub const Compiler = struct {
409414 }
410415 }
411416
412 var first_error: ?std.fs.File.OpenError = null;
417 var first_error: ?(std.fs.File.OpenError || std.fs.File.StatError) = null;
413418 for (self.search_dirs) |search_dir| {
414419 if (utils.openFileNotDir(search_dir.dir, path, .{})) |file| {
415420 errdefer file.close();
......@@ -496,6 +501,8 @@ pub const Compiler = struct {
496501 }
497502
498503 pub fn writeResourceExternal(self: *Compiler, node: *Node.ResourceExternal, writer: *std.Io.Writer) !void {
504 const io = self.io;
505
499506 // Init header with data size zero for now, will need to fill it in later
500507 var header = try self.resourceHeader(node.id, node.type, .{});
501508 defer header.deinit(self.allocator);
......@@ -582,7 +589,7 @@ pub const Compiler = struct {
582589 };
583590 defer file_handle.close();
584591 var file_buffer: [2048]u8 = undefined;
585 var file_reader = file_handle.reader(&file_buffer);
592 var file_reader = file_handle.reader(io, &file_buffer);
586593
587594 if (maybe_predefined_type) |predefined_type| {
588595 switch (predefined_type) {
lib/compiler/resinator/cvtres.zig+11-4
......@@ -1,5 +1,7 @@
11const std = @import("std");
2const Io = std.Io;
23const Allocator = std.mem.Allocator;
4
35const res = @import("res.zig");
46const NameOrOrdinal = res.NameOrOrdinal;
57const MemoryFlags = res.MemoryFlags;
......@@ -169,8 +171,7 @@ pub fn parseNameOrOrdinal(allocator: Allocator, reader: *std.Io.Reader) !NameOrO
169171
170172pub const CoffOptions = struct {
171173 target: std.coff.IMAGE.FILE.MACHINE = .AMD64,
172 /// If true, zeroes will be written to all timestamp fields
173 reproducible: bool = true,
174 timestamp: i64 = 0,
174175 /// If true, the MEM_WRITE flag will not be set in the .rsrc section header
175176 read_only: bool = false,
176177 /// If non-null, a symbol with this name and storage class EXTERNAL will be added to the symbol table.
......@@ -188,7 +189,13 @@ pub const Diagnostics = union {
188189 overflow_resource: usize,
189190};
190191
191pub fn writeCoff(allocator: Allocator, writer: *std.Io.Writer, resources: []const Resource, options: CoffOptions, diagnostics: ?*Diagnostics) !void {
192pub fn writeCoff(
193 allocator: Allocator,
194 writer: *std.Io.Writer,
195 resources: []const Resource,
196 options: CoffOptions,
197 diagnostics: ?*Diagnostics,
198) !void {
192199 var resource_tree = ResourceTree.init(allocator, options);
193200 defer resource_tree.deinit();
194201
......@@ -215,7 +222,7 @@ pub fn writeCoff(allocator: Allocator, writer: *std.Io.Writer, resources: []cons
215222 const pointer_to_rsrc02_data = pointer_to_relocations + relocations_len;
216223 const pointer_to_symbol_table = pointer_to_rsrc02_data + lengths.rsrc02;
217224
218 const timestamp: i64 = if (options.reproducible) 0 else std.time.timestamp();
225 const timestamp: i64 = options.timestamp;
219226 const size_of_optional_header = 0;
220227 const machine_type: std.coff.IMAGE.FILE.MACHINE = options.target;
221228 const flags = std.coff.Header.Flags{
lib/compiler/resinator/errors.zig+27-9
......@@ -1,5 +1,11 @@
1const builtin = @import("builtin");
2const native_endian = builtin.cpu.arch.endian();
3
14const std = @import("std");
5const Io = std.Io;
26const assert = std.debug.assert;
7const Allocator = std.mem.Allocator;
8
39const Token = @import("lex.zig").Token;
410const SourceMappings = @import("source_mapping.zig").SourceMappings;
511const utils = @import("utils.zig");
......@@ -11,19 +17,19 @@ const parse = @import("parse.zig");
1117const lang = @import("lang.zig");
1218const code_pages = @import("code_pages.zig");
1319const SupportedCodePage = code_pages.SupportedCodePage;
14const builtin = @import("builtin");
15const native_endian = builtin.cpu.arch.endian();
1620
1721pub const Diagnostics = struct {
1822 errors: std.ArrayList(ErrorDetails) = .empty,
1923 /// Append-only, cannot handle removing strings.
2024 /// Expects to own all strings within the list.
2125 strings: std.ArrayList([]const u8) = .empty,
22 allocator: std.mem.Allocator,
26 allocator: Allocator,
27 io: Io,
2328
24 pub fn init(allocator: std.mem.Allocator) Diagnostics {
29 pub fn init(allocator: Allocator, io: Io) Diagnostics {
2530 return .{
2631 .allocator = allocator,
32 .io = io,
2733 };
2834 }
2935
......@@ -62,10 +68,11 @@ pub const Diagnostics = struct {
6268 }
6369
6470 pub fn renderToStdErr(self: *Diagnostics, cwd: std.fs.Dir, source: []const u8, tty_config: std.Io.tty.Config, source_mappings: ?SourceMappings) void {
71 const io = self.io;
6572 const stderr = std.debug.lockStderrWriter(&.{});
6673 defer std.debug.unlockStderrWriter();
6774 for (self.errors.items) |err_details| {
68 renderErrorMessage(stderr, tty_config, cwd, err_details, source, self.strings.items, source_mappings) catch return;
75 renderErrorMessage(io, stderr, tty_config, cwd, err_details, source, self.strings.items, source_mappings) catch return;
6976 }
7077 }
7178
......@@ -167,9 +174,9 @@ pub const ErrorDetails = struct {
167174 filename_string_index: FilenameStringIndex,
168175
169176 pub const FilenameStringIndex = std.meta.Int(.unsigned, 32 - @bitSizeOf(FileOpenErrorEnum));
170 pub const FileOpenErrorEnum = std.meta.FieldEnum(std.fs.File.OpenError);
177 pub const FileOpenErrorEnum = std.meta.FieldEnum(std.fs.File.OpenError || std.fs.File.StatError);
171178
172 pub fn enumFromError(err: std.fs.File.OpenError) FileOpenErrorEnum {
179 pub fn enumFromError(err: (std.fs.File.OpenError || std.fs.File.StatError)) FileOpenErrorEnum {
173180 return switch (err) {
174181 inline else => |e| @field(ErrorDetails.FileOpenError.FileOpenErrorEnum, @errorName(e)),
175182 };
......@@ -894,7 +901,16 @@ fn cellCount(code_page: SupportedCodePage, source: []const u8, start_index: usiz
894901
895902const truncated_str = "<...truncated...>";
896903
897pub fn renderErrorMessage(writer: *std.Io.Writer, tty_config: std.Io.tty.Config, cwd: std.fs.Dir, err_details: ErrorDetails, source: []const u8, strings: []const []const u8, source_mappings: ?SourceMappings) !void {
904pub fn renderErrorMessage(
905 io: Io,
906 writer: *std.Io.Writer,
907 tty_config: std.Io.tty.Config,
908 cwd: std.fs.Dir,
909 err_details: ErrorDetails,
910 source: []const u8,
911 strings: []const []const u8,
912 source_mappings: ?SourceMappings,
913) !void {
898914 if (err_details.type == .hint) return;
899915
900916 const source_line_start = err_details.token.getLineStartForErrorDisplay(source);
......@@ -989,6 +1005,7 @@ pub fn renderErrorMessage(writer: *std.Io.Writer, tty_config: std.Io.tty.Config,
9891005 var initial_lines_err: ?anyerror = null;
9901006 var file_reader_buf: [max_source_line_bytes * 2]u8 = undefined;
9911007 var corresponding_lines: ?CorrespondingLines = CorrespondingLines.init(
1008 io,
9921009 cwd,
9931010 err_details,
9941011 source_line_for_display.line,
......@@ -1084,6 +1101,7 @@ const CorrespondingLines = struct {
10841101 code_page: SupportedCodePage,
10851102
10861103 pub fn init(
1104 io: Io,
10871105 cwd: std.fs.Dir,
10881106 err_details: ErrorDetails,
10891107 line_for_comparison: []const u8,
......@@ -1108,7 +1126,7 @@ const CorrespondingLines = struct {
11081126 .code_page = err_details.code_page,
11091127 .file_reader = undefined,
11101128 };
1111 corresponding_lines.file_reader = corresponding_lines.file.reader(file_reader_buf);
1129 corresponding_lines.file_reader = corresponding_lines.file.reader(io, file_reader_buf);
11121130 errdefer corresponding_lines.deinit();
11131131
11141132 try corresponding_lines.writeLineFromStreamVerbatim(
lib/compiler/resinator/main.zig+89-72
......@@ -1,5 +1,9 @@
1const std = @import("std");
21const builtin = @import("builtin");
2
3const std = @import("std");
4const Io = std.Io;
5const Allocator = std.mem.Allocator;
6
37const removeComments = @import("comments.zig").removeComments;
48const parseAndRemoveLineCommands = @import("source_mapping.zig").parseAndRemoveLineCommands;
59const compile = @import("compile.zig").compile;
......@@ -16,19 +20,18 @@ const aro = @import("aro");
1620const compiler_util = @import("../util.zig");
1721
1822pub fn main() !void {
19 var gpa: std.heap.GeneralPurposeAllocator(.{}) = .init;
20 defer std.debug.assert(gpa.deinit() == .ok);
21 const allocator = gpa.allocator();
23 var debug_allocator: std.heap.DebugAllocator(.{}) = .init;
24 defer std.debug.assert(debug_allocator.deinit() == .ok);
25 const gpa = debug_allocator.allocator();
2226
23 var arena_state = std.heap.ArenaAllocator.init(allocator);
27 var arena_state = std.heap.ArenaAllocator.init(gpa);
2428 defer arena_state.deinit();
2529 const arena = arena_state.allocator();
2630
2731 const stderr = std.fs.File.stderr();
2832 const stderr_config = std.Io.tty.detectConfig(stderr);
2933
30 const args = try std.process.argsAlloc(allocator);
31 defer std.process.argsFree(allocator, args);
34 const args = try std.process.argsAlloc(arena);
3235
3336 if (args.len < 2) {
3437 try renderErrorMessage(std.debug.lockStderrWriter(&.{}), stderr_config, .err, "expected zig lib dir as first argument", .{});
......@@ -59,11 +62,11 @@ pub fn main() !void {
5962 };
6063
6164 var options = options: {
62 var cli_diagnostics = cli.Diagnostics.init(allocator);
65 var cli_diagnostics = cli.Diagnostics.init(gpa);
6366 defer cli_diagnostics.deinit();
64 var options = cli.parse(allocator, cli_args, &cli_diagnostics) catch |err| switch (err) {
67 var options = cli.parse(gpa, cli_args, &cli_diagnostics) catch |err| switch (err) {
6568 error.ParseError => {
66 try error_handler.emitCliDiagnostics(allocator, cli_args, &cli_diagnostics);
69 try error_handler.emitCliDiagnostics(gpa, cli_args, &cli_diagnostics);
6770 std.process.exit(1);
6871 },
6972 else => |e| return e,
......@@ -84,6 +87,10 @@ pub fn main() !void {
8487 };
8588 defer options.deinit();
8689
90 var threaded: std.Io.Threaded = .init(gpa);
91 defer threaded.deinit();
92 const io = threaded.io();
93
8794 if (options.print_help_and_exit) {
8895 try cli.writeUsage(stdout, "zig rc");
8996 try stdout.flush();
......@@ -99,12 +106,13 @@ pub fn main() !void {
99106 try stdout.flush();
100107 }
101108
102 var dependencies = Dependencies.init(allocator);
109 var dependencies = Dependencies.init(gpa);
103110 defer dependencies.deinit();
104111 const maybe_dependencies: ?*Dependencies = if (options.depfile_path != null) &dependencies else null;
105112
106113 var include_paths = LazyIncludePaths{
107114 .arena = arena,
115 .io = io,
108116 .auto_includes_option = options.auto_includes,
109117 .zig_lib_dir = zig_lib_dir,
110118 .target_machine_type = options.coff_options.target,
......@@ -112,12 +120,12 @@ pub fn main() !void {
112120
113121 const full_input = full_input: {
114122 if (options.input_format == .rc and options.preprocess != .no) {
115 var preprocessed_buf: std.Io.Writer.Allocating = .init(allocator);
123 var preprocessed_buf: std.Io.Writer.Allocating = .init(gpa);
116124 errdefer preprocessed_buf.deinit();
117125
118126 // We're going to throw away everything except the final preprocessed output anyway,
119127 // so we can use a scoped arena for everything else.
120 var aro_arena_state = std.heap.ArenaAllocator.init(allocator);
128 var aro_arena_state = std.heap.ArenaAllocator.init(gpa);
121129 defer aro_arena_state.deinit();
122130 const aro_arena = aro_arena_state.allocator();
123131
......@@ -129,12 +137,12 @@ pub fn main() !void {
129137 .color = stderr_config,
130138 } } },
131139 true => .{ .output = .{ .to_list = .{
132 .arena = .init(allocator),
140 .arena = .init(gpa),
133141 } } },
134142 };
135143 defer diagnostics.deinit();
136144
137 var comp = aro.Compilation.init(aro_arena, aro_arena, &diagnostics, std.fs.cwd());
145 var comp = aro.Compilation.init(aro_arena, aro_arena, io, &diagnostics, std.fs.cwd());
138146 defer comp.deinit();
139147
140148 var argv: std.ArrayList([]const u8) = .empty;
......@@ -159,20 +167,20 @@ pub fn main() !void {
159167
160168 preprocess.preprocess(&comp, &preprocessed_buf.writer, argv.items, maybe_dependencies) catch |err| switch (err) {
161169 error.GeneratedSourceError => {
162 try error_handler.emitAroDiagnostics(allocator, "failed during preprocessor setup (this is always a bug)", &comp);
170 try error_handler.emitAroDiagnostics(gpa, "failed during preprocessor setup (this is always a bug)", &comp);
163171 std.process.exit(1);
164172 },
165173 // ArgError can occur if e.g. the .rc file is not found
166174 error.ArgError, error.PreprocessError => {
167 try error_handler.emitAroDiagnostics(allocator, "failed during preprocessing", &comp);
175 try error_handler.emitAroDiagnostics(gpa, "failed during preprocessing", &comp);
168176 std.process.exit(1);
169177 },
170178 error.FileTooBig => {
171 try error_handler.emitMessage(allocator, .err, "failed during preprocessing: maximum file size exceeded", .{});
179 try error_handler.emitMessage(gpa, .err, "failed during preprocessing: maximum file size exceeded", .{});
172180 std.process.exit(1);
173181 },
174182 error.WriteFailed => {
175 try error_handler.emitMessage(allocator, .err, "failed during preprocessing: error writing the preprocessed output", .{});
183 try error_handler.emitMessage(gpa, .err, "failed during preprocessing: error writing the preprocessed output", .{});
176184 std.process.exit(1);
177185 },
178186 error.OutOfMemory => |e| return e,
......@@ -182,22 +190,22 @@ pub fn main() !void {
182190 } else {
183191 switch (options.input_source) {
184192 .stdio => |file| {
185 var file_reader = file.reader(&.{});
186 break :full_input file_reader.interface.allocRemaining(allocator, .unlimited) catch |err| {
187 try error_handler.emitMessage(allocator, .err, "unable to read input from stdin: {s}", .{@errorName(err)});
193 var file_reader = file.reader(io, &.{});
194 break :full_input file_reader.interface.allocRemaining(gpa, .unlimited) catch |err| {
195 try error_handler.emitMessage(gpa, .err, "unable to read input from stdin: {s}", .{@errorName(err)});
188196 std.process.exit(1);
189197 };
190198 },
191199 .filename => |input_filename| {
192 break :full_input std.fs.cwd().readFileAlloc(input_filename, allocator, .unlimited) catch |err| {
193 try error_handler.emitMessage(allocator, .err, "unable to read input file path '{s}': {s}", .{ input_filename, @errorName(err) });
200 break :full_input std.fs.cwd().readFileAlloc(input_filename, gpa, .unlimited) catch |err| {
201 try error_handler.emitMessage(gpa, .err, "unable to read input file path '{s}': {s}", .{ input_filename, @errorName(err) });
194202 std.process.exit(1);
195203 };
196204 },
197205 }
198206 }
199207 };
200 defer allocator.free(full_input);
208 defer gpa.free(full_input);
201209
202210 if (options.preprocess == .only) {
203211 switch (options.output_source) {
......@@ -221,55 +229,55 @@ pub fn main() !void {
221229 }
222230 else if (options.input_format == .res)
223231 IoStream.fromIoSource(options.input_source, .input) catch |err| {
224 try error_handler.emitMessage(allocator, .err, "unable to read res file path '{s}': {s}", .{ options.input_source.filename, @errorName(err) });
232 try error_handler.emitMessage(gpa, .err, "unable to read res file path '{s}': {s}", .{ options.input_source.filename, @errorName(err) });
225233 std.process.exit(1);
226234 }
227235 else
228236 IoStream.fromIoSource(options.output_source, .output) catch |err| {
229 try error_handler.emitMessage(allocator, .err, "unable to create output file '{s}': {s}", .{ options.output_source.filename, @errorName(err) });
237 try error_handler.emitMessage(gpa, .err, "unable to create output file '{s}': {s}", .{ options.output_source.filename, @errorName(err) });
230238 std.process.exit(1);
231239 };
232 defer res_stream.deinit(allocator);
240 defer res_stream.deinit(gpa);
233241
234242 const res_data = res_data: {
235243 if (options.input_format != .res) {
236244 // Note: We still want to run this when no-preprocess is set because:
237245 // 1. We want to print accurate line numbers after removing multiline comments
238246 // 2. We want to be able to handle an already-preprocessed input with #line commands in it
239 var mapping_results = parseAndRemoveLineCommands(allocator, full_input, full_input, .{ .initial_filename = options.input_source.filename }) catch |err| switch (err) {
247 var mapping_results = parseAndRemoveLineCommands(gpa, full_input, full_input, .{ .initial_filename = options.input_source.filename }) catch |err| switch (err) {
240248 error.InvalidLineCommand => {
241249 // TODO: Maybe output the invalid line command
242 try error_handler.emitMessage(allocator, .err, "invalid line command in the preprocessed source", .{});
250 try error_handler.emitMessage(gpa, .err, "invalid line command in the preprocessed source", .{});
243251 if (options.preprocess == .no) {
244 try error_handler.emitMessage(allocator, .note, "line commands must be of the format: #line <num> \"<path>\"", .{});
252 try error_handler.emitMessage(gpa, .note, "line commands must be of the format: #line <num> \"<path>\"", .{});
245253 } else {
246 try error_handler.emitMessage(allocator, .note, "this is likely to be a bug, please report it", .{});
254 try error_handler.emitMessage(gpa, .note, "this is likely to be a bug, please report it", .{});
247255 }
248256 std.process.exit(1);
249257 },
250258 error.LineNumberOverflow => {
251259 // TODO: Better error message
252 try error_handler.emitMessage(allocator, .err, "line number count exceeded maximum of {}", .{std.math.maxInt(usize)});
260 try error_handler.emitMessage(gpa, .err, "line number count exceeded maximum of {}", .{std.math.maxInt(usize)});
253261 std.process.exit(1);
254262 },
255263 error.OutOfMemory => |e| return e,
256264 };
257 defer mapping_results.mappings.deinit(allocator);
265 defer mapping_results.mappings.deinit(gpa);
258266
259267 const default_code_page = options.default_code_page orelse .windows1252;
260268 const has_disjoint_code_page = hasDisjointCodePage(mapping_results.result, &mapping_results.mappings, default_code_page);
261269
262270 const final_input = try removeComments(mapping_results.result, mapping_results.result, &mapping_results.mappings);
263271
264 var diagnostics = Diagnostics.init(allocator);
272 var diagnostics = Diagnostics.init(gpa, io);
265273 defer diagnostics.deinit();
266274
267275 var output_buffer: [4096]u8 = undefined;
268 var res_stream_writer = res_stream.source.writer(allocator, &output_buffer);
276 var res_stream_writer = res_stream.source.writer(gpa, &output_buffer);
269277 defer res_stream_writer.deinit(&res_stream.source);
270278 const output_buffered_stream = res_stream_writer.interface();
271279
272 compile(allocator, final_input, output_buffered_stream, .{
280 compile(gpa, io, final_input, output_buffered_stream, .{
273281 .cwd = std.fs.cwd(),
274282 .diagnostics = &diagnostics,
275283 .source_mappings = &mapping_results.mappings,
......@@ -287,7 +295,7 @@ pub fn main() !void {
287295 .warn_instead_of_error_on_invalid_code_page = options.warn_instead_of_error_on_invalid_code_page,
288296 }) catch |err| switch (err) {
289297 error.ParseError, error.CompileError => {
290 try error_handler.emitDiagnostics(allocator, std.fs.cwd(), final_input, &diagnostics, mapping_results.mappings);
298 try error_handler.emitDiagnostics(gpa, std.fs.cwd(), final_input, &diagnostics, mapping_results.mappings);
291299 // Delete the output file on error
292300 res_stream.cleanupAfterError();
293301 std.process.exit(1);
......@@ -305,7 +313,7 @@ pub fn main() !void {
305313 // write the depfile
306314 if (options.depfile_path) |depfile_path| {
307315 var depfile = std.fs.cwd().createFile(depfile_path, .{}) catch |err| {
308 try error_handler.emitMessage(allocator, .err, "unable to create depfile '{s}': {s}", .{ depfile_path, @errorName(err) });
316 try error_handler.emitMessage(gpa, .err, "unable to create depfile '{s}': {s}", .{ depfile_path, @errorName(err) });
309317 std.process.exit(1);
310318 };
311319 defer depfile.close();
......@@ -332,41 +340,41 @@ pub fn main() !void {
332340
333341 if (options.output_format != .coff) return;
334342
335 break :res_data res_stream.source.readAll(allocator) catch |err| {
336 try error_handler.emitMessage(allocator, .err, "unable to read res from '{s}': {s}", .{ res_stream.name, @errorName(err) });
343 break :res_data res_stream.source.readAll(gpa, io) catch |err| {
344 try error_handler.emitMessage(gpa, .err, "unable to read res from '{s}': {s}", .{ res_stream.name, @errorName(err) });
337345 std.process.exit(1);
338346 };
339347 };
340348 // No need to keep the res_data around after parsing the resources from it
341 defer res_data.deinit(allocator);
349 defer res_data.deinit(gpa);
342350
343351 std.debug.assert(options.output_format == .coff);
344352
345353 // TODO: Maybe use a buffered file reader instead of reading file into memory -> fbs
346354 var res_reader: std.Io.Reader = .fixed(res_data.bytes);
347 break :resources cvtres.parseRes(allocator, &res_reader, .{ .max_size = res_data.bytes.len }) catch |err| {
355 break :resources cvtres.parseRes(gpa, &res_reader, .{ .max_size = res_data.bytes.len }) catch |err| {
348356 // TODO: Better errors
349 try error_handler.emitMessage(allocator, .err, "unable to parse res from '{s}': {s}", .{ res_stream.name, @errorName(err) });
357 try error_handler.emitMessage(gpa, .err, "unable to parse res from '{s}': {s}", .{ res_stream.name, @errorName(err) });
350358 std.process.exit(1);
351359 };
352360 };
353361 defer resources.deinit();
354362
355363 var coff_stream = IoStream.fromIoSource(options.output_source, .output) catch |err| {
356 try error_handler.emitMessage(allocator, .err, "unable to create output file '{s}': {s}", .{ options.output_source.filename, @errorName(err) });
364 try error_handler.emitMessage(gpa, .err, "unable to create output file '{s}': {s}", .{ options.output_source.filename, @errorName(err) });
357365 std.process.exit(1);
358366 };
359 defer coff_stream.deinit(allocator);
367 defer coff_stream.deinit(gpa);
360368
361369 var coff_output_buffer: [4096]u8 = undefined;
362 var coff_output_buffered_stream = coff_stream.source.writer(allocator, &coff_output_buffer);
370 var coff_output_buffered_stream = coff_stream.source.writer(gpa, &coff_output_buffer);
363371
364372 var cvtres_diagnostics: cvtres.Diagnostics = .{ .none = {} };
365 cvtres.writeCoff(allocator, coff_output_buffered_stream.interface(), resources.list.items, options.coff_options, &cvtres_diagnostics) catch |err| {
373 cvtres.writeCoff(gpa, coff_output_buffered_stream.interface(), resources.list.items, options.coff_options, &cvtres_diagnostics) catch |err| {
366374 switch (err) {
367375 error.DuplicateResource => {
368376 const duplicate_resource = resources.list.items[cvtres_diagnostics.duplicate_resource];
369 try error_handler.emitMessage(allocator, .err, "duplicate resource [id: {f}, type: {f}, language: {f}]", .{
377 try error_handler.emitMessage(gpa, .err, "duplicate resource [id: {f}, type: {f}, language: {f}]", .{
370378 duplicate_resource.name_value,
371379 fmtResourceType(duplicate_resource.type_value),
372380 duplicate_resource.language,
......@@ -374,8 +382,8 @@ pub fn main() !void {
374382 },
375383 error.ResourceDataTooLong => {
376384 const overflow_resource = resources.list.items[cvtres_diagnostics.duplicate_resource];
377 try error_handler.emitMessage(allocator, .err, "resource has a data length that is too large to be written into a coff section", .{});
378 try error_handler.emitMessage(allocator, .note, "the resource with the invalid size is [id: {f}, type: {f}, language: {f}]", .{
385 try error_handler.emitMessage(gpa, .err, "resource has a data length that is too large to be written into a coff section", .{});
386 try error_handler.emitMessage(gpa, .note, "the resource with the invalid size is [id: {f}, type: {f}, language: {f}]", .{
379387 overflow_resource.name_value,
380388 fmtResourceType(overflow_resource.type_value),
381389 overflow_resource.language,
......@@ -383,15 +391,15 @@ pub fn main() !void {
383391 },
384392 error.TotalResourceDataTooLong => {
385393 const overflow_resource = resources.list.items[cvtres_diagnostics.duplicate_resource];
386 try error_handler.emitMessage(allocator, .err, "total resource data exceeds the maximum of the coff 'size of raw data' field", .{});
387 try error_handler.emitMessage(allocator, .note, "size overflow occurred when attempting to write this resource: [id: {f}, type: {f}, language: {f}]", .{
394 try error_handler.emitMessage(gpa, .err, "total resource data exceeds the maximum of the coff 'size of raw data' field", .{});
395 try error_handler.emitMessage(gpa, .note, "size overflow occurred when attempting to write this resource: [id: {f}, type: {f}, language: {f}]", .{
388396 overflow_resource.name_value,
389397 fmtResourceType(overflow_resource.type_value),
390398 overflow_resource.language,
391399 });
392400 },
393401 else => {
394 try error_handler.emitMessage(allocator, .err, "unable to write coff output file '{s}': {s}", .{ coff_stream.name, @errorName(err) });
402 try error_handler.emitMessage(gpa, .err, "unable to write coff output file '{s}': {s}", .{ coff_stream.name, @errorName(err) });
395403 },
396404 }
397405 // Delete the output file on error
......@@ -423,7 +431,7 @@ const IoStream = struct {
423431 };
424432 }
425433
426 pub fn deinit(self: *IoStream, allocator: std.mem.Allocator) void {
434 pub fn deinit(self: *IoStream, allocator: Allocator) void {
427435 self.source.deinit(allocator);
428436 }
429437
......@@ -458,7 +466,7 @@ const IoStream = struct {
458466 }
459467 }
460468
461 pub fn deinit(self: *Source, allocator: std.mem.Allocator) void {
469 pub fn deinit(self: *Source, allocator: Allocator) void {
462470 switch (self.*) {
463471 .file => |file| file.close(),
464472 .stdio => {},
......@@ -471,18 +479,18 @@ const IoStream = struct {
471479 bytes: []const u8,
472480 needs_free: bool,
473481
474 pub fn deinit(self: Data, allocator: std.mem.Allocator) void {
482 pub fn deinit(self: Data, allocator: Allocator) void {
475483 if (self.needs_free) {
476484 allocator.free(self.bytes);
477485 }
478486 }
479487 };
480488
481 pub fn readAll(self: Source, allocator: std.mem.Allocator) !Data {
489 pub fn readAll(self: Source, allocator: Allocator, io: Io) !Data {
482490 return switch (self) {
483491 inline .file, .stdio => |file| .{
484492 .bytes = b: {
485 var file_reader = file.reader(&.{});
493 var file_reader = file.reader(io, &.{});
486494 break :b try file_reader.interface.allocRemaining(allocator, .unlimited);
487495 },
488496 .needs_free = true,
......@@ -496,7 +504,7 @@ const IoStream = struct {
496504 file: std.fs.File.Writer,
497505 allocating: std.Io.Writer.Allocating,
498506
499 pub const Error = std.mem.Allocator.Error || std.fs.File.WriteError;
507 pub const Error = Allocator.Error || std.fs.File.WriteError;
500508
501509 pub fn interface(this: *@This()) *std.Io.Writer {
502510 return switch (this.*) {
......@@ -514,7 +522,7 @@ const IoStream = struct {
514522 }
515523 };
516524
517 pub fn writer(source: *Source, allocator: std.mem.Allocator, buffer: []u8) Writer {
525 pub fn writer(source: *Source, allocator: Allocator, buffer: []u8) Writer {
518526 return switch (source.*) {
519527 .file, .stdio => |file| .{ .file = file.writer(buffer) },
520528 .memory => |*list| .{ .allocating = .fromArrayList(allocator, list) },
......@@ -525,17 +533,20 @@ const IoStream = struct {
525533};
526534
527535const LazyIncludePaths = struct {
528 arena: std.mem.Allocator,
536 arena: Allocator,
537 io: Io,
529538 auto_includes_option: cli.Options.AutoIncludes,
530539 zig_lib_dir: []const u8,
531540 target_machine_type: std.coff.IMAGE.FILE.MACHINE,
532541 resolved_include_paths: ?[]const []const u8 = null,
533542
534543 pub fn get(self: *LazyIncludePaths, error_handler: *ErrorHandler) ![]const []const u8 {
544 const io = self.io;
545
535546 if (self.resolved_include_paths) |include_paths|
536547 return include_paths;
537548
538 return getIncludePaths(self.arena, self.auto_includes_option, self.zig_lib_dir, self.target_machine_type) catch |err| switch (err) {
549 return getIncludePaths(self.arena, io, self.auto_includes_option, self.zig_lib_dir, self.target_machine_type) catch |err| switch (err) {
539550 error.OutOfMemory => |e| return e,
540551 else => |e| {
541552 switch (e) {
......@@ -556,7 +567,13 @@ const LazyIncludePaths = struct {
556567 }
557568};
558569
559fn getIncludePaths(arena: std.mem.Allocator, auto_includes_option: cli.Options.AutoIncludes, zig_lib_dir: []const u8, target_machine_type: std.coff.IMAGE.FILE.MACHINE) ![]const []const u8 {
570fn getIncludePaths(
571 arena: Allocator,
572 io: Io,
573 auto_includes_option: cli.Options.AutoIncludes,
574 zig_lib_dir: []const u8,
575 target_machine_type: std.coff.IMAGE.FILE.MACHINE,
576) ![]const []const u8 {
560577 if (auto_includes_option == .none) return &[_][]const u8{};
561578
562579 const includes_arch: std.Target.Cpu.Arch = switch (target_machine_type) {
......@@ -626,7 +643,7 @@ fn getIncludePaths(arena: std.mem.Allocator, auto_includes_option: cli.Options.A
626643 .cpu_arch = includes_arch,
627644 .abi = .gnu,
628645 };
629 const target = std.zig.resolveTargetQueryOrFatal(target_query);
646 const target = std.zig.resolveTargetQueryOrFatal(io, target_query);
630647 const is_native_abi = target_query.isNativeAbi();
631648 const detected_libc = std.zig.LibCDirs.detect(arena, zig_lib_dir, &target, is_native_abi, true, null) catch |err| switch (err) {
632649 error.OutOfMemory => |e| return e,
......@@ -647,7 +664,7 @@ const ErrorHandler = union(enum) {
647664
648665 pub fn emitCliDiagnostics(
649666 self: *ErrorHandler,
650 allocator: std.mem.Allocator,
667 allocator: Allocator,
651668 args: []const []const u8,
652669 diagnostics: *cli.Diagnostics,
653670 ) !void {
......@@ -666,7 +683,7 @@ const ErrorHandler = union(enum) {
666683
667684 pub fn emitAroDiagnostics(
668685 self: *ErrorHandler,
669 allocator: std.mem.Allocator,
686 allocator: Allocator,
670687 fail_msg: []const u8,
671688 comp: *aro.Compilation,
672689 ) !void {
......@@ -692,7 +709,7 @@ const ErrorHandler = union(enum) {
692709
693710 pub fn emitDiagnostics(
694711 self: *ErrorHandler,
695 allocator: std.mem.Allocator,
712 allocator: Allocator,
696713 cwd: std.fs.Dir,
697714 source: []const u8,
698715 diagnostics: *Diagnostics,
......@@ -713,7 +730,7 @@ const ErrorHandler = union(enum) {
713730
714731 pub fn emitMessage(
715732 self: *ErrorHandler,
716 allocator: std.mem.Allocator,
733 allocator: Allocator,
717734 msg_type: @import("utils.zig").ErrorMessageType,
718735 comptime format: []const u8,
719736 args: anytype,
......@@ -738,7 +755,7 @@ const ErrorHandler = union(enum) {
738755};
739756
740757fn cliDiagnosticsToErrorBundle(
741 gpa: std.mem.Allocator,
758 gpa: Allocator,
742759 diagnostics: *cli.Diagnostics,
743760) !ErrorBundle {
744761 @branchHint(.cold);
......@@ -783,7 +800,7 @@ fn cliDiagnosticsToErrorBundle(
783800}
784801
785802fn diagnosticsToErrorBundle(
786 gpa: std.mem.Allocator,
803 gpa: Allocator,
787804 source: []const u8,
788805 diagnostics: *Diagnostics,
789806 mappings: SourceMappings,
......@@ -870,7 +887,7 @@ fn diagnosticsToErrorBundle(
870887 return try bundle.toOwnedBundle("");
871888}
872889
873fn errorStringToErrorBundle(allocator: std.mem.Allocator, comptime format: []const u8, args: anytype) !ErrorBundle {
890fn errorStringToErrorBundle(allocator: Allocator, comptime format: []const u8, args: anytype) !ErrorBundle {
874891 @branchHint(.cold);
875892 var bundle: ErrorBundle.Wip = undefined;
876893 try bundle.init(allocator);
lib/compiler/resinator/utils.zig+5-1
......@@ -26,7 +26,11 @@ pub const UncheckedSliceWriter = struct {
2626/// Cross-platform 'std.fs.Dir.openFile' wrapper that will always return IsDir if
2727/// a directory is attempted to be opened.
2828/// TODO: Remove once https://github.com/ziglang/zig/issues/5732 is addressed.
29pub fn openFileNotDir(cwd: std.fs.Dir, path: []const u8, flags: std.fs.File.OpenFlags) std.fs.File.OpenError!std.fs.File {
29pub fn openFileNotDir(
30 cwd: std.fs.Dir,
31 path: []const u8,
32 flags: std.fs.File.OpenFlags,
33) (std.fs.File.OpenError || std.fs.File.StatError)!std.fs.File {
3034 const file = try cwd.openFile(path, flags);
3135 errdefer file.close();
3236 // https://github.com/ziglang/zig/issues/5732