mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2025-12-26 15:40:06 +01:00
util: add the macros required for magic vararg expansion
A set of macros that expand to different things depending on the number of arguments passed into the macro. Can be used for anything but in the test case we use it to differ between stringifying the single argument or taking a custom string for that same argument. Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1188>
This commit is contained in:
parent
9d828ae069
commit
d400b17bee
2 changed files with 70 additions and 0 deletions
|
|
@ -77,3 +77,54 @@
|
|||
|
||||
#define _unused_ __attribute__((unused))
|
||||
#define _fallthrough_ __attribute__((fallthrough))
|
||||
|
||||
/* Returns the number of macro arguments, this expands
|
||||
* _VARIABLE_MACRO_NARGS(a, b, c) to NTH_ARG(a, b, c, 15, 14, 13, .... 4, 3, 2, 1).
|
||||
* _VARIABLE_MACRO_NTH_ARG always returns the 16th argument which in our case is 3.
|
||||
*
|
||||
* If we want more than 16 values _VARIABLE_MACRO_COUNTDOWN and
|
||||
* _VARIABLE_MACRO_NTH_ARG both need to be updated.
|
||||
*/
|
||||
#define _VARIABLE_MACRO_NARGS(...) _VARIABLE_MACRO_NARGS1(__VA_ARGS__, _VARIABLE_MACRO_COUNTDOWN)
|
||||
#define _VARIABLE_MACRO_NARGS1(...) _VARIABLE_MACRO_NTH_ARG(__VA_ARGS__)
|
||||
|
||||
/* Add to this if we need more than 16 args */
|
||||
#define _VARIABLE_MACRO_COUNTDOWN \
|
||||
15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
|
||||
|
||||
/* Return the 16th argument passed in. See _VARIABLE_MACRO_NARGS above for usage.
|
||||
* Note this is 1-indexed.
|
||||
*/
|
||||
#define _VARIABLE_MACRO_NTH_ARG( \
|
||||
_1, _2, _3, _4, _5, _6, _7, _8, \
|
||||
_9, _10, _11, _12, _13, _14, _15,\
|
||||
N, ...) N
|
||||
|
||||
/* Defines a different expansion of macros depending on the
|
||||
* number of arguments, e.g. it turns
|
||||
* VARIABLE_MACRO(_ARG, a, b, c) into _ARG3(a, b, c)
|
||||
*
|
||||
* This can be used to have custom macros that expand to different things
|
||||
* depending on the number of arguments. This example converts a
|
||||
* single macro argument into value + stringify, two arguments into
|
||||
* first and second argument.
|
||||
*
|
||||
* #define _ARG1(_1) _1, #_1,
|
||||
* #define _ARG2(_1, _2) _1, _2,
|
||||
*
|
||||
* #define MYMACRO(...) _VARIABLE_MACRO(_ARG, __VA_ARGS__)
|
||||
*
|
||||
* static void foo(int value, char *name) { printf("%d: %s\n", value, name); }
|
||||
*
|
||||
* int main(void) {
|
||||
* foo(MYMACRO(0)); // prints "0: 0"
|
||||
* foo(MYMACRO(0, "zero")); // prints "0: zero"
|
||||
* return 0;
|
||||
* }
|
||||
*
|
||||
* The first argument to VARIABLE_MACRO defines the prefix of the
|
||||
* expander macros (here _ARG -> _ARG0, _ARG1, ...). These need to be defined
|
||||
* in the caller for the number of arguments accepted
|
||||
* (up to _VARIABLE_MACRO_COUNTDOWN args).
|
||||
*/
|
||||
#define _VARIABLE_MACRO(func, ...) CONCAT(func, _VARIABLE_MACRO_NARGS(__VA_ARGS__)) (__VA_ARGS__)
|
||||
|
|
|
|||
|
|
@ -2225,6 +2225,24 @@ START_TEST(attribute_cleanup)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(macros_expand)
|
||||
{
|
||||
#define _A1(_1) _1, #_1
|
||||
#define _A2(_1, _2) _1, _2
|
||||
#define A(...) _VARIABLE_MACRO(_A, __VA_ARGS__)
|
||||
char buf[64];
|
||||
snprintf(buf, sizeof(buf), "%d:%s", A(0));
|
||||
litest_assert_str_eq(buf, "0:0");
|
||||
snprintf(buf, sizeof(buf), "%d:%s", A(100));
|
||||
litest_assert_str_eq(buf, "100:100");
|
||||
snprintf(buf, sizeof(buf), "%d:%s", A(100, "hundred"));
|
||||
litest_assert_str_eq(buf, "100:hundred");
|
||||
#undef _A1
|
||||
#undef _A2
|
||||
#undef A
|
||||
}
|
||||
END_TEST
|
||||
|
||||
int main(void)
|
||||
{
|
||||
struct litest_runner *runner = litest_runner_new();
|
||||
|
|
@ -2297,6 +2315,7 @@ int main(void)
|
|||
|
||||
ADD_TEST(newtype_test);
|
||||
ADD_TEST(attribute_cleanup);
|
||||
ADD_TEST(macros_expand);
|
||||
|
||||
enum litest_runner_result result = litest_runner_run_tests(runner);
|
||||
litest_runner_destroy(runner);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue