1 /*
2  * Copyright (c) 2011-2014, Wind River Systems, Inc.
3  * Copyright (c) 2020, Nordic Semiconductor ASA
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 /**
9  * @file
10  * @brief Misc utilities
11  *
12  * Repetitive or obscure helper macros needed by sys/util.h.
13  */
14 
15 #ifndef ZEPHYR_INCLUDE_SYS_UTIL_INTERNAL_H_
16 #define ZEPHYR_INCLUDE_SYS_UTIL_INTERNAL_H_
17 
18 #include "util_loops.h"
19 
20 /* IS_ENABLED() helpers */
21 
22 /* This is called from IS_ENABLED(), and sticks on a "_XXXX" prefix,
23  * it will now be "_XXXX1" if config_macro is "1", or just "_XXXX" if it's
24  * undefined.
25  *   ENABLED:   Z_IS_ENABLED2(_XXXX1)
26  *   DISABLED   Z_IS_ENABLED2(_XXXX)
27  */
28 #define Z_IS_ENABLED1(config_macro) Z_IS_ENABLED2(_XXXX##config_macro)
29 
30 /* Here's the core trick, we map "_XXXX1" to "_YYYY," (i.e. a string
31  * with a trailing comma), so it has the effect of making this a
32  * two-argument tuple to the preprocessor only in the case where the
33  * value is defined to "1"
34  *   ENABLED:    _YYYY,    <--- note comma!
35  *   DISABLED:   _XXXX
36  */
37 #define _XXXX1 _YYYY,
38 
39 /* Then we append an extra argument to fool the gcc preprocessor into
40  * accepting it as a varargs macro.
41  *                         arg1   arg2  arg3
42  *   ENABLED:   Z_IS_ENABLED3(_YYYY,    1,    0)
43  *   DISABLED   Z_IS_ENABLED3(_XXXX 1,  0)
44  */
45 #define Z_IS_ENABLED2(one_or_two_args) Z_IS_ENABLED3(one_or_two_args 1, 0)
46 
47 /* And our second argument is thus now cooked to be 1 in the case
48  * where the value is defined to 1, and 0 if not:
49  */
50 #define Z_IS_ENABLED3(ignore_this, val, ...) val
51 
52 /* Implementation of IS_EQ(). Returns 1 if _0 and _1 are the same integer from
53  * 0 to 4095, 0 otherwise.
54  */
55 #define Z_IS_EQ(_0, _1) Z_HAS_COMMA(Z_CAT4(Z_IS_, _0, _EQ_, _1)())
56 
57 /* Used internally by COND_CODE_1 and COND_CODE_0. */
58 #define Z_COND_CODE_1(_flag, _if_1_code, _else_code) \
59 	__COND_CODE(_XXXX##_flag, _if_1_code, _else_code)
60 #define Z_COND_CODE_0(_flag, _if_0_code, _else_code) \
61 	__COND_CODE(_ZZZZ##_flag, _if_0_code, _else_code)
62 #define _ZZZZ0 _YYYY,
63 #define __COND_CODE(one_or_two_args, _if_code, _else_code) \
64 	__GET_ARG2_DEBRACKET(one_or_two_args _if_code, _else_code)
65 
66 /* Gets second argument and removes brackets around that argument. It
67  * is expected that the parameter is provided in brackets/parentheses.
68  */
69 #define __GET_ARG2_DEBRACKET(ignore_this, val, ...) __DEBRACKET val
70 
71 /* Used to remove brackets from around a single argument. */
72 #define __DEBRACKET(...) __VA_ARGS__
73 
74 /* Used by IS_EMPTY() */
75 /* reference: https://gustedt.wordpress.com/2010/06/08/detect-empty-macro-arguments/ */
76 #define Z_HAS_COMMA(...) \
77 	NUM_VA_ARGS_LESS_1_IMPL(__VA_ARGS__, 1, 1, 1, 1, 1, 1, 1, 1, \
78 	 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
79 	 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
80 	 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0)
81 #define Z_TRIGGER_PARENTHESIS_(...) ,
82 #define Z_IS_EMPTY_(...) \
83 	Z_IS_EMPTY__( \
84 		Z_HAS_COMMA(__VA_ARGS__), \
85 		Z_HAS_COMMA(Z_TRIGGER_PARENTHESIS_ __VA_ARGS__), \
86 		Z_HAS_COMMA(__VA_ARGS__ (/*empty*/)), \
87 		Z_HAS_COMMA(Z_TRIGGER_PARENTHESIS_ __VA_ARGS__ (/*empty*/)))
88 #define Z_CAT4(_0, _1, _2, _3) _0 ## _1 ## _2 ## _3
89 #define Z_CAT5(_0, _1, _2, _3, _4) _0 ## _1 ## _2 ## _3 ## _4
90 #define Z_IS_EMPTY__(_0, _1, _2, _3) \
91 	Z_HAS_COMMA(Z_CAT5(Z_IS_EMPTY_CASE_, _0, _1, _2, _3))
92 #define Z_IS_EMPTY_CASE_0001 ,
93 
94 /* Used by LIST_DROP_EMPTY() */
95 /* Adding ',' after each element would add empty element at the end of
96  * list, which is hard to remove, so instead precede each element with ',',
97  * this way first element is empty, and this one is easy to drop.
98  */
99 #define Z_LIST_ADD_ELEM(e) EMPTY, e
100 #define Z_LIST_DROP_FIRST(...) GET_ARGS_LESS_N(1, __VA_ARGS__)
101 #define Z_LIST_NO_EMPTIES(e) \
102 	COND_CODE_1(IS_EMPTY(e), (), (Z_LIST_ADD_ELEM(e)))
103 
104 #define UTIL_CAT(a, ...) UTIL_PRIMITIVE_CAT(a, __VA_ARGS__)
105 #define UTIL_PRIMITIVE_CAT(a, ...) a##__VA_ARGS__
106 #define UTIL_CHECK_N(x, n, ...) n
107 #define UTIL_CHECK(...) UTIL_CHECK_N(__VA_ARGS__, 0,)
108 #define UTIL_NOT(x) UTIL_CHECK(UTIL_PRIMITIVE_CAT(UTIL_NOT_, x))
109 #define UTIL_NOT_0 ~, 1,
110 #define UTIL_COMPL(b) UTIL_PRIMITIVE_CAT(UTIL_COMPL_, b)
111 #define UTIL_COMPL_0 1
112 #define UTIL_COMPL_1 0
113 #define UTIL_BOOL(x) UTIL_COMPL(UTIL_NOT(x))
114 
115 #define UTIL_EVAL(...) __VA_ARGS__
116 #define UTIL_EXPAND(...) __VA_ARGS__
117 #define UTIL_REPEAT(...) UTIL_LISTIFY(__VA_ARGS__)
118 
119 /* Implementation details for NUM_VA_ARGS_LESS_1 */
120 #define NUM_VA_ARGS_LESS_1_IMPL(				\
121 	_ignored,						\
122 	_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10,		\
123 	_11, _12, _13, _14, _15, _16, _17, _18, _19, _20,	\
124 	_21, _22, _23, _24, _25, _26, _27, _28, _29, _30,	\
125 	_31, _32, _33, _34, _35, _36, _37, _38, _39, _40,	\
126 	_41, _42, _43, _44, _45, _46, _47, _48, _49, _50,	\
127 	_51, _52, _53, _54, _55, _56, _57, _58, _59, _60,	\
128 	_61, _62, N, ...) N
129 
130 /* Used by MACRO_MAP_CAT */
131 #define MACRO_MAP_CAT_(...)						\
132 	/* To make sure it works also for 2 arguments in total */	\
133 	MACRO_MAP_CAT_N(NUM_VA_ARGS_LESS_1(__VA_ARGS__), __VA_ARGS__)
134 #define MACRO_MAP_CAT_N_(N, ...) UTIL_CAT(MACRO_MC_, N)(__VA_ARGS__,)
135 #define MACRO_MC_0(...)
136 #define MACRO_MC_1(m, a, ...)  m(a)
137 #define MACRO_MC_2(m, a, ...)  UTIL_CAT(m(a), MACRO_MC_1(m, __VA_ARGS__,))
138 #define MACRO_MC_3(m, a, ...)  UTIL_CAT(m(a), MACRO_MC_2(m, __VA_ARGS__,))
139 #define MACRO_MC_4(m, a, ...)  UTIL_CAT(m(a), MACRO_MC_3(m, __VA_ARGS__,))
140 #define MACRO_MC_5(m, a, ...)  UTIL_CAT(m(a), MACRO_MC_4(m, __VA_ARGS__,))
141 #define MACRO_MC_6(m, a, ...)  UTIL_CAT(m(a), MACRO_MC_5(m, __VA_ARGS__,))
142 #define MACRO_MC_7(m, a, ...)  UTIL_CAT(m(a), MACRO_MC_6(m, __VA_ARGS__,))
143 #define MACRO_MC_8(m, a, ...)  UTIL_CAT(m(a), MACRO_MC_7(m, __VA_ARGS__,))
144 #define MACRO_MC_9(m, a, ...)  UTIL_CAT(m(a), MACRO_MC_8(m, __VA_ARGS__,))
145 #define MACRO_MC_10(m, a, ...) UTIL_CAT(m(a), MACRO_MC_9(m, __VA_ARGS__,))
146 #define MACRO_MC_11(m, a, ...) UTIL_CAT(m(a), MACRO_MC_10(m, __VA_ARGS__,))
147 #define MACRO_MC_12(m, a, ...) UTIL_CAT(m(a), MACRO_MC_11(m, __VA_ARGS__,))
148 #define MACRO_MC_13(m, a, ...) UTIL_CAT(m(a), MACRO_MC_12(m, __VA_ARGS__,))
149 #define MACRO_MC_14(m, a, ...) UTIL_CAT(m(a), MACRO_MC_13(m, __VA_ARGS__,))
150 #define MACRO_MC_15(m, a, ...) UTIL_CAT(m(a), MACRO_MC_14(m, __VA_ARGS__,))
151 
152 /* Used by Z_IS_EQ */
153 #include "util_internal_is_eq.h"
154 
155 /*
156  * Generic sparse list of odd numbers (check the implementation of
157  * GPIO_DT_RESERVED_RANGES_NGPIOS as a usage example)
158  */
159 #define Z_SPARSE_LIST_ODD_NUMBERS		\
160 	EMPTY,  1, EMPTY,  3, EMPTY,  5, EMPTY,  7, \
161 	EMPTY,  9, EMPTY, 11, EMPTY, 13, EMPTY, 15, \
162 	EMPTY, 17, EMPTY, 19, EMPTY, 21, EMPTY, 23, \
163 	EMPTY, 25, EMPTY, 27, EMPTY, 29, EMPTY, 31, \
164 	EMPTY, 33, EMPTY, 35, EMPTY, 37, EMPTY, 39, \
165 	EMPTY, 41, EMPTY, 43, EMPTY, 45, EMPTY, 47, \
166 	EMPTY, 49, EMPTY, 51, EMPTY, 53, EMPTY, 55, \
167 	EMPTY, 57, EMPTY, 59, EMPTY, 61, EMPTY, 63
168 
169 /*
170  * Generic sparse list of even numbers (check the implementation of
171  * GPIO_DT_RESERVED_RANGES_NGPIOS as a usage example)
172  */
173 #define Z_SPARSE_LIST_EVEN_NUMBERS		\
174 	 0, EMPTY,  2, EMPTY,  4, EMPTY,  6, EMPTY, \
175 	 8, EMPTY, 10, EMPTY, 12, EMPTY, 14, EMPTY, \
176 	16, EMPTY, 18, EMPTY, 20, EMPTY, 22, EMPTY, \
177 	24, EMPTY, 26, EMPTY, 28, EMPTY, 30, EMPTY, \
178 	32, EMPTY, 34, EMPTY, 36, EMPTY, 38, EMPTY, \
179 	40, EMPTY, 42, EMPTY, 44, EMPTY, 46, EMPTY, \
180 	48, EMPTY, 50, EMPTY, 52, EMPTY, 54, EMPTY, \
181 	56, EMPTY, 58, EMPTY, 60, EMPTY, 62, EMPTY
182 
183 /* Used by UTIL_INC */
184 #include "util_internal_util_inc.h"
185 
186 /* Used by UTIL_DEC */
187 #include "util_internal_util_dec.h"
188 
189 /* Used by UTIL_X2 */
190 #include "util_internal_util_x2.h"
191 
192 #endif /* ZEPHYR_INCLUDE_SYS_UTIL_INTERNAL_H_ */
193