resinator: Sync with upstream

No functional differences, just some shuffling things around and the removal of the now-obsolete `utils.openFileNotDir`.
This commit is contained in:
Ryan Liptak 2026-01-13 01:47:27 -08:00 committed by Ryan Liptak
parent 3da6e67199
commit 9d1a39c50f
6 changed files with 39 additions and 53 deletions

View file

@ -128,15 +128,19 @@ pub const Diagnostics = struct {
pub fn renderToStderr(self: *Diagnostics, io: Io, args: []const []const u8) Io.Cancelable!void {
const stderr = try io.lockStderr(&.{}, null);
defer io.unlockStderr();
self.renderToWriter(args, stderr.terminal()) catch return;
self.renderToTerminal(stderr.terminal(), args) catch return;
}
pub fn renderToWriter(self: *Diagnostics, args: []const []const u8, t: Io.Terminal) !void {
pub fn renderToTerminal(self: *Diagnostics, terminal: Io.Terminal, args: []const []const u8) !void {
for (self.errors.items) |err_details| {
try renderErrorMessage(t, err_details, args);
try renderErrorMessage(terminal, err_details, args);
}
}
pub fn renderToWriter(self: *Diagnostics, writer: *Io.Writer, args: []const []const u8) !void {
return self.renderToTerminal(.{ .writer = writer, .mode = .no_color }, args);
}
pub fn hasError(self: *const Diagnostics) bool {
for (self.errors.items) |err| {
if (err.type == .err) return true;
@ -1475,9 +1479,9 @@ fn testParseOutput(args: []const []const u8, expected_output: []const u8) !?Opti
var output: std.Io.Writer.Allocating = .init(std.testing.allocator);
defer output.deinit();
var options = parse(std.testing.allocator, args, &diagnostics) catch |err| switch (err) {
var options = parse(std.testing.allocator, std.testing.io, args, &diagnostics) catch |err| switch (err) {
error.ParseError => {
try diagnostics.renderToWriter(args, &output.writer, .no_color);
try diagnostics.renderToWriter(&output.writer, args);
try std.testing.expectEqualStrings(expected_output, output.written());
return null;
},
@ -1485,7 +1489,7 @@ fn testParseOutput(args: []const []const u8, expected_output: []const u8) !?Opti
};
errdefer options.deinit();
try diagnostics.renderToWriter(args, &output.writer, .no_color);
try diagnostics.renderToWriter(&output.writer, args);
try std.testing.expectEqualStrings(expected_output, output.written());
return options;
}

View file

@ -59,6 +59,7 @@ pub const CompileOptions = struct {
max_string_literal_codepoints: u15 = lex.default_max_string_literal_codepoints,
silent_duplicate_control_ids: bool = false,
warn_instead_of_error_on_invalid_code_page: bool = false,
include_env_value: ?[]const u8 = null,
};
pub const Dependencies = struct {
@ -80,7 +81,7 @@ pub const Dependencies = struct {
}
};
pub fn compile(allocator: Allocator, io: Io, source: []const u8, writer: *std.Io.Writer, options: CompileOptions, environ_map: *const std.process.Environ.Map) !void {
pub fn compile(allocator: Allocator, io: Io, source: []const u8, writer: *std.Io.Writer, options: CompileOptions) !void {
var lexer = lex.Lexer.init(source, .{
.default_code_page = options.default_code_page,
.source_mappings = options.source_mappings,
@ -148,7 +149,7 @@ pub fn compile(allocator: Allocator, io: Io, source: []const u8, writer: *std.Io
try search_dirs.append(allocator, .{ .dir = dir, .path = try allocator.dupe(u8, system_include_path) });
}
if (!options.ignore_include_env_var) {
const INCLUDE = environ_map.get("INCLUDE") orelse "";
const INCLUDE = options.include_env_value orelse "";
// The only precedence here is llvm-rc which also uses the platform-specific
// delimiter. There's no precedence set by `rc.exe` since it's Windows-only.
@ -405,7 +406,7 @@ pub const Compiler = struct {
// `/test.bin` relative to include paths and instead only treats it as
// an absolute path.
if (std.fs.path.isAbsolute(path)) {
const file = try utils.openFileNotDir(Io.Dir.cwd(), io, path, .{});
const file = try Io.Dir.cwd().openFile(io, path, .{ .allow_directory = false });
errdefer file.close(io);
if (self.dependencies) |dependencies| {
@ -417,7 +418,7 @@ pub const Compiler = struct {
var first_error: ?(std.Io.File.OpenError || std.Io.File.StatError) = null;
for (self.search_dirs) |search_dir| {
if (utils.openFileNotDir(search_dir.dir, io, path, .{})) |file| {
if (search_dir.dir.openFile(io, path, .{ .allow_directory = false })) |file| {
errdefer file.close(io);
if (self.dependencies) |dependencies| {

View file

@ -24,12 +24,10 @@ pub const Diagnostics = struct {
/// Expects to own all strings within the list.
strings: std.ArrayList([]const u8) = .empty,
allocator: Allocator,
io: Io,
pub fn init(allocator: Allocator, io: Io) Diagnostics {
pub fn init(allocator: Allocator) Diagnostics {
return .{
.allocator = allocator,
.io = io,
};
}
@ -67,8 +65,7 @@ pub const Diagnostics = struct {
return @intCast(index);
}
pub fn renderToStderr(self: *Diagnostics, cwd: Io.Dir, source: []const u8, source_mappings: ?SourceMappings) Io.Cancelable!void {
const io = self.io;
pub fn renderToStderr(self: *Diagnostics, io: Io, cwd: Io.Dir, source: []const u8, source_mappings: ?SourceMappings) Io.Cancelable!void {
const stderr = try io.lockStderr(&.{}, null);
defer io.unlockStderr();
for (self.errors.items) |err_details| {
@ -1120,7 +1117,7 @@ const CorrespondingLines = struct {
var corresponding_lines = CorrespondingLines{
.span = corresponding_span,
.file = try utils.openFileNotDir(cwd, io, corresponding_file, .{}),
.file = try cwd.openFile(io, corresponding_file, .{ .allow_directory = false }),
.code_page = err_details.code_page,
.file_reader = undefined,
};

View file

@ -12,7 +12,6 @@ const Diagnostics = @import("errors.zig").Diagnostics;
const cli = @import("cli.zig");
const preprocess = @import("preprocess.zig");
const renderErrorMessage = @import("utils.zig").renderErrorMessage;
const openFileNotDir = @import("utils.zig").openFileNotDir;
const cvtres = @import("cvtres.zig");
const hasDisjointCodePage = @import("disjoint_code_page.zig").hasDisjointCodePage;
const fmtResourceType = @import("res.zig").NameOrOrdinal.fmtResourceType;
@ -141,7 +140,7 @@ pub fn main(init: std.process.Init.Minimal) !void {
} };
defer {
diagnostics.deinit();
if (!zig_integration) std.debug.unlockStderr();
if (!zig_integration) io.unlockStderr();
}
var comp = aro.Compilation.init(aro_arena, aro_arena, io, &diagnostics, Io.Dir.cwd());
@ -152,7 +151,7 @@ pub fn main(init: std.process.Init.Minimal) !void {
try argv.append(aro_arena, "arocc"); // dummy command name
const resolved_include_paths = try include_paths.get(&error_handler, &environ_map);
try preprocess.appendAroArgs(aro_arena, &argv, options, resolved_include_paths, &environ_map);
try preprocess.appendAroArgs(aro_arena, &argv, options, resolved_include_paths, environ_map.get("INCLUDE"));
try argv.append(aro_arena, switch (options.input_source) {
.stdio => "-",
.filename => |filename| filename,
@ -194,13 +193,13 @@ pub fn main(init: std.process.Init.Minimal) !void {
.stdio => |file| {
var file_reader = file.reader(io, &.{});
break :full_input file_reader.interface.allocRemaining(gpa, .unlimited) catch |err| {
try error_handler.emitMessage(gpa, io, .err, "unable to read input from stdin: {s}", .{@errorName(err)});
try error_handler.emitMessage(gpa, io, .err, "unable to read input from stdin: {t}", .{file_reader.err orelse err});
std.process.exit(1);
};
},
.filename => |input_filename| {
break :full_input Io.Dir.cwd().readFileAlloc(io, input_filename, gpa, .unlimited) catch |err| {
try error_handler.emitMessage(gpa, io, .err, "unable to read input file path '{s}': {s}", .{ input_filename, @errorName(err) });
try error_handler.emitMessage(gpa, io, .err, "unable to read input file path '{s}': {t}", .{ input_filename, err });
std.process.exit(1);
};
},
@ -271,7 +270,7 @@ pub fn main(init: std.process.Init.Minimal) !void {
const final_input = try removeComments(mapping_results.result, mapping_results.result, &mapping_results.mappings);
var diagnostics = Diagnostics.init(gpa, io);
var diagnostics = Diagnostics.init(gpa);
defer diagnostics.deinit();
var output_buffer: [4096]u8 = undefined;
@ -295,9 +294,10 @@ pub fn main(init: std.process.Init.Minimal) !void {
.max_string_literal_codepoints = options.max_string_literal_codepoints,
.silent_duplicate_control_ids = options.silent_duplicate_control_ids,
.warn_instead_of_error_on_invalid_code_page = options.warn_instead_of_error_on_invalid_code_page,
}, &environ_map) catch |err| switch (err) {
.include_env_value = environ_map.get("INCLUDE"),
}) catch |err| switch (err) {
error.ParseError, error.CompileError => {
try error_handler.emitDiagnostics(gpa, Io.Dir.cwd(), final_input, &diagnostics, mapping_results.mappings);
try error_handler.emitDiagnostics(gpa, io, Io.Dir.cwd(), final_input, &diagnostics, mapping_results.mappings);
// Delete the output file on error
res_stream.cleanupAfterError(io);
std.process.exit(1);
@ -309,7 +309,7 @@ pub fn main(init: std.process.Init.Minimal) !void {
// print any warnings/notes
if (!zig_integration) {
try diagnostics.renderToStderr(Io.Dir.cwd(), final_input, mapping_results.mappings);
try diagnostics.renderToStderr(io, Io.Dir.cwd(), final_input, mapping_results.mappings);
}
// write the depfile
@ -460,7 +460,7 @@ const IoStream = struct {
switch (source) {
.filename => |filename| return .{
.file = switch (io_direction) {
.input => try openFileNotDir(Io.Dir.cwd(), io, filename, .{}),
.input => try Io.Dir.cwd().openFile(io, filename, .{ .allow_directory = false }),
.output => try Io.Dir.cwd().createFile(io, filename, .{}),
},
},
@ -733,6 +733,7 @@ const ErrorHandler = union(enum) {
pub fn emitDiagnostics(
self: *ErrorHandler,
allocator: Allocator,
io: Io,
cwd: Io.Dir,
source: []const u8,
diagnostics: *Diagnostics,
@ -745,7 +746,7 @@ const ErrorHandler = union(enum) {
try server.serveErrorBundle(error_bundle);
},
.stderr => return diagnostics.renderToStderr(cwd, source, mappings),
.stderr => return diagnostics.renderToStderr(io, cwd, source, mappings),
}
}

View file

@ -84,9 +84,9 @@ fn hasAnyErrors(comp: *aro.Compilation) bool {
return comp.diagnostics.errors != 0;
}
/// `arena` is used for temporary -D argument strings and the INCLUDE environment variable.
/// `arena` is used for temporary -D argument strings.
/// The arena should be kept alive at least as long as `argv`.
pub fn appendAroArgs(arena: Allocator, argv: *std.ArrayList([]const u8), options: cli.Options, system_include_paths: []const []const u8, environ_map: *const std.process.Environ.Map) !void {
pub fn appendAroArgs(arena: Allocator, argv: *std.ArrayList([]const u8), options: cli.Options, system_include_paths: []const []const u8, include_env_value: ?[]const u8) !void {
try argv.appendSlice(arena, &.{
"-E",
"--comments",
@ -109,7 +109,7 @@ pub fn appendAroArgs(arena: Allocator, argv: *std.ArrayList([]const u8), options
}
if (!options.ignore_include_env_var) {
const INCLUDE = environ_map.get("INCLUDE") orelse "";
const INCLUDE = include_env_value orelse "";
// The only precedence here is llvm-rc which also uses the platform-specific
// delimiter. There's no precedence set by `rc.exe` since it's Windows-only.

View file

@ -1,5 +1,3 @@
const builtin = @import("builtin");
const std = @import("std");
const Io = std.Io;
@ -25,27 +23,6 @@ pub const UncheckedSliceWriter = struct {
}
};
/// Cross-platform 'Io.Dir.openFile' wrapper that will always return IsDir if
/// a directory is attempted to be opened.
/// TODO: Remove once https://github.com/ziglang/zig/issues/5732 is addressed.
pub fn openFileNotDir(
cwd: Io.Dir,
io: Io,
path: []const u8,
flags: Io.File.OpenFlags,
) (Io.File.OpenError || Io.File.StatError)!Io.File {
const file = try cwd.openFile(io, path, flags);
errdefer file.close(io);
// https://github.com/ziglang/zig/issues/5732
if (builtin.os.tag != .windows) {
const stat = try file.stat(io);
if (stat.kind == .directory)
return error.IsDir;
}
return file;
}
/// Emulates the Windows implementation of `iswdigit`, but only returns true
/// for the non-ASCII digits that `iswdigit` on Windows would return true for.
pub fn isNonAsciiDigit(c: u21) bool {
@ -90,6 +67,12 @@ pub fn isNonAsciiDigit(c: u21) bool {
pub const ErrorMessageType = enum { err, warning, note };
pub fn renderErrorMessageToStderr(io: std.Io, msg_type: ErrorMessageType, comptime format: []const u8, args: anytype) !void {
var stderr = try io.lockStderr(&.{}, null);
defer io.unlockStderr();
try renderErrorMessage(stderr.terminal(), msg_type, format, args);
}
/// Used for generic colored errors/warnings/notes, more context-specific error messages
/// are handled elsewhere.
pub fn renderErrorMessage(t: Io.Terminal, msg_type: ErrorMessageType, comptime format: []const u8, args: anytype) !void {