Zephyr API Documentation 4.3.99
A Scalable Open Source RTOS
Loading...
Searching...
No Matches
util_internal.h
Go to the documentation of this file.
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
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 4096, 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 COND_CASE_1(); supports up to 16 flag/value pairs */
75#define Z_COND_CASE_1(...) \
76 Z_COND_CASE_1_CAT_N(NUM_VA_ARGS_LESS_1(__VA_ARGS__), __VA_ARGS__)
77
78#define Z_COND_CASE_1_CAT_N(count_minus_one, ...) \
79 UTIL_CAT(Z_COND_CASE_1_N_, count_minus_one)(__VA_ARGS__)
80
81#define Z_COND_CASE_1_N_0(_default) __DEBRACKET _default
82#define Z_COND_CASE_1_N_2(flag0, value0, _default) \
83 Z_COND_CODE_1(flag0, (__DEBRACKET value0), (__DEBRACKET _default))
84#define Z_COND_CASE_1_N_4(flag0, value0, ...) \
85 Z_COND_CODE_1(flag0, (__DEBRACKET value0), (Z_COND_CASE_1_N_2(__VA_ARGS__)))
86#define Z_COND_CASE_1_N_6(flag0, value0, ...) \
87 Z_COND_CODE_1(flag0, (__DEBRACKET value0), (Z_COND_CASE_1_N_4(__VA_ARGS__)))
88#define Z_COND_CASE_1_N_8(flag0, value0, ...) \
89 Z_COND_CODE_1(flag0, (__DEBRACKET value0), (Z_COND_CASE_1_N_6(__VA_ARGS__)))
90#define Z_COND_CASE_1_N_10(flag0, value0, ...) \
91 Z_COND_CODE_1(flag0, (__DEBRACKET value0), (Z_COND_CASE_1_N_8(__VA_ARGS__)))
92#define Z_COND_CASE_1_N_12(flag0, value0, ...) \
93 Z_COND_CODE_1(flag0, (__DEBRACKET value0), (Z_COND_CASE_1_N_10(__VA_ARGS__)))
94#define Z_COND_CASE_1_N_14(flag0, value0, ...) \
95 Z_COND_CODE_1(flag0, (__DEBRACKET value0), (Z_COND_CASE_1_N_12(__VA_ARGS__)))
96#define Z_COND_CASE_1_N_16(flag0, value0, ...) \
97 Z_COND_CODE_1(flag0, (__DEBRACKET value0), (Z_COND_CASE_1_N_14(__VA_ARGS__)))
98#define Z_COND_CASE_1_N_18(flag0, value0, ...) \
99 Z_COND_CODE_1(flag0, (__DEBRACKET value0), (Z_COND_CASE_1_N_16(__VA_ARGS__)))
100#define Z_COND_CASE_1_N_20(flag0, value0, ...) \
101 Z_COND_CODE_1(flag0, (__DEBRACKET value0), (Z_COND_CASE_1_N_18(__VA_ARGS__)))
102#define Z_COND_CASE_1_N_22(flag0, value0, ...) \
103 Z_COND_CODE_1(flag0, (__DEBRACKET value0), (Z_COND_CASE_1_N_20(__VA_ARGS__)))
104#define Z_COND_CASE_1_N_24(flag0, value0, ...) \
105 Z_COND_CODE_1(flag0, (__DEBRACKET value0), (Z_COND_CASE_1_N_22(__VA_ARGS__)))
106#define Z_COND_CASE_1_N_26(flag0, value0, ...) \
107 Z_COND_CODE_1(flag0, (__DEBRACKET value0), (Z_COND_CASE_1_N_24(__VA_ARGS__)))
108#define Z_COND_CASE_1_N_28(flag0, value0, ...) \
109 Z_COND_CODE_1(flag0, (__DEBRACKET value0), (Z_COND_CASE_1_N_26(__VA_ARGS__)))
110#define Z_COND_CASE_1_N_30(flag0, value0, ...) \
111 Z_COND_CODE_1(flag0, (__DEBRACKET value0), (Z_COND_CASE_1_N_28(__VA_ARGS__)))
112#define Z_COND_CASE_1_N_32(flag0, value0, ...) \
113 Z_COND_CODE_1(flag0, (__DEBRACKET value0), (Z_COND_CASE_1_N_30(__VA_ARGS__)))
114
115/* Used by IS_EMPTY() */
116/* reference: https://gustedt.wordpress.com/2010/06/08/detect-empty-macro-arguments/ */
117#define Z_HAS_COMMA(...) \
118 NUM_VA_ARGS_LESS_1_IMPL(__VA_ARGS__, 1, 1, 1, 1, 1, 1, 1, 1, \
119 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
120 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
121 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0)
122#define Z_TRIGGER_PARENTHESIS_(...) ,
123#define Z_IS_EMPTY_(...) \
124 Z_IS_EMPTY__( \
125 Z_HAS_COMMA(__VA_ARGS__), \
126 Z_HAS_COMMA(Z_TRIGGER_PARENTHESIS_ __VA_ARGS__), \
127 Z_HAS_COMMA(__VA_ARGS__ (/*empty*/)), \
128 Z_HAS_COMMA(Z_TRIGGER_PARENTHESIS_ __VA_ARGS__ (/*empty*/)))
129#define Z_CAT4(_0, _1, _2, _3) _0 ## _1 ## _2 ## _3
130#define Z_CAT5(_0, _1, _2, _3, _4) _0 ## _1 ## _2 ## _3 ## _4
131#define Z_IS_EMPTY__(_0, _1, _2, _3) \
132 Z_HAS_COMMA(Z_CAT5(Z_IS_EMPTY_CASE_, _0, _1, _2, _3))
133#define Z_IS_EMPTY_CASE_0001 ,
134
135/* Used by LIST_DROP_EMPTY() */
136/* Adding ',' after each element would add empty element at the end of
137 * list, which is hard to remove, so instead precede each element with ',',
138 * this way first element is empty, and this one is easy to drop.
139 */
140#define Z_LIST_ADD_ELEM(e) EMPTY, e
141#define Z_LIST_DROP_FIRST(...) GET_ARGS_LESS_N(1, __VA_ARGS__)
142#define Z_LIST_NO_EMPTIES(e) \
143 COND_CODE_1(IS_EMPTY(e), (), (Z_LIST_ADD_ELEM(e)))
144
145#define UTIL_CAT(a, ...) UTIL_PRIMITIVE_CAT(a, __VA_ARGS__)
146#define UTIL_PRIMITIVE_CAT(a, ...) a##__VA_ARGS__
147#define UTIL_CHECK_N(x, n, ...) n
148#define UTIL_CHECK(...) UTIL_CHECK_N(__VA_ARGS__, 0,)
149#define UTIL_NOT(x) UTIL_CHECK(UTIL_PRIMITIVE_CAT(UTIL_NOT_, x))
150#define UTIL_NOT_0 ~, 1,
151#define UTIL_COMPL(b) UTIL_PRIMITIVE_CAT(UTIL_COMPL_, b)
152#define UTIL_COMPL_0 1
153#define UTIL_COMPL_1 0
154#define UTIL_BOOL(x) UTIL_COMPL(UTIL_NOT(x))
155
156#define UTIL_EVAL(...) __VA_ARGS__
157#define UTIL_EXPAND(...) __VA_ARGS__
158#define UTIL_REPEAT(...) UTIL_LISTIFY(__VA_ARGS__)
159
160#define _CONCAT_0(arg, ...) arg
161#define _CONCAT_1(arg, ...) UTIL_CAT(arg, _CONCAT_0(__VA_ARGS__))
162#define _CONCAT_2(arg, ...) UTIL_CAT(arg, _CONCAT_1(__VA_ARGS__))
163#define _CONCAT_3(arg, ...) UTIL_CAT(arg, _CONCAT_2(__VA_ARGS__))
164#define _CONCAT_4(arg, ...) UTIL_CAT(arg, _CONCAT_3(__VA_ARGS__))
165#define _CONCAT_5(arg, ...) UTIL_CAT(arg, _CONCAT_4(__VA_ARGS__))
166#define _CONCAT_6(arg, ...) UTIL_CAT(arg, _CONCAT_5(__VA_ARGS__))
167#define _CONCAT_7(arg, ...) UTIL_CAT(arg, _CONCAT_6(__VA_ARGS__))
168
169/* Implementation details for NUM_VA_ARGS_LESS_1 */
170#define NUM_VA_ARGS_LESS_1_IMPL( \
171 _ignored, \
172 _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, \
173 _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, \
174 _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, \
175 _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, \
176 _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, \
177 _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, \
178 _61, _62, N, ...) N
179
180/* Used by MACRO_MAP_CAT */
181#define MACRO_MAP_CAT_(...) \
182 /* To make sure it works also for 2 arguments in total */ \
183 MACRO_MAP_CAT_N(NUM_VA_ARGS_LESS_1(__VA_ARGS__), __VA_ARGS__)
184#define MACRO_MAP_CAT_N_(N, ...) UTIL_CAT(MACRO_MC_, N)(__VA_ARGS__,)
185#define MACRO_MC_0(...)
186#define MACRO_MC_1(m, a, ...) m(a)
187#define MACRO_MC_2(m, a, ...) UTIL_CAT(m(a), MACRO_MC_1(m, __VA_ARGS__,))
188#define MACRO_MC_3(m, a, ...) UTIL_CAT(m(a), MACRO_MC_2(m, __VA_ARGS__,))
189#define MACRO_MC_4(m, a, ...) UTIL_CAT(m(a), MACRO_MC_3(m, __VA_ARGS__,))
190#define MACRO_MC_5(m, a, ...) UTIL_CAT(m(a), MACRO_MC_4(m, __VA_ARGS__,))
191#define MACRO_MC_6(m, a, ...) UTIL_CAT(m(a), MACRO_MC_5(m, __VA_ARGS__,))
192#define MACRO_MC_7(m, a, ...) UTIL_CAT(m(a), MACRO_MC_6(m, __VA_ARGS__,))
193#define MACRO_MC_8(m, a, ...) UTIL_CAT(m(a), MACRO_MC_7(m, __VA_ARGS__,))
194#define MACRO_MC_9(m, a, ...) UTIL_CAT(m(a), MACRO_MC_8(m, __VA_ARGS__,))
195#define MACRO_MC_10(m, a, ...) UTIL_CAT(m(a), MACRO_MC_9(m, __VA_ARGS__,))
196#define MACRO_MC_11(m, a, ...) UTIL_CAT(m(a), MACRO_MC_10(m, __VA_ARGS__,))
197#define MACRO_MC_12(m, a, ...) UTIL_CAT(m(a), MACRO_MC_11(m, __VA_ARGS__,))
198#define MACRO_MC_13(m, a, ...) UTIL_CAT(m(a), MACRO_MC_12(m, __VA_ARGS__,))
199#define MACRO_MC_14(m, a, ...) UTIL_CAT(m(a), MACRO_MC_13(m, __VA_ARGS__,))
200#define MACRO_MC_15(m, a, ...) UTIL_CAT(m(a), MACRO_MC_14(m, __VA_ARGS__,))
201
202/* Used by Z_IS_EQ */
203#include "util_internal_is_eq.h"
204
205/*
206 * Generic sparse list of odd numbers (check the implementation of
207 * GPIO_DT_RESERVED_RANGES_NGPIOS as a usage example)
208 */
209#define Z_SPARSE_LIST_ODD_NUMBERS \
210 EMPTY, 1, EMPTY, 3, EMPTY, 5, EMPTY, 7, \
211 EMPTY, 9, EMPTY, 11, EMPTY, 13, EMPTY, 15, \
212 EMPTY, 17, EMPTY, 19, EMPTY, 21, EMPTY, 23, \
213 EMPTY, 25, EMPTY, 27, EMPTY, 29, EMPTY, 31, \
214 EMPTY, 33, EMPTY, 35, EMPTY, 37, EMPTY, 39, \
215 EMPTY, 41, EMPTY, 43, EMPTY, 45, EMPTY, 47, \
216 EMPTY, 49, EMPTY, 51, EMPTY, 53, EMPTY, 55, \
217 EMPTY, 57, EMPTY, 59, EMPTY, 61, EMPTY, 63
218
219/*
220 * Generic sparse list of even numbers (check the implementation of
221 * GPIO_DT_RESERVED_RANGES_NGPIOS as a usage example)
222 */
223#define Z_SPARSE_LIST_EVEN_NUMBERS \
224 0, EMPTY, 2, EMPTY, 4, EMPTY, 6, EMPTY, \
225 8, EMPTY, 10, EMPTY, 12, EMPTY, 14, EMPTY, \
226 16, EMPTY, 18, EMPTY, 20, EMPTY, 22, EMPTY, \
227 24, EMPTY, 26, EMPTY, 28, EMPTY, 30, EMPTY, \
228 32, EMPTY, 34, EMPTY, 36, EMPTY, 38, EMPTY, \
229 40, EMPTY, 42, EMPTY, 44, EMPTY, 46, EMPTY, \
230 48, EMPTY, 50, EMPTY, 52, EMPTY, 54, EMPTY, \
231 56, EMPTY, 58, EMPTY, 60, EMPTY, 62, EMPTY
232
233/* Used by UTIL_INC */
235
236/* Used by UTIL_DEC */
238
239/* Used by UTIL_X2 */
241
242#endif /* ZEPHYR_INCLUDE_SYS_UTIL_INTERNAL_H_ */
Internals for looping macros.