authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-04-21 16:32:37-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-07-01 16:35:27-07:00
logd62f22cc4d2f17db0877cd9316bf8be9470d04a5
treebc97e5ae7485bf5f50350a1068019aae4db9b0db
parent6a0f2227e8b40e3456d3c85c72f68f483b239af3

link: port to `std.io.BufferedReader` API changes


5 files changed, 103 insertions(+), 52 deletions(-)

lib/std/io/BufferedReader.zig+52-22
......@@ -484,11 +484,13 @@ fn peekDelimiterInclusiveUnlessEnd(br: *BufferedReader, delimiter: u8) Delimiter
484484/// found. Does not write the delimiter itself.
485485///
486486/// Returns number of bytes streamed.
487pub fn streamReadDelimiter(br: *BufferedReader, bw: *BufferedWriter, delimiter: u8) Reader.Error!usize {
488 _ = br;
489 _ = bw;
490 _ = delimiter;
491 @panic("TODO");
487pub fn streamToDelimiter(br: *BufferedReader, bw: *BufferedWriter, delimiter: u8) Reader.RwError!usize {
488 const amount, const to = try br.streamToAny(bw, delimiter, .unlimited);
489 return switch (to) {
490 .delimiter => amount,
491 .limit => unreachable,
492 .end => error.EndOfStream,
493 };
492494}
493495
494496/// Appends to `bw` contents by reading from the stream until `delimiter` is found.
......@@ -497,18 +499,19 @@ pub fn streamReadDelimiter(br: *BufferedReader, bw: *BufferedWriter, delimiter:
497499/// Succeeds if stream ends before delimiter found.
498500///
499501/// Returns number of bytes streamed. The end is not signaled to the writer.
500pub fn streamReadDelimiterExclusive(
502pub fn streamToDelimiterOrEnd(
501503 br: *BufferedReader,
502504 bw: *BufferedWriter,
503505 delimiter: u8,
504) Reader.ShortError!usize {
505 _ = br;
506 _ = bw;
507 _ = delimiter;
508 @panic("TODO");
506) Reader.RwAllError!usize {
507 const amount, const to = try br.streamToAny(bw, delimiter, .unlimited);
508 return switch (to) {
509 .delimiter, .end => amount,
510 .limit => unreachable,
511 };
509512}
510513
511pub const StreamDelimiterLimitedError = Reader.ShortError || error{
514pub const StreamDelimiterLimitedError = Reader.RwAllError || error{
512515 /// Stream ended before the delimiter was found.
513516 EndOfStream,
514517 /// The delimiter was not found within the limit.
......@@ -517,19 +520,46 @@ pub const StreamDelimiterLimitedError = Reader.ShortError || error{
517520
518521/// Appends to `bw` contents by reading from the stream until `delimiter` is found.
519522/// Does not write the delimiter itself.
520//
523///
521524/// Returns number of bytes streamed.
522pub fn streamReadDelimiterLimited(
525pub fn streamToDelimiterOrLimit(
523526 br: *BufferedReader,
524527 bw: *BufferedWriter,
525528 delimiter: u8,
526529 limit: Reader.Limit,
527530) StreamDelimiterLimitedError!usize {
528 _ = br;
529 _ = bw;
530 _ = delimiter;
531 _ = limit;
532 @panic("TODO");
531 const amount, const to = try br.streamToAny(bw, delimiter, limit);
532 return switch (to) {
533 .delimiter => amount,
534 .limit => error.StreamTooLong,
535 .end => error.EndOfStream,
536 };
537}
538
539fn streamToAny(
540 br: *BufferedReader,
541 bw: *BufferedWriter,
542 delimiter: ?u8,
543 limit: Reader.Limit,
544) Reader.RwAllError!struct { usize, enum { delimiter, limit, end } } {
545 var amount: usize = 0;
546 var remaining = limit;
547 while (remaining.nonzero()) {
548 const available = remaining.slice(br.peekGreedy(1) catch |err| switch (err) {
549 error.ReadFailed => |e| return e,
550 error.EndOfStream => return .{ amount, .end },
551 });
552 if (delimiter) |d| if (std.mem.indexOfScalar(u8, available, d)) |delimiter_index| {
553 try bw.writeAll(available[0..delimiter_index]);
554 br.toss(delimiter_index + 1);
555 return .{ amount + delimiter_index, .delimiter };
556 };
557 try bw.writeAll(available);
558 br.toss(available.len);
559 amount += available.len;
560 remaining = remaining.subtract(available.len).?;
561 }
562 return .{ amount, .limit };
533563}
534564
535565/// Reads from the stream until specified byte is found, discarding all data,
......@@ -824,15 +854,15 @@ test peekDelimiterExclusive {
824854 return error.Unimplemented;
825855}
826856
827test streamReadDelimiter {
857test streamToDelimiter {
828858 return error.Unimplemented;
829859}
830860
831test streamReadDelimiterExclusive {
861test streamToDelimiterOrEnd {
832862 return error.Unimplemented;
833863}
834864
835test streamReadDelimiterLimited {
865test streamToDelimiterOrLimit {
836866 return error.Unimplemented;
837867}
838868
src/Compilation.zig+14-11
......@@ -1000,11 +1000,14 @@ pub const CObject = struct {
10001000 defer file.close();
10011001 file.seekTo(diag.src_loc.offset + 1 - diag.src_loc.column) catch break :source_line 0;
10021002
1003 var line = std.ArrayList(u8).init(eb.gpa);
1004 defer line.deinit();
1005 file.reader().readUntilDelimiterArrayList(&line, '\n', 1 << 10) catch break :source_line 0;
1006
1007 break :source_line try eb.addString(line.items);
1003 var buffer: [1 << 10]u8 = undefined;
1004 var fr = file.reader();
1005 var br = fr.interface().buffered(&buffer);
1006 var bw: std.io.BufferedWriter = undefined;
1007 bw.initFixed(&buffer);
1008 break :source_line try eb.addString(
1009 buffer[0 .. br.streamToDelimiterOrEnd(&bw, '\n') catch break :source_line 0],
1010 );
10081011 };
10091012
10101013 return .{
......@@ -3781,7 +3784,7 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {
37813784 if (!refs.contains(anal_unit)) continue;
37823785 }
37833786
3784 std.log.scoped(.zcu).debug("analysis error '{s}' reported from unit '{}'", .{
3787 std.log.scoped(.zcu).debug("analysis error '{s}' reported from unit '{f}'", .{
37853788 error_msg.msg,
37863789 zcu.fmtAnalUnit(anal_unit),
37873790 });
......@@ -3941,12 +3944,12 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {
39413944 // This AU is referenced and has a transitive compile error, meaning it referenced something with a compile error.
39423945 // However, we haven't reported any such error.
39433946 // This is a compiler bug.
3944 var stderr = std.debug.lockStdErr2(&.{});
3945 defer std.debug.unlockStdErr();
3946 try stderr.writeAll("referenced transitive analysis errors, but none actually emitted\n");
3947 try stderr.print("{} [transitive failure]\n", .{zcu.fmtAnalUnit(failed_unit)});
3947 var stderr_bw = std.debug.lockStderrWriter(&.{});
3948 defer std.debug.unlockStderrWriter();
3949 try stderr_bw.writeAll("referenced transitive analysis errors, but none actually emitted\n");
3950 try stderr_bw.print("{f} [transitive failure]\n", .{zcu.fmtAnalUnit(failed_unit)});
39483951 while (ref) |r| {
3949 try stderr.print("referenced by: {}{s}\n", .{
3952 try stderr_bw.print("referenced by: {f}{s}\n", .{
39503953 zcu.fmtAnalUnit(r.referencer),
39513954 if (zcu.transitive_failed_analysis.contains(r.referencer)) " [transitive failure]" else "",
39523955 });
src/Zcu/PerThread.zig+2-2
......@@ -268,7 +268,7 @@ pub fn updateFile(
268268 file.zir = try AstGen.generate(gpa, file.tree.?);
269269 Zcu.saveZirCache(gpa, cache_file, stat, file.zir.?) catch |err| switch (err) {
270270 error.OutOfMemory => |e| return e,
271 else => log.warn("unable to write cached ZIR code for {} to {}{s}: {s}", .{
271 else => log.warn("unable to write cached ZIR code for {f} to {f}{s}: {s}", .{
272272 file.path.fmt(comp), cache_directory, &hex_digest, @errorName(err),
273273 }),
274274 };
......@@ -276,7 +276,7 @@ pub fn updateFile(
276276 .zon => {
277277 file.zoir = try ZonGen.generate(gpa, file.tree.?, .{});
278278 Zcu.saveZoirCache(cache_file, stat, file.zoir.?) catch |err| {
279 log.warn("unable to write cached ZOIR code for {} to {}{s}: {s}", .{
279 log.warn("unable to write cached ZOIR code for {f} to {f}{s}: {s}", .{
280280 file.path.fmt(comp), cache_directory, &hex_digest, @errorName(err),
281281 });
282282 };
src/link.zig+33-15
......@@ -1023,15 +1023,24 @@ pub const File = struct {
10231023 };
10241024 }
10251025
1026 fn loadGnuLdScript(base: *File, path: Path, parent_query: UnresolvedInput.Query, file: fs.File) anyerror!void {
1026 fn loadGnuLdScript(
1027 base: *File,
1028 path: Path,
1029 parent_query: UnresolvedInput.Query,
1030 file: fs.File,
1031 ) anyerror!void {
10271032 const diags = &base.comp.link_diags;
10281033 const gpa = base.comp.gpa;
10291034 const stat = try file.stat();
10301035 const size = std.math.cast(u32, stat.size) orelse return error.FileTooBig;
10311036 const buf = try gpa.alloc(u8, size);
10321037 defer gpa.free(buf);
1033 const n = try file.preadAll(buf, 0);
1034 if (buf.len != n) return error.UnexpectedEndOfFile;
1038 var fr = file.reader();
1039 var br = fr.interface().unbuffered();
1040 br.readSlice(buf) catch |err| switch (err) {
1041 error.ReadFailed => if (fr.err) |_| unreachable else |e| return e,
1042 error.EndOfStream => return error.UnexpectedEndOfFile,
1043 };
10351044 var ld_script = try LdScript.parse(gpa, diags, path, buf);
10361045 defer ld_script.deinit(gpa);
10371046 for (ld_script.args) |arg| {
......@@ -2092,24 +2101,33 @@ fn resolvePathInputLib(
20922101 };
20932102 errdefer file.close();
20942103 try ld_script_bytes.resize(gpa, @max(std.elf.MAGIC.len, std.elf.ARMAG.len));
2095 const n = file.preadAll(ld_script_bytes.items, 0) catch |err| fatal("failed to read '{f'}': {s}", .{
2096 test_path, @errorName(err),
2097 });
2098 const buf = ld_script_bytes.items[0..n];
2099 if (mem.startsWith(u8, buf, std.elf.MAGIC) or mem.startsWith(u8, buf, std.elf.ARMAG)) {
2100 // Appears to be an ELF or archive file.
2101 return finishResolveLibInput(resolved_inputs, test_path, file, link_mode, pq.query);
2104 var fr = file.reader();
2105 var br = fr.interface().unbuffered();
2106 ok: {
2107 br.readSlice(ld_script_bytes.items) catch |err| switch (err) {
2108 error.ReadFailed => fatal("failed to read '{f'}': {s}", .{
2109 test_path,
2110 @errorName(if (fr.err) |_| unreachable else |e| e),
2111 }),
2112 error.EndOfStream => break :ok,
2113 };
2114 if (mem.startsWith(u8, ld_script_bytes.items, std.elf.MAGIC) or
2115 mem.startsWith(u8, ld_script_bytes.items, std.elf.ARMAG))
2116 {
2117 // Appears to be an ELF or archive file.
2118 return finishResolveLibInput(resolved_inputs, test_path, file, link_mode, pq.query);
2119 }
21022120 }
21032121 const stat = file.stat() catch |err|
21042122 fatal("failed to stat {f}: {s}", .{ test_path, @errorName(err) });
21052123 const size = std.math.cast(u32, stat.size) orelse
21062124 fatal("{f}: linker script too big", .{test_path});
21072125 try ld_script_bytes.resize(gpa, size);
2108 const buf2 = ld_script_bytes.items[n..];
2109 const n2 = file.preadAll(buf2, n) catch |err|
2110 fatal("failed to read {f}: {s}", .{ test_path, @errorName(err) });
2111 if (n2 != buf2.len) fatal("failed to read {f}: unexpected end of file", .{test_path});
2112 var diags = Diags.init(gpa);
2126 br.readSlice(ld_script_bytes.items[@intCast(fr.pos)..]) catch |err| switch (err) {
2127 error.ReadFailed => if (fr.err) |_| unreachable else |e| fatal("failed to read {f}: {s}", .{ test_path, @errorName(e) }),
2128 error.EndOfStream => fatal("failed to read {f}: unexpected end of file", .{test_path}),
2129 };
2130 var diags: Diags = .init(gpa);
21132131 defer diags.deinit();
21142132 const ld_script_result = LdScript.parse(gpa, &diags, test_path, ld_script_bytes.items);
21152133 if (diags.hasErrors()) {
src/main.zig+2-2
......@@ -3511,7 +3511,7 @@ fn buildOutputType(
35113511 if (t.arch == target.cpu.arch and t.os == target.os.tag) {
35123512 // If there's a `glibc_min`, there's also an `os_ver`.
35133513 if (t.glibc_min) |glibc_min| {
3514 std.log.info("zig can provide libc for related target {s}-{s}.{}-{s}.{d}.{d}", .{
3514 std.log.info("zig can provide libc for related target {s}-{s}.{f}-{s}.{d}.{d}", .{
35153515 @tagName(t.arch),
35163516 @tagName(t.os),
35173517 t.os_ver.?,
......@@ -3520,7 +3520,7 @@ fn buildOutputType(
35203520 glibc_min.minor,
35213521 });
35223522 } else if (t.os_ver) |os_ver| {
3523 std.log.info("zig can provide libc for related target {s}-{s}.{}-{s}", .{
3523 std.log.info("zig can provide libc for related target {s}-{s}.{f}-{s}", .{
35243524 @tagName(t.arch),
35253525 @tagName(t.os),
35263526 os_ver,