Commit b33efa3739
Changed files (2)
lib
std
lib/std/zig/c_translation.zig
@@ -390,6 +390,20 @@ pub const Macros = struct {
pub fn WL_CONTAINER_OF(ptr: anytype, sample: anytype, comptime member: []const u8) @TypeOf(sample) {
return @fieldParentPtr(@TypeOf(sample.*), member, ptr);
}
+
+ /// A 2-argument function-like macro defined as #define FOO(A, B) (A)(B)
+ /// could be either: cast B to A, or call A with the value B.
+ pub fn CAST_OR_CALL(a: anytype, b: anytype) switch (@typeInfo(@TypeOf(a))) {
+ .Type => a,
+ .Fn => |fn_info| fn_info.return_type orelse void,
+ else => |info| @compileError("Unexpected argument type: " ++ @tagName(info)),
+ } {
+ switch (@typeInfo(@TypeOf(a))) {
+ .Type => return cast(a, b),
+ .Fn => return a(b),
+ else => unreachable, // return type will be a compile error otherwise
+ }
+ }
};
test "Macro suffix functions" {
@@ -430,3 +444,41 @@ test "WL_CONTAINER_OF" {
var ptr = Macros.WL_CONTAINER_OF(&x.b, &y, "b");
try testing.expectEqual(&x, ptr);
}
+
+test "CAST_OR_CALL casting" {
+ var arg = @as(c_int, 1000);
+ var casted = Macros.CAST_OR_CALL(u8, arg);
+ try testing.expectEqual(cast(u8, arg), casted);
+
+ const S = struct {
+ x: u32 = 0,
+ };
+ var s = S{};
+ var casted_ptr = Macros.CAST_OR_CALL(*u8, &s);
+ try testing.expectEqual(cast(*u8, &s), casted_ptr);
+}
+
+test "CAST_OR_CALL calling" {
+ const Helper = struct {
+ var last_val: bool = false;
+ fn returnsVoid(val: bool) void {
+ last_val = val;
+ }
+ fn returnsBool(f: f32) bool {
+ return f > 0;
+ }
+ fn identity(self: c_uint) c_uint {
+ return self;
+ }
+ };
+
+ Macros.CAST_OR_CALL(Helper.returnsVoid, true);
+ try testing.expectEqual(true, Helper.last_val);
+ Macros.CAST_OR_CALL(Helper.returnsVoid, false);
+ try testing.expectEqual(false, Helper.last_val);
+
+ try testing.expectEqual(Helper.returnsBool(1), Macros.CAST_OR_CALL(Helper.returnsBool, @as(f32, 1)));
+ try testing.expectEqual(Helper.returnsBool(-1), Macros.CAST_OR_CALL(Helper.returnsBool, @as(f32, -1)));
+
+ try testing.expectEqual(Helper.identity(@as(c_uint, 100)), Macros.CAST_OR_CALL(Helper.identity, @as(c_uint, 100)));
+}
src/translate_c.zig
@@ -4868,6 +4868,8 @@ const PatternList = struct {
[2][]const u8{ "Ull_SUFFIX(X) (X ## Ull)", "ULL_SUFFIX" },
[2][]const u8{ "ULL_SUFFIX(X) (X ## ULL)", "ULL_SUFFIX" },
+ [2][]const u8{ "CAST_OR_CALL(X, Y) (X)(Y)", "CAST_OR_CALL" },
+
[2][]const u8{
\\wl_container_of(ptr, sample, member) \
\\(__typeof__(sample))((char *)(ptr) - \
@@ -5048,6 +5050,7 @@ test "Macro matching" {
, "WL_CONTAINER_OF");
try helper.checkMacro(allocator, pattern_list, "NO_MATCH(X, Y) (X + Y)", null);
+ try helper.checkMacro(allocator, pattern_list, "CAST_OR_CALL(X, Y) (X)(Y)", "CAST_OR_CALL");
}
const MacroCtx = struct {