link: port to std.io.BufferedReader API changes

This commit is contained in:
Jacob Young 2025-04-21 16:32:37 -04:00 committed by Andrew Kelley
parent 6a0f2227e8
commit d62f22cc4d
5 changed files with 103 additions and 52 deletions

View File

@ -484,11 +484,13 @@ fn peekDelimiterInclusiveUnlessEnd(br: *BufferedReader, delimiter: u8) Delimiter
/// found. Does not write the delimiter itself.
///
/// Returns number of bytes streamed.
pub fn streamReadDelimiter(br: *BufferedReader, bw: *BufferedWriter, delimiter: u8) Reader.Error!usize {
_ = br;
_ = bw;
_ = delimiter;
@panic("TODO");
pub fn streamToDelimiter(br: *BufferedReader, bw: *BufferedWriter, delimiter: u8) Reader.RwError!usize {
const amount, const to = try br.streamToAny(bw, delimiter, .unlimited);
return switch (to) {
.delimiter => amount,
.limit => unreachable,
.end => error.EndOfStream,
};
}
/// 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:
/// Succeeds if stream ends before delimiter found.
///
/// Returns number of bytes streamed. The end is not signaled to the writer.
pub fn streamReadDelimiterExclusive(
pub fn streamToDelimiterOrEnd(
br: *BufferedReader,
bw: *BufferedWriter,
delimiter: u8,
) Reader.ShortError!usize {
_ = br;
_ = bw;
_ = delimiter;
@panic("TODO");
) Reader.RwAllError!usize {
const amount, const to = try br.streamToAny(bw, delimiter, .unlimited);
return switch (to) {
.delimiter, .end => amount,
.limit => unreachable,
};
}
pub const StreamDelimiterLimitedError = Reader.ShortError || error{
pub const StreamDelimiterLimitedError = Reader.RwAllError || error{
/// Stream ended before the delimiter was found.
EndOfStream,
/// The delimiter was not found within the limit.
@ -517,19 +520,46 @@ pub const StreamDelimiterLimitedError = Reader.ShortError || error{
/// Appends to `bw` contents by reading from the stream until `delimiter` is found.
/// Does not write the delimiter itself.
//
///
/// Returns number of bytes streamed.
pub fn streamReadDelimiterLimited(
pub fn streamToDelimiterOrLimit(
br: *BufferedReader,
bw: *BufferedWriter,
delimiter: u8,
limit: Reader.Limit,
) StreamDelimiterLimitedError!usize {
_ = br;
_ = bw;
_ = delimiter;
_ = limit;
@panic("TODO");
const amount, const to = try br.streamToAny(bw, delimiter, limit);
return switch (to) {
.delimiter => amount,
.limit => error.StreamTooLong,
.end => error.EndOfStream,
};
}
fn streamToAny(
br: *BufferedReader,
bw: *BufferedWriter,
delimiter: ?u8,
limit: Reader.Limit,
) Reader.RwAllError!struct { usize, enum { delimiter, limit, end } } {
var amount: usize = 0;
var remaining = limit;
while (remaining.nonzero()) {
const available = remaining.slice(br.peekGreedy(1) catch |err| switch (err) {
error.ReadFailed => |e| return e,
error.EndOfStream => return .{ amount, .end },
});
if (delimiter) |d| if (std.mem.indexOfScalar(u8, available, d)) |delimiter_index| {
try bw.writeAll(available[0..delimiter_index]);
br.toss(delimiter_index + 1);
return .{ amount + delimiter_index, .delimiter };
};
try bw.writeAll(available);
br.toss(available.len);
amount += available.len;
remaining = remaining.subtract(available.len).?;
}
return .{ amount, .limit };
}
/// Reads from the stream until specified byte is found, discarding all data,
@ -824,15 +854,15 @@ test peekDelimiterExclusive {
return error.Unimplemented;
}
test streamReadDelimiter {
test streamToDelimiter {
return error.Unimplemented;
}
test streamReadDelimiterExclusive {
test streamToDelimiterOrEnd {
return error.Unimplemented;
}
test streamReadDelimiterLimited {
test streamToDelimiterOrLimit {
return error.Unimplemented;
}

View File

@ -1000,11 +1000,14 @@ pub const CObject = struct {
defer file.close();
file.seekTo(diag.src_loc.offset + 1 - diag.src_loc.column) catch break :source_line 0;
var line = std.ArrayList(u8).init(eb.gpa);
defer line.deinit();
file.reader().readUntilDelimiterArrayList(&line, '\n', 1 << 10) catch break :source_line 0;
break :source_line try eb.addString(line.items);
var buffer: [1 << 10]u8 = undefined;
var fr = file.reader();
var br = fr.interface().buffered(&buffer);
var bw: std.io.BufferedWriter = undefined;
bw.initFixed(&buffer);
break :source_line try eb.addString(
buffer[0 .. br.streamToDelimiterOrEnd(&bw, '\n') catch break :source_line 0],
);
};
return .{
@ -3781,7 +3784,7 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {
if (!refs.contains(anal_unit)) continue;
}
std.log.scoped(.zcu).debug("analysis error '{s}' reported from unit '{}'", .{
std.log.scoped(.zcu).debug("analysis error '{s}' reported from unit '{f}'", .{
error_msg.msg,
zcu.fmtAnalUnit(anal_unit),
});
@ -3941,12 +3944,12 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {
// This AU is referenced and has a transitive compile error, meaning it referenced something with a compile error.
// However, we haven't reported any such error.
// This is a compiler bug.
var stderr = std.debug.lockStdErr2(&.{});
defer std.debug.unlockStdErr();
try stderr.writeAll("referenced transitive analysis errors, but none actually emitted\n");
try stderr.print("{} [transitive failure]\n", .{zcu.fmtAnalUnit(failed_unit)});
var stderr_bw = std.debug.lockStderrWriter(&.{});
defer std.debug.unlockStderrWriter();
try stderr_bw.writeAll("referenced transitive analysis errors, but none actually emitted\n");
try stderr_bw.print("{f} [transitive failure]\n", .{zcu.fmtAnalUnit(failed_unit)});
while (ref) |r| {
try stderr.print("referenced by: {}{s}\n", .{
try stderr_bw.print("referenced by: {f}{s}\n", .{
zcu.fmtAnalUnit(r.referencer),
if (zcu.transitive_failed_analysis.contains(r.referencer)) " [transitive failure]" else "",
});

View File

@ -268,7 +268,7 @@ pub fn updateFile(
file.zir = try AstGen.generate(gpa, file.tree.?);
Zcu.saveZirCache(gpa, cache_file, stat, file.zir.?) catch |err| switch (err) {
error.OutOfMemory => |e| return e,
else => log.warn("unable to write cached ZIR code for {} to {}{s}: {s}", .{
else => log.warn("unable to write cached ZIR code for {f} to {f}{s}: {s}", .{
file.path.fmt(comp), cache_directory, &hex_digest, @errorName(err),
}),
};
@ -276,7 +276,7 @@ pub fn updateFile(
.zon => {
file.zoir = try ZonGen.generate(gpa, file.tree.?, .{});
Zcu.saveZoirCache(cache_file, stat, file.zoir.?) catch |err| {
log.warn("unable to write cached ZOIR code for {} to {}{s}: {s}", .{
log.warn("unable to write cached ZOIR code for {f} to {f}{s}: {s}", .{
file.path.fmt(comp), cache_directory, &hex_digest, @errorName(err),
});
};

View File

@ -1023,15 +1023,24 @@ pub const File = struct {
};
}
fn loadGnuLdScript(base: *File, path: Path, parent_query: UnresolvedInput.Query, file: fs.File) anyerror!void {
fn loadGnuLdScript(
base: *File,
path: Path,
parent_query: UnresolvedInput.Query,
file: fs.File,
) anyerror!void {
const diags = &base.comp.link_diags;
const gpa = base.comp.gpa;
const stat = try file.stat();
const size = std.math.cast(u32, stat.size) orelse return error.FileTooBig;
const buf = try gpa.alloc(u8, size);
defer gpa.free(buf);
const n = try file.preadAll(buf, 0);
if (buf.len != n) return error.UnexpectedEndOfFile;
var fr = file.reader();
var br = fr.interface().unbuffered();
br.readSlice(buf) catch |err| switch (err) {
error.ReadFailed => if (fr.err) |_| unreachable else |e| return e,
error.EndOfStream => return error.UnexpectedEndOfFile,
};
var ld_script = try LdScript.parse(gpa, diags, path, buf);
defer ld_script.deinit(gpa);
for (ld_script.args) |arg| {
@ -2092,24 +2101,33 @@ fn resolvePathInputLib(
};
errdefer file.close();
try ld_script_bytes.resize(gpa, @max(std.elf.MAGIC.len, std.elf.ARMAG.len));
const n = file.preadAll(ld_script_bytes.items, 0) catch |err| fatal("failed to read '{f'}': {s}", .{
test_path, @errorName(err),
});
const buf = ld_script_bytes.items[0..n];
if (mem.startsWith(u8, buf, std.elf.MAGIC) or mem.startsWith(u8, buf, std.elf.ARMAG)) {
// Appears to be an ELF or archive file.
return finishResolveLibInput(resolved_inputs, test_path, file, link_mode, pq.query);
var fr = file.reader();
var br = fr.interface().unbuffered();
ok: {
br.readSlice(ld_script_bytes.items) catch |err| switch (err) {
error.ReadFailed => fatal("failed to read '{f'}': {s}", .{
test_path,
@errorName(if (fr.err) |_| unreachable else |e| e),
}),
error.EndOfStream => break :ok,
};
if (mem.startsWith(u8, ld_script_bytes.items, std.elf.MAGIC) or
mem.startsWith(u8, ld_script_bytes.items, std.elf.ARMAG))
{
// Appears to be an ELF or archive file.
return finishResolveLibInput(resolved_inputs, test_path, file, link_mode, pq.query);
}
}
const stat = file.stat() catch |err|
fatal("failed to stat {f}: {s}", .{ test_path, @errorName(err) });
const size = std.math.cast(u32, stat.size) orelse
fatal("{f}: linker script too big", .{test_path});
try ld_script_bytes.resize(gpa, size);
const buf2 = ld_script_bytes.items[n..];
const n2 = file.preadAll(buf2, n) catch |err|
fatal("failed to read {f}: {s}", .{ test_path, @errorName(err) });
if (n2 != buf2.len) fatal("failed to read {f}: unexpected end of file", .{test_path});
var diags = Diags.init(gpa);
br.readSlice(ld_script_bytes.items[@intCast(fr.pos)..]) catch |err| switch (err) {
error.ReadFailed => if (fr.err) |_| unreachable else |e| fatal("failed to read {f}: {s}", .{ test_path, @errorName(e) }),
error.EndOfStream => fatal("failed to read {f}: unexpected end of file", .{test_path}),
};
var diags: Diags = .init(gpa);
defer diags.deinit();
const ld_script_result = LdScript.parse(gpa, &diags, test_path, ld_script_bytes.items);
if (diags.hasErrors()) {

View File

@ -3511,7 +3511,7 @@ fn buildOutputType(
if (t.arch == target.cpu.arch and t.os == target.os.tag) {
// If there's a `glibc_min`, there's also an `os_ver`.
if (t.glibc_min) |glibc_min| {
std.log.info("zig can provide libc for related target {s}-{s}.{}-{s}.{d}.{d}", .{
std.log.info("zig can provide libc for related target {s}-{s}.{f}-{s}.{d}.{d}", .{
@tagName(t.arch),
@tagName(t.os),
t.os_ver.?,
@ -3520,7 +3520,7 @@ fn buildOutputType(
glibc_min.minor,
});
} else if (t.os_ver) |os_ver| {
std.log.info("zig can provide libc for related target {s}-{s}.{}-{s}", .{
std.log.info("zig can provide libc for related target {s}-{s}.{f}-{s}", .{
@tagName(t.arch),
@tagName(t.os),
os_ver,