From d77f5e7aaa94b66db4e3604f21c41b315743fb81 Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Sun, 26 May 2024 07:07:44 -0400 Subject: [PATCH] Progress: fix compile errors on windows Works for `zig build-exe`, IPC still not implemented yet. --- lib/std/Progress.zig | 79 ++++++++++++++++++++++++++++++++------------ lib/std/fmt.zig | 59 +++++++++++++++++++-------------- lib/std/io/tty.zig | 2 +- lib/std/process.zig | 5 +-- src/Module.zig | 2 +- 5 files changed, 96 insertions(+), 51 deletions(-) diff --git a/lib/std/Progress.zig b/lib/std/Progress.zig index 216460e6b7..af68899486 100644 --- a/lib/std/Progress.zig +++ b/lib/std/Progress.zig @@ -86,12 +86,20 @@ pub const Node = struct { name: [max_name_len]u8, fn getIpcFd(s: Storage) ?posix.fd_t { - return if (s.estimated_total_count != std.math.maxInt(u32)) null else @bitCast(s.completed_count); + return if (s.estimated_total_count == std.math.maxInt(u32)) switch (@typeInfo(posix.fd_t)) { + .Int => @bitCast(s.completed_count), + .Pointer => @ptrFromInt(s.completed_count), + else => @compileError("unsupported fd_t of " ++ @typeName(posix.fd_t)), + } else null; } fn setIpcFd(s: *Storage, fd: posix.fd_t) void { s.estimated_total_count = std.math.maxInt(u32); - s.completed_count = @bitCast(fd); + s.completed_count = switch (@typeInfo(posix.fd_t)) { + .Int => @bitCast(fd), + .Pointer => @intFromPtr(fd), + else => @compileError("unsupported fd_t of " ++ @typeName(posix.fd_t)), + }; } comptime { @@ -316,12 +324,16 @@ pub fn start(options: Options) Node { global_progress.initial_delay_ns = options.initial_delay_ns; if (std.process.parseEnvVarInt("ZIG_PROGRESS", u31, 10)) |ipc_fd| { - if (std.Thread.spawn(.{}, ipcThreadRun, .{ipc_fd})) |thread| { - global_progress.update_thread = thread; - } else |err| { + global_progress.update_thread = std.Thread.spawn(.{}, ipcThreadRun, .{ + @as(posix.fd_t, switch (@typeInfo(posix.fd_t)) { + .Int => ipc_fd, + .Pointer => @ptrFromInt(ipc_fd), + else => @compileError("unsupported fd_t of " ++ @typeName(posix.fd_t)), + }), + }) catch |err| { std.log.warn("failed to spawn IPC thread for communicating progress to parent: {s}", .{@errorName(err)}); return .{ .index = .none }; - } + }; } else |env_err| switch (env_err) { error.EnvironmentVariableNotFound => { if (options.disable_printing) { @@ -572,6 +584,20 @@ const SavedMetadata = struct { main_index: u16, start_index: u16, nodes_len: u16, + + fn getIpcFd(metadata: SavedMetadata) posix.fd_t { + return if (builtin.os.tag == .windows) + @ptrFromInt(@as(usize, metadata.ipc_fd) << 2) + else + metadata.ipc_fd; + } + + fn setIpcFd(fd: posix.fd_t) u16 { + return @intCast(if (builtin.os.tag == .windows) + @shrExact(@intFromPtr(fd), 2) + else + fd); + } }; fn serializeIpc(start_serialized_len: usize) usize { @@ -638,7 +664,7 @@ fn serializeIpc(start_serialized_len: usize) usize { // Remember in case the pipe is empty on next update. ipc_metadata[ipc_metadata_len] = .{ - .ipc_fd = @intCast(fd), + .ipc_fd = SavedMetadata.setIpcFd(fd), .start_index = @intCast(serialized_len), .nodes_len = @intCast(parents.len), .main_index = @intCast(main_index), @@ -687,7 +713,7 @@ fn copyRoot(dest: *Node.Storage, src: *align(2) Node.Storage) void { fn findOld(ipc_fd: posix.fd_t, old_metadata: []const SavedMetadata) ?*const SavedMetadata { for (old_metadata) |*m| { - if (m.ipc_fd == ipc_fd) + if (m.getIpcFd() == ipc_fd) return m; } return null; @@ -711,7 +737,7 @@ fn useSavedIpcData( const old_main_index = saved_metadata.main_index; ipc_metadata[ipc_metadata_len] = .{ - .ipc_fd = @intCast(ipc_fd), + .ipc_fd = SavedMetadata.setIpcFd(ipc_fd), .start_index = @intCast(start_serialized_len), .nodes_len = nodes_len, .main_index = @intCast(main_index), @@ -911,21 +937,32 @@ fn writeIpc(fd: posix.fd_t, serialized: Serialized) error{BrokenPipe}!void { fn maybeUpdateSize(resize_flag: bool) void { if (!resize_flag) return; - var winsize: posix.winsize = .{ - .ws_row = 0, - .ws_col = 0, - .ws_xpixel = 0, - .ws_ypixel = 0, - }; - const fd = (global_progress.terminal orelse return).handle; - const err = posix.system.ioctl(fd, posix.T.IOCGWINSZ, @intFromPtr(&winsize)); - if (posix.errno(err) == .SUCCESS) { - global_progress.rows = winsize.ws_row; - global_progress.cols = winsize.ws_col; + if (builtin.os.tag == .windows) { + var info: windows.CONSOLE_SCREEN_BUFFER_INFO = undefined; + + if (windows.kernel32.GetConsoleScreenBufferInfo(fd, &info) == windows.FALSE) { + @panic("TODO: handle this failure"); + } + + global_progress.rows = @intCast(info.dwSize.Y); + global_progress.cols = @intCast(info.dwSize.X); } else { - @panic("TODO: handle this failure"); + var winsize: posix.winsize = .{ + .ws_row = 0, + .ws_col = 0, + .ws_xpixel = 0, + .ws_ypixel = 0, + }; + + const err = posix.system.ioctl(fd, posix.T.IOCGWINSZ, @intFromPtr(&winsize)); + if (posix.errno(err) == .SUCCESS) { + global_progress.rows = winsize.ws_row; + global_progress.cols = winsize.ws_col; + } else { + @panic("TODO: handle this failure"); + } } } diff --git a/lib/std/fmt.zig b/lib/std/fmt.zig index 2d1f4402d6..1a7475e1c5 100644 --- a/lib/std/fmt.zig +++ b/lib/std/fmt.zig @@ -9,7 +9,7 @@ const assert = std.debug.assert; const mem = std.mem; const unicode = std.unicode; const meta = std.meta; -const lossyCast = std.math.lossyCast; +const lossyCast = math.lossyCast; const expectFmt = std.testing.expectFmt; pub const default_max_depth = 3; @@ -1494,10 +1494,20 @@ pub fn Formatter(comptime format_fn: anytype) type { /// Ignores '_' character in `buf`. /// See also `parseUnsigned`. pub fn parseInt(comptime T: type, buf: []const u8, base: u8) ParseIntError!T { + return parseIntWithGenericCharacter(T, u8, buf, base); +} + +/// Like `parseInt`, but with a generic `Character` type. +pub fn parseIntWithGenericCharacter( + comptime Result: type, + comptime Character: type, + buf: []const Character, + base: u8, +) ParseIntError!Result { if (buf.len == 0) return error.InvalidCharacter; - if (buf[0] == '+') return parseWithSign(T, buf[1..], base, .pos); - if (buf[0] == '-') return parseWithSign(T, buf[1..], base, .neg); - return parseWithSign(T, buf, base, .pos); + if (buf[0] == '+') return parseIntWithSign(Result, Character, buf[1..], base, .pos); + if (buf[0] == '-') return parseIntWithSign(Result, Character, buf[1..], base, .neg); + return parseIntWithSign(Result, Character, buf, base, .pos); } test parseInt { @@ -1560,12 +1570,13 @@ test parseInt { try std.testing.expectEqual(@as(i5, -16), try std.fmt.parseInt(i5, "-10", 16)); } -fn parseWithSign( - comptime T: type, - buf: []const u8, +fn parseIntWithSign( + comptime Result: type, + comptime Character: type, + buf: []const Character, base: u8, comptime sign: enum { pos, neg }, -) ParseIntError!T { +) ParseIntError!Result { if (buf.len == 0) return error.InvalidCharacter; var buf_base = base; @@ -1575,7 +1586,7 @@ fn parseWithSign( buf_base = 10; // Detect the base by looking at buf prefix. if (buf.len > 2 and buf[0] == '0') { - switch (std.ascii.toLower(buf[1])) { + if (math.cast(u8, buf[1])) |c| switch (std.ascii.toLower(c)) { 'b' => { buf_base = 2; buf_start = buf[2..]; @@ -1589,7 +1600,7 @@ fn parseWithSign( buf_start = buf[2..]; }, else => {}, - } + }; } } @@ -1598,33 +1609,33 @@ fn parseWithSign( .neg => math.sub, }; - // accumulate into U which is always 8 bits or larger. this prevents - // `buf_base` from overflowing T. - const info = @typeInfo(T); - const U = std.meta.Int(info.Int.signedness, @max(8, info.Int.bits)); - var x: U = 0; + // accumulate into Accumulate which is always 8 bits or larger. this prevents + // `buf_base` from overflowing Result. + const info = @typeInfo(Result); + const Accumulate = std.meta.Int(info.Int.signedness, @max(8, info.Int.bits)); + var accumulate: Accumulate = 0; if (buf_start[0] == '_' or buf_start[buf_start.len - 1] == '_') return error.InvalidCharacter; for (buf_start) |c| { if (c == '_') continue; - const digit = try charToDigit(c, buf_base); - if (x != 0) { - x = try math.mul(U, x, math.cast(U, buf_base) orelse return error.Overflow); + const digit = try charToDigit(math.cast(u8, c) orelse return error.InvalidCharacter, buf_base); + if (accumulate != 0) { + accumulate = try math.mul(Accumulate, accumulate, math.cast(Accumulate, buf_base) orelse return error.Overflow); } else if (sign == .neg) { // The first digit of a negative number. // Consider parsing "-4" as an i3. // This should work, but positive 4 overflows i3, so we can't cast the digit to T and subtract. - x = math.cast(U, -@as(i8, @intCast(digit))) orelse return error.Overflow; + accumulate = math.cast(Accumulate, -@as(i8, @intCast(digit))) orelse return error.Overflow; continue; } - x = try add(U, x, math.cast(U, digit) orelse return error.Overflow); + accumulate = try add(Accumulate, accumulate, math.cast(Accumulate, digit) orelse return error.Overflow); } - return if (T == U) - x + return if (Result == Accumulate) + accumulate else - math.cast(T, x) orelse return error.Overflow; + math.cast(Result, accumulate) orelse return error.Overflow; } /// Parses the string `buf` as unsigned representation in the specified base @@ -1639,7 +1650,7 @@ fn parseWithSign( /// Ignores '_' character in `buf`. /// See also `parseInt`. pub fn parseUnsigned(comptime T: type, buf: []const u8, base: u8) ParseIntError!T { - return parseWithSign(T, buf, base, .pos); + return parseIntWithSign(T, u8, buf, base, .pos); } test parseUnsigned { diff --git a/lib/std/io/tty.zig b/lib/std/io/tty.zig index baf54a1fdf..cdeaba81c5 100644 --- a/lib/std/io/tty.zig +++ b/lib/std/io/tty.zig @@ -24,7 +24,7 @@ pub fn detectConfig(file: File) Config { if (native_os == .windows and file.isTty()) { var info: windows.CONSOLE_SCREEN_BUFFER_INFO = undefined; - if (windows.kernel32.GetConsoleScreenBufferInfo(file.handle, &info) != windows.TRUE) { + if (windows.kernel32.GetConsoleScreenBufferInfo(file.handle, &info) == windows.FALSE) { return if (force_color == true) .escape_codes else .no_color; } return .{ .windows_api = .{ diff --git a/lib/std/process.zig b/lib/std/process.zig index e9de2cf517..7d1f817337 100644 --- a/lib/std/process.zig +++ b/lib/std/process.zig @@ -442,10 +442,7 @@ pub fn parseEnvVarInt(comptime key: []const u8, comptime I: type, base: u8) Pars if (native_os == .windows) { const key_w = comptime std.unicode.utf8ToUtf16LeStringLiteral(key); const text = getenvW(key_w) orelse return error.EnvironmentVariableNotFound; - // For this implementation perhaps std.fmt.parseInt can be expanded to be generic across - // []u8 and []u16 like how many std.mem functions work. - _ = text; - @compileError("TODO implement this"); + return std.fmt.parseIntWithGenericCharacter(I, u16, text, base); } else if (native_os == .wasi and !builtin.link_libc) { @compileError("parseEnvVarInt is not supported for WASI without libc"); } else { diff --git a/src/Module.zig b/src/Module.zig index d38a233a77..bfd79e6117 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -4504,7 +4504,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: InternPool.Index, arena: Allocato log.debug("finish func name '{}'", .{(decl.fullyQualifiedName(mod) catch break :blk).fmt(ip)}); } - const decl_prog_node = mod.sema_prog_ndoe.start((try decl.fullyQualifiedName(mod)).toSlice(ip), 0); + const decl_prog_node = mod.sema_prog_node.start((try decl.fullyQualifiedName(mod)).toSlice(ip), 0); defer decl_prog_node.end(); mod.intern_pool.removeDependenciesForDepender(gpa, InternPool.Depender.wrap(.{ .func = func_index }));