2022-02-13 04:35:29 +00:00
|
|
|
const builtin = @import("builtin");
|
2022-12-12 22:14:54 +00:00
|
|
|
const std = @import("std");
|
|
|
|
const expect = std.testing.expect;
|
2017-01-23 21:40:17 +00:00
|
|
|
|
2020-07-11 12:09:04 +01:00
|
|
|
fn add(args: anytype) i32 {
|
2019-11-07 04:25:57 +00:00
|
|
|
var sum = @as(i32, 0);
|
2018-05-01 01:35:54 +01:00
|
|
|
{
|
|
|
|
comptime var i: usize = 0;
|
|
|
|
inline while (i < args.len) : (i += 1) {
|
|
|
|
sum += args[i];
|
|
|
|
}
|
|
|
|
}
|
2017-01-23 21:40:17 +00:00
|
|
|
return sum;
|
|
|
|
}
|
|
|
|
|
2017-05-24 02:38:31 +01:00
|
|
|
test "add arbitrary args" {
|
2021-05-04 19:23:22 +01:00
|
|
|
try expect(add(.{ @as(i32, 1), @as(i32, 2), @as(i32, 3), @as(i32, 4) }) == 10);
|
|
|
|
try expect(add(.{@as(i32, 1234)}) == 1234);
|
|
|
|
try expect(add(.{}) == 0);
|
2017-01-23 21:40:17 +00:00
|
|
|
}
|
2017-01-31 20:50:38 +00:00
|
|
|
|
2020-07-11 12:09:04 +01:00
|
|
|
fn readFirstVarArg(args: anytype) void {
|
2021-06-10 02:35:42 +01:00
|
|
|
_ = args[0];
|
2017-01-31 20:50:38 +00:00
|
|
|
}
|
|
|
|
|
2017-05-24 02:38:31 +01:00
|
|
|
test "send void arg to var args" {
|
2019-12-09 19:55:51 +00:00
|
|
|
readFirstVarArg(.{{}});
|
2017-01-31 20:50:38 +00:00
|
|
|
}
|
2017-03-09 21:13:38 +00:00
|
|
|
|
2017-05-24 02:38:31 +01:00
|
|
|
test "pass args directly" {
|
2022-03-02 01:24:00 +00:00
|
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
2022-10-11 14:39:47 +01:00
|
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
2022-02-13 04:35:29 +00:00
|
|
|
|
2021-05-04 19:23:22 +01:00
|
|
|
try expect(addSomeStuff(.{ @as(i32, 1), @as(i32, 2), @as(i32, 3), @as(i32, 4) }) == 10);
|
|
|
|
try expect(addSomeStuff(.{@as(i32, 1234)}) == 1234);
|
|
|
|
try expect(addSomeStuff(.{}) == 0);
|
2017-03-09 21:13:38 +00:00
|
|
|
}
|
|
|
|
|
2020-07-11 12:09:04 +01:00
|
|
|
fn addSomeStuff(args: anytype) i32 {
|
2017-03-09 21:13:38 +00:00
|
|
|
return add(args);
|
|
|
|
}
|
2017-04-07 02:00:49 +01:00
|
|
|
|
|
|
|
test "runtime parameter before var args" {
|
2022-03-02 01:24:00 +00:00
|
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
2022-10-11 14:39:47 +01:00
|
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
2022-02-13 04:35:29 +00:00
|
|
|
|
2021-05-04 19:23:22 +01:00
|
|
|
try expect((try extraFn(10, .{})) == 0);
|
|
|
|
try expect((try extraFn(10, .{false})) == 1);
|
|
|
|
try expect((try extraFn(10, .{ false, true })) == 2);
|
2017-04-07 02:00:49 +01:00
|
|
|
|
2019-12-09 19:55:51 +00:00
|
|
|
comptime {
|
2021-05-04 19:23:22 +01:00
|
|
|
try expect((try extraFn(10, .{})) == 0);
|
|
|
|
try expect((try extraFn(10, .{false})) == 1);
|
|
|
|
try expect((try extraFn(10, .{ false, true })) == 2);
|
2019-12-09 19:55:51 +00:00
|
|
|
}
|
2017-04-07 02:00:49 +01:00
|
|
|
}
|
|
|
|
|
2021-05-04 19:23:22 +01:00
|
|
|
fn extraFn(extra: u32, args: anytype) !usize {
|
2021-06-20 02:10:22 +01:00
|
|
|
_ = extra;
|
2017-04-07 02:00:49 +01:00
|
|
|
if (args.len >= 1) {
|
2021-05-04 19:23:22 +01:00
|
|
|
try expect(args[0] == false);
|
2017-04-07 02:00:49 +01:00
|
|
|
}
|
|
|
|
if (args.len >= 2) {
|
2021-05-04 19:23:22 +01:00
|
|
|
try expect(args[1] == true);
|
2017-04-07 02:00:49 +01:00
|
|
|
}
|
|
|
|
return args.len;
|
|
|
|
}
|
2017-05-26 19:39:18 +01:00
|
|
|
|
2020-07-11 12:09:04 +01:00
|
|
|
const foos = [_]fn (anytype) bool{
|
2018-05-01 01:35:54 +01:00
|
|
|
foo1,
|
|
|
|
foo2,
|
|
|
|
};
|
2017-05-26 19:39:18 +01:00
|
|
|
|
2020-07-11 12:09:04 +01:00
|
|
|
fn foo1(args: anytype) bool {
|
2021-06-20 02:10:22 +01:00
|
|
|
_ = args;
|
2018-05-01 01:35:54 +01:00
|
|
|
return true;
|
|
|
|
}
|
2020-07-11 12:09:04 +01:00
|
|
|
fn foo2(args: anytype) bool {
|
2021-06-20 02:10:22 +01:00
|
|
|
_ = args;
|
2018-05-01 01:35:54 +01:00
|
|
|
return false;
|
|
|
|
}
|
2017-05-26 19:39:18 +01:00
|
|
|
|
|
|
|
test "array of var args functions" {
|
2021-05-04 19:23:22 +01:00
|
|
|
try expect(foos[0](.{}));
|
|
|
|
try expect(!foos[1](.{}));
|
2017-05-26 19:39:18 +01:00
|
|
|
}
|
2017-05-27 04:31:38 +01:00
|
|
|
|
2018-01-18 20:08:20 +00:00
|
|
|
test "pass zero length array to var args param" {
|
2019-12-09 19:55:51 +00:00
|
|
|
doNothingWithFirstArg(.{""});
|
2018-01-18 20:08:20 +00:00
|
|
|
}
|
|
|
|
|
2020-07-11 12:09:04 +01:00
|
|
|
fn doNothingWithFirstArg(args: anytype) void {
|
2021-06-10 02:35:42 +01:00
|
|
|
_ = args[0];
|
2018-01-18 20:08:20 +00:00
|
|
|
}
|
2022-12-12 22:14:54 +00:00
|
|
|
|
|
|
|
test "simple variadic function" {
|
|
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
|
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
|
|
|
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
|
|
|
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
|
|
|
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
|
|
|
if (builtin.cpu.arch == .aarch64 and builtin.os.tag != .windows and builtin.os.tag != .macos) return error.SkipZigTest; // TODO
|
|
|
|
if (builtin.cpu.arch == .x86_64 and builtin.os.tag == .windows) return error.SkipZigTest; // TODO
|
|
|
|
|
|
|
|
const S = struct {
|
|
|
|
fn simple(...) callconv(.C) c_int {
|
|
|
|
var ap = @cVaStart();
|
|
|
|
defer @cVaEnd(&ap);
|
|
|
|
return @cVaArg(&ap, c_int);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn add(count: c_int, ...) callconv(.C) c_int {
|
|
|
|
var ap = @cVaStart();
|
|
|
|
defer @cVaEnd(&ap);
|
|
|
|
var i: usize = 0;
|
|
|
|
var sum: c_int = 0;
|
|
|
|
while (i < count) : (i += 1) {
|
|
|
|
sum += @cVaArg(&ap, c_int);
|
|
|
|
}
|
|
|
|
return sum;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
try std.testing.expectEqual(@as(c_int, 0), S.simple(@as(c_int, 0)));
|
|
|
|
try std.testing.expectEqual(@as(c_int, 1024), S.simple(@as(c_int, 1024)));
|
|
|
|
try std.testing.expectEqual(@as(c_int, 0), S.add(0));
|
|
|
|
try std.testing.expectEqual(@as(c_int, 1), S.add(1, @as(c_int, 1)));
|
|
|
|
try std.testing.expectEqual(@as(c_int, 3), S.add(2, @as(c_int, 1), @as(c_int, 2)));
|
|
|
|
}
|
|
|
|
|
|
|
|
test "variadic functions" {
|
|
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
|
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
|
|
|
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
|
|
|
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
|
|
|
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
|
|
|
if (builtin.cpu.arch == .aarch64 and builtin.os.tag != .windows and builtin.os.tag != .macos) return error.SkipZigTest; // TODO
|
|
|
|
if (builtin.cpu.arch == .x86_64 and builtin.os.tag == .windows) return error.SkipZigTest; // TODO
|
|
|
|
|
|
|
|
const S = struct {
|
|
|
|
fn printf(list_ptr: *std.ArrayList(u8), format: [*:0]const u8, ...) callconv(.C) void {
|
|
|
|
var ap = @cVaStart();
|
|
|
|
defer @cVaEnd(&ap);
|
|
|
|
vprintf(list_ptr, format, &ap);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn vprintf(
|
|
|
|
list: *std.ArrayList(u8),
|
|
|
|
format: [*:0]const u8,
|
|
|
|
ap: *std.builtin.VaList,
|
|
|
|
) callconv(.C) void {
|
|
|
|
for (std.mem.span(format)) |c| switch (c) {
|
|
|
|
's' => {
|
|
|
|
const arg = @cVaArg(ap, [*:0]const u8);
|
|
|
|
list.writer().print("{s}", .{arg}) catch return;
|
|
|
|
},
|
|
|
|
'd' => {
|
|
|
|
const arg = @cVaArg(ap, c_int);
|
|
|
|
list.writer().print("{d}", .{arg}) catch return;
|
|
|
|
},
|
|
|
|
else => unreachable,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
var list = std.ArrayList(u8).init(std.testing.allocator);
|
|
|
|
defer list.deinit();
|
|
|
|
S.printf(&list, "dsd", @as(c_int, 1), @as([*:0]const u8, "hello"), @as(c_int, 5));
|
|
|
|
try std.testing.expectEqualStrings("1hello5", list.items);
|
|
|
|
}
|
|
|
|
|
|
|
|
test "copy VaList" {
|
|
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
|
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
|
|
|
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
|
|
|
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
|
|
|
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
|
|
|
if (builtin.cpu.arch == .aarch64 and builtin.os.tag != .windows and builtin.os.tag != .macos) return error.SkipZigTest; // TODO
|
|
|
|
if (builtin.cpu.arch == .x86_64 and builtin.os.tag == .windows) return error.SkipZigTest; // TODO
|
|
|
|
|
|
|
|
const S = struct {
|
|
|
|
fn add(count: c_int, ...) callconv(.C) c_int {
|
|
|
|
var ap = @cVaStart();
|
|
|
|
defer @cVaEnd(&ap);
|
|
|
|
var copy = @cVaCopy(&ap);
|
|
|
|
defer @cVaEnd(©);
|
|
|
|
var i: usize = 0;
|
|
|
|
var sum: c_int = 0;
|
|
|
|
while (i < count) : (i += 1) {
|
|
|
|
sum += @cVaArg(&ap, c_int);
|
|
|
|
sum += @cVaArg(©, c_int) * 2;
|
|
|
|
}
|
|
|
|
return sum;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
try std.testing.expectEqual(@as(c_int, 0), S.add(0));
|
|
|
|
try std.testing.expectEqual(@as(c_int, 3), S.add(1, @as(c_int, 1)));
|
|
|
|
try std.testing.expectEqual(@as(c_int, 9), S.add(2, @as(c_int, 1), @as(c_int, 2)));
|
|
|
|
}
|