Skip to content

Commit 94e8173

Browse files
committed
[nrf fromlist] sys: util_macro: Add IF_ENABLED_ALL and IF_ENABLED_ANY
-Added macro IF_ENABLED_ALL to emit code if all flags are defined to 1, otherwise an empty token is emitted. -Added macro IF_ENABLED_ANY to emit code if any flags are defined to 1, otherwise an empty token is emitted. -Added unit tests for IF_ENABLED_ALL and IF_ENABLED_ANY Both macros utilize the same strategy as the IF_ENABLED macro, but supports a list of flags as a single argument. The flags to check must be wrapped in parentheses. Upstream PR #: 87026 Signed-off-by: Frank Audun Kvamtrø <[email protected]> (cherry picked from commit 7131122bca3100267fa1ec0edff6e7c98afccf31)
1 parent 0ea44bd commit 94e8173

File tree

3 files changed

+278
-7
lines changed

3 files changed

+278
-7
lines changed

include/zephyr/sys/util_internal.h

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,148 @@
125125
#define Z_IS_ENABLED_ANY_31(a, ...) COND_CODE_1(a, (1), (Z_IS_ENABLED_ANY_30(__VA_ARGS__,)))
126126
#define Z_IS_ENABLED_ANY_32(a, ...) COND_CODE_1(a, (1), (Z_IS_ENABLED_ANY_31(__VA_ARGS__,)))
127127

128+
/* Helper macro for IF_ENABLED_ALL */
129+
#define Z_IF_ENABLED_ALL(_code, ...) \
130+
Z_IF_ENABLED_ALL_N(NUM_VA_ARGS(__VA_ARGS__), _code, __VA_ARGS__)
131+
#define Z_IF_ENABLED_ALL_N(N, _code, ...) \
132+
UTIL_CAT(Z_IF_ENABLED_ALL_, N)(_code, __VA_ARGS__)
133+
#define IF_ENABLED_ALL_0(_code, ...)
134+
#define Z_IF_ENABLED_ALL_1(_code, a, ...) \
135+
COND_CODE_1(a, _code, ())
136+
#define Z_IF_ENABLED_ALL_2(_code, a, ...) \
137+
COND_CODE_1(a, (Z_IF_ENABLED_ALL_1(_code, __VA_ARGS__,)), ())
138+
#define Z_IF_ENABLED_ALL_3(_code, a, ...) \
139+
COND_CODE_1(a, (Z_IF_ENABLED_ALL_2(_code, __VA_ARGS__,)), ())
140+
#define Z_IF_ENABLED_ALL_4(_code, a, ...) \
141+
COND_CODE_1(a, (Z_IF_ENABLED_ALL_3(_code, __VA_ARGS__,)), ())
142+
#define Z_IF_ENABLED_ALL_5(_code, a, ...) \
143+
COND_CODE_1(a, (Z_IF_ENABLED_ALL_4(_code, __VA_ARGS__,)), ())
144+
#define Z_IF_ENABLED_ALL_6(_code, a, ...) \
145+
COND_CODE_1(a, (Z_IF_ENABLED_ALL_5(_code, __VA_ARGS__,)), ())
146+
#define Z_IF_ENABLED_ALL_7(_code, a, ...) \
147+
COND_CODE_1(a, (Z_IF_ENABLED_ALL_6(_code, __VA_ARGS__,)), ())
148+
#define Z_IF_ENABLED_ALL_8(_code, a, ...) \
149+
COND_CODE_1(a, (Z_IF_ENABLED_ALL_7(_code, __VA_ARGS__,)), ())
150+
#define Z_IF_ENABLED_ALL_9(_code, a, ...) \
151+
COND_CODE_1(a, (Z_IF_ENABLED_ALL_8(_code, __VA_ARGS__,)), ())
152+
#define Z_IF_ENABLED_ALL_10(_code, a, ...) \
153+
COND_CODE_1(a, (Z_IF_ENABLED_ALL_9(_code, __VA_ARGS__,)), ())
154+
#define Z_IF_ENABLED_ALL_11(_code, a, ...) \
155+
COND_CODE_1(a, (Z_IF_ENABLED_ALL_10(_code, __VA_ARGS__,)), ())
156+
#define Z_IF_ENABLED_ALL_12(_code, a, ...) \
157+
COND_CODE_1(a, (Z_IF_ENABLED_ALL_11(_code, __VA_ARGS__,)), ())
158+
#define Z_IF_ENABLED_ALL_13(_code, a, ...) \
159+
COND_CODE_1(a, (Z_IF_ENABLED_ALL_12(_code, __VA_ARGS__,)), ())
160+
#define Z_IF_ENABLED_ALL_14(_code, a, ...) \
161+
COND_CODE_1(a, (Z_IF_ENABLED_ALL_13(_code, __VA_ARGS__,)), ())
162+
#define Z_IF_ENABLED_ALL_15(_code, a, ...) \
163+
COND_CODE_1(a, (Z_IF_ENABLED_ALL_14(_code, __VA_ARGS__,)), ())
164+
#define Z_IF_ENABLED_ALL_16(_code, a, ...) \
165+
COND_CODE_1(a, (Z_IF_ENABLED_ALL_15(_code, __VA_ARGS__,)), ())
166+
#define Z_IF_ENABLED_ALL_17(_code, a, ...) \
167+
COND_CODE_1(a, (Z_IF_ENABLED_ALL_16(_code, __VA_ARGS__,)), ())
168+
#define Z_IF_ENABLED_ALL_18(_code, a, ...) \
169+
COND_CODE_1(a, (Z_IF_ENABLED_ALL_17(_code, __VA_ARGS__,)), ())
170+
#define Z_IF_ENABLED_ALL_19(_code, a, ...) \
171+
COND_CODE_1(a, (Z_IF_ENABLED_ALL_18(_code, __VA_ARGS__,)), ())
172+
#define Z_IF_ENABLED_ALL_20(_code, a, ...) \
173+
COND_CODE_1(a, (Z_IF_ENABLED_ALL_19(_code, __VA_ARGS__,)), ())
174+
#define Z_IF_ENABLED_ALL_21(_code, a, ...) \
175+
COND_CODE_1(a, (Z_IF_ENABLED_ALL_20(_code, __VA_ARGS__,)), ())
176+
#define Z_IF_ENABLED_ALL_22(_code, a, ...) \
177+
COND_CODE_1(a, (Z_IF_ENABLED_ALL_21(_code, __VA_ARGS__,)), ())
178+
#define Z_IF_ENABLED_ALL_23(_code, a, ...) \
179+
COND_CODE_1(a, (Z_IF_ENABLED_ALL_22(_code, __VA_ARGS__,)), ())
180+
#define Z_IF_ENABLED_ALL_24(_code, a, ...) \
181+
COND_CODE_1(a, (Z_IF_ENABLED_ALL_23(_code, __VA_ARGS__,)), ())
182+
#define Z_IF_ENABLED_ALL_25(_code, a, ...) \
183+
COND_CODE_1(a, (Z_IF_ENABLED_ALL_24(_code, __VA_ARGS__,)), ())
184+
#define Z_IF_ENABLED_ALL_26(_code, a, ...) \
185+
COND_CODE_1(a, (Z_IF_ENABLED_ALL_25(_code, __VA_ARGS__,)), ())
186+
#define Z_IF_ENABLED_ALL_27(_code, a, ...) \
187+
COND_CODE_1(a, (Z_IF_ENABLED_ALL_26(_code, __VA_ARGS__,)), ())
188+
#define Z_IF_ENABLED_ALL_28(_code, a, ...) \
189+
COND_CODE_1(a, (Z_IF_ENABLED_ALL_27(_code, __VA_ARGS__,)), ())
190+
#define Z_IF_ENABLED_ALL_29(_code, a, ...) \
191+
COND_CODE_1(a, (Z_IF_ENABLED_ALL_28(_code, __VA_ARGS__,)), ())
192+
#define Z_IF_ENABLED_ALL_30(_code, a, ...) \
193+
COND_CODE_1(a, (Z_IF_ENABLED_ALL_29(_code, __VA_ARGS__,)), ())
194+
#define Z_IF_ENABLED_ALL_31(_code, a, ...) \
195+
COND_CODE_1(a, (Z_IF_ENABLED_ALL_30(_code, __VA_ARGS__,)), ())
196+
#define Z_IF_ENABLED_ALL_32(_code, a, ...) \
197+
COND_CODE_1(a, (Z_IF_ENABLED_ALL_31(_code, __VA_ARGS__,)), ())
198+
199+
/* Helper macro for IF_ENABLED_ANY */
200+
#define Z_IF_ENABLED_ANY(_code, ...) \
201+
Z_IF_ENABLED_ANY_N(NUM_VA_ARGS(__VA_ARGS__), _code, __VA_ARGS__)
202+
#define Z_IF_ENABLED_ANY_N(N, _code, ...) \
203+
UTIL_CAT(Z_IF_ENABLED_ANY_, N)(_code, __VA_ARGS__)
204+
#define Z_IF_ENABLED_ANY_0(_code, ...)
205+
#define Z_IF_ENABLED_ANY_1(_code, a, ...) \
206+
COND_CODE_1(a, _code, ())
207+
#define Z_IF_ENABLED_ANY_2(_code, a, ...) \
208+
COND_CODE_1(a, _code, (Z_IF_ENABLED_ANY_1(_code, __VA_ARGS__,)))
209+
#define Z_IF_ENABLED_ANY_3(_code, a, ...) \
210+
COND_CODE_1(a, _code, (Z_IF_ENABLED_ANY_2(_code, __VA_ARGS__,)))
211+
#define Z_IF_ENABLED_ANY_4(_code, a, ...) \
212+
COND_CODE_1(a, _code, (Z_IF_ENABLED_ANY_3(_code, __VA_ARGS__,)))
213+
#define Z_IF_ENABLED_ANY_5(_code, a, ...) \
214+
COND_CODE_1(a, _code, (Z_IF_ENABLED_ANY_4(_code, __VA_ARGS__,)))
215+
#define Z_IF_ENABLED_ANY_6(_code, a, ...) \
216+
COND_CODE_1(a, _code, (Z_IF_ENABLED_ANY_5(_code, __VA_ARGS__,)))
217+
#define Z_IF_ENABLED_ANY_7(_code, a, ...) \
218+
COND_CODE_1(a, _code, (Z_IF_ENABLED_ANY_6(_code, __VA_ARGS__,)))
219+
#define Z_IF_ENABLED_ANY_8(_code, a, ...) \
220+
COND_CODE_1(a, _code, (Z_IF_ENABLED_ANY_7(_code, __VA_ARGS__,)))
221+
#define Z_IF_ENABLED_ANY_9(_code, a, ...) \
222+
COND_CODE_1(a, _code, (Z_IF_ENABLED_ANY_8(_code, __VA_ARGS__,)))
223+
#define Z_IF_ENABLED_ANY_10(_code, a, ...) \
224+
COND_CODE_1(a, _code, (Z_IF_ENABLED_ANY_9(_code, __VA_ARGS__,)))
225+
#define Z_IF_ENABLED_ANY_11(_code, a, ...) \
226+
COND_CODE_1(a, _code, (Z_IF_ENABLED_ANY_10(_code, __VA_ARGS__,)))
227+
#define Z_IF_ENABLED_ANY_12(_code, a, ...) \
228+
COND_CODE_1(a, _code, (Z_IF_ENABLED_ANY_11(_code, __VA_ARGS__,)))
229+
#define Z_IF_ENABLED_ANY_13(_code, a, ...) \
230+
COND_CODE_1(a, _code, (Z_IF_ENABLED_ANY_12(_code, __VA_ARGS__,)))
231+
#define Z_IF_ENABLED_ANY_14(_code, a, ...) \
232+
COND_CODE_1(a, _code, (Z_IF_ENABLED_ANY_13(_code, __VA_ARGS__,)))
233+
#define Z_IF_ENABLED_ANY_15(_code, a, ...) \
234+
COND_CODE_1(a, _code, (Z_IF_ENABLED_ANY_14(_code, __VA_ARGS__,)))
235+
#define Z_IF_ENABLED_ANY_16(_code, a, ...) \
236+
COND_CODE_1(a, _code, (Z_IF_ENABLED_ANY_15(_code, __VA_ARGS__,)))
237+
#define Z_IF_ENABLED_ANY_17(_code, a, ...) \
238+
COND_CODE_1(a, _code, (Z_IF_ENABLED_ANY_16(_code, __VA_ARGS__,)))
239+
#define Z_IF_ENABLED_ANY_18(_code, a, ...) \
240+
COND_CODE_1(a, _code, (Z_IF_ENABLED_ANY_17(_code, __VA_ARGS__,)))
241+
#define Z_IF_ENABLED_ANY_19(_code, a, ...) \
242+
COND_CODE_1(a, _code, (Z_IF_ENABLED_ANY_18(_code, __VA_ARGS__,)))
243+
#define Z_IF_ENABLED_ANY_20(_code, a, ...) \
244+
COND_CODE_1(a, _code, (Z_IF_ENABLED_ANY_19(_code, __VA_ARGS__,)))
245+
#define Z_IF_ENABLED_ANY_21(_code, a, ...) \
246+
COND_CODE_1(a, _code, (Z_IF_ENABLED_ANY_20(_code, __VA_ARGS__,)))
247+
#define Z_IF_ENABLED_ANY_22(_code, a, ...) \
248+
COND_CODE_1(a, _code, (Z_IF_ENABLED_ANY_21(_code, __VA_ARGS__,)))
249+
#define Z_IF_ENABLED_ANY_23(_code, a, ...) \
250+
COND_CODE_1(a, _code, (Z_IF_ENABLED_ANY_22(_code, __VA_ARGS__,)))
251+
#define Z_IF_ENABLED_ANY_24(_code, a, ...) \
252+
COND_CODE_1(a, _code, (Z_IF_ENABLED_ANY_23(_code, __VA_ARGS__,)))
253+
#define Z_IF_ENABLED_ANY_25(_code, a, ...) \
254+
COND_CODE_1(a, _code, (Z_IF_ENABLED_ANY_24(_code, __VA_ARGS__,)))
255+
#define Z_IF_ENABLED_ANY_26(_code, a, ...) \
256+
COND_CODE_1(a, _code, (Z_IF_ENABLED_ANY_25(_code, __VA_ARGS__,)))
257+
#define Z_IF_ENABLED_ANY_27(_code, a, ...) \
258+
COND_CODE_1(a, _code, (Z_IF_ENABLED_ANY_26(_code, __VA_ARGS__,)))
259+
#define Z_IF_ENABLED_ANY_28(_code, a, ...) \
260+
COND_CODE_1(a, _code, (Z_IF_ENABLED_ANY_27(_code, __VA_ARGS__,)))
261+
#define Z_IF_ENABLED_ANY_29(_code, a, ...) \
262+
COND_CODE_1(a, _code, (Z_IF_ENABLED_ANY_28(_code, __VA_ARGS__,)))
263+
#define Z_IF_ENABLED_ANY_30(_code, a, ...) \
264+
COND_CODE_1(a, _code, (Z_IF_ENABLED_ANY_29(_code, __VA_ARGS__,)))
265+
#define Z_IF_ENABLED_ANY_31(_code, a, ...) \
266+
COND_CODE_1(a, _code, (Z_IF_ENABLED_ANY_30(_code, __VA_ARGS__,)))
267+
#define Z_IF_ENABLED_ANY_32(_code, a, ...) \
268+
COND_CODE_1(a, _code, (Z_IF_ENABLED_ANY_31(_code, __VA_ARGS__,)))
269+
128270
/* Implementation of IS_EQ(). Returns 1 if _0 and _1 are the same integer from
129271
* 0 to 4096, 0 otherwise.
130272
*/

include/zephyr/sys/util_macro.h

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,50 @@ extern "C" {
285285
#define IF_ENABLED(_flag, _code) \
286286
COND_CODE_1(_flag, _code, ())
287287

288+
/**
289+
* @brief Insert code if all @p _flags are defined and equals 1.
290+
*
291+
* Like IF_ENABLED(), this emits code if @p _flags are all defined and
292+
* set to 1; it expands to nothing otherwise.
293+
*
294+
* Example:
295+
*
296+
* IF_ENABLED_ALL((CONFIG_FLAG_A, CONFIG_FLAG_B), uint32_t foo;)
297+
*
298+
* If @p CONFIG_FLAG_A and @p CONFIG_FLAG_B are defined to 1, this expands to:
299+
*
300+
* uint32_t foo;
301+
*
302+
* and to nothing otherwise.
303+
*
304+
* @param _flags evaluated flags; must be in parentheses
305+
* @param ... Emitted code if all @p _flags are defined to 1
306+
*/
307+
#define IF_ENABLED_ALL(_flags, ...) \
308+
Z_IF_ENABLED_ALL((__VA_ARGS__), __DEBRACKET _flags)
309+
310+
/**
311+
* @brief Insert code if any @p _flags are defined to 1.
312+
*
313+
* Like IF_ENABLED(), this emits code if any @p _flags are defined to 1;
314+
* it expands to nothing otherwise.
315+
*
316+
* Example:
317+
*
318+
* IF_ENABLED_ANY((CONFIG_FLAG_A, CONFIG_FLAG_B), uint32_t foo;)
319+
*
320+
* If @p CONFIG_FLAG_A or @p CONFIG_FLAG_B defined to 1, this expands to:
321+
*
322+
* uint32_t foo;
323+
*
324+
* and to nothing otherwise.
325+
*
326+
* @param _flags evaluated flags; must be in parentheses
327+
* @param ... Emitted code if any @p _flags expands to 1
328+
*/
329+
#define IF_ENABLED_ANY(_flags, ...) \
330+
Z_IF_ENABLED_ANY((__VA_ARGS__), __DEBRACKET _flags)
331+
288332
/**
289333
* @brief Insert code if @p _flag is not defined as 1.
290334
*

tests/unit/util/main.c

Lines changed: 92 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -275,21 +275,106 @@ ZTEST(util, test_UTIL_AND) {
275275
}
276276

277277
ZTEST(util, test_IF_ENABLED) {
278-
#define test_IF_ENABLED_FLAG_A 1
279-
#define test_IF_ENABLED_FLAG_B 0
278+
#define TEST_FLAG_A 1
279+
#define TEST_FLAG_B 0
280280

281-
IF_ENABLED(test_IF_ENABLED_FLAG_A, (goto skipped;))
281+
IF_ENABLED(TEST_FLAG_A, (goto skipped;))
282282
/* location should be skipped if IF_ENABLED macro is correct. */
283283
zassert_false(true, "location should be skipped");
284284
skipped:
285-
IF_ENABLED(test_IF_ENABLED_FLAG_B, (zassert_false(true, "");))
285+
IF_ENABLED(TEST_FLAG_B, (zassert_false(true, "");))
286+
287+
zassert_true(true, "");
288+
289+
#undef TEST_FLAG_A
290+
#undef TEST_FLAG_B
291+
}
292+
293+
ZTEST(util, test_IF_ENABLED_ALL) {
294+
#define TEST_FLAG_A 1
295+
#define TEST_FLAG_B 1
296+
#define TEST_FLAG_C 0
297+
#define TEST_FLAG_D 0
298+
299+
IF_ENABLED_ALL((TEST_FLAG_A, TEST_FLAG_B),
300+
goto skipped;
301+
)
302+
303+
/* location should be skipped (TEST_FLAG_A/B are 1). */
304+
zassert_false(true, "location should be skipped");
305+
skipped:
306+
IF_ENABLED_ALL((TEST_FLAG_A),
307+
goto skipped_1;
308+
)
309+
310+
/* location should be skipped (TEST_FLAG_A is 1). */
311+
zassert_false(true, "location should be skipped (single valid)");
312+
skipped_1:
313+
IF_ENABLED_ALL((TEST_FLAG_C),
314+
zassert_false(true, "Unexpected (single invalid)");
315+
)
316+
317+
IF_ENABLED_ALL((TEST_FLAG_A, test_IF_ENABLED_FLAG_C),
318+
zassert_false(true, "Unexpected (one invalid)");
319+
)
320+
321+
IF_ENABLED_ALL((TEST_FLAG_C, TEST_FLAG_D),
322+
zassert_false(true, "Unexpected (no valid)");
323+
)
324+
325+
/* Verify that emitted code supports comma separated parameters */
326+
struct { int a; int b; int c; } test_struct = {
327+
IF_ENABLED_ALL((TEST_FLAG_A, TEST_FLAG_B), .a = 2, .b = 3,)
328+
.c = 4,
329+
};
286330

287-
IF_ENABLED(test_IF_ENABLED_FLAG_C, (zassert_false(true, "");))
331+
zassert_true(test_struct.a == 2 && test_struct.b == 3,
332+
"IF_ENABLED_ALL: Comma-separated emit failed (all valid)");
288333

289334
zassert_true(true, "");
290335

291-
#undef test_IF_ENABLED_FLAG_A
292-
#undef test_IF_ENABLED_FLAG_B
336+
#undef TEST_FLAG_A
337+
#undef TEST_FLAG_B
338+
#undef TEST_FLAG_C
339+
#undef TEST_FLAG_D
340+
}
341+
342+
ZTEST(util, test_IF_ENABLED_ANY) {
343+
#define TEST_FLAG_A 1
344+
#define TEST_FLAG_B 1
345+
#define TEST_FLAG_C 0
346+
#define TEST_FLAG_D 0
347+
348+
IF_ENABLED_ANY((TEST_FLAG_A, TEST_FLAG_B),
349+
goto skipped;
350+
)
351+
352+
/* location should be skipped (TEST_FLAG_A/C is 1). */
353+
zassert_false(true, "location should be skipped");
354+
skipped:
355+
IF_ENABLED_ANY((TEST_FLAG_C, TEST_FLAG_D),
356+
zassert_false(true, "Unexpected (no valid)");
357+
)
358+
359+
IF_ENABLED_ANY((TEST_FLAG_A, TEST_FLAG_B),
360+
zassert_true(true, "Unexpected (one valid)");
361+
)
362+
363+
/* Verify that emitted code supports comma separated parameters */
364+
struct { int a; int b; int c; } test_struct = {
365+
IF_ENABLED_ANY((TEST_FLAG_A, TEST_FLAG_C), .a = 2, .b = 3,)
366+
.c = 4,
367+
};
368+
369+
zassert_true(test_struct.a == 2 && test_struct.b == 3,
370+
"IF_ENABLED_ALL: Comma-separated emit failed (one valid)");
371+
372+
zassert_true(true, "");
373+
374+
#undef TEST_FLAG_A
375+
#undef TEST_FLAG_B
376+
#undef TEST_FLAG_C
377+
#undef TEST_FLAG_D
293378
}
294379

295380
ZTEST(util, test_LISTIFY) {

0 commit comments

Comments
 (0)