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 {
279279
280280 const ancestor_ver = try std.SemanticVersion.parse(tagged_ancestor);
281281 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 });
283283 std.process.exit(1);
284284 }
285285
......@@ -304,7 +304,7 @@ pub fn build(b: *std.Build) !void {
304304 if (enable_llvm) {
305305 const cmake_cfg = if (static_llvm) null else blk: {
306306 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;
308308 break :blk parseConfigH(b, file_contents);
309309 } else {
310310 std.log.warn("config.h could not be located automatically. Consider providing it explicitly via \"-Dconfig_h\"", .{});
......@@ -912,7 +912,7 @@ fn addCxxKnownPath(
912912 return error.RequiredLibraryNotFound;
913913
914914 const path_padded = run: {
915 var args = std.ArrayList([]const u8).init(b.allocator);
915 var args: std.ArrayList([]const u8) = .init(b.allocator);
916916 try args.append(ctx.cxx_compiler);
917917 var it = std.mem.tokenizeAny(u8, ctx.cxx_compiler_arg1, &std.ascii.whitespace);
918918 while (it.next()) |arg| try args.append(arg);
......@@ -1418,7 +1418,7 @@ fn generateLangRef(b: *std.Build) std.Build.LazyPath {
14181418 });
14191419
14201420 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}", .{
14221422 b.build_root, @errorName(err),
14231423 });
14241424 };
......@@ -1439,7 +1439,7 @@ fn generateLangRef(b: *std.Build) std.Build.LazyPath {
14391439 // in a temporary directory
14401440 "--cache-root", b.cache_root.path orelse ".",
14411441 });
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}) });
14431443 cmd.addArgs(&.{"-i"});
14441444 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 {
330330 }
331331 }
332332
333 const stderr = std.io.getStdErr();
333 const stderr: std.fs.File = .stderr();
334334 const ttyconf = get_tty_conf(color, stderr);
335335 switch (ttyconf) {
336336 .no_color => try graph.env_map.put("NO_COLOR", "1"),
......@@ -365,7 +365,7 @@ pub fn main() !void {
365365 .data = buffer.items,
366366 .flags = .{ .exclusive = true },
367367 }) catch |err| {
368 fatal("unable to write configuration results to '{}{s}': {s}", .{
368 fatal("unable to write configuration results to '{f}{s}': {s}", .{
369369 local_cache_directory, tmp_sub_path, @errorName(err),
370370 });
371371 };
......@@ -378,16 +378,11 @@ pub fn main() !void {
378378
379379 validateSystemLibraryOptions(builder);
380380
381 var stdout_writer: std.io.BufferedWriter = .{
382 .buffer = &stdout_buffer,
383 .unbuffered_writer = std.io.getStdOut().writer(),
384 };
385
386 if (help_menu)
387 return usage(builder, &stdout_writer);
388
389 if (steps_menu)
390 return steps(builder, &stdout_writer);
381 {
382 var stdout_bw = std.fs.File.stdout().writer().buffered(&stdio_buffer);
383 if (help_menu) return usage(builder, &stdout_bw);
384 if (steps_menu) return steps(builder, &stdout_bw);
385 }
391386
392387 var run: Run = .{
393388 .max_rss = max_rss,
......@@ -699,7 +694,7 @@ fn runStepNames(
699694 const ttyconf = run.ttyconf;
700695
701696 if (run.summary != .none) {
702 var bw = std.debug.lockStdErr2();
697 var bw = std.debug.lockStdErr2(&stdio_buffer);
703698 defer std.debug.unlockStdErr();
704699
705700 const total_count = success_count + failure_count + pending_count + skipped_count;
......@@ -1131,7 +1126,7 @@ fn workerMakeOneStep(
11311126 const show_stderr = s.result_stderr.len > 0;
11321127
11331128 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);
11351130 defer std.debug.unlockStdErr();
11361131
11371132 const gpa = b.allocator;
......@@ -1256,7 +1251,7 @@ fn steps(builder: *std.Build, bw: *std.io.BufferedWriter) !void {
12561251 }
12571252}
12581253
1259var stdout_buffer: [256]u8 = undefined;
1254var stdio_buffer: [256]u8 = undefined;
12601255
12611256fn usage(b: *std.Build, bw: *std.io.BufferedWriter) !void {
12621257 try bw.print(
lib/std/Build.zig+7-7
......@@ -284,7 +284,7 @@ pub fn create(
284284 .h_dir = undefined,
285285 .dest_dir = graph.env_map.get("DESTDIR"),
286286 .install_tls = .{
287 .step = Step.init(.{
287 .step = .init(.{
288288 .id = TopLevelStep.base_id,
289289 .name = "install",
290290 .owner = b,
......@@ -292,7 +292,7 @@ pub fn create(
292292 .description = "Copy build artifacts to prefix path",
293293 },
294294 .uninstall_tls = .{
295 .step = Step.init(.{
295 .step = .init(.{
296296 .id = TopLevelStep.base_id,
297297 .name = "uninstall",
298298 .owner = b,
......@@ -342,7 +342,7 @@ fn createChildOnly(
342342 .graph = parent.graph,
343343 .allocator = allocator,
344344 .install_tls = .{
345 .step = Step.init(.{
345 .step = .init(.{
346346 .id = TopLevelStep.base_id,
347347 .name = "install",
348348 .owner = child,
......@@ -350,7 +350,7 @@ fn createChildOnly(
350350 .description = "Copy build artifacts to prefix path",
351351 },
352352 .uninstall_tls = .{
353 .step = Step.init(.{
353 .step = .init(.{
354354 .id = TopLevelStep.base_id,
355355 .name = "uninstall",
356356 .owner = child,
......@@ -1525,7 +1525,7 @@ pub fn option(b: *Build, comptime T: type, name_raw: []const u8, description_raw
15251525pub fn step(b: *Build, name: []const u8, description: []const u8) *Step {
15261526 const step_info = b.allocator.create(TopLevelStep) catch @panic("OOM");
15271527 step_info.* = .{
1528 .step = Step.init(.{
1528 .step = .init(.{
15291529 .id = TopLevelStep.base_id,
15301530 .name = name,
15311531 .owner = b,
......@@ -1745,7 +1745,7 @@ pub fn addUserInputOption(b: *Build, name_raw: []const u8, value_raw: []const u8
17451745 return true;
17461746 },
17471747 .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)) });
17491749 return true;
17501750 },
17511751 }
......@@ -2059,7 +2059,7 @@ pub fn runAllowFail(
20592059 try Step.handleVerbose2(b, null, child.env_map, argv);
20602060 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 {
20632063 return error.ReadFailure;
20642064 };
20652065 errdefer b.allocator.free(stdout);
lib/std/Build/Cache.zig+2-2
......@@ -333,7 +333,7 @@ pub const Manifest = struct {
333333 pub const Diagnostic = union(enum) {
334334 none,
335335 manifest_create: fs.File.OpenError,
336 manifest_read: fs.File.ReadError,
336 manifest_read: anyerror,
337337 manifest_lock: fs.File.LockError,
338338 manifest_seek: fs.File.SeekError,
339339 file_open: FileOp,
......@@ -1062,7 +1062,7 @@ pub const Manifest = struct {
10621062
10631063 fn addDepFileMaybePost(self: *Manifest, dir: fs.Dir, dep_file_basename: []const u8) !void {
10641064 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));
10661066 defer gpa.free(dep_file_contents);
10671067
10681068 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 {
5757
5858pub fn format(
5959 self: Directory,
60 bw: *std.io.BufferedWriter,
6061 comptime fmt_string: []const u8,
61 options: fmt.FormatOptions,
62 writer: anytype,
6362) !void {
64 _ = options;
6563 if (fmt_string.len != 0) fmt.invalidFmtError(fmt_string, self);
6664 if (self.path) |p| {
67 try writer.writeAll(p);
68 try writer.writeAll(fs.path.sep_str);
65 try bw.writeAll(p);
66 try bw.writeAll(fs.path.sep_str);
6967 }
7068}
7169
lib/std/Build/Cache/Path.zig+10-11
......@@ -142,9 +142,8 @@ pub fn toStringZ(p: Path, allocator: Allocator) Allocator.Error![:0]u8 {
142142
143143pub fn format(
144144 self: Path,
145 bw: *std.io.BufferedWriter,
145146 comptime fmt_string: []const u8,
146 options: std.fmt.FormatOptions,
147 writer: anytype,
148147) !void {
149148 if (fmt_string.len == 1) {
150149 // Quote-escape the string.
......@@ -155,33 +154,33 @@ pub fn format(
155154 else => @compileError("unsupported format string: " ++ fmt_string),
156155 };
157156 if (self.root_dir.path) |p| {
158 try stringEscape(p, f, options, writer);
159 if (self.sub_path.len > 0) try stringEscape(fs.path.sep_str, f, options, writer);
157 try stringEscape(p, bw, f);
158 if (self.sub_path.len > 0) try stringEscape(fs.path.sep_str, bw, f);
160159 }
161160 if (self.sub_path.len > 0) {
162 try stringEscape(self.sub_path, f, options, writer);
161 try stringEscape(self.sub_path, bw, f);
163162 }
164163 return;
165164 }
166165 if (fmt_string.len > 0)
167166 std.fmt.invalidFmtError(fmt_string, self);
168167 if (std.fs.path.isAbsolute(self.sub_path)) {
169 try writer.writeAll(self.sub_path);
168 try bw.writeAll(self.sub_path);
170169 return;
171170 }
172171 if (self.root_dir.path) |p| {
173 try writer.writeAll(p);
172 try bw.writeAll(p);
174173 if (self.sub_path.len > 0) {
175 try writer.writeAll(fs.path.sep_str);
176 try writer.writeAll(self.sub_path);
174 try bw.writeAll(fs.path.sep_str);
175 try bw.writeAll(self.sub_path);
177176 }
178177 return;
179178 }
180179 if (self.sub_path.len > 0) {
181 try writer.writeAll(self.sub_path);
180 try bw.writeAll(self.sub_path);
182181 return;
183182 }
184 try writer.writeByte('.');
183 try bw.writeByte('.');
185184}
186185
187186pub fn eql(self: Path, other: Path) bool {
lib/std/Build/Fuzz/WebServer.zig+15-18
......@@ -169,8 +169,8 @@ fn serveFile(
169169 // The desired API is actually sendfile, which will require enhancing std.http.Server.
170170 // We load the file with every request so that the user can make changes to the file
171171 // 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| {
173 log.err("failed to read '{}{s}': {s}", .{ ws.zig_lib_directory, name, @errorName(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 '{f}{s}': {s}", .{ ws.zig_lib_directory, name, @errorName(err) });
174174 return error.AlreadyReported;
175175 };
176176 defer gpa.free(file_contents);
......@@ -206,7 +206,7 @@ fn serveWasm(
206206 });
207207 // std.http.Server does not have a sendfile API yet.
208208 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));
210210 defer gpa.free(file_contents);
211211 try request.respond(file_contents, .{
212212 .extra_headers = &.{
......@@ -251,10 +251,10 @@ fn buildWasmBinary(
251251 "-fsingle-threaded", //
252252 "--dep", "Walk", //
253253 "--dep", "html_render", //
254 try std.fmt.allocPrint(arena, "-Mroot={}", .{main_src_path}), //
255 try std.fmt.allocPrint(arena, "-MWalk={}", .{walk_src_path}), //
254 try std.fmt.allocPrint(arena, "-Mroot={f}", .{main_src_path}), //
255 try std.fmt.allocPrint(arena, "-MWalk={f}", .{walk_src_path}), //
256256 "--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}), //
258258 "--listen=-",
259259 });
260260
......@@ -280,13 +280,10 @@ fn buildWasmBinary(
280280 const stdout = poller.fifo(.stdout);
281281
282282 poll: while (true) {
283 while (stdout.readableLength() < @sizeOf(Header)) {
284 if (!(try poller.poll())) break :poll;
285 }
286 const header = stdout.reader().readStruct(Header) catch unreachable;
287 while (stdout.readableLength() < header.bytes_len) {
288 if (!(try poller.poll())) break :poll;
289 }
283 while (stdout.readableLength() < @sizeOf(Header)) if (!try poller.poll()) break :poll;
284 var header: Header = undefined;
285 assert(stdout.read(std.mem.asBytes(&header)) == @sizeOf(Header));
286 while (stdout.readableLength() < header.bytes_len) if (!try poller.poll()) break :poll;
290287 const body = stdout.readableSliceOfLen(header.bytes_len);
291288
292289 switch (header.tag) {
......@@ -527,7 +524,7 @@ fn serveSourcesTar(ws: *WebServer, request: *std.http.Server.Request) !void {
527524
528525 for (deduped_paths) |joined_path| {
529526 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) });
531528 continue;
532529 };
533530 defer file.close();
......@@ -605,7 +602,7 @@ fn prepareTables(
605602
606603 const rebuilt_exe_path = run_step.rebuilt_executable.?;
607604 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}", .{
609606 run_step.step.name, rebuilt_exe_path, @errorName(err),
610607 });
611608 return error.AlreadyReported;
......@@ -617,7 +614,7 @@ fn prepareTables(
617614 .sub_path = "v/" ++ std.fmt.hex(coverage_id),
618615 };
619616 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}", .{
621618 run_step.step.name, coverage_file_path, @errorName(err),
622619 });
623620 return error.AlreadyReported;
......@@ -625,7 +622,7 @@ fn prepareTables(
625622 defer coverage_file.close();
626623
627624 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) });
629626 return error.AlreadyReported;
630627 };
631628
......@@ -637,7 +634,7 @@ fn prepareTables(
637634 coverage_file.handle,
638635 0,
639636 ) 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) });
641638 return error.AlreadyReported;
642639 };
643640 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 {
516516 const stdout = zp.poller.fifo(.stdout);
517517
518518 poll: while (true) {
519 while (stdout.readableLength() < @sizeOf(Header)) {
520 if (!(try zp.poller.poll())) break :poll;
521 }
522 const header = stdout.reader().readStruct(Header) catch unreachable;
523 while (stdout.readableLength() < header.bytes_len) {
524 if (!(try zp.poller.poll())) break :poll;
525 }
519 while (stdout.readableLength() < @sizeOf(Header)) if (!try zp.poller.poll()) break :poll;
520 var header: Header = undefined;
521 assert(stdout.read(std.mem.asBytes(&header)) == @sizeOf(Header));
522 while (stdout.readableLength() < header.bytes_len) if (!try zp.poller.poll()) break :poll;
526523 const body = stdout.readableSliceOfLen(header.bytes_len);
527524
528525 switch (header.tag) {
lib/std/Build/Step/CheckFile.zig+2-2
......@@ -28,7 +28,7 @@ pub fn create(
2828) *CheckFile {
2929 const check_file = owner.allocator.create(CheckFile) catch @panic("OOM");
3030 check_file.* = .{
31 .step = Step.init(.{
31 .step = .init(.{
3232 .id = base_id,
3333 .name = "CheckFile",
3434 .owner = owner,
......@@ -53,7 +53,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
5353 try step.singleUnchangingWatchInput(check_file.source);
5454
5555 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| {
5757 return step.fail("unable to read '{s}': {s}", .{
5858 src_path, @errorName(err),
5959 });
lib/std/Build/Step/CheckObject.zig+300-401
......@@ -28,14 +28,14 @@ pub fn create(
2828 const gpa = owner.allocator;
2929 const check_object = gpa.create(CheckObject) catch @panic("OOM");
3030 check_object.* = .{
31 .step = Step.init(.{
31 .step = .init(.{
3232 .id = base_id,
3333 .name = "CheckObject",
3434 .owner = owner,
3535 .makeFn = make,
3636 }),
3737 .source = source.dupe(owner),
38 .checks = std.ArrayList(Check).init(gpa),
38 .checks = .init(gpa),
3939 .obj_format = obj_format,
4040 };
4141 check_object.source.addStepDependencies(&check_object.step);
......@@ -74,13 +74,13 @@ const Action = struct {
7474 b: *std.Build,
7575 step: *Step,
7676 haystack: []const u8,
77 global_vars: anytype,
77 global_vars: *std.StringHashMap(u64),
7878 ) !bool {
7979 assert(act.tag == .extract);
8080 const hay = mem.trim(u8, haystack, " ");
8181 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);
8484 var hay_it = mem.tokenizeScalar(u8, hay, ' ');
8585 var needle_it = mem.tokenizeScalar(u8, phrase, ' ');
8686
......@@ -153,11 +153,11 @@ const Action = struct {
153153 /// Will return true if the `phrase` is correctly parsed into an RPN program and
154154 /// its reduced, computed value compares using `op` with the expected value, either
155155 /// 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 {
157157 const gpa = step.owner.allocator;
158158 const phrase = act.phrase.resolve(b, step);
159 var op_stack = std.ArrayList(enum { add, sub, mod, mul }).init(gpa);
160 var values = std.ArrayList(u64).init(gpa);
159 var op_stack: std.ArrayList(enum { add, sub, mod, mul }) = .init(gpa);
160 var values: std.ArrayList(u64) = .init(gpa);
161161
162162 var it = mem.tokenizeScalar(u8, phrase, ' ');
163163 while (it.next()) |next| {
......@@ -230,17 +230,15 @@ const ComputeCompareExpected = struct {
230230 },
231231
232232 pub fn format(
233 value: @This(),
233 value: ComputeCompareExpected,
234 bw: *std.io.BufferedWriter,
234235 comptime fmt: []const u8,
235 options: std.fmt.FormatOptions,
236 writer: anytype,
237 ) !void {
236 ) anyerror!void {
238237 if (fmt.len != 0) std.fmt.invalidFmtError(fmt, value);
239 _ = options;
240 try writer.print("{s} ", .{@tagName(value.op)});
238 try bw.print("{s} ", .{@tagName(value.op)});
241239 switch (value.value) {
242 .variable => |name| try writer.writeAll(name),
243 .literal => |x| try writer.print("{x}", .{x}),
240 .variable => |name| try bw.writeAll(name),
241 .literal => |x| try bw.print("{x}", .{x}),
244242 }
245243 }
246244};
......@@ -566,15 +564,15 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {
566564
567565 const src_path = check_object.source.getPath3(b, step);
568566 const contents = src_path.root_dir.handle.readFileAllocOptions(
569 gpa,
570567 src_path.sub_path,
571 check_object.max_bytes,
568 gpa,
569 .limited(check_object.max_bytes),
572570 null,
573571 .of(u64),
574572 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);
578576 for (check_object.checks.items) |chk| {
579577 if (chk.kind == .compute_compare) {
580578 assert(chk.actions.items.len == 1);
......@@ -588,7 +586,7 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {
588586 return step.fail(
589587 \\
590588 \\========= comparison failed for action: ===========
591 \\{s} {}
589 \\{s} {f}
592590 \\===================================================
593591 , .{ act.phrase.resolve(b, step), act.expected.? });
594592 }
......@@ -621,15 +619,13 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {
621619
622620 fn formatMessageString(
623621 ctx: Ctx,
622 bw: *std.io.BufferedWriter,
624623 comptime unused_fmt_string: []const u8,
625 options: std.fmt.FormatOptions,
626 writer: anytype,
627624 ) !void {
628625 _ = unused_fmt_string;
629 _ = options;
630626 switch (ctx.kind) {
631 .dump_section => try writer.print("{s}", .{std.fmt.fmtSliceEscapeLower(ctx.msg)}),
632 else => try writer.writeAll(ctx.msg),
627 .dump_section => try bw.print("{f}", .{std.fmt.fmtSliceEscapeLower(ctx.msg)}),
628 else => try bw.writeAll(ctx.msg),
633629 }
634630 }
635631 }.fmtMessageString;
......@@ -644,11 +640,11 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {
644640 return step.fail(
645641 \\
646642 \\========= expected to find: ==========================
647 \\{s}
643 \\{f}
648644 \\========= but parsed file does not contain it: =======
649 \\{s}
645 \\{f}
650646 \\========= file path: =================================
651 \\{}
647 \\{f}
652648 , .{
653649 fmtMessageString(chk.kind, act.phrase.resolve(b, step)),
654650 fmtMessageString(chk.kind, output),
......@@ -664,11 +660,11 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {
664660 return step.fail(
665661 \\
666662 \\========= expected to find: ==========================
667 \\*{s}*
663 \\*{f}*
668664 \\========= but parsed file does not contain it: =======
669 \\{s}
665 \\{f}
670666 \\========= file path: =================================
671 \\{}
667 \\{f}
672668 , .{
673669 fmtMessageString(chk.kind, act.phrase.resolve(b, step)),
674670 fmtMessageString(chk.kind, output),
......@@ -683,11 +679,11 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {
683679 return step.fail(
684680 \\
685681 \\========= expected not to find: ===================
686 \\{s}
682 \\{f}
687683 \\========= but parsed file does contain it: ========
688 \\{s}
684 \\{f}
689685 \\========= file path: ==============================
690 \\{}
686 \\{f}
691687 , .{
692688 fmtMessageString(chk.kind, act.phrase.resolve(b, step)),
693689 fmtMessageString(chk.kind, output),
......@@ -703,13 +699,13 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {
703699 return step.fail(
704700 \\
705701 \\========= expected to find and extract: ==============
706 \\{s}
702 \\{f}
707703 \\========= but parsed file does not contain it: =======
708 \\{s}
704 \\{f}
709705 \\========= file path: ==============================
710 \\{}
706 \\{f}
711707 , .{
712 act.phrase.resolve(b, step),
708 fmtMessageString(chk.kind, act.phrase.resolve(b, step)),
713709 fmtMessageString(chk.kind, output),
714710 src_path,
715711 });
......@@ -762,14 +758,14 @@ const MachODumper = struct {
762758 },
763759 .SYMTAB => {
764760 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];
766762 const strtab = ctx.data[lc.stroff..][0..lc.strsize];
767763 try ctx.symtab.appendUnalignedSlice(ctx.gpa, symtab);
768764 try ctx.strtab.appendSlice(ctx.gpa, strtab);
769765 },
770766 .DYSYMTAB => {
771767 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];
773769 try ctx.indsymtab.appendUnalignedSlice(ctx.gpa, indexes);
774770 },
775771 .LOAD_DYLIB,
......@@ -787,7 +783,7 @@ const MachODumper = struct {
787783
788784 fn getString(ctx: ObjectContext, off: u32) [:0]const u8 {
789785 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);
791787 }
792788
793789 fn getLoadCommandIterator(ctx: ObjectContext) macho.LoadCommandIterator {
......@@ -1232,7 +1228,7 @@ const MachODumper = struct {
12321228 }
12331229
12341230 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);
12361232 defer rebases.deinit();
12371233 try ctx.parseRebaseInfo(data, &rebases);
12381234 mem.sort(u64, rebases.items, {}, std.sort.asc(u64));
......@@ -1242,14 +1238,13 @@ const MachODumper = struct {
12421238 }
12431239
12441240 fn parseRebaseInfo(ctx: ObjectContext, data: []const u8, rebases: *std.ArrayList(u64)) !void {
1245 var stream: std.io.FixedBufferStream = .{ .buffer = data };
1246 var creader = std.io.countingReader(stream.reader());
1247 const reader = creader.reader();
1241 var br: std.io.BufferedReader = undefined;
1242 br.initFixed(data);
12481243
12491244 var seg_id: ?u8 = null;
12501245 var offset: u64 = 0;
12511246 while (true) {
1252 const byte = reader.readByte() catch break;
1247 const byte = br.takeByte() catch break;
12531248 const opc = byte & macho.REBASE_OPCODE_MASK;
12541249 const imm = byte & macho.REBASE_IMMEDIATE_MASK;
12551250 switch (opc) {
......@@ -1257,17 +1252,17 @@ const MachODumper = struct {
12571252 macho.REBASE_OPCODE_SET_TYPE_IMM => {},
12581253 macho.REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB => {
12591254 seg_id = imm;
1260 offset = try std.leb.readUleb128(u64, reader);
1255 offset = try br.takeLeb128(u64);
12611256 },
12621257 macho.REBASE_OPCODE_ADD_ADDR_IMM_SCALED => {
12631258 offset += imm * @sizeOf(u64);
12641259 },
12651260 macho.REBASE_OPCODE_ADD_ADDR_ULEB => {
1266 const addend = try std.leb.readUleb128(u64, reader);
1261 const addend = try br.takeLeb128(u64);
12671262 offset += addend;
12681263 },
12691264 macho.REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB => {
1270 const addend = try std.leb.readUleb128(u64, reader);
1265 const addend = try br.takeLeb128(u64);
12711266 const seg = ctx.segments.items[seg_id.?];
12721267 const addr = seg.vmaddr + offset;
12731268 try rebases.append(addr);
......@@ -1284,11 +1279,11 @@ const MachODumper = struct {
12841279 ntimes = imm;
12851280 },
12861281 macho.REBASE_OPCODE_DO_REBASE_ULEB_TIMES => {
1287 ntimes = try std.leb.readUleb128(u64, reader);
1282 ntimes = try br.takeLeb128(u64);
12881283 },
12891284 macho.REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB => {
1290 ntimes = try std.leb.readUleb128(u64, reader);
1291 skip = try std.leb.readUleb128(u64, reader);
1285 ntimes = try br.takeLeb128(u64);
1286 skip = try br.takeLeb128(u64);
12921287 },
12931288 else => unreachable,
12941289 }
......@@ -1331,7 +1326,7 @@ const MachODumper = struct {
13311326 };
13321327
13331328 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);
13351330 defer {
13361331 for (bindings.items) |*b| {
13371332 b.deinit(ctx.gpa);
......@@ -1354,9 +1349,8 @@ const MachODumper = struct {
13541349 }
13551350
13561351 fn parseBindInfo(ctx: ObjectContext, data: []const u8, bindings: *std.ArrayList(Binding)) !void {
1357 var stream: std.io.FixedBufferStream = .{ .buffer = data };
1358 var creader = std.io.countingReader(stream.reader());
1359 const reader = creader.reader();
1352 var br: std.io.BufferedReader = undefined;
1353 br.initFixed(data);
13601354
13611355 var seg_id: ?u8 = null;
13621356 var tag: Binding.Tag = .self;
......@@ -1364,11 +1358,10 @@ const MachODumper = struct {
13641358 var offset: u64 = 0;
13651359 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);
13681362 defer name_buf.deinit();
13691363
1370 while (true) {
1371 const byte = reader.readByte() catch break;
1364 while (br.takeByte()) |byte| {
13721365 const opc = byte & macho.BIND_OPCODE_MASK;
13731366 const imm = byte & macho.BIND_IMMEDIATE_MASK;
13741367 switch (opc) {
......@@ -1389,7 +1382,7 @@ const MachODumper = struct {
13891382 },
13901383 macho.BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB => {
13911384 seg_id = imm;
1392 offset = try std.leb.readUleb128(u64, reader);
1385 offset = try br.takeLeb128(u64);
13931386 },
13941387 macho.BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM => {
13951388 name_buf.clearRetainingCapacity();
......@@ -1398,10 +1391,10 @@ const MachODumper = struct {
13981391 try name_buf.append(0);
13991392 },
14001393 macho.BIND_OPCODE_SET_ADDEND_SLEB => {
1401 addend = try std.leb.readIleb128(i64, reader);
1394 addend = try br.takeLeb128(i64);
14021395 },
14031396 macho.BIND_OPCODE_ADD_ADDR_ULEB => {
1404 const x = try std.leb.readUleb128(u64, reader);
1397 const x = try br.takeLeb128(u64);
14051398 offset = @intCast(@as(i64, @intCast(offset)) + @as(i64, @bitCast(x)));
14061399 },
14071400 macho.BIND_OPCODE_DO_BIND,
......@@ -1416,14 +1409,14 @@ const MachODumper = struct {
14161409 switch (opc) {
14171410 macho.BIND_OPCODE_DO_BIND => {},
14181411 macho.BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB => {
1419 add_addr = try std.leb.readUleb128(u64, reader);
1412 add_addr = try br.takeLeb128(u64);
14201413 },
14211414 macho.BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED => {
14221415 add_addr = imm * @sizeOf(u64);
14231416 },
14241417 macho.BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB => {
1425 count = try std.leb.readUleb128(u64, reader);
1426 skip = try std.leb.readUleb128(u64, reader);
1418 count = try br.takeLeb128(u64);
1419 skip = try br.takeLeb128(u64);
14271420 },
14281421 else => unreachable,
14291422 }
......@@ -1444,7 +1437,7 @@ const MachODumper = struct {
14441437 },
14451438 else => break,
14461439 }
1447 }
1440 } else |_| {}
14481441 }
14491442
14501443 fn dumpExportsTrie(ctx: ObjectContext, data: []const u8, bw: *std.io.BufferedWriter) !void {
......@@ -1453,9 +1446,10 @@ const MachODumper = struct {
14531446 var arena = std.heap.ArenaAllocator.init(ctx.gpa);
14541447 defer arena.deinit();
14551448
1456 var exports = std.ArrayList(Export).init(arena.allocator());
1457 var it = TrieIterator{ .data = data };
1458 try parseTrieNode(arena.allocator(), &it, "", &exports);
1449 var exports: std.ArrayList(Export) = .init(arena.allocator());
1450 var br: std.io.BufferedReader = undefined;
1451 br.initFixed(data);
1452 try parseTrieNode(arena.allocator(), &br, "", &exports);
14591453
14601454 mem.sort(Export, exports.items, {}, Export.lessThan);
14611455
......@@ -1484,46 +1478,6 @@ const MachODumper = struct {
14841478 }
14851479 }
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
15271481 const Export = struct {
15281482 name: []const u8,
15291483 tag: enum { @"export", reexport, stub_resolver },
......@@ -1563,17 +1517,17 @@ const MachODumper = struct {
15631517
15641518 fn parseTrieNode(
15651519 arena: Allocator,
1566 it: *TrieIterator,
1520 br: *std.io.BufferedReader,
15671521 prefix: []const u8,
15681522 exports: *std.ArrayList(Export),
15691523 ) !void {
1570 const size = try it.readUleb128();
1524 const size = try br.takeLeb128(u64);
15711525 if (size > 0) {
1572 const flags = try it.readUleb128();
1526 const flags = try br.takeLeb128(u64);
15731527 switch (flags) {
15741528 macho.EXPORT_SYMBOL_FLAGS_REEXPORT => {
1575 const ord = try it.readUleb128();
1576 const name = try arena.dupe(u8, try it.readString());
1529 const ord = try br.takeLeb128(u64);
1530 const name = try br.takeDelimiterConclusive(0);
15771531 try exports.append(.{
15781532 .name = if (name.len > 0) name else prefix,
15791533 .tag = .reexport,
......@@ -1581,8 +1535,8 @@ const MachODumper = struct {
15811535 });
15821536 },
15831537 macho.EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER => {
1584 const stub_offset = try it.readUleb128();
1585 const resolver_offset = try it.readUleb128();
1538 const stub_offset = try br.takeLeb128(u64);
1539 const resolver_offset = try br.takeLeb128(u64);
15861540 try exports.append(.{
15871541 .name = prefix,
15881542 .tag = .stub_resolver,
......@@ -1593,7 +1547,7 @@ const MachODumper = struct {
15931547 });
15941548 },
15951549 else => {
1596 const vmoff = try it.readUleb128();
1550 const vmoff = try br.takeLeb128(u64);
15971551 try exports.append(.{
15981552 .name = prefix,
15991553 .tag = .@"export",
......@@ -1612,15 +1566,15 @@ const MachODumper = struct {
16121566 }
16131567 }
16141568
1615 const nedges = try it.readByte();
1569 const nedges = try br.takeByte();
16161570 for (0..nedges) |_| {
1617 const label = try it.readString();
1618 const off = try it.readUleb128();
1571 const label = try br.takeDelimiterConclusive(0);
1572 const off = try br.takeLeb128(u64);
16191573 const prefix_label = try std.fmt.allocPrint(arena, "{s}{s}", .{ prefix, label });
1620 const curr = it.pos;
1621 it.pos = off;
1622 try parseTrieNode(arena, it, prefix_label, exports);
1623 it.pos = curr;
1574 const seek = br.seek;
1575 br.seek = off;
1576 try parseTrieNode(arena, br, prefix_label, exports);
1577 br.seek = seek;
16241578 }
16251579 }
16261580
......@@ -1640,8 +1594,10 @@ const MachODumper = struct {
16401594 var ctx = ObjectContext{ .gpa = gpa, .data = bytes, .header = hdr };
16411595 try ctx.parse();
16421596
1643 var output: std.io.AllocatingWriter = undefined;
1644 const bw = output.init(gpa);
1597 var aw: std.io.AllocatingWriter = undefined;
1598 aw.init(gpa);
1599 defer aw.deinit();
1600 const bw = &aw.buffered_writer;
16451601
16461602 switch (check.kind) {
16471603 .headers => {
......@@ -1717,7 +1673,7 @@ const MachODumper = struct {
17171673 },
17181674
17191675 .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);
17211677 const sep_index = mem.indexOfScalar(u8, name, ',') orelse
17221678 return step.fail("invalid section name: {s}", .{name});
17231679 const segname = name[0..sep_index];
......@@ -1730,7 +1686,7 @@ const MachODumper = struct {
17301686 else => return step.fail("invalid check kind for MachO file format: {s}", .{@tagName(check.kind)}),
17311687 }
17321688
1733 return output.toOwnedSlice();
1689 return aw.toOwnedSlice();
17341690 }
17351691};
17361692
......@@ -1749,153 +1705,133 @@ const ElfDumper = struct {
17491705
17501706 fn parseAndDumpArchive(step: *Step, check: Check, bytes: []const u8) ![]const u8 {
17511707 const gpa = step.owner.allocator;
1752 var stream: std.io.FixedBufferStream = .{ .buffer = bytes };
1753 const reader = stream.reader();
1708 var br: std.io.BufferedReader = undefined;
1709 br.initFixed(bytes);
17541710
1755 const magic = try reader.readBytesNoEof(elf.ARMAG.len);
1756 if (!mem.eql(u8, &magic, elf.ARMAG)) {
1757 return error.InvalidArchiveMagicNumber;
1758 }
1711 if (!mem.eql(u8, try br.takeArray(elf.ARMAG.len), elf.ARMAG)) return error.InvalidArchiveMagicNumber;
17591712
1760 var ctx = ArchiveContext{
1713 var ctx: ArchiveContext = .{
17611714 .gpa = gpa,
17621715 .data = bytes,
1763 .strtab = &[0]u8{},
1716 .symtab = &.{},
1717 .strtab = &.{},
1718 .objects = .empty,
17641719 };
1765 defer {
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;
1720 defer ctx.deinit();
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
17781727 if (!mem.eql(u8, &hdr.ar_fmag, elf.ARFMAG)) return error.InvalidArchiveHeaderMagicNumber;
17791728
1780 const size = try hdr.size();
1781 defer {
1782 _ = stream.seekBy(size) catch {};
1783 }
1729 const data = try br.take(try hdr.size());
17841730
17851731 if (hdr.isSymtab()) {
1786 try ctx.parseSymtab(ctx.data[stream.pos..][0..size], .p32);
1732 try ctx.parseSymtab(data, .p32);
17871733 continue;
17881734 }
17891735 if (hdr.isSymtab64()) {
1790 try ctx.parseSymtab(ctx.data[stream.pos..][0..size], .p64);
1736 try ctx.parseSymtab(data, .p64);
17911737 continue;
17921738 }
17931739 if (hdr.isStrtab()) {
1794 ctx.strtab = ctx.data[stream.pos..][0..size];
1740 ctx.strtab = data;
17951741 continue;
17961742 }
17971743 if (hdr.isSymdef() or hdr.isSymdefSorted()) continue;
17981744
1799 const name = if (hdr.name()) |name|
1800 try gpa.dupe(u8, name)
1801 else if (try hdr.nameOffset()) |off|
1802 try gpa.dupe(u8, ctx.getString(off))
1803 else
1804 unreachable;
1805
1806 try ctx.objects.append(gpa, .{ .name = name, .off = stream.pos, .len = size });
1745 const name = hdr.name() orelse ctx.getString((try hdr.nameOffset()).?);
1746 try ctx.objects.putNoClobber(gpa, hdr_seek, .{
1747 .name = name,
1748 .data = data,
1749 });
18071750 }
18081751
1809 var output: std.io.AllocatingWriter = undefined;
1810 const writer = output.init(gpa);
1752 var aw: std.io.AllocatingWriter = undefined;
1753 aw.init(gpa);
1754 defer aw.deinit();
1755 const bw = &aw.buffered_writer;
18111756
18121757 switch (check.kind) {
1813 .archive_symtab => if (ctx.symtab.items.len > 0) {
1814 try ctx.dumpSymtab(writer);
1758 .archive_symtab => if (ctx.symtab.len > 0) {
1759 try ctx.dumpSymtab(bw);
18151760 } else return step.fail("no archive symbol table found", .{}),
18161761
1817 else => if (ctx.objects.items.len > 0) {
1818 try ctx.dumpObjects(step, check, writer);
1762 else => if (ctx.objects.count() > 0) {
1763 try ctx.dumpObjects(step, check, bw);
18191764 } else return step.fail("empty archive", .{}),
18201765 }
18211766
1822 return output.toOwnedSlice();
1767 return aw.toOwnedSlice();
18231768 }
18241769
18251770 const ArchiveContext = struct {
18261771 gpa: Allocator,
18271772 data: []const u8,
1828 symtab: std.ArrayListUnmanaged(ArSymtabEntry) = .empty,
1773 symtab: []ArSymtabEntry,
18291774 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 {
1833 var stream: std.io.FixedBufferStream = .{ .buffer = raw };
1834 const reader = stream.reader();
1777 fn deinit(ctx: *ArchiveContext) void {
1778 ctx.gpa.free(ctx.symtab);
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);
18351785 const num = switch (ptr_width) {
1836 .p32 => try reader.readInt(u32, .big),
1837 .p64 => try reader.readInt(u64, .big),
1786 .p32 => try br.takeInt(u32, .big),
1787 .p64 => try br.takeInt(u64, .big),
18381788 };
18391789 const ptr_size: usize = switch (ptr_width) {
18401790 .p32 => @sizeOf(u32),
18411791 .p64 => @sizeOf(u64),
18421792 };
1843 const strtab_off = (num + 1) * ptr_size;
1844 const strtab_len = raw.len - strtab_off;
1845 const strtab = raw[strtab_off..][0..strtab_len];
1793 try br.discard(num * ptr_size);
1794 const strtab = try br.peekAll(0);
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
18491799 var stroff: usize = 0;
1850 for (0..num) |_| {
1800 for (ctx.symtab) |*entry| {
18511801 const off = switch (ptr_width) {
1852 .p32 => try reader.readInt(u32, .big),
1853 .p64 => try reader.readInt(u64, .big),
1802 .p32 => try br.takeInt(u32, .big),
1803 .p64 => try br.takeInt(u64, .big),
18541804 };
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);
18561806 stroff += name.len + 1;
1857 ctx.symtab.appendAssumeCapacity(.{ .off = off, .name = name });
1807 entry.* = .{ .off = off, .name = name };
18581808 }
18591809 }
18601810
18611811 fn dumpSymtab(ctx: ArchiveContext, bw: *std.io.BufferedWriter) !void {
1862 var files = std.AutoHashMap(usize, []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);
1812 var symbols: std.AutoArrayHashMap(usize, std.ArrayList([]const u8)) = .init(ctx.gpa);
18711813 defer {
1872 for (symbols.values()) |*value| {
1873 value.deinit();
1874 }
1814 for (symbols.values()) |*value| value.deinit();
18751815 symbols.deinit();
18761816 }
18771817
1878 for (ctx.symtab.items) |entry| {
1818 for (ctx.symtab) |entry| {
18791819 const gop = try symbols.getOrPut(@intCast(entry.off));
1880 if (!gop.found_existing) {
1881 gop.value_ptr.* = std.ArrayList([]const u8).init(ctx.gpa);
1882 }
1820 if (!gop.found_existing) gop.value_ptr.* = .init(ctx.gpa);
18831821 try gop.value_ptr.append(entry.name);
18841822 }
18851823
18861824 try bw.print("{s}\n", .{archive_symtab_label});
18871825 for (symbols.keys(), symbols.values()) |off, values| {
1888 try bw.print("in object {s}\n", .{files.get(off).?});
1889 for (values.items) |value| {
1890 try bw.print("{s}\n", .{value});
1891 }
1826 try bw.print("in object {s}\n", .{ctx.objects.get(off).?.name});
1827 for (values.items) |value| try bw.print("{s}\n", .{value});
18921828 }
18931829 }
18941830
18951831 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| {
18971833 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);
18991835 defer ctx.gpa.free(output);
19001836 try bw.print("{s}\n", .{output});
19011837 }
......@@ -1903,7 +1839,7 @@ const ElfDumper = struct {
19031839
19041840 fn getString(ctx: ArchiveContext, off: u32) []const u8 {
19051841 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);
19071843 return name[0 .. name.len - 1];
19081844 }
19091845
......@@ -1915,24 +1851,24 @@ const ElfDumper = struct {
19151851
19161852 fn parseAndDumpObject(step: *Step, check: Check, bytes: []const u8) ![]const u8 {
19171853 const gpa = step.owner.allocator;
1918 var stream: std.io.FixedBufferStream = .{ .buffer = bytes };
1919 const reader = stream.reader();
1854 var br: std.io.BufferedReader = undefined;
1855 br.initFixed(bytes);
19201856
1921 const hdr = try reader.readStruct(elf.Elf64_Ehdr);
1922 if (!mem.eql(u8, hdr.e_ident[0..4], "\x7fELF")) {
1923 return error.InvalidMagicNumber;
1924 }
1857 const hdr = try br.takeStruct(elf.Elf64_Ehdr);
1858 if (!mem.eql(u8, hdr.e_ident[0..4], "\x7fELF")) return error.InvalidMagicNumber;
19251859
1926 const shdrs = @as([*]align(1) const elf.Elf64_Shdr, @ptrCast(bytes.ptr + hdr.e_shoff))[0..hdr.e_shnum];
1927 const phdrs = @as([*]align(1) const elf.Elf64_Phdr, @ptrCast(bytes.ptr + hdr.e_phoff))[0..hdr.e_phnum];
1860 const shdrs = @as([*]align(1) const elf.Elf64_Shdr, @ptrCast(bytes[hdr.e_shoff..].ptr))[0..hdr.e_shnum];
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 = .{
19301864 .gpa = gpa,
19311865 .data = bytes,
19321866 .hdr = hdr,
19331867 .shdrs = shdrs,
19341868 .phdrs = phdrs,
19351869 .shstrtab = undefined,
1870 .symtab = .{},
1871 .dysymtab = .{},
19361872 };
19371873 ctx.shstrtab = ctx.getSectionContents(ctx.hdr.e_shstrndx);
19381874
......@@ -1963,8 +1899,10 @@ const ElfDumper = struct {
19631899 else => {},
19641900 };
19651901
1966 var output: std.io.AllocatingWriter = undefined;
1967 const bw = output.init(gpa);
1902 var aw: std.io.AllocatingWriter = undefined;
1903 aw.init(gpa);
1904 defer aw.deinit();
1905 const bw = &aw.buffered_writer;
19681906
19691907 switch (check.kind) {
19701908 .headers => {
......@@ -1986,7 +1924,7 @@ const ElfDumper = struct {
19861924 } else return step.fail("no .dynamic section found", .{}),
19871925
19881926 .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);
19901928 const shndx = ctx.getSectionByName(name) orelse return step.fail("no '{s}' section found", .{name});
19911929 try ctx.dumpSection(shndx, bw);
19921930 },
......@@ -1994,18 +1932,18 @@ const ElfDumper = struct {
19941932 else => return step.fail("invalid check kind for ELF file format: {s}", .{@tagName(check.kind)}),
19951933 }
19961934
1997 return output.toOwnedSlice();
1935 return aw.toOwnedSlice();
19981936 }
19991937
20001938 const ObjectContext = struct {
20011939 gpa: Allocator,
20021940 data: []const u8,
2003 hdr: elf.Elf64_Ehdr,
1941 hdr: *align(1) const elf.Elf64_Ehdr,
20041942 shdrs: []align(1) const elf.Elf64_Shdr,
20051943 phdrs: []align(1) const elf.Elf64_Phdr,
20061944 shstrtab: []const u8,
2007 symtab: Symtab = .{},
2008 dysymtab: Symtab = .{},
1945 symtab: Symtab,
1946 dysymtab: Symtab,
20091947
20101948 fn dumpHeader(ctx: ObjectContext, bw: *std.io.BufferedWriter) !void {
20111949 try bw.writeAll("header\n");
......@@ -2020,7 +1958,7 @@ const ElfDumper = struct {
20201958
20211959 for (ctx.phdrs, 0..) |phdr, phndx| {
20221960 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)});
20241962 try bw.print("vaddr {x}\n", .{phdr.p_vaddr});
20251963 try bw.print("paddr {x}\n", .{phdr.p_paddr});
20261964 try bw.print("offset {x}\n", .{phdr.p_offset});
......@@ -2060,7 +1998,7 @@ const ElfDumper = struct {
20601998 for (ctx.shdrs, 0..) |shdr, shndx| {
20611999 try bw.print("shdr {d}\n", .{shndx});
20622000 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)});
20642002 try bw.print("addr {x}\n", .{shdr.sh_addr});
20652003 try bw.print("offset {x}\n", .{shdr.sh_offset});
20662004 try bw.print("size {x}\n", .{shdr.sh_size});
......@@ -2329,8 +2267,8 @@ const ElfDumper = struct {
23292267 };
23302268
23312269 fn getString(strtab: []const u8, off: u32) []const u8 {
2332 assert(off < strtab.len);
2333 return mem.sliceTo(@as([*:0]const u8, @ptrCast(strtab.ptr + off)), 0);
2270 const str = strtab[off..];
2271 return str[0..std.mem.indexOfScalar(u8, str, 0).?];
23342272 }
23352273
23362274 fn fmtShType(sh_type: u32) std.fmt.Formatter(formatShType) {
......@@ -2339,12 +2277,10 @@ const ElfDumper = struct {
23392277
23402278 fn formatShType(
23412279 sh_type: u32,
2342 comptime unused_fmt_string: []const u8,
2343 options: std.fmt.FormatOptions,
23442280 bw: *std.io.BufferedWriter,
2281 comptime unused_fmt_string: []const u8,
23452282 ) !void {
23462283 _ = unused_fmt_string;
2347 _ = options;
23482284 const name = switch (sh_type) {
23492285 elf.SHT_NULL => "NULL",
23502286 elf.SHT_PROGBITS => "PROGBITS",
......@@ -2386,12 +2322,10 @@ const ElfDumper = struct {
23862322
23872323 fn formatPhType(
23882324 ph_type: u32,
2389 comptime unused_fmt_string: []const u8,
2390 options: std.fmt.FormatOptions,
23912325 bw: *std.io.BufferedWriter,
2326 comptime unused_fmt_string: []const u8,
23922327 ) !void {
23932328 _ = unused_fmt_string;
2394 _ = options;
23952329 const p_type = switch (ph_type) {
23962330 elf.PT_NULL => "NULL",
23972331 elf.PT_LOAD => "LOAD",
......@@ -2420,49 +2354,41 @@ const WasmDumper = struct {
24202354
24212355 fn parseAndDump(step: *Step, check: Check, bytes: []const u8) ![]const u8 {
24222356 const gpa = step.owner.allocator;
2423 var fbs: std.io.FixedBufferStream = .{ .buffer = bytes };
2424 const reader = fbs.reader();
2357 var br: std.io.BufferedReader = undefined;
2358 br.initFixed(bytes);
24252359
2426 const buf = try reader.readBytesNoEof(8);
2427 if (!mem.eql(u8, buf[0..4], &std.wasm.magic)) {
2428 return error.InvalidMagicByte;
2429 }
2430 if (!mem.eql(u8, buf[4..], &std.wasm.version)) {
2431 return error.UnsupportedWasmVersion;
2432 }
2360 const buf = try br.takeArray(8);
2361 if (!mem.eql(u8, buf[0..4], &std.wasm.magic)) return error.InvalidMagicByte;
2362 if (!mem.eql(u8, buf[4..8], &std.wasm.version)) return error.UnsupportedWasmVersion;
24332363
2434 var output: std.io.AllocatingWriter = undefined;
2435 const bw = output.init(gpa);
2436 defer output.deinit();
2437 parseAndDumpInner(step, check, bytes, &fbs, bw) catch |err| switch (err) {
2364 var aw: std.io.AllocatingWriter = undefined;
2365 aw.init(gpa);
2366 defer aw.deinit();
2367 const bw = &aw.buffered_writer;
2368
2369 parseAndDumpInner(step, check, &br, bw) catch |err| switch (err) {
24382370 error.EndOfStream => try bw.writeAll("\n<UnexpectedEndOfStream>"),
24392371 else => |e| return e,
24402372 };
2441 return output.toOwnedSlice();
2373 return aw.toOwnedSlice();
24422374 }
24432375
24442376 fn parseAndDumpInner(
24452377 step: *Step,
24462378 check: Check,
2447 bytes: []const u8,
2448 fbs: *std.io.FixedBufferStream,
2379 br: *std.io.BufferedReader,
24492380 bw: *std.io.BufferedWriter,
24502381 ) !void {
2451 const reader = fbs.reader();
2452
2382 var section_br: std.io.BufferedReader = undefined;
24532383 switch (check.kind) {
2454 .headers => {
2455 while (reader.readByte()) |current_byte| {
2456 const section = std.enums.fromInt(std.wasm.Section, current_byte) orelse {
2457 return step.fail("Found invalid section id '{d}'", .{current_byte});
2458 };
2459
2460 const section_length = try std.leb.readUleb128(u32, reader);
2461 try parseAndDumpSection(step, section, bytes[fbs.pos..][0..section_length], bw);
2462 fbs.pos += section_length;
2463 } else |_| {} // reached end of stream
2384 .headers => while (br.takeEnum(std.wasm.Section, .little)) |section| {
2385 section_br.initFixed(try br.take(try br.takeLeb128(u32)));
2386 try parseAndDumpSection(step, section, &section_br, bw);
2387 } else |err| switch (err) {
2388 error.InvalidEnumTag => return step.fail("invalid section id", .{}),
2389 error.EndOfStream => {},
2390 else => |e| return e,
24642391 },
2465
24662392 else => return step.fail("invalid check kind for Wasm file format: {s}", .{@tagName(check.kind)}),
24672393 }
24682394 }
......@@ -2470,16 +2396,13 @@ const WasmDumper = struct {
24702396 fn parseAndDumpSection(
24712397 step: *Step,
24722398 section: std.wasm.Section,
2473 data: []const u8,
2399 br: *std.io.BufferedReader,
24742400 bw: *std.io.BufferedWriter,
24752401 ) !void {
2476 var fbs: std.io.FixedBufferStream = .{ .buffer = data };
2477 const reader = fbs.reader();
2478
24792402 try bw.print(
24802403 \\Section {s}
24812404 \\size {d}
2482 , .{ @tagName(section), data.len });
2405 , .{ @tagName(section), br.storageBuffer().len });
24832406
24842407 switch (section) {
24852408 .type,
......@@ -2493,74 +2416,65 @@ const WasmDumper = struct {
24932416 .code,
24942417 .data,
24952418 => {
2496 const entries = try std.leb.readUleb128(u32, reader);
2419 const entries = try br.takeLeb128(u32);
24972420 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);
24992422 },
25002423 .custom => {
2501 const name_length = try std.leb.readUleb128(u32, reader);
2502 const name = data[fbs.pos..][0..name_length];
2503 fbs.pos += name_length;
2424 const name = try br.take(try br.takeLeb128(u32));
25042425 try bw.print("\nname {s}\n", .{name});
25052426
25062427 if (mem.eql(u8, name, "name")) {
2507 try parseDumpNames(step, reader, bw, data);
2428 try parseDumpNames(step, br, bw);
25082429 } else if (mem.eql(u8, name, "producers")) {
2509 try parseDumpProducers(reader, bw, data);
2430 try parseDumpProducers(br, bw);
25102431 } else if (mem.eql(u8, name, "target_features")) {
2511 try parseDumpFeatures(reader, bw, data);
2432 try parseDumpFeatures(br, bw);
25122433 }
25132434 // TODO: Implement parsing and dumping other custom sections (such as relocations)
25142435 },
25152436 .start => {
2516 const start = try std.leb.readUleb128(u32, reader);
2437 const start = try br.takeLeb128(u32);
25172438 try bw.print("\nstart {d}\n", .{start});
25182439 },
25192440 .data_count => {
2520 const count = try std.leb.readUleb128(u32, reader);
2441 const count = try br.takeLeb128(u32);
25212442 try bw.print("\ncount {d}\n", .{count});
25222443 },
25232444 else => {}, // skip unknown sections
25242445 }
25252446 }
25262447
2527 fn parseSection(step: *Step, section: std.wasm.Section, data: []const u8, entries: u32, bw: *std.io.BufferedWriter) !void {
2528 var fbs: std.io.FixedBufferStream = .{ .buffer = data };
2529 const reader = fbs.reader();
2530
2448 fn parseSection(step: *Step, section: std.wasm.Section, br: *std.io.BufferedReader, entries: u32, bw: *std.io.BufferedWriter) !void {
25312449 switch (section) {
25322450 .type => {
25332451 var i: u32 = 0;
25342452 while (i < entries) : (i += 1) {
2535 const func_type = try reader.readByte();
2453 const func_type = try br.takeByte();
25362454 if (func_type != std.wasm.function_type) {
25372455 return step.fail("expected function type, found byte '{d}'", .{func_type});
25382456 }
2539 const params = try std.leb.readUleb128(u32, reader);
2457 const params = try br.takeLeb128(u32);
25402458 try bw.print("params {d}\n", .{params});
25412459 var index: u32 = 0;
25422460 while (index < params) : (index += 1) {
2543 _ = try parseDumpType(step, std.wasm.Valtype, reader, bw);
2461 _ = try parseDumpType(step, std.wasm.Valtype, br, bw);
25442462 } else index = 0;
2545 const returns = try std.leb.readUleb128(u32, reader);
2463 const returns = try br.takeLeb128(u32);
25462464 try bw.print("returns {d}\n", .{returns});
25472465 while (index < returns) : (index += 1) {
2548 _ = try parseDumpType(step, std.wasm.Valtype, reader, bw);
2466 _ = try parseDumpType(step, std.wasm.Valtype, br, bw);
25492467 }
25502468 }
25512469 },
25522470 .import => {
25532471 var i: u32 = 0;
25542472 while (i < entries) : (i += 1) {
2555 const module_name_len = try std.leb.readUleb128(u32, reader);
2556 const module_name = data[fbs.pos..][0..module_name_len];
2557 fbs.pos += module_name_len;
2558 const name_len = try std.leb.readUleb128(u32, reader);
2559 const name = data[fbs.pos..][0..name_len];
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", .{});
2473 const module_name = try br.take(try br.takeLeb128(u32));
2474 const name = try br.take(try br.takeLeb128(u32));
2475 const kind = br.takeEnum(std.wasm.ExternalKind, .little) catch |err| switch (err) {
2476 error.InvalidEnumTag => return step.fail("invalid import kind", .{}),
2477 else => |e| return e,
25642478 };
25652479
25662480 try bw.print(
......@@ -2570,19 +2484,15 @@ const WasmDumper = struct {
25702484 , .{ module_name, name, @tagName(kind) });
25712485 try bw.writeByte('\n');
25722486 switch (kind) {
2573 .function => {
2574 try bw.print("index {d}\n", .{try std.leb.readUleb128(u32, reader)});
2575 },
2576 .memory => {
2577 try parseDumpLimits(reader, bw);
2578 },
2487 .function => try bw.print("index {d}\n", .{try br.takeLeb128(u32)}),
2488 .memory => try parseDumpLimits(br, bw),
25792489 .global => {
2580 _ = try parseDumpType(step, std.wasm.Valtype, reader, bw);
2581 try bw.print("mutable {}\n", .{0x01 == try std.leb.readUleb128(u32, reader)});
2490 _ = try parseDumpType(step, std.wasm.Valtype, br, bw);
2491 try bw.print("mutable {}\n", .{0x01 == try br.takeLeb128(u32)});
25822492 },
25832493 .table => {
2584 _ = try parseDumpType(step, std.wasm.RefType, reader, bw);
2585 try parseDumpLimits(reader, bw);
2494 _ = try parseDumpType(step, std.wasm.RefType, br, bw);
2495 try parseDumpLimits(br, bw);
25862496 },
25872497 }
25882498 }
......@@ -2590,41 +2500,39 @@ const WasmDumper = struct {
25902500 .function => {
25912501 var i: u32 = 0;
25922502 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)});
25942504 }
25952505 },
25962506 .table => {
25972507 var i: u32 = 0;
25982508 while (i < entries) : (i += 1) {
2599 _ = try parseDumpType(step, std.wasm.RefType, reader, bw);
2600 try parseDumpLimits(reader, bw);
2509 _ = try parseDumpType(step, std.wasm.RefType, br, bw);
2510 try parseDumpLimits(br, bw);
26012511 }
26022512 },
26032513 .memory => {
26042514 var i: u32 = 0;
26052515 while (i < entries) : (i += 1) {
2606 try parseDumpLimits(reader, bw);
2516 try parseDumpLimits(br, bw);
26072517 }
26082518 },
26092519 .global => {
26102520 var i: u32 = 0;
26112521 while (i < entries) : (i += 1) {
2612 _ = try parseDumpType(step, std.wasm.Valtype, reader, bw);
2613 try bw.print("mutable {}\n", .{0x01 == try std.leb.readUleb128(u1, reader)});
2614 try parseDumpInit(step, reader, bw);
2522 _ = try parseDumpType(step, std.wasm.Valtype, br, bw);
2523 try bw.print("mutable {}\n", .{0x01 == try br.takeLeb128(u1)});
2524 try parseDumpInit(step, br, bw);
26152525 }
26162526 },
26172527 .@"export" => {
26182528 var i: u32 = 0;
26192529 while (i < entries) : (i += 1) {
2620 const name_len = try std.leb.readUleb128(u32, reader);
2621 const name = data[fbs.pos..][0..name_len];
2622 fbs.pos += name_len;
2623 const kind_byte = try std.leb.readUleb128(u8, reader);
2624 const kind = std.enums.fromInt(std.wasm.ExternalKind, kind_byte) orelse {
2625 return step.fail("invalid export kind value '{d}'", .{kind_byte});
2530 const name = try br.take(try br.takeLeb128(u32));
2531 const kind = br.takeEnum(std.wasm.ExternalKind, .little) catch |err| switch (err) {
2532 error.InvalidEnumTag => return step.fail("invalid export kind value", .{}),
2533 else => |e| return e,
26262534 };
2627 const index = try std.leb.readUleb128(u32, reader);
2535 const index = try br.takeLeb128(u32);
26282536 try bw.print(
26292537 \\name {s}
26302538 \\kind {s}
......@@ -2636,14 +2544,14 @@ const WasmDumper = struct {
26362544 .element => {
26372545 var i: u32 = 0;
26382546 while (i < entries) : (i += 1) {
2639 try bw.print("table index {d}\n", .{try std.leb.readUleb128(u32, reader)});
2640 try parseDumpInit(step, reader, bw);
2547 try bw.print("table index {d}\n", .{try br.takeLeb128(u32)});
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);
26432551 var function_index: u32 = 0;
26442552 try bw.print("indexes {d}\n", .{function_indexes});
26452553 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)});
26472555 }
26482556 }
26492557 },
......@@ -2651,101 +2559,95 @@ const WasmDumper = struct {
26512559 .data => {
26522560 var i: u32 = 0;
26532561 while (i < entries) : (i += 1) {
2654 const flags = try std.leb.readUleb128(u32, reader);
2655 const index = if (flags & 0x02 != 0)
2656 try std.leb.readUleb128(u32, reader)
2657 else
2658 0;
2562 const flags: packed struct(u32) {
2563 passive: bool,
2564 memidx: bool,
2565 unused: u30,
2566 } = @bitCast(try br.takeLeb128(u32));
2567 const index = if (flags.memidx) try br.takeLeb128(u32) else 0;
26592568 try bw.print("memory index 0x{x}\n", .{index});
2660 if (flags == 0) {
2661 try parseDumpInit(step, reader, bw);
2662 }
2663
2664 const size = try std.leb.readUleb128(u32, reader);
2569 if (!flags.passive) try parseDumpInit(step, br, bw);
2570 const size = try br.takeLeb128(u32);
26652571 try bw.print("size {d}\n", .{size});
2666 try reader.skipBytes(size, .{}); // we do not care about the content of the segments
2572 try br.discard(size); // we do not care about the content of the segments
26672573 }
26682574 },
26692575 else => unreachable,
26702576 }
26712577 }
26722578
2673 fn parseDumpType(step: *Step, comptime E: type, reader: anytype, bw: *std.io.BufferedWriter) !E {
2674 const byte = try reader.readByte();
2675 const tag = std.enums.fromInt(E, byte) orelse {
2676 return step.fail("invalid wasm type value '{d}'", .{byte});
2579 fn parseDumpType(step: *Step, comptime E: type, br: *std.io.BufferedReader, bw: *std.io.BufferedWriter) !E {
2580 const tag = br.takeEnum(E, .little) catch |err| switch (err) {
2581 error.InvalidEnumTag => return step.fail("invalid wasm type value", .{}),
2582 else => |e| return e,
26772583 };
26782584 try bw.print("type {s}\n", .{@tagName(tag)});
26792585 return tag;
26802586 }
26812587
2682 fn parseDumpLimits(reader: anytype, bw: *std.io.BufferedWriter) !void {
2683 const flags = try std.leb.readUleb128(u8, reader);
2684 const min = try std.leb.readUleb128(u32, reader);
2588 fn parseDumpLimits(br: *std.io.BufferedReader, bw: *std.io.BufferedWriter) !void {
2589 const flags = try br.takeLeb128(u8);
2590 const min = try br.takeLeb128(u32);
26852591
26862592 try bw.print("min {x}\n", .{min});
2687 if (flags != 0) {
2688 try bw.print("max {x}\n", .{try std.leb.readUleb128(u32, reader)});
2689 }
2593 if (flags != 0) try bw.print("max {x}\n", .{try br.takeLeb128(u32)});
26902594 }
26912595
2692 fn parseDumpInit(step: *Step, reader: anytype, bw: *std.io.BufferedWriter) !void {
2693 const byte = try reader.readByte();
2694 const opcode = std.enums.fromInt(std.wasm.Opcode, byte) orelse {
2695 return step.fail("invalid wasm opcode '{d}'", .{byte});
2596 fn parseDumpInit(step: *Step, br: *std.io.BufferedReader, bw: *std.io.BufferedWriter) !void {
2597 const opcode = br.takeEnum(std.wasm.Opcode, .little) catch |err| switch (err) {
2598 error.InvalidEnumTag => return step.fail("invalid wasm opcode", .{}),
2599 else => |e| return e,
26962600 };
26972601 switch (opcode) {
2698 .i32_const => try bw.print("i32.const {x}\n", .{try std.leb.readIleb128(i32, reader)}),
2699 .i64_const => try bw.print("i64.const {x}\n", .{try std.leb.readIleb128(i64, reader)}),
2700 .f32_const => try bw.print("f32.const {x}\n", .{@as(f32, @bitCast(try reader.readInt(u32, .little)))}),
2701 .f64_const => try bw.print("f64.const {x}\n", .{@as(f64, @bitCast(try reader.readInt(u64, .little)))}),
2702 .global_get => try bw.print("global.get {x}\n", .{try std.leb.readUleb128(u32, reader)}),
2602 .i32_const => try bw.print("i32.const {x}\n", .{try br.takeLeb128(i32)}),
2603 .i64_const => try bw.print("i64.const {x}\n", .{try br.takeLeb128(i64)}),
2604 .f32_const => try bw.print("f32.const {x}\n", .{@as(f32, @bitCast(try br.takeInt(u32, .little)))}),
2605 .f64_const => try bw.print("f64.const {x}\n", .{@as(f64, @bitCast(try br.takeInt(u64, .little)))}),
2606 .global_get => try bw.print("global.get {x}\n", .{try br.takeLeb128(u32)}),
27032607 else => unreachable,
27042608 }
2705 const end_opcode = try std.leb.readUleb128(u8, reader);
2609 const end_opcode = try br.takeLeb128(u8);
27062610 if (end_opcode != @intFromEnum(std.wasm.Opcode.end)) {
27072611 return step.fail("expected 'end' opcode in init expression", .{});
27082612 }
27092613 }
27102614
27112615 /// https://webassembly.github.io/spec/core/appendix/custom.html
2712 fn parseDumpNames(step: *Step, reader: anytype, bw: *std.io.BufferedWriter, data: []const u8) !void {
2713 while (reader.context.pos < data.len) {
2714 switch (try parseDumpType(step, std.wasm.NameSubsection, reader, bw)) {
2616 fn parseDumpNames(step: *Step, br: *std.io.BufferedReader, bw: *std.io.BufferedWriter) !void {
2617 var subsection_br: std.io.BufferedReader = undefined;
2618 while (br.seek < br.storageBuffer().len) {
2619 switch (try parseDumpType(step, std.wasm.NameSubsection, br, bw)) {
27152620 // The module name subsection ... consists of a single name
27162621 // that is assigned to the module itself.
27172622 .module => {
2718 const size = try std.leb.readUleb128(u32, reader);
2719 const name_len = try std.leb.readUleb128(u32, reader);
2720 if (size != name_len + 1) return error.BadSubsectionSize;
2721 if (reader.context.pos + name_len > data.len) return error.UnexpectedEndOfStream;
2722 try bw.print("name {s}\n", .{data[reader.context.pos..][0..name_len]});
2723 reader.context.pos += name_len;
2623 subsection_br.initFixed(try br.take(try br.takeLeb128(u32)));
2624 const name = try subsection_br.take(try subsection_br.takeLeb128(u32));
2625 try bw.print(
2626 \\name {s}
2627 \\
2628 , .{name});
2629 if (subsection_br.seek != subsection_br.storageBuffer().len) return error.BadSubsectionSize;
27242630 },
27252631
27262632 // The function name subsection ... consists of a name map
27272633 // assigning function names to function indices.
27282634 .function, .global, .data_segment => {
2729 const size = try std.leb.readUleb128(u32, reader);
2730 const entries = try std.leb.readUleb128(u32, reader);
2635 subsection_br.initFixed(try br.take(try br.takeLeb128(u32)));
2636 const entries = try br.takeLeb128(u32);
27312637 try bw.print(
2732 \\size {d}
27332638 \\names {d}
27342639 \\
2735 , .{ size, entries });
2640 , .{entries});
27362641 for (0..entries) |_| {
2737 const index = try std.leb.readUleb128(u32, reader);
2738 const name_len = try std.leb.readUleb128(u32, reader);
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
2642 const index = try br.takeLeb128(u32);
2643 const name = try br.take(try br.takeLeb128(u32));
27432644 try bw.print(
27442645 \\index {d}
27452646 \\name {s}
27462647 \\
27472648 , .{ index, name });
27482649 }
2650 if (subsection_br.seek != subsection_br.storageBuffer().len) return error.BadSubsectionSize;
27492651 },
27502652
27512653 // The local name subsection ... consists of an indirect name
......@@ -2760,52 +2662,49 @@ const WasmDumper = struct {
27602662 }
27612663 }
27622664
2763 fn parseDumpProducers(reader: anytype, bw: *std.io.BufferedWriter, data: []const u8) !void {
2764 const field_count = try std.leb.readUleb128(u32, reader);
2765 try bw.print("fields {d}\n", .{field_count});
2665 fn parseDumpProducers(br: *std.io.BufferedReader, bw: *std.io.BufferedWriter) !void {
2666 const field_count = try br.takeLeb128(u32);
2667 try bw.print(
2668 \\fields {d}
2669 \\
2670 , .{field_count});
27662671 var current_field: u32 = 0;
27672672 while (current_field < field_count) : (current_field += 1) {
2768 const field_name_length = try std.leb.readUleb128(u32, reader);
2769 const field_name = data[reader.context.pos..][0..field_name_length];
2770 reader.context.pos += field_name_length;
2771
2772 const value_count = try std.leb.readUleb128(u32, reader);
2673 const field_name = try br.take(try br.takeLeb128(u32));
2674 const value_count = try br.takeLeb128(u32);
27732675 try bw.print(
27742676 \\field_name {s}
27752677 \\values {d}
2678 \\
27762679 , .{ field_name, value_count });
2777 try bw.writeByte('\n');
27782680 var current_value: u32 = 0;
27792681 while (current_value < value_count) : (current_value += 1) {
2780 const value_length = try std.leb.readUleb128(u32, reader);
2781 const value = data[reader.context.pos..][0..value_length];
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
2682 const value = try br.take(try br.takeLeb128(u32));
2683 const version = try br.take(try br.takeLeb128(u32));
27882684 try bw.print(
27892685 \\value_name {s}
27902686 \\version {s}
2687 \\
27912688 , .{ value, version });
2792 try bw.writeByte('\n');
27932689 }
27942690 }
27952691 }
27962692
2797 fn parseDumpFeatures(reader: anytype, bw: *std.io.BufferedWriter, data: []const u8) !void {
2798 const feature_count = try std.leb.readUleb128(u32, reader);
2799 try bw.print("features {d}\n", .{feature_count});
2693 fn parseDumpFeatures(br: *std.io.BufferedReader, bw: *std.io.BufferedWriter) !void {
2694 const feature_count = try br.takeLeb128(u32);
2695 try bw.print(
2696 \\features {d}
2697 \\
2698 , .{feature_count});
28002699
28012700 var index: u32 = 0;
28022701 while (index < feature_count) : (index += 1) {
2803 const prefix_byte = try std.leb.readUleb128(u8, reader);
2804 const name_length = try std.leb.readUleb128(u32, reader);
2805 const feature_name = data[reader.context.pos..][0..name_length];
2806 reader.context.pos += name_length;
2807
2808 try bw.print("{c} {s}\n", .{ prefix_byte, feature_name });
2702 const prefix_byte = try br.takeLeb128(u8);
2703 const feature_name = try br.take(try br.takeLeb128(u32));
2704 try bw.print(
2705 \\{c} {s}
2706 \\
2707 , .{ prefix_byte, feature_name });
28092708 }
28102709 }
28112710};
lib/std/Build/Step/Compile.zig+6-6
......@@ -409,7 +409,7 @@ pub fn create(owner: *std.Build, options: Options) *Compile {
409409 .linkage = options.linkage,
410410 .kind = options.kind,
411411 .name = name,
412 .step = Step.init(.{
412 .step = .init(.{
413413 .id = base_id,
414414 .name = step_name,
415415 .owner = owner,
......@@ -1542,7 +1542,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 {
15421542 if (compile.kind == .lib and compile.linkage != null and compile.linkage.? == .dynamic) {
15431543 if (compile.version) |version| {
15441544 try zig_args.append("--version");
1545 try zig_args.append(b.fmt("{}", .{version}));
1545 try zig_args.append(b.fmt("{f}", .{version}));
15461546 }
15471547
15481548 if (compile.rootModuleTarget().os.tag.isDarwin()) {
......@@ -1704,7 +1704,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 {
17041704 const opt_zig_lib_dir = if (compile.zig_lib_dir) |dir|
17051705 dir.getPath2(b, step)
17061706 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})
17081708 else
17091709 null;
17101710
......@@ -1830,7 +1830,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
18301830 // Update generated files
18311831 if (maybe_output_dir) |output_dir| {
18321832 if (compile.emit_directory) |lp| {
1833 lp.path = b.fmt("{}", .{output_dir});
1833 lp.path = b.fmt("{f}", .{output_dir});
18341834 }
18351835
18361836 // zig fmt: off
......@@ -1970,13 +1970,13 @@ fn checkCompileErrors(compile: *Compile) !void {
19701970
19711971 const actual_errors = ae: {
19721972 var aw: std.io.AllocatingWriter = undefined;
1973 const bw = aw.init(arena);
1973 aw.init(arena);
19741974 defer aw.deinit();
19751975 try actual_eb.renderToWriter(.{
19761976 .ttyconf = .no_color,
19771977 .include_reference_trace = false,
19781978 .include_source_line = false,
1979 }, bw);
1979 }, &aw.buffered_writer);
19801980 break :ae try aw.toOwnedSlice();
19811981 };
19821982
lib/std/Build/Step/ConfigHeader.zig+89-137
......@@ -87,7 +87,7 @@ pub fn create(owner: *std.Build, options: Options) *ConfigHeader {
8787 owner.fmt("configure {s} header to {s}", .{ @tagName(options.style), include_path });
8888
8989 config_header.* = .{
90 .step = Step.init(.{
90 .step = .init(.{
9191 .id = base_id,
9292 .name = name,
9393 .owner = owner,
......@@ -95,7 +95,7 @@ pub fn create(owner: *std.Build, options: Options) *ConfigHeader {
9595 .first_ret_addr = options.first_ret_addr orelse @returnAddress(),
9696 }),
9797 .style = options.style,
98 .values = std.StringArrayHashMap(Value).init(owner.allocator),
98 .values = .init(owner.allocator),
9999
100100 .max_bytes = options.max_bytes,
101101 .include_path = include_path,
......@@ -195,8 +195,10 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
195195 man.hash.addBytes(config_header.include_path);
196196 man.hash.addOptionalBytes(config_header.include_guard_override);
197197
198 var output = std.ArrayList(u8).init(gpa);
199 defer output.deinit();
198 var aw: std.io.AllocatingWriter = undefined;
199 aw.init(gpa);
200 defer aw.deinit();
201 const bw = &aw.buffered_writer;
200202
201203 const header_text = "This file was generated by ConfigHeader using the Zig Build System.";
202204 const c_generated_line = "/* " ++ header_text ++ " */\n";
......@@ -204,40 +206,41 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
204206
205207 switch (config_header.style) {
206208 .autoconf_undef, .autoconf, .autoconf_at => |file_source| {
207 try output.appendSlice(c_generated_line);
209 try bw.writeAll(c_generated_line);
208210 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| {
210212 return step.fail("unable to read autoconf input file '{s}': {s}", .{
211213 src_path, @errorName(err),
212214 });
213215 };
214216 switch (config_header.style) {
215 .autoconf_undef, .autoconf => try render_autoconf_undef(step, contents, &output, config_header.values, src_path),
216 .autoconf_at => try render_autoconf_at(step, contents, &output, config_header.values, src_path),
217 .autoconf_undef, .autoconf => try render_autoconf_undef(step, contents, bw, config_header.values, src_path),
218 .autoconf_at => try render_autoconf_at(step, contents, &aw, config_header.values, src_path),
217219 else => unreachable,
218220 }
219221 },
220222 .cmake => |file_source| {
221 try output.appendSlice(c_generated_line);
223 try bw.writeAll(c_generated_line);
222224 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| {
224226 return step.fail("unable to read cmake input file '{s}': {s}", .{
225227 src_path, @errorName(err),
226228 });
227229 };
228 try render_cmake(step, contents, &output, config_header.values, src_path);
230 try render_cmake(step, contents, bw, config_header.values, src_path);
229231 },
230232 .blank => {
231 try output.appendSlice(c_generated_line);
232 try render_blank(&output, config_header.values, config_header.include_path, config_header.include_guard_override);
233 try bw.writeAll(c_generated_line);
234 try render_blank(gpa, bw, config_header.values, config_header.include_path, config_header.include_guard_override);
233235 },
234236 .nasm => {
235 try output.appendSlice(asm_generated_line);
236 try render_nasm(&output, config_header.values);
237 try bw.writeAll(asm_generated_line);
238 try render_nasm(bw, config_header.values);
237239 },
238240 }
239241
240 man.hash.addBytes(output.items);
242 const output = aw.getWritten();
243 man.hash.addBytes(output);
241244
242245 if (try step.cacheHit(&man)) {
243246 const digest = man.final();
......@@ -256,13 +259,13 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
256259 const sub_path_dirname = std.fs.path.dirname(sub_path).?;
257260
258261 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}", .{
260263 b.cache_root, sub_path_dirname, @errorName(err),
261264 });
262265 };
263266
264 b.cache_root.handle.writeFile(.{ .sub_path = sub_path, .data = output.items }) catch |err| {
265 return step.fail("unable to write file '{}{s}': {s}", .{
267 b.cache_root.handle.writeFile(.{ .sub_path = sub_path, .data = output }) catch |err| {
268 return step.fail("unable to write file '{f}{s}': {s}", .{
266269 b.cache_root, sub_path, @errorName(err),
267270 });
268271 };
......@@ -274,7 +277,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
274277fn render_autoconf_undef(
275278 step: *Step,
276279 contents: []const u8,
277 output: *std.ArrayList(u8),
280 bw: *std.io.BufferedWriter,
278281 values: std.StringArrayHashMap(Value),
279282 src_path: []const u8,
280283) !void {
......@@ -289,15 +292,15 @@ fn render_autoconf_undef(
289292 var line_it = std.mem.splitScalar(u8, contents, '\n');
290293 while (line_it.next()) |line| : (line_index += 1) {
291294 if (!std.mem.startsWith(u8, line, "#")) {
292 try output.appendSlice(line);
293 try output.appendSlice("\n");
295 try bw.writeAll(line);
296 try bw.writeByte('\n');
294297 continue;
295298 }
296299 var it = std.mem.tokenizeAny(u8, line[1..], " \t\r");
297300 const undef = it.next().?;
298301 if (!std.mem.eql(u8, undef, "undef")) {
299 try output.appendSlice(line);
300 try output.appendSlice("\n");
302 try bw.writeAll(line);
303 try bw.writeByte('\n');
301304 continue;
302305 }
303306 const name = it.next().?;
......@@ -309,7 +312,7 @@ fn render_autoconf_undef(
309312 continue;
310313 };
311314 is_used.set(index);
312 try renderValueC(output, name, values.values()[index]);
315 try renderValueC(bw, name, values.values()[index]);
313316 }
314317
315318 var unused_value_it = is_used.iterator(.{ .kind = .unset });
......@@ -326,12 +329,13 @@ fn render_autoconf_undef(
326329fn render_autoconf_at(
327330 step: *Step,
328331 contents: []const u8,
329 output: *std.ArrayList(u8),
332 aw: *std.io.AllocatingWriter,
330333 values: std.StringArrayHashMap(Value),
331334 src_path: []const u8,
332335) !void {
333336 const build = step.owner;
334337 const allocator = build.allocator;
338 const bw = &aw.buffered_writer;
335339
336340 const used = allocator.alloc(bool, values.count()) catch @panic("OOM");
337341 for (used) |*u| u.* = false;
......@@ -343,11 +347,11 @@ fn render_autoconf_at(
343347 while (line_it.next()) |line| : (line_index += 1) {
344348 const last_line = line_it.index == line_it.buffer.len;
345349
346 const old_len = output.items.len;
347 expand_variables_autoconf_at(output, line, values, used) catch |err| switch (err) {
350 const old_len = aw.getWritten().len;
351 expand_variables_autoconf_at(bw, line, values, used) catch |err| switch (err) {
348352 error.MissingValue => {
349 const name = output.items[old_len..];
350 defer output.shrinkRetainingCapacity(old_len);
353 const name = aw.getWritten()[old_len..];
354 defer aw.shrinkRetainingCapacity(old_len);
351355 try step.addError("{s}:{d}: error: unspecified config header value: '{s}'", .{
352356 src_path, line_index + 1, name,
353357 });
......@@ -362,9 +366,7 @@ fn render_autoconf_at(
362366 continue;
363367 },
364368 };
365 if (!last_line) {
366 try output.append('\n');
367 }
369 if (!last_line) try bw.writeByte('\n');
368370 }
369371
370372 for (values.unmanaged.entries.slice().items(.key), used) |name, u| {
......@@ -374,15 +376,13 @@ fn render_autoconf_at(
374376 }
375377 }
376378
377 if (any_errors) {
378 return error.MakeFailed;
379 }
379 if (any_errors) return error.MakeFailed;
380380}
381381
382382fn render_cmake(
383383 step: *Step,
384384 contents: []const u8,
385 output: *std.ArrayList(u8),
385 bw: *std.io.BufferedWriter,
386386 values: std.StringArrayHashMap(Value),
387387 src_path: []const u8,
388388) !void {
......@@ -417,10 +417,8 @@ fn render_cmake(
417417 defer allocator.free(line);
418418
419419 if (!std.mem.startsWith(u8, line, "#")) {
420 try output.appendSlice(line);
421 if (!last_line) {
422 try output.appendSlice("\n");
423 }
420 try bw.writeAll(line);
421 if (!last_line) try bw.writeByte('\n');
424422 continue;
425423 }
426424 var it = std.mem.tokenizeAny(u8, line[1..], " \t\r");
......@@ -428,10 +426,8 @@ fn render_cmake(
428426 if (!std.mem.eql(u8, cmakedefine, "cmakedefine") and
429427 !std.mem.eql(u8, cmakedefine, "cmakedefine01"))
430428 {
431 try output.appendSlice(line);
432 if (!last_line) {
433 try output.appendSlice("\n");
434 }
429 try bw.writeAll(line);
430 if (!last_line) try bw.writeByte('\n');
435431 continue;
436432 }
437433
......@@ -502,7 +498,7 @@ fn render_cmake(
502498 value = Value{ .ident = it.rest() };
503499 }
504500
505 try renderValueC(output, name, value);
501 try renderValueC(bw, name, value);
506502 }
507503
508504 if (any_errors) {
......@@ -511,13 +507,14 @@ fn render_cmake(
511507}
512508
513509fn render_blank(
514 output: *std.ArrayList(u8),
510 gpa: std.mem.Allocator,
511 bw: *std.io.BufferedWriter,
515512 defines: std.StringArrayHashMap(Value),
516513 include_path: []const u8,
517514 include_guard_override: ?[]const u8,
518515) !void {
519516 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);
521518 for (name) |*byte| {
522519 switch (byte.*) {
523520 'a'...'z' => byte.* = byte.* - 'a' + 'A',
......@@ -527,92 +524,53 @@ fn render_blank(
527524 }
528525 break :blk name;
529526 };
527 defer if (include_guard_override == null) gpa.free(include_guard_name);
530528
531 try output.appendSlice("#ifndef ");
532 try output.appendSlice(include_guard_name);
533 try output.appendSlice("\n#define ");
534 try output.appendSlice(include_guard_name);
535 try output.appendSlice("\n");
529 try bw.print(
530 \\#ifndef {[0]s}
531 \\#define {[0]s}
532 \\
533 , .{include_guard_name});
536534
537535 const values = defines.values();
538 for (defines.keys(), 0..) |name, i| {
539 try renderValueC(output, name, values[i]);
540 }
536 for (defines.keys(), 0..) |name, i| try renderValueC(bw, name, values[i]);
541537
542 try output.appendSlice("#endif /* ");
543 try output.appendSlice(include_guard_name);
544 try output.appendSlice(" */\n");
538 try bw.print(
539 \\#endif /* {s} */
540 \\
541 , .{include_guard_name});
545542}
546543
547fn render_nasm(output: *std.ArrayList(u8), defines: std.StringArrayHashMap(Value)) !void {
548 const values = defines.values();
549 for (defines.keys(), 0..) |name, i| {
550 try renderValueNasm(output, name, values[i]);
551 }
544fn render_nasm(bw: *std.io.BufferedWriter, defines: std.StringArrayHashMap(Value)) !void {
545 for (defines.keys(), defines.values()) |name, value| try renderValueNasm(bw, name, value);
552546}
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 {
555549 switch (value) {
556 .undef => {
557 try output.appendSlice("/* #undef ");
558 try output.appendSlice(name);
559 try output.appendSlice(" */\n");
560 },
561 .defined => {
562 try output.appendSlice("#define ");
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 },
550 .undef => try bw.print("/* #undef {s} */\n", .{name}),
551 .defined => try bw.print("#define {s}\n", .{name}),
552 .boolean => |b| try bw.print("#define {s} {c}\n", .{ name, @as(u8, '0') + @intFromBool(b) }),
553 .int => |i| try bw.print("#define {s} {d}\n", .{ name, i }),
554 .ident => |ident| try bw.print("#define {s} {s}\n", .{ name, ident }),
555 // TODO: use C-specific escaping instead of zig string literals
556 .string => |string| try bw.print("#define {s} \"{f}\"\n", .{ name, std.zig.fmtEscapes(string) }),
581557 }
582558}
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 {
585561 switch (value) {
586 .undef => {
587 try output.appendSlice("; %undef ");
588 try output.appendSlice(name);
589 try output.appendSlice("\n");
590 },
591 .defined => {
592 try output.appendSlice("%define ");
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 },
562 .undef => try bw.print("; %undef {s}\n", .{name}),
563 .defined => try bw.print("%define {s}\n", .{name}),
564 .boolean => |b| try bw.print("%define {s} {c}\n", .{ name, @as(u8, '0') + @intFromBool(b) }),
565 .int => |i| try bw.print("%define {s} {d}\n", .{ name, i }),
566 .ident => |ident| try bw.print("%define {s} {s}\n", .{ name, ident }),
567 // TODO: use nasm-specific escaping instead of zig string literals
568 .string => |string| try bw.print("%define {s} \"{f}\"\n", .{ name, std.zig.fmtEscapes(string) }),
611569 }
612570}
613571
614572fn expand_variables_autoconf_at(
615 output: *std.ArrayList(u8),
573 bw: *std.io.BufferedWriter,
616574 contents: []const u8,
617575 values: std.StringArrayHashMap(Value),
618576 used: []bool,
......@@ -637,23 +595,17 @@ fn expand_variables_autoconf_at(
637595 const key = contents[curr + 1 .. close_pos];
638596 const index = values.getIndex(key) orelse {
639597 // Report the missing key to the caller.
640 try output.appendSlice(key);
598 try bw.writeAll(key);
641599 return error.MissingValue;
642600 };
643601 const value = values.unmanaged.entries.slice().items(.value)[index];
644602 used[index] = true;
645 try output.appendSlice(contents[source_offset..curr]);
603 try bw.writeAll(contents[source_offset..curr]);
646604 switch (value) {
647605 .undef, .defined => {},
648 .boolean => |b| {
649 try output.append(if (b) '1' else '0');
650 },
651 .int => |i| {
652 try output.writer().print("{d}", .{i});
653 },
654 .ident, .string => |s| {
655 try output.appendSlice(s);
656 },
606 .boolean => |b| try bw.writeByte(@as(u8, '0') + @intFromBool(b)),
607 .int => |i| try bw.print("{d}", .{i}),
608 .ident, .string => |s| try bw.writeAll(s),
657609 }
658610
659611 curr = close_pos;
......@@ -661,7 +613,7 @@ fn expand_variables_autoconf_at(
661613 }
662614 }
663615
664 try output.appendSlice(contents[source_offset..]);
616 try bw.writeAll(contents[source_offset..]);
665617}
666618
667619fn expand_variables_cmake(
......@@ -669,7 +621,7 @@ fn expand_variables_cmake(
669621 contents: []const u8,
670622 values: std.StringArrayHashMap(Value),
671623) ![]const u8 {
672 var result = std.ArrayList(u8).init(allocator);
624 var result: std.ArrayList(u8) = .init(allocator);
673625 errdefer result.deinit();
674626
675627 const valid_varname_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789/_.+-";
......@@ -681,7 +633,7 @@ fn expand_variables_cmake(
681633 source: usize,
682634 target: usize,
683635 };
684 var var_stack = std.ArrayList(Position).init(allocator);
636 var var_stack: std.ArrayList(Position) = .init(allocator);
685637 defer var_stack.deinit();
686638 loop: while (curr < contents.len) : (curr += 1) {
687639 switch (contents[curr]) {
......@@ -801,7 +753,7 @@ fn testReplaceVariablesAutoconfAt(
801753 expected: []const u8,
802754 values: std.StringArrayHashMap(Value),
803755) !void {
804 var output = std.ArrayList(u8).init(allocator);
756 var output: std.ArrayList(u8) = .init(allocator);
805757 defer output.deinit();
806758
807759 const used = try allocator.alloc(bool, values.count());
......@@ -828,7 +780,7 @@ fn testReplaceVariablesCMake(
828780
829781test "expand_variables_autoconf_at simple cases" {
830782 const allocator = std.testing.allocator;
831 var values = std.StringArrayHashMap(Value).init(allocator);
783 var values: std.StringArrayHashMap(Value) = .init(allocator);
832784 defer values.deinit();
833785
834786 // empty strings are preserved
......@@ -924,7 +876,7 @@ test "expand_variables_autoconf_at simple cases" {
924876
925877test "expand_variables_autoconf_at edge cases" {
926878 const allocator = std.testing.allocator;
927 var values = std.StringArrayHashMap(Value).init(allocator);
879 var values: std.StringArrayHashMap(Value) = .init(allocator);
928880 defer values.deinit();
929881
930882 // @-vars resolved only when they wrap valid characters, otherwise considered literals
......@@ -940,7 +892,7 @@ test "expand_variables_autoconf_at edge cases" {
940892
941893test "expand_variables_cmake simple cases" {
942894 const allocator = std.testing.allocator;
943 var values = std.StringArrayHashMap(Value).init(allocator);
895 var values: std.StringArrayHashMap(Value) = .init(allocator);
944896 defer values.deinit();
945897
946898 try values.putNoClobber("undef", .undef);
......@@ -1028,7 +980,7 @@ test "expand_variables_cmake simple cases" {
1028980
1029981test "expand_variables_cmake edge cases" {
1030982 const allocator = std.testing.allocator;
1031 var values = std.StringArrayHashMap(Value).init(allocator);
983 var values: std.StringArrayHashMap(Value) = .init(allocator);
1032984 defer values.deinit();
1033985
1034986 // special symbols
......@@ -1089,7 +1041,7 @@ test "expand_variables_cmake edge cases" {
10891041
10901042test "expand_variables_cmake escaped characters" {
10911043 const allocator = std.testing.allocator;
1092 var values = std.StringArrayHashMap(Value).init(allocator);
1044 var values: std.StringArrayHashMap(Value) = .init(allocator);
10931045 defer values.deinit();
10941046
10951047 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 {
1212 const fail = owner.allocator.create(Fail) catch @panic("OOM");
1313
1414 fail.* = .{
15 .step = Step.init(.{
15 .step = .init(.{
1616 .id = base_id,
1717 .name = "fail",
1818 .owner = owner,
lib/std/Build/Step/Fmt.zig+1-1
......@@ -23,7 +23,7 @@ pub fn create(owner: *std.Build, options: Options) *Fmt {
2323 const fmt = owner.allocator.create(Fmt) catch @panic("OOM");
2424 const name = if (options.check) "zig fmt --check" else "zig fmt";
2525 fmt.* = .{
26 .step = Step.init(.{
26 .step = .init(.{
2727 .id = base_id,
2828 .name = name,
2929 .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
6363 .override => |o| o,
6464 };
6565 install_artifact.* = .{
66 .step = Step.init(.{
66 .step = .init(.{
6767 .id = base_id,
6868 .name = owner.fmt("install {s}", .{artifact.name}),
6969 .owner = owner,
......@@ -164,7 +164,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
164164 const full_h_prefix = b.getInstallPath(h_dir, dir.dest_rel_path);
165165
166166 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}", .{
168168 src_dir_path, @errorName(err),
169169 });
170170 };
lib/std/Build/Step/InstallDir.zig+2-2
......@@ -43,7 +43,7 @@ pub const Options = struct {
4343pub fn create(owner: *std.Build, options: Options) *InstallDir {
4444 const install_dir = owner.allocator.create(InstallDir) catch @panic("OOM");
4545 install_dir.* = .{
46 .step = Step.init(.{
46 .step = .init(.{
4747 .id = base_id,
4848 .name = owner.fmt("install {s}/", .{options.source_dir.getDisplayName()}),
4949 .owner = owner,
......@@ -65,7 +65,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
6565 const src_dir_path = install_dir.options.source_dir.getPath3(b, step);
6666 const need_derived_inputs = try step.addDirectoryWatchInput(install_dir.options.source_dir);
6767 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}", .{
6969 src_dir_path, @errorName(err),
7070 });
7171 };
lib/std/Build/Step/InstallFile.zig+1-1
......@@ -21,7 +21,7 @@ pub fn create(
2121 assert(dest_rel_path.len != 0);
2222 const install_file = owner.allocator.create(InstallFile) catch @panic("OOM");
2323 install_file.* = .{
24 .step = Step.init(.{
24 .step = .init(.{
2525 .id = base_id,
2626 .name = owner.fmt("install {s} to {s}", .{ source.getDisplayName(), dest_rel_path }),
2727 .owner = owner,
lib/std/Build/Step/ObjCopy.zig+2-2
......@@ -111,8 +111,8 @@ pub fn create(
111111 options: Options,
112112) *ObjCopy {
113113 const objcopy = owner.allocator.create(ObjCopy) catch @panic("OOM");
114 objcopy.* = ObjCopy{
115 .step = Step.init(.{
114 objcopy.* = .{
115 .step = .init(.{
116116 .id = base_id,
117117 .name = owner.fmt("objcopy {s}", .{input_file.getDisplayName()}),
118118 .owner = owner,
lib/std/Build/Step/Options.zig+19-19
......@@ -19,7 +19,7 @@ encountered_types: std.StringHashMapUnmanaged(void),
1919pub fn create(owner: *std.Build) *Options {
2020 const options = owner.allocator.create(Options) catch @panic("OOM");
2121 options.* = .{
22 .step = Step.init(.{
22 .step = .init(.{
2323 .id = base_id,
2424 .name = "options",
2525 .owner = owner,
......@@ -79,15 +79,15 @@ fn printType(
7979 std.zig.fmtId(some), std.zig.fmtEscapes(value),
8080 });
8181 } else {
82 try out.print(gpa, "\"{}\",", .{std.zig.fmtEscapes(value)});
82 try out.print(gpa, "\"{f}\",", .{std.zig.fmtEscapes(value)});
8383 }
8484 return out.appendSlice(gpa, "\n");
8585 },
8686 [:0]const u8 => {
8787 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) });
8989 } else {
90 try out.print(gpa, "\"{}\",", .{std.zig.fmtEscapes(value)});
90 try out.print(gpa, "\"{f}\",", .{std.zig.fmtEscapes(value)});
9191 }
9292 return out.appendSlice(gpa, "\n");
9393 },
......@@ -97,7 +97,7 @@ fn printType(
9797 }
9898
9999 if (value) |payload| {
100 try out.print(gpa, "\"{}\"", .{std.zig.fmtEscapes(payload)});
100 try out.print(gpa, "\"{f}\"", .{std.zig.fmtEscapes(payload)});
101101 } else {
102102 try out.appendSlice(gpa, "null");
103103 }
......@@ -115,7 +115,7 @@ fn printType(
115115 }
116116
117117 if (value) |payload| {
118 try out.print(gpa, "\"{}\"", .{std.zig.fmtEscapes(payload)});
118 try out.print(gpa, "\"{f}\"", .{std.zig.fmtEscapes(payload)});
119119 } else {
120120 try out.appendSlice(gpa, "null");
121121 }
......@@ -129,7 +129,7 @@ fn printType(
129129 },
130130 std.SemanticVersion => {
131131 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)});
133133 }
134134
135135 try out.appendSlice(gpa, ".{\n");
......@@ -142,11 +142,11 @@ fn printType(
142142
143143 if (value.pre) |some| {
144144 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)});
146146 }
147147 if (value.build) |some| {
148148 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)});
150150 }
151151
152152 if (name != null) {
......@@ -233,7 +233,7 @@ fn printType(
233233 .null,
234234 => {
235235 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 });
237237 } else {
238238 try out.print(gpa, "{any},\n", .{value});
239239 }
......@@ -243,7 +243,7 @@ fn printType(
243243 try printEnum(options, out, T, info, indent);
244244
245245 if (name) |some| {
246 try out.print(gpa, "pub const {}: {} = .{p_};\n", .{
246 try out.print(gpa, "pub const {f}: {f} = .{fp_};\n", .{
247247 std.zig.fmtId(some),
248248 std.zig.fmtId(@typeName(T)),
249249 std.zig.fmtId(@tagName(value)),
......@@ -255,7 +255,7 @@ fn printType(
255255 try printStruct(options, out, T, info, indent);
256256
257257 if (name) |some| {
258 try out.print(gpa, "pub const {}: {} = ", .{
258 try out.print(gpa, "pub const {f}: {f} = ", .{
259259 std.zig.fmtId(some),
260260 std.zig.fmtId(@typeName(T)),
261261 });
......@@ -291,7 +291,7 @@ fn printEnum(
291291 if (gop.found_existing) return;
292292
293293 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
296296 inline for (val.fields) |field| {
297297 try out.appendNTimes(gpa, ' ', indent);
......@@ -464,7 +464,7 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {
464464 error.FileNotFound => {
465465 const sub_dirname = fs.path.dirname(sub_path).?;
466466 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}", .{
468468 b.cache_root, sub_dirname, @errorName(e),
469469 });
470470 };
......@@ -476,13 +476,13 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {
476476 const tmp_sub_path_dirname = fs.path.dirname(tmp_sub_path).?;
477477
478478 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}", .{
480480 b.cache_root, tmp_sub_path_dirname, @errorName(err),
481481 });
482482 };
483483
484484 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}", .{
486486 b.cache_root, tmp_sub_path, @errorName(err),
487487 });
488488 };
......@@ -491,7 +491,7 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {
491491 error.PathAlreadyExists => {
492492 // Other process beat us to it. Clean up the temp file.
493493 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}", .{
495495 b.cache_root, tmp_sub_path, @errorName(e),
496496 });
497497 };
......@@ -499,7 +499,7 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {
499499 return;
500500 },
501501 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}", .{
503503 b.cache_root, tmp_sub_path,
504504 b.cache_root, sub_path,
505505 @errorName(err),
......@@ -507,7 +507,7 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {
507507 },
508508 };
509509 },
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}", .{
511511 b.cache_root, sub_path, @errorName(e),
512512 }),
513513 }
lib/std/Build/Step/RemoveDir.zig+1-1
......@@ -12,7 +12,7 @@ doomed_path: LazyPath,
1212pub fn create(owner: *std.Build, doomed_path: LazyPath) *RemoveDir {
1313 const remove_dir = owner.allocator.create(RemoveDir) catch @panic("OOM");
1414 remove_dir.* = .{
15 .step = Step.init(.{
15 .step = .init(.{
1616 .id = base_id,
1717 .name = owner.fmt("RemoveDir {s}", .{doomed_path.getDisplayName()}),
1818 .owner = owner,
lib/std/Build/Step/Run.zig+23-30
......@@ -169,7 +169,7 @@ pub const Output = struct {
169169pub fn create(owner: *std.Build, name: []const u8) *Run {
170170 const run = owner.allocator.create(Run) catch @panic("OOM");
171171 run.* = .{
172 .step = Step.init(.{
172 .step = .init(.{
173173 .id = base_id,
174174 .name = name,
175175 .owner = owner,
......@@ -832,7 +832,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
832832 else => unreachable,
833833 };
834834 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}", .{
836836 b.cache_root, output_sub_dir_path, @errorName(err),
837837 });
838838 };
......@@ -864,7 +864,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
864864 else => unreachable,
865865 };
866866 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}", .{
868868 b.cache_root, output_sub_dir_path, @errorName(err),
869869 });
870870 };
......@@ -903,21 +903,21 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
903903 b.cache_root.handle.rename(tmp_dir_path, o_sub_path) catch |err| {
904904 if (err == error.PathAlreadyExists) {
905905 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}", .{
907907 b.cache_root,
908908 tmp_dir_path,
909909 @errorName(del_err),
910910 });
911911 };
912912 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}", .{
914914 b.cache_root, tmp_dir_path,
915915 b.cache_root, o_sub_path,
916916 @errorName(retry_err),
917917 });
918918 };
919919 } 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}", .{
921921 b.cache_root, tmp_dir_path,
922922 b.cache_root, o_sub_path,
923923 @errorName(err),
......@@ -964,7 +964,7 @@ pub fn rerunInFuzzMode(
964964 .artifact => |pa| {
965965 const artifact = pa.artifact;
966966 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.?});
968968 break :p artifact.installed_path orelse artifact.generated_bin.?.path.?;
969969 };
970970 try argv_list.append(arena, b.fmt("{s}{s}", .{
......@@ -1013,20 +1013,16 @@ fn populateGeneratedPaths(
10131013
10141014fn formatTerm(
10151015 term: ?std.process.Child.Term,
1016 bw: *std.io.BufferedWriter,
10161017 comptime fmt: []const u8,
1017 options: std.fmt.FormatOptions,
1018 writer: anytype,
10191018) !void {
10201019 _ = fmt;
1021 _ = options;
10221020 if (term) |t| switch (t) {
1023 .Exited => |code| try writer.print("exited with code {}", .{code}),
1024 .Signal => |sig| try writer.print("terminated with signal {}", .{sig}),
1025 .Stopped => |sig| try writer.print("stopped with signal {}", .{sig}),
1026 .Unknown => |code| try writer.print("terminated for unknown reason with code {}", .{code}),
1027 } else {
1028 try writer.writeAll("exited with any code");
1029 }
1021 .Exited => |code| try bw.print("exited with code {}", .{code}),
1022 .Signal => |sig| try bw.print("terminated with signal {}", .{sig}),
1023 .Stopped => |sig| try bw.print("stopped with signal {}", .{sig}),
1024 .Unknown => |code| try bw.print("terminated for unknown reason with code {}", .{code}),
1025 } else try bw.writeAll("exited with any code");
10301026}
10311027fn fmtTerm(term: ?std.process.Child.Term) std.fmt.Formatter(formatTerm) {
10321028 return .{ .data = term };
......@@ -1262,12 +1258,12 @@ fn runCommand(
12621258 const sub_path = b.pathJoin(&output_components);
12631259 const sub_path_dirname = fs.path.dirname(sub_path).?;
12641260 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}", .{
12661262 b.cache_root, sub_path_dirname, @errorName(err),
12671263 });
12681264 };
12691265 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}", .{
12711267 b.cache_root, sub_path, @errorName(err),
12721268 });
12731269 };
......@@ -1346,7 +1342,7 @@ fn runCommand(
13461342 },
13471343 .expect_term => |expected_term| {
13481344 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}", .{
13501346 fmtTerm(result.term),
13511347 fmtTerm(expected_term),
13521348 try Step.allocPrintCmd(arena, cwd, final_argv),
......@@ -1366,7 +1362,7 @@ fn runCommand(
13661362 };
13671363 const expected_term: std.process.Child.Term = .{ .Exited = 0 };
13681364 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}", .{
13701366 prefix,
13711367 fmtTerm(result.term),
13721368 fmtTerm(expected_term),
......@@ -1535,13 +1531,10 @@ fn evalZigTest(
15351531 defer if (sub_prog_node) |n| n.end();
15361532
15371533 const any_write_failed = first_write_failed or poll: while (true) {
1538 while (stdout.readableLength() < @sizeOf(Header)) {
1539 if (!(try poller.poll())) break :poll false;
1540 }
1541 const header = stdout.reader().readStruct(Header) catch unreachable;
1542 while (stdout.readableLength() < header.bytes_len) {
1543 if (!(try poller.poll())) break :poll false;
1544 }
1534 while (stdout.readableLength() < @sizeOf(Header)) if (!try poller.poll()) break :poll false;
1535 var header: Header = undefined;
1536 assert(stdout.read(std.mem.asBytes(&header)) == @sizeOf(Header));
1537 while (stdout.readableLength() < header.bytes_len) if (!try poller.poll()) break :poll false;
15451538 const body = stdout.readableSliceOfLen(header.bytes_len);
15461539
15471540 switch (header.tag) {
......@@ -1797,10 +1790,10 @@ fn evalGeneric(run: *Run, child: *std.process.Child) !StdIoResult {
17971790 stdout_bytes = try poller.fifo(.stdout).toOwnedSlice();
17981791 stderr_bytes = try poller.fifo(.stderr).toOwnedSlice();
17991792 } 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);
18011794 }
18021795 } 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);
18041797 }
18051798
18061799 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 {
3131 const translate_c = owner.allocator.create(TranslateC) catch @panic("OOM");
3232 const source = options.root_source_file.dupe(owner);
3333 translate_c.* = .{
34 .step = Step.init(.{
34 .step = .init(.{
3535 .id = base_id,
3636 .name = "translate-c",
3737 .owner = owner,
lib/std/Build/Step/UpdateSourceFiles.zig+4-4
......@@ -27,7 +27,7 @@ pub const Contents = union(enum) {
2727pub fn create(owner: *std.Build) *UpdateSourceFiles {
2828 const usf = owner.allocator.create(UpdateSourceFiles) catch @panic("OOM");
2929 usf.* = .{
30 .step = Step.init(.{
30 .step = .init(.{
3131 .id = base_id,
3232 .name = "UpdateSourceFiles",
3333 .owner = owner,
......@@ -76,7 +76,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
7676 for (usf.output_source_files.items) |output_source_file| {
7777 if (fs.path.dirname(output_source_file.sub_path)) |dirname| {
7878 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}", .{
8080 b.build_root, dirname, @errorName(err),
8181 });
8282 };
......@@ -84,7 +84,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
8484 switch (output_source_file.contents) {
8585 .bytes => |bytes| {
8686 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}", .{
8888 b.build_root, output_source_file.sub_path, @errorName(err),
8989 });
9090 };
......@@ -101,7 +101,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
101101 output_source_file.sub_path,
102102 .{},
103103 ) 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}", .{
105105 source_path, b.build_root, output_source_file.sub_path, @errorName(err),
106106 });
107107 };
lib/std/Build/Step/WriteFile.zig+8-8
......@@ -67,7 +67,7 @@ pub const Contents = union(enum) {
6767pub fn create(owner: *std.Build) *WriteFile {
6868 const write_file = owner.allocator.create(WriteFile) catch @panic("OOM");
6969 write_file.* = .{
70 .step = Step.init(.{
70 .step = .init(.{
7171 .id = base_id,
7272 .name = "WriteFile",
7373 .owner = owner,
......@@ -217,7 +217,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
217217 const src_dir_path = dir.source.getPath3(b, step);
218218
219219 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}", .{
221221 src_dir_path, @errorName(err),
222222 });
223223 };
......@@ -258,7 +258,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
258258 write_file.generated_directory.path = try b.cache_root.join(arena, &.{ "o", &digest });
259259
260260 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}", .{
262262 b.cache_root, cache_path, @errorName(err),
263263 });
264264 };
......@@ -269,7 +269,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
269269 for (write_file.files.items) |file| {
270270 if (fs.path.dirname(file.sub_path)) |dirname| {
271271 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}", .{
273273 b.cache_root, cache_path, fs.path.sep, dirname, @errorName(err),
274274 });
275275 };
......@@ -277,7 +277,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
277277 switch (file.contents) {
278278 .bytes => |bytes| {
279279 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}", .{
281281 b.cache_root, cache_path, fs.path.sep, file.sub_path, @errorName(err),
282282 });
283283 };
......@@ -291,7 +291,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
291291 file.sub_path,
292292 .{},
293293 ) 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}", .{
295295 source_path,
296296 b.cache_root,
297297 cache_path,
......@@ -315,7 +315,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
315315
316316 if (dest_dirname.len != 0) {
317317 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}", .{
319319 b.cache_root, cache_path, fs.path.sep, dest_dirname, @errorName(err),
320320 });
321321 };
......@@ -338,7 +338,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
338338 dest_path,
339339 .{},
340340 ) 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}", .{
342342 src_entry_path, b.cache_root, cache_path, fs.path.sep, dest_path, @errorName(err),
343343 });
344344 };
lib/std/Build/Watch.zig+2-2
......@@ -211,7 +211,7 @@ const Os = switch (builtin.os.tag) {
211211 .ADD = true,
212212 .ONLYDIR = true,
213213 }, 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) });
215215 };
216216 }
217217 break :rs &dh_gop.value_ptr.reaction_set;
......@@ -265,7 +265,7 @@ const Os = switch (builtin.os.tag) {
265265 .ONLYDIR = true,
266266 }, fan_mask, path.root_dir.handle.fd, path.subPathOrDot()) catch |err| switch (err) {
267267 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) }),
269269 };
270270
271271 w.dir_table.swapRemoveAt(i);
lib/std/SemanticVersion.zig+4-6
......@@ -152,15 +152,13 @@ fn parseNum(text: []const u8) error{ InvalidVersion, Overflow }!usize {
152152
153153pub fn format(
154154 self: Version,
155 bw: *std.io.BufferedWriter,
155156 comptime fmt: []const u8,
156 options: std.fmt.FormatOptions,
157 out_stream: anytype,
158157) !void {
159 _ = options;
160158 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 });
162 if (self.pre) |pre| try std.fmt.format(out_stream, "-{s}", .{pre});
163 if (self.build) |build| try std.fmt.format(out_stream, "+{s}", .{build});
159 try bw.print("{d}.{d}.{d}", .{ self.major, self.minor, self.patch });
160 if (self.pre) |pre| try bw.print("-{s}", .{pre});
161 if (self.build) |build| try bw.print("+{s}", .{build});
164162}
165163
166164const 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 {
423423 try formatVersion(v, gpa, &result);
424424 },
425425 .windows => |v| {
426 try result.print(gpa, "{s}", .{v});
426 try result.print(gpa, "{d}", .{v});
427427 },
428428 }
429429 }
......@@ -437,7 +437,7 @@ pub fn zigTriple(self: Query, gpa: Allocator) Allocator.Error![]u8 {
437437 .windows => |v| {
438438 // This is counting on a custom format() function defined on `WindowsVersion`
439439 // 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});
441441 },
442442 }
443443 }
lib/std/fifo.zig+57-6
......@@ -38,8 +38,6 @@ pub fn LinearFifo(
3838 count: usize,
3939
4040 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
4442 // Type of Self argument for slice operations.
4543 // If buffer is inline (Static) then we need to ensure we haven't
......@@ -236,8 +234,31 @@ pub fn LinearFifo(
236234 return self.read(dest);
237235 }
238236
239 pub fn reader(self: *Self) Reader {
240 return .{ .context = self };
237 pub fn reader(self: *Self) std.io.Reader {
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");
241262 }
242263
243264 /// Returns number of items available in fifo
......@@ -326,8 +347,38 @@ pub fn LinearFifo(
326347 return bytes.len;
327348 }
328349
329 pub fn writer(self: *Self) Writer {
330 return .{ .context = self };
350 pub fn writer(fifo: *Self) std.io.Writer {
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");
331382 }
332383
333384 /// 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 {
451451 return struct {
452452 pub fn format(
453453 bytes: []const u8,
454 bw: *std.io.BufferedWriter,
454455 comptime fmt: []const u8,
455 options: std.fmt.Options,
456 writer: anytype,
457456 ) !void {
458457 _ = fmt;
459 _ = options;
460458 var buf: [4]u8 = undefined;
461459
462460 buf[0] = '\\';
......@@ -464,11 +462,11 @@ fn SliceEscape(comptime case: Case) type {
464462
465463 for (bytes) |c| {
466464 if (std.ascii.isPrint(c)) {
467 try writer.writeByte(c);
465 try bw.writeByte(c);
468466 } else {
469467 buf[2] = charset[c >> 4];
470468 buf[3] = charset[c & 15];
471 try writer.writeAll(&buf);
469 try bw.writeAll(&buf);
472470 }
473471 }
474472 }
......@@ -535,11 +533,10 @@ pub fn Formatter(comptime formatFn: anytype) type {
535533 data: Data,
536534 pub fn format(
537535 self: @This(),
538 comptime fmt: []const u8,
539 options: std.fmt.Options,
540536 writer: *std.io.BufferedWriter,
537 comptime fmt: []const u8,
541538 ) anyerror!void {
542 try formatFn(self.data, fmt, options, writer);
539 try formatFn(self.data, writer, fmt);
543540 }
544541 };
545542}
lib/std/fs/Dir.zig+39-4
......@@ -1979,10 +1979,45 @@ pub fn readFileAlloc(
19791979 /// * `error.FileTooBig` is returned.
19801980 limit: std.io.Reader.Limit,
19811981) (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;
19832007 defer buffer.deinit(gpa);
1984 try readFileIntoArrayList(dir, file_path, gpa, limit, null, &buffer);
1985 return buffer.toOwnedSlice(gpa);
2008 try readFileIntoArrayList(
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);
19862021}
19872022
19882023/// Reads all the bytes from the named file, appending them into the provided
......@@ -2004,7 +2039,7 @@ pub fn readFileIntoArrayList(
20042039 /// otherwise the effective file size is used instead.
20052040 size_hint: ?usize,
20062041 comptime alignment: ?std.mem.Alignment,
2007 list: *std.ArrayListAligned(u8, alignment),
2042 list: *std.ArrayListAlignedUnmanaged(u8, alignment),
20082043) (File.OpenError || File.ReadAllocError)!void {
20092044 var file = try dir.openFile(file_path, .{});
20102045 defer file.close();
lib/std/fs/File.zig+5-5
......@@ -1169,7 +1169,7 @@ pub fn readIntoArrayList(
11691169 gpa: Allocator,
11701170 limit: std.io.Reader.Limit,
11711171 comptime alignment: ?std.mem.Alignment,
1172 list: *std.ArrayListAligned(u8, alignment),
1172 list: *std.ArrayListAlignedUnmanaged(u8, alignment),
11731173) ReadAllocError!void {
11741174 var remaining = limit;
11751175 while (true) {
......@@ -1676,7 +1676,7 @@ fn streamReadVec(context: ?*anyopaque, data: []const []u8) anyerror!std.io.Reade
16761676 return .{ .len = @intCast(n), .end = n == 0 };
16771677}
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 {
16801680 const handle = opaqueToHandle(context);
16811681 var splat_buffer: [256]u8 = undefined;
16821682 if (is_windows) {
......@@ -1716,7 +1716,7 @@ fn writeSplat(context: ?*anyopaque, data: []const []const u8, splat: usize) anye
17161716 return std.posix.writev(handle, iovecs[0..len]);
17171717}
17181718
1719fn writeFile(
1719pub fn writeFile(
17201720 context: ?*anyopaque,
17211721 in_file: std.fs.File,
17221722 in_offset: std.io.Writer.Offset,
......@@ -1727,8 +1727,8 @@ fn writeFile(
17271727 const out_fd = opaqueToHandle(context);
17281728 const in_fd = in_file.handle;
17291729 const len_int = switch (in_limit) {
1730 .zero => return writeSplat(context, headers_and_trailers, 1),
1731 .none => 0,
1730 .nothing => return writeSplat(context, headers_and_trailers, 1),
1731 .unlimited => 0,
17321732 else => in_limit.toInt().?,
17331733 };
17341734 if (native_os == .linux) sf: {
lib/std/http/Server.zig+64-20
......@@ -593,8 +593,46 @@ pub const Request = struct {
593593 HttpHeadersOversize,
594594 };
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
596634 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));
598636 const s = request.server;
599637
600638 const remaining_content_length = &request.reader_state.remaining_content_length;
......@@ -622,7 +660,7 @@ pub const Request = struct {
622660 }
623661
624662 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));
626664 const s = request.server;
627665
628666 const cp = &request.reader_state.chunk_parser;
......@@ -724,7 +762,7 @@ pub const Request = struct {
724762 /// request's expect field to `null`.
725763 ///
726764 /// 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 {
728766 const s = request.server;
729767 assert(s.state == .received_head);
730768 s.state = .receiving_body;
......@@ -747,8 +785,11 @@ pub const Request = struct {
747785 .chunked => {
748786 request.reader_state = .{ .chunk_parser = http.ChunkParser.init };
749787 return .{
750 .readFn = read_chunked,
751788 .context = request,
789 .vtable = &.{
790 .read = &chunkedReader_read,
791 .readv = &chunkedReader_readv,
792 },
752793 };
753794 },
754795 .none => {
......@@ -756,8 +797,11 @@ pub const Request = struct {
756797 .remaining_content_length = request.head.content_length orelse 0,
757798 };
758799 return .{
759 .readFn = read_cl,
760800 .context = request,
801 .vtable = &.{
802 .read = &contentLengthReader_read,
803 .readv = &contentLengthReader_readv,
804 },
761805 };
762806 },
763807 }
......@@ -779,7 +823,7 @@ pub const Request = struct {
779823 if (keep_alive and request.head.keep_alive) switch (s.state) {
780824 .received_head => {
781825 const r = request.reader() catch return false;
782 _ = r.discard() catch return false;
826 _ = r.discardUntilEnd() catch return false;
783827 assert(s.state == .ready);
784828 return true;
785829 },
......@@ -868,30 +912,30 @@ pub const Response = struct {
868912 }
869913 }
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 {
872916 _ = splat;
873917 return cl_write(context, data[0]); // TODO: try to send all the data
874918 }
875919
876920 fn cl_writeFile(
877 context: *anyopaque,
921 context: ?*anyopaque,
878922 file: std.fs.File,
879 offset: u64,
880 len: std.io.Writer.FileLen,
923 offset: std.io.Writer.Offset,
924 limit: std.io.Writer.Limit,
881925 headers_and_trailers: []const []const u8,
882926 headers_len: usize,
883927 ) anyerror!usize {
884928 _ = context;
885929 _ = file;
886930 _ = offset;
887 _ = len;
931 _ = limit;
888932 _ = headers_and_trailers;
889933 _ = headers_len;
890934 return error.Unimplemented;
891935 }
892936
893 fn cl_write(context: *anyopaque, bytes: []const u8) anyerror!usize {
894 const r: *Response = @constCast(@alignCast(@ptrCast(context)));
937 fn cl_write(context: ?*anyopaque, bytes: []const u8) anyerror!usize {
938 const r: *Response = @alignCast(@ptrCast(context));
895939
896940 var trash: u64 = std.math.maxInt(u64);
897941 const len = switch (r.transfer_encoding) {
......@@ -935,30 +979,30 @@ pub const Response = struct {
935979 return bytes.len;
936980 }
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 {
939983 _ = splat;
940984 return chunked_write(context, data[0]); // TODO: try to send all the data
941985 }
942986
943987 fn chunked_writeFile(
944 context: *anyopaque,
988 context: ?*anyopaque,
945989 file: std.fs.File,
946 offset: u64,
947 len: std.io.Writer.FileLen,
990 offset: std.io.Writer.Offset,
991 limit: std.io.Writer.Limit,
948992 headers_and_trailers: []const []const u8,
949993 headers_len: usize,
950994 ) anyerror!usize {
951995 _ = context;
952996 _ = file;
953997 _ = offset;
954 _ = len;
998 _ = limit;
955999 _ = headers_and_trailers;
9561000 _ = headers_len;
9571001 return error.Unimplemented; // TODO lower to a call to writeFile on the output
9581002 }
9591003
960 fn chunked_write(context: *anyopaque, bytes: []const u8) anyerror!usize {
961 const r: *Response = @constCast(@alignCast(@ptrCast(context)));
1004 fn chunked_write(context: ?*anyopaque, bytes: []const u8) anyerror!usize {
1005 const r: *Response = @alignCast(@ptrCast(context));
9621006 assert(r.transfer_encoding == .chunked);
9631007
9641008 if (r.elide_body)
lib/std/http/WebSocket.zig+3-2
......@@ -57,8 +57,8 @@ pub fn init(
5757
5858 ws.* = .{
5959 .key = key,
60 .recv_fifo = std.fifo.LinearFifo(u8, .Slice).init(recv_buffer),
61 .reader = try request.reader(),
60 .recv_fifo = .init(recv_buffer),
61 .reader = undefined,
6262 .response = request.respondStreaming(.{
6363 .send_buffer = send_buffer,
6464 .respond_options = .{
......@@ -74,6 +74,7 @@ pub fn init(
7474 .request = request,
7575 .outstanding_len = 0,
7676 };
77 ws.reader.init(try request.reader(), &.{});
7778 return true;
7879}
7980
lib/std/io/AllocatingWriter.zig+14-10
......@@ -28,12 +28,12 @@ const vtable: std.io.Writer.VTable = .{
2828
2929/// Sets the `AllocatingWriter` to an empty state.
3030pub fn init(aw: *AllocatingWriter, allocator: std.mem.Allocator) void {
31 initOwnedSlice(aw, allocator, &.{});
31 aw.initOwnedSlice(allocator, &.{});
3232}
3333
3434pub fn initCapacity(aw: *AllocatingWriter, allocator: std.mem.Allocator, capacity: usize) error{OutOfMemory}!void {
3535 const initial_buffer = try allocator.alloc(u8, capacity);
36 initOwnedSlice(aw, allocator, initial_buffer);
36 aw.initOwnedSlice(allocator, initial_buffer);
3737}
3838
3939pub fn initOwnedSlice(aw: *AllocatingWriter, allocator: std.mem.Allocator, slice: []u8) void {
......@@ -119,11 +119,15 @@ pub fn getWritten(aw: *AllocatingWriter) []u8 {
119119 return written;
120120}
121121
122pub fn clearRetainingCapacity(aw: *AllocatingWriter) void {
122pub fn shrinkRetainingCapacity(aw: *AllocatingWriter, new_len: usize) void {
123123 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];
125125 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);
127131}
128132
129133fn writeSplat(context: ?*anyopaque, data: []const []const u8, splat: usize) anyerror!usize {
......@@ -161,7 +165,7 @@ fn writeFile(
161165 context: ?*anyopaque,
162166 file: std.fs.File,
163167 offset: std.io.Writer.Offset,
164 len: std.io.Writer.FileLen,
168 limit: std.io.Writer.Limit,
165169 headers_and_trailers_full: []const []const u8,
166170 headers_len_full: usize,
167171) anyerror!usize {
......@@ -177,7 +181,7 @@ fn writeFile(
177181 } else .{ headers_and_trailers_full, headers_len_full };
178182 const trailers = headers_and_trailers[headers_len..];
179183 const pos = offset.toInt() orelse @panic("TODO treat file as stream");
180 if (len == .entire_file) {
184 const limit_int = limit.toInt() orelse {
181185 var new_capacity: usize = list.capacity + std.atomic.cache_line;
182186 for (headers_and_trailers) |bytes| new_capacity += bytes.len;
183187 try list.ensureTotalCapacity(gpa, new_capacity);
......@@ -193,12 +197,12 @@ fn writeFile(
193197 }
194198 list.items.len += n;
195199 return list.items.len - start_len;
196 }
197 var new_capacity: usize = list.capacity + len.int();
200 };
201 var new_capacity: usize = list.capacity + limit_int;
198202 for (headers_and_trailers) |bytes| new_capacity += bytes.len;
199203 try list.ensureTotalCapacity(gpa, new_capacity);
200204 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];
202206 const n = try file.pread(dest, pos);
203207 list.items.len += n;
204208 if (n < dest.len) {
lib/std/io/BufferedReader.zig+8-9
......@@ -253,18 +253,17 @@ pub fn discardUpTo(br: *BufferedReader, n: usize) anyerror!usize {
253253 const proposed_seek = br.seek + remaining;
254254 if (proposed_seek <= storage.end) {
255255 br.seek = proposed_seek;
256 return;
256 return n;
257257 }
258258 remaining -= (storage.end - br.seek);
259259 storage.end = 0;
260260 br.seek = 0;
261 const result = try br.unbuffered_reader.read(&storage, .none);
262 result.write_err catch unreachable;
263 try result.read_err;
261 const result = try br.unbuffered_reader.read(storage, .unlimited);
264262 assert(result.len == storage.end);
265263 if (remaining <= storage.end) continue;
266264 if (result.end) return n - remaining;
267265 }
266 return n;
268267}
269268
270269/// Reads the stream until the end, ignoring all the data.
......@@ -302,7 +301,7 @@ pub fn read(br: *BufferedReader, buffer: []u8) anyerror!void {
302301 br.seek = 0;
303302 var i: usize = in_buffer.len;
304303 while (true) {
305 const status = try br.unbuffered_reader.read(storage, .none);
304 const status = try br.unbuffered_reader.read(storage, .unlimited);
306305 const next_i = i + storage.end;
307306 if (next_i >= buffer.len) {
308307 const remaining = buffer[i..];
......@@ -389,7 +388,7 @@ pub fn peekDelimiterInclusive(br: *BufferedReader, delimiter: u8) anyerror![]u8
389388/// * `peekDelimiterConclusive`
390389pub fn takeDelimiterConclusive(br: *BufferedReader, delimiter: u8) anyerror![]u8 {
391390 const result = try peekDelimiterConclusive(br, delimiter);
392 toss(result.len);
391 br.toss(result.len);
393392 return result;
394393}
395394
......@@ -407,7 +406,7 @@ pub fn peekDelimiterConclusive(br: *BufferedReader, delimiter: u8) anyerror![]u8
407406 storage.end = i;
408407 br.seek = 0;
409408 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);
411410 if (std.mem.indexOfScalarPos(u8, storage.buffer[0..storage.end], i, delimiter)) |end| {
412411 return storage.buffer[0 .. end + 1];
413412 }
......@@ -505,7 +504,7 @@ pub fn fill(br: *BufferedReader, n: usize) anyerror!void {
505504 storage.end = remainder.len;
506505 br.seek = 0;
507506 while (true) {
508 const status = try br.unbuffered_reader.read(storage, .none);
507 const status = try br.unbuffered_reader.read(storage, .unlimited);
509508 if (n <= storage.end) return;
510509 if (status.end) return error.EndOfStream;
511510 }
......@@ -589,7 +588,7 @@ fn takeMultipleOf7Leb128(br: *BufferedReader, comptime Result: type) anyerror!Re
589588 const buffer: []const packed struct(u8) { bits: u7, more: bool } = @ptrCast(try br.peekAll(1));
590589 for (buffer, 1..) |byte, len| {
591590 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;
593592 remaining_bits -= 7;
594593 } else if (fits) fits = switch (result_info.signedness) {
595594 .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 {
503503 offset: Writer.Offset = .none,
504504 /// If the size of the source file is known, it is likely that passing the
505505 /// size here will save one syscall.
506 limit: Writer.Limit = .none,
506 limit: Writer.Limit = .unlimited,
507507 /// Headers and trailers must be passed together so that in case `len` is
508508 /// zero, they can be forwarded directly to `Writer.VTable.writev`.
509509 ///
......@@ -518,55 +518,58 @@ pub const WriteFileOptions = struct {
518518pub fn writeFileAll(bw: *BufferedWriter, file: std.fs.File, options: WriteFileOptions) anyerror!void {
519519 const headers_and_trailers = options.headers_and_trailers;
520520 const headers = headers_and_trailers[0..options.headers_len];
521 if (options.limit == .zero) return writevAll(bw, headers_and_trailers);
522 if (options.limit == .none) {
523 // When reading the whole file, we cannot include the trailers in the
524 // call that reads from the file handle, because we have no way to
525 // determine whether a partial write is past the end of the file or
526 // not.
527 var i: usize = 0;
528 var offset = options.offset;
529 while (true) {
530 var n = try writeFile(bw, file, offset, .entire_file, headers[i..], headers.len - i);
531 while (i < headers.len and n >= headers[i].len) {
532 n -= headers[i].len;
533 i += 1;
534 }
535 if (i < headers.len) {
536 headers[i] = headers[i][n..];
537 continue;
538 }
539 if (n == 0) break;
540 offset += n;
541 }
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;
521 switch (options.limit) {
522 .nothing => return writevAll(bw, headers_and_trailers),
523 .unlimited => {
524 // When reading the whole file, we cannot include the trailers in the
525 // call that reads from the file handle, because we have no way to
526 // determine whether a partial write is past the end of the file or
527 // not.
528 var i: usize = 0;
529 var offset = options.offset;
530 while (true) {
531 var n = try writeFile(bw, file, offset, .unlimited, headers[i..], headers.len - i);
532 while (i < headers.len and n >= headers[i].len) {
533 n -= headers[i].len;
534 i += 1;
535 }
536 if (i < headers.len) {
537 headers[i] = headers[i][n..];
538 continue;
539 }
540 if (n == 0) break;
541 offset = offset.advance(n);
555542 }
556 if (n >= len) {
557 n -= len;
558 if (i >= headers_and_trailers.len) return;
559 while (n >= headers_and_trailers[i].len) {
560 n -= headers_and_trailers[i].len;
543 },
544 else => {
545 var len = options.limit.toInt().?;
546 var i: usize = 0;
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;
561552 i += 1;
553 }
554 if (i < headers.len) {
555 headers[i] = headers[i][n..];
556 continue;
557 }
558 if (n >= len) {
559 n -= len;
562560 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..]);
563568 }
564 headers_and_trailers[i] = headers_and_trailers[i][n..];
565 return writevAll(bw, headers_and_trailers[i..]);
569 offset = offset.advance(n);
570 len -= n;
566571 }
567 offset += n;
568 len -= n;
569 }
572 },
570573 }
571574}
572575
......@@ -717,9 +720,9 @@ pub fn printValue(
717720 }
718721 }
719722
720 try bw.writeByteCount('(');
723 try bw.writeByte('(');
721724 try printValue(bw, actual_fmt, options, @intFromEnum(value), max_depth);
722 try bw.writeByteCount(')');
725 try bw.writeByte(')');
723726 },
724727 .@"union" => |info| {
725728 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) {
4848};
4949
5050pub const Limit = enum(usize) {
51 zero = 0,
52 none = std.math.maxInt(usize),
51 nothing = 0,
52 unlimited = std.math.maxInt(usize),
5353 _,
5454
55 /// `std.math.maxInt(usize)` is interpreted to mean "no limit".
56 pub fn init(n: usize) Limit {
55 /// `std.math.maxInt(usize)` is interpreted to mean `.unlimited`.
56 pub fn limited(n: usize) Limit {
5757 return @enumFromInt(n);
5858 }
5959
......@@ -66,7 +66,10 @@ pub const Limit = enum(usize) {
6666 }
6767
6868 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 };
7073 }
7174
7275 /// Reduces a slice to account for the limit, leaving room for one extra
......@@ -84,7 +87,7 @@ pub const Limit = enum(usize) {
8487 /// Return a new limit reduced by `amount` or return `null` indicating
8588 /// limit would be exceeded.
8689 pub fn subtract(l: Limit, amount: usize) ?Limit {
87 if (l == .none) return .{ .next = .none };
90 if (l == .unlimited) return .unlimited;
8891 if (amount > @intFromEnum(l)) return null;
8992 return @enumFromInt(@intFromEnum(l) - amount);
9093 }
......@@ -103,7 +106,7 @@ pub fn readAll(r: Reader, w: *std.io.BufferedWriter) anyerror!usize {
103106 const readFn = r.vtable.read;
104107 var offset: usize = 0;
105108 while (true) {
106 const status = try readFn(r.context, w, .none);
109 const status = try readFn(r.context, w, .unlimited);
107110 offset += status.len;
108111 if (status.end) return offset;
109112 }
......@@ -119,21 +122,21 @@ pub fn readAlloc(r: Reader, gpa: std.mem.Allocator, max_size: usize) anyerror![]
119122 const readFn = r.vtable.read;
120123 var aw: std.io.AllocatingWriter = undefined;
121124 errdefer aw.deinit();
122 const bw = aw.init(gpa);
125 aw.init(gpa);
123126 var remaining = max_size;
124127 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));
126129 if (status.end) break;
127130 remaining -= status.len;
128131 }
129 return aw.toOwnedSlice(gpa);
132 return aw.toOwnedSlice();
130133}
131134
132135/// Reads the stream until the end, ignoring all the data.
133136/// Returns the number of bytes discarded.
134137pub fn discardUntilEnd(r: Reader) anyerror!usize {
135 var bw = std.io.null_writer.unbuffered();
136 return readAll(r, &bw);
138 var bw = std.io.Writer.null.unbuffered();
139 return r.readAll(&bw);
137140}
138141
139142test "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) {
6060 pub fn toInt(o: Offset) ?u64 {
6161 return if (o == .none) null else @intFromEnum(o);
6262 }
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 }
6370};
6471
6572pub fn writev(w: Writer, data: []const []const u8) anyerror!usize {
......@@ -106,7 +113,7 @@ pub fn buffered(w: Writer, buffer: []u8) std.io.BufferedWriter {
106113}
107114
108115pub fn unbuffered(w: Writer) std.io.BufferedWriter {
109 return buffered(w, &.{});
116 return w.buffered(&.{});
110117}
111118
112119/// A `Writer` that discards all data.
lib/std/net.zig+4-4
......@@ -1853,7 +1853,7 @@ pub const Stream = struct {
18531853 },
18541854 else => &.{
18551855 .writeSplat = posix_writeSplat,
1856 .writeFile = std.fs.File.writer_writeFile,
1856 .writeFile = std.fs.File.writeFile,
18571857 },
18581858 },
18591859 };
......@@ -1960,7 +1960,7 @@ pub const Stream = struct {
19601960 return n;
19611961 }
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 {
19641964 const sock_fd = opaqueToHandle(context);
19651965 comptime assert(native_os != .windows);
19661966 var splat_buffer: [256]u8 = undefined;
......@@ -2029,7 +2029,7 @@ pub const Stream = struct {
20292029
20302030 const max_buffers_len = 8;
20312031
2032 fn handleToOpaque(handle: Handle) *anyopaque {
2032 fn handleToOpaque(handle: Handle) ?*anyopaque {
20332033 return switch (@typeInfo(Handle)) {
20342034 .pointer => @ptrCast(handle),
20352035 .int => @ptrFromInt(@as(u32, @bitCast(handle))),
......@@ -2037,7 +2037,7 @@ pub const Stream = struct {
20372037 };
20382038 }
20392039
2040 fn opaqueToHandle(userdata: *anyopaque) Handle {
2040 fn opaqueToHandle(userdata: ?*anyopaque) Handle {
20412041 return switch (@typeInfo(Handle)) {
20422042 .pointer => @ptrCast(userdata),
20432043 .int => @intCast(@intFromPtr(userdata)),
lib/std/process/Child.zig+7-3
......@@ -1004,13 +1004,17 @@ fn forkChildErrReport(fd: i32, err: ChildProcess.SpawnError) noreturn {
10041004
10051005fn writeIntFd(fd: i32, value: ErrInt) !void {
10061006 const file: File = .{ .handle = fd };
1007 var bw = file.writer().unbuffered();
1008 bw.writeInt(u64, @intCast(value), .little) catch return error.SystemResources;
1007 var buffer: [8]u8 = undefined;
1008 std.mem.writeInt(u64, &buffer, @intCast(value), .little);
1009 file.writeAll(&buffer) catch return error.SystemResorces;
10091010}
10101011
10111012fn readIntFd(fd: i32) !ErrInt {
10121013 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));
10141018}
10151019
10161020const 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 {
4444 try header.setMtime(mtime);
4545 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) });
4848 try self.writePadding(stat.size);
4949}
5050
lib/std/zig.zig+6-9
......@@ -414,9 +414,8 @@ test fmtId {
414414/// Print the string as a Zig identifier, escaping it with `@""` syntax if needed.
415415fn formatId(
416416 bytes: []const u8,
417 bw: *std.io.BufferedWriter,
417418 comptime fmt: []const u8,
418 options: std.fmt.FormatOptions,
419 writer: *std.io.BufferedWriter,
420419) !void {
421420 const allow_primitive, const allow_underscore = comptime parse_fmt: {
422421 var allow_primitive = false;
......@@ -442,11 +441,11 @@ fn formatId(
442441 (allow_primitive or !std.zig.isPrimitive(bytes)) and
443442 (allow_underscore or !isUnderscore(bytes)))
444443 {
445 return writer.writeAll(bytes);
444 return bw.writeAll(bytes);
446445 }
447 try writer.writeAll("@\"");
448 try stringEscape(bytes, "", options, writer);
449 try writer.writeByte('"');
446 try bw.writeAll("@\"");
447 try stringEscape(bytes, bw, "");
448 try bw.writeByte('"');
450449}
451450
452451/// Return a Formatter for Zig Escapes of a double quoted string.
......@@ -473,11 +472,9 @@ test fmtEscapes {
473472/// Format `{'}` treats contents as a single-quoted string.
474473pub fn stringEscape(
475474 bytes: []const u8,
476 comptime f: []const u8,
477 options: std.fmt.FormatOptions,
478475 bw: *std.io.BufferedWriter,
476 comptime f: []const u8,
479477) !void {
480 _ = options;
481478 for (bytes) |byte| switch (byte) {
482479 '\n' => try bw.writeAll("\\n"),
483480 '\r' => try bw.writeAll("\\r"),
lib/std/zig/ErrorBundle.zig+2-2
......@@ -190,7 +190,7 @@ fn renderErrorMessageToWriter(
190190) anyerror!void {
191191 const ttyconf = options.ttyconf;
192192 const err_msg = eb.getErrorMessage(err_msg_index);
193 const prefix_start = bw.bytes_written;
193 const prefix_start = bw.count;
194194 if (err_msg.src_loc != .none) {
195195 const src = eb.extraData(SourceLocation, @intFromEnum(err_msg.src_loc));
196196 try bw.splatByteAll(' ', indent);
......@@ -205,7 +205,7 @@ fn renderErrorMessageToWriter(
205205 try bw.writeAll(": ");
206206 // This is the length of the part before the error message:
207207 // e.g. "file.zig:4:5: error: "
208 const prefix_len = bw.bytes_written - prefix_start;
208 const prefix_len = bw.count - prefix_start;
209209 try ttyconf.setColor(bw, .reset);
210210 try ttyconf.setColor(bw, .bold);
211211 if (err_msg.count == 1) {
test/src/Cases.zig+1-1
......@@ -378,7 +378,7 @@ fn addFromDirInner(
378378 current_file.* = filename;
379379
380380 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
383383 // Parse the manifest
384384 var manifest = try TestManifest.parse(ctx.arena, src);
test/standalone/run_output_caching/build.zig+2-2
......@@ -75,7 +75,7 @@ const CheckOutputCaching = struct {
7575 pub fn init(owner: *std.Build, expect_caching: bool, output_paths: []const std.Build.LazyPath) *CheckOutputCaching {
7676 const check = owner.allocator.create(CheckOutputCaching) catch @panic("OOM");
7777 check.* = .{
78 .step = std.Build.Step.init(.{
78 .step = .init(.{
7979 .id = .custom,
8080 .name = "check output caching",
8181 .owner = owner,
......@@ -112,7 +112,7 @@ const CheckPathEquality = struct {
112112 pub fn init(owner: *std.Build, expected_equality: bool, output_paths: []const std.Build.LazyPath) *CheckPathEquality {
113113 const check = owner.allocator.create(CheckPathEquality) catch @panic("OOM");
114114 check.* = .{
115 .step = std.Build.Step.init(.{
115 .step = .init(.{
116116 .id = .custom,
117117 .name = "check output path equality",
118118 .owner = owner,
test/tests.zig+1-1
......@@ -2711,7 +2711,7 @@ pub fn addIncrementalTests(b: *std.Build, test_step: *Step) !void {
27112711
27122712 run.addArg(b.graph.zig_exe);
27132713 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
27162716 run.addCheck(.{ .expect_term = .{ .Exited = 0 } });
27172717