mirror of
https://codeberg.org/ziglang/zig.git
synced 2026-05-21 16:41:56 +03:00
implement defining C variadic functions
This commit is contained in:
+108
-1
@@ -1,5 +1,6 @@
|
||||
const builtin = @import("builtin");
|
||||
const expect = @import("std").testing.expect;
|
||||
const std = @import("std");
|
||||
const expect = std.testing.expect;
|
||||
|
||||
fn add(args: anytype) i32 {
|
||||
var sum = @as(i32, 0);
|
||||
@@ -91,3 +92,109 @@ test "pass zero length array to var args param" {
|
||||
fn doNothingWithFirstArg(args: anytype) void {
|
||||
_ = args[0];
|
||||
}
|
||||
|
||||
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)));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
fn foo(...) void {}
|
||||
fn bar(a: anytype, ...) callconv(a) void {}
|
||||
|
||||
comptime { _ = foo; }
|
||||
comptime { _ = bar; }
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :1:1: error: variadic function must have 'C' calling convention
|
||||
// :2:1: error: generic function cannot be variadic
|
||||
Reference in New Issue
Block a user