mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 06:13:07 +00:00
resinator: update for new Io APIs
This commit is contained in:
parent
76107e9e65
commit
4174ac18e9
@ -1,6 +1,12 @@
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const native_endian = builtin.cpu.arch.endian();
|
||||
|
||||
const std = @import("std");
|
||||
const Io = std.Io;
|
||||
const Allocator = std.mem.Allocator;
|
||||
const WORD = std.os.windows.WORD;
|
||||
const DWORD = std.os.windows.DWORD;
|
||||
|
||||
const Node = @import("ast.zig").Node;
|
||||
const lex = @import("lex.zig");
|
||||
const Parser = @import("parse.zig").Parser;
|
||||
@ -17,8 +23,6 @@ const res = @import("res.zig");
|
||||
const ico = @import("ico.zig");
|
||||
const ani = @import("ani.zig");
|
||||
const bmp = @import("bmp.zig");
|
||||
const WORD = std.os.windows.WORD;
|
||||
const DWORD = std.os.windows.DWORD;
|
||||
const utils = @import("utils.zig");
|
||||
const NameOrOrdinal = res.NameOrOrdinal;
|
||||
const SupportedCodePage = @import("code_pages.zig").SupportedCodePage;
|
||||
@ -28,7 +32,6 @@ const windows1252 = @import("windows1252.zig");
|
||||
const lang = @import("lang.zig");
|
||||
const code_pages = @import("code_pages.zig");
|
||||
const errors = @import("errors.zig");
|
||||
const native_endian = builtin.cpu.arch.endian();
|
||||
|
||||
pub const CompileOptions = struct {
|
||||
cwd: std.fs.Dir,
|
||||
@ -77,7 +80,7 @@ pub const Dependencies = struct {
|
||||
}
|
||||
};
|
||||
|
||||
pub fn compile(allocator: Allocator, source: []const u8, writer: *std.Io.Writer, options: CompileOptions) !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,
|
||||
@ -166,10 +169,11 @@ pub fn compile(allocator: Allocator, source: []const u8, writer: *std.Io.Writer,
|
||||
defer arena_allocator.deinit();
|
||||
const arena = arena_allocator.allocator();
|
||||
|
||||
var compiler = Compiler{
|
||||
var compiler: Compiler = .{
|
||||
.source = source,
|
||||
.arena = arena,
|
||||
.allocator = allocator,
|
||||
.io = io,
|
||||
.cwd = options.cwd,
|
||||
.diagnostics = options.diagnostics,
|
||||
.dependencies = options.dependencies,
|
||||
@ -191,6 +195,7 @@ pub const Compiler = struct {
|
||||
source: []const u8,
|
||||
arena: Allocator,
|
||||
allocator: Allocator,
|
||||
io: Io,
|
||||
cwd: std.fs.Dir,
|
||||
state: State = .{},
|
||||
diagnostics: *Diagnostics,
|
||||
@ -409,7 +414,7 @@ pub const Compiler = struct {
|
||||
}
|
||||
}
|
||||
|
||||
var first_error: ?std.fs.File.OpenError = null;
|
||||
var first_error: ?(std.fs.File.OpenError || std.fs.File.StatError) = null;
|
||||
for (self.search_dirs) |search_dir| {
|
||||
if (utils.openFileNotDir(search_dir.dir, path, .{})) |file| {
|
||||
errdefer file.close();
|
||||
@ -496,6 +501,8 @@ pub const Compiler = struct {
|
||||
}
|
||||
|
||||
pub fn writeResourceExternal(self: *Compiler, node: *Node.ResourceExternal, writer: *std.Io.Writer) !void {
|
||||
const io = self.io;
|
||||
|
||||
// Init header with data size zero for now, will need to fill it in later
|
||||
var header = try self.resourceHeader(node.id, node.type, .{});
|
||||
defer header.deinit(self.allocator);
|
||||
@ -582,7 +589,7 @@ pub const Compiler = struct {
|
||||
};
|
||||
defer file_handle.close();
|
||||
var file_buffer: [2048]u8 = undefined;
|
||||
var file_reader = file_handle.reader(&file_buffer);
|
||||
var file_reader = file_handle.reader(io, &file_buffer);
|
||||
|
||||
if (maybe_predefined_type) |predefined_type| {
|
||||
switch (predefined_type) {
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
const std = @import("std");
|
||||
const Io = std.Io;
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
||||
const res = @import("res.zig");
|
||||
const NameOrOrdinal = res.NameOrOrdinal;
|
||||
const MemoryFlags = res.MemoryFlags;
|
||||
@ -169,8 +171,7 @@ pub fn parseNameOrOrdinal(allocator: Allocator, reader: *std.Io.Reader) !NameOrO
|
||||
|
||||
pub const CoffOptions = struct {
|
||||
target: std.coff.IMAGE.FILE.MACHINE = .AMD64,
|
||||
/// If true, zeroes will be written to all timestamp fields
|
||||
reproducible: bool = true,
|
||||
timestamp: i64 = 0,
|
||||
/// If true, the MEM_WRITE flag will not be set in the .rsrc section header
|
||||
read_only: bool = false,
|
||||
/// If non-null, a symbol with this name and storage class EXTERNAL will be added to the symbol table.
|
||||
@ -188,7 +189,13 @@ pub const Diagnostics = union {
|
||||
overflow_resource: usize,
|
||||
};
|
||||
|
||||
pub fn writeCoff(allocator: Allocator, writer: *std.Io.Writer, resources: []const Resource, options: CoffOptions, diagnostics: ?*Diagnostics) !void {
|
||||
pub fn writeCoff(
|
||||
allocator: Allocator,
|
||||
writer: *std.Io.Writer,
|
||||
resources: []const Resource,
|
||||
options: CoffOptions,
|
||||
diagnostics: ?*Diagnostics,
|
||||
) !void {
|
||||
var resource_tree = ResourceTree.init(allocator, options);
|
||||
defer resource_tree.deinit();
|
||||
|
||||
@ -215,7 +222,7 @@ pub fn writeCoff(allocator: Allocator, writer: *std.Io.Writer, resources: []cons
|
||||
const pointer_to_rsrc02_data = pointer_to_relocations + relocations_len;
|
||||
const pointer_to_symbol_table = pointer_to_rsrc02_data + lengths.rsrc02;
|
||||
|
||||
const timestamp: i64 = if (options.reproducible) 0 else std.time.timestamp();
|
||||
const timestamp: i64 = options.timestamp;
|
||||
const size_of_optional_header = 0;
|
||||
const machine_type: std.coff.IMAGE.FILE.MACHINE = options.target;
|
||||
const flags = std.coff.Header.Flags{
|
||||
|
||||
@ -1,5 +1,11 @@
|
||||
const builtin = @import("builtin");
|
||||
const native_endian = builtin.cpu.arch.endian();
|
||||
|
||||
const std = @import("std");
|
||||
const Io = std.Io;
|
||||
const assert = std.debug.assert;
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
||||
const Token = @import("lex.zig").Token;
|
||||
const SourceMappings = @import("source_mapping.zig").SourceMappings;
|
||||
const utils = @import("utils.zig");
|
||||
@ -11,19 +17,19 @@ const parse = @import("parse.zig");
|
||||
const lang = @import("lang.zig");
|
||||
const code_pages = @import("code_pages.zig");
|
||||
const SupportedCodePage = code_pages.SupportedCodePage;
|
||||
const builtin = @import("builtin");
|
||||
const native_endian = builtin.cpu.arch.endian();
|
||||
|
||||
pub const Diagnostics = struct {
|
||||
errors: std.ArrayList(ErrorDetails) = .empty,
|
||||
/// Append-only, cannot handle removing strings.
|
||||
/// Expects to own all strings within the list.
|
||||
strings: std.ArrayList([]const u8) = .empty,
|
||||
allocator: std.mem.Allocator,
|
||||
allocator: Allocator,
|
||||
io: Io,
|
||||
|
||||
pub fn init(allocator: std.mem.Allocator) Diagnostics {
|
||||
pub fn init(allocator: Allocator, io: Io) Diagnostics {
|
||||
return .{
|
||||
.allocator = allocator,
|
||||
.io = io,
|
||||
};
|
||||
}
|
||||
|
||||
@ -62,10 +68,11 @@ pub const Diagnostics = struct {
|
||||
}
|
||||
|
||||
pub fn renderToStdErr(self: *Diagnostics, cwd: std.fs.Dir, source: []const u8, tty_config: std.Io.tty.Config, source_mappings: ?SourceMappings) void {
|
||||
const io = self.io;
|
||||
const stderr = std.debug.lockStderrWriter(&.{});
|
||||
defer std.debug.unlockStderrWriter();
|
||||
for (self.errors.items) |err_details| {
|
||||
renderErrorMessage(stderr, tty_config, cwd, err_details, source, self.strings.items, source_mappings) catch return;
|
||||
renderErrorMessage(io, stderr, tty_config, cwd, err_details, source, self.strings.items, source_mappings) catch return;
|
||||
}
|
||||
}
|
||||
|
||||
@ -167,9 +174,9 @@ pub const ErrorDetails = struct {
|
||||
filename_string_index: FilenameStringIndex,
|
||||
|
||||
pub const FilenameStringIndex = std.meta.Int(.unsigned, 32 - @bitSizeOf(FileOpenErrorEnum));
|
||||
pub const FileOpenErrorEnum = std.meta.FieldEnum(std.fs.File.OpenError);
|
||||
pub const FileOpenErrorEnum = std.meta.FieldEnum(std.fs.File.OpenError || std.fs.File.StatError);
|
||||
|
||||
pub fn enumFromError(err: std.fs.File.OpenError) FileOpenErrorEnum {
|
||||
pub fn enumFromError(err: (std.fs.File.OpenError || std.fs.File.StatError)) FileOpenErrorEnum {
|
||||
return switch (err) {
|
||||
inline else => |e| @field(ErrorDetails.FileOpenError.FileOpenErrorEnum, @errorName(e)),
|
||||
};
|
||||
@ -894,7 +901,16 @@ fn cellCount(code_page: SupportedCodePage, source: []const u8, start_index: usiz
|
||||
|
||||
const truncated_str = "<...truncated...>";
|
||||
|
||||
pub fn renderErrorMessage(writer: *std.Io.Writer, tty_config: std.Io.tty.Config, cwd: std.fs.Dir, err_details: ErrorDetails, source: []const u8, strings: []const []const u8, source_mappings: ?SourceMappings) !void {
|
||||
pub fn renderErrorMessage(
|
||||
io: Io,
|
||||
writer: *std.Io.Writer,
|
||||
tty_config: std.Io.tty.Config,
|
||||
cwd: std.fs.Dir,
|
||||
err_details: ErrorDetails,
|
||||
source: []const u8,
|
||||
strings: []const []const u8,
|
||||
source_mappings: ?SourceMappings,
|
||||
) !void {
|
||||
if (err_details.type == .hint) return;
|
||||
|
||||
const source_line_start = err_details.token.getLineStartForErrorDisplay(source);
|
||||
@ -989,6 +1005,7 @@ pub fn renderErrorMessage(writer: *std.Io.Writer, tty_config: std.Io.tty.Config,
|
||||
var initial_lines_err: ?anyerror = null;
|
||||
var file_reader_buf: [max_source_line_bytes * 2]u8 = undefined;
|
||||
var corresponding_lines: ?CorrespondingLines = CorrespondingLines.init(
|
||||
io,
|
||||
cwd,
|
||||
err_details,
|
||||
source_line_for_display.line,
|
||||
@ -1084,6 +1101,7 @@ const CorrespondingLines = struct {
|
||||
code_page: SupportedCodePage,
|
||||
|
||||
pub fn init(
|
||||
io: Io,
|
||||
cwd: std.fs.Dir,
|
||||
err_details: ErrorDetails,
|
||||
line_for_comparison: []const u8,
|
||||
@ -1108,7 +1126,7 @@ const CorrespondingLines = struct {
|
||||
.code_page = err_details.code_page,
|
||||
.file_reader = undefined,
|
||||
};
|
||||
corresponding_lines.file_reader = corresponding_lines.file.reader(file_reader_buf);
|
||||
corresponding_lines.file_reader = corresponding_lines.file.reader(io, file_reader_buf);
|
||||
errdefer corresponding_lines.deinit();
|
||||
|
||||
try corresponding_lines.writeLineFromStreamVerbatim(
|
||||
|
||||
@ -1,5 +1,9 @@
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
|
||||
const std = @import("std");
|
||||
const Io = std.Io;
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
||||
const removeComments = @import("comments.zig").removeComments;
|
||||
const parseAndRemoveLineCommands = @import("source_mapping.zig").parseAndRemoveLineCommands;
|
||||
const compile = @import("compile.zig").compile;
|
||||
@ -16,19 +20,18 @@ const aro = @import("aro");
|
||||
const compiler_util = @import("../util.zig");
|
||||
|
||||
pub fn main() !void {
|
||||
var gpa: std.heap.GeneralPurposeAllocator(.{}) = .init;
|
||||
defer std.debug.assert(gpa.deinit() == .ok);
|
||||
const allocator = gpa.allocator();
|
||||
var debug_allocator: std.heap.DebugAllocator(.{}) = .init;
|
||||
defer std.debug.assert(debug_allocator.deinit() == .ok);
|
||||
const gpa = debug_allocator.allocator();
|
||||
|
||||
var arena_state = std.heap.ArenaAllocator.init(allocator);
|
||||
var arena_state = std.heap.ArenaAllocator.init(gpa);
|
||||
defer arena_state.deinit();
|
||||
const arena = arena_state.allocator();
|
||||
|
||||
const stderr = std.fs.File.stderr();
|
||||
const stderr_config = std.Io.tty.detectConfig(stderr);
|
||||
|
||||
const args = try std.process.argsAlloc(allocator);
|
||||
defer std.process.argsFree(allocator, args);
|
||||
const args = try std.process.argsAlloc(arena);
|
||||
|
||||
if (args.len < 2) {
|
||||
try renderErrorMessage(std.debug.lockStderrWriter(&.{}), stderr_config, .err, "expected zig lib dir as first argument", .{});
|
||||
@ -59,11 +62,11 @@ pub fn main() !void {
|
||||
};
|
||||
|
||||
var options = options: {
|
||||
var cli_diagnostics = cli.Diagnostics.init(allocator);
|
||||
var cli_diagnostics = cli.Diagnostics.init(gpa);
|
||||
defer cli_diagnostics.deinit();
|
||||
var options = cli.parse(allocator, cli_args, &cli_diagnostics) catch |err| switch (err) {
|
||||
var options = cli.parse(gpa, cli_args, &cli_diagnostics) catch |err| switch (err) {
|
||||
error.ParseError => {
|
||||
try error_handler.emitCliDiagnostics(allocator, cli_args, &cli_diagnostics);
|
||||
try error_handler.emitCliDiagnostics(gpa, cli_args, &cli_diagnostics);
|
||||
std.process.exit(1);
|
||||
},
|
||||
else => |e| return e,
|
||||
@ -84,6 +87,10 @@ pub fn main() !void {
|
||||
};
|
||||
defer options.deinit();
|
||||
|
||||
var threaded: std.Io.Threaded = .init(gpa);
|
||||
defer threaded.deinit();
|
||||
const io = threaded.io();
|
||||
|
||||
if (options.print_help_and_exit) {
|
||||
try cli.writeUsage(stdout, "zig rc");
|
||||
try stdout.flush();
|
||||
@ -99,12 +106,13 @@ pub fn main() !void {
|
||||
try stdout.flush();
|
||||
}
|
||||
|
||||
var dependencies = Dependencies.init(allocator);
|
||||
var dependencies = Dependencies.init(gpa);
|
||||
defer dependencies.deinit();
|
||||
const maybe_dependencies: ?*Dependencies = if (options.depfile_path != null) &dependencies else null;
|
||||
|
||||
var include_paths = LazyIncludePaths{
|
||||
.arena = arena,
|
||||
.io = io,
|
||||
.auto_includes_option = options.auto_includes,
|
||||
.zig_lib_dir = zig_lib_dir,
|
||||
.target_machine_type = options.coff_options.target,
|
||||
@ -112,12 +120,12 @@ pub fn main() !void {
|
||||
|
||||
const full_input = full_input: {
|
||||
if (options.input_format == .rc and options.preprocess != .no) {
|
||||
var preprocessed_buf: std.Io.Writer.Allocating = .init(allocator);
|
||||
var preprocessed_buf: std.Io.Writer.Allocating = .init(gpa);
|
||||
errdefer preprocessed_buf.deinit();
|
||||
|
||||
// We're going to throw away everything except the final preprocessed output anyway,
|
||||
// so we can use a scoped arena for everything else.
|
||||
var aro_arena_state = std.heap.ArenaAllocator.init(allocator);
|
||||
var aro_arena_state = std.heap.ArenaAllocator.init(gpa);
|
||||
defer aro_arena_state.deinit();
|
||||
const aro_arena = aro_arena_state.allocator();
|
||||
|
||||
@ -129,12 +137,12 @@ pub fn main() !void {
|
||||
.color = stderr_config,
|
||||
} } },
|
||||
true => .{ .output = .{ .to_list = .{
|
||||
.arena = .init(allocator),
|
||||
.arena = .init(gpa),
|
||||
} } },
|
||||
};
|
||||
defer diagnostics.deinit();
|
||||
|
||||
var comp = aro.Compilation.init(aro_arena, aro_arena, &diagnostics, std.fs.cwd());
|
||||
var comp = aro.Compilation.init(aro_arena, aro_arena, io, &diagnostics, std.fs.cwd());
|
||||
defer comp.deinit();
|
||||
|
||||
var argv: std.ArrayList([]const u8) = .empty;
|
||||
@ -159,20 +167,20 @@ pub fn main() !void {
|
||||
|
||||
preprocess.preprocess(&comp, &preprocessed_buf.writer, argv.items, maybe_dependencies) catch |err| switch (err) {
|
||||
error.GeneratedSourceError => {
|
||||
try error_handler.emitAroDiagnostics(allocator, "failed during preprocessor setup (this is always a bug)", &comp);
|
||||
try error_handler.emitAroDiagnostics(gpa, "failed during preprocessor setup (this is always a bug)", &comp);
|
||||
std.process.exit(1);
|
||||
},
|
||||
// ArgError can occur if e.g. the .rc file is not found
|
||||
error.ArgError, error.PreprocessError => {
|
||||
try error_handler.emitAroDiagnostics(allocator, "failed during preprocessing", &comp);
|
||||
try error_handler.emitAroDiagnostics(gpa, "failed during preprocessing", &comp);
|
||||
std.process.exit(1);
|
||||
},
|
||||
error.FileTooBig => {
|
||||
try error_handler.emitMessage(allocator, .err, "failed during preprocessing: maximum file size exceeded", .{});
|
||||
try error_handler.emitMessage(gpa, .err, "failed during preprocessing: maximum file size exceeded", .{});
|
||||
std.process.exit(1);
|
||||
},
|
||||
error.WriteFailed => {
|
||||
try error_handler.emitMessage(allocator, .err, "failed during preprocessing: error writing the preprocessed output", .{});
|
||||
try error_handler.emitMessage(gpa, .err, "failed during preprocessing: error writing the preprocessed output", .{});
|
||||
std.process.exit(1);
|
||||
},
|
||||
error.OutOfMemory => |e| return e,
|
||||
@ -182,22 +190,22 @@ pub fn main() !void {
|
||||
} else {
|
||||
switch (options.input_source) {
|
||||
.stdio => |file| {
|
||||
var file_reader = file.reader(&.{});
|
||||
break :full_input file_reader.interface.allocRemaining(allocator, .unlimited) catch |err| {
|
||||
try error_handler.emitMessage(allocator, .err, "unable to read input from stdin: {s}", .{@errorName(err)});
|
||||
var file_reader = file.reader(io, &.{});
|
||||
break :full_input file_reader.interface.allocRemaining(gpa, .unlimited) catch |err| {
|
||||
try error_handler.emitMessage(gpa, .err, "unable to read input from stdin: {s}", .{@errorName(err)});
|
||||
std.process.exit(1);
|
||||
};
|
||||
},
|
||||
.filename => |input_filename| {
|
||||
break :full_input std.fs.cwd().readFileAlloc(input_filename, allocator, .unlimited) catch |err| {
|
||||
try error_handler.emitMessage(allocator, .err, "unable to read input file path '{s}': {s}", .{ input_filename, @errorName(err) });
|
||||
break :full_input std.fs.cwd().readFileAlloc(input_filename, gpa, .unlimited) catch |err| {
|
||||
try error_handler.emitMessage(gpa, .err, "unable to read input file path '{s}': {s}", .{ input_filename, @errorName(err) });
|
||||
std.process.exit(1);
|
||||
};
|
||||
},
|
||||
}
|
||||
}
|
||||
};
|
||||
defer allocator.free(full_input);
|
||||
defer gpa.free(full_input);
|
||||
|
||||
if (options.preprocess == .only) {
|
||||
switch (options.output_source) {
|
||||
@ -221,55 +229,55 @@ pub fn main() !void {
|
||||
}
|
||||
else if (options.input_format == .res)
|
||||
IoStream.fromIoSource(options.input_source, .input) catch |err| {
|
||||
try error_handler.emitMessage(allocator, .err, "unable to read res file path '{s}': {s}", .{ options.input_source.filename, @errorName(err) });
|
||||
try error_handler.emitMessage(gpa, .err, "unable to read res file path '{s}': {s}", .{ options.input_source.filename, @errorName(err) });
|
||||
std.process.exit(1);
|
||||
}
|
||||
else
|
||||
IoStream.fromIoSource(options.output_source, .output) catch |err| {
|
||||
try error_handler.emitMessage(allocator, .err, "unable to create output file '{s}': {s}", .{ options.output_source.filename, @errorName(err) });
|
||||
try error_handler.emitMessage(gpa, .err, "unable to create output file '{s}': {s}", .{ options.output_source.filename, @errorName(err) });
|
||||
std.process.exit(1);
|
||||
};
|
||||
defer res_stream.deinit(allocator);
|
||||
defer res_stream.deinit(gpa);
|
||||
|
||||
const res_data = res_data: {
|
||||
if (options.input_format != .res) {
|
||||
// Note: We still want to run this when no-preprocess is set because:
|
||||
// 1. We want to print accurate line numbers after removing multiline comments
|
||||
// 2. We want to be able to handle an already-preprocessed input with #line commands in it
|
||||
var mapping_results = parseAndRemoveLineCommands(allocator, full_input, full_input, .{ .initial_filename = options.input_source.filename }) catch |err| switch (err) {
|
||||
var mapping_results = parseAndRemoveLineCommands(gpa, full_input, full_input, .{ .initial_filename = options.input_source.filename }) catch |err| switch (err) {
|
||||
error.InvalidLineCommand => {
|
||||
// TODO: Maybe output the invalid line command
|
||||
try error_handler.emitMessage(allocator, .err, "invalid line command in the preprocessed source", .{});
|
||||
try error_handler.emitMessage(gpa, .err, "invalid line command in the preprocessed source", .{});
|
||||
if (options.preprocess == .no) {
|
||||
try error_handler.emitMessage(allocator, .note, "line commands must be of the format: #line <num> \"<path>\"", .{});
|
||||
try error_handler.emitMessage(gpa, .note, "line commands must be of the format: #line <num> \"<path>\"", .{});
|
||||
} else {
|
||||
try error_handler.emitMessage(allocator, .note, "this is likely to be a bug, please report it", .{});
|
||||
try error_handler.emitMessage(gpa, .note, "this is likely to be a bug, please report it", .{});
|
||||
}
|
||||
std.process.exit(1);
|
||||
},
|
||||
error.LineNumberOverflow => {
|
||||
// TODO: Better error message
|
||||
try error_handler.emitMessage(allocator, .err, "line number count exceeded maximum of {}", .{std.math.maxInt(usize)});
|
||||
try error_handler.emitMessage(gpa, .err, "line number count exceeded maximum of {}", .{std.math.maxInt(usize)});
|
||||
std.process.exit(1);
|
||||
},
|
||||
error.OutOfMemory => |e| return e,
|
||||
};
|
||||
defer mapping_results.mappings.deinit(allocator);
|
||||
defer mapping_results.mappings.deinit(gpa);
|
||||
|
||||
const default_code_page = options.default_code_page orelse .windows1252;
|
||||
const has_disjoint_code_page = hasDisjointCodePage(mapping_results.result, &mapping_results.mappings, default_code_page);
|
||||
|
||||
const final_input = try removeComments(mapping_results.result, mapping_results.result, &mapping_results.mappings);
|
||||
|
||||
var diagnostics = Diagnostics.init(allocator);
|
||||
var diagnostics = Diagnostics.init(gpa, io);
|
||||
defer diagnostics.deinit();
|
||||
|
||||
var output_buffer: [4096]u8 = undefined;
|
||||
var res_stream_writer = res_stream.source.writer(allocator, &output_buffer);
|
||||
var res_stream_writer = res_stream.source.writer(gpa, &output_buffer);
|
||||
defer res_stream_writer.deinit(&res_stream.source);
|
||||
const output_buffered_stream = res_stream_writer.interface();
|
||||
|
||||
compile(allocator, final_input, output_buffered_stream, .{
|
||||
compile(gpa, io, final_input, output_buffered_stream, .{
|
||||
.cwd = std.fs.cwd(),
|
||||
.diagnostics = &diagnostics,
|
||||
.source_mappings = &mapping_results.mappings,
|
||||
@ -287,7 +295,7 @@ pub fn main() !void {
|
||||
.warn_instead_of_error_on_invalid_code_page = options.warn_instead_of_error_on_invalid_code_page,
|
||||
}) catch |err| switch (err) {
|
||||
error.ParseError, error.CompileError => {
|
||||
try error_handler.emitDiagnostics(allocator, std.fs.cwd(), final_input, &diagnostics, mapping_results.mappings);
|
||||
try error_handler.emitDiagnostics(gpa, std.fs.cwd(), final_input, &diagnostics, mapping_results.mappings);
|
||||
// Delete the output file on error
|
||||
res_stream.cleanupAfterError();
|
||||
std.process.exit(1);
|
||||
@ -305,7 +313,7 @@ pub fn main() !void {
|
||||
// write the depfile
|
||||
if (options.depfile_path) |depfile_path| {
|
||||
var depfile = std.fs.cwd().createFile(depfile_path, .{}) catch |err| {
|
||||
try error_handler.emitMessage(allocator, .err, "unable to create depfile '{s}': {s}", .{ depfile_path, @errorName(err) });
|
||||
try error_handler.emitMessage(gpa, .err, "unable to create depfile '{s}': {s}", .{ depfile_path, @errorName(err) });
|
||||
std.process.exit(1);
|
||||
};
|
||||
defer depfile.close();
|
||||
@ -332,41 +340,41 @@ pub fn main() !void {
|
||||
|
||||
if (options.output_format != .coff) return;
|
||||
|
||||
break :res_data res_stream.source.readAll(allocator) catch |err| {
|
||||
try error_handler.emitMessage(allocator, .err, "unable to read res from '{s}': {s}", .{ res_stream.name, @errorName(err) });
|
||||
break :res_data res_stream.source.readAll(gpa, io) catch |err| {
|
||||
try error_handler.emitMessage(gpa, .err, "unable to read res from '{s}': {s}", .{ res_stream.name, @errorName(err) });
|
||||
std.process.exit(1);
|
||||
};
|
||||
};
|
||||
// No need to keep the res_data around after parsing the resources from it
|
||||
defer res_data.deinit(allocator);
|
||||
defer res_data.deinit(gpa);
|
||||
|
||||
std.debug.assert(options.output_format == .coff);
|
||||
|
||||
// TODO: Maybe use a buffered file reader instead of reading file into memory -> fbs
|
||||
var res_reader: std.Io.Reader = .fixed(res_data.bytes);
|
||||
break :resources cvtres.parseRes(allocator, &res_reader, .{ .max_size = res_data.bytes.len }) catch |err| {
|
||||
break :resources cvtres.parseRes(gpa, &res_reader, .{ .max_size = res_data.bytes.len }) catch |err| {
|
||||
// TODO: Better errors
|
||||
try error_handler.emitMessage(allocator, .err, "unable to parse res from '{s}': {s}", .{ res_stream.name, @errorName(err) });
|
||||
try error_handler.emitMessage(gpa, .err, "unable to parse res from '{s}': {s}", .{ res_stream.name, @errorName(err) });
|
||||
std.process.exit(1);
|
||||
};
|
||||
};
|
||||
defer resources.deinit();
|
||||
|
||||
var coff_stream = IoStream.fromIoSource(options.output_source, .output) catch |err| {
|
||||
try error_handler.emitMessage(allocator, .err, "unable to create output file '{s}': {s}", .{ options.output_source.filename, @errorName(err) });
|
||||
try error_handler.emitMessage(gpa, .err, "unable to create output file '{s}': {s}", .{ options.output_source.filename, @errorName(err) });
|
||||
std.process.exit(1);
|
||||
};
|
||||
defer coff_stream.deinit(allocator);
|
||||
defer coff_stream.deinit(gpa);
|
||||
|
||||
var coff_output_buffer: [4096]u8 = undefined;
|
||||
var coff_output_buffered_stream = coff_stream.source.writer(allocator, &coff_output_buffer);
|
||||
var coff_output_buffered_stream = coff_stream.source.writer(gpa, &coff_output_buffer);
|
||||
|
||||
var cvtres_diagnostics: cvtres.Diagnostics = .{ .none = {} };
|
||||
cvtres.writeCoff(allocator, coff_output_buffered_stream.interface(), resources.list.items, options.coff_options, &cvtres_diagnostics) catch |err| {
|
||||
cvtres.writeCoff(gpa, coff_output_buffered_stream.interface(), resources.list.items, options.coff_options, &cvtres_diagnostics) catch |err| {
|
||||
switch (err) {
|
||||
error.DuplicateResource => {
|
||||
const duplicate_resource = resources.list.items[cvtres_diagnostics.duplicate_resource];
|
||||
try error_handler.emitMessage(allocator, .err, "duplicate resource [id: {f}, type: {f}, language: {f}]", .{
|
||||
try error_handler.emitMessage(gpa, .err, "duplicate resource [id: {f}, type: {f}, language: {f}]", .{
|
||||
duplicate_resource.name_value,
|
||||
fmtResourceType(duplicate_resource.type_value),
|
||||
duplicate_resource.language,
|
||||
@ -374,8 +382,8 @@ pub fn main() !void {
|
||||
},
|
||||
error.ResourceDataTooLong => {
|
||||
const overflow_resource = resources.list.items[cvtres_diagnostics.duplicate_resource];
|
||||
try error_handler.emitMessage(allocator, .err, "resource has a data length that is too large to be written into a coff section", .{});
|
||||
try error_handler.emitMessage(allocator, .note, "the resource with the invalid size is [id: {f}, type: {f}, language: {f}]", .{
|
||||
try error_handler.emitMessage(gpa, .err, "resource has a data length that is too large to be written into a coff section", .{});
|
||||
try error_handler.emitMessage(gpa, .note, "the resource with the invalid size is [id: {f}, type: {f}, language: {f}]", .{
|
||||
overflow_resource.name_value,
|
||||
fmtResourceType(overflow_resource.type_value),
|
||||
overflow_resource.language,
|
||||
@ -383,15 +391,15 @@ pub fn main() !void {
|
||||
},
|
||||
error.TotalResourceDataTooLong => {
|
||||
const overflow_resource = resources.list.items[cvtres_diagnostics.duplicate_resource];
|
||||
try error_handler.emitMessage(allocator, .err, "total resource data exceeds the maximum of the coff 'size of raw data' field", .{});
|
||||
try error_handler.emitMessage(allocator, .note, "size overflow occurred when attempting to write this resource: [id: {f}, type: {f}, language: {f}]", .{
|
||||
try error_handler.emitMessage(gpa, .err, "total resource data exceeds the maximum of the coff 'size of raw data' field", .{});
|
||||
try error_handler.emitMessage(gpa, .note, "size overflow occurred when attempting to write this resource: [id: {f}, type: {f}, language: {f}]", .{
|
||||
overflow_resource.name_value,
|
||||
fmtResourceType(overflow_resource.type_value),
|
||||
overflow_resource.language,
|
||||
});
|
||||
},
|
||||
else => {
|
||||
try error_handler.emitMessage(allocator, .err, "unable to write coff output file '{s}': {s}", .{ coff_stream.name, @errorName(err) });
|
||||
try error_handler.emitMessage(gpa, .err, "unable to write coff output file '{s}': {s}", .{ coff_stream.name, @errorName(err) });
|
||||
},
|
||||
}
|
||||
// Delete the output file on error
|
||||
@ -423,7 +431,7 @@ const IoStream = struct {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn deinit(self: *IoStream, allocator: std.mem.Allocator) void {
|
||||
pub fn deinit(self: *IoStream, allocator: Allocator) void {
|
||||
self.source.deinit(allocator);
|
||||
}
|
||||
|
||||
@ -458,7 +466,7 @@ const IoStream = struct {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn deinit(self: *Source, allocator: std.mem.Allocator) void {
|
||||
pub fn deinit(self: *Source, allocator: Allocator) void {
|
||||
switch (self.*) {
|
||||
.file => |file| file.close(),
|
||||
.stdio => {},
|
||||
@ -471,18 +479,18 @@ const IoStream = struct {
|
||||
bytes: []const u8,
|
||||
needs_free: bool,
|
||||
|
||||
pub fn deinit(self: Data, allocator: std.mem.Allocator) void {
|
||||
pub fn deinit(self: Data, allocator: Allocator) void {
|
||||
if (self.needs_free) {
|
||||
allocator.free(self.bytes);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
pub fn readAll(self: Source, allocator: std.mem.Allocator) !Data {
|
||||
pub fn readAll(self: Source, allocator: Allocator, io: Io) !Data {
|
||||
return switch (self) {
|
||||
inline .file, .stdio => |file| .{
|
||||
.bytes = b: {
|
||||
var file_reader = file.reader(&.{});
|
||||
var file_reader = file.reader(io, &.{});
|
||||
break :b try file_reader.interface.allocRemaining(allocator, .unlimited);
|
||||
},
|
||||
.needs_free = true,
|
||||
@ -496,7 +504,7 @@ const IoStream = struct {
|
||||
file: std.fs.File.Writer,
|
||||
allocating: std.Io.Writer.Allocating,
|
||||
|
||||
pub const Error = std.mem.Allocator.Error || std.fs.File.WriteError;
|
||||
pub const Error = Allocator.Error || std.fs.File.WriteError;
|
||||
|
||||
pub fn interface(this: *@This()) *std.Io.Writer {
|
||||
return switch (this.*) {
|
||||
@ -514,7 +522,7 @@ const IoStream = struct {
|
||||
}
|
||||
};
|
||||
|
||||
pub fn writer(source: *Source, allocator: std.mem.Allocator, buffer: []u8) Writer {
|
||||
pub fn writer(source: *Source, allocator: Allocator, buffer: []u8) Writer {
|
||||
return switch (source.*) {
|
||||
.file, .stdio => |file| .{ .file = file.writer(buffer) },
|
||||
.memory => |*list| .{ .allocating = .fromArrayList(allocator, list) },
|
||||
@ -525,17 +533,20 @@ const IoStream = struct {
|
||||
};
|
||||
|
||||
const LazyIncludePaths = struct {
|
||||
arena: std.mem.Allocator,
|
||||
arena: Allocator,
|
||||
io: Io,
|
||||
auto_includes_option: cli.Options.AutoIncludes,
|
||||
zig_lib_dir: []const u8,
|
||||
target_machine_type: std.coff.IMAGE.FILE.MACHINE,
|
||||
resolved_include_paths: ?[]const []const u8 = null,
|
||||
|
||||
pub fn get(self: *LazyIncludePaths, error_handler: *ErrorHandler) ![]const []const u8 {
|
||||
const io = self.io;
|
||||
|
||||
if (self.resolved_include_paths) |include_paths|
|
||||
return include_paths;
|
||||
|
||||
return getIncludePaths(self.arena, self.auto_includes_option, self.zig_lib_dir, self.target_machine_type) catch |err| switch (err) {
|
||||
return getIncludePaths(self.arena, io, self.auto_includes_option, self.zig_lib_dir, self.target_machine_type) catch |err| switch (err) {
|
||||
error.OutOfMemory => |e| return e,
|
||||
else => |e| {
|
||||
switch (e) {
|
||||
@ -556,7 +567,13 @@ const LazyIncludePaths = struct {
|
||||
}
|
||||
};
|
||||
|
||||
fn getIncludePaths(arena: std.mem.Allocator, auto_includes_option: cli.Options.AutoIncludes, zig_lib_dir: []const u8, target_machine_type: std.coff.IMAGE.FILE.MACHINE) ![]const []const u8 {
|
||||
fn getIncludePaths(
|
||||
arena: Allocator,
|
||||
io: Io,
|
||||
auto_includes_option: cli.Options.AutoIncludes,
|
||||
zig_lib_dir: []const u8,
|
||||
target_machine_type: std.coff.IMAGE.FILE.MACHINE,
|
||||
) ![]const []const u8 {
|
||||
if (auto_includes_option == .none) return &[_][]const u8{};
|
||||
|
||||
const includes_arch: std.Target.Cpu.Arch = switch (target_machine_type) {
|
||||
@ -626,7 +643,7 @@ fn getIncludePaths(arena: std.mem.Allocator, auto_includes_option: cli.Options.A
|
||||
.cpu_arch = includes_arch,
|
||||
.abi = .gnu,
|
||||
};
|
||||
const target = std.zig.resolveTargetQueryOrFatal(target_query);
|
||||
const target = std.zig.resolveTargetQueryOrFatal(io, target_query);
|
||||
const is_native_abi = target_query.isNativeAbi();
|
||||
const detected_libc = std.zig.LibCDirs.detect(arena, zig_lib_dir, &target, is_native_abi, true, null) catch |err| switch (err) {
|
||||
error.OutOfMemory => |e| return e,
|
||||
@ -647,7 +664,7 @@ const ErrorHandler = union(enum) {
|
||||
|
||||
pub fn emitCliDiagnostics(
|
||||
self: *ErrorHandler,
|
||||
allocator: std.mem.Allocator,
|
||||
allocator: Allocator,
|
||||
args: []const []const u8,
|
||||
diagnostics: *cli.Diagnostics,
|
||||
) !void {
|
||||
@ -666,7 +683,7 @@ const ErrorHandler = union(enum) {
|
||||
|
||||
pub fn emitAroDiagnostics(
|
||||
self: *ErrorHandler,
|
||||
allocator: std.mem.Allocator,
|
||||
allocator: Allocator,
|
||||
fail_msg: []const u8,
|
||||
comp: *aro.Compilation,
|
||||
) !void {
|
||||
@ -692,7 +709,7 @@ const ErrorHandler = union(enum) {
|
||||
|
||||
pub fn emitDiagnostics(
|
||||
self: *ErrorHandler,
|
||||
allocator: std.mem.Allocator,
|
||||
allocator: Allocator,
|
||||
cwd: std.fs.Dir,
|
||||
source: []const u8,
|
||||
diagnostics: *Diagnostics,
|
||||
@ -713,7 +730,7 @@ const ErrorHandler = union(enum) {
|
||||
|
||||
pub fn emitMessage(
|
||||
self: *ErrorHandler,
|
||||
allocator: std.mem.Allocator,
|
||||
allocator: Allocator,
|
||||
msg_type: @import("utils.zig").ErrorMessageType,
|
||||
comptime format: []const u8,
|
||||
args: anytype,
|
||||
@ -738,7 +755,7 @@ const ErrorHandler = union(enum) {
|
||||
};
|
||||
|
||||
fn cliDiagnosticsToErrorBundle(
|
||||
gpa: std.mem.Allocator,
|
||||
gpa: Allocator,
|
||||
diagnostics: *cli.Diagnostics,
|
||||
) !ErrorBundle {
|
||||
@branchHint(.cold);
|
||||
@ -783,7 +800,7 @@ fn cliDiagnosticsToErrorBundle(
|
||||
}
|
||||
|
||||
fn diagnosticsToErrorBundle(
|
||||
gpa: std.mem.Allocator,
|
||||
gpa: Allocator,
|
||||
source: []const u8,
|
||||
diagnostics: *Diagnostics,
|
||||
mappings: SourceMappings,
|
||||
@ -870,7 +887,7 @@ fn diagnosticsToErrorBundle(
|
||||
return try bundle.toOwnedBundle("");
|
||||
}
|
||||
|
||||
fn errorStringToErrorBundle(allocator: std.mem.Allocator, comptime format: []const u8, args: anytype) !ErrorBundle {
|
||||
fn errorStringToErrorBundle(allocator: Allocator, comptime format: []const u8, args: anytype) !ErrorBundle {
|
||||
@branchHint(.cold);
|
||||
var bundle: ErrorBundle.Wip = undefined;
|
||||
try bundle.init(allocator);
|
||||
|
||||
@ -26,7 +26,11 @@ pub const UncheckedSliceWriter = struct {
|
||||
/// Cross-platform 'std.fs.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: std.fs.Dir, path: []const u8, flags: std.fs.File.OpenFlags) std.fs.File.OpenError!std.fs.File {
|
||||
pub fn openFileNotDir(
|
||||
cwd: std.fs.Dir,
|
||||
path: []const u8,
|
||||
flags: std.fs.File.OpenFlags,
|
||||
) (std.fs.File.OpenError || std.fs.File.StatError)!std.fs.File {
|
||||
const file = try cwd.openFile(path, flags);
|
||||
errdefer file.close();
|
||||
// https://github.com/ziglang/zig/issues/5732
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user