Commit d77f5e7aaa

Jacob Young <jacobly0@users.noreply.github.com>
2024-05-26 13:07:44
Progress: fix compile errors on windows
Works for `zig build-exe`, IPC still not implemented yet.
1 parent d403d8c
Changed files (5)
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 = .{
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 {
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 {
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");
+        }
     }
 }
 
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 }));