test-standalone: update more cases to new main API

This commit is contained in:
Andrew Kelley
2026-01-02 17:57:54 -08:00
parent 1b56686012
commit bf74827ddb
41 changed files with 346 additions and 416 deletions
+11 -10
View File
@@ -74,9 +74,7 @@ pub const Environment = struct {
pub const default: @This() = .{ .provided = 0 }; pub const default: @This() = .{ .provided = 0 };
}; };
/// Load all of the environment variables using the std.process API. Do not use if using Aro as a shared library on Linux without libc pub fn loadAll(allocator: std.mem.Allocator, environ_map: *const std.process.Environ.Map) !Environment {
/// See https://github.com/ziglang/zig/issues/4524
pub fn loadAll(allocator: std.mem.Allocator) !Environment {
var env: Environment = .{}; var env: Environment = .{};
errdefer env.deinit(allocator); errdefer env.deinit(allocator);
@@ -85,11 +83,7 @@ pub const Environment = struct {
var env_var_buf: [field.name.len]u8 = undefined; var env_var_buf: [field.name.len]u8 = undefined;
const env_var_name = std.ascii.upperString(&env_var_buf, field.name); const env_var_name = std.ascii.upperString(&env_var_buf, field.name);
const val: ?[]const u8 = std.process.getEnvVarOwned(allocator, env_var_name) catch |err| switch (err) { const val: ?[]const u8 = if (environ_map.get(env_var_name)) |v| try allocator.dupe(u8, v) else null;
error.OutOfMemory => |e| return e,
error.EnvironmentVariableNotFound => null,
error.InvalidWtf8 => null,
};
@field(env, field.name) = val; @field(env, field.name) = val;
} }
return env; return env;
@@ -193,13 +187,20 @@ pub fn init(gpa: Allocator, arena: Allocator, io: Io, diagnostics: *Diagnostics,
/// Initialize Compilation with default environment, /// Initialize Compilation with default environment,
/// pragma handlers and emulation mode set to target. /// pragma handlers and emulation mode set to target.
pub fn initDefault(gpa: Allocator, arena: Allocator, io: Io, diagnostics: *Diagnostics, cwd: Io.Dir) !Compilation { pub fn initDefault(
gpa: Allocator,
arena: Allocator,
io: Io,
diagnostics: *Diagnostics,
cwd: Io.Dir,
env_map: *const std.process.Environ.Map,
) !Compilation {
var comp: Compilation = .{ var comp: Compilation = .{
.gpa = gpa, .gpa = gpa,
.arena = arena, .arena = arena,
.io = io, .io = io,
.diagnostics = diagnostics, .diagnostics = diagnostics,
.environment = try Environment.loadAll(gpa), .environment = try Environment.loadAll(gpa, env_map),
.cwd = cwd, .cwd = cwd,
}; };
errdefer comp.deinit(); errdefer comp.deinit();
+24 -16
View File
@@ -1250,21 +1250,25 @@ fn getOutFileName(d: *Driver, source: Source, buf: *[std.fs.max_name_bytes]u8) !
} }
fn invokeAssembler(d: *Driver, tc: *Toolchain, input_path: []const u8, output_path: []const u8) !void { fn invokeAssembler(d: *Driver, tc: *Toolchain, input_path: []const u8, output_path: []const u8) !void {
const io = d.comp.io;
var assembler_path_buf: [std.fs.max_path_bytes]u8 = undefined; var assembler_path_buf: [std.fs.max_path_bytes]u8 = undefined;
const assembler_path = try tc.getAssemblerPath(&assembler_path_buf); const assembler_path = try tc.getAssemblerPath(&assembler_path_buf);
const argv = [_][]const u8{ assembler_path, input_path, "-o", output_path }; const argv = [_][]const u8{ assembler_path, input_path, "-o", output_path };
var child = std.process.Child.init(&argv, d.comp.gpa); var child = std.process.spawn(io, .{
// TODO handle better .argv = &argv,
child.stdin_behavior = .inherit; // TODO handle better
child.stdout_behavior = .inherit; .stdin = .inherit,
child.stderr_behavior = .inherit; .stdout = .inherit,
.stderr = .inherit,
const term = child.spawnAndWait() catch |er| { }) catch |er| {
return d.fatal("unable to spawn linker: {s}", .{errorDescription(er)}); return d.fatal("unable to spawn linker: {s}", .{errorDescription(er)});
}; };
const term = child.wait(io) catch |er| {
return d.fatal("unable to wait linker: {s}", .{errorDescription(er)});
};
switch (term) { switch (term) {
.Exited => |code| if (code != 0) { .exited => |code| if (code != 0) {
const e = d.fatal("assembler exited with an error code", .{}); const e = d.fatal("assembler exited with an error code", .{});
return e; return e;
}, },
@@ -1490,6 +1494,7 @@ fn dumpLinkerArgs(w: *std.Io.Writer, items: []const []const u8) !void {
/// **MAY call `exit` if `fast_exit` is set.** /// **MAY call `exit` if `fast_exit` is set.**
pub fn invokeLinker(d: *Driver, tc: *Toolchain, comptime fast_exit: bool) Compilation.Error!void { pub fn invokeLinker(d: *Driver, tc: *Toolchain, comptime fast_exit: bool) Compilation.Error!void {
const gpa = d.comp.gpa; const gpa = d.comp.gpa;
const io = d.comp.io;
var argv: std.ArrayList([]const u8) = .empty; var argv: std.ArrayList([]const u8) = .empty;
defer argv.deinit(gpa); defer argv.deinit(gpa);
@@ -1506,17 +1511,20 @@ pub fn invokeLinker(d: *Driver, tc: *Toolchain, comptime fast_exit: bool) Compil
return d.fatal("unable to dump linker args: {s}", .{errorDescription(stdout.err.?)}); return d.fatal("unable to dump linker args: {s}", .{errorDescription(stdout.err.?)});
}; };
} }
var child = std.process.Child.init(argv.items, d.comp.gpa); var child = std.process.spawn(io, .{
// TODO handle better .argv = argv.items,
child.stdin_behavior = .inherit; // TODO handle better
child.stdout_behavior = .inherit; .stdin = .inherit,
child.stderr_behavior = .inherit; .stdout = .inherit,
.stderr = .inherit,
const term = child.spawnAndWait() catch |er| { }) catch |er| {
return d.fatal("unable to spawn linker: {s}", .{errorDescription(er)}); return d.fatal("unable to spawn linker: {s}", .{errorDescription(er)});
}; };
const term = child.wait(io) catch |er| {
return d.fatal("unable to wait linker: {s}", .{errorDescription(er)});
};
switch (term) { switch (term) {
.Exited => |code| if (code != 0) { .exited => |code| if (code != 0) {
const e = d.fatal("linker exited with an error code", .{}); const e = d.fatal("linker exited with an error code", .{});
if (fast_exit) d.exitWithCleanup(code); if (fast_exit) d.exitWithCleanup(code);
return e; return e;
+2 -3
View File
@@ -80,7 +80,7 @@ pub const Dependencies = struct {
} }
}; };
pub fn compile(allocator: Allocator, io: Io, 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, env_map: *const std.process.Environ.Map) !void {
var lexer = lex.Lexer.init(source, .{ var lexer = lex.Lexer.init(source, .{
.default_code_page = options.default_code_page, .default_code_page = options.default_code_page,
.source_mappings = options.source_mappings, .source_mappings = options.source_mappings,
@@ -148,8 +148,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) }); try search_dirs.append(allocator, .{ .dir = dir, .path = try allocator.dupe(u8, system_include_path) });
} }
if (!options.ignore_include_env_var) { if (!options.ignore_include_env_var) {
const INCLUDE = std.process.getEnvVarOwned(allocator, "INCLUDE") catch ""; const INCLUDE = env_map.get("INCLUDE") orelse "";
defer allocator.free(INCLUDE);
// The only precedence here is llvm-rc which also uses the platform-specific // 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. // delimiter. There's no precedence set by `rc.exe` since it's Windows-only.
+7 -4
View File
@@ -24,6 +24,9 @@ pub fn main(init: std.process.Init.Minimal) !void {
defer std.debug.assert(debug_allocator.deinit() == .ok); defer std.debug.assert(debug_allocator.deinit() == .ok);
const gpa = debug_allocator.allocator(); const gpa = debug_allocator.allocator();
var env_map = try init.environ.createMap(gpa);
defer env_map.deinit();
var threaded: std.Io.Threaded = .init(gpa, .{ var threaded: std.Io.Threaded = .init(gpa, .{
.environ = init.environ, .environ = init.environ,
.argv0 = .init(init.args), .argv0 = .init(init.args),
@@ -148,8 +151,8 @@ pub fn main(init: std.process.Init.Minimal) !void {
defer argv.deinit(aro_arena); defer argv.deinit(aro_arena);
try argv.append(aro_arena, "arocc"); // dummy command name try argv.append(aro_arena, "arocc"); // dummy command name
const resolved_include_paths = try include_paths.get(&error_handler); const resolved_include_paths = try include_paths.get(&error_handler, &env_map);
try preprocess.appendAroArgs(aro_arena, &argv, options, resolved_include_paths); try preprocess.appendAroArgs(aro_arena, &argv, options, resolved_include_paths, &env_map);
try argv.append(aro_arena, switch (options.input_source) { try argv.append(aro_arena, switch (options.input_source) {
.stdio => "-", .stdio => "-",
.filename => |filename| filename, .filename => |filename| filename,
@@ -283,7 +286,7 @@ pub fn main(init: std.process.Init.Minimal) !void {
.dependencies = maybe_dependencies, .dependencies = maybe_dependencies,
.ignore_include_env_var = options.ignore_include_env_var, .ignore_include_env_var = options.ignore_include_env_var,
.extra_include_paths = options.extra_include_paths.items, .extra_include_paths = options.extra_include_paths.items,
.system_include_paths = try include_paths.get(&error_handler), .system_include_paths = try include_paths.get(&error_handler, &env_map),
.default_language_id = options.default_language_id, .default_language_id = options.default_language_id,
.default_code_page = default_code_page, .default_code_page = default_code_page,
.disjoint_code_page = has_disjoint_code_page, .disjoint_code_page = has_disjoint_code_page,
@@ -292,7 +295,7 @@ pub fn main(init: std.process.Init.Minimal) !void {
.max_string_literal_codepoints = options.max_string_literal_codepoints, .max_string_literal_codepoints = options.max_string_literal_codepoints,
.silent_duplicate_control_ids = options.silent_duplicate_control_ids, .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, .warn_instead_of_error_on_invalid_code_page = options.warn_instead_of_error_on_invalid_code_page,
}) catch |err| switch (err) { }, &env_map) catch |err| switch (err) {
error.ParseError, error.CompileError => { error.ParseError, error.CompileError => {
try error_handler.emitDiagnostics(gpa, Io.Dir.cwd(), final_input, &diagnostics, mapping_results.mappings); try error_handler.emitDiagnostics(gpa, Io.Dir.cwd(), final_input, &diagnostics, mapping_results.mappings);
// Delete the output file on error // Delete the output file on error
+2 -2
View File
@@ -86,7 +86,7 @@ fn hasAnyErrors(comp: *aro.Compilation) bool {
/// `arena` is used for temporary -D argument strings and the INCLUDE environment variable. /// `arena` is used for temporary -D argument strings and the INCLUDE environment variable.
/// The arena should be kept alive at least as long as `argv`. /// 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) !void { pub fn appendAroArgs(arena: Allocator, argv: *std.ArrayList([]const u8), options: cli.Options, system_include_paths: []const []const u8, env_map: *const std.process.Environ.Map) !void {
try argv.appendSlice(arena, &.{ try argv.appendSlice(arena, &.{
"-E", "-E",
"--comments", "--comments",
@@ -109,7 +109,7 @@ pub fn appendAroArgs(arena: Allocator, argv: *std.ArrayList([]const u8), options
} }
if (!options.ignore_include_env_var) { if (!options.ignore_include_env_var) {
const INCLUDE = std.process.getEnvVarOwned(arena, "INCLUDE") catch ""; const INCLUDE = env_map.get("INCLUDE") orelse "";
// The only precedence here is llvm-rc which also uses the platform-specific // 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. // delimiter. There's no precedence set by `rc.exe` since it's Windows-only.
+29 -30
View File
@@ -13,6 +13,7 @@ pub fn main(init: std.process.Init) u8 {
const gpa = init.gpa; const gpa = init.gpa;
const arena = init.arena.allocator(); const arena = init.arena.allocator();
const io = init.io; const io = init.io;
const env_map = init.env_map;
const args = init.minimal.args.toSlice(arena) catch { const args = init.minimal.args.toSlice(arena) catch {
std.debug.print("ran out of memory allocating arguments\n", .{}); std.debug.print("ran out of memory allocating arguments\n", .{});
@@ -25,8 +26,8 @@ pub fn main(init: std.process.Init) u8 {
zig_integration = true; zig_integration = true;
} }
const NO_COLOR = std.zig.EnvVar.NO_COLOR.isSet(init.env_map); const NO_COLOR = std.zig.EnvVar.NO_COLOR.isSet(env_map);
const CLICOLOR_FORCE = std.zig.EnvVar.CLICOLOR_FORCE.isSet(init.env_map); const CLICOLOR_FORCE = std.zig.EnvVar.CLICOLOR_FORCE.isSet(env_map);
var stderr_buf: [1024]u8 = undefined; var stderr_buf: [1024]u8 = undefined;
var stderr = Io.File.stderr().writer(io, &stderr_buf); var stderr = Io.File.stderr().writer(io, &stderr_buf);
@@ -41,7 +42,7 @@ pub fn main(init: std.process.Init) u8 {
}; };
defer diagnostics.deinit(); defer diagnostics.deinit();
var comp = aro.Compilation.initDefault(gpa, arena, io, &diagnostics, Io.Dir.cwd()) catch |err| switch (err) { var comp = aro.Compilation.initDefault(gpa, arena, io, &diagnostics, .cwd(), env_map) catch |err| switch (err) {
error.OutOfMemory => { error.OutOfMemory => {
std.debug.print("ran out of memory initializing C compilation\n", .{}); std.debug.print("ran out of memory initializing C compilation\n", .{});
if (fast_exit) process.exit(1); if (fast_exit) process.exit(1);
@@ -114,43 +115,41 @@ pub const usage =
\\ \\
; ;
fn translate(d: *aro.Driver, tc: *aro.Toolchain, args: [][:0]u8, zig_integration: bool) !void { fn translate(d: *aro.Driver, tc: *aro.Toolchain, args: []const [:0]const u8, zig_integration: bool) !void {
const gpa = d.comp.gpa; const gpa = d.comp.gpa;
const io = d.comp.io; const io = d.comp.io;
const aro_args = args: { var aro_args: std.ArrayList([:0]const u8) = .empty;
var i: usize = 0; defer aro_args.deinit(gpa);
for (args) |arg| {
args[i] = arg; for (args, 0..) |arg, i| {
if (mem.eql(u8, arg, "--help")) { if (mem.eql(u8, arg, "--help")) {
var stdout_buf: [512]u8 = undefined; var stdout_buf: [512]u8 = undefined;
var stdout = Io.File.stdout().writer(io, &stdout_buf); var stdout = Io.File.stdout().writer(io, &stdout_buf);
try stdout.interface.print(usage, .{args[0]}); try stdout.interface.print(usage, .{args[0]});
try stdout.interface.flush(); try stdout.interface.flush();
return; return;
} else if (mem.eql(u8, arg, "--version")) { } else if (mem.eql(u8, arg, "--version")) {
var stdout_buf: [512]u8 = undefined; var stdout_buf: [512]u8 = undefined;
var stdout = Io.File.stdout().writer(io, &stdout_buf); var stdout = Io.File.stdout().writer(io, &stdout_buf);
// TODO add version // TODO add version
try stdout.interface.writeAll("0.0.0-dev\n"); try stdout.interface.writeAll("0.0.0-dev\n");
try stdout.interface.flush(); try stdout.interface.flush();
return; return;
} else if (mem.eql(u8, arg, "--zig-integration")) { } else if (mem.eql(u8, arg, "--zig-integration")) {
if (i != 1 or !zig_integration) if (i != 1 or !zig_integration)
return d.fatal("--zig-integration must be the first argument", .{}); return d.fatal("--zig-integration must be the first argument", .{});
} else { } else {
i += 1; try aro_args.append(gpa, arg);
}
} }
break :args args[0..i]; }
};
const user_macros = macros: { const user_macros = macros: {
var macro_buf: std.ArrayList(u8) = .empty; var macro_buf: std.ArrayList(u8) = .empty;
defer macro_buf.deinit(gpa); defer macro_buf.deinit(gpa);
var discard_buf: [256]u8 = undefined; var discard_buf: [256]u8 = undefined;
var discarding: std.Io.Writer.Discarding = .init(&discard_buf); var discarding: std.Io.Writer.Discarding = .init(&discard_buf);
assert(!try d.parseArgs(&discarding.writer, &macro_buf, aro_args)); assert(!try d.parseArgs(&discarding.writer, &macro_buf, aro_args.items));
if (macro_buf.items.len > std.math.maxInt(u32)) { if (macro_buf.items.len > std.math.maxInt(u32)) {
return d.fatal("user provided macro source exceeded max size", .{}); return d.fatal("user provided macro source exceeded max size", .{});
} }
+10 -8
View File
@@ -9,7 +9,7 @@ pub fn main(init: std.process.Init.Minimal) !void {
}; };
const gpa = gpa_state.allocator(); const gpa = gpa_state.allocator();
var it = try init.iterateAllocator(gpa); var it = try init.args.iterateAllocator(gpa);
defer it.deinit(); defer it.deinit();
_ = it.next() orelse unreachable; // skip binary name _ = it.next() orelse unreachable; // skip binary name
const child_path, const needs_free = child_path: { const child_path, const needs_free = child_path: {
@@ -28,11 +28,13 @@ pub fn main(init: std.process.Init.Minimal) !void {
defer threaded.deinit(); defer threaded.deinit();
const io = threaded.io(); const io = threaded.io();
var child = std.process.Child.init(&.{ child_path, "hello arg" }, gpa); var child = try std.process.spawn(.{
child.stdin_behavior = .pipe; .argv = &.{ child_path, "hello arg" },
child.stdout_behavior = .pipe; .stdin = .pipe,
child.stderr_behavior = .inherit; .stdout = .pipe,
try child.spawn(io); .stderr = .inherit,
});
const child_stdin = child.stdin.?; const child_stdin = child.stdin.?;
try child_stdin.writeStreamingAll(io, "hello from stdin"); // verified in child try child_stdin.writeStreamingAll(io, "hello from stdin"); // verified in child
child_stdin.close(io); child_stdin.close(io);
@@ -47,7 +49,7 @@ pub fn main(init: std.process.Init.Minimal) !void {
} }
switch (try child.wait(io)) { switch (try child.wait(io)) {
.Exited => |code| { .exited => |code| {
const child_ok_code = 42; // set by child if no test errors const child_ok_code = 42; // set by child if no test errors
if (code != child_ok_code) { if (code != child_ok_code) {
testError(io, "child exit code: {d}; want {d}", .{ code, child_ok_code }); testError(io, "child exit code: {d}; want {d}", .{ code, child_ok_code });
@@ -60,7 +62,7 @@ pub fn main(init: std.process.Init.Minimal) !void {
// Check that FileNotFound is consistent across platforms when trying to spawn an executable that doesn't exist // Check that FileNotFound is consistent across platforms when trying to spawn an executable that doesn't exist
const missing_child_path = try std.mem.concat(gpa, u8, &.{ child_path, "_intentionally_missing" }); const missing_child_path = try std.mem.concat(gpa, u8, &.{ child_path, "_intentionally_missing" });
defer gpa.free(missing_child_path); defer gpa.free(missing_child_path);
try std.testing.expectError(error.FileNotFound, std.process.Child.run(gpa, io, .{ .argv = &.{missing_child_path} })); try std.testing.expectError(error.FileNotFound, std.process.run(gpa, io, .{ .argv = &.{missing_child_path} }));
} }
var parent_test_error = false; var parent_test_error = false;
+4 -8
View File
@@ -1,16 +1,12 @@
pub fn main() !void { pub fn main(init: std.process.Init) !void {
var arena_state: std.heap.ArenaAllocator = .init(std.heap.page_allocator); const arena = init.arena.allocator();
defer arena_state.deinit(); const io = init.io;
const arena = arena_state.allocator(); const args = try init.minimal.args.toSlice(arena);
const args = try std.process.argsAlloc(arena);
if (args.len != 3) return error.BadUsage; if (args.len != 3) return error.BadUsage;
const actual_path = args[1]; const actual_path = args[1];
const expected_path = args[2]; const expected_path = args[2];
const io = std.Io.Threaded.global_single_threaded.ioBasic();
const actual = try std.Io.Dir.cwd().readFileAlloc(io, actual_path, arena, .limited(1024 * 1024)); const actual = try std.Io.Dir.cwd().readFileAlloc(io, actual_path, arena, .limited(1024 * 1024));
const expected = try std.Io.Dir.cwd().readFileAlloc(io, expected_path, arena, .limited(1024 * 1024)); const expected = try std.Io.Dir.cwd().readFileAlloc(io, expected_path, arena, .limited(1024 * 1024));
+2 -5
View File
@@ -1,8 +1,5 @@
const std = @import("std"); const std = @import("std");
pub fn main() !void { pub fn main(init: std.process.Init) !void {
var gpa: std.heap.GeneralPurposeAllocator(.{}) = .init; try std.testing.expect(init.env_map.count() == 0);
defer _ = gpa.deinit();
const env_map = std.process.getEnvMap(gpa.allocator()) catch @panic("unable to get env map");
try std.testing.expect(env_map.count() == 0);
} }
+6 -8
View File
@@ -1,13 +1,12 @@
pub fn main() !void { const std = @import("std");
var arena_state: std.heap.ArenaAllocator = .init(std.heap.page_allocator);
defer arena_state.deinit(); pub fn main(init: std.process.Init) !void {
const arena = arena_state.allocator(); const arena = init.arena.allocator();
const io = init.io;
const args = try init.minimal.args.toSlice(arena);
const args = try std.process.argsAlloc(arena);
if (args.len != 3) return error.BadUsage; // usage: 'check_differ <path a> <path b>' if (args.len != 3) return error.BadUsage; // usage: 'check_differ <path a> <path b>'
const io = std.Io.Threaded.global_single_threaded.ioBasic();
const contents_1 = try std.Io.Dir.cwd().readFileAlloc(io, args[1], arena, .limited(1024 * 1024 * 64)); // 64 MiB ought to be plenty const contents_1 = try std.Io.Dir.cwd().readFileAlloc(io, args[1], arena, .limited(1024 * 1024 * 64)); // 64 MiB ought to be plenty
const contents_2 = try std.Io.Dir.cwd().readFileAlloc(io, args[2], arena, .limited(1024 * 1024 * 64)); // 64 MiB ought to be plenty const contents_2 = try std.Io.Dir.cwd().readFileAlloc(io, args[2], arena, .limited(1024 * 1024 * 64)); // 64 MiB ought to be plenty
@@ -16,4 +15,3 @@ pub fn main() !void {
} }
// success, files differ // success, files differ
} }
const std = @import("std");
+73 -92
View File
@@ -7,145 +7,126 @@ pub fn main(init: std.process.Init) !void {
const allocator = init.gpa; const allocator = init.gpa;
const arena = init.arena.allocator(); const arena = init.arena.allocator();
const environ = init.minimal.environ;
// hasNonEmptyEnvVar // containsUnempty
{ {
try std.testing.expect(try std.process.hasNonEmptyEnvVar(allocator, "FOO")); try std.testing.expect(try environ.containsUnempty(allocator, "FOO"));
try std.testing.expect(!(try std.process.hasNonEmptyEnvVar(allocator, "FOO="))); try std.testing.expect(!(try environ.containsUnempty(allocator, "FOO=")));
try std.testing.expect(!(try std.process.hasNonEmptyEnvVar(allocator, "FO"))); try std.testing.expect(!(try environ.containsUnempty(allocator, "FO")));
try std.testing.expect(!(try std.process.hasNonEmptyEnvVar(allocator, "FOOO"))); try std.testing.expect(!(try environ.containsUnempty(allocator, "FOOO")));
if (builtin.os.tag == .windows) { if (builtin.os.tag == .windows) {
try std.testing.expect(try std.process.hasNonEmptyEnvVar(allocator, "foo")); try std.testing.expect(try environ.containsUnempty(allocator, "foo"));
} }
try std.testing.expect(try std.process.hasNonEmptyEnvVar(allocator, "EQUALS")); try std.testing.expect(try environ.containsUnempty(allocator, "EQUALS"));
try std.testing.expect(!(try std.process.hasNonEmptyEnvVar(allocator, "EQUALS=ABC"))); try std.testing.expect(!(try environ.containsUnempty(allocator, "EQUALS=ABC")));
try std.testing.expect(try std.process.hasNonEmptyEnvVar(allocator, "КИРиллИЦА")); try std.testing.expect(try environ.containsUnempty(allocator, "КИРиллИЦА"));
if (builtin.os.tag == .windows) { if (builtin.os.tag == .windows) {
try std.testing.expect(try std.process.hasNonEmptyEnvVar(allocator, "кирИЛЛица")); try std.testing.expect(try environ.containsUnempty(allocator, "кирИЛЛица"));
} }
try std.testing.expect(!(try std.process.hasNonEmptyEnvVar(allocator, "NO_VALUE"))); try std.testing.expect(!(try environ.containsUnempty(allocator, "NO_VALUE")));
try std.testing.expect(!(try std.process.hasNonEmptyEnvVar(allocator, "NOT_SET"))); try std.testing.expect(!(try environ.containsUnempty(allocator, "NOT_SET")));
if (builtin.os.tag == .windows) { if (builtin.os.tag == .windows) {
try std.testing.expect(try std.process.hasNonEmptyEnvVar(allocator, "=HIDDEN")); try std.testing.expect(try environ.containsUnempty(allocator, "=HIDDEN"));
try std.testing.expect(try std.process.hasNonEmptyEnvVar(allocator, "INVALID_UTF16_\xed\xa0\x80")); try std.testing.expect(try environ.containsUnempty(allocator, "INVALID_UTF16_\xed\xa0\x80"));
} }
} }
// hasNonEmptyEnvVarContstant // containsUnemptyConstant
{ {
try std.testing.expect(std.process.hasNonEmptyEnvVarConstant("FOO")); try std.testing.expect(environ.containsUnemptyConstant("FOO"));
try std.testing.expect(!std.process.hasNonEmptyEnvVarConstant("FOO=")); try std.testing.expect(!environ.containsUnemptyConstant("FOO="));
try std.testing.expect(!std.process.hasNonEmptyEnvVarConstant("FO")); try std.testing.expect(!environ.containsUnemptyConstant("FO"));
try std.testing.expect(!std.process.hasNonEmptyEnvVarConstant("FOOO")); try std.testing.expect(!environ.containsUnemptyConstant("FOOO"));
if (builtin.os.tag == .windows) { if (builtin.os.tag == .windows) {
try std.testing.expect(std.process.hasNonEmptyEnvVarConstant("foo")); try std.testing.expect(environ.containsUnemptyConstant("foo"));
} }
try std.testing.expect(std.process.hasNonEmptyEnvVarConstant("EQUALS")); try std.testing.expect(environ.containsUnemptyConstant("EQUALS"));
try std.testing.expect(!std.process.hasNonEmptyEnvVarConstant("EQUALS=ABC")); try std.testing.expect(!environ.containsUnemptyConstant("EQUALS=ABC"));
try std.testing.expect(std.process.hasNonEmptyEnvVarConstant("КИРиллИЦА")); try std.testing.expect(environ.containsUnemptyConstant("КИРиллИЦА"));
if (builtin.os.tag == .windows) { if (builtin.os.tag == .windows) {
try std.testing.expect(std.process.hasNonEmptyEnvVarConstant("кирИЛЛица")); try std.testing.expect(environ.containsUnemptyConstant("кирИЛЛица"));
} }
try std.testing.expect(!(std.process.hasNonEmptyEnvVarConstant("NO_VALUE"))); try std.testing.expect(!(environ.containsUnemptyConstant("NO_VALUE")));
try std.testing.expect(!(std.process.hasNonEmptyEnvVarConstant("NOT_SET"))); try std.testing.expect(!(environ.containsUnemptyConstant("NOT_SET")));
if (builtin.os.tag == .windows) { if (builtin.os.tag == .windows) {
try std.testing.expect(std.process.hasNonEmptyEnvVarConstant("=HIDDEN")); try std.testing.expect(environ.containsUnemptyConstant("=HIDDEN"));
try std.testing.expect(std.process.hasNonEmptyEnvVarConstant("INVALID_UTF16_\xed\xa0\x80")); try std.testing.expect(environ.containsUnemptyConstant("INVALID_UTF16_\xed\xa0\x80"));
} }
} }
// hasEnvVar // contains
{ {
try std.testing.expect(try std.process.hasEnvVar(allocator, "FOO")); try std.testing.expect(try environ.contains(allocator, "FOO"));
try std.testing.expect(!(try std.process.hasEnvVar(allocator, "FOO="))); try std.testing.expect(!(try environ.contains(allocator, "FOO=")));
try std.testing.expect(!(try std.process.hasEnvVar(allocator, "FO"))); try std.testing.expect(!(try environ.contains(allocator, "FO")));
try std.testing.expect(!(try std.process.hasEnvVar(allocator, "FOOO"))); try std.testing.expect(!(try environ.contains(allocator, "FOOO")));
if (builtin.os.tag == .windows) { if (builtin.os.tag == .windows) {
try std.testing.expect(try std.process.hasEnvVar(allocator, "foo")); try std.testing.expect(try environ.contains(allocator, "foo"));
} }
try std.testing.expect(try std.process.hasEnvVar(allocator, "EQUALS")); try std.testing.expect(try environ.contains(allocator, "EQUALS"));
try std.testing.expect(!(try std.process.hasEnvVar(allocator, "EQUALS=ABC"))); try std.testing.expect(!(try environ.contains(allocator, "EQUALS=ABC")));
try std.testing.expect(try std.process.hasEnvVar(allocator, "КИРиллИЦА")); try std.testing.expect(try environ.contains(allocator, "КИРиллИЦА"));
if (builtin.os.tag == .windows) { if (builtin.os.tag == .windows) {
try std.testing.expect(try std.process.hasEnvVar(allocator, "кирИЛЛица")); try std.testing.expect(try environ.contains(allocator, "кирИЛЛица"));
} }
try std.testing.expect(try std.process.hasEnvVar(allocator, "NO_VALUE")); try std.testing.expect(try environ.contains(allocator, "NO_VALUE"));
try std.testing.expect(!(try std.process.hasEnvVar(allocator, "NOT_SET"))); try std.testing.expect(!(try environ.contains(allocator, "NOT_SET")));
if (builtin.os.tag == .windows) { if (builtin.os.tag == .windows) {
try std.testing.expect(try std.process.hasEnvVar(allocator, "=HIDDEN")); try std.testing.expect(try environ.contains(allocator, "=HIDDEN"));
try std.testing.expect(try std.process.hasEnvVar(allocator, "INVALID_UTF16_\xed\xa0\x80")); try std.testing.expect(try environ.contains(allocator, "INVALID_UTF16_\xed\xa0\x80"));
} }
} }
// hasEnvVarConstant // containsConstant
{ {
try std.testing.expect(std.process.hasEnvVarConstant("FOO")); try std.testing.expect(environ.containsConstant("FOO"));
try std.testing.expect(!std.process.hasEnvVarConstant("FOO=")); try std.testing.expect(!environ.containsConstant("FOO="));
try std.testing.expect(!std.process.hasEnvVarConstant("FO")); try std.testing.expect(!environ.containsConstant("FO"));
try std.testing.expect(!std.process.hasEnvVarConstant("FOOO")); try std.testing.expect(!environ.containsConstant("FOOO"));
if (builtin.os.tag == .windows) { if (builtin.os.tag == .windows) {
try std.testing.expect(std.process.hasEnvVarConstant("foo")); try std.testing.expect(environ.containsConstant("foo"));
} }
try std.testing.expect(std.process.hasEnvVarConstant("EQUALS")); try std.testing.expect(environ.containsConstant("EQUALS"));
try std.testing.expect(!std.process.hasEnvVarConstant("EQUALS=ABC")); try std.testing.expect(!environ.containsConstant("EQUALS=ABC"));
try std.testing.expect(std.process.hasEnvVarConstant("КИРиллИЦА")); try std.testing.expect(environ.containsConstant("КИРиллИЦА"));
if (builtin.os.tag == .windows) { if (builtin.os.tag == .windows) {
try std.testing.expect(std.process.hasEnvVarConstant("кирИЛЛица")); try std.testing.expect(environ.containsConstant("кирИЛЛица"));
} }
try std.testing.expect(std.process.hasEnvVarConstant("NO_VALUE")); try std.testing.expect(environ.containsConstant("NO_VALUE"));
try std.testing.expect(!(std.process.hasEnvVarConstant("NOT_SET"))); try std.testing.expect(!(environ.containsConstant("NOT_SET")));
if (builtin.os.tag == .windows) { if (builtin.os.tag == .windows) {
try std.testing.expect(std.process.hasEnvVarConstant("=HIDDEN")); try std.testing.expect(environ.containsConstant("=HIDDEN"));
try std.testing.expect(std.process.hasEnvVarConstant("INVALID_UTF16_\xed\xa0\x80")); try std.testing.expect(environ.containsConstant("INVALID_UTF16_\xed\xa0\x80"));
} }
} }
// getEnvVarOwned // getAlloc
{ {
try std.testing.expectEqualSlices(u8, "123", try std.process.getEnvVarOwned(arena, "FOO")); try std.testing.expectEqualSlices(u8, "123", try environ.getAlloc(arena, "FOO"));
try std.testing.expectError(error.EnvironmentVariableNotFound, std.process.getEnvVarOwned(arena, "FOO=")); try std.testing.expectError(error.EnvironmentVariableNotFound, environ.getAlloc(arena, "FOO="));
try std.testing.expectError(error.EnvironmentVariableNotFound, std.process.getEnvVarOwned(arena, "FO")); try std.testing.expectError(error.EnvironmentVariableNotFound, environ.getAlloc(arena, "FO"));
try std.testing.expectError(error.EnvironmentVariableNotFound, std.process.getEnvVarOwned(arena, "FOOO")); try std.testing.expectError(error.EnvironmentVariableNotFound, environ.getAlloc(arena, "FOOO"));
if (builtin.os.tag == .windows) { if (builtin.os.tag == .windows) {
try std.testing.expectEqualSlices(u8, "123", try std.process.getEnvVarOwned(arena, "foo")); try std.testing.expectEqualSlices(u8, "123", try environ.getAlloc(arena, "foo"));
} }
try std.testing.expectEqualSlices(u8, "ABC=123", try std.process.getEnvVarOwned(arena, "EQUALS")); try std.testing.expectEqualSlices(u8, "ABC=123", try environ.getAlloc(arena, "EQUALS"));
try std.testing.expectError(error.EnvironmentVariableNotFound, std.process.getEnvVarOwned(arena, "EQUALS=ABC")); try std.testing.expectError(error.EnvironmentVariableNotFound, environ.getAlloc(arena, "EQUALS=ABC"));
try std.testing.expectEqualSlices(u8, "non-ascii አማርኛ \u{10FFFF}", try std.process.getEnvVarOwned(arena, "КИРиллИЦА")); try std.testing.expectEqualSlices(u8, "non-ascii አማርኛ \u{10FFFF}", try environ.getAlloc(arena, "КИРиллИЦА"));
if (builtin.os.tag == .windows) { if (builtin.os.tag == .windows) {
try std.testing.expectEqualSlices(u8, "non-ascii አማርኛ \u{10FFFF}", try std.process.getEnvVarOwned(arena, "кирИЛЛица")); try std.testing.expectEqualSlices(u8, "non-ascii አማርኛ \u{10FFFF}", try environ.getAlloc(arena, "кирИЛЛица"));
} }
try std.testing.expectEqualSlices(u8, "", try std.process.getEnvVarOwned(arena, "NO_VALUE")); try std.testing.expectEqualSlices(u8, "", try environ.getAlloc(arena, "NO_VALUE"));
try std.testing.expectError(error.EnvironmentVariableNotFound, std.process.getEnvVarOwned(arena, "NOT_SET")); try std.testing.expectError(error.EnvironmentVariableNotFound, environ.getAlloc(arena, "NOT_SET"));
if (builtin.os.tag == .windows) { if (builtin.os.tag == .windows) {
try std.testing.expectEqualSlices(u8, "hi", try std.process.getEnvVarOwned(arena, "=HIDDEN")); try std.testing.expectEqualSlices(u8, "hi", try environ.getAlloc(arena, "=HIDDEN"));
try std.testing.expectEqualSlices(u8, "\xed\xa0\x80", try std.process.getEnvVarOwned(arena, "INVALID_UTF16_\xed\xa0\x80")); try std.testing.expectEqualSlices(u8, "\xed\xa0\x80", try environ.getAlloc(arena, "INVALID_UTF16_\xed\xa0\x80"));
} }
} }
// parseEnvVarInt // Environ.Map
{ {
try std.testing.expectEqual(123, try std.process.parseEnvVarInt("FOO", u32, 10)); var env_map = try environ.createMap(allocator);
try std.testing.expectError(error.EnvironmentVariableNotFound, std.process.parseEnvVarInt("FO", u32, 10));
try std.testing.expectError(error.EnvironmentVariableNotFound, std.process.parseEnvVarInt("FOOO", u32, 10));
try std.testing.expectEqual(0x123, try std.process.parseEnvVarInt("FOO", u32, 16));
if (builtin.os.tag == .windows) {
try std.testing.expectEqual(123, try std.process.parseEnvVarInt("foo", u32, 10));
}
try std.testing.expectError(error.InvalidCharacter, std.process.parseEnvVarInt("EQUALS", u32, 10));
try std.testing.expectError(error.EnvironmentVariableNotFound, std.process.parseEnvVarInt("EQUALS=ABC", u32, 10));
try std.testing.expectError(error.InvalidCharacter, std.process.parseEnvVarInt("КИРиллИЦА", u32, 10));
try std.testing.expectError(error.InvalidCharacter, std.process.parseEnvVarInt("NO_VALUE", u32, 10));
try std.testing.expectError(error.EnvironmentVariableNotFound, std.process.parseEnvVarInt("NOT_SET", u32, 10));
if (builtin.os.tag == .windows) {
try std.testing.expectError(error.InvalidCharacter, std.process.parseEnvVarInt("=HIDDEN", u32, 10));
try std.testing.expectError(error.InvalidCharacter, std.process.parseEnvVarInt("INVALID_UTF16_\xed\xa0\x80", u32, 10));
}
}
// EnvMap
{
var env_map = try std.process.getEnvMap(allocator);
defer env_map.deinit(); defer env_map.deinit();
try std.testing.expectEqualSlices(u8, "123", env_map.get("FOO").?); try std.testing.expectEqualSlices(u8, "123", env_map.get("FOO").?);
+11 -10
View File
@@ -1,9 +1,9 @@
// test getting environment variables //! test getting environment variables
const std = @import("std"); const std = @import("std");
const builtin = @import("builtin"); const builtin = @import("builtin");
pub fn main() !void { pub fn main(init: std.process.Init.Minimal) !void {
if (builtin.target.os.tag == .windows) { if (builtin.target.os.tag == .windows) {
return; // Windows env strings are WTF-16, so not supported by Zig's std.posix.getenv() return; // Windows env strings are WTF-16, so not supported by Zig's std.posix.getenv()
} }
@@ -12,21 +12,22 @@ pub fn main() !void {
return; // std.posix.getenv is not supported on WASI due to the need of allocation return; // std.posix.getenv is not supported on WASI due to the need of allocation
} }
// Test some unset env vars: const environ = init.environ;
try std.testing.expectEqual(std.posix.getenv(""), null); // Test some unset env vars:
try std.testing.expectEqual(std.posix.getenv("BOGUSDOESNOTEXISTENVVAR"), null); try std.testing.expectEqual(environ.getPosix(""), null);
try std.testing.expectEqual(std.posix.getenvZ("BOGUSDOESNOTEXISTENVVAR"), null); try std.testing.expectEqual(environ.getPosix("BOGUSDOESNOTEXISTENVVAR"), null);
try std.testing.expectEqual(environ.getPosix("BOGUSDOESNOTEXISTENVVAR"), null);
if (builtin.link_libc) { if (builtin.link_libc) {
// Test if USER matches what C library sees // Test if USER matches what C library sees
const expected = std.mem.span(std.c.getenv("USER") orelse ""); const expected = std.mem.span(std.c.getenv("USER") orelse "");
const actual = std.posix.getenv("USER") orelse ""; const actual = environ.getPosix("USER") orelse "";
try std.testing.expectEqualStrings(expected, actual); try std.testing.expectEqualStrings(expected, actual);
} }
// env vars set by our build.zig run step: // env vars set by our build.zig run step:
try std.testing.expectEqualStrings("", std.posix.getenv("ZIG_TEST_POSIX_EMPTY") orelse "invalid"); try std.testing.expectEqualStrings("", environ.getPosix("ZIG_TEST_POSIX_EMPTY") orelse "invalid");
try std.testing.expectEqualStrings("test=variable", std.posix.getenv("ZIG_TEST_POSIX_1EQ") orelse "invalid"); try std.testing.expectEqualStrings("test=variable", environ.getPosix("ZIG_TEST_POSIX_1EQ") orelse "invalid");
try std.testing.expectEqualStrings("=test=variable=", std.posix.getenv("ZIG_TEST_POSIX_3EQ") orelse "invalid"); try std.testing.expectEqualStrings("=test=variable=", environ.getPosix("ZIG_TEST_POSIX_3EQ") orelse "invalid");
} }
+1 -1
View File
@@ -2,7 +2,7 @@ const std = @import("std");
pub fn main(init: std.process.Init) !void { pub fn main(init: std.process.Init) !void {
const io = init.io; const io = init.io;
var args = try init.minimal.argsAllocator(init.arena.allocator()); var args = try init.minimal.args.iterateAllocator(init.arena.allocator());
_ = args.skip(); _ = args.skip();
const filename = args.next().?; const filename = args.next().?;
const file = try std.Io.Dir.cwd().createFile(io, filename, .{}); const file = try std.Io.Dir.cwd().createFile(io, filename, .{});
@@ -2,7 +2,7 @@ const std = @import("std");
pub fn main(init: std.process.Init) !void { pub fn main(init: std.process.Init) !void {
const io = init.io; const io = init.io;
var args = try init.args.iterateAllocator(init.arena.allocator()); var args = try init.minimal.args.iterateAllocator(init.arena.allocator());
_ = args.skip(); _ = args.skip();
const dir_name = args.next().?; const dir_name = args.next().?;
const dir = try std.Io.Dir.cwd().openDir(io, if (std.mem.startsWith(u8, dir_name, "--dir=")) const dir = try std.Io.Dir.cwd().openDir(io, if (std.mem.startsWith(u8, dir_name, "--dir="))
@@ -3,14 +3,16 @@ const std = @import("std");
pub fn main(init: std.process.Init) !void { pub fn main(init: std.process.Init) !void {
const io = init.io; const io = init.io;
const gpa = init.gpa; const gpa = init.gpa;
var it = try init.args.iterateAllocator(gpa); var it = try init.minimal.args.iterateAllocator(gpa);
defer it.deinit(); defer it.deinit();
_ = it.next() orelse unreachable; // skip binary name _ = it.next() orelse unreachable; // skip binary name
const exe_path = it.next() orelse unreachable; const exe_path = it.next() orelse unreachable;
const symlink_path = it.next() orelse unreachable; const symlink_path = it.next() orelse unreachable;
const cwd = std.process.getCwdAlloc(init.arena.allocator());
// If `exe_path` is relative to our cwd, we need to convert it to be relative to the dirname of `symlink_path`. // If `exe_path` is relative to our cwd, we need to convert it to be relative to the dirname of `symlink_path`.
const exe_rel_path = try std.fs.path.relative(gpa, std.fs.path.dirname(symlink_path) orelse ".", exe_path); const exe_rel_path = try std.fs.path.relative(gpa, cwd, init.env_map, std.fs.path.dirname(symlink_path) orelse ".", exe_path);
defer gpa.free(exe_rel_path); defer gpa.free(exe_rel_path);
try std.Io.Dir.cwd().symLink(io, exe_rel_path, symlink_path, .{}); try std.Io.Dir.cwd().symLink(io, exe_rel_path, symlink_path, .{});
+3 -8
View File
@@ -1,13 +1,8 @@
const std = @import("std"); const std = @import("std");
pub fn main() !void { pub fn main(init: std.process.Init) !void {
var debug_allocator: std.heap.DebugAllocator(.{}) = .init; const gpa = init.gpa;
defer if (debug_allocator.deinit() == .leak) @panic("found memory leaks"); const io = init.io;
const gpa = debug_allocator.allocator();
var threaded: std.Io.Threaded = .init(gpa, .{});
defer threaded.deinit();
const io = threaded.io();
const self_path = try std.process.executablePathAlloc(io, gpa); const self_path = try std.process.executablePathAlloc(io, gpa);
defer gpa.free(self_path); defer gpa.free(self_path);
+1 -1
View File
@@ -7,7 +7,7 @@ const fatal = std.process.fatal;
pub fn main(init: std.process.Init) !void { pub fn main(init: std.process.Init) !void {
const arena = init.arena.allocator(); const arena = init.arena.allocator();
const io = init.io; const io = init.io;
const args = try init.args.toSlice(arena); const args = try init.minimal.args.toSlice(arena);
const exe = args[0]; const exe = args[0];
var catted_anything = false; var catted_anything = false;
+3 -14
View File
@@ -1,22 +1,11 @@
const builtin = @import("builtin");
const std = @import("std"); const std = @import("std");
// See https://github.com/ziglang/zig/issues/24510 pub fn main(init: std.process.Init) !void {
// for the plan to simplify this code. var stdout_writer = std.Io.File.stdout().writerStreaming(init.io, &.{});
pub fn main() !void {
var debug_allocator: std.heap.DebugAllocator(.{}) = .init;
defer _ = debug_allocator.deinit();
const gpa = debug_allocator.allocator();
var threaded: std.Io.Threaded = .init(gpa, .{});
defer threaded.deinit();
const io = threaded.io();
var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{});
const out = &stdout_writer.interface; const out = &stdout_writer.interface;
var line_buffer: [20]u8 = undefined; var line_buffer: [20]u8 = undefined;
var stdin_reader: std.Io.File.Reader = .init(.stdin(), io, &line_buffer); var stdin_reader: std.Io.File.Reader = .init(.stdin(), init.io, &line_buffer);
const in = &stdin_reader.interface; const in = &stdin_reader.interface;
try out.writeAll("Welcome to the Guess Number Game in Zig.\n"); try out.writeAll("Welcome to the Guess Number Game in Zig.\n");
+1 -1
View File
@@ -93,7 +93,7 @@ fn testExecBat(gpa: Allocator, io: Io, bat: []const u8, args: []const []const u8
const can_have_trailing_empty_args = std.mem.eql(u8, bat, "args3.bat"); const can_have_trailing_empty_args = std.mem.eql(u8, bat, "args3.bat");
const result = try std.process.Child.run(gpa, io, .{ const result = try std.process.run(gpa, io, .{
.env_map = env, .env_map = env,
.argv = argv, .argv = argv,
}); });
+1 -1
View File
@@ -140,7 +140,7 @@ fn testExecBat(gpa: Allocator, io: Io, bat: []const u8, args: []const []const u8
const can_have_trailing_empty_args = std.mem.eql(u8, bat, "args3.bat"); const can_have_trailing_empty_args = std.mem.eql(u8, bat, "args3.bat");
const result = try std.process.Child.run(gpa, io, .{ const result = try std.process.run(gpa, io, .{
.env_map = env, .env_map = env,
.argv = argv, .argv = argv,
}); });
+1 -1
View File
@@ -98,7 +98,7 @@ fn checkRelative(
cwd: ?[]const u8, cwd: ?[]const u8,
env_map: ?*const std.process.Environ.Map, env_map: ?*const std.process.Environ.Map,
) !void { ) !void {
const result = try std.process.Child.run(allocator, io, .{ const result = try std.process.run(allocator, io, .{
.argv = argv, .argv = argv,
.cwd = cwd, .cwd = cwd,
.env_map = env_map, .env_map = env_map,
+1 -1
View File
@@ -207,7 +207,7 @@ fn testExec(gpa: Allocator, io: Io, command: []const u8, expected_stdout: []cons
} }
fn testExecWithCwd(gpa: Allocator, io: Io, command: []const u8, cwd: ?[]const u8, expected_stdout: []const u8) !void { fn testExecWithCwd(gpa: Allocator, io: Io, command: []const u8, cwd: ?[]const u8, expected_stdout: []const u8) !void {
const result = try std.process.Child.run(gpa, io, .{ const result = try std.process.run(gpa, io, .{
.argv = &[_][]const u8{command}, .argv = &[_][]const u8{command},
.cwd = cwd, .cwd = cwd,
}); });
+14 -14
View File
@@ -193,14 +193,14 @@ fn printOutput(
try shell_out.print("\n", .{}); try shell_out.print("\n", .{});
if (expected_outcome == .build_fail) { if (expected_outcome == .build_fail) {
const result = try process.Child.run(arena, io, .{ const result = try process.run(arena, io, .{
.argv = build_args.items, .argv = build_args.items,
.cwd = tmp_dir_path, .cwd = tmp_dir_path,
.env_map = &env_map, .env_map = &env_map,
.max_output_bytes = max_doc_file_size, .max_output_bytes = max_doc_file_size,
}); });
switch (result.term) { switch (result.term) {
.Exited => |exit_code| { .exited => |exit_code| {
if (exit_code == 0) { if (exit_code == 0) {
print("{s}\nThe following command incorrectly succeeded:\n", .{result.stderr}); print("{s}\nThe following command incorrectly succeeded:\n", .{result.stderr});
dumpArgs(build_args.items); dumpArgs(build_args.items);
@@ -249,21 +249,21 @@ fn printOutput(
var exited_with_signal = false; var exited_with_signal = false;
const result = if (expected_outcome == .fail) blk: { const result = if (expected_outcome == .fail) blk: {
const result = try process.Child.run(arena, io, .{ const result = try process.run(arena, io, .{
.argv = run_args, .argv = run_args,
.env_map = &env_map, .env_map = &env_map,
.cwd = tmp_dir_path, .cwd = tmp_dir_path,
.max_output_bytes = max_doc_file_size, .max_output_bytes = max_doc_file_size,
}); });
switch (result.term) { switch (result.term) {
.Exited => |exit_code| { .exited => |exit_code| {
if (exit_code == 0) { if (exit_code == 0) {
print("{s}\nThe following command incorrectly succeeded:\n", .{result.stderr}); print("{s}\nThe following command incorrectly succeeded:\n", .{result.stderr});
dumpArgs(run_args); dumpArgs(run_args);
fatal("example incorrectly compiled", .{}); fatal("example incorrectly compiled", .{});
} }
}, },
.Signal => exited_with_signal = true, .signal => exited_with_signal = true,
else => {}, else => {},
} }
break :blk result; break :blk result;
@@ -368,14 +368,14 @@ fn printOutput(
try test_args.append("-lc"); try test_args.append("-lc");
try shell_out.print("-lc ", .{}); try shell_out.print("-lc ", .{});
} }
const result = try process.Child.run(arena, io, .{ const result = try process.run(arena, io, .{
.argv = test_args.items, .argv = test_args.items,
.env_map = &env_map, .env_map = &env_map,
.cwd = tmp_dir_path, .cwd = tmp_dir_path,
.max_output_bytes = max_doc_file_size, .max_output_bytes = max_doc_file_size,
}); });
switch (result.term) { switch (result.term) {
.Exited => |exit_code| { .exited => |exit_code| {
if (exit_code == 0) { if (exit_code == 0) {
print("{s}\nThe following command incorrectly succeeded:\n", .{result.stderr}); print("{s}\nThe following command incorrectly succeeded:\n", .{result.stderr});
dumpArgs(test_args.items); dumpArgs(test_args.items);
@@ -424,14 +424,14 @@ fn printOutput(
}, },
} }
const result = try process.Child.run(arena, io, .{ const result = try process.run(arena, io, .{
.argv = test_args.items, .argv = test_args.items,
.env_map = &env_map, .env_map = &env_map,
.cwd = tmp_dir_path, .cwd = tmp_dir_path,
.max_output_bytes = max_doc_file_size, .max_output_bytes = max_doc_file_size,
}); });
switch (result.term) { switch (result.term) {
.Exited => |exit_code| { .exited => |exit_code| {
if (exit_code == 0) { if (exit_code == 0) {
print("{s}\nThe following command incorrectly succeeded:\n", .{result.stderr}); print("{s}\nThe following command incorrectly succeeded:\n", .{result.stderr});
dumpArgs(test_args.items); dumpArgs(test_args.items);
@@ -500,14 +500,14 @@ fn printOutput(
} }
if (maybe_error_match) |error_match| { if (maybe_error_match) |error_match| {
const result = try process.Child.run(arena, io, .{ const result = try process.run(arena, io, .{
.argv = build_args.items, .argv = build_args.items,
.env_map = &env_map, .env_map = &env_map,
.cwd = tmp_dir_path, .cwd = tmp_dir_path,
.max_output_bytes = max_doc_file_size, .max_output_bytes = max_doc_file_size,
}); });
switch (result.term) { switch (result.term) {
.Exited => |exit_code| { .exited => |exit_code| {
if (exit_code == 0) { if (exit_code == 0) {
print("{s}\nThe following command incorrectly succeeded:\n", .{result.stderr}); print("{s}\nThe following command incorrectly succeeded:\n", .{result.stderr});
dumpArgs(build_args.items); dumpArgs(build_args.items);
@@ -1123,15 +1123,15 @@ fn run(
env_map: *process.Environ.Map, env_map: *process.Environ.Map,
cwd: []const u8, cwd: []const u8,
args: []const []const u8, args: []const []const u8,
) !process.Child.RunResult { ) !process.RunResult {
const result = try process.Child.run(allocator, io, .{ const result = try process.run(allocator, io, .{
.argv = args, .argv = args,
.env_map = env_map, .env_map = env_map,
.cwd = cwd, .cwd = cwd,
.max_output_bytes = max_doc_file_size, .max_output_bytes = max_doc_file_size,
}); });
switch (result.term) { switch (result.term) {
.Exited => |exit_code| { .exited => |exit_code| {
if (exit_code != 0) { if (exit_code != 0) {
std.debug.print("{s}\nThe following command exited with code {}:\n", .{ result.stderr, exit_code }); std.debug.print("{s}\nThe following command exited with code {}:\n", .{ result.stderr, exit_code });
dumpArgs(args); dumpArgs(args);
+2 -2
View File
@@ -10,9 +10,9 @@ const SeenPcsHeader = std.Build.abi.fuzz.SeenPcsHeader;
pub fn main(init: std.process.Init) !void { pub fn main(init: std.process.Init) !void {
const gpa = init.gpa; const gpa = init.gpa;
const arena = init.arena; const arena = init.arena.allocator();
const io = init.io; const io = init.io;
const args = try init.args.toSlice(arena); const args = try init.minimal.args.toSlice(arena);
const target_query_str = switch (args.len) { const target_query_str = switch (args.len) {
3 => "native", 3 => "native",
+2 -2
View File
@@ -68,7 +68,7 @@ const usage =
pub fn main(init: std.process.Init) !void { pub fn main(init: std.process.Init) !void {
const allocator = init.arena; const allocator = init.arena;
const args = try init.args.toSlice(allocator); const args = try init.minimal.args.toSlice(allocator);
var argv = std.array_list.Managed([]const u8).init(allocator); var argv = std.array_list.Managed([]const u8).init(allocator);
var sysroot: ?[]const u8 = null; var sysroot: ?[]const u8 = null;
@@ -161,7 +161,7 @@ fn fetchTarget(
}); });
try cc_argv.appendSlice(args); try cc_argv.appendSlice(args);
const res = try std.process.Child.run(arena, io, .{ .argv = cc_argv.items }); const res = try std.process.run(arena, io, .{ .argv = cc_argv.items });
if (res.stderr.len != 0) { if (res.stderr.len != 0) {
std.log.err("{s}", .{res.stderr}); std.log.err("{s}", .{res.stderr});
+1 -1
View File
@@ -16,8 +16,8 @@ const usage =
pub fn main(init: std.process.Init) !void { pub fn main(init: std.process.Init) !void {
const arena = init.arena; const arena = init.arena;
const io = init.io; const io = init.io;
const args = try init.minimal.args.toSlice(arena);
const args = try init.args.toSlice(arena);
if (args.len == 1) fatal("no command or option specified", .{}); if (args.len == 1) fatal("no command or option specified", .{});
var positionals = std.array_list.Managed([]const u8).init(arena); var positionals = std.array_list.Managed([]const u8).init(arena);
+1 -1
View File
@@ -12,7 +12,7 @@ const AtomicOp = enum {
}; };
pub fn main(init: std.process.Init) !void { pub fn main(init: std.process.Init) !void {
const arena = init.arena; const arena = init.arena.allocator();
const io = init.io; const io = init.io;
//const args = try std.process.argsAlloc(arena); //const args = try std.process.argsAlloc(arena);
+49 -49
View File
@@ -1,6 +1,7 @@
const std = @import("std"); const std = @import("std");
const Io = std.Io; const Io = std.Io;
const Allocator = std.mem.Allocator; const Allocator = std.mem.Allocator;
const assert = std.debug.assert;
const g = @import("spirv/grammar.zig"); const g = @import("spirv/grammar.zig");
const CoreRegistry = g.CoreRegistry; const CoreRegistry = g.CoreRegistry;
@@ -54,28 +55,22 @@ const set_names = std.StaticStringMap(struct { []const u8, []const u8 }).initCom
.{ "zig", .{ "zig", "Zig" } }, .{ "zig", .{ "zig", "Zig" } },
}); });
var arena = std.heap.ArenaAllocator.init(std.heap.smp_allocator); pub fn main(init: std.process.Init) !void {
const allocator = arena.allocator(); const arena = init.arena.allocator();
const args = try init.minimal.args.toSlice(arena);
pub fn main() !void {
defer arena.deinit();
const args = try std.process.argsAlloc(allocator);
if (args.len != 3) { if (args.len != 3) {
usageAndExit(args[0], 1); usageAndExit(args[0], 1);
} }
var threaded: std.Io.Threaded = .init(allocator, .{}); const io = init.io;
defer threaded.deinit();
const io = threaded.io();
const json_path = try Io.Dir.path.join(allocator, &.{ args[1], "include/spirv/unified1/" }); const json_path = try Io.Dir.path.join(arena, &.{ args[1], "include/spirv/unified1/" });
const dir = try Io.Dir.cwd().openDir(io, json_path, .{ .iterate = true }); const dir = try Io.Dir.cwd().openDir(io, json_path, .{ .iterate = true });
const core_spec = try readRegistry(io, CoreRegistry, dir, "spirv.core.grammar.json"); const core_spec = try readRegistry(io, arena, CoreRegistry, dir, "spirv.core.grammar.json");
std.mem.sortUnstable(Instruction, core_spec.instructions, CmpInst{}, CmpInst.lt); std.mem.sortUnstable(Instruction, core_spec.instructions, CmpInst{}, CmpInst.lt);
var exts = std.array_list.Managed(Extension).init(allocator); var exts = std.array_list.Managed(Extension).init(arena);
var it = dir.iterate(); var it = dir.iterate();
while (try it.next(io)) |entry| { while (try it.next(io)) |entry| {
@@ -83,48 +78,48 @@ pub fn main() !void {
continue; continue;
} }
try readExtRegistry(io, &exts, dir, entry.name); try readExtRegistry(io, arena, &exts, dir, entry.name);
} }
try readExtRegistry(io, &exts, Io.Dir.cwd(), args[2]); try readExtRegistry(io, arena, &exts, Io.Dir.cwd(), args[2]);
var allocating: std.Io.Writer.Allocating = .init(allocator); var allocating: std.Io.Writer.Allocating = .init(arena);
defer allocating.deinit(); defer allocating.deinit();
try render(&allocating.writer, core_spec, exts.items); try render(arena, &allocating.writer, core_spec, exts.items);
try allocating.writer.writeByte(0); try allocating.writer.writeByte(0);
const output = allocating.written()[0 .. allocating.written().len - 1 :0]; const output = allocating.written()[0 .. allocating.written().len - 1 :0];
var tree = try std.zig.Ast.parse(allocator, output, .zig); var tree = try std.zig.Ast.parse(arena, output, .zig);
if (tree.errors.len != 0) { if (tree.errors.len != 0) {
try std.zig.printAstErrorsToStderr(allocator, io, tree, "", .auto); try std.zig.printAstErrorsToStderr(arena, io, tree, "", .auto);
return; return;
} }
var zir = try std.zig.AstGen.generate(allocator, tree); var zir = try std.zig.AstGen.generate(arena, tree);
if (zir.hasCompileErrors()) { if (zir.hasCompileErrors()) {
var wip_errors: std.zig.ErrorBundle.Wip = undefined; var wip_errors: std.zig.ErrorBundle.Wip = undefined;
try wip_errors.init(allocator); try wip_errors.init(arena);
defer wip_errors.deinit(); defer wip_errors.deinit();
try wip_errors.addZirErrorMessages(zir, tree, output, ""); try wip_errors.addZirErrorMessages(zir, tree, output, "");
var error_bundle = try wip_errors.toOwnedBundle(""); var error_bundle = try wip_errors.toOwnedBundle("");
defer error_bundle.deinit(allocator); defer error_bundle.deinit(arena);
try error_bundle.renderToStderr(io, .{}, .auto); try error_bundle.renderToStderr(io, .{}, .auto);
} }
const formatted_output = try tree.renderAlloc(allocator); const formatted_output = try tree.renderAlloc(arena);
try Io.File.stdout().writeStreamingAll(io, formatted_output); try Io.File.stdout().writeStreamingAll(io, formatted_output);
} }
fn readExtRegistry(io: Io, exts: *std.array_list.Managed(Extension), dir: Io.Dir, sub_path: []const u8) !void { fn readExtRegistry(io: Io, arena: Allocator, exts: *std.array_list.Managed(Extension), dir: Io.Dir, sub_path: []const u8) !void {
const filename = Io.Dir.path.basename(sub_path); const filename = Io.Dir.path.basename(sub_path);
if (!std.mem.startsWith(u8, filename, "extinst.")) { if (!std.mem.startsWith(u8, filename, "extinst.")) {
return; return;
} }
std.debug.assert(std.mem.endsWith(u8, filename, ".grammar.json")); assert(std.mem.endsWith(u8, filename, ".grammar.json"));
const name = filename["extinst.".len .. filename.len - ".grammar.json".len]; const name = filename["extinst.".len .. filename.len - ".grammar.json".len];
const spec = try readRegistry(io, ExtensionRegistry, dir, sub_path); const spec = try readRegistry(io, arena, ExtensionRegistry, dir, sub_path);
const set_name = set_names.get(name) orelse { const set_name = set_names.get(name) orelse {
std.log.info("ignored instruction set '{s}'", .{name}); std.log.info("ignored instruction set '{s}'", .{name});
@@ -140,16 +135,16 @@ fn readExtRegistry(io: Io, exts: *std.array_list.Managed(Extension), dir: Io.Dir
}); });
} }
fn readRegistry(io: Io, comptime RegistryType: type, dir: Io.Dir, path: []const u8) !RegistryType { fn readRegistry(io: Io, arena: Allocator, comptime RegistryType: type, dir: Io.Dir, path: []const u8) !RegistryType {
const spec = try dir.readFileAlloc(io, path, allocator, .unlimited); const spec = try dir.readFileAlloc(io, path, arena, .unlimited);
// Required for json parsing. // Required for json parsing.
// TODO: ALI // TODO: ALI
@setEvalBranchQuota(10000); @setEvalBranchQuota(10000);
var scanner = std.json.Scanner.initCompleteInput(allocator, spec); var scanner = std.json.Scanner.initCompleteInput(arena, spec);
var diagnostics = std.json.Diagnostics{}; var diagnostics = std.json.Diagnostics{};
scanner.enableDiagnostics(&diagnostics); scanner.enableDiagnostics(&diagnostics);
const parsed = std.json.parseFromTokenSource(RegistryType, allocator, &scanner, .{}) catch |err| { const parsed = std.json.parseFromTokenSource(RegistryType, arena, &scanner, .{}) catch |err| {
std.debug.print("{s}:{}:{}:\n", .{ path, diagnostics.getLine(), diagnostics.getColumn() }); std.debug.print("{s}:{}:{}:\n", .{ path, diagnostics.getLine(), diagnostics.getColumn() });
return err; return err;
}; };
@@ -158,8 +153,8 @@ fn readRegistry(io: Io, comptime RegistryType: type, dir: Io.Dir, path: []const
/// Returns a set with types that require an extra struct for the `Instruction` interface /// Returns a set with types that require an extra struct for the `Instruction` interface
/// to the spir-v spec, or whether the original type can be used. /// to the spir-v spec, or whether the original type can be used.
fn extendedStructs(kinds: []const OperandKind) !ExtendedStructSet { fn extendedStructs(arena: Allocator, kinds: []const OperandKind) !ExtendedStructSet {
var map = ExtendedStructSet.init(allocator); var map = ExtendedStructSet.init(arena);
try map.ensureTotalCapacity(@as(u32, @intCast(kinds.len))); try map.ensureTotalCapacity(@as(u32, @intCast(kinds.len)));
for (kinds) |kind| { for (kinds) |kind| {
@@ -194,6 +189,7 @@ fn tagPriorityScore(tag: []const u8) usize {
} }
fn render( fn render(
arena: Allocator,
writer: *std.Io.Writer, writer: *std.Io.Writer,
registry: CoreRegistry, registry: CoreRegistry,
extensions: []const Extension, extensions: []const Extension,
@@ -299,7 +295,7 @@ fn render(
); );
// Merge the operand kinds from all extensions together. // Merge the operand kinds from all extensions together.
var all_operand_kinds = OperandKindMap.init(allocator); var all_operand_kinds = OperandKindMap.init(arena);
for (registry.operand_kinds) |kind| { for (registry.operand_kinds) |kind| {
try all_operand_kinds.putNoClobber(.{ "core", kind.kind }, kind); try all_operand_kinds.putNoClobber(.{ "core", kind.kind }, kind);
} }
@@ -312,22 +308,22 @@ fn render(
try all_operand_kinds.ensureUnusedCapacity(ext.spec.operand_kinds.len); try all_operand_kinds.ensureUnusedCapacity(ext.spec.operand_kinds.len);
for (ext.spec.operand_kinds) |kind| { for (ext.spec.operand_kinds) |kind| {
var new_kind = kind; var new_kind = kind;
new_kind.kind = try std.mem.join(allocator, ".", &.{ ext.name, kind.kind }); new_kind.kind = try std.mem.join(arena, ".", &.{ ext.name, kind.kind });
try all_operand_kinds.putNoClobber(.{ ext.name, kind.kind }, new_kind); try all_operand_kinds.putNoClobber(.{ ext.name, kind.kind }, new_kind);
} }
} }
const extended_structs = try extendedStructs(all_operand_kinds.values()); const extended_structs = try extendedStructs(arena, all_operand_kinds.values());
// Note: extensions don't seem to have class. // Note: extensions don't seem to have class.
try renderClass(writer, registry.instructions); try renderClass(arena, writer, registry.instructions);
try renderOperandKind(writer, all_operand_kinds.values()); try renderOperandKind(writer, all_operand_kinds.values());
try renderOpcodes(writer, "Opcode", true, registry.instructions, extended_structs); try renderOpcodes(arena, writer, "Opcode", true, registry.instructions, extended_structs);
for (extensions) |ext| { for (extensions) |ext| {
try renderOpcodes(writer, ext.opcode_name, false, ext.spec.instructions, extended_structs); try renderOpcodes(arena, writer, ext.opcode_name, false, ext.spec.instructions, extended_structs);
} }
try renderOperandKinds(writer, all_operand_kinds.values(), extended_structs); try renderOperandKinds(arena, writer, all_operand_kinds.values(), extended_structs);
try renderInstructionSet(writer, registry, extensions, all_operand_kinds); try renderInstructionSet(writer, registry, extensions, all_operand_kinds);
} }
@@ -414,8 +410,8 @@ fn renderInstructionsCase(
); );
} }
fn renderClass(writer: *std.Io.Writer, instructions: []const Instruction) !void { fn renderClass(arena: Allocator, writer: *std.Io.Writer, instructions: []const Instruction) !void {
var class_map = std.StringArrayHashMap(void).init(allocator); var class_map = std.StringArrayHashMap(void).init(arena);
for (instructions) |inst| { for (instructions) |inst| {
if (std.mem.eql(u8, inst.class.?, "@exclude")) continue; if (std.mem.eql(u8, inst.class.?, "@exclude")) continue;
@@ -535,16 +531,17 @@ fn renderEnumerant(writer: *std.Io.Writer, enumerant: Enumerant) !void {
} }
fn renderOpcodes( fn renderOpcodes(
arena: Allocator,
writer: *std.Io.Writer, writer: *std.Io.Writer,
opcode_type_name: []const u8, opcode_type_name: []const u8,
want_operands: bool, want_operands: bool,
instructions: []const Instruction, instructions: []const Instruction,
extended_structs: ExtendedStructSet, extended_structs: ExtendedStructSet,
) !void { ) !void {
var inst_map = std.AutoArrayHashMap(u32, usize).init(allocator); var inst_map = std.AutoArrayHashMap(u32, usize).init(arena);
try inst_map.ensureTotalCapacity(instructions.len); try inst_map.ensureTotalCapacity(instructions.len);
var aliases = std.array_list.Managed(struct { inst: usize, alias: usize }).init(allocator); var aliases = std.array_list.Managed(struct { inst: usize, alias: usize }).init(arena);
try aliases.ensureTotalCapacity(instructions.len); try aliases.ensureTotalCapacity(instructions.len);
for (instructions, 0..) |inst, i| { for (instructions, 0..) |inst, i| {
@@ -634,30 +631,32 @@ fn renderOpcodes(
} }
fn renderOperandKinds( fn renderOperandKinds(
arena: Allocator,
writer: *std.Io.Writer, writer: *std.Io.Writer,
kinds: []const OperandKind, kinds: []const OperandKind,
extended_structs: ExtendedStructSet, extended_structs: ExtendedStructSet,
) !void { ) !void {
for (kinds) |kind| { for (kinds) |kind| {
switch (kind.category) { switch (kind.category) {
.ValueEnum => try renderValueEnum(writer, kind, extended_structs), .ValueEnum => try renderValueEnum(arena, writer, kind, extended_structs),
.BitEnum => try renderBitEnum(writer, kind, extended_structs), .BitEnum => try renderBitEnum(arena, writer, kind, extended_structs),
else => {}, else => {},
} }
} }
} }
fn renderValueEnum( fn renderValueEnum(
arena: Allocator,
writer: *std.Io.Writer, writer: *std.Io.Writer,
enumeration: OperandKind, enumeration: OperandKind,
extended_structs: ExtendedStructSet, extended_structs: ExtendedStructSet,
) !void { ) !void {
const enumerants = enumeration.enumerants orelse return error.InvalidRegistry; const enumerants = enumeration.enumerants orelse return error.InvalidRegistry;
var enum_map = std.AutoArrayHashMap(u32, usize).init(allocator); var enum_map = std.AutoArrayHashMap(u32, usize).init(arena);
try enum_map.ensureTotalCapacity(enumerants.len); try enum_map.ensureTotalCapacity(enumerants.len);
var aliases = std.array_list.Managed(struct { enumerant: usize, alias: usize }).init(allocator); var aliases = std.array_list.Managed(struct { enumerant: usize, alias: usize }).init(arena);
try aliases.ensureTotalCapacity(enumerants.len); try aliases.ensureTotalCapacity(enumerants.len);
for (enumerants, 0..) |enumerant, i| { for (enumerants, 0..) |enumerant, i| {
@@ -726,6 +725,7 @@ fn renderValueEnum(
} }
fn renderBitEnum( fn renderBitEnum(
arena: Allocator,
writer: *std.Io.Writer, writer: *std.Io.Writer,
enumeration: OperandKind, enumeration: OperandKind,
extended_structs: ExtendedStructSet, extended_structs: ExtendedStructSet,
@@ -735,7 +735,7 @@ fn renderBitEnum(
var flags_by_bitpos = [_]?usize{null} ** 32; var flags_by_bitpos = [_]?usize{null} ** 32;
const enumerants = enumeration.enumerants orelse return error.InvalidRegistry; const enumerants = enumeration.enumerants orelse return error.InvalidRegistry;
var aliases = std.array_list.Managed(struct { flag: usize, alias: u5 }).init(allocator); var aliases = std.array_list.Managed(struct { flag: usize, alias: u5 }).init(arena);
try aliases.ensureTotalCapacity(enumerants.len); try aliases.ensureTotalCapacity(enumerants.len);
for (enumerants, 0..) |enumerant, i| { for (enumerants, 0..) |enumerant, i| {
@@ -749,7 +749,7 @@ fn renderBitEnum(
continue; continue;
} }
std.debug.assert(@popCount(value) == 1); assert(@popCount(value) == 1);
const bitpos = std.math.log2_int(u32, value); const bitpos = std.math.log2_int(u32, value);
if (flags_by_bitpos[bitpos]) |*existing| { if (flags_by_bitpos[bitpos]) |*existing| {
+4 -10
View File
@@ -281,16 +281,10 @@ const Parse = struct {
arch: Arch, arch: Arch,
}; };
pub fn main() !void { pub fn main(init: std.process.Init) !void {
var arena_instance = std.heap.ArenaAllocator.init(std.heap.page_allocator); const arena = init.arena.allocator();
defer arena_instance.deinit(); const io = init.io;
const arena = arena_instance.allocator(); const args = try init.minimal.args.toSlice(arena);
var threaded: std.Io.Threaded = .init(arena, .{});
defer threaded.deinit();
const io = threaded.io();
const args = try std.process.argsAlloc(arena);
const build_all_path = args[1]; const build_all_path = args[1];
var build_all_dir = try Io.Dir.cwd().openDir(io, build_all_path, .{}); var build_all_dir = try Io.Dir.cwd().openDir(io, build_all_path, .{});
+1 -1
View File
@@ -29,7 +29,7 @@ fn cName(ty: std.Target.CType) []const u8 {
var general_purpose_allocator: std.heap.GeneralPurposeAllocator(.{}) = .init; var general_purpose_allocator: std.heap.GeneralPurposeAllocator(.{}) = .init;
pub fn main(init: std.process.Init) !void { pub fn main(init: std.process.Init) !void {
const args = try init.args.toSlice(init.arena); const args = try init.minimal.args.toSlice(init.arena.allocator());
const io = init.io; const io = init.io;
if (args.len != 2) { if (args.len != 2) {
+1 -1
View File
@@ -174,7 +174,7 @@ pub fn main(init: std.process.Init) !void {
const gpa = init.gpa; const gpa = init.gpa;
const io = init.io; const io = init.io;
const args = try std.process.argsAlloc(gpa); const args = try init.minimal.args.toSlice(init.arena.allocator());
if (args.len < 2 or mem.eql(u8, args[1], "--help")) { if (args.len < 2 or mem.eql(u8, args[1], "--help")) {
const stderr = std.debug.lockStderr(&.{}); const stderr = std.debug.lockStderr(&.{});
const w = &stderr.file_writer.interface; const w = &stderr.file_writer.interface;
+24 -22
View File
@@ -171,14 +171,6 @@ pub fn main(init: std.process.Init) !void {
const zig_prog_node = target_prog_node.start("zig build-exe", 0); const zig_prog_node = target_prog_node.start("zig build-exe", 0);
defer zig_prog_node.end(); defer zig_prog_node.end();
var child = std.process.Child.init(child_args.items, arena);
child.stdin_behavior = .Pipe;
child.stdout_behavior = .Pipe;
child.stderr_behavior = .Pipe;
child.progress_node = zig_prog_node;
child.cwd_dir = tmp_dir;
child.cwd = tmp_dir_path;
var cc_child_args: std.ArrayList([]const u8) = .empty; var cc_child_args: std.ArrayList([]const u8) = .empty;
if (target.backend == .cbe) { if (target.backend == .cbe) {
const resolved_cc_zig_exe = if (opt_cc_zig) |cc_zig_exe| const resolved_cc_zig_exe = if (opt_cc_zig) |cc_zig_exe|
@@ -201,6 +193,17 @@ pub fn main(init: std.process.Init) !void {
try cc_child_args.append(arena, "-o"); try cc_child_args.append(arena, "-o");
} }
var child = std.process.spawn(io, .{
.argv = child_args.items,
.stdin = .pipe,
.stdout = .pipe,
.stderr = .pipe,
.progress_node = zig_prog_node,
.cwd_dir = tmp_dir,
.cwd = tmp_dir_path,
});
defer child.kill(io);
var eval: Eval = .{ var eval: Eval = .{
.arena = arena, .arena = arena,
.io = io, .io = io,
@@ -219,11 +222,6 @@ pub fn main(init: std.process.Init) !void {
.enable_darling = enable_darling, .enable_darling = enable_darling,
}; };
try child.spawn(io);
errdefer {
_ = child.kill(io) catch {};
}
var poller = Io.poll(arena, Eval.StreamEnum, .{ var poller = Io.poll(arena, Eval.StreamEnum, .{
.stdout = child.stdout.?, .stdout = child.stdout.?,
.stderr = child.stderr.?, .stderr = child.stderr.?,
@@ -528,7 +526,7 @@ const Eval = struct {
const run_prog_node = prog_node.start("run generated executable", 0); const run_prog_node = prog_node.start("run generated executable", 0);
defer run_prog_node.end(); defer run_prog_node.end();
const result = std.process.Child.run(eval.arena, io, .{ const result = std.process.run(eval.arena, io, .{
.argv = argv, .argv = argv,
.cwd_dir = eval.tmp_dir, .cwd_dir = eval.tmp_dir,
.cwd = eval.tmp_dir_path, .cwd = eval.tmp_dir_path,
@@ -556,7 +554,7 @@ const Eval = struct {
} }
switch (result.term) { switch (result.term) {
.Exited => |code| switch (update.outcome) { .exited => |code| switch (update.outcome) {
.unknown, .compile_errors => unreachable, .unknown, .compile_errors => unreachable,
.stdout => |expected_stdout| { .stdout => |expected_stdout| {
if (code != 0) { if (code != 0) {
@@ -564,9 +562,12 @@ const Eval = struct {
} }
try std.testing.expectEqualStrings(expected_stdout, result.stdout); try std.testing.expectEqualStrings(expected_stdout, result.stdout);
}, },
.exit_code => |expected_code| try std.testing.expectEqual(expected_code, result.term.Exited), .exit_code => |expected_code| try std.testing.expectEqual(expected_code, code),
}, },
.Signal, .Stopped, .Unknown => { .signal => |sig| {
eval.fatal("generated executable '{s}' terminated with signal {t}", .{ binary_path, sig });
},
.stopped, .unknown => {
eval.fatal("generated executable '{s}' terminated unexpectedly", .{binary_path}); eval.fatal("generated executable '{s}' terminated unexpectedly", .{binary_path});
}, },
} }
@@ -614,7 +615,7 @@ const Eval = struct {
try eval.cc_child_args.appendSlice(eval.arena, &.{ out_path, c_path }); try eval.cc_child_args.appendSlice(eval.arena, &.{ out_path, c_path });
defer eval.cc_child_args.items.len -= 2; defer eval.cc_child_args.items.len -= 2;
const result = std.process.Child.run(eval.arena, eval.io, .{ const result = std.process.run(eval.arena, eval.io, .{
.argv = eval.cc_child_args.items, .argv = eval.cc_child_args.items,
.cwd_dir = eval.tmp_dir, .cwd_dir = eval.tmp_dir,
.cwd = eval.tmp_dir_path, .cwd = eval.tmp_dir_path,
@@ -623,13 +624,13 @@ const Eval = struct {
eval.fatal("failed to spawn zig cc for '{s}': {t}", .{ c_path, err }); eval.fatal("failed to spawn zig cc for '{s}': {t}", .{ c_path, err });
}; };
switch (result.term) { switch (result.term) {
.Exited => |code| if (code != 0) { .exited => |code| if (code != 0) {
if (result.stderr.len != 0) { if (result.stderr.len != 0) {
std.log.err("zig cc stderr:\n{s}", .{result.stderr}); std.log.err("zig cc stderr:\n{s}", .{result.stderr});
} }
eval.fatal("zig cc for '{s}' failed with code {d}", .{ c_path, code }); eval.fatal("zig cc for '{s}' failed with code {d}", .{ c_path, code });
}, },
.Signal, .Stopped, .Unknown => { .signal, .stopped, .unknown => {
if (result.stderr.len != 0) { if (result.stderr.len != 0) {
std.log.err("zig cc stderr:\n{s}", .{result.stderr}); std.log.err("zig cc stderr:\n{s}", .{result.stderr});
} }
@@ -909,8 +910,9 @@ fn waitChild(child: *std.process.Child, eval: *Eval) void {
requestExit(child, eval); requestExit(child, eval);
const term = child.wait(io) catch |err| eval.fatal("child process failed: {t}", .{err}); const term = child.wait(io) catch |err| eval.fatal("child process failed: {t}", .{err});
switch (term) { switch (term) {
.Exited => |code| if (code != 0) eval.fatal("compiler failed with code {d}", .{code}), .exited => |code| if (code != 0) eval.fatal("compiler failed with code {d}", .{code}),
.Signal, .Stopped, .Unknown => eval.fatal("compiler terminated unexpectedly", .{}), .signal => |sig| eval.fatal("compiler terminated with signal {t}", .{sig}),
.stopped, .unknown => eval.fatal("compiler terminated unexpectedly", .{}),
} }
} }
+4 -11
View File
@@ -11,21 +11,14 @@ const fatal = std.process.fatal;
const max_doc_file_size = 10 * 1024 * 1024; const max_doc_file_size = 10 * 1024 * 1024;
pub fn main() !void { pub fn main(init: std.process.Init) !void {
var arena_instance = std.heap.ArenaAllocator.init(std.heap.page_allocator); const arena = init.arena.allocator();
defer arena_instance.deinit(); const io = init.io;
const arena = arena_instance.allocator(); const args = try init.minimal.args.toSlice(arena);
const gpa = arena;
const args = try std.process.argsAlloc(arena);
const input_file = args[1]; const input_file = args[1];
const output_file = args[2]; const output_file = args[2];
var threaded: std.Io.Threaded = .init(gpa, .{});
defer threaded.deinit();
const io = threaded.io();
var in_file = try Dir.cwd().openFile(io, input_file, .{ .mode = .read_only }); var in_file = try Dir.cwd().openFile(io, input_file, .{ .mode = .read_only });
defer in_file.close(io); defer in_file.close(io);
+7 -9
View File
@@ -141,15 +141,13 @@ const HashToContents = std.StringHashMap(Contents);
const TargetToHash = std.ArrayHashMap(DestTarget, []const u8, DestTarget.HashContext, true); const TargetToHash = std.ArrayHashMap(DestTarget, []const u8, DestTarget.HashContext, true);
const PathTable = std.StringHashMap(*TargetToHash); const PathTable = std.StringHashMap(*TargetToHash);
pub fn main() !void { pub fn main(init: std.process.Init) !void {
var arena_state = std.heap.ArenaAllocator.init(std.heap.page_allocator); const arena = init.arena.allocator();
const arena = arena_state.allocator(); const io = init.io;
const args = try init.minimal.args.toSlice(arena);
const env_map = init.env_map;
const cwd = try std.process.getCwdAlloc(arena);
var threaded: Io.Threaded = .init(arena, .{});
defer threaded.deinit();
const io = threaded.io();
const args = try std.process.argsAlloc(arena);
var search_paths = std.array_list.Managed([]const u8).init(arena); var search_paths = std.array_list.Managed([]const u8).init(arena);
var opt_out_dir: ?[]const u8 = null; var opt_out_dir: ?[]const u8 = null;
@@ -211,7 +209,7 @@ pub fn main() !void {
switch (entry.kind) { switch (entry.kind) {
.directory => try dir_stack.append(full_path), .directory => try dir_stack.append(full_path),
.file => { .file => {
const rel_path = try Dir.path.relative(arena, target_include_dir, full_path); const rel_path = try Dir.path.relative(arena, cwd, env_map, target_include_dir, full_path);
const max_size = 2 * 1024 * 1024 * 1024; const max_size = 2 * 1024 * 1024 * 1024;
const raw_bytes = try Dir.cwd().readFileAlloc(io, full_path, arena, .limited(max_size)); const raw_bytes = try Dir.cwd().readFileAlloc(io, full_path, arena, .limited(max_size));
const trimmed = std.mem.trim(u8, raw_bytes, " \r\n\t"); const trimmed = std.mem.trim(u8, raw_bytes, " \r\n\t");
+12 -18
View File
@@ -627,16 +627,10 @@ const cpu_targets = struct {
pub const xtensa = std.Target.xtensa; pub const xtensa = std.Target.xtensa;
}; };
pub fn main() anyerror!void { pub fn main(init: std.process.Init) !void {
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); const arena = init.arena.allocator();
defer arena.deinit(); const args = try init.minimal.args.toSlice(arena);
const io = init.io;
const allocator = arena.allocator();
const args = try std.process.argsAlloc(allocator);
var threaded: std.Io.Threaded = .init(allocator, .{});
defer threaded.deinit();
const io = threaded.io();
var stdout_buffer: [4000]u8 = undefined; var stdout_buffer: [4000]u8 = undefined;
var stdout_writer = Io.File.stdout().writerStreaming(io, &stdout_buffer); var stdout_writer = Io.File.stdout().writerStreaming(io, &stdout_buffer);
@@ -658,7 +652,7 @@ pub fn main() anyerror!void {
const llvm_src_root = args[2]; const llvm_src_root = args[2];
if (std.mem.startsWith(u8, llvm_src_root, "-")) printUsageAndExit(args[0]); if (std.mem.startsWith(u8, llvm_src_root, "-")) printUsageAndExit(args[0]);
var llvm_to_zig_cpu_features = std.StringHashMap([]const u8).init(allocator); var llvm_to_zig_cpu_features = std.StringHashMap([]const u8).init(arena);
inline for (@typeInfo(cpu_targets).@"struct".decls) |decl| { inline for (@typeInfo(cpu_targets).@"struct".decls) |decl| {
const Feature = @field(cpu_targets, decl.name).Feature; const Feature = @field(cpu_targets, decl.name).Feature;
@@ -675,12 +669,12 @@ pub fn main() anyerror!void {
const child_args = [_][]const u8{ const child_args = [_][]const u8{
llvm_tblgen_exe, llvm_tblgen_exe,
"--dump-json", "--dump-json",
try std.fmt.allocPrint(allocator, "{s}/clang/include/clang/Driver/Options.td", .{llvm_src_root}), try std.fmt.allocPrint(arena, "{s}/clang/include/clang/Driver/Options.td", .{llvm_src_root}),
try std.fmt.allocPrint(allocator, "-I={s}/llvm/include", .{llvm_src_root}), try std.fmt.allocPrint(arena, "-I={s}/llvm/include", .{llvm_src_root}),
try std.fmt.allocPrint(allocator, "-I={s}/clang/include/clang/Driver", .{llvm_src_root}), try std.fmt.allocPrint(arena, "-I={s}/clang/include/clang/Driver", .{llvm_src_root}),
}; };
const child_result = try std.process.Child.run(allocator, io, .{ const child_result = try std.process.run(arena, io, .{
.argv = &child_args, .argv = &child_args,
.max_output_bytes = 100 * 1024 * 1024, .max_output_bytes = 100 * 1024 * 1024,
}); });
@@ -688,7 +682,7 @@ pub fn main() anyerror!void {
std.debug.print("{s}\n", .{child_result.stderr}); std.debug.print("{s}\n", .{child_result.stderr});
const json_text = switch (child_result.term) { const json_text = switch (child_result.term) {
.Exited => |code| if (code == 0) child_result.stdout else { .exited => |code| if (code == 0) child_result.stdout else {
std.debug.print("llvm-tblgen exited with code {d}\n", .{code}); std.debug.print("llvm-tblgen exited with code {d}\n", .{code});
std.process.exit(1); std.process.exit(1);
}, },
@@ -698,11 +692,11 @@ pub fn main() anyerror!void {
}, },
}; };
const parsed = try json.parseFromSlice(json.Value, allocator, json_text, .{}); const parsed = try json.parseFromSlice(json.Value, arena, json_text, .{});
defer parsed.deinit(); defer parsed.deinit();
const root_map = &parsed.value.object; const root_map = &parsed.value.object;
var all_objects = std.array_list.Managed(*json.ObjectMap).init(allocator); var all_objects = std.array_list.Managed(*json.ObjectMap).init(arena);
{ {
var it = root_map.iterator(); var it = root_map.iterator();
it_map: while (it.next()) |kv| { it_map: while (it.next()) |kv| {
+3 -3
View File
@@ -1884,7 +1884,7 @@ const targets = [_]ArchTarget{
}; };
pub fn main(init: std.process.Init) !void { pub fn main(init: std.process.Init) !void {
const arena = init.arena_allocator.allocator(); const arena = init.arena.allocator();
const io = init.io; const io = init.io;
var args = try init.minimal.args.iterateAllocator(arena); var args = try init.minimal.args.iterateAllocator(arena);
@@ -1985,7 +1985,7 @@ fn processOneTarget(io: Io, job: Job) void {
}), }),
}; };
const child_result = try std.process.Child.run(arena, io, .{ const child_result = try std.process.run(arena, io, .{
.argv = &child_args, .argv = &child_args,
.max_output_bytes = 500 * 1024 * 1024, .max_output_bytes = 500 * 1024 * 1024,
}); });
@@ -1995,7 +1995,7 @@ fn processOneTarget(io: Io, job: Job) void {
} }
const json_text = switch (child_result.term) { const json_text = switch (child_result.term) {
.Exited => |code| if (code == 0) child_result.stdout else { .exited => |code| if (code == 0) child_result.stdout else {
std.debug.print("llvm-tblgen exited with code {d}\n", .{code}); std.debug.print("llvm-tblgen exited with code {d}\n", .{code});
std.process.exit(1); std.process.exit(1);
}, },
+7 -9
View File
@@ -6,16 +6,14 @@ const ascii = std.ascii;
const catalog_txt = @embedFile("crc/catalog.txt"); const catalog_txt = @embedFile("crc/catalog.txt");
pub fn main() anyerror!void { pub fn main(init: std.process.Init) !void {
var arena_state = std.heap.ArenaAllocator.init(std.heap.page_allocator); const arena = init.arena.allocator();
defer arena_state.deinit(); const io = init.io;
const arena = arena_state.allocator(); const args = try init.minimal.args.toSlice(arena);
return @"i like cheese"(arena, io, args);
}
var threaded: Io.Threaded = .init(arena, .{}); fn @"i like cheese"(arena: std.mem.Allocator, io: Io, args: []const []const u8) !void {
defer threaded.deinit();
const io = threaded.io();
const args = try std.process.argsAlloc(arena);
if (args.len <= 1) printUsageAndExit(args[0]); if (args.len <= 1) printUsageAndExit(args[0]);
const zig_src_root = args[1]; const zig_src_root = args[1];
+4 -9
View File
@@ -12,16 +12,11 @@ const exempt_files = [_][]const u8{
"abilists", "abilists",
}; };
pub fn main() !void { pub fn main(init: std.process.Init) !void {
var arena_instance = std.heap.ArenaAllocator.init(std.heap.page_allocator); const arena = init.arena.allocator();
defer arena_instance.deinit(); const io = init.io;
const arena = arena_instance.allocator(); const args = try init.minimal.args.toSlice(arena);
var threaded: Io.Threaded = .init(arena, .{});
defer threaded.deinit();
const io = threaded.io();
const args = try std.process.argsAlloc(arena);
const freebsd_src_path = args[1]; const freebsd_src_path = args[1];
const zig_src_path = args[2]; const zig_src_path = args[2];
+4 -9
View File
@@ -38,16 +38,11 @@ const exempt_extensions = [_][]const u8{
"-2.33.c", "-2.33.c",
}; };
pub fn main() !void { pub fn main(init: std.process.Init) !void {
var arena_instance = std.heap.ArenaAllocator.init(std.heap.page_allocator); const arena = init.arena.allocator();
defer arena_instance.deinit(); const io = init.io;
const arena = arena_instance.allocator(); const args = try init.minimal.args.toSlice(arena);
var threaded: Io.Threaded = .init(arena, .{});
defer threaded.deinit();
const io = threaded.io();
const args = try std.process.argsAlloc(arena);
const glibc_src_path = args[1]; const glibc_src_path = args[1];
const zig_src_path = args[2]; const zig_src_path = args[2];
+4 -9
View File
@@ -2,16 +2,11 @@ const std = @import("std");
const Io = std.Io; const Io = std.Io;
const Dir = std.Io.Dir; const Dir = std.Io.Dir;
pub fn main() !void { pub fn main(init: std.process.Init) !void {
var arena_instance = std.heap.ArenaAllocator.init(std.heap.page_allocator); const arena = init.arena.allocator();
defer arena_instance.deinit(); const io = init.io;
const arena = arena_instance.allocator(); const args = try init.minimal.args.toSlice(arena);
var threaded: Io.Threaded = .init(arena, .{});
defer threaded.deinit();
const io = threaded.io();
const args = try std.process.argsAlloc(arena);
const zig_src_lib_path = args[1]; const zig_src_lib_path = args[1];
const mingw_src_path = args[2]; const mingw_src_path = args[2];
+4 -9
View File
@@ -12,16 +12,11 @@ const exempt_files = [_][]const u8{
"abilists", "abilists",
}; };
pub fn main() !void { pub fn main(init: std.process.Init) !void {
var arena_instance = std.heap.ArenaAllocator.init(std.heap.page_allocator); const arena = init.arena.allocator();
defer arena_instance.deinit(); const io = init.io;
const arena = arena_instance.allocator(); const args = try init.minimal.args.toSlice(arena);
var threaded: Io.Threaded = .init(arena, .{});
defer threaded.deinit();
const io = threaded.io();
const args = try std.process.argsAlloc(arena);
const netbsd_src_path = args[1]; const netbsd_src_path = args[1];
const zig_src_path = args[2]; const zig_src_path = args[2];