Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 47 additions & 42 deletions include/nuttx/macro.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,28 @@
_24, _25, _26, _27, _28, _29, _30, _31, \
_32, name, ...) name

/* Get the number of arguments (up to 32) */

#define GET_ARG_COUNT(...) \
/* Get the number of arguments (up to 32)
*
* C++ strict mode drops the GNU ", ##__VA_ARGS__" comma elision, which
* would shift the selector off by one for the zero-argument case; use the
* standard __VA_OPT__ there instead. This is the only place where the
* empty-argument case needs special handling: every higher-level macro
* (REVERSE_ARG, FOREACH_ARG, ...) dispatches on top of GET_ARG_COUNT.
*/

#if defined(__cplusplus)
# define GET_ARG_COUNT(...) \
GET_ARG_VALUE(_0 __VA_OPT__(,) __VA_ARGS__, 32, 31, 30, \
29, 28, 27, 26, 25, 24, 23, 22, 21, 20, \
19, 18, 17, 16, 15, 14, 13, 12, 11, 10, \
9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
#else
# define GET_ARG_COUNT(...) \
GET_ARG_VALUE(_0, ##__VA_ARGS__, 32, 31, 30, \
29, 28, 27, 26, 25, 24, 23, 22, 21, 20, \
19, 18, 17, 16, 15, 14, 13, 12, 11, 10, \
9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
#endif

/* Expand the arguments */

Expand All @@ -56,17 +71,17 @@

/* Reverse the arguments */

#define REVERSE_00()
#define REVERSE_01(a) a
#define REVERSE_02(a,b) b,a
#define REVERSE_03(a,...) EXPAND(REVERSE_02(__VA_ARGS__)),a
#define REVERSE_04(a,...) EXPAND(REVERSE_03(__VA_ARGS__)),a
#define REVERSE_05(a,...) EXPAND(REVERSE_04(__VA_ARGS__)),a
#define REVERSE_06(a,...) EXPAND(REVERSE_05(__VA_ARGS__)),a
#define REVERSE_07(a,...) EXPAND(REVERSE_06(__VA_ARGS__)),a
#define REVERSE_08(a,...) EXPAND(REVERSE_07(__VA_ARGS__)),a
#define REVERSE_09(a,...) EXPAND(REVERSE_08(__VA_ARGS__)),a
#define REVERSE_10(a,...) EXPAND(REVERSE_09(__VA_ARGS__)),a
#define REVERSE_0()
#define REVERSE_1(a) a
#define REVERSE_2(a,b) b,a
#define REVERSE_3(a,...) EXPAND(REVERSE_2(__VA_ARGS__)),a
#define REVERSE_4(a,...) EXPAND(REVERSE_3(__VA_ARGS__)),a
#define REVERSE_5(a,...) EXPAND(REVERSE_4(__VA_ARGS__)),a
#define REVERSE_6(a,...) EXPAND(REVERSE_5(__VA_ARGS__)),a
#define REVERSE_7(a,...) EXPAND(REVERSE_6(__VA_ARGS__)),a
#define REVERSE_8(a,...) EXPAND(REVERSE_7(__VA_ARGS__)),a
#define REVERSE_9(a,...) EXPAND(REVERSE_8(__VA_ARGS__)),a
#define REVERSE_10(a,...) EXPAND(REVERSE_9(__VA_ARGS__)),a
#define REVERSE_11(a,...) EXPAND(REVERSE_10(__VA_ARGS__)),a
#define REVERSE_12(a,...) EXPAND(REVERSE_11(__VA_ARGS__)),a
#define REVERSE_13(a,...) EXPAND(REVERSE_12(__VA_ARGS__)),a
Expand All @@ -90,30 +105,26 @@
#define REVERSE_31(a,...) EXPAND(REVERSE_30(__VA_ARGS__)),a
#define REVERSE_32(a,...) EXPAND(REVERSE_31(__VA_ARGS__)),a

#define REVERSE_ARG_(...) \
GET_ARG_VALUE(0, ##__VA_ARGS__, \
REVERSE_32, REVERSE_31, REVERSE_30, REVERSE_29, REVERSE_28, REVERSE_27, \
REVERSE_26, REVERSE_25, REVERSE_24, REVERSE_23, REVERSE_22, REVERSE_21, \
REVERSE_20, REVERSE_19, REVERSE_18, REVERSE_17, REVERSE_16, REVERSE_15, \
REVERSE_14, REVERSE_13, REVERSE_12, REVERSE_11, REVERSE_10, REVERSE_09, \
REVERSE_08, REVERSE_07, REVERSE_06, REVERSE_05, REVERSE_04, REVERSE_03, \
REVERSE_02, REVERSE_01, REVERSE_00)(__VA_ARGS__)
/* Select the worker through GET_ARG_COUNT so the zero-argument case
* expands correctly in both C and C++ (see GET_ARG_COUNT).
*/

#define REVERSE_ARG(...) REVERSE_ARG_(##__VA_ARGS__)
#define REVERSE_ARG(...) \
CONCATENATE(REVERSE_, GET_ARG_COUNT(__VA_ARGS__))(__VA_ARGS__)

/* Apply the macro to each argument */

#define FOREACH_00(action, count, param, ...) 0
#define FOREACH_01(action, count, param, arg, ...) action(param, arg, count - 1 )
#define FOREACH_02(action, count, param, arg, ...) action(param, arg, count - 2 ) FOREACH_01(action, count, param, __VA_ARGS__)
#define FOREACH_03(action, count, param, arg, ...) action(param, arg, count - 3 ) FOREACH_02(action, count, param, __VA_ARGS__)
#define FOREACH_04(action, count, param, arg, ...) action(param, arg, count - 4 ) FOREACH_03(action, count, param, __VA_ARGS__)
#define FOREACH_05(action, count, param, arg, ...) action(param, arg, count - 5 ) FOREACH_04(action, count, param, __VA_ARGS__)
#define FOREACH_06(action, count, param, arg, ...) action(param, arg, count - 6 ) FOREACH_05(action, count, param, __VA_ARGS__)
#define FOREACH_07(action, count, param, arg, ...) action(param, arg, count - 7 ) FOREACH_06(action, count, param, __VA_ARGS__)
#define FOREACH_08(action, count, param, arg, ...) action(param, arg, count - 8 ) FOREACH_07(action, count, param, __VA_ARGS__)
#define FOREACH_09(action, count, param, arg, ...) action(param, arg, count - 9 ) FOREACH_08(action, count, param, __VA_ARGS__)
#define FOREACH_10(action, count, param, arg, ...) action(param, arg, count - 10) FOREACH_09(action, count, param, __VA_ARGS__)
#define FOREACH_0(action, count, param, ...) 0
#define FOREACH_1(action, count, param, arg, ...) action(param, arg, count - 1 )
#define FOREACH_2(action, count, param, arg, ...) action(param, arg, count - 2 ) FOREACH_1(action, count, param, __VA_ARGS__)
#define FOREACH_3(action, count, param, arg, ...) action(param, arg, count - 3 ) FOREACH_2(action, count, param, __VA_ARGS__)
#define FOREACH_4(action, count, param, arg, ...) action(param, arg, count - 4 ) FOREACH_3(action, count, param, __VA_ARGS__)
#define FOREACH_5(action, count, param, arg, ...) action(param, arg, count - 5 ) FOREACH_4(action, count, param, __VA_ARGS__)
#define FOREACH_6(action, count, param, arg, ...) action(param, arg, count - 6 ) FOREACH_5(action, count, param, __VA_ARGS__)
#define FOREACH_7(action, count, param, arg, ...) action(param, arg, count - 7 ) FOREACH_6(action, count, param, __VA_ARGS__)
#define FOREACH_8(action, count, param, arg, ...) action(param, arg, count - 8 ) FOREACH_7(action, count, param, __VA_ARGS__)
#define FOREACH_9(action, count, param, arg, ...) action(param, arg, count - 9 ) FOREACH_8(action, count, param, __VA_ARGS__)
#define FOREACH_10(action, count, param, arg, ...) action(param, arg, count - 10) FOREACH_9(action, count, param, __VA_ARGS__)
#define FOREACH_11(action, count, param, arg, ...) action(param, arg, count - 11) FOREACH_10(action, count, param, __VA_ARGS__)
#define FOREACH_12(action, count, param, arg, ...) action(param, arg, count - 12) FOREACH_11(action, count, param, __VA_ARGS__)
#define FOREACH_13(action, count, param, arg, ...) action(param, arg, count - 13) FOREACH_12(action, count, param, __VA_ARGS__)
Expand All @@ -138,15 +149,9 @@
#define FOREACH_32(action, count, param, arg, ...) action(param, arg, count - 32) FOREACH_31(action, count, param, __VA_ARGS__)

#define FOREACH_ARG_(action, count, param, ...) \
GET_ARG_VALUE(0, ##__VA_ARGS__, \
FOREACH_32, FOREACH_31, FOREACH_30, FOREACH_29, FOREACH_28, FOREACH_27, \
FOREACH_26, FOREACH_25, FOREACH_24, FOREACH_23, FOREACH_22, FOREACH_21, \
FOREACH_20, FOREACH_19, FOREACH_18, FOREACH_17, FOREACH_16, FOREACH_15, \
FOREACH_14, FOREACH_13, FOREACH_12, FOREACH_11, FOREACH_10, FOREACH_09, \
FOREACH_08, FOREACH_07, FOREACH_06, FOREACH_05, FOREACH_04, FOREACH_03, \
FOREACH_02, FOREACH_01, FOREACH_00)(action, count, param, ##__VA_ARGS__)
CONCATENATE(FOREACH_, count)(action, count, param, __VA_ARGS__)

#define FOREACH_ARG(action, param, ...) \
FOREACH_ARG_(action, GET_ARG_COUNT(__VA_ARGS__), param, ##__VA_ARGS__)
FOREACH_ARG_(action, GET_ARG_COUNT(__VA_ARGS__), param, __VA_ARGS__)

#endif /* __INCLUDE_NUTTX_MACRO_H */
Loading