#undef buz
}
+static void if_args_example(struct kunit *test)
+{
+ enum { Z = 1, Q };
+
+#define foo X, Y
+#define bar IF_ARGS(Z, Q, foo)
+#define buz IF_ARGS(Z, Q, DROP_FIRST_ARG(FIRST_ARG(foo)))
+
+ KUNIT_EXPECT_EQ(test, bar, Z);
+ KUNIT_EXPECT_EQ(test, buz, Q);
+ KUNIT_EXPECT_STREQ(test, __stringify(bar), "Z");
+ KUNIT_EXPECT_STREQ(test, __stringify(buz), "Q");
+
+#undef foo
+#undef bar
+#undef buz
+}
+
static void sep_comma_example(struct kunit *test)
{
#define foo(f) f(X) f(Y) f(Z) f(Q)
KUNIT_EXPECT_STREQ(test, __stringify(LAST_ARG(MAX_ARGS)), "-12");
}
+static void if_args_test(struct kunit *test)
+{
+ bool with_args = true;
+ bool no_args = false;
+ enum { X = 100 };
+
+ KUNIT_EXPECT_TRUE(test, IF_ARGS(true, false, FOO_ARGS));
+ KUNIT_EXPECT_FALSE(test, IF_ARGS(true, false, NO_ARGS));
+
+ KUNIT_EXPECT_TRUE(test, CONCATENATE(IF_ARGS(with, no, FOO_ARGS), _args));
+ KUNIT_EXPECT_FALSE(test, CONCATENATE(IF_ARGS(with, no, NO_ARGS), _args));
+
+ KUNIT_EXPECT_STREQ(test, __stringify(IF_ARGS(yes, no, FOO_ARGS)), "yes");
+ KUNIT_EXPECT_STREQ(test, __stringify(IF_ARGS(yes, no, NO_ARGS)), "no");
+
+ KUNIT_EXPECT_EQ(test, IF_ARGS(CALL_ARGS(COUNT_ARGS, FOO_ARGS), -1, FOO_ARGS), 4);
+ KUNIT_EXPECT_EQ(test, IF_ARGS(CALL_ARGS(COUNT_ARGS, FOO_ARGS), -1, NO_ARGS), -1);
+ KUNIT_EXPECT_EQ(test, IF_ARGS(CALL_ARGS(COUNT_ARGS, NO_ARGS), -1, FOO_ARGS), 0);
+ KUNIT_EXPECT_EQ(test, IF_ARGS(CALL_ARGS(COUNT_ARGS, NO_ARGS), -1, NO_ARGS), -1);
+
+ KUNIT_EXPECT_EQ(test,
+ CALL_ARGS(FIRST_ARG,
+ CALL_ARGS(CONCATENATE, IF_ARGS(FOO, MAX, FOO_ARGS), _ARGS)), X);
+ KUNIT_EXPECT_EQ(test,
+ CALL_ARGS(FIRST_ARG,
+ CALL_ARGS(CONCATENATE, IF_ARGS(FOO, MAX, NO_ARGS), _ARGS)), -1);
+ KUNIT_EXPECT_EQ(test,
+ CALL_ARGS(COUNT_ARGS,
+ CALL_ARGS(CONCATENATE, IF_ARGS(FOO, MAX, FOO_ARGS), _ARGS)), 4);
+ KUNIT_EXPECT_EQ(test,
+ CALL_ARGS(COUNT_ARGS,
+ CALL_ARGS(CONCATENATE, IF_ARGS(FOO, MAX, NO_ARGS), _ARGS)), 12);
+}
+
static struct kunit_case args_tests[] = {
KUNIT_CASE(count_args_test),
KUNIT_CASE(call_args_example),
KUNIT_CASE(last_arg_example),
KUNIT_CASE(last_arg_test),
KUNIT_CASE(pick_arg_example),
+ KUNIT_CASE(if_args_example),
+ KUNIT_CASE(if_args_test),
KUNIT_CASE(sep_comma_example),
{}
};
#define PICK_ARG11(args...) PICK_ARG10(DROP_FIRST_ARG(args))
#define PICK_ARG12(args...) PICK_ARG11(DROP_FIRST_ARG(args))
+/**
+ * IF_ARGS() - Make selection based on optional argument list.
+ * @then: token to return if arguments are present
+ * @else: token to return if arguments are empty
+ * @...: arguments to check (optional)
+ *
+ * This macro allows to select a token based on the presence of the argument list.
+ *
+ * Example:
+ *
+ * #define foo X, Y
+ * #define bar IF_ARGS(Z, Q, foo)
+ * #define buz IF_ARGS(Z, Q, DROP_FIRST_ARG(FIRST_ARG(foo)))
+ *
+ * With above definitions bar expands to Z while buz expands to Q.
+ */
+#if defined(CONFIG_CC_IS_CLANG) || GCC_VERSION >= 100100
+#define IF_ARGS(then, else, ...) FIRST_ARG(__VA_OPT__(then,) else)
+#else
+#define IF_ARGS(then, else, ...) _IF_ARGS(then, else, CALL_ARGS(FIRST_ARG, __VA_ARGS__))
+#define _IF_ARGS(then, else, ...) __IF_ARGS(then, else, CALL_ARGS(COUNT_ARGS, __VA_ARGS__))
+#define __IF_ARGS(then, else, n) ___IF_ARGS(then, else, CALL_ARGS(CONCATENATE, ___IF_ARG, n))
+#define ___IF_ARGS(then, else, if) CALL_ARGS(if, then, else)
+#define ___IF_ARG1(then, else) then
+#define ___IF_ARG0(then, else) else
+#endif
+
/**
* ARGS_SEP_COMMA - Definition of a comma character.
*