Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 2011-2014, Wind River Systems, Inc. |
| 3 | * |
David B. Kinder | ac74d8b | 2017-01-18 17:01:01 -0800 | [diff] [blame] | 4 | * SPDX-License-Identifier: Apache-2.0 |
Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 5 | */ |
| 6 | |
Anas Nashif | 275ca60 | 2015-12-04 10:09:39 -0500 | [diff] [blame] | 7 | /** |
| 8 | * @file |
| 9 | * @brief Misc utilities |
| 10 | * |
Leandro Pereira | 1209245 | 2016-11-21 13:50:18 -0800 | [diff] [blame] | 11 | * Misc utilities usable by the kernel and application code. |
Anas Nashif | ea0d0b2 | 2015-07-01 17:22:39 -0400 | [diff] [blame] | 12 | */ |
Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 13 | |
Flavio Ceolin | 67ca176 | 2018-09-14 10:43:44 -0700 | [diff] [blame] | 14 | #ifndef ZEPHYR_INCLUDE_MISC_UTIL_H_ |
| 15 | #define ZEPHYR_INCLUDE_MISC_UTIL_H_ |
Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 16 | |
Benjamin Walsh | 0304cbc | 2015-08-12 10:48:18 -0400 | [diff] [blame] | 17 | #ifndef _ASMLANGUAGE |
| 18 | |
Kumar Gala | 7890816 | 2017-04-19 10:32:08 -0500 | [diff] [blame] | 19 | #include <zephyr/types.h> |
Flavio Ceolin | 6fdc56d | 2018-09-18 12:32:27 -0700 | [diff] [blame] | 20 | #include <stdbool.h> |
Bogdan Davidoaia | bcca0dc | 2016-06-28 14:20:46 +0300 | [diff] [blame] | 21 | |
Tomasz Bursztyka | 8017b64 | 2015-09-10 16:03:23 +0300 | [diff] [blame] | 22 | /* Helper to pass a int as a pointer or vice-versa. |
Dan Kalowsky | da67b29 | 2015-10-20 09:42:33 -0700 | [diff] [blame] | 23 | * Those are available for 32 bits architectures: |
| 24 | */ |
Kumar Gala | cc334c7 | 2017-04-21 10:55:34 -0500 | [diff] [blame] | 25 | #define POINTER_TO_UINT(x) ((u32_t) (x)) |
Tomasz Bursztyka | 8017b64 | 2015-09-10 16:03:23 +0300 | [diff] [blame] | 26 | #define UINT_TO_POINTER(x) ((void *) (x)) |
Kumar Gala | cc334c7 | 2017-04-21 10:55:34 -0500 | [diff] [blame] | 27 | #define POINTER_TO_INT(x) ((s32_t) (x)) |
Tomasz Bursztyka | 8017b64 | 2015-09-10 16:03:23 +0300 | [diff] [blame] | 28 | #define INT_TO_POINTER(x) ((void *) (x)) |
| 29 | |
Himanshu Jha | b8c19d8 | 2018-10-30 23:15:51 +0530 | [diff] [blame] | 30 | #if !(defined (__CHAR_BIT__) && defined (__SIZEOF_LONG__)) |
| 31 | # error Missing required predefined macros for BITS_PER_LONG calculation |
| 32 | #endif |
| 33 | |
| 34 | #define BITS_PER_LONG (__CHAR_BIT__ * __SIZEOF_LONG__) |
| 35 | /* Create a contiguous bitmask starting at bit position @l and ending at |
| 36 | * position @h. |
| 37 | */ |
| 38 | #define GENMASK(h, l) \ |
| 39 | (((~0UL) - (1UL << (l)) + 1) & (~0UL >> (BITS_PER_LONG - 1 - (h)))) |
| 40 | |
Leandro Pereira | 1209245 | 2016-11-21 13:50:18 -0800 | [diff] [blame] | 41 | /* Evaluates to 0 if cond is true-ish; compile error otherwise */ |
| 42 | #define ZERO_OR_COMPILE_ERROR(cond) ((int) sizeof(char[1 - 2 * !(cond)]) - 1) |
Johan Hedberg | 85921c9 | 2015-05-12 11:15:11 +0300 | [diff] [blame] | 43 | |
Leandro Pereira | 1209245 | 2016-11-21 13:50:18 -0800 | [diff] [blame] | 44 | /* Evaluates to 0 if array is an array; compile error if not array (e.g. |
| 45 | * pointer) |
| 46 | */ |
| 47 | #define IS_ARRAY(array) \ |
| 48 | ZERO_OR_COMPILE_ERROR( \ |
| 49 | !__builtin_types_compatible_p(__typeof__(array), \ |
| 50 | __typeof__(&(array)[0]))) |
| 51 | |
Michael Hope | 5f67a61 | 2018-03-17 12:44:40 +0100 | [diff] [blame] | 52 | #if defined(__cplusplus) |
| 53 | template < class T, size_t N > |
| 54 | constexpr size_t ARRAY_SIZE(T(&)[N]) { return N; } |
| 55 | |
| 56 | #else |
Leandro Pereira | 1209245 | 2016-11-21 13:50:18 -0800 | [diff] [blame] | 57 | /* Evaluates to number of elements in an array; compile error if not |
| 58 | * an array (e.g. pointer) |
| 59 | */ |
| 60 | #define ARRAY_SIZE(array) \ |
| 61 | ((unsigned long) (IS_ARRAY(array) + \ |
| 62 | (sizeof(array) / sizeof((array)[0])))) |
Michael Hope | 5f67a61 | 2018-03-17 12:44:40 +0100 | [diff] [blame] | 63 | #endif |
Leandro Pereira | 1209245 | 2016-11-21 13:50:18 -0800 | [diff] [blame] | 64 | |
| 65 | /* Evaluates to 1 if ptr is part of array, 0 otherwise; compile error if |
| 66 | * "array" argument is not an array (e.g. "ptr" and "array" mixed up) |
| 67 | */ |
Leandro Pereira | 4f3be39 | 2016-11-22 10:07:40 -0800 | [diff] [blame] | 68 | #define PART_OF_ARRAY(array, ptr) \ |
| 69 | ((ptr) && ((ptr) >= &array[0] && (ptr) < &array[ARRAY_SIZE(array)])) |
| 70 | |
Leandro Pereira | 1209245 | 2016-11-21 13:50:18 -0800 | [diff] [blame] | 71 | #define CONTAINER_OF(ptr, type, field) \ |
| 72 | ((type *)(((char *)(ptr)) - offsetof(type, field))) |
| 73 | |
Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 74 | /* round "x" up/down to next multiple of "align" (which must be a power of 2) */ |
| 75 | #define ROUND_UP(x, align) \ |
| 76 | (((unsigned long)(x) + ((unsigned long)align - 1)) & \ |
| 77 | ~((unsigned long)align - 1)) |
| 78 | #define ROUND_DOWN(x, align) ((unsigned long)(x) & ~((unsigned long)align - 1)) |
| 79 | |
Benjamin Walsh | 95061b6 | 2016-12-21 10:13:02 -0500 | [diff] [blame] | 80 | #define ceiling_fraction(numerator, divider) \ |
| 81 | (((numerator) + ((divider) - 1)) / (divider)) |
| 82 | |
Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 83 | #ifdef INLINED |
| 84 | #define INLINE inline |
| 85 | #else |
| 86 | #define INLINE |
| 87 | #endif |
| 88 | |
Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 89 | #ifndef max |
| 90 | #define max(a, b) (((a) > (b)) ? (a) : (b)) |
| 91 | #endif |
| 92 | |
| 93 | #ifndef min |
| 94 | #define min(a, b) (((a) < (b)) ? (a) : (b)) |
| 95 | #endif |
| 96 | |
Benjamin Walsh | 4dca2df | 2015-08-20 13:56:10 -0400 | [diff] [blame] | 97 | static inline int is_power_of_two(unsigned int x) |
Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 98 | { |
| 99 | return (x != 0) && !(x & (x - 1)); |
| 100 | } |
Bogdan Davidoaia | bcca0dc | 2016-06-28 14:20:46 +0300 | [diff] [blame] | 101 | |
Kumar Gala | cc334c7 | 2017-04-21 10:55:34 -0500 | [diff] [blame] | 102 | static inline s64_t arithmetic_shift_right(s64_t value, u8_t shift) |
Bogdan Davidoaia | bcca0dc | 2016-06-28 14:20:46 +0300 | [diff] [blame] | 103 | { |
Kumar Gala | cc334c7 | 2017-04-21 10:55:34 -0500 | [diff] [blame] | 104 | s64_t sign_ext; |
Bogdan Davidoaia | bcca0dc | 2016-06-28 14:20:46 +0300 | [diff] [blame] | 105 | |
| 106 | if (shift == 0) { |
| 107 | return value; |
| 108 | } |
| 109 | |
| 110 | /* extract sign bit */ |
| 111 | sign_ext = (value >> 63) & 1; |
| 112 | |
| 113 | /* make all bits of sign_ext be the same as the value's sign bit */ |
| 114 | sign_ext = -sign_ext; |
| 115 | |
| 116 | /* shift value and fill opened bit positions with sign bit */ |
| 117 | return (value >> shift) | (sign_ext << (64 - shift)); |
| 118 | } |
| 119 | |
Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 120 | #endif /* !_ASMLANGUAGE */ |
| 121 | |
| 122 | /* KB, MB, GB */ |
| 123 | #define KB(x) ((x) << 10) |
| 124 | #define MB(x) (KB(x) << 10) |
| 125 | #define GB(x) (MB(x) << 10) |
| 126 | |
| 127 | /* KHZ, MHZ */ |
| 128 | #define KHZ(x) ((x) * 1000) |
| 129 | #define MHZ(x) (KHZ(x) * 1000) |
| 130 | |
Andrei Emeltchenko | bdb62b8 | 2016-07-08 12:23:41 +0300 | [diff] [blame] | 131 | #ifndef BIT |
Flavio Ceolin | 8aec087 | 2018-08-15 11:52:00 -0700 | [diff] [blame] | 132 | #if defined(_ASMLANGUAGE) |
| 133 | #define BIT(n) (1 << (n)) |
| 134 | #else |
Michael LeMay | ebba3bf | 2015-10-26 16:38:13 -0700 | [diff] [blame] | 135 | #define BIT(n) (1UL << (n)) |
Andrei Emeltchenko | bdb62b8 | 2016-07-08 12:23:41 +0300 | [diff] [blame] | 136 | #endif |
Flavio Ceolin | 8aec087 | 2018-08-15 11:52:00 -0700 | [diff] [blame] | 137 | #endif |
Michael LeMay | ebba3bf | 2015-10-26 16:38:13 -0700 | [diff] [blame] | 138 | |
Mieszko Mierunski | 030a65c | 2018-07-03 11:19:55 +0200 | [diff] [blame] | 139 | /** |
| 140 | * @brief Macro sets or clears bit depending on boolean value |
| 141 | * |
| 142 | * @param var Variable to be altered |
| 143 | * @param bit Bit number |
| 144 | * @param set Value 0 clears bit, any other value sets bit |
| 145 | */ |
| 146 | #define WRITE_BIT(var, bit, set) \ |
| 147 | ((var) = (set) ? ((var) | BIT(bit)) : ((var) & ~BIT(bit))) |
| 148 | |
Tomasz Bursztyka | 69ffd8e | 2016-03-22 13:53:41 +0100 | [diff] [blame] | 149 | #define BIT_MASK(n) (BIT(n) - 1) |
| 150 | |
Andy Ross | 5bc458a | 2016-08-16 09:47:16 -0700 | [diff] [blame] | 151 | /** |
| 152 | * @brief Check for macro definition in compiler-visible expressions |
| 153 | * |
| 154 | * This trick was pioneered in Linux as the config_enabled() macro. |
| 155 | * The madness has the effect of taking a macro value that may be |
| 156 | * defined to "1" (e.g. CONFIG_MYFEATURE), or may not be defined at |
| 157 | * all and turning it into a literal expression that can be used at |
| 158 | * "runtime". That is, it works similarly to |
| 159 | * "defined(CONFIG_MYFEATURE)" does except that it is an expansion |
| 160 | * that can exist in a standard expression and be seen by the compiler |
| 161 | * and optimizer. Thus much ifdef usage can be replaced with cleaner |
| 162 | * expressions like: |
| 163 | * |
| 164 | * if (IS_ENABLED(CONFIG_MYFEATURE)) |
| 165 | * myfeature_enable(); |
| 166 | * |
| 167 | * INTERNAL |
| 168 | * First pass just to expand any existing macros, we need the macro |
| 169 | * value to be e.g. a literal "1" at expansion time in the next macro, |
| 170 | * not "(1)", etc... Standard recursive expansion does not work. |
| 171 | */ |
| 172 | #define IS_ENABLED(config_macro) _IS_ENABLED1(config_macro) |
| 173 | |
| 174 | /* Now stick on a "_XXXX" prefix, it will now be "_XXXX1" if config_macro |
| 175 | * is "1", or just "_XXXX" if it's undefined. |
| 176 | * ENABLED: _IS_ENABLED2(_XXXX1) |
| 177 | * DISABLED _IS_ENABLED2(_XXXX) |
| 178 | */ |
| 179 | #define _IS_ENABLED1(config_macro) _IS_ENABLED2(_XXXX##config_macro) |
| 180 | |
| 181 | /* Here's the core trick, we map "_XXXX1" to "_YYYY," (i.e. a string |
| 182 | * with a trailing comma), so it has the effect of making this a |
| 183 | * two-argument tuple to the preprocessor only in the case where the |
| 184 | * value is defined to "1" |
| 185 | * ENABLED: _YYYY, <--- note comma! |
| 186 | * DISABLED: _XXXX |
| 187 | */ |
| 188 | #define _XXXX1 _YYYY, |
| 189 | |
| 190 | /* Then we append an extra argument to fool the gcc preprocessor into |
| 191 | * accepting it as a varargs macro. |
| 192 | * arg1 arg2 arg3 |
| 193 | * ENABLED: _IS_ENABLED3(_YYYY, 1, 0) |
| 194 | * DISABLED _IS_ENABLED3(_XXXX 1, 0) |
| 195 | */ |
Flavio Ceolin | 6fdc56d | 2018-09-18 12:32:27 -0700 | [diff] [blame] | 196 | #define _IS_ENABLED2(one_or_two_args) _IS_ENABLED3(one_or_two_args true, false) |
Andy Ross | 5bc458a | 2016-08-16 09:47:16 -0700 | [diff] [blame] | 197 | |
| 198 | /* And our second argument is thus now cooked to be 1 in the case |
| 199 | * where the value is defined to 1, and 0 if not: |
| 200 | */ |
| 201 | #define _IS_ENABLED3(ignore_this, val, ...) val |
| 202 | |
Anas Nashif | 0a4808b | 2017-10-31 09:30:38 -0400 | [diff] [blame] | 203 | /** |
Krzysztof Chruscinski | 70b738f | 2019-01-23 13:17:44 +0100 | [diff] [blame] | 204 | * @brief Insert code depending on result of flag evaluation. |
| 205 | * |
| 206 | * This is based on same idea as @ref IS_ENABLED macro but as the result of |
| 207 | * flag evaluation provided code is injected. Because preprocessor interprets |
Krzysztof Chruscinski | 8cdca11 | 2019-01-23 13:29:43 +0100 | [diff] [blame] | 208 | * each comma as an argument boundary, code must be provided in the brackets. |
Krzysztof Chruscinski | 70b738f | 2019-01-23 13:17:44 +0100 | [diff] [blame] | 209 | * Brackets are stripped away during macro processing. |
| 210 | * |
| 211 | * Usage example: |
| 212 | * |
Krzysztof Chruscinski | 8cdca11 | 2019-01-23 13:29:43 +0100 | [diff] [blame] | 213 | * \#define MACRO(x) COND_CODE_1(CONFIG_FLAG, (u32_t x;), ()) |
Krzysztof Chruscinski | 70b738f | 2019-01-23 13:17:44 +0100 | [diff] [blame] | 214 | * |
| 215 | * It can be considered as alternative to: |
| 216 | * |
Krzysztof Chruscinski | 8cdca11 | 2019-01-23 13:29:43 +0100 | [diff] [blame] | 217 | * \#if defined(CONFIG_FLAG) && (CONFIG_FLAG == 1) |
| 218 | * \#define MACRO(x) u32_t x; |
| 219 | * \#else |
| 220 | * \#define MACRO(x) |
| 221 | * \#endif |
Krzysztof Chruscinski | 70b738f | 2019-01-23 13:17:44 +0100 | [diff] [blame] | 222 | * |
| 223 | * However, the advantage of that approach is that code is resolved in place |
| 224 | * where it is used while \#if method resolves given macro when header is |
| 225 | * included and product is fixed in the given scope. |
| 226 | * |
| 227 | * @note Flag can also be a result of preprocessor output e.g. |
| 228 | * product of NUM_VA_ARGS_LESS_1(...). |
| 229 | * |
| 230 | * @param _flag Evaluated flag |
| 231 | * @param _if_1_code Code used if flag exists and equal 1. Argument must be |
| 232 | * in brackets. |
| 233 | * @param _else_code Code used if flag doesn't exists or isn't equal 1. |
| 234 | * |
| 235 | */ |
| 236 | #define COND_CODE_1(_flag, _if_1_code, _else_code) \ |
| 237 | _COND_CODE_1(_flag, _if_1_code, _else_code) |
| 238 | |
| 239 | #define _COND_CODE_1(_flag, _if_1_code, _else_code) \ |
| 240 | __COND_CODE(_XXXX##_flag, _if_1_code, _else_code) |
| 241 | |
| 242 | /** |
| 243 | * @brief Insert code depending on result of flag evaluation. |
| 244 | * |
| 245 | * See @ref COND_CODE_1 for details. |
| 246 | * |
| 247 | * @param _flag Evaluated flag |
| 248 | * @param _if_0_code Code used if flag exists and equal 0. Argument must be |
| 249 | * in brackets. |
| 250 | * @param _else_code Code used if flag doesn't exists or isn't equal 0. |
| 251 | * |
| 252 | */ |
| 253 | #define COND_CODE_0(_flag, _if_0_code, _else_code) \ |
| 254 | _COND_CODE_0(_flag, _if_0_code, _else_code) |
| 255 | |
| 256 | #define _COND_CODE_0(_flag, _if_0_code, _else_code) \ |
| 257 | __COND_CODE(_ZZZZ##_flag, _if_0_code, _else_code) |
| 258 | |
| 259 | #define _ZZZZ0 _YYYY, |
| 260 | |
| 261 | /* Macro used internally by @ref COND_CODE_1 and @ref COND_CODE_0. */ |
| 262 | #define __COND_CODE(one_or_two_args, _if_code, _else_code) \ |
| 263 | __GET_ARG2_DEBRACKET(one_or_two_args _if_code, _else_code) |
| 264 | |
| 265 | /* Macro used internally to remove brackets from argument. */ |
| 266 | #define __DEBRACKET(...) __VA_ARGS__ |
| 267 | |
| 268 | /* Macro used internally for getting second argument and removing brackets |
| 269 | * around that argument. It is expected that parameter is provided in brackets |
| 270 | */ |
| 271 | #define __GET_ARG2_DEBRACKET(ignore_this, val, ...) __DEBRACKET val |
| 272 | |
| 273 | /** |
| 274 | * @brief Get first argument from variable list of arguments |
| 275 | */ |
| 276 | #define GET_ARG1(arg1, ...) arg1 |
| 277 | |
| 278 | /** |
| 279 | * @brief Get second argument from variable list of arguments |
| 280 | */ |
| 281 | #define GET_ARG2(arg1, arg2, ...) arg2 |
| 282 | |
| 283 | /** |
| 284 | * @brief Get all arguments except the first one. |
| 285 | */ |
| 286 | #define GET_ARGS_LESS_1(val, ...) __VA_ARGS__ |
| 287 | |
| 288 | /** |
Anas Nashif | 0a4808b | 2017-10-31 09:30:38 -0400 | [diff] [blame] | 289 | * Macros for doing code-generation with the preprocessor. |
| 290 | * |
| 291 | * Generally it is better to generate code with the preprocessor than |
| 292 | * to copy-paste code or to generate code with the build system / |
| 293 | * python script's etc. |
| 294 | * |
| 295 | * http://stackoverflow.com/a/12540675 |
| 296 | */ |
| 297 | #define UTIL_EMPTY(...) |
| 298 | #define UTIL_DEFER(...) __VA_ARGS__ UTIL_EMPTY() |
| 299 | #define UTIL_OBSTRUCT(...) __VA_ARGS__ UTIL_DEFER(UTIL_EMPTY)() |
| 300 | #define UTIL_EXPAND(...) __VA_ARGS__ |
| 301 | |
| 302 | #define UTIL_EVAL(...) UTIL_EVAL1(UTIL_EVAL1(UTIL_EVAL1(__VA_ARGS__))) |
| 303 | #define UTIL_EVAL1(...) UTIL_EVAL2(UTIL_EVAL2(UTIL_EVAL2(__VA_ARGS__))) |
| 304 | #define UTIL_EVAL2(...) UTIL_EVAL3(UTIL_EVAL3(UTIL_EVAL3(__VA_ARGS__))) |
| 305 | #define UTIL_EVAL3(...) UTIL_EVAL4(UTIL_EVAL4(UTIL_EVAL4(__VA_ARGS__))) |
| 306 | #define UTIL_EVAL4(...) UTIL_EVAL5(UTIL_EVAL5(UTIL_EVAL5(__VA_ARGS__))) |
| 307 | #define UTIL_EVAL5(...) __VA_ARGS__ |
| 308 | |
| 309 | #define UTIL_CAT(a, ...) UTIL_PRIMITIVE_CAT(a, __VA_ARGS__) |
| 310 | #define UTIL_PRIMITIVE_CAT(a, ...) a##__VA_ARGS__ |
| 311 | |
| 312 | #define UTIL_INC(x) UTIL_PRIMITIVE_CAT(UTIL_INC_, x) |
| 313 | #define UTIL_INC_0 1 |
| 314 | #define UTIL_INC_1 2 |
| 315 | #define UTIL_INC_2 3 |
| 316 | #define UTIL_INC_3 4 |
| 317 | #define UTIL_INC_4 5 |
| 318 | #define UTIL_INC_5 6 |
| 319 | #define UTIL_INC_6 7 |
| 320 | #define UTIL_INC_7 8 |
| 321 | #define UTIL_INC_8 9 |
| 322 | #define UTIL_INC_9 10 |
| 323 | #define UTIL_INC_10 11 |
| 324 | #define UTIL_INC_11 12 |
| 325 | #define UTIL_INC_12 13 |
| 326 | #define UTIL_INC_13 14 |
| 327 | #define UTIL_INC_14 15 |
| 328 | #define UTIL_INC_15 16 |
| 329 | #define UTIL_INC_16 17 |
| 330 | #define UTIL_INC_17 18 |
| 331 | #define UTIL_INC_18 19 |
| 332 | #define UTIL_INC_19 19 |
| 333 | |
| 334 | #define UTIL_DEC(x) UTIL_PRIMITIVE_CAT(UTIL_DEC_, x) |
| 335 | #define UTIL_DEC_0 0 |
| 336 | #define UTIL_DEC_1 0 |
| 337 | #define UTIL_DEC_2 1 |
| 338 | #define UTIL_DEC_3 2 |
| 339 | #define UTIL_DEC_4 3 |
| 340 | #define UTIL_DEC_5 4 |
| 341 | #define UTIL_DEC_6 5 |
| 342 | #define UTIL_DEC_7 6 |
| 343 | #define UTIL_DEC_8 7 |
| 344 | #define UTIL_DEC_9 8 |
| 345 | #define UTIL_DEC_10 9 |
| 346 | #define UTIL_DEC_11 10 |
| 347 | #define UTIL_DEC_12 11 |
| 348 | #define UTIL_DEC_13 12 |
| 349 | #define UTIL_DEC_14 13 |
| 350 | #define UTIL_DEC_15 14 |
| 351 | #define UTIL_DEC_16 15 |
| 352 | #define UTIL_DEC_17 16 |
| 353 | #define UTIL_DEC_18 17 |
| 354 | #define UTIL_DEC_19 18 |
Adithya Baglody | d70196b | 2018-04-04 17:20:09 +0530 | [diff] [blame] | 355 | #define UTIL_DEC_20 19 |
| 356 | #define UTIL_DEC_21 20 |
| 357 | #define UTIL_DEC_22 21 |
| 358 | #define UTIL_DEC_23 22 |
| 359 | #define UTIL_DEC_24 23 |
| 360 | #define UTIL_DEC_25 24 |
| 361 | #define UTIL_DEC_26 25 |
| 362 | #define UTIL_DEC_27 26 |
| 363 | #define UTIL_DEC_28 27 |
| 364 | #define UTIL_DEC_29 28 |
| 365 | #define UTIL_DEC_30 29 |
| 366 | #define UTIL_DEC_31 30 |
| 367 | #define UTIL_DEC_32 31 |
| 368 | #define UTIL_DEC_33 32 |
| 369 | #define UTIL_DEC_34 33 |
| 370 | #define UTIL_DEC_35 34 |
| 371 | #define UTIL_DEC_36 35 |
| 372 | #define UTIL_DEC_37 36 |
| 373 | #define UTIL_DEC_38 37 |
| 374 | #define UTIL_DEC_39 38 |
| 375 | #define UTIL_DEC_40 39 |
Anas Nashif | 0a4808b | 2017-10-31 09:30:38 -0400 | [diff] [blame] | 376 | |
| 377 | #define UTIL_CHECK_N(x, n, ...) n |
| 378 | #define UTIL_CHECK(...) UTIL_CHECK_N(__VA_ARGS__, 0,) |
| 379 | |
| 380 | #define UTIL_NOT(x) UTIL_CHECK(UTIL_PRIMITIVE_CAT(UTIL_NOT_, x)) |
| 381 | #define UTIL_NOT_0 ~, 1, |
| 382 | |
| 383 | #define UTIL_COMPL(b) UTIL_PRIMITIVE_CAT(UTIL_COMPL_, b) |
| 384 | #define UTIL_COMPL_0 1 |
| 385 | #define UTIL_COMPL_1 0 |
| 386 | |
| 387 | #define UTIL_BOOL(x) UTIL_COMPL(UTIL_NOT(x)) |
| 388 | |
| 389 | #define UTIL_IIF(c) UTIL_PRIMITIVE_CAT(UTIL_IIF_, c) |
| 390 | #define UTIL_IIF_0(t, ...) __VA_ARGS__ |
| 391 | #define UTIL_IIF_1(t, ...) t |
| 392 | |
| 393 | #define UTIL_IF(c) UTIL_IIF(UTIL_BOOL(c)) |
| 394 | |
| 395 | #define UTIL_EAT(...) |
| 396 | #define UTIL_EXPAND(...) __VA_ARGS__ |
| 397 | #define UTIL_WHEN(c) UTIL_IF(c)(UTIL_EXPAND, UTIL_EAT) |
| 398 | |
| 399 | #define UTIL_REPEAT(count, macro, ...) \ |
| 400 | UTIL_WHEN(count) \ |
| 401 | ( \ |
| 402 | UTIL_OBSTRUCT(UTIL_REPEAT_INDIRECT) () \ |
| 403 | ( \ |
| 404 | UTIL_DEC(count), macro, __VA_ARGS__ \ |
| 405 | ) \ |
| 406 | UTIL_OBSTRUCT(macro) \ |
| 407 | ( \ |
| 408 | UTIL_DEC(count), __VA_ARGS__ \ |
| 409 | ) \ |
| 410 | ) |
| 411 | #define UTIL_REPEAT_INDIRECT() UTIL_REPEAT |
| 412 | |
| 413 | /** |
| 414 | * Generates a sequence of code. |
| 415 | * Useful for generating code like; |
| 416 | * |
| 417 | * NRF_PWM0, NRF_PWM1, NRF_PWM2, |
| 418 | * |
| 419 | * @arg LEN: The length of the sequence. Must be defined and less than |
| 420 | * 20. |
| 421 | * |
| 422 | * @arg F(i, F_ARG): A macro function that accepts two arguments. |
| 423 | * F is called repeatedly, the first argument |
| 424 | * is the index in the sequence, and the second argument is the third |
| 425 | * argument given to UTIL_LISTIFY. |
| 426 | * |
| 427 | * Example: |
| 428 | * |
| 429 | * \#define FOO(i, _) NRF_PWM ## i , |
| 430 | * { UTIL_LISTIFY(PWM_COUNT, FOO) } |
Flavio Ceolin | fcfcb7e | 2018-11-03 22:13:06 -0700 | [diff] [blame] | 431 | * The above two lines will generate the below: |
Anas Nashif | 0a4808b | 2017-10-31 09:30:38 -0400 | [diff] [blame] | 432 | * { NRF_PWM0 , NRF_PWM1 , } |
| 433 | * |
| 434 | * @note Calling UTIL_LISTIFY with undefined arguments has undefined |
David B. Kinder | 79e9165 | 2018-01-30 11:41:06 -0800 | [diff] [blame] | 435 | * behavior. |
Anas Nashif | 0a4808b | 2017-10-31 09:30:38 -0400 | [diff] [blame] | 436 | */ |
| 437 | #define UTIL_LISTIFY(LEN, F, F_ARG) UTIL_EVAL(UTIL_REPEAT(LEN, F, F_ARG)) |
| 438 | |
Krzysztof Chruściński | bbeef41 | 2018-05-16 08:50:33 +0200 | [diff] [blame] | 439 | /**@brief Implementation details for NUM_VAR_ARGS */ |
| 440 | #define NUM_VA_ARGS_LESS_1_IMPL( \ |
| 441 | _ignored, \ |
| 442 | _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, \ |
| 443 | _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, \ |
| 444 | _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, \ |
| 445 | _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, \ |
| 446 | _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, \ |
| 447 | _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, \ |
| 448 | _61, _62, N, ...) N |
| 449 | |
| 450 | /**@brief Macro to get the number of arguments in a call variadic macro call. |
| 451 | * First argument is not counted. |
| 452 | * |
| 453 | * param[in] ... List of arguments |
| 454 | * |
| 455 | * @retval Number of variadic arguments in the argument list |
| 456 | */ |
| 457 | #define NUM_VA_ARGS_LESS_1(...) \ |
| 458 | NUM_VA_ARGS_LESS_1_IMPL(__VA_ARGS__, 63, 62, 61, \ |
| 459 | 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, \ |
| 460 | 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, \ |
| 461 | 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, \ |
| 462 | 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, \ |
| 463 | 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, \ |
| 464 | 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, ~) |
| 465 | |
| 466 | /** |
| 467 | * @brief Mapping macro |
| 468 | * |
| 469 | * Macro that process all arguments using given macro |
| 470 | * |
| 471 | * @param ... Macro name to be used for argument processing followed by |
| 472 | * arguments to process. Macro should have following |
| 473 | * form: MACRO(argument). |
| 474 | * |
| 475 | * @return All arguments processed by given macro |
| 476 | */ |
| 477 | #define MACRO_MAP(...) MACRO_MAP_(__VA_ARGS__) |
| 478 | #define MACRO_MAP_(...) \ |
| 479 | /* To make sure it works also for 2 arguments in total */ \ |
| 480 | MACRO_MAP_N(NUM_VA_ARGS_LESS_1(__VA_ARGS__), __VA_ARGS__) |
| 481 | |
| 482 | /** |
| 483 | * @brief Mapping N arguments macro |
| 484 | * |
| 485 | * Macro similar to @ref MACRO_MAP but maps exact number of arguments. |
| 486 | * If there is more arguments given, the rest would be ignored. |
| 487 | * |
| 488 | * @param N Number of arguments to map |
| 489 | * @param ... Macro name to be used for argument processing followed by |
| 490 | * arguments to process. Macro should have following |
| 491 | * form: MACRO(argument). |
| 492 | * |
| 493 | * @return Selected number of arguments processed by given macro |
| 494 | */ |
| 495 | #define MACRO_MAP_N(N, ...) MACRO_MAP_N_(N, __VA_ARGS__) |
| 496 | #define MACRO_MAP_N_(N, ...) UTIL_CAT(MACRO_MAP_, N)(__VA_ARGS__,) |
| 497 | |
| 498 | #define MACRO_MAP_0(...) |
| 499 | #define MACRO_MAP_1(macro, a, ...) macro(a) |
| 500 | #define MACRO_MAP_2(macro, a, ...) macro(a)MACRO_MAP_1(macro, __VA_ARGS__,) |
| 501 | #define MACRO_MAP_3(macro, a, ...) macro(a)MACRO_MAP_2(macro, __VA_ARGS__,) |
| 502 | #define MACRO_MAP_4(macro, a, ...) macro(a)MACRO_MAP_3(macro, __VA_ARGS__,) |
| 503 | #define MACRO_MAP_5(macro, a, ...) macro(a)MACRO_MAP_4(macro, __VA_ARGS__,) |
| 504 | #define MACRO_MAP_6(macro, a, ...) macro(a)MACRO_MAP_5(macro, __VA_ARGS__,) |
| 505 | #define MACRO_MAP_7(macro, a, ...) macro(a)MACRO_MAP_6(macro, __VA_ARGS__,) |
| 506 | #define MACRO_MAP_8(macro, a, ...) macro(a)MACRO_MAP_7(macro, __VA_ARGS__,) |
| 507 | #define MACRO_MAP_9(macro, a, ...) macro(a)MACRO_MAP_8(macro, __VA_ARGS__,) |
| 508 | #define MACRO_MAP_10(macro, a, ...) macro(a)MACRO_MAP_9(macro, __VA_ARGS__,) |
| 509 | #define MACRO_MAP_11(macro, a, ...) macro(a)MACRO_MAP_10(macro, __VA_ARGS__,) |
| 510 | #define MACRO_MAP_12(macro, a, ...) macro(a)MACRO_MAP_11(macro, __VA_ARGS__,) |
| 511 | #define MACRO_MAP_13(macro, a, ...) macro(a)MACRO_MAP_12(macro, __VA_ARGS__,) |
| 512 | #define MACRO_MAP_14(macro, a, ...) macro(a)MACRO_MAP_13(macro, __VA_ARGS__,) |
| 513 | #define MACRO_MAP_15(macro, a, ...) macro(a)MACRO_MAP_14(macro, __VA_ARGS__,) |
Shawn Mosley | 573f32b | 2018-04-26 10:14:02 -0400 | [diff] [blame] | 514 | /* |
| 515 | * The following provides variadic preprocessor macro support to |
| 516 | * help eliminate multiple, repetitive function/macro calls. This |
| 517 | * allows up to 10 "arguments" in addition to _call . |
| 518 | * Note - derived from work on: |
| 519 | * https://codecraft.co/2014/11/25/variadic-macros-tricks/ |
| 520 | */ |
| 521 | |
| 522 | #define _GET_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N |
| 523 | |
| 524 | #define _for_0(_call, ...) |
| 525 | #define _for_1(_call, x) _call(x) |
| 526 | #define _for_2(_call, x, ...) _call(x) _for_1(_call, ##__VA_ARGS__) |
| 527 | #define _for_3(_call, x, ...) _call(x) _for_2(_call, ##__VA_ARGS__) |
| 528 | #define _for_4(_call, x, ...) _call(x) _for_3(_call, ##__VA_ARGS__) |
| 529 | #define _for_5(_call, x, ...) _call(x) _for_4(_call, ##__VA_ARGS__) |
| 530 | #define _for_6(_call, x, ...) _call(x) _for_5(_call, ##__VA_ARGS__) |
| 531 | #define _for_7(_call, x, ...) _call(x) _for_6(_call, ##__VA_ARGS__) |
| 532 | #define _for_8(_call, x, ...) _call(x) _for_7(_call, ##__VA_ARGS__) |
| 533 | #define _for_9(_call, x, ...) _call(x) _for_8(_call, ##__VA_ARGS__) |
| 534 | #define _for_10(_call, x, ...) _call(x) _for_9(_call, ##__VA_ARGS__) |
| 535 | |
| 536 | #define FOR_EACH(x, ...) \ |
| 537 | _GET_ARG(__VA_ARGS__, \ |
| 538 | _for_10, _for_9, _for_8, _for_7, _for_6, _for_5, \ |
| 539 | _for_4, _for_3, _for_2, _for_1, _for_0)(x, ##__VA_ARGS__) |
Krzysztof Chruściński | bbeef41 | 2018-05-16 08:50:33 +0200 | [diff] [blame] | 540 | |
Adithya Baglody | 9febb65 | 2019-01-02 14:21:15 +0530 | [diff] [blame] | 541 | /* FOR_EACH_FIXED_ARG is used for calling the same function |
| 542 | * With one fixed argument and changing 2nd argument. |
| 543 | */ |
| 544 | |
| 545 | #define z_rep_0(_fn, f, ...) |
| 546 | #define z_rep_1(_fn, f, x) {_fn(x, f); z_rep_0(_fn, f)} |
| 547 | #define z_rep_2(_fn, f, x, ...) {_fn(x, f); z_rep_1(_fn, f, ##__VA_ARGS__)} |
| 548 | #define z_rep_3(_fn, f, x, ...) {_fn(x, f); z_rep_2(_fn, f, ##__VA_ARGS__)} |
| 549 | #define z_rep_4(_fn, f, x, ...) {_fn(x, f); z_rep_3(_fn, f, ##__VA_ARGS__)} |
| 550 | #define z_rep_5(_fn, f, x, ...) {_fn(x, f); z_rep_4(_fn, f, ##__VA_ARGS__)} |
| 551 | #define z_rep_6(_fn, f, x, ...) {_fn(x, f); z_rep_5(_fn, f, ##__VA_ARGS__)} |
| 552 | #define z_rep_7(_fn, f, x, ...) {_fn(x, f); z_rep_6(_fn, f, ##__VA_ARGS__)} |
| 553 | #define z_rep_8(_fn, f, x, ...) {_fn(x, f); z_rep_7(_fn, f, ##__VA_ARGS__)} |
| 554 | #define z_rep_9(_fn, f, x, ...) {_fn(x, f); z_rep_8(_fn, f, ##__VA_ARGS__)} |
| 555 | #define z_rep_10(_fn, f, x, ...) {_fn(x, f); z_rep_9(_fn, f, ##__VA_ARGS__)} |
| 556 | #define z_rep_11(_fn, f, x, ...) {_fn(x, f); z_rep_10(_fn, f, ##__VA_ARGS__)} |
| 557 | #define z_rep_12(_fn, f, x, ...) {_fn(x, f); z_rep_11(_fn, f, ##__VA_ARGS__)} |
| 558 | #define z_rep_13(_fn, f, x, ...) {_fn(x, f); z_rep_12(_fn, f, ##__VA_ARGS__)} |
| 559 | #define z_rep_14(_fn, f, x, ...) {_fn(x, f); z_rep_13(_fn, f, ##__VA_ARGS__)} |
| 560 | #define z_rep_15(_fn, f, x, ...) {_fn(x, f); z_rep_14(_fn, f, ##__VA_ARGS__)} |
| 561 | #define z_rep_16(_fn, f, x, ...) {_fn(x, f); z_rep_15(_fn, f, ##__VA_ARGS__)} |
| 562 | #define z_rep_17(_fn, f, x, ...) {_fn(x, f); z_rep_16(_fn, f, ##__VA_ARGS__)} |
| 563 | #define z_rep_18(_fn, f, x, ...) {_fn(x, f); z_rep_17(_fn, f, ##__VA_ARGS__)} |
| 564 | #define z_rep_19(_fn, f, x, ...) {_fn(x, f); z_rep_18(_fn, f, ##__VA_ARGS__)} |
| 565 | #define z_rep_20(_fn, f, x, ...) {_fn(x, f); z_rep_19(_fn, f, ##__VA_ARGS__)} |
| 566 | |
| 567 | |
| 568 | #define Z_GET_ARG_2(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, \ |
| 569 | _14, _15, _16, _17, _18, _19, _20, N, ...) N |
| 570 | |
| 571 | #define FOR_EACH_FIXED_ARG(fixed_arg, x, ...) \ |
| 572 | {Z_GET_ARG_2(__VA_ARGS__, \ |
| 573 | z_rep_20, z_rep_19, z_rep_18, z_rep_17, z_rep_16, \ |
| 574 | z_rep_15, z_rep_14, z_rep_13, z_rep_12, z_rep_11, \ |
| 575 | z_rep_10, z_rep_9, z_rep_8, z_rep_7, z_rep_6, \ |
| 576 | z_rep_5, z_rep_4, z_rep_3, z_rep_2, z_rep_1, z_rep_0) \ |
| 577 | (fixed_arg, x, ##__VA_ARGS__)} |
| 578 | |
Flavio Ceolin | 67ca176 | 2018-09-14 10:43:44 -0700 | [diff] [blame] | 579 | #endif /* ZEPHYR_INCLUDE_MISC_UTIL_H_ */ |