| 1 | const std = @import("std"); |
| 2 | |
| 3 | /// Returns 1 on success, 0 on failure |
| 4 | export fn verify(argc: c_int, argv: [*]const [*:0]const u16) c_int { |
| 5 | const argv_slice = argv[0..@intCast(argc)]; |
| 6 | testArgv(argv_slice) catch |err| switch (err) { |
| 7 | error.OutOfMemory => @panic("oom"), |
| 8 | error.Unexpected => @panic("unexpected error"), |
| 9 | error.ArgvMismatch => return 0, |
| 10 | }; |
| 11 | return 1; |
| 12 | } |
| 13 | |
| 14 | fn testArgv(expected_args: []const [*:0]const u16) !void { |
| 15 | var arena_state = std.heap.ArenaAllocator.init(std.heap.page_allocator); |
| 16 | defer arena_state.deinit(); |
| 17 | const allocator = arena_state.allocator(); |
| 18 | |
| 19 | const raw_args: std.process.Args = .{ |
| 20 | .vector = std.os.windows.peb().ProcessParameters.CommandLine.slice(), |
| 21 | }; |
| 22 | const args = try raw_args.toSlice(allocator); |
| 23 | var wtf8_buf = std.array_list.Managed(u8).init(allocator); |
| 24 | |
| 25 | var eql = true; |
| 26 | if (args.len != expected_args.len) eql = false; |
| 27 | |
| 28 | const min_len = @min(expected_args.len, args.len); |
| 29 | for (expected_args[0..min_len], args[0..min_len], 0..) |expected_arg, arg_wtf8, i| { |
| 30 | wtf8_buf.clearRetainingCapacity(); |
| 31 | try std.unicode.wtf16LeToWtf8ArrayList(&wtf8_buf, std.mem.span(expected_arg)); |
| 32 | if (!std.mem.eql(u8, wtf8_buf.items, arg_wtf8)) { |
| 33 | std.debug.print("{}: expected: \"{f}\"\n", .{ i, std.zig.fmtString(wtf8_buf.items) }); |
| 34 | std.debug.print("{}: actual: \"{f}\"\n", .{ i, std.zig.fmtString(arg_wtf8) }); |
| 35 | eql = false; |
| 36 | } |
| 37 | } |
| 38 | if (!eql) { |
| 39 | for (expected_args[min_len..], min_len..) |arg, i| { |
| 40 | wtf8_buf.clearRetainingCapacity(); |
| 41 | try std.unicode.wtf16LeToWtf8ArrayList(&wtf8_buf, std.mem.span(arg)); |
| 42 | std.debug.print("{}: expected: \"{f}\"\n", .{ i, std.zig.fmtString(wtf8_buf.items) }); |
| 43 | } |
| 44 | for (args[min_len..], min_len..) |arg, i| { |
| 45 | std.debug.print("{}: actual: \"{f}\"\n", .{ i, std.zig.fmtString(arg) }); |
| 46 | } |
| 47 | const peb = std.os.windows.peb(); |
| 48 | const lpCmdLine: [*:0]u16 = @ptrCast(peb.ProcessParameters.CommandLine.Buffer); |
| 49 | wtf8_buf.clearRetainingCapacity(); |
| 50 | try std.unicode.wtf16LeToWtf8ArrayList(&wtf8_buf, std.mem.span(lpCmdLine)); |
| 51 | std.debug.print("command line: \"{f}\"\n", .{std.zig.fmtString(wtf8_buf.items)}); |
| 52 | std.debug.print("expected argv:\n", .{}); |
| 53 | std.debug.print("&.{{\n", .{}); |
| 54 | for (expected_args) |arg| { |
| 55 | wtf8_buf.clearRetainingCapacity(); |
| 56 | try std.unicode.wtf16LeToWtf8ArrayList(&wtf8_buf, std.mem.span(arg)); |
| 57 | std.debug.print(" \"{f}\",\n", .{std.zig.fmtString(wtf8_buf.items)}); |
| 58 | } |
| 59 | std.debug.print("}}\n", .{}); |
| 60 | return error.ArgvMismatch; |
| 61 | } |
| 62 | } |