sys: util: Added separator to FOR_EACH_ macros

Added separator (e.g. comma or semicolon) parameter to FOR_EACH_ family.
Separator is added between macro execution for each argument and not at
the end.

Signed-off-by: Krzysztof Chruscinski <krzysztof.chruscinski@nordicsemi.no>
This commit is contained in:
Krzysztof Chruscinski 2020-05-08 07:06:58 +02:00 committed by Carles Cufí
commit 1b4b9386e5
8 changed files with 56 additions and 46 deletions

View file

@ -121,7 +121,7 @@ struct z_app_region {
.bss_start = &Z_APP_BSS_START(name), \ .bss_start = &Z_APP_BSS_START(name), \
.bss_size = (size_t) &Z_APP_BSS_SIZE(name) \ .bss_size = (size_t) &Z_APP_BSS_SIZE(name) \
}; \ }; \
Z_APPMEM_PLACEHOLDER(name); Z_APPMEM_PLACEHOLDER(name)
#else #else
#define K_APP_BMEM(ptn) #define K_APP_BMEM(ptn)

View file

@ -830,7 +830,7 @@ extern FUNC_NORETURN void k_thread_user_mode_enter(k_thread_entry_t entry,
* @param ... list of kernel object pointers * @param ... list of kernel object pointers
*/ */
#define k_thread_access_grant(thread, ...) \ #define k_thread_access_grant(thread, ...) \
FOR_EACH_FIXED_ARG(k_object_access_grant, thread, __VA_ARGS__) FOR_EACH_FIXED_ARG(k_object_access_grant, (;), thread, __VA_ARGS__)
/** /**
* @brief Assign a resource memory pool to a thread * @brief Assign a resource memory pool to a thread

View file

@ -206,9 +206,9 @@ extern "C" {
#define _LOG_INTERNAL_3(_src_level, _str, _arg0, _arg1, _arg2) \ #define _LOG_INTERNAL_3(_src_level, _str, _arg0, _arg1, _arg2) \
log_3(_str, (log_arg_t)(_arg0), (log_arg_t)(_arg1), (log_arg_t)(_arg2), _src_level) log_3(_str, (log_arg_t)(_arg0), (log_arg_t)(_arg1), (log_arg_t)(_arg2), _src_level)
#define __LOG_ARG_CAST(_x) (log_arg_t)(_x), #define __LOG_ARG_CAST(_x) (log_arg_t)(_x)
#define __LOG_ARGUMENTS(...) FOR_EACH(__LOG_ARG_CAST, __VA_ARGS__) #define __LOG_ARGUMENTS(...) FOR_EACH(__LOG_ARG_CAST, (,), __VA_ARGS__)
#define _LOG_INTERNAL_LONG(_src_level, _str, ...) \ #define _LOG_INTERNAL_LONG(_src_level, _str, ...) \
do { \ do { \

View file

@ -408,7 +408,7 @@ uint8_t u8_to_dec(char *buf, uint8_t buflen, uint8_t value);
* @param ... list to be processed * @param ... list to be processed
*/ */
#define LIST_DROP_EMPTY(...) \ #define LIST_DROP_EMPTY(...) \
Z_LIST_DROP_FIRST(FOR_EACH(Z_LIST_NO_EMPTIES, __VA_ARGS__)) Z_LIST_DROP_FIRST(FOR_EACH(Z_LIST_NO_EMPTIES, (), __VA_ARGS__))
/* Adding ',' after each element would add empty element at the end of /* Adding ',' after each element would add empty element at the end of
* list, which is hard to remove, so instead precede each element with ',', * list, which is hard to remove, so instead precede each element with ',',
@ -959,16 +959,16 @@ uint8_t u8_to_dec(char *buf, uint8_t buflen, uint8_t value);
#define UTIL_LISTIFY(LEN, F, ...) UTIL_EVAL(UTIL_REPEAT(LEN, F, __VA_ARGS__)) #define UTIL_LISTIFY(LEN, F, ...) UTIL_EVAL(UTIL_REPEAT(LEN, F, __VA_ARGS__))
/* Set of internal macros used for FOR_EACH series of macros. */ /* Set of internal macros used for FOR_EACH series of macros. */
#define Z_FOR_EACH_IDX(count, n, macro, semicolon, fixed_arg0, fixed_arg1, ...)\ #define Z_FOR_EACH_IDX(count, n, macro, sep, fixed_arg0, fixed_arg1, ...)\
UTIL_WHEN(count) \ UTIL_WHEN(count) \
( \ ( \
UTIL_OBSTRUCT(macro) \ UTIL_OBSTRUCT(macro) \
( \ ( \
fixed_arg0, fixed_arg1, n, GET_ARG1(__VA_ARGS__)\ fixed_arg0, fixed_arg1, n, GET_ARG1(__VA_ARGS__)\
)semicolon \ ) COND_CODE_1(count, (), (__DEBRACKET sep)) \
UTIL_OBSTRUCT(Z_FOR_EACH_IDX_INDIRECT) () \ UTIL_OBSTRUCT(Z_FOR_EACH_IDX_INDIRECT) () \
( \ ( \
UTIL_DEC(count), UTIL_INC(n), macro, semicolon, \ UTIL_DEC(count), UTIL_INC(n), macro, sep, \
fixed_arg0, fixed_arg1, \ fixed_arg0, fixed_arg1, \
GET_ARGS_LESS_1(__VA_ARGS__) \ GET_ARGS_LESS_1(__VA_ARGS__) \
) \ ) \
@ -992,10 +992,13 @@ uint8_t u8_to_dec(char *buf, uint8_t buflen, uint8_t value);
* @brief Calls macro F for each provided argument with index as first argument * @brief Calls macro F for each provided argument with index as first argument
* and nth parameter as the second argument. * and nth parameter as the second argument.
* *
* @note Separator argument must be in parentheses. It is required to enable
* providing comma as separator.
*
* Example: * Example:
* *
* #define F(idx, x) int a##idx = x; * #define F(idx, x) int a##idx = x
* FOR_EACH_IDX(F, 4, 5, 6) * FOR_EACH_IDX(F, (;), 4, 5, 6);
* *
* will result in following code: * will result in following code:
* *
@ -1005,11 +1008,12 @@ uint8_t u8_to_dec(char *buf, uint8_t buflen, uint8_t value);
* *
* @param F Macro takes index and first argument and nth variable argument as * @param F Macro takes index and first argument and nth variable argument as
* the second one. * the second one.
* @param sep Separator (e.g. comma or semicolon). Must be in parentheses.
* @param ... Variable list of argument. For each argument macro F is executed. * @param ... Variable list of argument. For each argument macro F is executed.
*/ */
#define FOR_EACH_IDX(F, ...) \ #define FOR_EACH_IDX(F, sep, ...) \
Z_FOR_EACH_IDX2(NUM_VA_ARGS_LESS_1(__VA_ARGS__, _), \ Z_FOR_EACH_IDX2(NUM_VA_ARGS_LESS_1(__VA_ARGS__, _), \
0, Z_FOR_EACH_SWALLOW_FIXED_ARG, /*no ;*/, \ 0, Z_FOR_EACH_SWALLOW_FIXED_ARG, sep, \
F, 0, __VA_ARGS__) F, 0, __VA_ARGS__)
/** /**
@ -1017,10 +1021,12 @@ uint8_t u8_to_dec(char *buf, uint8_t buflen, uint8_t value);
* and nth parameter as the second argument and fixed argument as the * and nth parameter as the second argument and fixed argument as the
* third one. * third one.
* *
* @note Separator argument must be in parentheses. It is required to enable
* providing comma as separator.
* Example: * Example:
* *
* #define F(idx, x, fixed_arg) int fixed_arg##idx = x; * #define F(idx, x, fixed_arg) int fixed_arg##idx = x
* FOR_EACH_IDX_FIXED_ARG(F, a, 4, 5, 6) * FOR_EACH_IDX_FIXED_ARG(F, (;), a, 4, 5, 6);
* *
* will result in following code: * will result in following code:
* *
@ -1030,21 +1036,24 @@ uint8_t u8_to_dec(char *buf, uint8_t buflen, uint8_t value);
* *
* @param F Macro takes index and first argument and nth variable argument as * @param F Macro takes index and first argument and nth variable argument as
* the second one and fixed argumnet as the third. * the second one and fixed argumnet as the third.
* @param sep Separator (e.g. comma or semicolon). Must be in parentheses.
* @param fixed_arg Fixed argument passed to F macro. * @param fixed_arg Fixed argument passed to F macro.
* @param ... Variable list of argument. For each argument macro F is executed. * @param ... Variable list of argument. For each argument macro F is executed.
*/ */
#define FOR_EACH_IDX_FIXED_ARG(F, fixed_arg, ...) \ #define FOR_EACH_IDX_FIXED_ARG(F, sep, fixed_arg, ...) \
Z_FOR_EACH_IDX2(NUM_VA_ARGS_LESS_1(__VA_ARGS__, _), \ Z_FOR_EACH_IDX2(NUM_VA_ARGS_LESS_1(__VA_ARGS__, _), \
0, Z_FOR_EACH_SWALLOW_NOTHING, /*no ;*/, \ 0, Z_FOR_EACH_SWALLOW_NOTHING, sep, \
F, fixed_arg, __VA_ARGS__) F, fixed_arg, __VA_ARGS__)
/** /**
* @brief Calls macro F for each provided argument. * @brief Calls macro F for each provided argument.
* *
* @note Separator argument must be in parentheses. It is required to enable
* providing comma as separator.
* Example: * Example:
* *
* #define F(x) int a##x; * #define F(x) int a##x
* FOR_EACH(F, 4, 5, 6) * FOR_EACH(F, (;), 4, 5, 6);
* *
* will result in following code: * will result in following code:
* *
@ -1053,23 +1062,25 @@ uint8_t u8_to_dec(char *buf, uint8_t buflen, uint8_t value);
* int a6; * int a6;
* *
* @param F Macro takes nth variable argument as the argument. * @param F Macro takes nth variable argument as the argument.
* @param sep Separator (e.g. comma or semicolon). Must be in parentheses.
* @param ... Variable list of argument. For each argument macro F is executed. * @param ... Variable list of argument. For each argument macro F is executed.
*/ */
#define FOR_EACH(F, ...) \ #define FOR_EACH(F, sep, ...) \
Z_FOR_EACH_IDX2(NUM_VA_ARGS_LESS_1(__VA_ARGS__, _), \ Z_FOR_EACH_IDX2(NUM_VA_ARGS_LESS_1(__VA_ARGS__, _), \
0, Z_FOR_EACH_SWALLOW_INDEX_FIXED_ARG, /*no ;*/, \ 0, Z_FOR_EACH_SWALLOW_INDEX_FIXED_ARG, sep, \
F, 0, __VA_ARGS__) F, 0, __VA_ARGS__)
/** /**
* @brief Calls macro F for each provided argument with additional fixed * @brief Calls macro F for each provided argument with additional fixed
* argument. * argument.
* *
* After each iteration semicolon is added. * @note Separator argument must be in parentheses. It is required to enable
* providing comma as separator.
* *
* Example: * Example:
* *
* static void func(int val, void *dev); * static void func(int val, void *dev);
* FOR_EACH_FIXED_ARG(func, dev, 4, 5, 6) * FOR_EACH_FIXED_ARG(func, (;), dev, 4, 5, 6);
* *
* will result in following code: * will result in following code:
* *
@ -1079,12 +1090,13 @@ uint8_t u8_to_dec(char *buf, uint8_t buflen, uint8_t value);
* *
* @param F Macro takes nth variable argument as the first parameter and * @param F Macro takes nth variable argument as the first parameter and
* fixed argument as the second parameter. * fixed argument as the second parameter.
* @param sep Separator (e.g. comma or semicolon). Must be in parentheses.
* @param fixed_arg Fixed argument forward to macro execution for each argument. * @param fixed_arg Fixed argument forward to macro execution for each argument.
* @param ... Variable list of argument. For each argument macro F is executed. * @param ... Variable list of argument. For each argument macro F is executed.
*/ */
#define FOR_EACH_FIXED_ARG(F, fixed_arg, ...) \ #define FOR_EACH_FIXED_ARG(F, sep, fixed_arg, ...) \
Z_FOR_EACH_IDX2(NUM_VA_ARGS_LESS_1(__VA_ARGS__, _), \ Z_FOR_EACH_IDX2(NUM_VA_ARGS_LESS_1(__VA_ARGS__, _), \
0, Z_FOR_EACH_SWALLOW_INDEX, ;, \ 0, Z_FOR_EACH_SWALLOW_INDEX, sep, \
F, fixed_arg, __VA_ARGS__) F, fixed_arg, __VA_ARGS__)
/**@brief Implementation details for NUM_VAR_ARGS */ /**@brief Implementation details for NUM_VAR_ARGS */
@ -1120,13 +1132,13 @@ uint8_t u8_to_dec(char *buf, uint8_t buflen, uint8_t value);
* *
* @deprecated Use FOR_EACH instead. * @deprecated Use FOR_EACH instead.
* *
* @param ... Macro name to be used for argument processing followed by * @param F Macro name to be used for argument processing Macro should have
* arguments to process. Macro should have following * following form: MACRO(argument).
* form: MACRO(argument). * @param ... Arguments to process.
* *
* @return All arguments processed by given macro * @return All arguments processed by given macro
*/ */
#define MACRO_MAP(...) __DEPRECATED_MACRO FOR_EACH(__VA_ARGS__) #define MACRO_MAP(F, ...) __DEPRECATED_MACRO FOR_EACH(F, (), __VA_ARGS__)
/** /**
* @brief Mapping macro that pastes results together * @brief Mapping macro that pastes results together

View file

@ -27,7 +27,7 @@
*/ */
/* prepare the memory partition structures */ /* prepare the memory partition structures */
FOR_EACH(K_APPMEM_PARTITION_DEFINE, part0, part1, part2, part3, part4); FOR_EACH(K_APPMEM_PARTITION_DEFINE, (;), part0, part1, part2, part3, part4);
/* prepare the memory domain structures */ /* prepare the memory domain structures */
struct k_mem_domain dom0, dom1, dom2; struct k_mem_domain dom0, dom1, dom2;
/* each variable starts with a name defined in main.h /* each variable starts with a name defined in main.h

View file

@ -41,7 +41,7 @@ K_SEM_DEFINE(expect_fault_sem, 0, 1);
* ztest and this test suite. part1 is for * ztest and this test suite. part1 is for
* subsequent test specifically for this new implementation. * subsequent test specifically for this new implementation.
*/ */
FOR_EACH(K_APPMEM_PARTITION_DEFINE, part0, part1); FOR_EACH(K_APPMEM_PARTITION_DEFINE, (;), part0, part1);
/* /*
* Create memory domains. dom0 is for the ztest and this * Create memory domains. dom0 is for the ztest and this

View file

@ -627,7 +627,7 @@ void test_poll_grant_access(void)
&no_wait_signal, &wait_sem, &wait_fifo, &no_wait_signal, &wait_sem, &wait_fifo,
&cancel_fifo, &non_cancel_fifo, &cancel_fifo, &non_cancel_fifo,
&wait_signal, &test_thread, &wait_signal, &test_thread,
&test_stack, &multi_sem, &multi_reply) &test_stack, &multi_sem, &multi_reply);
} }
void test_poll_zero_events(void) void test_poll_zero_events(void)

View file

@ -219,12 +219,12 @@ static void test_z_max_z_min(void)
static void test_FOR_EACH(void) static void test_FOR_EACH(void)
{ {
#define FOR_EACH_MACRO_TEST(arg) *buf++ = arg; #define FOR_EACH_MACRO_TEST(arg) *buf++ = arg
uint8_t array[3] = {0}; uint8_t array[3] = {0};
uint8_t *buf = array; uint8_t *buf = array;
FOR_EACH(FOR_EACH_MACRO_TEST, 1, 2, 3) FOR_EACH(FOR_EACH_MACRO_TEST, (;), 1, 2, 3);
zassert_equal(array[0], 1, "Unexpected value %d", array[0]); zassert_equal(array[0], 1, "Unexpected value %d", array[0]);
zassert_equal(array[1], 2, "Unexpected value %d", array[1]); zassert_equal(array[1], 2, "Unexpected value %d", array[1]);
@ -240,25 +240,25 @@ static void test_FOR_EACH_FIXED_ARG(void)
{ {
uint32_t sum = 0; uint32_t sum = 0;
FOR_EACH_FIXED_ARG(fsum, &sum, 1, 2, 3) FOR_EACH_FIXED_ARG(fsum, (;), &sum, 1, 2, 3);
zassert_equal(sum, 6, "Unexpected value %d", sum); zassert_equal(sum, 6, "Unexpected value %d", sum);
} }
static void test_FOR_EACH_IDX(void) static void test_FOR_EACH_IDX(void)
{ {
#define FOR_EACH_IDX_MACRO_TEST(n, arg) uint8_t a##n = arg; #define FOR_EACH_IDX_MACRO_TEST(n, arg) uint8_t a##n = arg
FOR_EACH_IDX(FOR_EACH_IDX_MACRO_TEST, 1, 2, 3) FOR_EACH_IDX(FOR_EACH_IDX_MACRO_TEST, (;), 1, 2, 3);
zassert_equal(a0, 1, "Unexpected value %d", a0); zassert_equal(a0, 1, "Unexpected value %d", a0);
zassert_equal(a1, 2, "Unexpected value %d", a1); zassert_equal(a1, 2, "Unexpected value %d", a1);
zassert_equal(a2, 3, "Unexpected value %d", a2); zassert_equal(a2, 3, "Unexpected value %d", a2);
#define FOR_EACH_IDX_MACRO_TEST2(n, arg) array[n] = arg; #define FOR_EACH_IDX_MACRO_TEST2(n, arg) array[n] = arg
uint8_t array[32] = {0}; uint8_t array[32] = {0};
FOR_EACH_IDX(FOR_EACH_IDX_MACRO_TEST2, 1, 2, 3, 4, 5, 6, 7, 8, FOR_EACH_IDX(FOR_EACH_IDX_MACRO_TEST2, (;), 1, 2, 3, 4, 5, 6, 7, 8,
9, 10, 11, 12, 13, 14, 15); 9, 10, 11, 12, 13, 14, 15);
for (int i = 0; i < 15; i++) { for (int i = 0; i < 15; i++) {
zassert_equal(array[i], i + 1, zassert_equal(array[i], i + 1,
@ -266,10 +266,10 @@ static void test_FOR_EACH_IDX(void)
} }
zassert_equal(array[15], 0, "Unexpected value: %d", array[15]); zassert_equal(array[15], 0, "Unexpected value: %d", array[15]);
#define FOR_EACH_IDX_MACRO_TEST3(n, arg) &a##n, #define FOR_EACH_IDX_MACRO_TEST3(n, arg) &a##n
uint8_t *a[] = { uint8_t *a[] = {
FOR_EACH_IDX(FOR_EACH_IDX_MACRO_TEST3, 1, 2, 3) FOR_EACH_IDX(FOR_EACH_IDX_MACRO_TEST3, (,), 1, 2, 3)
}; };
zassert_equal(ARRAY_SIZE(a), 3, "Unexpected value:%d", ARRAY_SIZE(a)); zassert_equal(ARRAY_SIZE(a), 3, "Unexpected value:%d", ARRAY_SIZE(a));
@ -279,9 +279,9 @@ static void test_FOR_EACH_IDX_FIXED_ARG(void)
{ {
#undef FOO #undef FOO
#define FOO(n, arg, fixed_arg) \ #define FOO(n, arg, fixed_arg) \
uint8_t fixed_arg##n = arg; uint8_t fixed_arg##n = arg
FOR_EACH_IDX_FIXED_ARG(FOO, a, 1, 2, 3) FOR_EACH_IDX_FIXED_ARG(FOO, (;), a, 1, 2, 3);
zassert_equal(a0, 1, "Unexpected value %d", a0); zassert_equal(a0, 1, "Unexpected value %d", a0);
zassert_equal(a1, 2, "Unexpected value %d", a1); zassert_equal(a1, 2, "Unexpected value %d", a1);
@ -307,13 +307,11 @@ static void test_LIST_DROP_EMPTY(void)
*/ */
#define TEST_BROKEN_LIST EMPTY, Henry, EMPTY, Dorsett, Case, #define TEST_BROKEN_LIST EMPTY, Henry, EMPTY, Dorsett, Case,
#define TEST_FIXED_LIST LIST_DROP_EMPTY(TEST_BROKEN_LIST) #define TEST_FIXED_LIST LIST_DROP_EMPTY(TEST_BROKEN_LIST)
#define TEST_MKSTR(a) #a,
static const char *const arr[] = { static const char *const arr[] = {
FOR_EACH(TEST_MKSTR, TEST_FIXED_LIST) FOR_EACH(STRINGIFY, (,), TEST_FIXED_LIST)
}; };
zassert_equal(sizeof(arr) / sizeof(char *), 3, zassert_equal(ARRAY_SIZE(arr), 3, "Failed to cleanup list");
"Failed to cleanup list");
zassert_equal(strcmp(arr[0], "Henry"), 0, "Failed at 0"); zassert_equal(strcmp(arr[0], "Henry"), 0, "Failed at 0");
zassert_equal(strcmp(arr[1], "Dorsett"), 0, "Failed at 1"); zassert_equal(strcmp(arr[1], "Dorsett"), 0, "Failed at 1");
zassert_equal(strcmp(arr[2], "Case"), 0, "Failed at 0"); zassert_equal(strcmp(arr[2], "Case"), 0, "Failed at 0");