authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-04-14 10:07:16-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-07-01 16:35:26-07:00
loga21e7ab64f66c83c57b2d87b71c19d50d94ed543
tree9e47decd91c6bf7079344d2f40ca999d6dc043cf
parent1164d5ece5b12b573c6501c94b9ad9e326199ba9

build_runner: port to new `std.io.BufferedWriter` API


46 files changed, 818 insertions(+), 845 deletions(-)

build.zig+5-5
...@@ -279,7 +279,7 @@ pub fn build(b: *std.Build) !void {...@@ -279,7 +279,7 @@ pub fn build(b: *std.Build) !void {
279279
280 const ancestor_ver = try std.SemanticVersion.parse(tagged_ancestor);280 const ancestor_ver = try std.SemanticVersion.parse(tagged_ancestor);
281 if (zig_version.order(ancestor_ver) != .gt) {281 if (zig_version.order(ancestor_ver) != .gt) {
282 std.debug.print("Zig version '{}' must be greater than tagged ancestor '{}'\n", .{ zig_version, ancestor_ver });282 std.debug.print("Zig version '{f}' must be greater than tagged ancestor '{f}'\n", .{ zig_version, ancestor_ver });
283 std.process.exit(1);283 std.process.exit(1);
284 }284 }
285285
...@@ -304,7 +304,7 @@ pub fn build(b: *std.Build) !void {...@@ -304,7 +304,7 @@ pub fn build(b: *std.Build) !void {
304 if (enable_llvm) {304 if (enable_llvm) {
305 const cmake_cfg = if (static_llvm) null else blk: {305 const cmake_cfg = if (static_llvm) null else blk: {
306 if (findConfigH(b, config_h_path_option)) |config_h_path| {306 if (findConfigH(b, config_h_path_option)) |config_h_path| {
307 const file_contents = fs.cwd().readFileAlloc(b.allocator, config_h_path, max_config_h_bytes) catch unreachable;307 const file_contents = fs.cwd().readFileAlloc(config_h_path, b.allocator, .limited(max_config_h_bytes)) catch unreachable;
308 break :blk parseConfigH(b, file_contents);308 break :blk parseConfigH(b, file_contents);
309 } else {309 } else {
310 std.log.warn("config.h could not be located automatically. Consider providing it explicitly via \"-Dconfig_h\"", .{});310 std.log.warn("config.h could not be located automatically. Consider providing it explicitly via \"-Dconfig_h\"", .{});
...@@ -912,7 +912,7 @@ fn addCxxKnownPath(...@@ -912,7 +912,7 @@ fn addCxxKnownPath(
912 return error.RequiredLibraryNotFound;912 return error.RequiredLibraryNotFound;
913913
914 const path_padded = run: {914 const path_padded = run: {
915 var args = std.ArrayList([]const u8).init(b.allocator);915 var args: std.ArrayList([]const u8) = .init(b.allocator);
916 try args.append(ctx.cxx_compiler);916 try args.append(ctx.cxx_compiler);
917 var it = std.mem.tokenizeAny(u8, ctx.cxx_compiler_arg1, &std.ascii.whitespace);917 var it = std.mem.tokenizeAny(u8, ctx.cxx_compiler_arg1, &std.ascii.whitespace);
918 while (it.next()) |arg| try args.append(arg);918 while (it.next()) |arg| try args.append(arg);
...@@ -1418,7 +1418,7 @@ fn generateLangRef(b: *std.Build) std.Build.LazyPath {...@@ -1418,7 +1418,7 @@ fn generateLangRef(b: *std.Build) std.Build.LazyPath {
1418 });1418 });
14191419
1420 var dir = b.build_root.handle.openDir("doc/langref", .{ .iterate = true }) catch |err| {1420 var dir = b.build_root.handle.openDir("doc/langref", .{ .iterate = true }) catch |err| {
1421 std.debug.panic("unable to open '{}doc/langref' directory: {s}", .{1421 std.debug.panic("unable to open '{f}doc/langref' directory: {s}", .{
1422 b.build_root, @errorName(err),1422 b.build_root, @errorName(err),
1423 });1423 });
1424 };1424 };
...@@ -1439,7 +1439,7 @@ fn generateLangRef(b: *std.Build) std.Build.LazyPath {...@@ -1439,7 +1439,7 @@ fn generateLangRef(b: *std.Build) std.Build.LazyPath {
1439 // in a temporary directory1439 // in a temporary directory
1440 "--cache-root", b.cache_root.path orelse ".",1440 "--cache-root", b.cache_root.path orelse ".",
1441 });1441 });
1442 cmd.addArgs(&.{ "--zig-lib-dir", b.fmt("{}", .{b.graph.zig_lib_directory}) });1442 cmd.addArgs(&.{ "--zig-lib-dir", b.fmt("{f}", .{b.graph.zig_lib_directory}) });
1443 cmd.addArgs(&.{"-i"});1443 cmd.addArgs(&.{"-i"});
1444 cmd.addFileArg(b.path(b.fmt("doc/langref/{s}", .{entry.name})));1444 cmd.addFileArg(b.path(b.fmt("doc/langref/{s}", .{entry.name})));
14451445
lib/compiler/build_runner.zig+10-15
...@@ -330,7 +330,7 @@ pub fn main() !void {...@@ -330,7 +330,7 @@ pub fn main() !void {
330 }330 }
331 }331 }
332332
333 const stderr = std.io.getStdErr();333 const stderr: std.fs.File = .stderr();
334 const ttyconf = get_tty_conf(color, stderr);334 const ttyconf = get_tty_conf(color, stderr);
335 switch (ttyconf) {335 switch (ttyconf) {
336 .no_color => try graph.env_map.put("NO_COLOR", "1"),336 .no_color => try graph.env_map.put("NO_COLOR", "1"),
...@@ -365,7 +365,7 @@ pub fn main() !void {...@@ -365,7 +365,7 @@ pub fn main() !void {
365 .data = buffer.items,365 .data = buffer.items,
366 .flags = .{ .exclusive = true },366 .flags = .{ .exclusive = true },
367 }) catch |err| {367 }) catch |err| {
368 fatal("unable to write configuration results to '{}{s}': {s}", .{368 fatal("unable to write configuration results to '{f}{s}': {s}", .{
369 local_cache_directory, tmp_sub_path, @errorName(err),369 local_cache_directory, tmp_sub_path, @errorName(err),
370 });370 });
371 };371 };
...@@ -378,16 +378,11 @@ pub fn main() !void {...@@ -378,16 +378,11 @@ pub fn main() !void {
378378
379 validateSystemLibraryOptions(builder);379 validateSystemLibraryOptions(builder);
380380
381 var stdout_writer: std.io.BufferedWriter = .{381 {
382 .buffer = &stdout_buffer,382 var stdout_bw = std.fs.File.stdout().writer().buffered(&stdio_buffer);
383 .unbuffered_writer = std.io.getStdOut().writer(),383 if (help_menu) return usage(builder, &stdout_bw);
384 };384 if (steps_menu) return steps(builder, &stdout_bw);
385385 }
386 if (help_menu)
387 return usage(builder, &stdout_writer);
388
389 if (steps_menu)
390 return steps(builder, &stdout_writer);
391386
392 var run: Run = .{387 var run: Run = .{
393 .max_rss = max_rss,388 .max_rss = max_rss,
...@@ -699,7 +694,7 @@ fn runStepNames(...@@ -699,7 +694,7 @@ fn runStepNames(
699 const ttyconf = run.ttyconf;694 const ttyconf = run.ttyconf;
700695
701 if (run.summary != .none) {696 if (run.summary != .none) {
702 var bw = std.debug.lockStdErr2();697 var bw = std.debug.lockStdErr2(&stdio_buffer);
703 defer std.debug.unlockStdErr();698 defer std.debug.unlockStdErr();
704699
705 const total_count = success_count + failure_count + pending_count + skipped_count;700 const total_count = success_count + failure_count + pending_count + skipped_count;
...@@ -1131,7 +1126,7 @@ fn workerMakeOneStep(...@@ -1131,7 +1126,7 @@ fn workerMakeOneStep(
1131 const show_stderr = s.result_stderr.len > 0;1126 const show_stderr = s.result_stderr.len > 0;
11321127
1133 if (show_error_msgs or show_compile_errors or show_stderr) {1128 if (show_error_msgs or show_compile_errors or show_stderr) {
1134 var bw = std.debug.lockStdErr2();1129 var bw = std.debug.lockStdErr2(&stdio_buffer);
1135 defer std.debug.unlockStdErr();1130 defer std.debug.unlockStdErr();
11361131
1137 const gpa = b.allocator;1132 const gpa = b.allocator;
...@@ -1256,7 +1251,7 @@ fn steps(builder: *std.Build, bw: *std.io.BufferedWriter) !void {...@@ -1256,7 +1251,7 @@ fn steps(builder: *std.Build, bw: *std.io.BufferedWriter) !void {
1256 }1251 }
1257}1252}
12581253
1259var stdout_buffer: [256]u8 = undefined;1254var stdio_buffer: [256]u8 = undefined;
12601255
1261fn usage(b: *std.Build, bw: *std.io.BufferedWriter) !void {1256fn usage(b: *std.Build, bw: *std.io.BufferedWriter) !void {
1262 try bw.print(1257 try bw.print(
lib/std/Build.zig+7-7
...@@ -284,7 +284,7 @@ pub fn create(...@@ -284,7 +284,7 @@ pub fn create(
284 .h_dir = undefined,284 .h_dir = undefined,
285 .dest_dir = graph.env_map.get("DESTDIR"),285 .dest_dir = graph.env_map.get("DESTDIR"),
286 .install_tls = .{286 .install_tls = .{
287 .step = Step.init(.{287 .step = .init(.{
288 .id = TopLevelStep.base_id,288 .id = TopLevelStep.base_id,
289 .name = "install",289 .name = "install",
290 .owner = b,290 .owner = b,
...@@ -292,7 +292,7 @@ pub fn create(...@@ -292,7 +292,7 @@ pub fn create(
292 .description = "Copy build artifacts to prefix path",292 .description = "Copy build artifacts to prefix path",
293 },293 },
294 .uninstall_tls = .{294 .uninstall_tls = .{
295 .step = Step.init(.{295 .step = .init(.{
296 .id = TopLevelStep.base_id,296 .id = TopLevelStep.base_id,
297 .name = "uninstall",297 .name = "uninstall",
298 .owner = b,298 .owner = b,
...@@ -342,7 +342,7 @@ fn createChildOnly(...@@ -342,7 +342,7 @@ fn createChildOnly(
342 .graph = parent.graph,342 .graph = parent.graph,
343 .allocator = allocator,343 .allocator = allocator,
344 .install_tls = .{344 .install_tls = .{
345 .step = Step.init(.{345 .step = .init(.{
346 .id = TopLevelStep.base_id,346 .id = TopLevelStep.base_id,
347 .name = "install",347 .name = "install",
348 .owner = child,348 .owner = child,
...@@ -350,7 +350,7 @@ fn createChildOnly(...@@ -350,7 +350,7 @@ fn createChildOnly(
350 .description = "Copy build artifacts to prefix path",350 .description = "Copy build artifacts to prefix path",
351 },351 },
352 .uninstall_tls = .{352 .uninstall_tls = .{
353 .step = Step.init(.{353 .step = .init(.{
354 .id = TopLevelStep.base_id,354 .id = TopLevelStep.base_id,
355 .name = "uninstall",355 .name = "uninstall",
356 .owner = child,356 .owner = child,
...@@ -1525,7 +1525,7 @@ pub fn option(b: *Build, comptime T: type, name_raw: []const u8, description_raw...@@ -1525,7 +1525,7 @@ pub fn option(b: *Build, comptime T: type, name_raw: []const u8, description_raw
1525pub fn step(b: *Build, name: []const u8, description: []const u8) *Step {1525pub fn step(b: *Build, name: []const u8, description: []const u8) *Step {
1526 const step_info = b.allocator.create(TopLevelStep) catch @panic("OOM");1526 const step_info = b.allocator.create(TopLevelStep) catch @panic("OOM");
1527 step_info.* = .{1527 step_info.* = .{
1528 .step = Step.init(.{1528 .step = .init(.{
1529 .id = TopLevelStep.base_id,1529 .id = TopLevelStep.base_id,
1530 .name = name,1530 .name = name,
1531 .owner = b,1531 .owner = b,
...@@ -1745,7 +1745,7 @@ pub fn addUserInputOption(b: *Build, name_raw: []const u8, value_raw: []const u8...@@ -1745,7 +1745,7 @@ pub fn addUserInputOption(b: *Build, name_raw: []const u8, value_raw: []const u8
1745 return true;1745 return true;
1746 },1746 },
1747 .lazy_path, .lazy_path_list => {1747 .lazy_path, .lazy_path_list => {
1748 log.warn("the lazy path value type isn't added from the CLI, but somehow '{s}' is a .{}", .{ name, std.zig.fmtId(@tagName(gop.value_ptr.value)) });1748 log.warn("the lazy path value type isn't added from the CLI, but somehow '{s}' is a .{f}", .{ name, std.zig.fmtId(@tagName(gop.value_ptr.value)) });
1749 return true;1749 return true;
1750 },1750 },
1751 }1751 }
...@@ -2059,7 +2059,7 @@ pub fn runAllowFail(...@@ -2059,7 +2059,7 @@ pub fn runAllowFail(
2059 try Step.handleVerbose2(b, null, child.env_map, argv);2059 try Step.handleVerbose2(b, null, child.env_map, argv);
2060 try child.spawn();2060 try child.spawn();
20612061
2062 const stdout = child.stdout.?.reader().readAllAlloc(b.allocator, max_output_size) catch {2062 const stdout = child.stdout.?.readToEndAlloc(b.allocator, .limited(max_output_size)) catch {
2063 return error.ReadFailure;2063 return error.ReadFailure;
2064 };2064 };
2065 errdefer b.allocator.free(stdout);2065 errdefer b.allocator.free(stdout);
lib/std/Build/Cache.zig+2-2
...@@ -333,7 +333,7 @@ pub const Manifest = struct {...@@ -333,7 +333,7 @@ pub const Manifest = struct {
333 pub const Diagnostic = union(enum) {333 pub const Diagnostic = union(enum) {
334 none,334 none,
335 manifest_create: fs.File.OpenError,335 manifest_create: fs.File.OpenError,
336 manifest_read: fs.File.ReadError,336 manifest_read: anyerror,
337 manifest_lock: fs.File.LockError,337 manifest_lock: fs.File.LockError,
338 manifest_seek: fs.File.SeekError,338 manifest_seek: fs.File.SeekError,
339 file_open: FileOp,339 file_open: FileOp,
...@@ -1062,7 +1062,7 @@ pub const Manifest = struct {...@@ -1062,7 +1062,7 @@ pub const Manifest = struct {
10621062
1063 fn addDepFileMaybePost(self: *Manifest, dir: fs.Dir, dep_file_basename: []const u8) !void {1063 fn addDepFileMaybePost(self: *Manifest, dir: fs.Dir, dep_file_basename: []const u8) !void {
1064 const gpa = self.cache.gpa;1064 const gpa = self.cache.gpa;
1065 const dep_file_contents = try dir.readFileAlloc(gpa, dep_file_basename, manifest_file_size_max);1065 const dep_file_contents = try dir.readFileAlloc(dep_file_basename, gpa, .limited(manifest_file_size_max));
1066 defer gpa.free(dep_file_contents);1066 defer gpa.free(dep_file_contents);
10671067
1068 var error_buf: std.ArrayListUnmanaged(u8) = .empty;1068 var error_buf: std.ArrayListUnmanaged(u8) = .empty;
lib/std/Build/Cache/Directory.zig+3-5
...@@ -57,15 +57,13 @@ pub fn closeAndFree(self: *Directory, gpa: Allocator) void {...@@ -57,15 +57,13 @@ pub fn closeAndFree(self: *Directory, gpa: Allocator) void {
5757
58pub fn format(58pub fn format(
59 self: Directory,59 self: Directory,
60 bw: *std.io.BufferedWriter,
60 comptime fmt_string: []const u8,61 comptime fmt_string: []const u8,
61 options: fmt.FormatOptions,
62 writer: anytype,
63) !void {62) !void {
64 _ = options;
65 if (fmt_string.len != 0) fmt.invalidFmtError(fmt_string, self);63 if (fmt_string.len != 0) fmt.invalidFmtError(fmt_string, self);
66 if (self.path) |p| {64 if (self.path) |p| {
67 try writer.writeAll(p);65 try bw.writeAll(p);
68 try writer.writeAll(fs.path.sep_str);66 try bw.writeAll(fs.path.sep_str);
69 }67 }
70}68}
7169
lib/std/Build/Cache/Path.zig+10-11
...@@ -142,9 +142,8 @@ pub fn toStringZ(p: Path, allocator: Allocator) Allocator.Error![:0]u8 {...@@ -142,9 +142,8 @@ pub fn toStringZ(p: Path, allocator: Allocator) Allocator.Error![:0]u8 {
142142
143pub fn format(143pub fn format(
144 self: Path,144 self: Path,
145 bw: *std.io.BufferedWriter,
145 comptime fmt_string: []const u8,146 comptime fmt_string: []const u8,
146 options: std.fmt.FormatOptions,
147 writer: anytype,
148) !void {147) !void {
149 if (fmt_string.len == 1) {148 if (fmt_string.len == 1) {
150 // Quote-escape the string.149 // Quote-escape the string.
...@@ -155,33 +154,33 @@ pub fn format(...@@ -155,33 +154,33 @@ pub fn format(
155 else => @compileError("unsupported format string: " ++ fmt_string),154 else => @compileError("unsupported format string: " ++ fmt_string),
156 };155 };
157 if (self.root_dir.path) |p| {156 if (self.root_dir.path) |p| {
158 try stringEscape(p, f, options, writer);157 try stringEscape(p, bw, f);
159 if (self.sub_path.len > 0) try stringEscape(fs.path.sep_str, f, options, writer);158 if (self.sub_path.len > 0) try stringEscape(fs.path.sep_str, bw, f);
160 }159 }
161 if (self.sub_path.len > 0) {160 if (self.sub_path.len > 0) {
162 try stringEscape(self.sub_path, f, options, writer);161 try stringEscape(self.sub_path, bw, f);
163 }162 }
164 return;163 return;
165 }164 }
166 if (fmt_string.len > 0)165 if (fmt_string.len > 0)
167 std.fmt.invalidFmtError(fmt_string, self);166 std.fmt.invalidFmtError(fmt_string, self);
168 if (std.fs.path.isAbsolute(self.sub_path)) {167 if (std.fs.path.isAbsolute(self.sub_path)) {
169 try writer.writeAll(self.sub_path);168 try bw.writeAll(self.sub_path);
170 return;169 return;
171 }170 }
172 if (self.root_dir.path) |p| {171 if (self.root_dir.path) |p| {
173 try writer.writeAll(p);172 try bw.writeAll(p);
174 if (self.sub_path.len > 0) {173 if (self.sub_path.len > 0) {
175 try writer.writeAll(fs.path.sep_str);174 try bw.writeAll(fs.path.sep_str);
176 try writer.writeAll(self.sub_path);175 try bw.writeAll(self.sub_path);
177 }176 }
178 return;177 return;
179 }178 }
180 if (self.sub_path.len > 0) {179 if (self.sub_path.len > 0) {
181 try writer.writeAll(self.sub_path);180 try bw.writeAll(self.sub_path);
182 return;181 return;
183 }182 }
184 try writer.writeByte('.');183 try bw.writeByte('.');
185}184}
186185
187pub fn eql(self: Path, other: Path) bool {186pub fn eql(self: Path, other: Path) bool {
lib/std/Build/Fuzz/WebServer.zig+15-18
...@@ -169,8 +169,8 @@ fn serveFile(...@@ -169,8 +169,8 @@ fn serveFile(
169 // The desired API is actually sendfile, which will require enhancing std.http.Server.169 // The desired API is actually sendfile, which will require enhancing std.http.Server.
170 // We load the file with every request so that the user can make changes to the file170 // We load the file with every request so that the user can make changes to the file
171 // and refresh the HTML page without restarting this server.171 // and refresh the HTML page without restarting this server.
172 const file_contents = ws.zig_lib_directory.handle.readFileAlloc(gpa, name, 10 * 1024 * 1024) catch |err| {172 const file_contents = ws.zig_lib_directory.handle.readFileAlloc(name, gpa, .limited(10 * 1024 * 1024)) catch |err| {
173 log.err("failed to read '{}{s}': {s}", .{ ws.zig_lib_directory, name, @errorName(err) });173 log.err("failed to read '{f}{s}': {s}", .{ ws.zig_lib_directory, name, @errorName(err) });
174 return error.AlreadyReported;174 return error.AlreadyReported;
175 };175 };
176 defer gpa.free(file_contents);176 defer gpa.free(file_contents);
...@@ -206,7 +206,7 @@ fn serveWasm(...@@ -206,7 +206,7 @@ fn serveWasm(
206 });206 });
207 // std.http.Server does not have a sendfile API yet.207 // std.http.Server does not have a sendfile API yet.
208 const bin_path = try wasm_base_path.join(arena, bin_name);208 const bin_path = try wasm_base_path.join(arena, bin_name);
209 const file_contents = try bin_path.root_dir.handle.readFileAlloc(gpa, bin_path.sub_path, 10 * 1024 * 1024);209 const file_contents = try bin_path.root_dir.handle.readFileAlloc(bin_path.sub_path, gpa, .limited(10 * 1024 * 1024));
210 defer gpa.free(file_contents);210 defer gpa.free(file_contents);
211 try request.respond(file_contents, .{211 try request.respond(file_contents, .{
212 .extra_headers = &.{212 .extra_headers = &.{
...@@ -251,10 +251,10 @@ fn buildWasmBinary(...@@ -251,10 +251,10 @@ fn buildWasmBinary(
251 "-fsingle-threaded", //251 "-fsingle-threaded", //
252 "--dep", "Walk", //252 "--dep", "Walk", //
253 "--dep", "html_render", //253 "--dep", "html_render", //
254 try std.fmt.allocPrint(arena, "-Mroot={}", .{main_src_path}), //254 try std.fmt.allocPrint(arena, "-Mroot={f}", .{main_src_path}), //
255 try std.fmt.allocPrint(arena, "-MWalk={}", .{walk_src_path}), //255 try std.fmt.allocPrint(arena, "-MWalk={f}", .{walk_src_path}), //
256 "--dep", "Walk", //256 "--dep", "Walk", //
257 try std.fmt.allocPrint(arena, "-Mhtml_render={}", .{html_render_src_path}), //257 try std.fmt.allocPrint(arena, "-Mhtml_render={f}", .{html_render_src_path}), //
258 "--listen=-",258 "--listen=-",
259 });259 });
260260
...@@ -280,13 +280,10 @@ fn buildWasmBinary(...@@ -280,13 +280,10 @@ fn buildWasmBinary(
280 const stdout = poller.fifo(.stdout);280 const stdout = poller.fifo(.stdout);
281281
282 poll: while (true) {282 poll: while (true) {
283 while (stdout.readableLength() < @sizeOf(Header)) {283 while (stdout.readableLength() < @sizeOf(Header)) if (!try poller.poll()) break :poll;
284 if (!(try poller.poll())) break :poll;284 var header: Header = undefined;
285 }285 assert(stdout.read(std.mem.asBytes(&header)) == @sizeOf(Header));
286 const header = stdout.reader().readStruct(Header) catch unreachable;286 while (stdout.readableLength() < header.bytes_len) if (!try poller.poll()) break :poll;
287 while (stdout.readableLength() < header.bytes_len) {
288 if (!(try poller.poll())) break :poll;
289 }
290 const body = stdout.readableSliceOfLen(header.bytes_len);287 const body = stdout.readableSliceOfLen(header.bytes_len);
291288
292 switch (header.tag) {289 switch (header.tag) {
...@@ -527,7 +524,7 @@ fn serveSourcesTar(ws: *WebServer, request: *std.http.Server.Request) !void {...@@ -527,7 +524,7 @@ fn serveSourcesTar(ws: *WebServer, request: *std.http.Server.Request) !void {
527524
528 for (deduped_paths) |joined_path| {525 for (deduped_paths) |joined_path| {
529 var file = joined_path.root_dir.handle.openFile(joined_path.sub_path, .{}) catch |err| {526 var file = joined_path.root_dir.handle.openFile(joined_path.sub_path, .{}) catch |err| {
530 log.err("failed to open {}: {s}", .{ joined_path, @errorName(err) });527 log.err("failed to open {f}: {s}", .{ joined_path, @errorName(err) });
531 continue;528 continue;
532 };529 };
533 defer file.close();530 defer file.close();
...@@ -605,7 +602,7 @@ fn prepareTables(...@@ -605,7 +602,7 @@ fn prepareTables(
605602
606 const rebuilt_exe_path = run_step.rebuilt_executable.?;603 const rebuilt_exe_path = run_step.rebuilt_executable.?;
607 var debug_info = std.debug.Info.load(gpa, rebuilt_exe_path, &gop.value_ptr.coverage) catch |err| {604 var debug_info = std.debug.Info.load(gpa, rebuilt_exe_path, &gop.value_ptr.coverage) catch |err| {
608 log.err("step '{s}': failed to load debug information for '{}': {s}", .{605 log.err("step '{s}': failed to load debug information for '{f}': {s}", .{
609 run_step.step.name, rebuilt_exe_path, @errorName(err),606 run_step.step.name, rebuilt_exe_path, @errorName(err),
610 });607 });
611 return error.AlreadyReported;608 return error.AlreadyReported;
...@@ -617,7 +614,7 @@ fn prepareTables(...@@ -617,7 +614,7 @@ fn prepareTables(
617 .sub_path = "v/" ++ std.fmt.hex(coverage_id),614 .sub_path = "v/" ++ std.fmt.hex(coverage_id),
618 };615 };
619 var coverage_file = coverage_file_path.root_dir.handle.openFile(coverage_file_path.sub_path, .{}) catch |err| {616 var coverage_file = coverage_file_path.root_dir.handle.openFile(coverage_file_path.sub_path, .{}) catch |err| {
620 log.err("step '{s}': failed to load coverage file '{}': {s}", .{617 log.err("step '{s}': failed to load coverage file '{f}': {s}", .{
621 run_step.step.name, coverage_file_path, @errorName(err),618 run_step.step.name, coverage_file_path, @errorName(err),
622 });619 });
623 return error.AlreadyReported;620 return error.AlreadyReported;
...@@ -625,7 +622,7 @@ fn prepareTables(...@@ -625,7 +622,7 @@ fn prepareTables(
625 defer coverage_file.close();622 defer coverage_file.close();
626623
627 const file_size = coverage_file.getEndPos() catch |err| {624 const file_size = coverage_file.getEndPos() catch |err| {
628 log.err("unable to check len of coverage file '{}': {s}", .{ coverage_file_path, @errorName(err) });625 log.err("unable to check len of coverage file '{f}': {s}", .{ coverage_file_path, @errorName(err) });
629 return error.AlreadyReported;626 return error.AlreadyReported;
630 };627 };
631628
...@@ -637,7 +634,7 @@ fn prepareTables(...@@ -637,7 +634,7 @@ fn prepareTables(
637 coverage_file.handle,634 coverage_file.handle,
638 0,635 0,
639 ) catch |err| {636 ) catch |err| {
640 log.err("failed to map coverage file '{}': {s}", .{ coverage_file_path, @errorName(err) });637 log.err("failed to map coverage file '{f}': {s}", .{ coverage_file_path, @errorName(err) });
641 return error.AlreadyReported;638 return error.AlreadyReported;
642 };639 };
643 gop.value_ptr.mapped_memory = mapped_memory;640 gop.value_ptr.mapped_memory = mapped_memory;
lib/std/Build/Step.zig+4-7
...@@ -516,13 +516,10 @@ fn zigProcessUpdate(s: *Step, zp: *ZigProcess, watch: bool) !?Path {...@@ -516,13 +516,10 @@ fn zigProcessUpdate(s: *Step, zp: *ZigProcess, watch: bool) !?Path {
516 const stdout = zp.poller.fifo(.stdout);516 const stdout = zp.poller.fifo(.stdout);
517517
518 poll: while (true) {518 poll: while (true) {
519 while (stdout.readableLength() < @sizeOf(Header)) {519 while (stdout.readableLength() < @sizeOf(Header)) if (!try zp.poller.poll()) break :poll;
520 if (!(try zp.poller.poll())) break :poll;520 var header: Header = undefined;
521 }521 assert(stdout.read(std.mem.asBytes(&header)) == @sizeOf(Header));
522 const header = stdout.reader().readStruct(Header) catch unreachable;522 while (stdout.readableLength() < header.bytes_len) if (!try zp.poller.poll()) break :poll;
523 while (stdout.readableLength() < header.bytes_len) {
524 if (!(try zp.poller.poll())) break :poll;
525 }
526 const body = stdout.readableSliceOfLen(header.bytes_len);523 const body = stdout.readableSliceOfLen(header.bytes_len);
527524
528 switch (header.tag) {525 switch (header.tag) {
lib/std/Build/Step/CheckFile.zig+2-2
...@@ -28,7 +28,7 @@ pub fn create(...@@ -28,7 +28,7 @@ pub fn create(
28) *CheckFile {28) *CheckFile {
29 const check_file = owner.allocator.create(CheckFile) catch @panic("OOM");29 const check_file = owner.allocator.create(CheckFile) catch @panic("OOM");
30 check_file.* = .{30 check_file.* = .{
31 .step = Step.init(.{31 .step = .init(.{
32 .id = base_id,32 .id = base_id,
33 .name = "CheckFile",33 .name = "CheckFile",
34 .owner = owner,34 .owner = owner,
...@@ -53,7 +53,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {...@@ -53,7 +53,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
53 try step.singleUnchangingWatchInput(check_file.source);53 try step.singleUnchangingWatchInput(check_file.source);
5454
55 const src_path = check_file.source.getPath2(b, step);55 const src_path = check_file.source.getPath2(b, step);
56 const contents = fs.cwd().readFileAlloc(b.allocator, src_path, check_file.max_bytes) catch |err| {56 const contents = fs.cwd().readFileAlloc(src_path, b.allocator, .limited(check_file.max_bytes)) catch |err| {
57 return step.fail("unable to read '{s}': {s}", .{57 return step.fail("unable to read '{s}': {s}", .{
58 src_path, @errorName(err),58 src_path, @errorName(err),
59 });59 });
lib/std/Build/Step/CheckObject.zig+300-401
...@@ -28,14 +28,14 @@ pub fn create(...@@ -28,14 +28,14 @@ pub fn create(
28 const gpa = owner.allocator;28 const gpa = owner.allocator;
29 const check_object = gpa.create(CheckObject) catch @panic("OOM");29 const check_object = gpa.create(CheckObject) catch @panic("OOM");
30 check_object.* = .{30 check_object.* = .{
31 .step = Step.init(.{31 .step = .init(.{
32 .id = base_id,32 .id = base_id,
33 .name = "CheckObject",33 .name = "CheckObject",
34 .owner = owner,34 .owner = owner,
35 .makeFn = make,35 .makeFn = make,
36 }),36 }),
37 .source = source.dupe(owner),37 .source = source.dupe(owner),
38 .checks = std.ArrayList(Check).init(gpa),38 .checks = .init(gpa),
39 .obj_format = obj_format,39 .obj_format = obj_format,
40 };40 };
41 check_object.source.addStepDependencies(&check_object.step);41 check_object.source.addStepDependencies(&check_object.step);
...@@ -74,13 +74,13 @@ const Action = struct {...@@ -74,13 +74,13 @@ const Action = struct {
74 b: *std.Build,74 b: *std.Build,
75 step: *Step,75 step: *Step,
76 haystack: []const u8,76 haystack: []const u8,
77 global_vars: anytype,77 global_vars: *std.StringHashMap(u64),
78 ) !bool {78 ) !bool {
79 assert(act.tag == .extract);79 assert(act.tag == .extract);
80 const hay = mem.trim(u8, haystack, " ");80 const hay = mem.trim(u8, haystack, " ");
81 const phrase = mem.trim(u8, act.phrase.resolve(b, step), " ");81 const phrase = mem.trim(u8, act.phrase.resolve(b, step), " ");
8282
83 var candidate_vars = std.ArrayList(struct { name: []const u8, value: u64 }).init(b.allocator);83 var candidate_vars: std.ArrayList(struct { name: []const u8, value: u64 }) = .init(b.allocator);
84 var hay_it = mem.tokenizeScalar(u8, hay, ' ');84 var hay_it = mem.tokenizeScalar(u8, hay, ' ');
85 var needle_it = mem.tokenizeScalar(u8, phrase, ' ');85 var needle_it = mem.tokenizeScalar(u8, phrase, ' ');
8686
...@@ -153,11 +153,11 @@ const Action = struct {...@@ -153,11 +153,11 @@ const Action = struct {
153 /// Will return true if the `phrase` is correctly parsed into an RPN program and153 /// Will return true if the `phrase` is correctly parsed into an RPN program and
154 /// its reduced, computed value compares using `op` with the expected value, either154 /// its reduced, computed value compares using `op` with the expected value, either
155 /// a literal or another extracted variable.155 /// a literal or another extracted variable.
156 fn computeCmp(act: Action, b: *std.Build, step: *Step, global_vars: anytype) !bool {156 fn computeCmp(act: Action, b: *std.Build, step: *Step, global_vars: std.StringHashMap(u64)) !bool {
157 const gpa = step.owner.allocator;157 const gpa = step.owner.allocator;
158 const phrase = act.phrase.resolve(b, step);158 const phrase = act.phrase.resolve(b, step);
159 var op_stack = std.ArrayList(enum { add, sub, mod, mul }).init(gpa);159 var op_stack: std.ArrayList(enum { add, sub, mod, mul }) = .init(gpa);
160 var values = std.ArrayList(u64).init(gpa);160 var values: std.ArrayList(u64) = .init(gpa);
161161
162 var it = mem.tokenizeScalar(u8, phrase, ' ');162 var it = mem.tokenizeScalar(u8, phrase, ' ');
163 while (it.next()) |next| {163 while (it.next()) |next| {
...@@ -230,17 +230,15 @@ const ComputeCompareExpected = struct {...@@ -230,17 +230,15 @@ const ComputeCompareExpected = struct {
230 },230 },
231231
232 pub fn format(232 pub fn format(
233 value: @This(),233 value: ComputeCompareExpected,
234 bw: *std.io.BufferedWriter,
234 comptime fmt: []const u8,235 comptime fmt: []const u8,
235 options: std.fmt.FormatOptions,236 ) anyerror!void {
236 writer: anytype,
237 ) !void {
238 if (fmt.len != 0) std.fmt.invalidFmtError(fmt, value);237 if (fmt.len != 0) std.fmt.invalidFmtError(fmt, value);
239 _ = options;238 try bw.print("{s} ", .{@tagName(value.op)});
240 try writer.print("{s} ", .{@tagName(value.op)});
241 switch (value.value) {239 switch (value.value) {
242 .variable => |name| try writer.writeAll(name),240 .variable => |name| try bw.writeAll(name),
243 .literal => |x| try writer.print("{x}", .{x}),241 .literal => |x| try bw.print("{x}", .{x}),
244 }242 }
245 }243 }
246};244};
...@@ -566,15 +564,15 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {...@@ -566,15 +564,15 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {
566564
567 const src_path = check_object.source.getPath3(b, step);565 const src_path = check_object.source.getPath3(b, step);
568 const contents = src_path.root_dir.handle.readFileAllocOptions(566 const contents = src_path.root_dir.handle.readFileAllocOptions(
569 gpa,
570 src_path.sub_path,567 src_path.sub_path,
571 check_object.max_bytes,568 gpa,
569 .limited(check_object.max_bytes),
572 null,570 null,
573 .of(u64),571 .of(u64),
574 null,572 null,
575 ) catch |err| return step.fail("unable to read '{'}': {s}", .{ src_path, @errorName(err) });573 ) catch |err| return step.fail("unable to read '{f'}': {s}", .{ src_path, @errorName(err) });
576574
577 var vars = std.StringHashMap(u64).init(gpa);575 var vars: std.StringHashMap(u64) = .init(gpa);
578 for (check_object.checks.items) |chk| {576 for (check_object.checks.items) |chk| {
579 if (chk.kind == .compute_compare) {577 if (chk.kind == .compute_compare) {
580 assert(chk.actions.items.len == 1);578 assert(chk.actions.items.len == 1);
...@@ -588,7 +586,7 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {...@@ -588,7 +586,7 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {
588 return step.fail(586 return step.fail(
589 \\587 \\
590 \\========= comparison failed for action: ===========588 \\========= comparison failed for action: ===========
591 \\{s} {}589 \\{s} {f}
592 \\===================================================590 \\===================================================
593 , .{ act.phrase.resolve(b, step), act.expected.? });591 , .{ act.phrase.resolve(b, step), act.expected.? });
594 }592 }
...@@ -621,15 +619,13 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {...@@ -621,15 +619,13 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {
621619
622 fn formatMessageString(620 fn formatMessageString(
623 ctx: Ctx,621 ctx: Ctx,
622 bw: *std.io.BufferedWriter,
624 comptime unused_fmt_string: []const u8,623 comptime unused_fmt_string: []const u8,
625 options: std.fmt.FormatOptions,
626 writer: anytype,
627 ) !void {624 ) !void {
628 _ = unused_fmt_string;625 _ = unused_fmt_string;
629 _ = options;
630 switch (ctx.kind) {626 switch (ctx.kind) {
631 .dump_section => try writer.print("{s}", .{std.fmt.fmtSliceEscapeLower(ctx.msg)}),627 .dump_section => try bw.print("{f}", .{std.fmt.fmtSliceEscapeLower(ctx.msg)}),
632 else => try writer.writeAll(ctx.msg),628 else => try bw.writeAll(ctx.msg),
633 }629 }
634 }630 }
635 }.fmtMessageString;631 }.fmtMessageString;
...@@ -644,11 +640,11 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {...@@ -644,11 +640,11 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {
644 return step.fail(640 return step.fail(
645 \\641 \\
646 \\========= expected to find: ==========================642 \\========= expected to find: ==========================
647 \\{s}643 \\{f}
648 \\========= but parsed file does not contain it: =======644 \\========= but parsed file does not contain it: =======
649 \\{s}645 \\{f}
650 \\========= file path: =================================646 \\========= file path: =================================
651 \\{}647 \\{f}
652 , .{648 , .{
653 fmtMessageString(chk.kind, act.phrase.resolve(b, step)),649 fmtMessageString(chk.kind, act.phrase.resolve(b, step)),
654 fmtMessageString(chk.kind, output),650 fmtMessageString(chk.kind, output),
...@@ -664,11 +660,11 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {...@@ -664,11 +660,11 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {
664 return step.fail(660 return step.fail(
665 \\661 \\
666 \\========= expected to find: ==========================662 \\========= expected to find: ==========================
667 \\*{s}*663 \\*{f}*
668 \\========= but parsed file does not contain it: =======664 \\========= but parsed file does not contain it: =======
669 \\{s}665 \\{f}
670 \\========= file path: =================================666 \\========= file path: =================================
671 \\{}667 \\{f}
672 , .{668 , .{
673 fmtMessageString(chk.kind, act.phrase.resolve(b, step)),669 fmtMessageString(chk.kind, act.phrase.resolve(b, step)),
674 fmtMessageString(chk.kind, output),670 fmtMessageString(chk.kind, output),
...@@ -683,11 +679,11 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {...@@ -683,11 +679,11 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {
683 return step.fail(679 return step.fail(
684 \\680 \\
685 \\========= expected not to find: ===================681 \\========= expected not to find: ===================
686 \\{s}682 \\{f}
687 \\========= but parsed file does contain it: ========683 \\========= but parsed file does contain it: ========
688 \\{s}684 \\{f}
689 \\========= file path: ==============================685 \\========= file path: ==============================
690 \\{}686 \\{f}
691 , .{687 , .{
692 fmtMessageString(chk.kind, act.phrase.resolve(b, step)),688 fmtMessageString(chk.kind, act.phrase.resolve(b, step)),
693 fmtMessageString(chk.kind, output),689 fmtMessageString(chk.kind, output),
...@@ -703,13 +699,13 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {...@@ -703,13 +699,13 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {
703 return step.fail(699 return step.fail(
704 \\700 \\
705 \\========= expected to find and extract: ==============701 \\========= expected to find and extract: ==============
706 \\{s}702 \\{f}
707 \\========= but parsed file does not contain it: =======703 \\========= but parsed file does not contain it: =======
708 \\{s}704 \\{f}
709 \\========= file path: ==============================705 \\========= file path: ==============================
710 \\{}706 \\{f}
711 , .{707 , .{
712 act.phrase.resolve(b, step),708 fmtMessageString(chk.kind, act.phrase.resolve(b, step)),
713 fmtMessageString(chk.kind, output),709 fmtMessageString(chk.kind, output),
714 src_path,710 src_path,
715 });711 });
...@@ -762,14 +758,14 @@ const MachODumper = struct {...@@ -762,14 +758,14 @@ const MachODumper = struct {
762 },758 },
763 .SYMTAB => {759 .SYMTAB => {
764 const lc = cmd.cast(macho.symtab_command).?;760 const lc = cmd.cast(macho.symtab_command).?;
765 const symtab = @as([*]align(1) const macho.nlist_64, @ptrCast(ctx.data.ptr + lc.symoff))[0..lc.nsyms];761 const symtab = @as([*]align(1) const macho.nlist_64, @ptrCast(ctx.data[lc.symoff..].ptr))[0..lc.nsyms];
766 const strtab = ctx.data[lc.stroff..][0..lc.strsize];762 const strtab = ctx.data[lc.stroff..][0..lc.strsize];
767 try ctx.symtab.appendUnalignedSlice(ctx.gpa, symtab);763 try ctx.symtab.appendUnalignedSlice(ctx.gpa, symtab);
768 try ctx.strtab.appendSlice(ctx.gpa, strtab);764 try ctx.strtab.appendSlice(ctx.gpa, strtab);
769 },765 },
770 .DYSYMTAB => {766 .DYSYMTAB => {
771 const lc = cmd.cast(macho.dysymtab_command).?;767 const lc = cmd.cast(macho.dysymtab_command).?;
772 const indexes = @as([*]align(1) const u32, @ptrCast(ctx.data.ptr + lc.indirectsymoff))[0..lc.nindirectsyms];768 const indexes = @as([*]align(1) const u32, @ptrCast(ctx.data[lc.indirectsymoff..].ptr))[0..lc.nindirectsyms];
773 try ctx.indsymtab.appendUnalignedSlice(ctx.gpa, indexes);769 try ctx.indsymtab.appendUnalignedSlice(ctx.gpa, indexes);
774 },770 },
775 .LOAD_DYLIB,771 .LOAD_DYLIB,
...@@ -787,7 +783,7 @@ const MachODumper = struct {...@@ -787,7 +783,7 @@ const MachODumper = struct {
787783
788 fn getString(ctx: ObjectContext, off: u32) [:0]const u8 {784 fn getString(ctx: ObjectContext, off: u32) [:0]const u8 {
789 assert(off < ctx.strtab.items.len);785 assert(off < ctx.strtab.items.len);
790 return mem.sliceTo(@as([*:0]const u8, @ptrCast(ctx.strtab.items.ptr + off)), 0);786 return mem.sliceTo(@as([*:0]const u8, @ptrCast(ctx.strtab.items[off..].ptr)), 0);
791 }787 }
792788
793 fn getLoadCommandIterator(ctx: ObjectContext) macho.LoadCommandIterator {789 fn getLoadCommandIterator(ctx: ObjectContext) macho.LoadCommandIterator {
...@@ -1232,7 +1228,7 @@ const MachODumper = struct {...@@ -1232,7 +1228,7 @@ const MachODumper = struct {
1232 }1228 }
12331229
1234 fn dumpRebaseInfo(ctx: ObjectContext, data: []const u8, bw: *std.io.BufferedWriter) !void {1230 fn dumpRebaseInfo(ctx: ObjectContext, data: []const u8, bw: *std.io.BufferedWriter) !void {
1235 var rebases = std.ArrayList(u64).init(ctx.gpa);1231 var rebases: std.ArrayList(u64) = .init(ctx.gpa);
1236 defer rebases.deinit();1232 defer rebases.deinit();
1237 try ctx.parseRebaseInfo(data, &rebases);1233 try ctx.parseRebaseInfo(data, &rebases);
1238 mem.sort(u64, rebases.items, {}, std.sort.asc(u64));1234 mem.sort(u64, rebases.items, {}, std.sort.asc(u64));
...@@ -1242,14 +1238,13 @@ const MachODumper = struct {...@@ -1242,14 +1238,13 @@ const MachODumper = struct {
1242 }1238 }
12431239
1244 fn parseRebaseInfo(ctx: ObjectContext, data: []const u8, rebases: *std.ArrayList(u64)) !void {1240 fn parseRebaseInfo(ctx: ObjectContext, data: []const u8, rebases: *std.ArrayList(u64)) !void {
1245 var stream: std.io.FixedBufferStream = .{ .buffer = data };1241 var br: std.io.BufferedReader = undefined;
1246 var creader = std.io.countingReader(stream.reader());1242 br.initFixed(data);
1247 const reader = creader.reader();
12481243
1249 var seg_id: ?u8 = null;1244 var seg_id: ?u8 = null;
1250 var offset: u64 = 0;1245 var offset: u64 = 0;
1251 while (true) {1246 while (true) {
1252 const byte = reader.readByte() catch break;1247 const byte = br.takeByte() catch break;
1253 const opc = byte & macho.REBASE_OPCODE_MASK;1248 const opc = byte & macho.REBASE_OPCODE_MASK;
1254 const imm = byte & macho.REBASE_IMMEDIATE_MASK;1249 const imm = byte & macho.REBASE_IMMEDIATE_MASK;
1255 switch (opc) {1250 switch (opc) {
...@@ -1257,17 +1252,17 @@ const MachODumper = struct {...@@ -1257,17 +1252,17 @@ const MachODumper = struct {
1257 macho.REBASE_OPCODE_SET_TYPE_IMM => {},1252 macho.REBASE_OPCODE_SET_TYPE_IMM => {},
1258 macho.REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB => {1253 macho.REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB => {
1259 seg_id = imm;1254 seg_id = imm;
1260 offset = try std.leb.readUleb128(u64, reader);1255 offset = try br.takeLeb128(u64);
1261 },1256 },
1262 macho.REBASE_OPCODE_ADD_ADDR_IMM_SCALED => {1257 macho.REBASE_OPCODE_ADD_ADDR_IMM_SCALED => {
1263 offset += imm * @sizeOf(u64);1258 offset += imm * @sizeOf(u64);
1264 },1259 },
1265 macho.REBASE_OPCODE_ADD_ADDR_ULEB => {1260 macho.REBASE_OPCODE_ADD_ADDR_ULEB => {
1266 const addend = try std.leb.readUleb128(u64, reader);1261 const addend = try br.takeLeb128(u64);
1267 offset += addend;1262 offset += addend;
1268 },1263 },
1269 macho.REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB => {1264 macho.REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB => {
1270 const addend = try std.leb.readUleb128(u64, reader);1265 const addend = try br.takeLeb128(u64);
1271 const seg = ctx.segments.items[seg_id.?];1266 const seg = ctx.segments.items[seg_id.?];
1272 const addr = seg.vmaddr + offset;1267 const addr = seg.vmaddr + offset;
1273 try rebases.append(addr);1268 try rebases.append(addr);
...@@ -1284,11 +1279,11 @@ const MachODumper = struct {...@@ -1284,11 +1279,11 @@ const MachODumper = struct {
1284 ntimes = imm;1279 ntimes = imm;
1285 },1280 },
1286 macho.REBASE_OPCODE_DO_REBASE_ULEB_TIMES => {1281 macho.REBASE_OPCODE_DO_REBASE_ULEB_TIMES => {
1287 ntimes = try std.leb.readUleb128(u64, reader);1282 ntimes = try br.takeLeb128(u64);
1288 },1283 },
1289 macho.REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB => {1284 macho.REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB => {
1290 ntimes = try std.leb.readUleb128(u64, reader);1285 ntimes = try br.takeLeb128(u64);
1291 skip = try std.leb.readUleb128(u64, reader);1286 skip = try br.takeLeb128(u64);
1292 },1287 },
1293 else => unreachable,1288 else => unreachable,
1294 }1289 }
...@@ -1331,7 +1326,7 @@ const MachODumper = struct {...@@ -1331,7 +1326,7 @@ const MachODumper = struct {
1331 };1326 };
13321327
1333 fn dumpBindInfo(ctx: ObjectContext, data: []const u8, bw: *std.io.BufferedWriter) !void {1328 fn dumpBindInfo(ctx: ObjectContext, data: []const u8, bw: *std.io.BufferedWriter) !void {
1334 var bindings = std.ArrayList(Binding).init(ctx.gpa);1329 var bindings: std.ArrayList(Binding) = .init(ctx.gpa);
1335 defer {1330 defer {
1336 for (bindings.items) |*b| {1331 for (bindings.items) |*b| {
1337 b.deinit(ctx.gpa);1332 b.deinit(ctx.gpa);
...@@ -1354,9 +1349,8 @@ const MachODumper = struct {...@@ -1354,9 +1349,8 @@ const MachODumper = struct {
1354 }1349 }
13551350
1356 fn parseBindInfo(ctx: ObjectContext, data: []const u8, bindings: *std.ArrayList(Binding)) !void {1351 fn parseBindInfo(ctx: ObjectContext, data: []const u8, bindings: *std.ArrayList(Binding)) !void {
1357 var stream: std.io.FixedBufferStream = .{ .buffer = data };1352 var br: std.io.BufferedReader = undefined;
1358 var creader = std.io.countingReader(stream.reader());1353 br.initFixed(data);
1359 const reader = creader.reader();
13601354
1361 var seg_id: ?u8 = null;1355 var seg_id: ?u8 = null;
1362 var tag: Binding.Tag = .self;1356 var tag: Binding.Tag = .self;
...@@ -1364,11 +1358,10 @@ const MachODumper = struct {...@@ -1364,11 +1358,10 @@ const MachODumper = struct {
1364 var offset: u64 = 0;1358 var offset: u64 = 0;
1365 var addend: i64 = 0;1359 var addend: i64 = 0;
13661360
1367 var name_buf = std.ArrayList(u8).init(ctx.gpa);1361 var name_buf: std.ArrayList(u8) = .init(ctx.gpa);
1368 defer name_buf.deinit();1362 defer name_buf.deinit();
13691363
1370 while (true) {1364 while (br.takeByte()) |byte| {
1371 const byte = reader.readByte() catch break;
1372 const opc = byte & macho.BIND_OPCODE_MASK;1365 const opc = byte & macho.BIND_OPCODE_MASK;
1373 const imm = byte & macho.BIND_IMMEDIATE_MASK;1366 const imm = byte & macho.BIND_IMMEDIATE_MASK;
1374 switch (opc) {1367 switch (opc) {
...@@ -1389,7 +1382,7 @@ const MachODumper = struct {...@@ -1389,7 +1382,7 @@ const MachODumper = struct {
1389 },1382 },
1390 macho.BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB => {1383 macho.BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB => {
1391 seg_id = imm;1384 seg_id = imm;
1392 offset = try std.leb.readUleb128(u64, reader);1385 offset = try br.takeLeb128(u64);
1393 },1386 },
1394 macho.BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM => {1387 macho.BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM => {
1395 name_buf.clearRetainingCapacity();1388 name_buf.clearRetainingCapacity();
...@@ -1398,10 +1391,10 @@ const MachODumper = struct {...@@ -1398,10 +1391,10 @@ const MachODumper = struct {
1398 try name_buf.append(0);1391 try name_buf.append(0);
1399 },1392 },
1400 macho.BIND_OPCODE_SET_ADDEND_SLEB => {1393 macho.BIND_OPCODE_SET_ADDEND_SLEB => {
1401 addend = try std.leb.readIleb128(i64, reader);1394 addend = try br.takeLeb128(i64);
1402 },1395 },
1403 macho.BIND_OPCODE_ADD_ADDR_ULEB => {1396 macho.BIND_OPCODE_ADD_ADDR_ULEB => {
1404 const x = try std.leb.readUleb128(u64, reader);1397 const x = try br.takeLeb128(u64);
1405 offset = @intCast(@as(i64, @intCast(offset)) + @as(i64, @bitCast(x)));1398 offset = @intCast(@as(i64, @intCast(offset)) + @as(i64, @bitCast(x)));
1406 },1399 },
1407 macho.BIND_OPCODE_DO_BIND,1400 macho.BIND_OPCODE_DO_BIND,
...@@ -1416,14 +1409,14 @@ const MachODumper = struct {...@@ -1416,14 +1409,14 @@ const MachODumper = struct {
1416 switch (opc) {1409 switch (opc) {
1417 macho.BIND_OPCODE_DO_BIND => {},1410 macho.BIND_OPCODE_DO_BIND => {},
1418 macho.BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB => {1411 macho.BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB => {
1419 add_addr = try std.leb.readUleb128(u64, reader);1412 add_addr = try br.takeLeb128(u64);
1420 },1413 },
1421 macho.BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED => {1414 macho.BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED => {
1422 add_addr = imm * @sizeOf(u64);1415 add_addr = imm * @sizeOf(u64);
1423 },1416 },
1424 macho.BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB => {1417 macho.BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB => {
1425 count = try std.leb.readUleb128(u64, reader);1418 count = try br.takeLeb128(u64);
1426 skip = try std.leb.readUleb128(u64, reader);1419 skip = try br.takeLeb128(u64);
1427 },1420 },
1428 else => unreachable,1421 else => unreachable,
1429 }1422 }
...@@ -1444,7 +1437,7 @@ const MachODumper = struct {...@@ -1444,7 +1437,7 @@ const MachODumper = struct {
1444 },1437 },
1445 else => break,1438 else => break,
1446 }1439 }
1447 }1440 } else |_| {}
1448 }1441 }
14491442
1450 fn dumpExportsTrie(ctx: ObjectContext, data: []const u8, bw: *std.io.BufferedWriter) !void {1443 fn dumpExportsTrie(ctx: ObjectContext, data: []const u8, bw: *std.io.BufferedWriter) !void {
...@@ -1453,9 +1446,10 @@ const MachODumper = struct {...@@ -1453,9 +1446,10 @@ const MachODumper = struct {
1453 var arena = std.heap.ArenaAllocator.init(ctx.gpa);1446 var arena = std.heap.ArenaAllocator.init(ctx.gpa);
1454 defer arena.deinit();1447 defer arena.deinit();
14551448
1456 var exports = std.ArrayList(Export).init(arena.allocator());1449 var exports: std.ArrayList(Export) = .init(arena.allocator());
1457 var it = TrieIterator{ .data = data };1450 var br: std.io.BufferedReader = undefined;
1458 try parseTrieNode(arena.allocator(), &it, "", &exports);1451 br.initFixed(data);
1452 try parseTrieNode(arena.allocator(), &br, "", &exports);
14591453
1460 mem.sort(Export, exports.items, {}, Export.lessThan);1454 mem.sort(Export, exports.items, {}, Export.lessThan);
14611455
...@@ -1484,46 +1478,6 @@ const MachODumper = struct {...@@ -1484,46 +1478,6 @@ const MachODumper = struct {
1484 }1478 }
1485 }1479 }
14861480
1487 const TrieIterator = struct {
1488 data: []const u8,
1489 pos: usize = 0,
1490
1491 fn getStream(it: *TrieIterator) std.io.FixedBufferStream {
1492 return .{ .buffer = it.data[it.pos..] };
1493 }
1494
1495 fn readUleb128(it: *TrieIterator) !u64 {
1496 var stream = it.getStream();
1497 var creader = std.io.countingReader(stream.reader());
1498 const reader = creader.reader();
1499 const value = try std.leb.readUleb128(u64, reader);
1500 it.pos += creader.bytes_read;
1501 return value;
1502 }
1503
1504 fn readString(it: *TrieIterator) ![:0]const u8 {
1505 var stream = it.getStream();
1506 const reader = stream.reader();
1507
1508 var count: usize = 0;
1509 while (true) : (count += 1) {
1510 const byte = try reader.readByte();
1511 if (byte == 0) break;
1512 }
1513
1514 const str = @as([*:0]const u8, @ptrCast(it.data.ptr + it.pos))[0..count :0];
1515 it.pos += count + 1;
1516 return str;
1517 }
1518
1519 fn readByte(it: *TrieIterator) !u8 {
1520 var stream = it.getStream();
1521 const value = try stream.reader().readByte();
1522 it.pos += 1;
1523 return value;
1524 }
1525 };
1526
1527 const Export = struct {1481 const Export = struct {
1528 name: []const u8,1482 name: []const u8,
1529 tag: enum { @"export", reexport, stub_resolver },1483 tag: enum { @"export", reexport, stub_resolver },
...@@ -1563,17 +1517,17 @@ const MachODumper = struct {...@@ -1563,17 +1517,17 @@ const MachODumper = struct {
15631517
1564 fn parseTrieNode(1518 fn parseTrieNode(
1565 arena: Allocator,1519 arena: Allocator,
1566 it: *TrieIterator,1520 br: *std.io.BufferedReader,
1567 prefix: []const u8,1521 prefix: []const u8,
1568 exports: *std.ArrayList(Export),1522 exports: *std.ArrayList(Export),
1569 ) !void {1523 ) !void {
1570 const size = try it.readUleb128();1524 const size = try br.takeLeb128(u64);
1571 if (size > 0) {1525 if (size > 0) {
1572 const flags = try it.readUleb128();1526 const flags = try br.takeLeb128(u64);
1573 switch (flags) {1527 switch (flags) {
1574 macho.EXPORT_SYMBOL_FLAGS_REEXPORT => {1528 macho.EXPORT_SYMBOL_FLAGS_REEXPORT => {
1575 const ord = try it.readUleb128();1529 const ord = try br.takeLeb128(u64);
1576 const name = try arena.dupe(u8, try it.readString());1530 const name = try br.takeDelimiterConclusive(0);
1577 try exports.append(.{1531 try exports.append(.{
1578 .name = if (name.len > 0) name else prefix,1532 .name = if (name.len > 0) name else prefix,
1579 .tag = .reexport,1533 .tag = .reexport,
...@@ -1581,8 +1535,8 @@ const MachODumper = struct {...@@ -1581,8 +1535,8 @@ const MachODumper = struct {
1581 });1535 });
1582 },1536 },
1583 macho.EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER => {1537 macho.EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER => {
1584 const stub_offset = try it.readUleb128();1538 const stub_offset = try br.takeLeb128(u64);
1585 const resolver_offset = try it.readUleb128();1539 const resolver_offset = try br.takeLeb128(u64);
1586 try exports.append(.{1540 try exports.append(.{
1587 .name = prefix,1541 .name = prefix,
1588 .tag = .stub_resolver,1542 .tag = .stub_resolver,
...@@ -1593,7 +1547,7 @@ const MachODumper = struct {...@@ -1593,7 +1547,7 @@ const MachODumper = struct {
1593 });1547 });
1594 },1548 },
1595 else => {1549 else => {
1596 const vmoff = try it.readUleb128();1550 const vmoff = try br.takeLeb128(u64);
1597 try exports.append(.{1551 try exports.append(.{
1598 .name = prefix,1552 .name = prefix,
1599 .tag = .@"export",1553 .tag = .@"export",
...@@ -1612,15 +1566,15 @@ const MachODumper = struct {...@@ -1612,15 +1566,15 @@ const MachODumper = struct {
1612 }1566 }
1613 }1567 }
16141568
1615 const nedges = try it.readByte();1569 const nedges = try br.takeByte();
1616 for (0..nedges) |_| {1570 for (0..nedges) |_| {
1617 const label = try it.readString();1571 const label = try br.takeDelimiterConclusive(0);
1618 const off = try it.readUleb128();1572 const off = try br.takeLeb128(u64);
1619 const prefix_label = try std.fmt.allocPrint(arena, "{s}{s}", .{ prefix, label });1573 const prefix_label = try std.fmt.allocPrint(arena, "{s}{s}", .{ prefix, label });
1620 const curr = it.pos;1574 const seek = br.seek;
1621 it.pos = off;1575 br.seek = off;
1622 try parseTrieNode(arena, it, prefix_label, exports);1576 try parseTrieNode(arena, br, prefix_label, exports);
1623 it.pos = curr;1577 br.seek = seek;
1624 }1578 }
1625 }1579 }
16261580
...@@ -1640,8 +1594,10 @@ const MachODumper = struct {...@@ -1640,8 +1594,10 @@ const MachODumper = struct {
1640 var ctx = ObjectContext{ .gpa = gpa, .data = bytes, .header = hdr };1594 var ctx = ObjectContext{ .gpa = gpa, .data = bytes, .header = hdr };
1641 try ctx.parse();1595 try ctx.parse();
16421596
1643 var output: std.io.AllocatingWriter = undefined;1597 var aw: std.io.AllocatingWriter = undefined;
1644 const bw = output.init(gpa);1598 aw.init(gpa);
1599 defer aw.deinit();
1600 const bw = &aw.buffered_writer;
16451601
1646 switch (check.kind) {1602 switch (check.kind) {
1647 .headers => {1603 .headers => {
...@@ -1717,7 +1673,7 @@ const MachODumper = struct {...@@ -1717,7 +1673,7 @@ const MachODumper = struct {
1717 },1673 },
17181674
1719 .dump_section => {1675 .dump_section => {
1720 const name = mem.sliceTo(@as([*:0]const u8, @ptrCast(check.data.items.ptr + check.payload.dump_section)), 0);1676 const name = mem.sliceTo(@as([*:0]const u8, @ptrCast(check.data.items[check.payload.dump_section..].ptr)), 0);
1721 const sep_index = mem.indexOfScalar(u8, name, ',') orelse1677 const sep_index = mem.indexOfScalar(u8, name, ',') orelse
1722 return step.fail("invalid section name: {s}", .{name});1678 return step.fail("invalid section name: {s}", .{name});
1723 const segname = name[0..sep_index];1679 const segname = name[0..sep_index];
...@@ -1730,7 +1686,7 @@ const MachODumper = struct {...@@ -1730,7 +1686,7 @@ const MachODumper = struct {
1730 else => return step.fail("invalid check kind for MachO file format: {s}", .{@tagName(check.kind)}),1686 else => return step.fail("invalid check kind for MachO file format: {s}", .{@tagName(check.kind)}),
1731 }1687 }
17321688
1733 return output.toOwnedSlice();1689 return aw.toOwnedSlice();
1734 }1690 }
1735};1691};
17361692
...@@ -1749,153 +1705,133 @@ const ElfDumper = struct {...@@ -1749,153 +1705,133 @@ const ElfDumper = struct {
17491705
1750 fn parseAndDumpArchive(step: *Step, check: Check, bytes: []const u8) ![]const u8 {1706 fn parseAndDumpArchive(step: *Step, check: Check, bytes: []const u8) ![]const u8 {
1751 const gpa = step.owner.allocator;1707 const gpa = step.owner.allocator;
1752 var stream: std.io.FixedBufferStream = .{ .buffer = bytes };1708 var br: std.io.BufferedReader = undefined;
1753 const reader = stream.reader();1709 br.initFixed(bytes);
17541710
1755 const magic = try reader.readBytesNoEof(elf.ARMAG.len);1711 if (!mem.eql(u8, try br.takeArray(elf.ARMAG.len), elf.ARMAG)) return error.InvalidArchiveMagicNumber;
1756 if (!mem.eql(u8, &magic, elf.ARMAG)) {
1757 return error.InvalidArchiveMagicNumber;
1758 }
17591712
1760 var ctx = ArchiveContext{1713 var ctx: ArchiveContext = .{
1761 .gpa = gpa,1714 .gpa = gpa,
1762 .data = bytes,1715 .data = bytes,
1763 .strtab = &[0]u8{},1716 .symtab = &.{},
1717 .strtab = &.{},
1718 .objects = .empty,
1764 };1719 };
1765 defer {1720 defer ctx.deinit();
1766 for (ctx.objects.items) |*object| {
1767 gpa.free(object.name);
1768 }
1769 ctx.objects.deinit(gpa);
1770 }
1771
1772 while (true) {
1773 if (stream.pos >= ctx.data.len) break;
1774 if (!mem.isAligned(stream.pos, 2)) stream.pos += 1;
17751721
1776 const hdr = try reader.readStruct(elf.ar_hdr);1722 while (br.seek < bytes.len) {
1723 const hdr_seek = std.mem.alignForward(usize, br.seek, 2);
1724 br.seek = hdr_seek;
1725 const hdr = try br.takeStruct(elf.ar_hdr);
17771726
1778 if (!mem.eql(u8, &hdr.ar_fmag, elf.ARFMAG)) return error.InvalidArchiveHeaderMagicNumber;1727 if (!mem.eql(u8, &hdr.ar_fmag, elf.ARFMAG)) return error.InvalidArchiveHeaderMagicNumber;
17791728
1780 const size = try hdr.size();1729 const data = try br.take(try hdr.size());
1781 defer {
1782 _ = stream.seekBy(size) catch {};
1783 }
17841730
1785 if (hdr.isSymtab()) {1731 if (hdr.isSymtab()) {
1786 try ctx.parseSymtab(ctx.data[stream.pos..][0..size], .p32);1732 try ctx.parseSymtab(data, .p32);
1787 continue;1733 continue;
1788 }1734 }
1789 if (hdr.isSymtab64()) {1735 if (hdr.isSymtab64()) {
1790 try ctx.parseSymtab(ctx.data[stream.pos..][0..size], .p64);1736 try ctx.parseSymtab(data, .p64);
1791 continue;1737 continue;
1792 }1738 }
1793 if (hdr.isStrtab()) {1739 if (hdr.isStrtab()) {
1794 ctx.strtab = ctx.data[stream.pos..][0..size];1740 ctx.strtab = data;
1795 continue;1741 continue;
1796 }1742 }
1797 if (hdr.isSymdef() or hdr.isSymdefSorted()) continue;1743 if (hdr.isSymdef() or hdr.isSymdefSorted()) continue;
17981744
1799 const name = if (hdr.name()) |name|1745 const name = hdr.name() orelse ctx.getString((try hdr.nameOffset()).?);
1800 try gpa.dupe(u8, name)1746 try ctx.objects.putNoClobber(gpa, hdr_seek, .{
1801 else if (try hdr.nameOffset()) |off|1747 .name = name,
1802 try gpa.dupe(u8, ctx.getString(off))1748 .data = data,
1803 else1749 });
1804 unreachable;
1805
1806 try ctx.objects.append(gpa, .{ .name = name, .off = stream.pos, .len = size });
1807 }1750 }
18081751
1809 var output: std.io.AllocatingWriter = undefined;1752 var aw: std.io.AllocatingWriter = undefined;
1810 const writer = output.init(gpa);1753 aw.init(gpa);
1754 defer aw.deinit();
1755 const bw = &aw.buffered_writer;
18111756
1812 switch (check.kind) {1757 switch (check.kind) {
1813 .archive_symtab => if (ctx.symtab.items.len > 0) {1758 .archive_symtab => if (ctx.symtab.len > 0) {
1814 try ctx.dumpSymtab(writer);1759 try ctx.dumpSymtab(bw);
1815 } else return step.fail("no archive symbol table found", .{}),1760 } else return step.fail("no archive symbol table found", .{}),
18161761
1817 else => if (ctx.objects.items.len > 0) {1762 else => if (ctx.objects.count() > 0) {
1818 try ctx.dumpObjects(step, check, writer);1763 try ctx.dumpObjects(step, check, bw);
1819 } else return step.fail("empty archive", .{}),1764 } else return step.fail("empty archive", .{}),
1820 }1765 }
18211766
1822 return output.toOwnedSlice();1767 return aw.toOwnedSlice();
1823 }1768 }
18241769
1825 const ArchiveContext = struct {1770 const ArchiveContext = struct {
1826 gpa: Allocator,1771 gpa: Allocator,
1827 data: []const u8,1772 data: []const u8,
1828 symtab: std.ArrayListUnmanaged(ArSymtabEntry) = .empty,1773 symtab: []ArSymtabEntry,
1829 strtab: []const u8,1774 strtab: []const u8,
1830 objects: std.ArrayListUnmanaged(struct { name: []const u8, off: usize, len: usize }) = .empty,1775 objects: std.AutoArrayHashMapUnmanaged(usize, struct { name: []const u8, data: []const u8 }),
18311776
1832 fn parseSymtab(ctx: *ArchiveContext, raw: []const u8, ptr_width: enum { p32, p64 }) !void {1777 fn deinit(ctx: *ArchiveContext) void {
1833 var stream: std.io.FixedBufferStream = .{ .buffer = raw };1778 ctx.gpa.free(ctx.symtab);
1834 const reader = stream.reader();1779 ctx.objects.deinit(ctx.gpa);
1780 }
1781
1782 fn parseSymtab(ctx: *ArchiveContext, data: []const u8, ptr_width: enum { p32, p64 }) !void {
1783 var br: std.io.BufferedReader = undefined;
1784 br.initFixed(data);
1835 const num = switch (ptr_width) {1785 const num = switch (ptr_width) {
1836 .p32 => try reader.readInt(u32, .big),1786 .p32 => try br.takeInt(u32, .big),
1837 .p64 => try reader.readInt(u64, .big),1787 .p64 => try br.takeInt(u64, .big),
1838 };1788 };
1839 const ptr_size: usize = switch (ptr_width) {1789 const ptr_size: usize = switch (ptr_width) {
1840 .p32 => @sizeOf(u32),1790 .p32 => @sizeOf(u32),
1841 .p64 => @sizeOf(u64),1791 .p64 => @sizeOf(u64),
1842 };1792 };
1843 const strtab_off = (num + 1) * ptr_size;1793 try br.discard(num * ptr_size);
1844 const strtab_len = raw.len - strtab_off;1794 const strtab = try br.peekAll(0);
1845 const strtab = raw[strtab_off..][0..strtab_len];
18461795
1847 try ctx.symtab.ensureTotalCapacityPrecise(ctx.gpa, num);1796 assert(ctx.symtab.len == 0);
1797 ctx.symtab = try ctx.gpa.alloc(ArSymtabEntry, num);
18481798
1849 var stroff: usize = 0;1799 var stroff: usize = 0;
1850 for (0..num) |_| {1800 for (ctx.symtab) |*entry| {
1851 const off = switch (ptr_width) {1801 const off = switch (ptr_width) {
1852 .p32 => try reader.readInt(u32, .big),1802 .p32 => try br.takeInt(u32, .big),
1853 .p64 => try reader.readInt(u64, .big),1803 .p64 => try br.takeInt(u64, .big),
1854 };1804 };
1855 const name = mem.sliceTo(@as([*:0]const u8, @ptrCast(strtab.ptr + stroff)), 0);1805 const name = mem.sliceTo(@as([*:0]const u8, @ptrCast(strtab[stroff..].ptr)), 0);
1856 stroff += name.len + 1;1806 stroff += name.len + 1;
1857 ctx.symtab.appendAssumeCapacity(.{ .off = off, .name = name });1807 entry.* = .{ .off = off, .name = name };
1858 }1808 }
1859 }1809 }
18601810
1861 fn dumpSymtab(ctx: ArchiveContext, bw: *std.io.BufferedWriter) !void {1811 fn dumpSymtab(ctx: ArchiveContext, bw: *std.io.BufferedWriter) !void {
1862 var files = std.AutoHashMap(usize, []const u8).init(ctx.gpa);1812 var symbols: std.AutoArrayHashMap(usize, std.ArrayList([]const u8)) = .init(ctx.gpa);
1863 defer files.deinit();
1864 try files.ensureUnusedCapacity(@intCast(ctx.objects.items.len));
1865
1866 for (ctx.objects.items) |object| {
1867 files.putAssumeCapacityNoClobber(object.off - @sizeOf(elf.ar_hdr), object.name);
1868 }
1869
1870 var symbols = std.AutoArrayHashMap(usize, std.ArrayList([]const u8)).init(ctx.gpa);
1871 defer {1813 defer {
1872 for (symbols.values()) |*value| {1814 for (symbols.values()) |*value| value.deinit();
1873 value.deinit();
1874 }
1875 symbols.deinit();1815 symbols.deinit();
1876 }1816 }
18771817
1878 for (ctx.symtab.items) |entry| {1818 for (ctx.symtab) |entry| {
1879 const gop = try symbols.getOrPut(@intCast(entry.off));1819 const gop = try symbols.getOrPut(@intCast(entry.off));
1880 if (!gop.found_existing) {1820 if (!gop.found_existing) gop.value_ptr.* = .init(ctx.gpa);
1881 gop.value_ptr.* = std.ArrayList([]const u8).init(ctx.gpa);
1882 }
1883 try gop.value_ptr.append(entry.name);1821 try gop.value_ptr.append(entry.name);
1884 }1822 }
18851823
1886 try bw.print("{s}\n", .{archive_symtab_label});1824 try bw.print("{s}\n", .{archive_symtab_label});
1887 for (symbols.keys(), symbols.values()) |off, values| {1825 for (symbols.keys(), symbols.values()) |off, values| {
1888 try bw.print("in object {s}\n", .{files.get(off).?});1826 try bw.print("in object {s}\n", .{ctx.objects.get(off).?.name});
1889 for (values.items) |value| {1827 for (values.items) |value| try bw.print("{s}\n", .{value});
1890 try bw.print("{s}\n", .{value});
1891 }
1892 }1828 }
1893 }1829 }
18941830
1895 fn dumpObjects(ctx: ArchiveContext, step: *Step, check: Check, bw: *std.io.BufferedWriter) !void {1831 fn dumpObjects(ctx: ArchiveContext, step: *Step, check: Check, bw: *std.io.BufferedWriter) !void {
1896 for (ctx.objects.items) |object| {1832 for (ctx.objects.values()) |object| {
1897 try bw.print("object {s}\n", .{object.name});1833 try bw.print("object {s}\n", .{object.name});
1898 const output = try parseAndDumpObject(step, check, ctx.data[object.off..][0..object.len]);1834 const output = try parseAndDumpObject(step, check, object.data);
1899 defer ctx.gpa.free(output);1835 defer ctx.gpa.free(output);
1900 try bw.print("{s}\n", .{output});1836 try bw.print("{s}\n", .{output});
1901 }1837 }
...@@ -1903,7 +1839,7 @@ const ElfDumper = struct {...@@ -1903,7 +1839,7 @@ const ElfDumper = struct {
19031839
1904 fn getString(ctx: ArchiveContext, off: u32) []const u8 {1840 fn getString(ctx: ArchiveContext, off: u32) []const u8 {
1905 assert(off < ctx.strtab.len);1841 assert(off < ctx.strtab.len);
1906 const name = mem.sliceTo(@as([*:'\n']const u8, @ptrCast(ctx.strtab.ptr + off)), 0);1842 const name = mem.sliceTo(@as([*:'\n']const u8, @ptrCast(ctx.strtab[off..].ptr)), 0);
1907 return name[0 .. name.len - 1];1843 return name[0 .. name.len - 1];
1908 }1844 }
19091845
...@@ -1915,24 +1851,24 @@ const ElfDumper = struct {...@@ -1915,24 +1851,24 @@ const ElfDumper = struct {
19151851
1916 fn parseAndDumpObject(step: *Step, check: Check, bytes: []const u8) ![]const u8 {1852 fn parseAndDumpObject(step: *Step, check: Check, bytes: []const u8) ![]const u8 {
1917 const gpa = step.owner.allocator;1853 const gpa = step.owner.allocator;
1918 var stream: std.io.FixedBufferStream = .{ .buffer = bytes };1854 var br: std.io.BufferedReader = undefined;
1919 const reader = stream.reader();1855 br.initFixed(bytes);
19201856
1921 const hdr = try reader.readStruct(elf.Elf64_Ehdr);1857 const hdr = try br.takeStruct(elf.Elf64_Ehdr);
1922 if (!mem.eql(u8, hdr.e_ident[0..4], "\x7fELF")) {1858 if (!mem.eql(u8, hdr.e_ident[0..4], "\x7fELF")) return error.InvalidMagicNumber;
1923 return error.InvalidMagicNumber;
1924 }
19251859
1926 const shdrs = @as([*]align(1) const elf.Elf64_Shdr, @ptrCast(bytes.ptr + hdr.e_shoff))[0..hdr.e_shnum];1860 const shdrs = @as([*]align(1) const elf.Elf64_Shdr, @ptrCast(bytes[hdr.e_shoff..].ptr))[0..hdr.e_shnum];
1927 const phdrs = @as([*]align(1) const elf.Elf64_Phdr, @ptrCast(bytes.ptr + hdr.e_phoff))[0..hdr.e_phnum];1861 const phdrs = @as([*]align(1) const elf.Elf64_Phdr, @ptrCast(bytes[hdr.e_phoff..].ptr))[0..hdr.e_phnum];
19281862
1929 var ctx = ObjectContext{1863 var ctx: ObjectContext = .{
1930 .gpa = gpa,1864 .gpa = gpa,
1931 .data = bytes,1865 .data = bytes,
1932 .hdr = hdr,1866 .hdr = hdr,
1933 .shdrs = shdrs,1867 .shdrs = shdrs,
1934 .phdrs = phdrs,1868 .phdrs = phdrs,
1935 .shstrtab = undefined,1869 .shstrtab = undefined,
1870 .symtab = .{},
1871 .dysymtab = .{},
1936 };1872 };
1937 ctx.shstrtab = ctx.getSectionContents(ctx.hdr.e_shstrndx);1873 ctx.shstrtab = ctx.getSectionContents(ctx.hdr.e_shstrndx);
19381874
...@@ -1963,8 +1899,10 @@ const ElfDumper = struct {...@@ -1963,8 +1899,10 @@ const ElfDumper = struct {
1963 else => {},1899 else => {},
1964 };1900 };
19651901
1966 var output: std.io.AllocatingWriter = undefined;1902 var aw: std.io.AllocatingWriter = undefined;
1967 const bw = output.init(gpa);1903 aw.init(gpa);
1904 defer aw.deinit();
1905 const bw = &aw.buffered_writer;
19681906
1969 switch (check.kind) {1907 switch (check.kind) {
1970 .headers => {1908 .headers => {
...@@ -1986,7 +1924,7 @@ const ElfDumper = struct {...@@ -1986,7 +1924,7 @@ const ElfDumper = struct {
1986 } else return step.fail("no .dynamic section found", .{}),1924 } else return step.fail("no .dynamic section found", .{}),
19871925
1988 .dump_section => {1926 .dump_section => {
1989 const name = mem.sliceTo(@as([*:0]const u8, @ptrCast(check.data.items.ptr + check.payload.dump_section)), 0);1927 const name = mem.sliceTo(@as([*:0]const u8, @ptrCast(check.data.items[check.payload.dump_section..].ptr)), 0);
1990 const shndx = ctx.getSectionByName(name) orelse return step.fail("no '{s}' section found", .{name});1928 const shndx = ctx.getSectionByName(name) orelse return step.fail("no '{s}' section found", .{name});
1991 try ctx.dumpSection(shndx, bw);1929 try ctx.dumpSection(shndx, bw);
1992 },1930 },
...@@ -1994,18 +1932,18 @@ const ElfDumper = struct {...@@ -1994,18 +1932,18 @@ const ElfDumper = struct {
1994 else => return step.fail("invalid check kind for ELF file format: {s}", .{@tagName(check.kind)}),1932 else => return step.fail("invalid check kind for ELF file format: {s}", .{@tagName(check.kind)}),
1995 }1933 }
19961934
1997 return output.toOwnedSlice();1935 return aw.toOwnedSlice();
1998 }1936 }
19991937
2000 const ObjectContext = struct {1938 const ObjectContext = struct {
2001 gpa: Allocator,1939 gpa: Allocator,
2002 data: []const u8,1940 data: []const u8,
2003 hdr: elf.Elf64_Ehdr,1941 hdr: *align(1) const elf.Elf64_Ehdr,
2004 shdrs: []align(1) const elf.Elf64_Shdr,1942 shdrs: []align(1) const elf.Elf64_Shdr,
2005 phdrs: []align(1) const elf.Elf64_Phdr,1943 phdrs: []align(1) const elf.Elf64_Phdr,
2006 shstrtab: []const u8,1944 shstrtab: []const u8,
2007 symtab: Symtab = .{},1945 symtab: Symtab,
2008 dysymtab: Symtab = .{},1946 dysymtab: Symtab,
20091947
2010 fn dumpHeader(ctx: ObjectContext, bw: *std.io.BufferedWriter) !void {1948 fn dumpHeader(ctx: ObjectContext, bw: *std.io.BufferedWriter) !void {
2011 try bw.writeAll("header\n");1949 try bw.writeAll("header\n");
...@@ -2020,7 +1958,7 @@ const ElfDumper = struct {...@@ -2020,7 +1958,7 @@ const ElfDumper = struct {
20201958
2021 for (ctx.phdrs, 0..) |phdr, phndx| {1959 for (ctx.phdrs, 0..) |phdr, phndx| {
2022 try bw.print("phdr {d}\n", .{phndx});1960 try bw.print("phdr {d}\n", .{phndx});
2023 try bw.print("type {s}\n", .{fmtPhType(phdr.p_type)});1961 try bw.print("type {f}\n", .{fmtPhType(phdr.p_type)});
2024 try bw.print("vaddr {x}\n", .{phdr.p_vaddr});1962 try bw.print("vaddr {x}\n", .{phdr.p_vaddr});
2025 try bw.print("paddr {x}\n", .{phdr.p_paddr});1963 try bw.print("paddr {x}\n", .{phdr.p_paddr});
2026 try bw.print("offset {x}\n", .{phdr.p_offset});1964 try bw.print("offset {x}\n", .{phdr.p_offset});
...@@ -2060,7 +1998,7 @@ const ElfDumper = struct {...@@ -2060,7 +1998,7 @@ const ElfDumper = struct {
2060 for (ctx.shdrs, 0..) |shdr, shndx| {1998 for (ctx.shdrs, 0..) |shdr, shndx| {
2061 try bw.print("shdr {d}\n", .{shndx});1999 try bw.print("shdr {d}\n", .{shndx});
2062 try bw.print("name {s}\n", .{ctx.getSectionName(shndx)});2000 try bw.print("name {s}\n", .{ctx.getSectionName(shndx)});
2063 try bw.print("type {s}\n", .{fmtShType(shdr.sh_type)});2001 try bw.print("type {f}\n", .{fmtShType(shdr.sh_type)});
2064 try bw.print("addr {x}\n", .{shdr.sh_addr});2002 try bw.print("addr {x}\n", .{shdr.sh_addr});
2065 try bw.print("offset {x}\n", .{shdr.sh_offset});2003 try bw.print("offset {x}\n", .{shdr.sh_offset});
2066 try bw.print("size {x}\n", .{shdr.sh_size});2004 try bw.print("size {x}\n", .{shdr.sh_size});
...@@ -2329,8 +2267,8 @@ const ElfDumper = struct {...@@ -2329,8 +2267,8 @@ const ElfDumper = struct {
2329 };2267 };
23302268
2331 fn getString(strtab: []const u8, off: u32) []const u8 {2269 fn getString(strtab: []const u8, off: u32) []const u8 {
2332 assert(off < strtab.len);2270 const str = strtab[off..];
2333 return mem.sliceTo(@as([*:0]const u8, @ptrCast(strtab.ptr + off)), 0);2271 return str[0..std.mem.indexOfScalar(u8, str, 0).?];
2334 }2272 }
23352273
2336 fn fmtShType(sh_type: u32) std.fmt.Formatter(formatShType) {2274 fn fmtShType(sh_type: u32) std.fmt.Formatter(formatShType) {
...@@ -2339,12 +2277,10 @@ const ElfDumper = struct {...@@ -2339,12 +2277,10 @@ const ElfDumper = struct {
23392277
2340 fn formatShType(2278 fn formatShType(
2341 sh_type: u32,2279 sh_type: u32,
2342 comptime unused_fmt_string: []const u8,
2343 options: std.fmt.FormatOptions,
2344 bw: *std.io.BufferedWriter,2280 bw: *std.io.BufferedWriter,
2281 comptime unused_fmt_string: []const u8,
2345 ) !void {2282 ) !void {
2346 _ = unused_fmt_string;2283 _ = unused_fmt_string;
2347 _ = options;
2348 const name = switch (sh_type) {2284 const name = switch (sh_type) {
2349 elf.SHT_NULL => "NULL",2285 elf.SHT_NULL => "NULL",
2350 elf.SHT_PROGBITS => "PROGBITS",2286 elf.SHT_PROGBITS => "PROGBITS",
...@@ -2386,12 +2322,10 @@ const ElfDumper = struct {...@@ -2386,12 +2322,10 @@ const ElfDumper = struct {
23862322
2387 fn formatPhType(2323 fn formatPhType(
2388 ph_type: u32,2324 ph_type: u32,
2389 comptime unused_fmt_string: []const u8,
2390 options: std.fmt.FormatOptions,
2391 bw: *std.io.BufferedWriter,2325 bw: *std.io.BufferedWriter,
2326 comptime unused_fmt_string: []const u8,
2392 ) !void {2327 ) !void {
2393 _ = unused_fmt_string;2328 _ = unused_fmt_string;
2394 _ = options;
2395 const p_type = switch (ph_type) {2329 const p_type = switch (ph_type) {
2396 elf.PT_NULL => "NULL",2330 elf.PT_NULL => "NULL",
2397 elf.PT_LOAD => "LOAD",2331 elf.PT_LOAD => "LOAD",
...@@ -2420,49 +2354,41 @@ const WasmDumper = struct {...@@ -2420,49 +2354,41 @@ const WasmDumper = struct {
24202354
2421 fn parseAndDump(step: *Step, check: Check, bytes: []const u8) ![]const u8 {2355 fn parseAndDump(step: *Step, check: Check, bytes: []const u8) ![]const u8 {
2422 const gpa = step.owner.allocator;2356 const gpa = step.owner.allocator;
2423 var fbs: std.io.FixedBufferStream = .{ .buffer = bytes };2357 var br: std.io.BufferedReader = undefined;
2424 const reader = fbs.reader();2358 br.initFixed(bytes);
24252359
2426 const buf = try reader.readBytesNoEof(8);2360 const buf = try br.takeArray(8);
2427 if (!mem.eql(u8, buf[0..4], &std.wasm.magic)) {2361 if (!mem.eql(u8, buf[0..4], &std.wasm.magic)) return error.InvalidMagicByte;
2428 return error.InvalidMagicByte;2362 if (!mem.eql(u8, buf[4..8], &std.wasm.version)) return error.UnsupportedWasmVersion;
2429 }
2430 if (!mem.eql(u8, buf[4..], &std.wasm.version)) {
2431 return error.UnsupportedWasmVersion;
2432 }
24332363
2434 var output: std.io.AllocatingWriter = undefined;2364 var aw: std.io.AllocatingWriter = undefined;
2435 const bw = output.init(gpa);2365 aw.init(gpa);
2436 defer output.deinit();2366 defer aw.deinit();
2437 parseAndDumpInner(step, check, bytes, &fbs, bw) catch |err| switch (err) {2367 const bw = &aw.buffered_writer;
2368
2369 parseAndDumpInner(step, check, &br, bw) catch |err| switch (err) {
2438 error.EndOfStream => try bw.writeAll("\n<UnexpectedEndOfStream>"),2370 error.EndOfStream => try bw.writeAll("\n<UnexpectedEndOfStream>"),
2439 else => |e| return e,2371 else => |e| return e,
2440 };2372 };
2441 return output.toOwnedSlice();2373 return aw.toOwnedSlice();
2442 }2374 }
24432375
2444 fn parseAndDumpInner(2376 fn parseAndDumpInner(
2445 step: *Step,2377 step: *Step,
2446 check: Check,2378 check: Check,
2447 bytes: []const u8,2379 br: *std.io.BufferedReader,
2448 fbs: *std.io.FixedBufferStream,
2449 bw: *std.io.BufferedWriter,2380 bw: *std.io.BufferedWriter,
2450 ) !void {2381 ) !void {
2451 const reader = fbs.reader();2382 var section_br: std.io.BufferedReader = undefined;
2452
2453 switch (check.kind) {2383 switch (check.kind) {
2454 .headers => {2384 .headers => while (br.takeEnum(std.wasm.Section, .little)) |section| {
2455 while (reader.readByte()) |current_byte| {2385 section_br.initFixed(try br.take(try br.takeLeb128(u32)));
2456 const section = std.enums.fromInt(std.wasm.Section, current_byte) orelse {2386 try parseAndDumpSection(step, section, &section_br, bw);
2457 return step.fail("Found invalid section id '{d}'", .{current_byte});2387 } else |err| switch (err) {
2458 };2388 error.InvalidEnumTag => return step.fail("invalid section id", .{}),
24592389 error.EndOfStream => {},
2460 const section_length = try std.leb.readUleb128(u32, reader);2390 else => |e| return e,
2461 try parseAndDumpSection(step, section, bytes[fbs.pos..][0..section_length], bw);
2462 fbs.pos += section_length;
2463 } else |_| {} // reached end of stream
2464 },2391 },
2465
2466 else => return step.fail("invalid check kind for Wasm file format: {s}", .{@tagName(check.kind)}),2392 else => return step.fail("invalid check kind for Wasm file format: {s}", .{@tagName(check.kind)}),
2467 }2393 }
2468 }2394 }
...@@ -2470,16 +2396,13 @@ const WasmDumper = struct {...@@ -2470,16 +2396,13 @@ const WasmDumper = struct {
2470 fn parseAndDumpSection(2396 fn parseAndDumpSection(
2471 step: *Step,2397 step: *Step,
2472 section: std.wasm.Section,2398 section: std.wasm.Section,
2473 data: []const u8,2399 br: *std.io.BufferedReader,
2474 bw: *std.io.BufferedWriter,2400 bw: *std.io.BufferedWriter,
2475 ) !void {2401 ) !void {
2476 var fbs: std.io.FixedBufferStream = .{ .buffer = data };
2477 const reader = fbs.reader();
2478
2479 try bw.print(2402 try bw.print(
2480 \\Section {s}2403 \\Section {s}
2481 \\size {d}2404 \\size {d}
2482 , .{ @tagName(section), data.len });2405 , .{ @tagName(section), br.storageBuffer().len });
24832406
2484 switch (section) {2407 switch (section) {
2485 .type,2408 .type,
...@@ -2493,74 +2416,65 @@ const WasmDumper = struct {...@@ -2493,74 +2416,65 @@ const WasmDumper = struct {
2493 .code,2416 .code,
2494 .data,2417 .data,
2495 => {2418 => {
2496 const entries = try std.leb.readUleb128(u32, reader);2419 const entries = try br.takeLeb128(u32);
2497 try bw.print("\nentries {d}\n", .{entries});2420 try bw.print("\nentries {d}\n", .{entries});
2498 try parseSection(step, section, data[fbs.pos..], entries, bw);2421 try parseSection(step, section, br, entries, bw);
2499 },2422 },
2500 .custom => {2423 .custom => {
2501 const name_length = try std.leb.readUleb128(u32, reader);2424 const name = try br.take(try br.takeLeb128(u32));
2502 const name = data[fbs.pos..][0..name_length];
2503 fbs.pos += name_length;
2504 try bw.print("\nname {s}\n", .{name});2425 try bw.print("\nname {s}\n", .{name});
25052426
2506 if (mem.eql(u8, name, "name")) {2427 if (mem.eql(u8, name, "name")) {
2507 try parseDumpNames(step, reader, bw, data);2428 try parseDumpNames(step, br, bw);
2508 } else if (mem.eql(u8, name, "producers")) {2429 } else if (mem.eql(u8, name, "producers")) {
2509 try parseDumpProducers(reader, bw, data);2430 try parseDumpProducers(br, bw);
2510 } else if (mem.eql(u8, name, "target_features")) {2431 } else if (mem.eql(u8, name, "target_features")) {
2511 try parseDumpFeatures(reader, bw, data);2432 try parseDumpFeatures(br, bw);
2512 }2433 }
2513 // TODO: Implement parsing and dumping other custom sections (such as relocations)2434 // TODO: Implement parsing and dumping other custom sections (such as relocations)
2514 },2435 },
2515 .start => {2436 .start => {
2516 const start = try std.leb.readUleb128(u32, reader);2437 const start = try br.takeLeb128(u32);
2517 try bw.print("\nstart {d}\n", .{start});2438 try bw.print("\nstart {d}\n", .{start});
2518 },2439 },
2519 .data_count => {2440 .data_count => {
2520 const count = try std.leb.readUleb128(u32, reader);2441 const count = try br.takeLeb128(u32);
2521 try bw.print("\ncount {d}\n", .{count});2442 try bw.print("\ncount {d}\n", .{count});
2522 },2443 },
2523 else => {}, // skip unknown sections2444 else => {}, // skip unknown sections
2524 }2445 }
2525 }2446 }
25262447
2527 fn parseSection(step: *Step, section: std.wasm.Section, data: []const u8, entries: u32, bw: *std.io.BufferedWriter) !void {2448 fn parseSection(step: *Step, section: std.wasm.Section, br: *std.io.BufferedReader, entries: u32, bw: *std.io.BufferedWriter) !void {
2528 var fbs: std.io.FixedBufferStream = .{ .buffer = data };
2529 const reader = fbs.reader();
2530
2531 switch (section) {2449 switch (section) {
2532 .type => {2450 .type => {
2533 var i: u32 = 0;2451 var i: u32 = 0;
2534 while (i < entries) : (i += 1) {2452 while (i < entries) : (i += 1) {
2535 const func_type = try reader.readByte();2453 const func_type = try br.takeByte();
2536 if (func_type != std.wasm.function_type) {2454 if (func_type != std.wasm.function_type) {
2537 return step.fail("expected function type, found byte '{d}'", .{func_type});2455 return step.fail("expected function type, found byte '{d}'", .{func_type});
2538 }2456 }
2539 const params = try std.leb.readUleb128(u32, reader);2457 const params = try br.takeLeb128(u32);
2540 try bw.print("params {d}\n", .{params});2458 try bw.print("params {d}\n", .{params});
2541 var index: u32 = 0;2459 var index: u32 = 0;
2542 while (index < params) : (index += 1) {2460 while (index < params) : (index += 1) {
2543 _ = try parseDumpType(step, std.wasm.Valtype, reader, bw);2461 _ = try parseDumpType(step, std.wasm.Valtype, br, bw);
2544 } else index = 0;2462 } else index = 0;
2545 const returns = try std.leb.readUleb128(u32, reader);2463 const returns = try br.takeLeb128(u32);
2546 try bw.print("returns {d}\n", .{returns});2464 try bw.print("returns {d}\n", .{returns});
2547 while (index < returns) : (index += 1) {2465 while (index < returns) : (index += 1) {
2548 _ = try parseDumpType(step, std.wasm.Valtype, reader, bw);2466 _ = try parseDumpType(step, std.wasm.Valtype, br, bw);
2549 }2467 }
2550 }2468 }
2551 },2469 },
2552 .import => {2470 .import => {
2553 var i: u32 = 0;2471 var i: u32 = 0;
2554 while (i < entries) : (i += 1) {2472 while (i < entries) : (i += 1) {
2555 const module_name_len = try std.leb.readUleb128(u32, reader);2473 const module_name = try br.take(try br.takeLeb128(u32));
2556 const module_name = data[fbs.pos..][0..module_name_len];2474 const name = try br.take(try br.takeLeb128(u32));
2557 fbs.pos += module_name_len;2475 const kind = br.takeEnum(std.wasm.ExternalKind, .little) catch |err| switch (err) {
2558 const name_len = try std.leb.readUleb128(u32, reader);2476 error.InvalidEnumTag => return step.fail("invalid import kind", .{}),
2559 const name = data[fbs.pos..][0..name_len];2477 else => |e| return e,
2560 fbs.pos += name_len;
2561
2562 const kind = std.enums.fromInt(std.wasm.ExternalKind, try reader.readByte()) orelse {
2563 return step.fail("invalid import kind", .{});
2564 };2478 };
25652479
2566 try bw.print(2480 try bw.print(
...@@ -2570,19 +2484,15 @@ const WasmDumper = struct {...@@ -2570,19 +2484,15 @@ const WasmDumper = struct {
2570 , .{ module_name, name, @tagName(kind) });2484 , .{ module_name, name, @tagName(kind) });
2571 try bw.writeByte('\n');2485 try bw.writeByte('\n');
2572 switch (kind) {2486 switch (kind) {
2573 .function => {2487 .function => try bw.print("index {d}\n", .{try br.takeLeb128(u32)}),
2574 try bw.print("index {d}\n", .{try std.leb.readUleb128(u32, reader)});2488 .memory => try parseDumpLimits(br, bw),
2575 },
2576 .memory => {
2577 try parseDumpLimits(reader, bw);
2578 },
2579 .global => {2489 .global => {
2580 _ = try parseDumpType(step, std.wasm.Valtype, reader, bw);2490 _ = try parseDumpType(step, std.wasm.Valtype, br, bw);
2581 try bw.print("mutable {}\n", .{0x01 == try std.leb.readUleb128(u32, reader)});2491 try bw.print("mutable {}\n", .{0x01 == try br.takeLeb128(u32)});
2582 },2492 },
2583 .table => {2493 .table => {
2584 _ = try parseDumpType(step, std.wasm.RefType, reader, bw);2494 _ = try parseDumpType(step, std.wasm.RefType, br, bw);
2585 try parseDumpLimits(reader, bw);2495 try parseDumpLimits(br, bw);
2586 },2496 },
2587 }2497 }
2588 }2498 }
...@@ -2590,41 +2500,39 @@ const WasmDumper = struct {...@@ -2590,41 +2500,39 @@ const WasmDumper = struct {
2590 .function => {2500 .function => {
2591 var i: u32 = 0;2501 var i: u32 = 0;
2592 while (i < entries) : (i += 1) {2502 while (i < entries) : (i += 1) {
2593 try bw.print("index {d}\n", .{try std.leb.readUleb128(u32, reader)});2503 try bw.print("index {d}\n", .{try br.takeLeb128(u32)});
2594 }2504 }
2595 },2505 },
2596 .table => {2506 .table => {
2597 var i: u32 = 0;2507 var i: u32 = 0;
2598 while (i < entries) : (i += 1) {2508 while (i < entries) : (i += 1) {
2599 _ = try parseDumpType(step, std.wasm.RefType, reader, bw);2509 _ = try parseDumpType(step, std.wasm.RefType, br, bw);
2600 try parseDumpLimits(reader, bw);2510 try parseDumpLimits(br, bw);
2601 }2511 }
2602 },2512 },
2603 .memory => {2513 .memory => {
2604 var i: u32 = 0;2514 var i: u32 = 0;
2605 while (i < entries) : (i += 1) {2515 while (i < entries) : (i += 1) {
2606 try parseDumpLimits(reader, bw);2516 try parseDumpLimits(br, bw);
2607 }2517 }
2608 },2518 },
2609 .global => {2519 .global => {
2610 var i: u32 = 0;2520 var i: u32 = 0;
2611 while (i < entries) : (i += 1) {2521 while (i < entries) : (i += 1) {
2612 _ = try parseDumpType(step, std.wasm.Valtype, reader, bw);2522 _ = try parseDumpType(step, std.wasm.Valtype, br, bw);
2613 try bw.print("mutable {}\n", .{0x01 == try std.leb.readUleb128(u1, reader)});2523 try bw.print("mutable {}\n", .{0x01 == try br.takeLeb128(u1)});
2614 try parseDumpInit(step, reader, bw);2524 try parseDumpInit(step, br, bw);
2615 }2525 }
2616 },2526 },
2617 .@"export" => {2527 .@"export" => {
2618 var i: u32 = 0;2528 var i: u32 = 0;
2619 while (i < entries) : (i += 1) {2529 while (i < entries) : (i += 1) {
2620 const name_len = try std.leb.readUleb128(u32, reader);2530 const name = try br.take(try br.takeLeb128(u32));
2621 const name = data[fbs.pos..][0..name_len];2531 const kind = br.takeEnum(std.wasm.ExternalKind, .little) catch |err| switch (err) {
2622 fbs.pos += name_len;2532 error.InvalidEnumTag => return step.fail("invalid export kind value", .{}),
2623 const kind_byte = try std.leb.readUleb128(u8, reader);2533 else => |e| return e,
2624 const kind = std.enums.fromInt(std.wasm.ExternalKind, kind_byte) orelse {
2625 return step.fail("invalid export kind value '{d}'", .{kind_byte});
2626 };2534 };
2627 const index = try std.leb.readUleb128(u32, reader);2535 const index = try br.takeLeb128(u32);
2628 try bw.print(2536 try bw.print(
2629 \\name {s}2537 \\name {s}
2630 \\kind {s}2538 \\kind {s}
...@@ -2636,14 +2544,14 @@ const WasmDumper = struct {...@@ -2636,14 +2544,14 @@ const WasmDumper = struct {
2636 .element => {2544 .element => {
2637 var i: u32 = 0;2545 var i: u32 = 0;
2638 while (i < entries) : (i += 1) {2546 while (i < entries) : (i += 1) {
2639 try bw.print("table index {d}\n", .{try std.leb.readUleb128(u32, reader)});2547 try bw.print("table index {d}\n", .{try br.takeLeb128(u32)});
2640 try parseDumpInit(step, reader, bw);2548 try parseDumpInit(step, br, bw);
26412549
2642 const function_indexes = try std.leb.readUleb128(u32, reader);2550 const function_indexes = try br.takeLeb128(u32);
2643 var function_index: u32 = 0;2551 var function_index: u32 = 0;
2644 try bw.print("indexes {d}\n", .{function_indexes});2552 try bw.print("indexes {d}\n", .{function_indexes});
2645 while (function_index < function_indexes) : (function_index += 1) {2553 while (function_index < function_indexes) : (function_index += 1) {
2646 try bw.print("index {d}\n", .{try std.leb.readUleb128(u32, reader)});2554 try bw.print("index {d}\n", .{try br.takeLeb128(u32)});
2647 }2555 }
2648 }2556 }
2649 },2557 },
...@@ -2651,101 +2559,95 @@ const WasmDumper = struct {...@@ -2651,101 +2559,95 @@ const WasmDumper = struct {
2651 .data => {2559 .data => {
2652 var i: u32 = 0;2560 var i: u32 = 0;
2653 while (i < entries) : (i += 1) {2561 while (i < entries) : (i += 1) {
2654 const flags = try std.leb.readUleb128(u32, reader);2562 const flags: packed struct(u32) {
2655 const index = if (flags & 0x02 != 0)2563 passive: bool,
2656 try std.leb.readUleb128(u32, reader)2564 memidx: bool,
2657 else2565 unused: u30,
2658 0;2566 } = @bitCast(try br.takeLeb128(u32));
2567 const index = if (flags.memidx) try br.takeLeb128(u32) else 0;
2659 try bw.print("memory index 0x{x}\n", .{index});2568 try bw.print("memory index 0x{x}\n", .{index});
2660 if (flags == 0) {2569 if (!flags.passive) try parseDumpInit(step, br, bw);
2661 try parseDumpInit(step, reader, bw);2570 const size = try br.takeLeb128(u32);
2662 }
2663
2664 const size = try std.leb.readUleb128(u32, reader);
2665 try bw.print("size {d}\n", .{size});2571 try bw.print("size {d}\n", .{size});
2666 try reader.skipBytes(size, .{}); // we do not care about the content of the segments2572 try br.discard(size); // we do not care about the content of the segments
2667 }2573 }
2668 },2574 },
2669 else => unreachable,2575 else => unreachable,
2670 }2576 }
2671 }2577 }
26722578
2673 fn parseDumpType(step: *Step, comptime E: type, reader: anytype, bw: *std.io.BufferedWriter) !E {2579 fn parseDumpType(step: *Step, comptime E: type, br: *std.io.BufferedReader, bw: *std.io.BufferedWriter) !E {
2674 const byte = try reader.readByte();2580 const tag = br.takeEnum(E, .little) catch |err| switch (err) {
2675 const tag = std.enums.fromInt(E, byte) orelse {2581 error.InvalidEnumTag => return step.fail("invalid wasm type value", .{}),
2676 return step.fail("invalid wasm type value '{d}'", .{byte});2582 else => |e| return e,
2677 };2583 };
2678 try bw.print("type {s}\n", .{@tagName(tag)});2584 try bw.print("type {s}\n", .{@tagName(tag)});
2679 return tag;2585 return tag;
2680 }2586 }
26812587
2682 fn parseDumpLimits(reader: anytype, bw: *std.io.BufferedWriter) !void {2588 fn parseDumpLimits(br: *std.io.BufferedReader, bw: *std.io.BufferedWriter) !void {
2683 const flags = try std.leb.readUleb128(u8, reader);2589 const flags = try br.takeLeb128(u8);
2684 const min = try std.leb.readUleb128(u32, reader);2590 const min = try br.takeLeb128(u32);
26852591
2686 try bw.print("min {x}\n", .{min});2592 try bw.print("min {x}\n", .{min});
2687 if (flags != 0) {2593 if (flags != 0) try bw.print("max {x}\n", .{try br.takeLeb128(u32)});
2688 try bw.print("max {x}\n", .{try std.leb.readUleb128(u32, reader)});
2689 }
2690 }2594 }
26912595
2692 fn parseDumpInit(step: *Step, reader: anytype, bw: *std.io.BufferedWriter) !void {2596 fn parseDumpInit(step: *Step, br: *std.io.BufferedReader, bw: *std.io.BufferedWriter) !void {
2693 const byte = try reader.readByte();2597 const opcode = br.takeEnum(std.wasm.Opcode, .little) catch |err| switch (err) {
2694 const opcode = std.enums.fromInt(std.wasm.Opcode, byte) orelse {2598 error.InvalidEnumTag => return step.fail("invalid wasm opcode", .{}),
2695 return step.fail("invalid wasm opcode '{d}'", .{byte});2599 else => |e| return e,
2696 };2600 };
2697 switch (opcode) {2601 switch (opcode) {
2698 .i32_const => try bw.print("i32.const {x}\n", .{try std.leb.readIleb128(i32, reader)}),2602 .i32_const => try bw.print("i32.const {x}\n", .{try br.takeLeb128(i32)}),
2699 .i64_const => try bw.print("i64.const {x}\n", .{try std.leb.readIleb128(i64, reader)}),2603 .i64_const => try bw.print("i64.const {x}\n", .{try br.takeLeb128(i64)}),
2700 .f32_const => try bw.print("f32.const {x}\n", .{@as(f32, @bitCast(try reader.readInt(u32, .little)))}),2604 .f32_const => try bw.print("f32.const {x}\n", .{@as(f32, @bitCast(try br.takeInt(u32, .little)))}),
2701 .f64_const => try bw.print("f64.const {x}\n", .{@as(f64, @bitCast(try reader.readInt(u64, .little)))}),2605 .f64_const => try bw.print("f64.const {x}\n", .{@as(f64, @bitCast(try br.takeInt(u64, .little)))}),
2702 .global_get => try bw.print("global.get {x}\n", .{try std.leb.readUleb128(u32, reader)}),2606 .global_get => try bw.print("global.get {x}\n", .{try br.takeLeb128(u32)}),
2703 else => unreachable,2607 else => unreachable,
2704 }2608 }
2705 const end_opcode = try std.leb.readUleb128(u8, reader);2609 const end_opcode = try br.takeLeb128(u8);
2706 if (end_opcode != @intFromEnum(std.wasm.Opcode.end)) {2610 if (end_opcode != @intFromEnum(std.wasm.Opcode.end)) {
2707 return step.fail("expected 'end' opcode in init expression", .{});2611 return step.fail("expected 'end' opcode in init expression", .{});
2708 }2612 }
2709 }2613 }
27102614
2711 /// https://webassembly.github.io/spec/core/appendix/custom.html2615 /// https://webassembly.github.io/spec/core/appendix/custom.html
2712 fn parseDumpNames(step: *Step, reader: anytype, bw: *std.io.BufferedWriter, data: []const u8) !void {2616 fn parseDumpNames(step: *Step, br: *std.io.BufferedReader, bw: *std.io.BufferedWriter) !void {
2713 while (reader.context.pos < data.len) {2617 var subsection_br: std.io.BufferedReader = undefined;
2714 switch (try parseDumpType(step, std.wasm.NameSubsection, reader, bw)) {2618 while (br.seek < br.storageBuffer().len) {
2619 switch (try parseDumpType(step, std.wasm.NameSubsection, br, bw)) {
2715 // The module name subsection ... consists of a single name2620 // The module name subsection ... consists of a single name
2716 // that is assigned to the module itself.2621 // that is assigned to the module itself.
2717 .module => {2622 .module => {
2718 const size = try std.leb.readUleb128(u32, reader);2623 subsection_br.initFixed(try br.take(try br.takeLeb128(u32)));
2719 const name_len = try std.leb.readUleb128(u32, reader);2624 const name = try subsection_br.take(try subsection_br.takeLeb128(u32));
2720 if (size != name_len + 1) return error.BadSubsectionSize;2625 try bw.print(
2721 if (reader.context.pos + name_len > data.len) return error.UnexpectedEndOfStream;2626 \\name {s}
2722 try bw.print("name {s}\n", .{data[reader.context.pos..][0..name_len]});2627 \\
2723 reader.context.pos += name_len;2628 , .{name});
2629 if (subsection_br.seek != subsection_br.storageBuffer().len) return error.BadSubsectionSize;
2724 },2630 },
27252631
2726 // The function name subsection ... consists of a name map2632 // The function name subsection ... consists of a name map
2727 // assigning function names to function indices.2633 // assigning function names to function indices.
2728 .function, .global, .data_segment => {2634 .function, .global, .data_segment => {
2729 const size = try std.leb.readUleb128(u32, reader);2635 subsection_br.initFixed(try br.take(try br.takeLeb128(u32)));
2730 const entries = try std.leb.readUleb128(u32, reader);2636 const entries = try br.takeLeb128(u32);
2731 try bw.print(2637 try bw.print(
2732 \\size {d}
2733 \\names {d}2638 \\names {d}
2734 \\2639 \\
2735 , .{ size, entries });2640 , .{entries});
2736 for (0..entries) |_| {2641 for (0..entries) |_| {
2737 const index = try std.leb.readUleb128(u32, reader);2642 const index = try br.takeLeb128(u32);
2738 const name_len = try std.leb.readUleb128(u32, reader);2643 const name = try br.take(try br.takeLeb128(u32));
2739 if (reader.context.pos + name_len > data.len) return error.UnexpectedEndOfStream;
2740 const name = data[reader.context.pos..][0..name_len];
2741 reader.context.pos += name.len;
2742
2743 try bw.print(2644 try bw.print(
2744 \\index {d}2645 \\index {d}
2745 \\name {s}2646 \\name {s}
2746 \\2647 \\
2747 , .{ index, name });2648 , .{ index, name });
2748 }2649 }
2650 if (subsection_br.seek != subsection_br.storageBuffer().len) return error.BadSubsectionSize;
2749 },2651 },
27502652
2751 // The local name subsection ... consists of an indirect name2653 // The local name subsection ... consists of an indirect name
...@@ -2760,52 +2662,49 @@ const WasmDumper = struct {...@@ -2760,52 +2662,49 @@ const WasmDumper = struct {
2760 }2662 }
2761 }2663 }
27622664
2763 fn parseDumpProducers(reader: anytype, bw: *std.io.BufferedWriter, data: []const u8) !void {2665 fn parseDumpProducers(br: *std.io.BufferedReader, bw: *std.io.BufferedWriter) !void {
2764 const field_count = try std.leb.readUleb128(u32, reader);2666 const field_count = try br.takeLeb128(u32);
2765 try bw.print("fields {d}\n", .{field_count});2667 try bw.print(
2668 \\fields {d}
2669 \\
2670 , .{field_count});
2766 var current_field: u32 = 0;2671 var current_field: u32 = 0;
2767 while (current_field < field_count) : (current_field += 1) {2672 while (current_field < field_count) : (current_field += 1) {
2768 const field_name_length = try std.leb.readUleb128(u32, reader);2673 const field_name = try br.take(try br.takeLeb128(u32));
2769 const field_name = data[reader.context.pos..][0..field_name_length];2674 const value_count = try br.takeLeb128(u32);
2770 reader.context.pos += field_name_length;
2771
2772 const value_count = try std.leb.readUleb128(u32, reader);
2773 try bw.print(2675 try bw.print(
2774 \\field_name {s}2676 \\field_name {s}
2775 \\values {d}2677 \\values {d}
2678 \\
2776 , .{ field_name, value_count });2679 , .{ field_name, value_count });
2777 try bw.writeByte('\n');
2778 var current_value: u32 = 0;2680 var current_value: u32 = 0;
2779 while (current_value < value_count) : (current_value += 1) {2681 while (current_value < value_count) : (current_value += 1) {
2780 const value_length = try std.leb.readUleb128(u32, reader);2682 const value = try br.take(try br.takeLeb128(u32));
2781 const value = data[reader.context.pos..][0..value_length];2683 const version = try br.take(try br.takeLeb128(u32));
2782 reader.context.pos += value_length;
2783
2784 const version_length = try std.leb.readUleb128(u32, reader);
2785 const version = data[reader.context.pos..][0..version_length];
2786 reader.context.pos += version_length;
2787
2788 try bw.print(2684 try bw.print(
2789 \\value_name {s}2685 \\value_name {s}
2790 \\version {s}2686 \\version {s}
2687 \\
2791 , .{ value, version });2688 , .{ value, version });
2792 try bw.writeByte('\n');
2793 }2689 }
2794 }2690 }
2795 }2691 }
27962692
2797 fn parseDumpFeatures(reader: anytype, bw: *std.io.BufferedWriter, data: []const u8) !void {2693 fn parseDumpFeatures(br: *std.io.BufferedReader, bw: *std.io.BufferedWriter) !void {
2798 const feature_count = try std.leb.readUleb128(u32, reader);2694 const feature_count = try br.takeLeb128(u32);
2799 try bw.print("features {d}\n", .{feature_count});2695 try bw.print(
2696 \\features {d}
2697 \\
2698 , .{feature_count});
28002699
2801 var index: u32 = 0;2700 var index: u32 = 0;
2802 while (index < feature_count) : (index += 1) {2701 while (index < feature_count) : (index += 1) {
2803 const prefix_byte = try std.leb.readUleb128(u8, reader);2702 const prefix_byte = try br.takeLeb128(u8);
2804 const name_length = try std.leb.readUleb128(u32, reader);2703 const feature_name = try br.take(try br.takeLeb128(u32));
2805 const feature_name = data[reader.context.pos..][0..name_length];2704 try bw.print(
2806 reader.context.pos += name_length;2705 \\{c} {s}
28072706 \\
2808 try bw.print("{c} {s}\n", .{ prefix_byte, feature_name });2707 , .{ prefix_byte, feature_name });
2809 }2708 }
2810 }2709 }
2811};2710};
lib/std/Build/Step/Compile.zig+6-6
...@@ -409,7 +409,7 @@ pub fn create(owner: *std.Build, options: Options) *Compile {...@@ -409,7 +409,7 @@ pub fn create(owner: *std.Build, options: Options) *Compile {
409 .linkage = options.linkage,409 .linkage = options.linkage,
410 .kind = options.kind,410 .kind = options.kind,
411 .name = name,411 .name = name,
412 .step = Step.init(.{412 .step = .init(.{
413 .id = base_id,413 .id = base_id,
414 .name = step_name,414 .name = step_name,
415 .owner = owner,415 .owner = owner,
...@@ -1542,7 +1542,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 {...@@ -1542,7 +1542,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 {
1542 if (compile.kind == .lib and compile.linkage != null and compile.linkage.? == .dynamic) {1542 if (compile.kind == .lib and compile.linkage != null and compile.linkage.? == .dynamic) {
1543 if (compile.version) |version| {1543 if (compile.version) |version| {
1544 try zig_args.append("--version");1544 try zig_args.append("--version");
1545 try zig_args.append(b.fmt("{}", .{version}));1545 try zig_args.append(b.fmt("{f}", .{version}));
1546 }1546 }
15471547
1548 if (compile.rootModuleTarget().os.tag.isDarwin()) {1548 if (compile.rootModuleTarget().os.tag.isDarwin()) {
...@@ -1704,7 +1704,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 {...@@ -1704,7 +1704,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 {
1704 const opt_zig_lib_dir = if (compile.zig_lib_dir) |dir|1704 const opt_zig_lib_dir = if (compile.zig_lib_dir) |dir|
1705 dir.getPath2(b, step)1705 dir.getPath2(b, step)
1706 else if (b.graph.zig_lib_directory.path) |_|1706 else if (b.graph.zig_lib_directory.path) |_|
1707 b.fmt("{}", .{b.graph.zig_lib_directory})1707 b.fmt("{f}", .{b.graph.zig_lib_directory})
1708 else1708 else
1709 null;1709 null;
17101710
...@@ -1830,7 +1830,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {...@@ -1830,7 +1830,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
1830 // Update generated files1830 // Update generated files
1831 if (maybe_output_dir) |output_dir| {1831 if (maybe_output_dir) |output_dir| {
1832 if (compile.emit_directory) |lp| {1832 if (compile.emit_directory) |lp| {
1833 lp.path = b.fmt("{}", .{output_dir});1833 lp.path = b.fmt("{f}", .{output_dir});
1834 }1834 }
18351835
1836 // zig fmt: off1836 // zig fmt: off
...@@ -1970,13 +1970,13 @@ fn checkCompileErrors(compile: *Compile) !void {...@@ -1970,13 +1970,13 @@ fn checkCompileErrors(compile: *Compile) !void {
19701970
1971 const actual_errors = ae: {1971 const actual_errors = ae: {
1972 var aw: std.io.AllocatingWriter = undefined;1972 var aw: std.io.AllocatingWriter = undefined;
1973 const bw = aw.init(arena);1973 aw.init(arena);
1974 defer aw.deinit();1974 defer aw.deinit();
1975 try actual_eb.renderToWriter(.{1975 try actual_eb.renderToWriter(.{
1976 .ttyconf = .no_color,1976 .ttyconf = .no_color,
1977 .include_reference_trace = false,1977 .include_reference_trace = false,
1978 .include_source_line = false,1978 .include_source_line = false,
1979 }, bw);1979 }, &aw.buffered_writer);
1980 break :ae try aw.toOwnedSlice();1980 break :ae try aw.toOwnedSlice();
1981 };1981 };
19821982
lib/std/Build/Step/ConfigHeader.zig+89-137
...@@ -87,7 +87,7 @@ pub fn create(owner: *std.Build, options: Options) *ConfigHeader {...@@ -87,7 +87,7 @@ pub fn create(owner: *std.Build, options: Options) *ConfigHeader {
87 owner.fmt("configure {s} header to {s}", .{ @tagName(options.style), include_path });87 owner.fmt("configure {s} header to {s}", .{ @tagName(options.style), include_path });
8888
89 config_header.* = .{89 config_header.* = .{
90 .step = Step.init(.{90 .step = .init(.{
91 .id = base_id,91 .id = base_id,
92 .name = name,92 .name = name,
93 .owner = owner,93 .owner = owner,
...@@ -95,7 +95,7 @@ pub fn create(owner: *std.Build, options: Options) *ConfigHeader {...@@ -95,7 +95,7 @@ pub fn create(owner: *std.Build, options: Options) *ConfigHeader {
95 .first_ret_addr = options.first_ret_addr orelse @returnAddress(),95 .first_ret_addr = options.first_ret_addr orelse @returnAddress(),
96 }),96 }),
97 .style = options.style,97 .style = options.style,
98 .values = std.StringArrayHashMap(Value).init(owner.allocator),98 .values = .init(owner.allocator),
9999
100 .max_bytes = options.max_bytes,100 .max_bytes = options.max_bytes,
101 .include_path = include_path,101 .include_path = include_path,
...@@ -195,8 +195,10 @@ fn make(step: *Step, options: Step.MakeOptions) !void {...@@ -195,8 +195,10 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
195 man.hash.addBytes(config_header.include_path);195 man.hash.addBytes(config_header.include_path);
196 man.hash.addOptionalBytes(config_header.include_guard_override);196 man.hash.addOptionalBytes(config_header.include_guard_override);
197197
198 var output = std.ArrayList(u8).init(gpa);198 var aw: std.io.AllocatingWriter = undefined;
199 defer output.deinit();199 aw.init(gpa);
200 defer aw.deinit();
201 const bw = &aw.buffered_writer;
200202
201 const header_text = "This file was generated by ConfigHeader using the Zig Build System.";203 const header_text = "This file was generated by ConfigHeader using the Zig Build System.";
202 const c_generated_line = "/* " ++ header_text ++ " */\n";204 const c_generated_line = "/* " ++ header_text ++ " */\n";
...@@ -204,40 +206,41 @@ fn make(step: *Step, options: Step.MakeOptions) !void {...@@ -204,40 +206,41 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
204206
205 switch (config_header.style) {207 switch (config_header.style) {
206 .autoconf_undef, .autoconf, .autoconf_at => |file_source| {208 .autoconf_undef, .autoconf, .autoconf_at => |file_source| {
207 try output.appendSlice(c_generated_line);209 try bw.writeAll(c_generated_line);
208 const src_path = file_source.getPath2(b, step);210 const src_path = file_source.getPath2(b, step);
209 const contents = std.fs.cwd().readFileAlloc(arena, src_path, config_header.max_bytes) catch |err| {211 const contents = std.fs.cwd().readFileAlloc(src_path, arena, .limited(config_header.max_bytes)) catch |err| {
210 return step.fail("unable to read autoconf input file '{s}': {s}", .{212 return step.fail("unable to read autoconf input file '{s}': {s}", .{
211 src_path, @errorName(err),213 src_path, @errorName(err),
212 });214 });
213 };215 };
214 switch (config_header.style) {216 switch (config_header.style) {
215 .autoconf_undef, .autoconf => try render_autoconf_undef(step, contents, &output, config_header.values, src_path),217 .autoconf_undef, .autoconf => try render_autoconf_undef(step, contents, bw, config_header.values, src_path),
216 .autoconf_at => try render_autoconf_at(step, contents, &output, config_header.values, src_path),218 .autoconf_at => try render_autoconf_at(step, contents, &aw, config_header.values, src_path),
217 else => unreachable,219 else => unreachable,
218 }220 }
219 },221 },
220 .cmake => |file_source| {222 .cmake => |file_source| {
221 try output.appendSlice(c_generated_line);223 try bw.writeAll(c_generated_line);
222 const src_path = file_source.getPath2(b, step);224 const src_path = file_source.getPath2(b, step);
223 const contents = std.fs.cwd().readFileAlloc(arena, src_path, config_header.max_bytes) catch |err| {225 const contents = std.fs.cwd().readFileAlloc(src_path, arena, .limited(config_header.max_bytes)) catch |err| {
224 return step.fail("unable to read cmake input file '{s}': {s}", .{226 return step.fail("unable to read cmake input file '{s}': {s}", .{
225 src_path, @errorName(err),227 src_path, @errorName(err),
226 });228 });
227 };229 };
228 try render_cmake(step, contents, &output, config_header.values, src_path);230 try render_cmake(step, contents, bw, config_header.values, src_path);
229 },231 },
230 .blank => {232 .blank => {
231 try output.appendSlice(c_generated_line);233 try bw.writeAll(c_generated_line);
232 try render_blank(&output, config_header.values, config_header.include_path, config_header.include_guard_override);234 try render_blank(gpa, bw, config_header.values, config_header.include_path, config_header.include_guard_override);
233 },235 },
234 .nasm => {236 .nasm => {
235 try output.appendSlice(asm_generated_line);237 try bw.writeAll(asm_generated_line);
236 try render_nasm(&output, config_header.values);238 try render_nasm(bw, config_header.values);
237 },239 },
238 }240 }
239241
240 man.hash.addBytes(output.items);242 const output = aw.getWritten();
243 man.hash.addBytes(output);
241244
242 if (try step.cacheHit(&man)) {245 if (try step.cacheHit(&man)) {
243 const digest = man.final();246 const digest = man.final();
...@@ -256,13 +259,13 @@ fn make(step: *Step, options: Step.MakeOptions) !void {...@@ -256,13 +259,13 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
256 const sub_path_dirname = std.fs.path.dirname(sub_path).?;259 const sub_path_dirname = std.fs.path.dirname(sub_path).?;
257260
258 b.cache_root.handle.makePath(sub_path_dirname) catch |err| {261 b.cache_root.handle.makePath(sub_path_dirname) catch |err| {
259 return step.fail("unable to make path '{}{s}': {s}", .{262 return step.fail("unable to make path '{f}{s}': {s}", .{
260 b.cache_root, sub_path_dirname, @errorName(err),263 b.cache_root, sub_path_dirname, @errorName(err),
261 });264 });
262 };265 };
263266
264 b.cache_root.handle.writeFile(.{ .sub_path = sub_path, .data = output.items }) catch |err| {267 b.cache_root.handle.writeFile(.{ .sub_path = sub_path, .data = output }) catch |err| {
265 return step.fail("unable to write file '{}{s}': {s}", .{268 return step.fail("unable to write file '{f}{s}': {s}", .{
266 b.cache_root, sub_path, @errorName(err),269 b.cache_root, sub_path, @errorName(err),
267 });270 });
268 };271 };
...@@ -274,7 +277,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {...@@ -274,7 +277,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
274fn render_autoconf_undef(277fn render_autoconf_undef(
275 step: *Step,278 step: *Step,
276 contents: []const u8,279 contents: []const u8,
277 output: *std.ArrayList(u8),280 bw: *std.io.BufferedWriter,
278 values: std.StringArrayHashMap(Value),281 values: std.StringArrayHashMap(Value),
279 src_path: []const u8,282 src_path: []const u8,
280) !void {283) !void {
...@@ -289,15 +292,15 @@ fn render_autoconf_undef(...@@ -289,15 +292,15 @@ fn render_autoconf_undef(
289 var line_it = std.mem.splitScalar(u8, contents, '\n');292 var line_it = std.mem.splitScalar(u8, contents, '\n');
290 while (line_it.next()) |line| : (line_index += 1) {293 while (line_it.next()) |line| : (line_index += 1) {
291 if (!std.mem.startsWith(u8, line, "#")) {294 if (!std.mem.startsWith(u8, line, "#")) {
292 try output.appendSlice(line);295 try bw.writeAll(line);
293 try output.appendSlice("\n");296 try bw.writeByte('\n');
294 continue;297 continue;
295 }298 }
296 var it = std.mem.tokenizeAny(u8, line[1..], " \t\r");299 var it = std.mem.tokenizeAny(u8, line[1..], " \t\r");
297 const undef = it.next().?;300 const undef = it.next().?;
298 if (!std.mem.eql(u8, undef, "undef")) {301 if (!std.mem.eql(u8, undef, "undef")) {
299 try output.appendSlice(line);302 try bw.writeAll(line);
300 try output.appendSlice("\n");303 try bw.writeByte('\n');
301 continue;304 continue;
302 }305 }
303 const name = it.next().?;306 const name = it.next().?;
...@@ -309,7 +312,7 @@ fn render_autoconf_undef(...@@ -309,7 +312,7 @@ fn render_autoconf_undef(
309 continue;312 continue;
310 };313 };
311 is_used.set(index);314 is_used.set(index);
312 try renderValueC(output, name, values.values()[index]);315 try renderValueC(bw, name, values.values()[index]);
313 }316 }
314317
315 var unused_value_it = is_used.iterator(.{ .kind = .unset });318 var unused_value_it = is_used.iterator(.{ .kind = .unset });
...@@ -326,12 +329,13 @@ fn render_autoconf_undef(...@@ -326,12 +329,13 @@ fn render_autoconf_undef(
326fn render_autoconf_at(329fn render_autoconf_at(
327 step: *Step,330 step: *Step,
328 contents: []const u8,331 contents: []const u8,
329 output: *std.ArrayList(u8),332 aw: *std.io.AllocatingWriter,
330 values: std.StringArrayHashMap(Value),333 values: std.StringArrayHashMap(Value),
331 src_path: []const u8,334 src_path: []const u8,
332) !void {335) !void {
333 const build = step.owner;336 const build = step.owner;
334 const allocator = build.allocator;337 const allocator = build.allocator;
338 const bw = &aw.buffered_writer;
335339
336 const used = allocator.alloc(bool, values.count()) catch @panic("OOM");340 const used = allocator.alloc(bool, values.count()) catch @panic("OOM");
337 for (used) |*u| u.* = false;341 for (used) |*u| u.* = false;
...@@ -343,11 +347,11 @@ fn render_autoconf_at(...@@ -343,11 +347,11 @@ fn render_autoconf_at(
343 while (line_it.next()) |line| : (line_index += 1) {347 while (line_it.next()) |line| : (line_index += 1) {
344 const last_line = line_it.index == line_it.buffer.len;348 const last_line = line_it.index == line_it.buffer.len;
345349
346 const old_len = output.items.len;350 const old_len = aw.getWritten().len;
347 expand_variables_autoconf_at(output, line, values, used) catch |err| switch (err) {351 expand_variables_autoconf_at(bw, line, values, used) catch |err| switch (err) {
348 error.MissingValue => {352 error.MissingValue => {
349 const name = output.items[old_len..];353 const name = aw.getWritten()[old_len..];
350 defer output.shrinkRetainingCapacity(old_len);354 defer aw.shrinkRetainingCapacity(old_len);
351 try step.addError("{s}:{d}: error: unspecified config header value: '{s}'", .{355 try step.addError("{s}:{d}: error: unspecified config header value: '{s}'", .{
352 src_path, line_index + 1, name,356 src_path, line_index + 1, name,
353 });357 });
...@@ -362,9 +366,7 @@ fn render_autoconf_at(...@@ -362,9 +366,7 @@ fn render_autoconf_at(
362 continue;366 continue;
363 },367 },
364 };368 };
365 if (!last_line) {369 if (!last_line) try bw.writeByte('\n');
366 try output.append('\n');
367 }
368 }370 }
369371
370 for (values.unmanaged.entries.slice().items(.key), used) |name, u| {372 for (values.unmanaged.entries.slice().items(.key), used) |name, u| {
...@@ -374,15 +376,13 @@ fn render_autoconf_at(...@@ -374,15 +376,13 @@ fn render_autoconf_at(
374 }376 }
375 }377 }
376378
377 if (any_errors) {379 if (any_errors) return error.MakeFailed;
378 return error.MakeFailed;
379 }
380}380}
381381
382fn render_cmake(382fn render_cmake(
383 step: *Step,383 step: *Step,
384 contents: []const u8,384 contents: []const u8,
385 output: *std.ArrayList(u8),385 bw: *std.io.BufferedWriter,
386 values: std.StringArrayHashMap(Value),386 values: std.StringArrayHashMap(Value),
387 src_path: []const u8,387 src_path: []const u8,
388) !void {388) !void {
...@@ -417,10 +417,8 @@ fn render_cmake(...@@ -417,10 +417,8 @@ fn render_cmake(
417 defer allocator.free(line);417 defer allocator.free(line);
418418
419 if (!std.mem.startsWith(u8, line, "#")) {419 if (!std.mem.startsWith(u8, line, "#")) {
420 try output.appendSlice(line);420 try bw.writeAll(line);
421 if (!last_line) {421 if (!last_line) try bw.writeByte('\n');
422 try output.appendSlice("\n");
423 }
424 continue;422 continue;
425 }423 }
426 var it = std.mem.tokenizeAny(u8, line[1..], " \t\r");424 var it = std.mem.tokenizeAny(u8, line[1..], " \t\r");
...@@ -428,10 +426,8 @@ fn render_cmake(...@@ -428,10 +426,8 @@ fn render_cmake(
428 if (!std.mem.eql(u8, cmakedefine, "cmakedefine") and426 if (!std.mem.eql(u8, cmakedefine, "cmakedefine") and
429 !std.mem.eql(u8, cmakedefine, "cmakedefine01"))427 !std.mem.eql(u8, cmakedefine, "cmakedefine01"))
430 {428 {
431 try output.appendSlice(line);429 try bw.writeAll(line);
432 if (!last_line) {430 if (!last_line) try bw.writeByte('\n');
433 try output.appendSlice("\n");
434 }
435 continue;431 continue;
436 }432 }
437433
...@@ -502,7 +498,7 @@ fn render_cmake(...@@ -502,7 +498,7 @@ fn render_cmake(
502 value = Value{ .ident = it.rest() };498 value = Value{ .ident = it.rest() };
503 }499 }
504500
505 try renderValueC(output, name, value);501 try renderValueC(bw, name, value);
506 }502 }
507503
508 if (any_errors) {504 if (any_errors) {
...@@ -511,13 +507,14 @@ fn render_cmake(...@@ -511,13 +507,14 @@ fn render_cmake(
511}507}
512508
513fn render_blank(509fn render_blank(
514 output: *std.ArrayList(u8),510 gpa: std.mem.Allocator,
511 bw: *std.io.BufferedWriter,
515 defines: std.StringArrayHashMap(Value),512 defines: std.StringArrayHashMap(Value),
516 include_path: []const u8,513 include_path: []const u8,
517 include_guard_override: ?[]const u8,514 include_guard_override: ?[]const u8,
518) !void {515) !void {
519 const include_guard_name = include_guard_override orelse blk: {516 const include_guard_name = include_guard_override orelse blk: {
520 const name = try output.allocator.dupe(u8, include_path);517 const name = try gpa.dupe(u8, include_path);
521 for (name) |*byte| {518 for (name) |*byte| {
522 switch (byte.*) {519 switch (byte.*) {
523 'a'...'z' => byte.* = byte.* - 'a' + 'A',520 'a'...'z' => byte.* = byte.* - 'a' + 'A',
...@@ -527,92 +524,53 @@ fn render_blank(...@@ -527,92 +524,53 @@ fn render_blank(
527 }524 }
528 break :blk name;525 break :blk name;
529 };526 };
527 defer if (include_guard_override == null) gpa.free(include_guard_name);
530528
531 try output.appendSlice("#ifndef ");529 try bw.print(
532 try output.appendSlice(include_guard_name);530 \\#ifndef {[0]s}
533 try output.appendSlice("\n#define ");531 \\#define {[0]s}
534 try output.appendSlice(include_guard_name);532 \\
535 try output.appendSlice("\n");533 , .{include_guard_name});
536534
537 const values = defines.values();535 const values = defines.values();
538 for (defines.keys(), 0..) |name, i| {536 for (defines.keys(), 0..) |name, i| try renderValueC(bw, name, values[i]);
539 try renderValueC(output, name, values[i]);
540 }
541537
542 try output.appendSlice("#endif /* ");538 try bw.print(
543 try output.appendSlice(include_guard_name);539 \\#endif /* {s} */
544 try output.appendSlice(" */\n");540 \\
541 , .{include_guard_name});
545}542}
546543
547fn render_nasm(output: *std.ArrayList(u8), defines: std.StringArrayHashMap(Value)) !void {544fn render_nasm(bw: *std.io.BufferedWriter, defines: std.StringArrayHashMap(Value)) !void {
548 const values = defines.values();545 for (defines.keys(), defines.values()) |name, value| try renderValueNasm(bw, name, value);
549 for (defines.keys(), 0..) |name, i| {
550 try renderValueNasm(output, name, values[i]);
551 }
552}546}
553547
554fn renderValueC(output: *std.ArrayList(u8), name: []const u8, value: Value) !void {548fn renderValueC(bw: *std.io.BufferedWriter, name: []const u8, value: Value) !void {
555 switch (value) {549 switch (value) {
556 .undef => {550 .undef => try bw.print("/* #undef {s} */\n", .{name}),
557 try output.appendSlice("/* #undef ");551 .defined => try bw.print("#define {s}\n", .{name}),
558 try output.appendSlice(name);552 .boolean => |b| try bw.print("#define {s} {c}\n", .{ name, @as(u8, '0') + @intFromBool(b) }),
559 try output.appendSlice(" */\n");553 .int => |i| try bw.print("#define {s} {d}\n", .{ name, i }),
560 },554 .ident => |ident| try bw.print("#define {s} {s}\n", .{ name, ident }),
561 .defined => {555 // TODO: use C-specific escaping instead of zig string literals
562 try output.appendSlice("#define ");556 .string => |string| try bw.print("#define {s} \"{f}\"\n", .{ name, std.zig.fmtEscapes(string) }),
563 try output.appendSlice(name);
564 try output.appendSlice("\n");
565 },
566 .boolean => |b| {
567 try output.appendSlice("#define ");
568 try output.appendSlice(name);
569 try output.appendSlice(if (b) " 1\n" else " 0\n");
570 },
571 .int => |i| {
572 try output.print("#define {s} {d}\n", .{ name, i });
573 },
574 .ident => |ident| {
575 try output.print("#define {s} {s}\n", .{ name, ident });
576 },
577 .string => |string| {
578 // TODO: use C-specific escaping instead of zig string literals
579 try output.print("#define {s} \"{}\"\n", .{ name, std.zig.fmtEscapes(string) });
580 },
581 }557 }
582}558}
583559
584fn renderValueNasm(output: *std.ArrayList(u8), name: []const u8, value: Value) !void {560fn renderValueNasm(bw: *std.io.BufferedWriter, name: []const u8, value: Value) !void {
585 switch (value) {561 switch (value) {
586 .undef => {562 .undef => try bw.print("; %undef {s}\n", .{name}),
587 try output.appendSlice("; %undef ");563 .defined => try bw.print("%define {s}\n", .{name}),
588 try output.appendSlice(name);564 .boolean => |b| try bw.print("%define {s} {c}\n", .{ name, @as(u8, '0') + @intFromBool(b) }),
589 try output.appendSlice("\n");565 .int => |i| try bw.print("%define {s} {d}\n", .{ name, i }),
590 },566 .ident => |ident| try bw.print("%define {s} {s}\n", .{ name, ident }),
591 .defined => {567 // TODO: use nasm-specific escaping instead of zig string literals
592 try output.appendSlice("%define ");568 .string => |string| try bw.print("%define {s} \"{f}\"\n", .{ name, std.zig.fmtEscapes(string) }),
593 try output.appendSlice(name);
594 try output.appendSlice("\n");
595 },
596 .boolean => |b| {
597 try output.appendSlice("%define ");
598 try output.appendSlice(name);
599 try output.appendSlice(if (b) " 1\n" else " 0\n");
600 },
601 .int => |i| {
602 try output.print("%define {s} {d}\n", .{ name, i });
603 },
604 .ident => |ident| {
605 try output.print("%define {s} {s}\n", .{ name, ident });
606 },
607 .string => |string| {
608 // TODO: use nasm-specific escaping instead of zig string literals
609 try output.print("%define {s} \"{}\"\n", .{ name, std.zig.fmtEscapes(string) });
610 },
611 }569 }
612}570}
613571
614fn expand_variables_autoconf_at(572fn expand_variables_autoconf_at(
615 output: *std.ArrayList(u8),573 bw: *std.io.BufferedWriter,
616 contents: []const u8,574 contents: []const u8,
617 values: std.StringArrayHashMap(Value),575 values: std.StringArrayHashMap(Value),
618 used: []bool,576 used: []bool,
...@@ -637,23 +595,17 @@ fn expand_variables_autoconf_at(...@@ -637,23 +595,17 @@ fn expand_variables_autoconf_at(
637 const key = contents[curr + 1 .. close_pos];595 const key = contents[curr + 1 .. close_pos];
638 const index = values.getIndex(key) orelse {596 const index = values.getIndex(key) orelse {
639 // Report the missing key to the caller.597 // Report the missing key to the caller.
640 try output.appendSlice(key);598 try bw.writeAll(key);
641 return error.MissingValue;599 return error.MissingValue;
642 };600 };
643 const value = values.unmanaged.entries.slice().items(.value)[index];601 const value = values.unmanaged.entries.slice().items(.value)[index];
644 used[index] = true;602 used[index] = true;
645 try output.appendSlice(contents[source_offset..curr]);603 try bw.writeAll(contents[source_offset..curr]);
646 switch (value) {604 switch (value) {
647 .undef, .defined => {},605 .undef, .defined => {},
648 .boolean => |b| {606 .boolean => |b| try bw.writeByte(@as(u8, '0') + @intFromBool(b)),
649 try output.append(if (b) '1' else '0');607 .int => |i| try bw.print("{d}", .{i}),
650 },608 .ident, .string => |s| try bw.writeAll(s),
651 .int => |i| {
652 try output.writer().print("{d}", .{i});
653 },
654 .ident, .string => |s| {
655 try output.appendSlice(s);
656 },
657 }609 }
658610
659 curr = close_pos;611 curr = close_pos;
...@@ -661,7 +613,7 @@ fn expand_variables_autoconf_at(...@@ -661,7 +613,7 @@ fn expand_variables_autoconf_at(
661 }613 }
662 }614 }
663615
664 try output.appendSlice(contents[source_offset..]);616 try bw.writeAll(contents[source_offset..]);
665}617}
666618
667fn expand_variables_cmake(619fn expand_variables_cmake(
...@@ -669,7 +621,7 @@ fn expand_variables_cmake(...@@ -669,7 +621,7 @@ fn expand_variables_cmake(
669 contents: []const u8,621 contents: []const u8,
670 values: std.StringArrayHashMap(Value),622 values: std.StringArrayHashMap(Value),
671) ![]const u8 {623) ![]const u8 {
672 var result = std.ArrayList(u8).init(allocator);624 var result: std.ArrayList(u8) = .init(allocator);
673 errdefer result.deinit();625 errdefer result.deinit();
674626
675 const valid_varname_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789/_.+-";627 const valid_varname_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789/_.+-";
...@@ -681,7 +633,7 @@ fn expand_variables_cmake(...@@ -681,7 +633,7 @@ fn expand_variables_cmake(
681 source: usize,633 source: usize,
682 target: usize,634 target: usize,
683 };635 };
684 var var_stack = std.ArrayList(Position).init(allocator);636 var var_stack: std.ArrayList(Position) = .init(allocator);
685 defer var_stack.deinit();637 defer var_stack.deinit();
686 loop: while (curr < contents.len) : (curr += 1) {638 loop: while (curr < contents.len) : (curr += 1) {
687 switch (contents[curr]) {639 switch (contents[curr]) {
...@@ -801,7 +753,7 @@ fn testReplaceVariablesAutoconfAt(...@@ -801,7 +753,7 @@ fn testReplaceVariablesAutoconfAt(
801 expected: []const u8,753 expected: []const u8,
802 values: std.StringArrayHashMap(Value),754 values: std.StringArrayHashMap(Value),
803) !void {755) !void {
804 var output = std.ArrayList(u8).init(allocator);756 var output: std.ArrayList(u8) = .init(allocator);
805 defer output.deinit();757 defer output.deinit();
806758
807 const used = try allocator.alloc(bool, values.count());759 const used = try allocator.alloc(bool, values.count());
...@@ -828,7 +780,7 @@ fn testReplaceVariablesCMake(...@@ -828,7 +780,7 @@ fn testReplaceVariablesCMake(
828780
829test "expand_variables_autoconf_at simple cases" {781test "expand_variables_autoconf_at simple cases" {
830 const allocator = std.testing.allocator;782 const allocator = std.testing.allocator;
831 var values = std.StringArrayHashMap(Value).init(allocator);783 var values: std.StringArrayHashMap(Value) = .init(allocator);
832 defer values.deinit();784 defer values.deinit();
833785
834 // empty strings are preserved786 // empty strings are preserved
...@@ -924,7 +876,7 @@ test "expand_variables_autoconf_at simple cases" {...@@ -924,7 +876,7 @@ test "expand_variables_autoconf_at simple cases" {
924876
925test "expand_variables_autoconf_at edge cases" {877test "expand_variables_autoconf_at edge cases" {
926 const allocator = std.testing.allocator;878 const allocator = std.testing.allocator;
927 var values = std.StringArrayHashMap(Value).init(allocator);879 var values: std.StringArrayHashMap(Value) = .init(allocator);
928 defer values.deinit();880 defer values.deinit();
929881
930 // @-vars resolved only when they wrap valid characters, otherwise considered literals882 // @-vars resolved only when they wrap valid characters, otherwise considered literals
...@@ -940,7 +892,7 @@ test "expand_variables_autoconf_at edge cases" {...@@ -940,7 +892,7 @@ test "expand_variables_autoconf_at edge cases" {
940892
941test "expand_variables_cmake simple cases" {893test "expand_variables_cmake simple cases" {
942 const allocator = std.testing.allocator;894 const allocator = std.testing.allocator;
943 var values = std.StringArrayHashMap(Value).init(allocator);895 var values: std.StringArrayHashMap(Value) = .init(allocator);
944 defer values.deinit();896 defer values.deinit();
945897
946 try values.putNoClobber("undef", .undef);898 try values.putNoClobber("undef", .undef);
...@@ -1028,7 +980,7 @@ test "expand_variables_cmake simple cases" {...@@ -1028,7 +980,7 @@ test "expand_variables_cmake simple cases" {
1028980
1029test "expand_variables_cmake edge cases" {981test "expand_variables_cmake edge cases" {
1030 const allocator = std.testing.allocator;982 const allocator = std.testing.allocator;
1031 var values = std.StringArrayHashMap(Value).init(allocator);983 var values: std.StringArrayHashMap(Value) = .init(allocator);
1032 defer values.deinit();984 defer values.deinit();
1033985
1034 // special symbols986 // special symbols
...@@ -1089,7 +1041,7 @@ test "expand_variables_cmake edge cases" {...@@ -1089,7 +1041,7 @@ test "expand_variables_cmake edge cases" {
10891041
1090test "expand_variables_cmake escaped characters" {1042test "expand_variables_cmake escaped characters" {
1091 const allocator = std.testing.allocator;1043 const allocator = std.testing.allocator;
1092 var values = std.StringArrayHashMap(Value).init(allocator);1044 var values: std.StringArrayHashMap(Value) = .init(allocator);
1093 defer values.deinit();1045 defer values.deinit();
10941046
1095 try values.putNoClobber("string", Value{ .string = "text" });1047 try values.putNoClobber("string", Value{ .string = "text" });
lib/std/Build/Step/Fail.zig+1-1
...@@ -12,7 +12,7 @@ pub fn create(owner: *std.Build, error_msg: []const u8) *Fail {...@@ -12,7 +12,7 @@ pub fn create(owner: *std.Build, error_msg: []const u8) *Fail {
12 const fail = owner.allocator.create(Fail) catch @panic("OOM");12 const fail = owner.allocator.create(Fail) catch @panic("OOM");
1313
14 fail.* = .{14 fail.* = .{
15 .step = Step.init(.{15 .step = .init(.{
16 .id = base_id,16 .id = base_id,
17 .name = "fail",17 .name = "fail",
18 .owner = owner,18 .owner = owner,
lib/std/Build/Step/Fmt.zig+1-1
...@@ -23,7 +23,7 @@ pub fn create(owner: *std.Build, options: Options) *Fmt {...@@ -23,7 +23,7 @@ pub fn create(owner: *std.Build, options: Options) *Fmt {
23 const fmt = owner.allocator.create(Fmt) catch @panic("OOM");23 const fmt = owner.allocator.create(Fmt) catch @panic("OOM");
24 const name = if (options.check) "zig fmt --check" else "zig fmt";24 const name = if (options.check) "zig fmt --check" else "zig fmt";
25 fmt.* = .{25 fmt.* = .{
26 .step = Step.init(.{26 .step = .init(.{
27 .id = base_id,27 .id = base_id,
28 .name = name,28 .name = name,
29 .owner = owner,29 .owner = owner,
lib/std/Build/Step/InstallArtifact.zig+2-2
...@@ -63,7 +63,7 @@ pub fn create(owner: *std.Build, artifact: *Step.Compile, options: Options) *Ins...@@ -63,7 +63,7 @@ pub fn create(owner: *std.Build, artifact: *Step.Compile, options: Options) *Ins
63 .override => |o| o,63 .override => |o| o,
64 };64 };
65 install_artifact.* = .{65 install_artifact.* = .{
66 .step = Step.init(.{66 .step = .init(.{
67 .id = base_id,67 .id = base_id,
68 .name = owner.fmt("install {s}", .{artifact.name}),68 .name = owner.fmt("install {s}", .{artifact.name}),
69 .owner = owner,69 .owner = owner,
...@@ -164,7 +164,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {...@@ -164,7 +164,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
164 const full_h_prefix = b.getInstallPath(h_dir, dir.dest_rel_path);164 const full_h_prefix = b.getInstallPath(h_dir, dir.dest_rel_path);
165165
166 var src_dir = src_dir_path.root_dir.handle.openDir(src_dir_path.subPathOrDot(), .{ .iterate = true }) catch |err| {166 var src_dir = src_dir_path.root_dir.handle.openDir(src_dir_path.subPathOrDot(), .{ .iterate = true }) catch |err| {
167 return step.fail("unable to open source directory '{}': {s}", .{167 return step.fail("unable to open source directory '{f}': {s}", .{
168 src_dir_path, @errorName(err),168 src_dir_path, @errorName(err),
169 });169 });
170 };170 };
lib/std/Build/Step/InstallDir.zig+2-2
...@@ -43,7 +43,7 @@ pub const Options = struct {...@@ -43,7 +43,7 @@ pub const Options = struct {
43pub fn create(owner: *std.Build, options: Options) *InstallDir {43pub fn create(owner: *std.Build, options: Options) *InstallDir {
44 const install_dir = owner.allocator.create(InstallDir) catch @panic("OOM");44 const install_dir = owner.allocator.create(InstallDir) catch @panic("OOM");
45 install_dir.* = .{45 install_dir.* = .{
46 .step = Step.init(.{46 .step = .init(.{
47 .id = base_id,47 .id = base_id,
48 .name = owner.fmt("install {s}/", .{options.source_dir.getDisplayName()}),48 .name = owner.fmt("install {s}/", .{options.source_dir.getDisplayName()}),
49 .owner = owner,49 .owner = owner,
...@@ -65,7 +65,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {...@@ -65,7 +65,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
65 const src_dir_path = install_dir.options.source_dir.getPath3(b, step);65 const src_dir_path = install_dir.options.source_dir.getPath3(b, step);
66 const need_derived_inputs = try step.addDirectoryWatchInput(install_dir.options.source_dir);66 const need_derived_inputs = try step.addDirectoryWatchInput(install_dir.options.source_dir);
67 var src_dir = src_dir_path.root_dir.handle.openDir(src_dir_path.subPathOrDot(), .{ .iterate = true }) catch |err| {67 var src_dir = src_dir_path.root_dir.handle.openDir(src_dir_path.subPathOrDot(), .{ .iterate = true }) catch |err| {
68 return step.fail("unable to open source directory '{}': {s}", .{68 return step.fail("unable to open source directory '{f}': {s}", .{
69 src_dir_path, @errorName(err),69 src_dir_path, @errorName(err),
70 });70 });
71 };71 };
lib/std/Build/Step/InstallFile.zig+1-1
...@@ -21,7 +21,7 @@ pub fn create(...@@ -21,7 +21,7 @@ pub fn create(
21 assert(dest_rel_path.len != 0);21 assert(dest_rel_path.len != 0);
22 const install_file = owner.allocator.create(InstallFile) catch @panic("OOM");22 const install_file = owner.allocator.create(InstallFile) catch @panic("OOM");
23 install_file.* = .{23 install_file.* = .{
24 .step = Step.init(.{24 .step = .init(.{
25 .id = base_id,25 .id = base_id,
26 .name = owner.fmt("install {s} to {s}", .{ source.getDisplayName(), dest_rel_path }),26 .name = owner.fmt("install {s} to {s}", .{ source.getDisplayName(), dest_rel_path }),
27 .owner = owner,27 .owner = owner,
lib/std/Build/Step/ObjCopy.zig+2-2
...@@ -111,8 +111,8 @@ pub fn create(...@@ -111,8 +111,8 @@ pub fn create(
111 options: Options,111 options: Options,
112) *ObjCopy {112) *ObjCopy {
113 const objcopy = owner.allocator.create(ObjCopy) catch @panic("OOM");113 const objcopy = owner.allocator.create(ObjCopy) catch @panic("OOM");
114 objcopy.* = ObjCopy{114 objcopy.* = .{
115 .step = Step.init(.{115 .step = .init(.{
116 .id = base_id,116 .id = base_id,
117 .name = owner.fmt("objcopy {s}", .{input_file.getDisplayName()}),117 .name = owner.fmt("objcopy {s}", .{input_file.getDisplayName()}),
118 .owner = owner,118 .owner = owner,
lib/std/Build/Step/Options.zig+19-19
...@@ -19,7 +19,7 @@ encountered_types: std.StringHashMapUnmanaged(void),...@@ -19,7 +19,7 @@ encountered_types: std.StringHashMapUnmanaged(void),
19pub fn create(owner: *std.Build) *Options {19pub fn create(owner: *std.Build) *Options {
20 const options = owner.allocator.create(Options) catch @panic("OOM");20 const options = owner.allocator.create(Options) catch @panic("OOM");
21 options.* = .{21 options.* = .{
22 .step = Step.init(.{22 .step = .init(.{
23 .id = base_id,23 .id = base_id,
24 .name = "options",24 .name = "options",
25 .owner = owner,25 .owner = owner,
...@@ -79,15 +79,15 @@ fn printType(...@@ -79,15 +79,15 @@ fn printType(
79 std.zig.fmtId(some), std.zig.fmtEscapes(value),79 std.zig.fmtId(some), std.zig.fmtEscapes(value),
80 });80 });
81 } else {81 } else {
82 try out.print(gpa, "\"{}\",", .{std.zig.fmtEscapes(value)});82 try out.print(gpa, "\"{f}\",", .{std.zig.fmtEscapes(value)});
83 }83 }
84 return out.appendSlice(gpa, "\n");84 return out.appendSlice(gpa, "\n");
85 },85 },
86 [:0]const u8 => {86 [:0]const u8 => {
87 if (name) |some| {87 if (name) |some| {
88 try out.print(gpa, "pub const {}: [:0]const u8 = \"{}\";", .{ std.zig.fmtId(some), std.zig.fmtEscapes(value) });88 try out.print(gpa, "pub const {f}: [:0]const u8 = \"{f}\";", .{ std.zig.fmtId(some), std.zig.fmtEscapes(value) });
89 } else {89 } else {
90 try out.print(gpa, "\"{}\",", .{std.zig.fmtEscapes(value)});90 try out.print(gpa, "\"{f}\",", .{std.zig.fmtEscapes(value)});
91 }91 }
92 return out.appendSlice(gpa, "\n");92 return out.appendSlice(gpa, "\n");
93 },93 },
...@@ -97,7 +97,7 @@ fn printType(...@@ -97,7 +97,7 @@ fn printType(
97 }97 }
9898
99 if (value) |payload| {99 if (value) |payload| {
100 try out.print(gpa, "\"{}\"", .{std.zig.fmtEscapes(payload)});100 try out.print(gpa, "\"{f}\"", .{std.zig.fmtEscapes(payload)});
101 } else {101 } else {
102 try out.appendSlice(gpa, "null");102 try out.appendSlice(gpa, "null");
103 }103 }
...@@ -115,7 +115,7 @@ fn printType(...@@ -115,7 +115,7 @@ fn printType(
115 }115 }
116116
117 if (value) |payload| {117 if (value) |payload| {
118 try out.print(gpa, "\"{}\"", .{std.zig.fmtEscapes(payload)});118 try out.print(gpa, "\"{f}\"", .{std.zig.fmtEscapes(payload)});
119 } else {119 } else {
120 try out.appendSlice(gpa, "null");120 try out.appendSlice(gpa, "null");
121 }121 }
...@@ -129,7 +129,7 @@ fn printType(...@@ -129,7 +129,7 @@ fn printType(
129 },129 },
130 std.SemanticVersion => {130 std.SemanticVersion => {
131 if (name) |some| {131 if (name) |some| {
132 try out.print(gpa, "pub const {}: @import(\"std\").SemanticVersion = ", .{std.zig.fmtId(some)});132 try out.print(gpa, "pub const {f}: @import(\"std\").SemanticVersion = ", .{std.zig.fmtId(some)});
133 }133 }
134134
135 try out.appendSlice(gpa, ".{\n");135 try out.appendSlice(gpa, ".{\n");
...@@ -142,11 +142,11 @@ fn printType(...@@ -142,11 +142,11 @@ fn printType(
142142
143 if (value.pre) |some| {143 if (value.pre) |some| {
144 try out.appendNTimes(gpa, ' ', indent);144 try out.appendNTimes(gpa, ' ', indent);
145 try out.print(gpa, " .pre = \"{}\",\n", .{std.zig.fmtEscapes(some)});145 try out.print(gpa, " .pre = \"{f}\",\n", .{std.zig.fmtEscapes(some)});
146 }146 }
147 if (value.build) |some| {147 if (value.build) |some| {
148 try out.appendNTimes(gpa, ' ', indent);148 try out.appendNTimes(gpa, ' ', indent);
149 try out.print(gpa, " .build = \"{}\",\n", .{std.zig.fmtEscapes(some)});149 try out.print(gpa, " .build = \"{f}\",\n", .{std.zig.fmtEscapes(some)});
150 }150 }
151151
152 if (name != null) {152 if (name != null) {
...@@ -233,7 +233,7 @@ fn printType(...@@ -233,7 +233,7 @@ fn printType(
233 .null,233 .null,
234 => {234 => {
235 if (name) |some| {235 if (name) |some| {
236 try out.print(gpa, "pub const {}: {s} = {any};\n", .{ std.zig.fmtId(some), @typeName(T), value });236 try out.print(gpa, "pub const {f}: {s} = {any};\n", .{ std.zig.fmtId(some), @typeName(T), value });
237 } else {237 } else {
238 try out.print(gpa, "{any},\n", .{value});238 try out.print(gpa, "{any},\n", .{value});
239 }239 }
...@@ -243,7 +243,7 @@ fn printType(...@@ -243,7 +243,7 @@ fn printType(
243 try printEnum(options, out, T, info, indent);243 try printEnum(options, out, T, info, indent);
244244
245 if (name) |some| {245 if (name) |some| {
246 try out.print(gpa, "pub const {}: {} = .{p_};\n", .{246 try out.print(gpa, "pub const {f}: {f} = .{fp_};\n", .{
247 std.zig.fmtId(some),247 std.zig.fmtId(some),
248 std.zig.fmtId(@typeName(T)),248 std.zig.fmtId(@typeName(T)),
249 std.zig.fmtId(@tagName(value)),249 std.zig.fmtId(@tagName(value)),
...@@ -255,7 +255,7 @@ fn printType(...@@ -255,7 +255,7 @@ fn printType(
255 try printStruct(options, out, T, info, indent);255 try printStruct(options, out, T, info, indent);
256256
257 if (name) |some| {257 if (name) |some| {
258 try out.print(gpa, "pub const {}: {} = ", .{258 try out.print(gpa, "pub const {f}: {f} = ", .{
259 std.zig.fmtId(some),259 std.zig.fmtId(some),
260 std.zig.fmtId(@typeName(T)),260 std.zig.fmtId(@typeName(T)),
261 });261 });
...@@ -291,7 +291,7 @@ fn printEnum(...@@ -291,7 +291,7 @@ fn printEnum(
291 if (gop.found_existing) return;291 if (gop.found_existing) return;
292292
293 try out.appendNTimes(gpa, ' ', indent);293 try out.appendNTimes(gpa, ' ', indent);
294 try out.print(gpa, "pub const {} = enum ({s}) {{\n", .{ std.zig.fmtId(@typeName(T)), @typeName(val.tag_type) });294 try out.print(gpa, "pub const {f} = enum ({s}) {{\n", .{ std.zig.fmtId(@typeName(T)), @typeName(val.tag_type) });
295295
296 inline for (val.fields) |field| {296 inline for (val.fields) |field| {
297 try out.appendNTimes(gpa, ' ', indent);297 try out.appendNTimes(gpa, ' ', indent);
...@@ -464,7 +464,7 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {...@@ -464,7 +464,7 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {
464 error.FileNotFound => {464 error.FileNotFound => {
465 const sub_dirname = fs.path.dirname(sub_path).?;465 const sub_dirname = fs.path.dirname(sub_path).?;
466 b.cache_root.handle.makePath(sub_dirname) catch |e| {466 b.cache_root.handle.makePath(sub_dirname) catch |e| {
467 return step.fail("unable to make path '{}{s}': {s}", .{467 return step.fail("unable to make path '{f}{s}': {s}", .{
468 b.cache_root, sub_dirname, @errorName(e),468 b.cache_root, sub_dirname, @errorName(e),
469 });469 });
470 };470 };
...@@ -476,13 +476,13 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {...@@ -476,13 +476,13 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {
476 const tmp_sub_path_dirname = fs.path.dirname(tmp_sub_path).?;476 const tmp_sub_path_dirname = fs.path.dirname(tmp_sub_path).?;
477477
478 b.cache_root.handle.makePath(tmp_sub_path_dirname) catch |err| {478 b.cache_root.handle.makePath(tmp_sub_path_dirname) catch |err| {
479 return step.fail("unable to make temporary directory '{}{s}': {s}", .{479 return step.fail("unable to make temporary directory '{f}{s}': {s}", .{
480 b.cache_root, tmp_sub_path_dirname, @errorName(err),480 b.cache_root, tmp_sub_path_dirname, @errorName(err),
481 });481 });
482 };482 };
483483
484 b.cache_root.handle.writeFile(.{ .sub_path = tmp_sub_path, .data = options.contents.items }) catch |err| {484 b.cache_root.handle.writeFile(.{ .sub_path = tmp_sub_path, .data = options.contents.items }) catch |err| {
485 return step.fail("unable to write options to '{}{s}': {s}", .{485 return step.fail("unable to write options to '{f}{s}': {s}", .{
486 b.cache_root, tmp_sub_path, @errorName(err),486 b.cache_root, tmp_sub_path, @errorName(err),
487 });487 });
488 };488 };
...@@ -491,7 +491,7 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {...@@ -491,7 +491,7 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {
491 error.PathAlreadyExists => {491 error.PathAlreadyExists => {
492 // Other process beat us to it. Clean up the temp file.492 // Other process beat us to it. Clean up the temp file.
493 b.cache_root.handle.deleteFile(tmp_sub_path) catch |e| {493 b.cache_root.handle.deleteFile(tmp_sub_path) catch |e| {
494 try step.addError("warning: unable to delete temp file '{}{s}': {s}", .{494 try step.addError("warning: unable to delete temp file '{f}{s}': {s}", .{
495 b.cache_root, tmp_sub_path, @errorName(e),495 b.cache_root, tmp_sub_path, @errorName(e),
496 });496 });
497 };497 };
...@@ -499,7 +499,7 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {...@@ -499,7 +499,7 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {
499 return;499 return;
500 },500 },
501 else => {501 else => {
502 return step.fail("unable to rename options from '{}{s}' to '{}{s}': {s}", .{502 return step.fail("unable to rename options from '{f}{s}' to '{f}{s}': {s}", .{
503 b.cache_root, tmp_sub_path,503 b.cache_root, tmp_sub_path,
504 b.cache_root, sub_path,504 b.cache_root, sub_path,
505 @errorName(err),505 @errorName(err),
...@@ -507,7 +507,7 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {...@@ -507,7 +507,7 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {
507 },507 },
508 };508 };
509 },509 },
510 else => |e| return step.fail("unable to access options file '{}{s}': {s}", .{510 else => |e| return step.fail("unable to access options file '{f}{s}': {s}", .{
511 b.cache_root, sub_path, @errorName(e),511 b.cache_root, sub_path, @errorName(e),
512 }),512 }),
513 }513 }
lib/std/Build/Step/RemoveDir.zig+1-1
...@@ -12,7 +12,7 @@ doomed_path: LazyPath,...@@ -12,7 +12,7 @@ doomed_path: LazyPath,
12pub fn create(owner: *std.Build, doomed_path: LazyPath) *RemoveDir {12pub fn create(owner: *std.Build, doomed_path: LazyPath) *RemoveDir {
13 const remove_dir = owner.allocator.create(RemoveDir) catch @panic("OOM");13 const remove_dir = owner.allocator.create(RemoveDir) catch @panic("OOM");
14 remove_dir.* = .{14 remove_dir.* = .{
15 .step = Step.init(.{15 .step = .init(.{
16 .id = base_id,16 .id = base_id,
17 .name = owner.fmt("RemoveDir {s}", .{doomed_path.getDisplayName()}),17 .name = owner.fmt("RemoveDir {s}", .{doomed_path.getDisplayName()}),
18 .owner = owner,18 .owner = owner,
lib/std/Build/Step/Run.zig+23-30
...@@ -169,7 +169,7 @@ pub const Output = struct {...@@ -169,7 +169,7 @@ pub const Output = struct {
169pub fn create(owner: *std.Build, name: []const u8) *Run {169pub fn create(owner: *std.Build, name: []const u8) *Run {
170 const run = owner.allocator.create(Run) catch @panic("OOM");170 const run = owner.allocator.create(Run) catch @panic("OOM");
171 run.* = .{171 run.* = .{
172 .step = Step.init(.{172 .step = .init(.{
173 .id = base_id,173 .id = base_id,
174 .name = name,174 .name = name,
175 .owner = owner,175 .owner = owner,
...@@ -832,7 +832,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {...@@ -832,7 +832,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
832 else => unreachable,832 else => unreachable,
833 };833 };
834 b.cache_root.handle.makePath(output_sub_dir_path) catch |err| {834 b.cache_root.handle.makePath(output_sub_dir_path) catch |err| {
835 return step.fail("unable to make path '{}{s}': {s}", .{835 return step.fail("unable to make path '{f}{s}': {s}", .{
836 b.cache_root, output_sub_dir_path, @errorName(err),836 b.cache_root, output_sub_dir_path, @errorName(err),
837 });837 });
838 };838 };
...@@ -864,7 +864,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {...@@ -864,7 +864,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
864 else => unreachable,864 else => unreachable,
865 };865 };
866 b.cache_root.handle.makePath(output_sub_dir_path) catch |err| {866 b.cache_root.handle.makePath(output_sub_dir_path) catch |err| {
867 return step.fail("unable to make path '{}{s}': {s}", .{867 return step.fail("unable to make path '{f}{s}': {s}", .{
868 b.cache_root, output_sub_dir_path, @errorName(err),868 b.cache_root, output_sub_dir_path, @errorName(err),
869 });869 });
870 };870 };
...@@ -903,21 +903,21 @@ fn make(step: *Step, options: Step.MakeOptions) !void {...@@ -903,21 +903,21 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
903 b.cache_root.handle.rename(tmp_dir_path, o_sub_path) catch |err| {903 b.cache_root.handle.rename(tmp_dir_path, o_sub_path) catch |err| {
904 if (err == error.PathAlreadyExists) {904 if (err == error.PathAlreadyExists) {
905 b.cache_root.handle.deleteTree(o_sub_path) catch |del_err| {905 b.cache_root.handle.deleteTree(o_sub_path) catch |del_err| {
906 return step.fail("unable to remove dir '{}'{s}: {s}", .{906 return step.fail("unable to remove dir '{f}'{s}: {s}", .{
907 b.cache_root,907 b.cache_root,
908 tmp_dir_path,908 tmp_dir_path,
909 @errorName(del_err),909 @errorName(del_err),
910 });910 });
911 };911 };
912 b.cache_root.handle.rename(tmp_dir_path, o_sub_path) catch |retry_err| {912 b.cache_root.handle.rename(tmp_dir_path, o_sub_path) catch |retry_err| {
913 return step.fail("unable to rename dir '{}{s}' to '{}{s}': {s}", .{913 return step.fail("unable to rename dir '{f}{s}' to '{f}{s}': {s}", .{
914 b.cache_root, tmp_dir_path,914 b.cache_root, tmp_dir_path,
915 b.cache_root, o_sub_path,915 b.cache_root, o_sub_path,
916 @errorName(retry_err),916 @errorName(retry_err),
917 });917 });
918 };918 };
919 } else {919 } else {
920 return step.fail("unable to rename dir '{}{s}' to '{}{s}': {s}", .{920 return step.fail("unable to rename dir '{f}{s}' to '{f}{s}': {s}", .{
921 b.cache_root, tmp_dir_path,921 b.cache_root, tmp_dir_path,
922 b.cache_root, o_sub_path,922 b.cache_root, o_sub_path,
923 @errorName(err),923 @errorName(err),
...@@ -964,7 +964,7 @@ pub fn rerunInFuzzMode(...@@ -964,7 +964,7 @@ pub fn rerunInFuzzMode(
964 .artifact => |pa| {964 .artifact => |pa| {
965 const artifact = pa.artifact;965 const artifact = pa.artifact;
966 const file_path: []const u8 = p: {966 const file_path: []const u8 = p: {
967 if (artifact == run.producer.?) break :p b.fmt("{}", .{run.rebuilt_executable.?});967 if (artifact == run.producer.?) break :p b.fmt("{f}", .{run.rebuilt_executable.?});
968 break :p artifact.installed_path orelse artifact.generated_bin.?.path.?;968 break :p artifact.installed_path orelse artifact.generated_bin.?.path.?;
969 };969 };
970 try argv_list.append(arena, b.fmt("{s}{s}", .{970 try argv_list.append(arena, b.fmt("{s}{s}", .{
...@@ -1013,20 +1013,16 @@ fn populateGeneratedPaths(...@@ -1013,20 +1013,16 @@ fn populateGeneratedPaths(
10131013
1014fn formatTerm(1014fn formatTerm(
1015 term: ?std.process.Child.Term,1015 term: ?std.process.Child.Term,
1016 bw: *std.io.BufferedWriter,
1016 comptime fmt: []const u8,1017 comptime fmt: []const u8,
1017 options: std.fmt.FormatOptions,
1018 writer: anytype,
1019) !void {1018) !void {
1020 _ = fmt;1019 _ = fmt;
1021 _ = options;
1022 if (term) |t| switch (t) {1020 if (term) |t| switch (t) {
1023 .Exited => |code| try writer.print("exited with code {}", .{code}),1021 .Exited => |code| try bw.print("exited with code {}", .{code}),
1024 .Signal => |sig| try writer.print("terminated with signal {}", .{sig}),1022 .Signal => |sig| try bw.print("terminated with signal {}", .{sig}),
1025 .Stopped => |sig| try writer.print("stopped with signal {}", .{sig}),1023 .Stopped => |sig| try bw.print("stopped with signal {}", .{sig}),
1026 .Unknown => |code| try writer.print("terminated for unknown reason with code {}", .{code}),1024 .Unknown => |code| try bw.print("terminated for unknown reason with code {}", .{code}),
1027 } else {1025 } else try bw.writeAll("exited with any code");
1028 try writer.writeAll("exited with any code");
1029 }
1030}1026}
1031fn fmtTerm(term: ?std.process.Child.Term) std.fmt.Formatter(formatTerm) {1027fn fmtTerm(term: ?std.process.Child.Term) std.fmt.Formatter(formatTerm) {
1032 return .{ .data = term };1028 return .{ .data = term };
...@@ -1262,12 +1258,12 @@ fn runCommand(...@@ -1262,12 +1258,12 @@ fn runCommand(
1262 const sub_path = b.pathJoin(&output_components);1258 const sub_path = b.pathJoin(&output_components);
1263 const sub_path_dirname = fs.path.dirname(sub_path).?;1259 const sub_path_dirname = fs.path.dirname(sub_path).?;
1264 b.cache_root.handle.makePath(sub_path_dirname) catch |err| {1260 b.cache_root.handle.makePath(sub_path_dirname) catch |err| {
1265 return step.fail("unable to make path '{}{s}': {s}", .{1261 return step.fail("unable to make path '{f}{s}': {s}", .{
1266 b.cache_root, sub_path_dirname, @errorName(err),1262 b.cache_root, sub_path_dirname, @errorName(err),
1267 });1263 });
1268 };1264 };
1269 b.cache_root.handle.writeFile(.{ .sub_path = sub_path, .data = stream.bytes.? }) catch |err| {1265 b.cache_root.handle.writeFile(.{ .sub_path = sub_path, .data = stream.bytes.? }) catch |err| {
1270 return step.fail("unable to write file '{}{s}': {s}", .{1266 return step.fail("unable to write file '{f}{s}': {s}", .{
1271 b.cache_root, sub_path, @errorName(err),1267 b.cache_root, sub_path, @errorName(err),
1272 });1268 });
1273 };1269 };
...@@ -1346,7 +1342,7 @@ fn runCommand(...@@ -1346,7 +1342,7 @@ fn runCommand(
1346 },1342 },
1347 .expect_term => |expected_term| {1343 .expect_term => |expected_term| {
1348 if (!termMatches(expected_term, result.term)) {1344 if (!termMatches(expected_term, result.term)) {
1349 return step.fail("the following command {} (expected {}):\n{s}", .{1345 return step.fail("the following command {f} (expected {f}):\n{s}", .{
1350 fmtTerm(result.term),1346 fmtTerm(result.term),
1351 fmtTerm(expected_term),1347 fmtTerm(expected_term),
1352 try Step.allocPrintCmd(arena, cwd, final_argv),1348 try Step.allocPrintCmd(arena, cwd, final_argv),
...@@ -1366,7 +1362,7 @@ fn runCommand(...@@ -1366,7 +1362,7 @@ fn runCommand(
1366 };1362 };
1367 const expected_term: std.process.Child.Term = .{ .Exited = 0 };1363 const expected_term: std.process.Child.Term = .{ .Exited = 0 };
1368 if (!termMatches(expected_term, result.term)) {1364 if (!termMatches(expected_term, result.term)) {
1369 return step.fail("{s}the following command {} (expected {}):\n{s}", .{1365 return step.fail("{s}the following command {f} (expected {f}):\n{s}", .{
1370 prefix,1366 prefix,
1371 fmtTerm(result.term),1367 fmtTerm(result.term),
1372 fmtTerm(expected_term),1368 fmtTerm(expected_term),
...@@ -1535,13 +1531,10 @@ fn evalZigTest(...@@ -1535,13 +1531,10 @@ fn evalZigTest(
1535 defer if (sub_prog_node) |n| n.end();1531 defer if (sub_prog_node) |n| n.end();
15361532
1537 const any_write_failed = first_write_failed or poll: while (true) {1533 const any_write_failed = first_write_failed or poll: while (true) {
1538 while (stdout.readableLength() < @sizeOf(Header)) {1534 while (stdout.readableLength() < @sizeOf(Header)) if (!try poller.poll()) break :poll false;
1539 if (!(try poller.poll())) break :poll false;1535 var header: Header = undefined;
1540 }1536 assert(stdout.read(std.mem.asBytes(&header)) == @sizeOf(Header));
1541 const header = stdout.reader().readStruct(Header) catch unreachable;1537 while (stdout.readableLength() < header.bytes_len) if (!try poller.poll()) break :poll false;
1542 while (stdout.readableLength() < header.bytes_len) {
1543 if (!(try poller.poll())) break :poll false;
1544 }
1545 const body = stdout.readableSliceOfLen(header.bytes_len);1538 const body = stdout.readableSliceOfLen(header.bytes_len);
15461539
1547 switch (header.tag) {1540 switch (header.tag) {
...@@ -1797,10 +1790,10 @@ fn evalGeneric(run: *Run, child: *std.process.Child) !StdIoResult {...@@ -1797,10 +1790,10 @@ fn evalGeneric(run: *Run, child: *std.process.Child) !StdIoResult {
1797 stdout_bytes = try poller.fifo(.stdout).toOwnedSlice();1790 stdout_bytes = try poller.fifo(.stdout).toOwnedSlice();
1798 stderr_bytes = try poller.fifo(.stderr).toOwnedSlice();1791 stderr_bytes = try poller.fifo(.stderr).toOwnedSlice();
1799 } else {1792 } else {
1800 stdout_bytes = try stdout.reader().readAllAlloc(arena, run.max_stdio_size);1793 stdout_bytes = try stdout.reader().readAlloc(arena, run.max_stdio_size);
1801 }1794 }
1802 } else if (child.stderr) |stderr| {1795 } else if (child.stderr) |stderr| {
1803 stderr_bytes = try stderr.reader().readAllAlloc(arena, run.max_stdio_size);1796 stderr_bytes = try stderr.reader().readAlloc(arena, run.max_stdio_size);
1804 }1797 }
18051798
1806 if (stderr_bytes) |bytes| if (bytes.len > 0) {1799 if (stderr_bytes) |bytes| if (bytes.len > 0) {
lib/std/Build/Step/TranslateC.zig+1-1
...@@ -31,7 +31,7 @@ pub fn create(owner: *std.Build, options: Options) *TranslateC {...@@ -31,7 +31,7 @@ pub fn create(owner: *std.Build, options: Options) *TranslateC {
31 const translate_c = owner.allocator.create(TranslateC) catch @panic("OOM");31 const translate_c = owner.allocator.create(TranslateC) catch @panic("OOM");
32 const source = options.root_source_file.dupe(owner);32 const source = options.root_source_file.dupe(owner);
33 translate_c.* = .{33 translate_c.* = .{
34 .step = Step.init(.{34 .step = .init(.{
35 .id = base_id,35 .id = base_id,
36 .name = "translate-c",36 .name = "translate-c",
37 .owner = owner,37 .owner = owner,
lib/std/Build/Step/UpdateSourceFiles.zig+4-4
...@@ -27,7 +27,7 @@ pub const Contents = union(enum) {...@@ -27,7 +27,7 @@ pub const Contents = union(enum) {
27pub fn create(owner: *std.Build) *UpdateSourceFiles {27pub fn create(owner: *std.Build) *UpdateSourceFiles {
28 const usf = owner.allocator.create(UpdateSourceFiles) catch @panic("OOM");28 const usf = owner.allocator.create(UpdateSourceFiles) catch @panic("OOM");
29 usf.* = .{29 usf.* = .{
30 .step = Step.init(.{30 .step = .init(.{
31 .id = base_id,31 .id = base_id,
32 .name = "UpdateSourceFiles",32 .name = "UpdateSourceFiles",
33 .owner = owner,33 .owner = owner,
...@@ -76,7 +76,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {...@@ -76,7 +76,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
76 for (usf.output_source_files.items) |output_source_file| {76 for (usf.output_source_files.items) |output_source_file| {
77 if (fs.path.dirname(output_source_file.sub_path)) |dirname| {77 if (fs.path.dirname(output_source_file.sub_path)) |dirname| {
78 b.build_root.handle.makePath(dirname) catch |err| {78 b.build_root.handle.makePath(dirname) catch |err| {
79 return step.fail("unable to make path '{}{s}': {s}", .{79 return step.fail("unable to make path '{f}{s}': {s}", .{
80 b.build_root, dirname, @errorName(err),80 b.build_root, dirname, @errorName(err),
81 });81 });
82 };82 };
...@@ -84,7 +84,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {...@@ -84,7 +84,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
84 switch (output_source_file.contents) {84 switch (output_source_file.contents) {
85 .bytes => |bytes| {85 .bytes => |bytes| {
86 b.build_root.handle.writeFile(.{ .sub_path = output_source_file.sub_path, .data = bytes }) catch |err| {86 b.build_root.handle.writeFile(.{ .sub_path = output_source_file.sub_path, .data = bytes }) catch |err| {
87 return step.fail("unable to write file '{}{s}': {s}", .{87 return step.fail("unable to write file '{f}{s}': {s}", .{
88 b.build_root, output_source_file.sub_path, @errorName(err),88 b.build_root, output_source_file.sub_path, @errorName(err),
89 });89 });
90 };90 };
...@@ -101,7 +101,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {...@@ -101,7 +101,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
101 output_source_file.sub_path,101 output_source_file.sub_path,
102 .{},102 .{},
103 ) catch |err| {103 ) catch |err| {
104 return step.fail("unable to update file from '{s}' to '{}{s}': {s}", .{104 return step.fail("unable to update file from '{s}' to '{f}{s}': {s}", .{
105 source_path, b.build_root, output_source_file.sub_path, @errorName(err),105 source_path, b.build_root, output_source_file.sub_path, @errorName(err),
106 });106 });
107 };107 };
lib/std/Build/Step/WriteFile.zig+8-8
...@@ -67,7 +67,7 @@ pub const Contents = union(enum) {...@@ -67,7 +67,7 @@ pub const Contents = union(enum) {
67pub fn create(owner: *std.Build) *WriteFile {67pub fn create(owner: *std.Build) *WriteFile {
68 const write_file = owner.allocator.create(WriteFile) catch @panic("OOM");68 const write_file = owner.allocator.create(WriteFile) catch @panic("OOM");
69 write_file.* = .{69 write_file.* = .{
70 .step = Step.init(.{70 .step = .init(.{
71 .id = base_id,71 .id = base_id,
72 .name = "WriteFile",72 .name = "WriteFile",
73 .owner = owner,73 .owner = owner,
...@@ -217,7 +217,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {...@@ -217,7 +217,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
217 const src_dir_path = dir.source.getPath3(b, step);217 const src_dir_path = dir.source.getPath3(b, step);
218218
219 var src_dir = src_dir_path.root_dir.handle.openDir(src_dir_path.subPathOrDot(), .{ .iterate = true }) catch |err| {219 var src_dir = src_dir_path.root_dir.handle.openDir(src_dir_path.subPathOrDot(), .{ .iterate = true }) catch |err| {
220 return step.fail("unable to open source directory '{}': {s}", .{220 return step.fail("unable to open source directory '{f}': {s}", .{
221 src_dir_path, @errorName(err),221 src_dir_path, @errorName(err),
222 });222 });
223 };223 };
...@@ -258,7 +258,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {...@@ -258,7 +258,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
258 write_file.generated_directory.path = try b.cache_root.join(arena, &.{ "o", &digest });258 write_file.generated_directory.path = try b.cache_root.join(arena, &.{ "o", &digest });
259259
260 var cache_dir = b.cache_root.handle.makeOpenPath(cache_path, .{}) catch |err| {260 var cache_dir = b.cache_root.handle.makeOpenPath(cache_path, .{}) catch |err| {
261 return step.fail("unable to make path '{}{s}': {s}", .{261 return step.fail("unable to make path '{f}{s}': {s}", .{
262 b.cache_root, cache_path, @errorName(err),262 b.cache_root, cache_path, @errorName(err),
263 });263 });
264 };264 };
...@@ -269,7 +269,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {...@@ -269,7 +269,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
269 for (write_file.files.items) |file| {269 for (write_file.files.items) |file| {
270 if (fs.path.dirname(file.sub_path)) |dirname| {270 if (fs.path.dirname(file.sub_path)) |dirname| {
271 cache_dir.makePath(dirname) catch |err| {271 cache_dir.makePath(dirname) catch |err| {
272 return step.fail("unable to make path '{}{s}{c}{s}': {s}", .{272 return step.fail("unable to make path '{f}{s}{c}{s}': {s}", .{
273 b.cache_root, cache_path, fs.path.sep, dirname, @errorName(err),273 b.cache_root, cache_path, fs.path.sep, dirname, @errorName(err),
274 });274 });
275 };275 };
...@@ -277,7 +277,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {...@@ -277,7 +277,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
277 switch (file.contents) {277 switch (file.contents) {
278 .bytes => |bytes| {278 .bytes => |bytes| {
279 cache_dir.writeFile(.{ .sub_path = file.sub_path, .data = bytes }) catch |err| {279 cache_dir.writeFile(.{ .sub_path = file.sub_path, .data = bytes }) catch |err| {
280 return step.fail("unable to write file '{}{s}{c}{s}': {s}", .{280 return step.fail("unable to write file '{f}{s}{c}{s}': {s}", .{
281 b.cache_root, cache_path, fs.path.sep, file.sub_path, @errorName(err),281 b.cache_root, cache_path, fs.path.sep, file.sub_path, @errorName(err),
282 });282 });
283 };283 };
...@@ -291,7 +291,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {...@@ -291,7 +291,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
291 file.sub_path,291 file.sub_path,
292 .{},292 .{},
293 ) catch |err| {293 ) catch |err| {
294 return step.fail("unable to update file from '{s}' to '{}{s}{c}{s}': {s}", .{294 return step.fail("unable to update file from '{s}' to '{f}{s}{c}{s}': {s}", .{
295 source_path,295 source_path,
296 b.cache_root,296 b.cache_root,
297 cache_path,297 cache_path,
...@@ -315,7 +315,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {...@@ -315,7 +315,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
315315
316 if (dest_dirname.len != 0) {316 if (dest_dirname.len != 0) {
317 cache_dir.makePath(dest_dirname) catch |err| {317 cache_dir.makePath(dest_dirname) catch |err| {
318 return step.fail("unable to make path '{}{s}{c}{s}': {s}", .{318 return step.fail("unable to make path '{f}{s}{c}{s}': {s}", .{
319 b.cache_root, cache_path, fs.path.sep, dest_dirname, @errorName(err),319 b.cache_root, cache_path, fs.path.sep, dest_dirname, @errorName(err),
320 });320 });
321 };321 };
...@@ -338,7 +338,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {...@@ -338,7 +338,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
338 dest_path,338 dest_path,
339 .{},339 .{},
340 ) catch |err| {340 ) catch |err| {
341 return step.fail("unable to update file from '{}' to '{}{s}{c}{s}': {s}", .{341 return step.fail("unable to update file from '{f}' to '{f}{s}{c}{s}': {s}", .{
342 src_entry_path, b.cache_root, cache_path, fs.path.sep, dest_path, @errorName(err),342 src_entry_path, b.cache_root, cache_path, fs.path.sep, dest_path, @errorName(err),
343 });343 });
344 };344 };
lib/std/Build/Watch.zig+2-2
...@@ -211,7 +211,7 @@ const Os = switch (builtin.os.tag) {...@@ -211,7 +211,7 @@ const Os = switch (builtin.os.tag) {
211 .ADD = true,211 .ADD = true,
212 .ONLYDIR = true,212 .ONLYDIR = true,
213 }, fan_mask, path.root_dir.handle.fd, path.subPathOrDot()) catch |err| {213 }, fan_mask, path.root_dir.handle.fd, path.subPathOrDot()) catch |err| {
214 fatal("unable to watch {}: {s}", .{ path, @errorName(err) });214 fatal("unable to watch {f}: {s}", .{ path, @errorName(err) });
215 };215 };
216 }216 }
217 break :rs &dh_gop.value_ptr.reaction_set;217 break :rs &dh_gop.value_ptr.reaction_set;
...@@ -265,7 +265,7 @@ const Os = switch (builtin.os.tag) {...@@ -265,7 +265,7 @@ const Os = switch (builtin.os.tag) {
265 .ONLYDIR = true,265 .ONLYDIR = true,
266 }, fan_mask, path.root_dir.handle.fd, path.subPathOrDot()) catch |err| switch (err) {266 }, fan_mask, path.root_dir.handle.fd, path.subPathOrDot()) catch |err| switch (err) {
267 error.FileNotFound => {}, // Expected, harmless.267 error.FileNotFound => {}, // Expected, harmless.
268 else => |e| std.log.warn("unable to unwatch '{}': {s}", .{ path, @errorName(e) }),268 else => |e| std.log.warn("unable to unwatch '{f}': {s}", .{ path, @errorName(e) }),
269 };269 };
270270
271 w.dir_table.swapRemoveAt(i);271 w.dir_table.swapRemoveAt(i);
lib/std/SemanticVersion.zig+4-6
...@@ -152,15 +152,13 @@ fn parseNum(text: []const u8) error{ InvalidVersion, Overflow }!usize {...@@ -152,15 +152,13 @@ fn parseNum(text: []const u8) error{ InvalidVersion, Overflow }!usize {
152152
153pub fn format(153pub fn format(
154 self: Version,154 self: Version,
155 bw: *std.io.BufferedWriter,
155 comptime fmt: []const u8,156 comptime fmt: []const u8,
156 options: std.fmt.FormatOptions,
157 out_stream: anytype,
158) !void {157) !void {
159 _ = options;
160 if (fmt.len != 0) std.fmt.invalidFmtError(fmt, self);158 if (fmt.len != 0) std.fmt.invalidFmtError(fmt, self);
161 try std.fmt.format(out_stream, "{d}.{d}.{d}", .{ self.major, self.minor, self.patch });159 try bw.print("{d}.{d}.{d}", .{ self.major, self.minor, self.patch });
162 if (self.pre) |pre| try std.fmt.format(out_stream, "-{s}", .{pre});160 if (self.pre) |pre| try bw.print("-{s}", .{pre});
163 if (self.build) |build| try std.fmt.format(out_stream, "+{s}", .{build});161 if (self.build) |build| try bw.print("+{s}", .{build});
164}162}
165163
166const expect = std.testing.expect;164const expect = std.testing.expect;
lib/std/Target/Query.zig+2-2
...@@ -423,7 +423,7 @@ pub fn zigTriple(self: Query, gpa: Allocator) Allocator.Error![]u8 {...@@ -423,7 +423,7 @@ pub fn zigTriple(self: Query, gpa: Allocator) Allocator.Error![]u8 {
423 try formatVersion(v, gpa, &result);423 try formatVersion(v, gpa, &result);
424 },424 },
425 .windows => |v| {425 .windows => |v| {
426 try result.print(gpa, "{s}", .{v});426 try result.print(gpa, "{d}", .{v});
427 },427 },
428 }428 }
429 }429 }
...@@ -437,7 +437,7 @@ pub fn zigTriple(self: Query, gpa: Allocator) Allocator.Error![]u8 {...@@ -437,7 +437,7 @@ pub fn zigTriple(self: Query, gpa: Allocator) Allocator.Error![]u8 {
437 .windows => |v| {437 .windows => |v| {
438 // This is counting on a custom format() function defined on `WindowsVersion`438 // This is counting on a custom format() function defined on `WindowsVersion`
439 // to add a prefix '.' and make there be a total of three dots.439 // to add a prefix '.' and make there be a total of three dots.
440 try result.print(gpa, "..{s}", .{v});440 try result.print(gpa, "..{d}", .{v});
441 },441 },
442 }442 }
443 }443 }
lib/std/fifo.zig+57-6
...@@ -38,8 +38,6 @@ pub fn LinearFifo(...@@ -38,8 +38,6 @@ pub fn LinearFifo(
38 count: usize,38 count: usize,
3939
40 const Self = @This();40 const Self = @This();
41 pub const Reader = std.io.Reader(*Self, error{}, readFn);
42 pub const Writer = std.io.Writer(*Self, error{OutOfMemory}, appendWrite);
4341
44 // Type of Self argument for slice operations.42 // Type of Self argument for slice operations.
45 // If buffer is inline (Static) then we need to ensure we haven't43 // If buffer is inline (Static) then we need to ensure we haven't
...@@ -236,8 +234,31 @@ pub fn LinearFifo(...@@ -236,8 +234,31 @@ pub fn LinearFifo(
236 return self.read(dest);234 return self.read(dest);
237 }235 }
238236
239 pub fn reader(self: *Self) Reader {237 pub fn reader(self: *Self) std.io.Reader {
240 return .{ .context = self };238 return .{
239 .context = self,
240 .vtable = &.{
241 .read = &reader_read,
242 .readv = &reader_readv,
243 },
244 };
245 }
246 fn reader_read(
247 ctx: ?*anyopaque,
248 bw: *std.io.BufferedWriter,
249 limit: std.io.Reader.Limit,
250 ) anyerror!std.io.Reader.Status {
251 const fifo: *Self = @alignCast(@ptrCast(ctx));
252 _ = fifo;
253 _ = bw;
254 _ = limit;
255 @panic("TODO");
256 }
257 fn reader_readv(ctx: ?*anyopaque, data: []const []u8) anyerror!std.io.Reader.Status {
258 const fifo: *Self = @alignCast(@ptrCast(ctx));
259 _ = fifo;
260 _ = data;
261 @panic("TODO");
241 }262 }
242263
243 /// Returns number of items available in fifo264 /// Returns number of items available in fifo
...@@ -326,8 +347,38 @@ pub fn LinearFifo(...@@ -326,8 +347,38 @@ pub fn LinearFifo(
326 return bytes.len;347 return bytes.len;
327 }348 }
328349
329 pub fn writer(self: *Self) Writer {350 pub fn writer(fifo: *Self) std.io.Writer {
330 return .{ .context = self };351 return .{
352 .context = fifo,
353 .vtable = &.{
354 .writeSplat = writer_writeSplat,
355 .writeFile = writer_writeFile,
356 },
357 };
358 }
359 fn writer_writeSplat(ctx: ?*anyopaque, data: []const []const u8, splat: usize) anyerror!usize {
360 const fifo: *Self = @alignCast(@ptrCast(ctx));
361 _ = fifo;
362 _ = data;
363 _ = splat;
364 @panic("TODO");
365 }
366 fn writer_writeFile(
367 ctx: ?*anyopaque,
368 file: std.fs.File,
369 offset: std.io.Writer.Offset,
370 limit: std.io.Writer.Limit,
371 headers_and_trailers: []const []const u8,
372 headers_len: usize,
373 ) anyerror!usize {
374 const fifo: *Self = @alignCast(@ptrCast(ctx));
375 _ = fifo;
376 _ = file;
377 _ = offset;
378 _ = limit;
379 _ = headers_and_trailers;
380 _ = headers_len;
381 @panic("TODO");
331 }382 }
332383
333 /// Make `count` items available before the current read location384 /// Make `count` items available before the current read location
lib/std/fmt.zig+5-8
...@@ -451,12 +451,10 @@ fn SliceEscape(comptime case: Case) type {...@@ -451,12 +451,10 @@ fn SliceEscape(comptime case: Case) type {
451 return struct {451 return struct {
452 pub fn format(452 pub fn format(
453 bytes: []const u8,453 bytes: []const u8,
454 bw: *std.io.BufferedWriter,
454 comptime fmt: []const u8,455 comptime fmt: []const u8,
455 options: std.fmt.Options,
456 writer: anytype,
457 ) !void {456 ) !void {
458 _ = fmt;457 _ = fmt;
459 _ = options;
460 var buf: [4]u8 = undefined;458 var buf: [4]u8 = undefined;
461459
462 buf[0] = '\\';460 buf[0] = '\\';
...@@ -464,11 +462,11 @@ fn SliceEscape(comptime case: Case) type {...@@ -464,11 +462,11 @@ fn SliceEscape(comptime case: Case) type {
464462
465 for (bytes) |c| {463 for (bytes) |c| {
466 if (std.ascii.isPrint(c)) {464 if (std.ascii.isPrint(c)) {
467 try writer.writeByte(c);465 try bw.writeByte(c);
468 } else {466 } else {
469 buf[2] = charset[c >> 4];467 buf[2] = charset[c >> 4];
470 buf[3] = charset[c & 15];468 buf[3] = charset[c & 15];
471 try writer.writeAll(&buf);469 try bw.writeAll(&buf);
472 }470 }
473 }471 }
474 }472 }
...@@ -535,11 +533,10 @@ pub fn Formatter(comptime formatFn: anytype) type {...@@ -535,11 +533,10 @@ pub fn Formatter(comptime formatFn: anytype) type {
535 data: Data,533 data: Data,
536 pub fn format(534 pub fn format(
537 self: @This(),535 self: @This(),
538 comptime fmt: []const u8,
539 options: std.fmt.Options,
540 writer: *std.io.BufferedWriter,536 writer: *std.io.BufferedWriter,
537 comptime fmt: []const u8,
541 ) anyerror!void {538 ) anyerror!void {
542 try formatFn(self.data, fmt, options, writer);539 try formatFn(self.data, writer, fmt);
543 }540 }
544 };541 };
545}542}
lib/std/fs/Dir.zig+39-4
...@@ -1979,10 +1979,45 @@ pub fn readFileAlloc(...@@ -1979,10 +1979,45 @@ pub fn readFileAlloc(
1979 /// * `error.FileTooBig` is returned.1979 /// * `error.FileTooBig` is returned.
1980 limit: std.io.Reader.Limit,1980 limit: std.io.Reader.Limit,
1981) (File.OpenError || File.ReadAllocError)![]u8 {1981) (File.OpenError || File.ReadAllocError)![]u8 {
1982 var buffer: std.ArrayListUnmanaged(u8) = .empty;1982 return dir.readFileAllocOptions(file_path, gpa, limit, null, .of(u8), null);
1983}
1984
1985/// Reads all the bytes from the named file. On success, caller owns returned
1986/// buffer.
1987pub fn readFileAllocOptions(
1988 dir: Dir,
1989 /// On Windows, should be encoded as [WTF-8](https://simonsapin.github.io/wtf-8/).
1990 /// On WASI, should be encoded as valid UTF-8.
1991 /// On other platforms, an opaque sequence of bytes with no particular encoding.
1992 file_path: []const u8,
1993 /// Used to allocate the result.
1994 gpa: mem.Allocator,
1995 /// If exceeded:
1996 /// * The array list's length is increased by exactly one byte past `limit`.
1997 /// * The file seek position is advanced by exactly one byte past `limit`.
1998 /// * `error.FileTooBig` is returned.
1999 limit: std.io.Reader.Limit,
2000 /// If specified, the initial buffer size is calculated using this value,
2001 /// otherwise the effective file size is used instead.
2002 size_hint: ?usize,
2003 comptime alignment: std.mem.Alignment,
2004 comptime optional_sentinel: ?u8,
2005) (File.OpenError || File.ReadAllocError)!(if (optional_sentinel) |s| [:s]align(alignment.toByteUnits()) u8 else []align(alignment.toByteUnits()) u8) {
2006 var buffer: std.ArrayListAlignedUnmanaged(u8, alignment) = .empty;
1983 defer buffer.deinit(gpa);2007 defer buffer.deinit(gpa);
1984 try readFileIntoArrayList(dir, file_path, gpa, limit, null, &buffer);2008 try readFileIntoArrayList(
1985 return buffer.toOwnedSlice(gpa);2009 dir,
2010 file_path,
2011 gpa,
2012 limit,
2013 if (size_hint) |sh| sh +| 1 else null,
2014 alignment,
2015 &buffer,
2016 );
2017 return if (optional_sentinel) |sentinel|
2018 buffer.toOwnedSliceSentinel(gpa, sentinel)
2019 else
2020 buffer.toOwnedSlice(gpa);
1986}2021}
19872022
1988/// Reads all the bytes from the named file, appending them into the provided2023/// Reads all the bytes from the named file, appending them into the provided
...@@ -2004,7 +2039,7 @@ pub fn readFileIntoArrayList(...@@ -2004,7 +2039,7 @@ pub fn readFileIntoArrayList(
2004 /// otherwise the effective file size is used instead.2039 /// otherwise the effective file size is used instead.
2005 size_hint: ?usize,2040 size_hint: ?usize,
2006 comptime alignment: ?std.mem.Alignment,2041 comptime alignment: ?std.mem.Alignment,
2007 list: *std.ArrayListAligned(u8, alignment),2042 list: *std.ArrayListAlignedUnmanaged(u8, alignment),
2008) (File.OpenError || File.ReadAllocError)!void {2043) (File.OpenError || File.ReadAllocError)!void {
2009 var file = try dir.openFile(file_path, .{});2044 var file = try dir.openFile(file_path, .{});
2010 defer file.close();2045 defer file.close();
lib/std/fs/File.zig+5-5
...@@ -1169,7 +1169,7 @@ pub fn readIntoArrayList(...@@ -1169,7 +1169,7 @@ pub fn readIntoArrayList(
1169 gpa: Allocator,1169 gpa: Allocator,
1170 limit: std.io.Reader.Limit,1170 limit: std.io.Reader.Limit,
1171 comptime alignment: ?std.mem.Alignment,1171 comptime alignment: ?std.mem.Alignment,
1172 list: *std.ArrayListAligned(u8, alignment),1172 list: *std.ArrayListAlignedUnmanaged(u8, alignment),
1173) ReadAllocError!void {1173) ReadAllocError!void {
1174 var remaining = limit;1174 var remaining = limit;
1175 while (true) {1175 while (true) {
...@@ -1676,7 +1676,7 @@ fn streamReadVec(context: ?*anyopaque, data: []const []u8) anyerror!std.io.Reade...@@ -1676,7 +1676,7 @@ fn streamReadVec(context: ?*anyopaque, data: []const []u8) anyerror!std.io.Reade
1676 return .{ .len = @intCast(n), .end = n == 0 };1676 return .{ .len = @intCast(n), .end = n == 0 };
1677}1677}
16781678
1679fn writeSplat(context: ?*anyopaque, data: []const []const u8, splat: usize) anyerror!usize {1679pub fn writeSplat(context: ?*anyopaque, data: []const []const u8, splat: usize) anyerror!usize {
1680 const handle = opaqueToHandle(context);1680 const handle = opaqueToHandle(context);
1681 var splat_buffer: [256]u8 = undefined;1681 var splat_buffer: [256]u8 = undefined;
1682 if (is_windows) {1682 if (is_windows) {
...@@ -1716,7 +1716,7 @@ fn writeSplat(context: ?*anyopaque, data: []const []const u8, splat: usize) anye...@@ -1716,7 +1716,7 @@ fn writeSplat(context: ?*anyopaque, data: []const []const u8, splat: usize) anye
1716 return std.posix.writev(handle, iovecs[0..len]);1716 return std.posix.writev(handle, iovecs[0..len]);
1717}1717}
17181718
1719fn writeFile(1719pub fn writeFile(
1720 context: ?*anyopaque,1720 context: ?*anyopaque,
1721 in_file: std.fs.File,1721 in_file: std.fs.File,
1722 in_offset: std.io.Writer.Offset,1722 in_offset: std.io.Writer.Offset,
...@@ -1727,8 +1727,8 @@ fn writeFile(...@@ -1727,8 +1727,8 @@ fn writeFile(
1727 const out_fd = opaqueToHandle(context);1727 const out_fd = opaqueToHandle(context);
1728 const in_fd = in_file.handle;1728 const in_fd = in_file.handle;
1729 const len_int = switch (in_limit) {1729 const len_int = switch (in_limit) {
1730 .zero => return writeSplat(context, headers_and_trailers, 1),1730 .nothing => return writeSplat(context, headers_and_trailers, 1),
1731 .none => 0,1731 .unlimited => 0,
1732 else => in_limit.toInt().?,1732 else => in_limit.toInt().?,
1733 };1733 };
1734 if (native_os == .linux) sf: {1734 if (native_os == .linux) sf: {
lib/std/http/Server.zig+64-20
...@@ -593,8 +593,46 @@ pub const Request = struct {...@@ -593,8 +593,46 @@ pub const Request = struct {
593 HttpHeadersOversize,593 HttpHeadersOversize,
594 };594 };
595595
596 fn contentLengthReader_read(
597 ctx: ?*anyopaque,
598 bw: *std.io.BufferedWriter,
599 limit: std.io.Reader.Limit,
600 ) anyerror!std.io.Reader.Status {
601 const request: *Request = @alignCast(@ptrCast(ctx));
602 _ = request;
603 _ = bw;
604 _ = limit;
605 @panic("TODO");
606 }
607
608 fn contentLengthReader_readv(ctx: ?*anyopaque, data: []const []u8) anyerror!std.io.Reader.Status {
609 const request: *Request = @alignCast(@ptrCast(ctx));
610 _ = request;
611 _ = data;
612 @panic("TODO");
613 }
614
615 fn chunkedReader_read(
616 ctx: ?*anyopaque,
617 bw: *std.io.BufferedWriter,
618 limit: std.io.Reader.Limit,
619 ) anyerror!std.io.Reader.Status {
620 const request: *Request = @alignCast(@ptrCast(ctx));
621 _ = request;
622 _ = bw;
623 _ = limit;
624 @panic("TODO");
625 }
626
627 fn chunkedReader_readv(ctx: ?*anyopaque, data: []const []u8) anyerror!std.io.Reader.Status {
628 const request: *Request = @alignCast(@ptrCast(ctx));
629 _ = request;
630 _ = data;
631 @panic("TODO");
632 }
633
596 fn read_cl(context: *const anyopaque, buffer: []u8) ReadError!usize {634 fn read_cl(context: *const anyopaque, buffer: []u8) ReadError!usize {
597 const request: *Request = @constCast(@alignCast(@ptrCast(context)));635 const request: *Request = @alignCast(@ptrCast(context));
598 const s = request.server;636 const s = request.server;
599637
600 const remaining_content_length = &request.reader_state.remaining_content_length;638 const remaining_content_length = &request.reader_state.remaining_content_length;
...@@ -622,7 +660,7 @@ pub const Request = struct {...@@ -622,7 +660,7 @@ pub const Request = struct {
622 }660 }
623661
624 fn read_chunked(context: *const anyopaque, buffer: []u8) ReadError!usize {662 fn read_chunked(context: *const anyopaque, buffer: []u8) ReadError!usize {
625 const request: *Request = @constCast(@alignCast(@ptrCast(context)));663 const request: *Request = @alignCast(@ptrCast(context));
626 const s = request.server;664 const s = request.server;
627665
628 const cp = &request.reader_state.chunk_parser;666 const cp = &request.reader_state.chunk_parser;
...@@ -724,7 +762,7 @@ pub const Request = struct {...@@ -724,7 +762,7 @@ pub const Request = struct {
724 /// request's expect field to `null`.762 /// request's expect field to `null`.
725 ///763 ///
726 /// Asserts that this function is only called once.764 /// Asserts that this function is only called once.
727 pub fn reader(request: *Request) ReaderError!std.io.AnyReader {765 pub fn reader(request: *Request) ReaderError!std.io.Reader {
728 const s = request.server;766 const s = request.server;
729 assert(s.state == .received_head);767 assert(s.state == .received_head);
730 s.state = .receiving_body;768 s.state = .receiving_body;
...@@ -747,8 +785,11 @@ pub const Request = struct {...@@ -747,8 +785,11 @@ pub const Request = struct {
747 .chunked => {785 .chunked => {
748 request.reader_state = .{ .chunk_parser = http.ChunkParser.init };786 request.reader_state = .{ .chunk_parser = http.ChunkParser.init };
749 return .{787 return .{
750 .readFn = read_chunked,
751 .context = request,788 .context = request,
789 .vtable = &.{
790 .read = &chunkedReader_read,
791 .readv = &chunkedReader_readv,
792 },
752 };793 };
753 },794 },
754 .none => {795 .none => {
...@@ -756,8 +797,11 @@ pub const Request = struct {...@@ -756,8 +797,11 @@ pub const Request = struct {
756 .remaining_content_length = request.head.content_length orelse 0,797 .remaining_content_length = request.head.content_length orelse 0,
757 };798 };
758 return .{799 return .{
759 .readFn = read_cl,
760 .context = request,800 .context = request,
801 .vtable = &.{
802 .read = &contentLengthReader_read,
803 .readv = &contentLengthReader_readv,
804 },
761 };805 };
762 },806 },
763 }807 }
...@@ -779,7 +823,7 @@ pub const Request = struct {...@@ -779,7 +823,7 @@ pub const Request = struct {
779 if (keep_alive and request.head.keep_alive) switch (s.state) {823 if (keep_alive and request.head.keep_alive) switch (s.state) {
780 .received_head => {824 .received_head => {
781 const r = request.reader() catch return false;825 const r = request.reader() catch return false;
782 _ = r.discard() catch return false;826 _ = r.discardUntilEnd() catch return false;
783 assert(s.state == .ready);827 assert(s.state == .ready);
784 return true;828 return true;
785 },829 },
...@@ -868,30 +912,30 @@ pub const Response = struct {...@@ -868,30 +912,30 @@ pub const Response = struct {
868 }912 }
869 }913 }
870914
871 fn cl_writeSplat(context: *anyopaque, data: []const []const u8, splat: usize) anyerror!usize {915 fn cl_writeSplat(context: ?*anyopaque, data: []const []const u8, splat: usize) anyerror!usize {
872 _ = splat;916 _ = splat;
873 return cl_write(context, data[0]); // TODO: try to send all the data917 return cl_write(context, data[0]); // TODO: try to send all the data
874 }918 }
875919
876 fn cl_writeFile(920 fn cl_writeFile(
877 context: *anyopaque,921 context: ?*anyopaque,
878 file: std.fs.File,922 file: std.fs.File,
879 offset: u64,923 offset: std.io.Writer.Offset,
880 len: std.io.Writer.FileLen,924 limit: std.io.Writer.Limit,
881 headers_and_trailers: []const []const u8,925 headers_and_trailers: []const []const u8,
882 headers_len: usize,926 headers_len: usize,
883 ) anyerror!usize {927 ) anyerror!usize {
884 _ = context;928 _ = context;
885 _ = file;929 _ = file;
886 _ = offset;930 _ = offset;
887 _ = len;931 _ = limit;
888 _ = headers_and_trailers;932 _ = headers_and_trailers;
889 _ = headers_len;933 _ = headers_len;
890 return error.Unimplemented;934 return error.Unimplemented;
891 }935 }
892936
893 fn cl_write(context: *anyopaque, bytes: []const u8) anyerror!usize {937 fn cl_write(context: ?*anyopaque, bytes: []const u8) anyerror!usize {
894 const r: *Response = @constCast(@alignCast(@ptrCast(context)));938 const r: *Response = @alignCast(@ptrCast(context));
895939
896 var trash: u64 = std.math.maxInt(u64);940 var trash: u64 = std.math.maxInt(u64);
897 const len = switch (r.transfer_encoding) {941 const len = switch (r.transfer_encoding) {
...@@ -935,30 +979,30 @@ pub const Response = struct {...@@ -935,30 +979,30 @@ pub const Response = struct {
935 return bytes.len;979 return bytes.len;
936 }980 }
937981
938 fn chunked_writeSplat(context: *anyopaque, data: []const []const u8, splat: usize) anyerror!usize {982 fn chunked_writeSplat(context: ?*anyopaque, data: []const []const u8, splat: usize) anyerror!usize {
939 _ = splat;983 _ = splat;
940 return chunked_write(context, data[0]); // TODO: try to send all the data984 return chunked_write(context, data[0]); // TODO: try to send all the data
941 }985 }
942986
943 fn chunked_writeFile(987 fn chunked_writeFile(
944 context: *anyopaque,988 context: ?*anyopaque,
945 file: std.fs.File,989 file: std.fs.File,
946 offset: u64,990 offset: std.io.Writer.Offset,
947 len: std.io.Writer.FileLen,991 limit: std.io.Writer.Limit,
948 headers_and_trailers: []const []const u8,992 headers_and_trailers: []const []const u8,
949 headers_len: usize,993 headers_len: usize,
950 ) anyerror!usize {994 ) anyerror!usize {
951 _ = context;995 _ = context;
952 _ = file;996 _ = file;
953 _ = offset;997 _ = offset;
954 _ = len;998 _ = limit;
955 _ = headers_and_trailers;999 _ = headers_and_trailers;
956 _ = headers_len;1000 _ = headers_len;
957 return error.Unimplemented; // TODO lower to a call to writeFile on the output1001 return error.Unimplemented; // TODO lower to a call to writeFile on the output
958 }1002 }
9591003
960 fn chunked_write(context: *anyopaque, bytes: []const u8) anyerror!usize {1004 fn chunked_write(context: ?*anyopaque, bytes: []const u8) anyerror!usize {
961 const r: *Response = @constCast(@alignCast(@ptrCast(context)));1005 const r: *Response = @alignCast(@ptrCast(context));
962 assert(r.transfer_encoding == .chunked);1006 assert(r.transfer_encoding == .chunked);
9631007
964 if (r.elide_body)1008 if (r.elide_body)
lib/std/http/WebSocket.zig+3-2
...@@ -57,8 +57,8 @@ pub fn init(...@@ -57,8 +57,8 @@ pub fn init(
5757
58 ws.* = .{58 ws.* = .{
59 .key = key,59 .key = key,
60 .recv_fifo = std.fifo.LinearFifo(u8, .Slice).init(recv_buffer),60 .recv_fifo = .init(recv_buffer),
61 .reader = try request.reader(),61 .reader = undefined,
62 .response = request.respondStreaming(.{62 .response = request.respondStreaming(.{
63 .send_buffer = send_buffer,63 .send_buffer = send_buffer,
64 .respond_options = .{64 .respond_options = .{
...@@ -74,6 +74,7 @@ pub fn init(...@@ -74,6 +74,7 @@ pub fn init(
74 .request = request,74 .request = request,
75 .outstanding_len = 0,75 .outstanding_len = 0,
76 };76 };
77 ws.reader.init(try request.reader(), &.{});
77 return true;78 return true;
78}79}
7980
lib/std/io/AllocatingWriter.zig+14-10
...@@ -28,12 +28,12 @@ const vtable: std.io.Writer.VTable = .{...@@ -28,12 +28,12 @@ const vtable: std.io.Writer.VTable = .{
2828
29/// Sets the `AllocatingWriter` to an empty state.29/// Sets the `AllocatingWriter` to an empty state.
30pub fn init(aw: *AllocatingWriter, allocator: std.mem.Allocator) void {30pub fn init(aw: *AllocatingWriter, allocator: std.mem.Allocator) void {
31 initOwnedSlice(aw, allocator, &.{});31 aw.initOwnedSlice(allocator, &.{});
32}32}
3333
34pub fn initCapacity(aw: *AllocatingWriter, allocator: std.mem.Allocator, capacity: usize) error{OutOfMemory}!void {34pub fn initCapacity(aw: *AllocatingWriter, allocator: std.mem.Allocator, capacity: usize) error{OutOfMemory}!void {
35 const initial_buffer = try allocator.alloc(u8, capacity);35 const initial_buffer = try allocator.alloc(u8, capacity);
36 initOwnedSlice(aw, allocator, initial_buffer);36 aw.initOwnedSlice(allocator, initial_buffer);
37}37}
3838
39pub fn initOwnedSlice(aw: *AllocatingWriter, allocator: std.mem.Allocator, slice: []u8) void {39pub fn initOwnedSlice(aw: *AllocatingWriter, allocator: std.mem.Allocator, slice: []u8) void {
...@@ -119,11 +119,15 @@ pub fn getWritten(aw: *AllocatingWriter) []u8 {...@@ -119,11 +119,15 @@ pub fn getWritten(aw: *AllocatingWriter) []u8 {
119 return written;119 return written;
120}120}
121121
122pub fn clearRetainingCapacity(aw: *AllocatingWriter) void {122pub fn shrinkRetainingCapacity(aw: *AllocatingWriter, new_len: usize) void {
123 const bw = &aw.buffered_writer;123 const bw = &aw.buffered_writer;
124 bw.buffer = aw.written.ptr[0 .. aw.written.len + bw.buffer.len];124 bw.buffer = aw.written.ptr[new_len .. aw.written.len + bw.buffer.len];
125 bw.end = 0;125 bw.end = 0;
126 aw.written.len = 0;126 aw.written.len = new_len;
127}
128
129pub fn clearRetainingCapacity(aw: *AllocatingWriter) void {
130 aw.shrinkRetainingCapacity(0);
127}131}
128132
129fn writeSplat(context: ?*anyopaque, data: []const []const u8, splat: usize) anyerror!usize {133fn writeSplat(context: ?*anyopaque, data: []const []const u8, splat: usize) anyerror!usize {
...@@ -161,7 +165,7 @@ fn writeFile(...@@ -161,7 +165,7 @@ fn writeFile(
161 context: ?*anyopaque,165 context: ?*anyopaque,
162 file: std.fs.File,166 file: std.fs.File,
163 offset: std.io.Writer.Offset,167 offset: std.io.Writer.Offset,
164 len: std.io.Writer.FileLen,168 limit: std.io.Writer.Limit,
165 headers_and_trailers_full: []const []const u8,169 headers_and_trailers_full: []const []const u8,
166 headers_len_full: usize,170 headers_len_full: usize,
167) anyerror!usize {171) anyerror!usize {
...@@ -177,7 +181,7 @@ fn writeFile(...@@ -177,7 +181,7 @@ fn writeFile(
177 } else .{ headers_and_trailers_full, headers_len_full };181 } else .{ headers_and_trailers_full, headers_len_full };
178 const trailers = headers_and_trailers[headers_len..];182 const trailers = headers_and_trailers[headers_len..];
179 const pos = offset.toInt() orelse @panic("TODO treat file as stream");183 const pos = offset.toInt() orelse @panic("TODO treat file as stream");
180 if (len == .entire_file) {184 const limit_int = limit.toInt() orelse {
181 var new_capacity: usize = list.capacity + std.atomic.cache_line;185 var new_capacity: usize = list.capacity + std.atomic.cache_line;
182 for (headers_and_trailers) |bytes| new_capacity += bytes.len;186 for (headers_and_trailers) |bytes| new_capacity += bytes.len;
183 try list.ensureTotalCapacity(gpa, new_capacity);187 try list.ensureTotalCapacity(gpa, new_capacity);
...@@ -193,12 +197,12 @@ fn writeFile(...@@ -193,12 +197,12 @@ fn writeFile(
193 }197 }
194 list.items.len += n;198 list.items.len += n;
195 return list.items.len - start_len;199 return list.items.len - start_len;
196 }200 };
197 var new_capacity: usize = list.capacity + len.int();201 var new_capacity: usize = list.capacity + limit_int;
198 for (headers_and_trailers) |bytes| new_capacity += bytes.len;202 for (headers_and_trailers) |bytes| new_capacity += bytes.len;
199 try list.ensureTotalCapacity(gpa, new_capacity);203 try list.ensureTotalCapacity(gpa, new_capacity);
200 for (headers_and_trailers[0..headers_len]) |bytes| list.appendSliceAssumeCapacity(bytes);204 for (headers_and_trailers[0..headers_len]) |bytes| list.appendSliceAssumeCapacity(bytes);
201 const dest = list.items.ptr[list.items.len..][0..len.int()];205 const dest = list.items.ptr[list.items.len..][0..limit_int];
202 const n = try file.pread(dest, pos);206 const n = try file.pread(dest, pos);
203 list.items.len += n;207 list.items.len += n;
204 if (n < dest.len) {208 if (n < dest.len) {
lib/std/io/BufferedReader.zig+8-9
...@@ -253,18 +253,17 @@ pub fn discardUpTo(br: *BufferedReader, n: usize) anyerror!usize {...@@ -253,18 +253,17 @@ pub fn discardUpTo(br: *BufferedReader, n: usize) anyerror!usize {
253 const proposed_seek = br.seek + remaining;253 const proposed_seek = br.seek + remaining;
254 if (proposed_seek <= storage.end) {254 if (proposed_seek <= storage.end) {
255 br.seek = proposed_seek;255 br.seek = proposed_seek;
256 return;256 return n;
257 }257 }
258 remaining -= (storage.end - br.seek);258 remaining -= (storage.end - br.seek);
259 storage.end = 0;259 storage.end = 0;
260 br.seek = 0;260 br.seek = 0;
261 const result = try br.unbuffered_reader.read(&storage, .none);261 const result = try br.unbuffered_reader.read(storage, .unlimited);
262 result.write_err catch unreachable;
263 try result.read_err;
264 assert(result.len == storage.end);262 assert(result.len == storage.end);
265 if (remaining <= storage.end) continue;263 if (remaining <= storage.end) continue;
266 if (result.end) return n - remaining;264 if (result.end) return n - remaining;
267 }265 }
266 return n;
268}267}
269268
270/// Reads the stream until the end, ignoring all the data.269/// Reads the stream until the end, ignoring all the data.
...@@ -302,7 +301,7 @@ pub fn read(br: *BufferedReader, buffer: []u8) anyerror!void {...@@ -302,7 +301,7 @@ pub fn read(br: *BufferedReader, buffer: []u8) anyerror!void {
302 br.seek = 0;301 br.seek = 0;
303 var i: usize = in_buffer.len;302 var i: usize = in_buffer.len;
304 while (true) {303 while (true) {
305 const status = try br.unbuffered_reader.read(storage, .none);304 const status = try br.unbuffered_reader.read(storage, .unlimited);
306 const next_i = i + storage.end;305 const next_i = i + storage.end;
307 if (next_i >= buffer.len) {306 if (next_i >= buffer.len) {
308 const remaining = buffer[i..];307 const remaining = buffer[i..];
...@@ -389,7 +388,7 @@ pub fn peekDelimiterInclusive(br: *BufferedReader, delimiter: u8) anyerror![]u8...@@ -389,7 +388,7 @@ pub fn peekDelimiterInclusive(br: *BufferedReader, delimiter: u8) anyerror![]u8
389/// * `peekDelimiterConclusive`388/// * `peekDelimiterConclusive`
390pub fn takeDelimiterConclusive(br: *BufferedReader, delimiter: u8) anyerror![]u8 {389pub fn takeDelimiterConclusive(br: *BufferedReader, delimiter: u8) anyerror![]u8 {
391 const result = try peekDelimiterConclusive(br, delimiter);390 const result = try peekDelimiterConclusive(br, delimiter);
392 toss(result.len);391 br.toss(result.len);
393 return result;392 return result;
394}393}
395394
...@@ -407,7 +406,7 @@ pub fn peekDelimiterConclusive(br: *BufferedReader, delimiter: u8) anyerror![]u8...@@ -407,7 +406,7 @@ pub fn peekDelimiterConclusive(br: *BufferedReader, delimiter: u8) anyerror![]u8
407 storage.end = i;406 storage.end = i;
408 br.seek = 0;407 br.seek = 0;
409 while (i < storage.buffer.len) {408 while (i < storage.buffer.len) {
410 const status = try br.unbuffered_reader.read(storage, .none);409 const status = try br.unbuffered_reader.read(storage, .unlimited);
411 if (std.mem.indexOfScalarPos(u8, storage.buffer[0..storage.end], i, delimiter)) |end| {410 if (std.mem.indexOfScalarPos(u8, storage.buffer[0..storage.end], i, delimiter)) |end| {
412 return storage.buffer[0 .. end + 1];411 return storage.buffer[0 .. end + 1];
413 }412 }
...@@ -505,7 +504,7 @@ pub fn fill(br: *BufferedReader, n: usize) anyerror!void {...@@ -505,7 +504,7 @@ pub fn fill(br: *BufferedReader, n: usize) anyerror!void {
505 storage.end = remainder.len;504 storage.end = remainder.len;
506 br.seek = 0;505 br.seek = 0;
507 while (true) {506 while (true) {
508 const status = try br.unbuffered_reader.read(storage, .none);507 const status = try br.unbuffered_reader.read(storage, .unlimited);
509 if (n <= storage.end) return;508 if (n <= storage.end) return;
510 if (status.end) return error.EndOfStream;509 if (status.end) return error.EndOfStream;
511 }510 }
...@@ -589,7 +588,7 @@ fn takeMultipleOf7Leb128(br: *BufferedReader, comptime Result: type) anyerror!Re...@@ -589,7 +588,7 @@ fn takeMultipleOf7Leb128(br: *BufferedReader, comptime Result: type) anyerror!Re
589 const buffer: []const packed struct(u8) { bits: u7, more: bool } = @ptrCast(try br.peekAll(1));588 const buffer: []const packed struct(u8) { bits: u7, more: bool } = @ptrCast(try br.peekAll(1));
590 for (buffer, 1..) |byte, len| {589 for (buffer, 1..) |byte, len| {
591 if (remaining_bits > 0) {590 if (remaining_bits > 0) {
592 result = @shlExact(@as(UnsignedResult, byte.bits), result_info.bits - 7) | @shrExact(result, 7);591 result = @shlExact(@as(UnsignedResult, byte.bits), result_info.bits - 7) | if (result_info.bits > 7) @shrExact(result, 7) else 0;
593 remaining_bits -= 7;592 remaining_bits -= 7;
594 } else if (fits) fits = switch (result_info.signedness) {593 } else if (fits) fits = switch (result_info.signedness) {
595 .signed => @as(i7, @bitCast(byte.bits)) == @as(i7, @truncate(@as(Result, @bitCast(result)) >> (result_info.bits - 1))),594 .signed => @as(i7, @bitCast(byte.bits)) == @as(i7, @truncate(@as(Result, @bitCast(result)) >> (result_info.bits - 1))),
lib/std/io/BufferedWriter.zig+50-47
...@@ -503,7 +503,7 @@ pub const WriteFileOptions = struct {...@@ -503,7 +503,7 @@ pub const WriteFileOptions = struct {
503 offset: Writer.Offset = .none,503 offset: Writer.Offset = .none,
504 /// If the size of the source file is known, it is likely that passing the504 /// If the size of the source file is known, it is likely that passing the
505 /// size here will save one syscall.505 /// size here will save one syscall.
506 limit: Writer.Limit = .none,506 limit: Writer.Limit = .unlimited,
507 /// Headers and trailers must be passed together so that in case `len` is507 /// Headers and trailers must be passed together so that in case `len` is
508 /// zero, they can be forwarded directly to `Writer.VTable.writev`.508 /// zero, they can be forwarded directly to `Writer.VTable.writev`.
509 ///509 ///
...@@ -518,55 +518,58 @@ pub const WriteFileOptions = struct {...@@ -518,55 +518,58 @@ pub const WriteFileOptions = struct {
518pub fn writeFileAll(bw: *BufferedWriter, file: std.fs.File, options: WriteFileOptions) anyerror!void {518pub fn writeFileAll(bw: *BufferedWriter, file: std.fs.File, options: WriteFileOptions) anyerror!void {
519 const headers_and_trailers = options.headers_and_trailers;519 const headers_and_trailers = options.headers_and_trailers;
520 const headers = headers_and_trailers[0..options.headers_len];520 const headers = headers_and_trailers[0..options.headers_len];
521 if (options.limit == .zero) return writevAll(bw, headers_and_trailers);521 switch (options.limit) {
522 if (options.limit == .none) {522 .nothing => return writevAll(bw, headers_and_trailers),
523 // When reading the whole file, we cannot include the trailers in the523 .unlimited => {
524 // call that reads from the file handle, because we have no way to524 // When reading the whole file, we cannot include the trailers in the
525 // determine whether a partial write is past the end of the file or525 // call that reads from the file handle, because we have no way to
526 // not.526 // determine whether a partial write is past the end of the file or
527 var i: usize = 0;527 // not.
528 var offset = options.offset;528 var i: usize = 0;
529 while (true) {529 var offset = options.offset;
530 var n = try writeFile(bw, file, offset, .entire_file, headers[i..], headers.len - i);530 while (true) {
531 while (i < headers.len and n >= headers[i].len) {531 var n = try writeFile(bw, file, offset, .unlimited, headers[i..], headers.len - i);
532 n -= headers[i].len;532 while (i < headers.len and n >= headers[i].len) {
533 i += 1;533 n -= headers[i].len;
534 }534 i += 1;
535 if (i < headers.len) {535 }
536 headers[i] = headers[i][n..];536 if (i < headers.len) {
537 continue;537 headers[i] = headers[i][n..];
538 }538 continue;
539 if (n == 0) break;539 }
540 offset += n;540 if (n == 0) break;
541 }541 offset = offset.advance(n);
542 } else {
543 var len = options.limit.toInt().?;
544 var i: usize = 0;
545 var offset = options.offset;
546 while (true) {
547 var n = try writeFile(bw, file, offset, .init(len), headers_and_trailers[i..], headers.len - i);
548 while (i < headers.len and n >= headers[i].len) {
549 n -= headers[i].len;
550 i += 1;
551 }
552 if (i < headers.len) {
553 headers[i] = headers[i][n..];
554 continue;
555 }542 }
556 if (n >= len) {543 },
557 n -= len;544 else => {
558 if (i >= headers_and_trailers.len) return;545 var len = options.limit.toInt().?;
559 while (n >= headers_and_trailers[i].len) {546 var i: usize = 0;
560 n -= headers_and_trailers[i].len;547 var offset = options.offset;
548 while (true) {
549 var n = try writeFile(bw, file, offset, .limited(len), headers_and_trailers[i..], headers.len - i);
550 while (i < headers.len and n >= headers[i].len) {
551 n -= headers[i].len;
561 i += 1;552 i += 1;
553 }
554 if (i < headers.len) {
555 headers[i] = headers[i][n..];
556 continue;
557 }
558 if (n >= len) {
559 n -= len;
562 if (i >= headers_and_trailers.len) return;560 if (i >= headers_and_trailers.len) return;
561 while (n >= headers_and_trailers[i].len) {
562 n -= headers_and_trailers[i].len;
563 i += 1;
564 if (i >= headers_and_trailers.len) return;
565 }
566 headers_and_trailers[i] = headers_and_trailers[i][n..];
567 return writevAll(bw, headers_and_trailers[i..]);
563 }568 }
564 headers_and_trailers[i] = headers_and_trailers[i][n..];569 offset = offset.advance(n);
565 return writevAll(bw, headers_and_trailers[i..]);570 len -= n;
566 }571 }
567 offset += n;572 },
568 len -= n;
569 }
570 }573 }
571}574}
572575
...@@ -717,9 +720,9 @@ pub fn printValue(...@@ -717,9 +720,9 @@ pub fn printValue(
717 }720 }
718 }721 }
719722
720 try bw.writeByteCount('(');723 try bw.writeByte('(');
721 try printValue(bw, actual_fmt, options, @intFromEnum(value), max_depth);724 try printValue(bw, actual_fmt, options, @intFromEnum(value), max_depth);
722 try bw.writeByteCount(')');725 try bw.writeByte(')');
723 },726 },
724 .@"union" => |info| {727 .@"union" => |info| {
725 if (actual_fmt.len != 0) invalidFmtError(fmt, value);728 if (actual_fmt.len != 0) invalidFmtError(fmt, value);
lib/std/io/Reader.zig+15-12
...@@ -48,12 +48,12 @@ pub const Status = packed struct(usize) {...@@ -48,12 +48,12 @@ pub const Status = packed struct(usize) {
48};48};
4949
50pub const Limit = enum(usize) {50pub const Limit = enum(usize) {
51 zero = 0,51 nothing = 0,
52 none = std.math.maxInt(usize),52 unlimited = std.math.maxInt(usize),
53 _,53 _,
5454
55 /// `std.math.maxInt(usize)` is interpreted to mean "no limit".55 /// `std.math.maxInt(usize)` is interpreted to mean `.unlimited`.
56 pub fn init(n: usize) Limit {56 pub fn limited(n: usize) Limit {
57 return @enumFromInt(n);57 return @enumFromInt(n);
58 }58 }
5959
...@@ -66,7 +66,10 @@ pub const Limit = enum(usize) {...@@ -66,7 +66,10 @@ pub const Limit = enum(usize) {
66 }66 }
6767
68 pub fn toInt(l: Limit) ?usize {68 pub fn toInt(l: Limit) ?usize {
69 return if (l == .none) null else @intFromEnum(l);69 return switch (l) {
70 else => @intFromEnum(l),
71 .unlimited => null,
72 };
70 }73 }
7174
72 /// Reduces a slice to account for the limit, leaving room for one extra75 /// Reduces a slice to account for the limit, leaving room for one extra
...@@ -84,7 +87,7 @@ pub const Limit = enum(usize) {...@@ -84,7 +87,7 @@ pub const Limit = enum(usize) {
84 /// Return a new limit reduced by `amount` or return `null` indicating87 /// Return a new limit reduced by `amount` or return `null` indicating
85 /// limit would be exceeded.88 /// limit would be exceeded.
86 pub fn subtract(l: Limit, amount: usize) ?Limit {89 pub fn subtract(l: Limit, amount: usize) ?Limit {
87 if (l == .none) return .{ .next = .none };90 if (l == .unlimited) return .unlimited;
88 if (amount > @intFromEnum(l)) return null;91 if (amount > @intFromEnum(l)) return null;
89 return @enumFromInt(@intFromEnum(l) - amount);92 return @enumFromInt(@intFromEnum(l) - amount);
90 }93 }
...@@ -103,7 +106,7 @@ pub fn readAll(r: Reader, w: *std.io.BufferedWriter) anyerror!usize {...@@ -103,7 +106,7 @@ pub fn readAll(r: Reader, w: *std.io.BufferedWriter) anyerror!usize {
103 const readFn = r.vtable.read;106 const readFn = r.vtable.read;
104 var offset: usize = 0;107 var offset: usize = 0;
105 while (true) {108 while (true) {
106 const status = try readFn(r.context, w, .none);109 const status = try readFn(r.context, w, .unlimited);
107 offset += status.len;110 offset += status.len;
108 if (status.end) return offset;111 if (status.end) return offset;
109 }112 }
...@@ -119,21 +122,21 @@ pub fn readAlloc(r: Reader, gpa: std.mem.Allocator, max_size: usize) anyerror![]...@@ -119,21 +122,21 @@ pub fn readAlloc(r: Reader, gpa: std.mem.Allocator, max_size: usize) anyerror![]
119 const readFn = r.vtable.read;122 const readFn = r.vtable.read;
120 var aw: std.io.AllocatingWriter = undefined;123 var aw: std.io.AllocatingWriter = undefined;
121 errdefer aw.deinit();124 errdefer aw.deinit();
122 const bw = aw.init(gpa);125 aw.init(gpa);
123 var remaining = max_size;126 var remaining = max_size;
124 while (remaining > 0) {127 while (remaining > 0) {
125 const status = try readFn(r.context, bw, .init(remaining));128 const status = try readFn(r.context, &aw.buffered_writer, .limited(remaining));
126 if (status.end) break;129 if (status.end) break;
127 remaining -= status.len;130 remaining -= status.len;
128 }131 }
129 return aw.toOwnedSlice(gpa);132 return aw.toOwnedSlice();
130}133}
131134
132/// Reads the stream until the end, ignoring all the data.135/// Reads the stream until the end, ignoring all the data.
133/// Returns the number of bytes discarded.136/// Returns the number of bytes discarded.
134pub fn discardUntilEnd(r: Reader) anyerror!usize {137pub fn discardUntilEnd(r: Reader) anyerror!usize {
135 var bw = std.io.null_writer.unbuffered();138 var bw = std.io.Writer.null.unbuffered();
136 return readAll(r, &bw);139 return r.readAll(&bw);
137}140}
138141
139test "readAlloc when the backing reader provides one byte at a time" {142test "readAlloc when the backing reader provides one byte at a time" {
lib/std/io/Writer.zig+8-1
...@@ -60,6 +60,13 @@ pub const Offset = enum(u64) {...@@ -60,6 +60,13 @@ pub const Offset = enum(u64) {
60 pub fn toInt(o: Offset) ?u64 {60 pub fn toInt(o: Offset) ?u64 {
61 return if (o == .none) null else @intFromEnum(o);61 return if (o == .none) null else @intFromEnum(o);
62 }62 }
63
64 pub fn advance(o: Offset, amount: u64) Offset {
65 return switch (o) {
66 .none => .none,
67 else => .init(@intFromEnum(o) + amount),
68 };
69 }
63};70};
6471
65pub fn writev(w: Writer, data: []const []const u8) anyerror!usize {72pub fn writev(w: Writer, data: []const []const u8) anyerror!usize {
...@@ -106,7 +113,7 @@ pub fn buffered(w: Writer, buffer: []u8) std.io.BufferedWriter {...@@ -106,7 +113,7 @@ pub fn buffered(w: Writer, buffer: []u8) std.io.BufferedWriter {
106}113}
107114
108pub fn unbuffered(w: Writer) std.io.BufferedWriter {115pub fn unbuffered(w: Writer) std.io.BufferedWriter {
109 return buffered(w, &.{});116 return w.buffered(&.{});
110}117}
111118
112/// A `Writer` that discards all data.119/// A `Writer` that discards all data.
lib/std/net.zig+4-4
...@@ -1853,7 +1853,7 @@ pub const Stream = struct {...@@ -1853,7 +1853,7 @@ pub const Stream = struct {
1853 },1853 },
1854 else => &.{1854 else => &.{
1855 .writeSplat = posix_writeSplat,1855 .writeSplat = posix_writeSplat,
1856 .writeFile = std.fs.File.writer_writeFile,1856 .writeFile = std.fs.File.writeFile,
1857 },1857 },
1858 },1858 },
1859 };1859 };
...@@ -1960,7 +1960,7 @@ pub const Stream = struct {...@@ -1960,7 +1960,7 @@ pub const Stream = struct {
1960 return n;1960 return n;
1961 }1961 }
19621962
1963 fn posix_writeSplat(context: *anyopaque, data: []const []const u8, splat: usize) anyerror!usize {1963 fn posix_writeSplat(context: ?*anyopaque, data: []const []const u8, splat: usize) anyerror!usize {
1964 const sock_fd = opaqueToHandle(context);1964 const sock_fd = opaqueToHandle(context);
1965 comptime assert(native_os != .windows);1965 comptime assert(native_os != .windows);
1966 var splat_buffer: [256]u8 = undefined;1966 var splat_buffer: [256]u8 = undefined;
...@@ -2029,7 +2029,7 @@ pub const Stream = struct {...@@ -2029,7 +2029,7 @@ pub const Stream = struct {
20292029
2030 const max_buffers_len = 8;2030 const max_buffers_len = 8;
20312031
2032 fn handleToOpaque(handle: Handle) *anyopaque {2032 fn handleToOpaque(handle: Handle) ?*anyopaque {
2033 return switch (@typeInfo(Handle)) {2033 return switch (@typeInfo(Handle)) {
2034 .pointer => @ptrCast(handle),2034 .pointer => @ptrCast(handle),
2035 .int => @ptrFromInt(@as(u32, @bitCast(handle))),2035 .int => @ptrFromInt(@as(u32, @bitCast(handle))),
...@@ -2037,7 +2037,7 @@ pub const Stream = struct {...@@ -2037,7 +2037,7 @@ pub const Stream = struct {
2037 };2037 };
2038 }2038 }
20392039
2040 fn opaqueToHandle(userdata: *anyopaque) Handle {2040 fn opaqueToHandle(userdata: ?*anyopaque) Handle {
2041 return switch (@typeInfo(Handle)) {2041 return switch (@typeInfo(Handle)) {
2042 .pointer => @ptrCast(userdata),2042 .pointer => @ptrCast(userdata),
2043 .int => @intCast(@intFromPtr(userdata)),2043 .int => @intCast(@intFromPtr(userdata)),
lib/std/process/Child.zig+7-3
...@@ -1004,13 +1004,17 @@ fn forkChildErrReport(fd: i32, err: ChildProcess.SpawnError) noreturn {...@@ -1004,13 +1004,17 @@ fn forkChildErrReport(fd: i32, err: ChildProcess.SpawnError) noreturn {
10041004
1005fn writeIntFd(fd: i32, value: ErrInt) !void {1005fn writeIntFd(fd: i32, value: ErrInt) !void {
1006 const file: File = .{ .handle = fd };1006 const file: File = .{ .handle = fd };
1007 var bw = file.writer().unbuffered();1007 var buffer: [8]u8 = undefined;
1008 bw.writeInt(u64, @intCast(value), .little) catch return error.SystemResources;1008 std.mem.writeInt(u64, &buffer, @intCast(value), .little);
1009 file.writeAll(&buffer) catch return error.SystemResorces;
1009}1010}
10101011
1011fn readIntFd(fd: i32) !ErrInt {1012fn readIntFd(fd: i32) !ErrInt {
1012 const file: File = .{ .handle = fd };1013 const file: File = .{ .handle = fd };
1013 return @intCast(file.reader().readInt(u64, .little) catch return error.SystemResources);1014 var buffer: [8]u8 = undefined;
1015 const n = file.readAll(&buffer) catch return error.SystemResources;
1016 if (n != buffer.len) return error.SystemResources;
1017 return @intCast(std.mem.readInt(u64, &buffer, .little));
1014}1018}
10151019
1016const ErrInt = std.meta.Int(.unsigned, @sizeOf(anyerror) * 8);1020const ErrInt = std.meta.Int(.unsigned, @sizeOf(anyerror) * 8);
lib/std/tar/Writer.zig+1-1
...@@ -44,7 +44,7 @@ pub fn writeFile(self: *Self, sub_path: []const u8, file: std.fs.File) !void {...@@ -44,7 +44,7 @@ pub fn writeFile(self: *Self, sub_path: []const u8, file: std.fs.File) !void {
44 try header.setMtime(mtime);44 try header.setMtime(mtime);
45 try header.write(self.underlying_writer);45 try header.write(self.underlying_writer);
4646
47 try self.underlying_writer.writeFileAll(file, .{ .len = .init(stat.size) });47 try self.underlying_writer.writeFileAll(file, .{ .limit = .limited(stat.size) });
48 try self.writePadding(stat.size);48 try self.writePadding(stat.size);
49}49}
5050
lib/std/zig.zig+6-9
...@@ -414,9 +414,8 @@ test fmtId {...@@ -414,9 +414,8 @@ test fmtId {
414/// Print the string as a Zig identifier, escaping it with `@""` syntax if needed.414/// Print the string as a Zig identifier, escaping it with `@""` syntax if needed.
415fn formatId(415fn formatId(
416 bytes: []const u8,416 bytes: []const u8,
417 bw: *std.io.BufferedWriter,
417 comptime fmt: []const u8,418 comptime fmt: []const u8,
418 options: std.fmt.FormatOptions,
419 writer: *std.io.BufferedWriter,
420) !void {419) !void {
421 const allow_primitive, const allow_underscore = comptime parse_fmt: {420 const allow_primitive, const allow_underscore = comptime parse_fmt: {
422 var allow_primitive = false;421 var allow_primitive = false;
...@@ -442,11 +441,11 @@ fn formatId(...@@ -442,11 +441,11 @@ fn formatId(
442 (allow_primitive or !std.zig.isPrimitive(bytes)) and441 (allow_primitive or !std.zig.isPrimitive(bytes)) and
443 (allow_underscore or !isUnderscore(bytes)))442 (allow_underscore or !isUnderscore(bytes)))
444 {443 {
445 return writer.writeAll(bytes);444 return bw.writeAll(bytes);
446 }445 }
447 try writer.writeAll("@\"");446 try bw.writeAll("@\"");
448 try stringEscape(bytes, "", options, writer);447 try stringEscape(bytes, bw, "");
449 try writer.writeByte('"');448 try bw.writeByte('"');
450}449}
451450
452/// Return a Formatter for Zig Escapes of a double quoted string.451/// Return a Formatter for Zig Escapes of a double quoted string.
...@@ -473,11 +472,9 @@ test fmtEscapes {...@@ -473,11 +472,9 @@ test fmtEscapes {
473/// Format `{'}` treats contents as a single-quoted string.472/// Format `{'}` treats contents as a single-quoted string.
474pub fn stringEscape(473pub fn stringEscape(
475 bytes: []const u8,474 bytes: []const u8,
476 comptime f: []const u8,
477 options: std.fmt.FormatOptions,
478 bw: *std.io.BufferedWriter,475 bw: *std.io.BufferedWriter,
476 comptime f: []const u8,
479) !void {477) !void {
480 _ = options;
481 for (bytes) |byte| switch (byte) {478 for (bytes) |byte| switch (byte) {
482 '\n' => try bw.writeAll("\\n"),479 '\n' => try bw.writeAll("\\n"),
483 '\r' => try bw.writeAll("\\r"),480 '\r' => try bw.writeAll("\\r"),
lib/std/zig/ErrorBundle.zig+2-2
...@@ -190,7 +190,7 @@ fn renderErrorMessageToWriter(...@@ -190,7 +190,7 @@ fn renderErrorMessageToWriter(
190) anyerror!void {190) anyerror!void {
191 const ttyconf = options.ttyconf;191 const ttyconf = options.ttyconf;
192 const err_msg = eb.getErrorMessage(err_msg_index);192 const err_msg = eb.getErrorMessage(err_msg_index);
193 const prefix_start = bw.bytes_written;193 const prefix_start = bw.count;
194 if (err_msg.src_loc != .none) {194 if (err_msg.src_loc != .none) {
195 const src = eb.extraData(SourceLocation, @intFromEnum(err_msg.src_loc));195 const src = eb.extraData(SourceLocation, @intFromEnum(err_msg.src_loc));
196 try bw.splatByteAll(' ', indent);196 try bw.splatByteAll(' ', indent);
...@@ -205,7 +205,7 @@ fn renderErrorMessageToWriter(...@@ -205,7 +205,7 @@ fn renderErrorMessageToWriter(
205 try bw.writeAll(": ");205 try bw.writeAll(": ");
206 // This is the length of the part before the error message:206 // This is the length of the part before the error message:
207 // e.g. "file.zig:4:5: error: "207 // e.g. "file.zig:4:5: error: "
208 const prefix_len = bw.bytes_written - prefix_start;208 const prefix_len = bw.count - prefix_start;
209 try ttyconf.setColor(bw, .reset);209 try ttyconf.setColor(bw, .reset);
210 try ttyconf.setColor(bw, .bold);210 try ttyconf.setColor(bw, .bold);
211 if (err_msg.count == 1) {211 if (err_msg.count == 1) {
test/src/Cases.zig+1-1
...@@ -378,7 +378,7 @@ fn addFromDirInner(...@@ -378,7 +378,7 @@ fn addFromDirInner(
378 current_file.* = filename;378 current_file.* = filename;
379379
380 const max_file_size = 10 * 1024 * 1024;380 const max_file_size = 10 * 1024 * 1024;
381 const src = try iterable_dir.readFileAllocOptions(ctx.arena, filename, max_file_size, null, .@"1", 0);381 const src = try iterable_dir.readFileAllocOptions(filename, ctx.arena, .limited(max_file_size), null, .@"1", 0);
382382
383 // Parse the manifest383 // Parse the manifest
384 var manifest = try TestManifest.parse(ctx.arena, src);384 var manifest = try TestManifest.parse(ctx.arena, src);
test/standalone/run_output_caching/build.zig+2-2
...@@ -75,7 +75,7 @@ const CheckOutputCaching = struct {...@@ -75,7 +75,7 @@ const CheckOutputCaching = struct {
75 pub fn init(owner: *std.Build, expect_caching: bool, output_paths: []const std.Build.LazyPath) *CheckOutputCaching {75 pub fn init(owner: *std.Build, expect_caching: bool, output_paths: []const std.Build.LazyPath) *CheckOutputCaching {
76 const check = owner.allocator.create(CheckOutputCaching) catch @panic("OOM");76 const check = owner.allocator.create(CheckOutputCaching) catch @panic("OOM");
77 check.* = .{77 check.* = .{
78 .step = std.Build.Step.init(.{78 .step = .init(.{
79 .id = .custom,79 .id = .custom,
80 .name = "check output caching",80 .name = "check output caching",
81 .owner = owner,81 .owner = owner,
...@@ -112,7 +112,7 @@ const CheckPathEquality = struct {...@@ -112,7 +112,7 @@ const CheckPathEquality = struct {
112 pub fn init(owner: *std.Build, expected_equality: bool, output_paths: []const std.Build.LazyPath) *CheckPathEquality {112 pub fn init(owner: *std.Build, expected_equality: bool, output_paths: []const std.Build.LazyPath) *CheckPathEquality {
113 const check = owner.allocator.create(CheckPathEquality) catch @panic("OOM");113 const check = owner.allocator.create(CheckPathEquality) catch @panic("OOM");
114 check.* = .{114 check.* = .{
115 .step = std.Build.Step.init(.{115 .step = .init(.{
116 .id = .custom,116 .id = .custom,
117 .name = "check output path equality",117 .name = "check output path equality",
118 .owner = owner,118 .owner = owner,
test/tests.zig+1-1
...@@ -2711,7 +2711,7 @@ pub fn addIncrementalTests(b: *std.Build, test_step: *Step) !void {...@@ -2711,7 +2711,7 @@ pub fn addIncrementalTests(b: *std.Build, test_step: *Step) !void {
27112711
2712 run.addArg(b.graph.zig_exe);2712 run.addArg(b.graph.zig_exe);
2713 run.addFileArg(b.path("test/incremental/").path(b, entry.path));2713 run.addFileArg(b.path("test/incremental/").path(b, entry.path));
2714 run.addArgs(&.{ "--zig-lib-dir", b.fmt("{}", .{b.graph.zig_lib_directory}) });2714 run.addArgs(&.{ "--zig-lib-dir", b.fmt("{f}", .{b.graph.zig_lib_directory}) });
27152715
2716 run.addCheck(.{ .expect_term = .{ .Exited = 0 } });2716 run.addCheck(.{ .expect_term = .{ .Exited = 0 } });
27172717