api: promote sys/util.h to experimental
This file contains definitions for macros which are integral to significant Zephyr use cases, such as CONTAINER_OF() and various macros used by devicetree.h internally. As such, in practice we expect at least advanced (if not intermediate) users to understand it, so the fact that it's not formally documented as an API with a stability level is a problem. Fix that by giving the docstrings a once-over and adding new ones where they are missing. Move all the remaining non-API macros to util_internal.h. Add a Sphinx API page for this header, and include it in the API overview at "experimental" stability level. Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
This commit is contained in:
parent
317eaa5a7e
commit
04df8124ac
5 changed files with 601 additions and 453 deletions
|
@ -30,4 +30,5 @@ API Reference
|
|||
storage/index.rst
|
||||
usb/index.rst
|
||||
usermode/index.rst
|
||||
util/index.rst
|
||||
settings/index.rst
|
||||
|
|
|
@ -273,3 +273,8 @@ current :ref:`stability level <api_lifecycle>`.
|
|||
- Stable
|
||||
- 1.11
|
||||
- 1.11
|
||||
|
||||
* - :ref:`util_api`
|
||||
- Experimental
|
||||
- 2.4
|
||||
- 2.4
|
||||
|
|
10
doc/reference/util/index.rst
Normal file
10
doc/reference/util/index.rst
Normal file
|
@ -0,0 +1,10 @@
|
|||
.. _util_api:
|
||||
|
||||
Utilities
|
||||
#########
|
||||
|
||||
This page contains reference documentation for ``<sys/util.h>``, which provides
|
||||
miscellaneous utility functions and macros.
|
||||
|
||||
.. doxygengroup:: sys-util
|
||||
:project: Zephyr
|
File diff suppressed because it is too large
Load diff
|
@ -15,6 +15,106 @@
|
|||
#ifndef ZEPHYR_INCLUDE_SYS_UTIL_INTERNAL_H_
|
||||
#define ZEPHYR_INCLUDE_SYS_UTIL_INTERNAL_H_
|
||||
|
||||
/* IS_ENABLED() helpers */
|
||||
|
||||
/* This is called from IS_ENABLED(), and sticks on a "_XXXX" prefix,
|
||||
* it will now be "_XXXX1" if config_macro is "1", or just "_XXXX" if it's
|
||||
* undefined.
|
||||
* ENABLED: Z_IS_ENABLED2(_XXXX1)
|
||||
* DISABLED Z_IS_ENABLED2(_XXXX)
|
||||
*/
|
||||
#define Z_IS_ENABLED1(config_macro) Z_IS_ENABLED2(_XXXX##config_macro)
|
||||
|
||||
/* Here's the core trick, we map "_XXXX1" to "_YYYY," (i.e. a string
|
||||
* with a trailing comma), so it has the effect of making this a
|
||||
* two-argument tuple to the preprocessor only in the case where the
|
||||
* value is defined to "1"
|
||||
* ENABLED: _YYYY, <--- note comma!
|
||||
* DISABLED: _XXXX
|
||||
*/
|
||||
#define _XXXX1 _YYYY,
|
||||
|
||||
/* Then we append an extra argument to fool the gcc preprocessor into
|
||||
* accepting it as a varargs macro.
|
||||
* arg1 arg2 arg3
|
||||
* ENABLED: Z_IS_ENABLED3(_YYYY, 1, 0)
|
||||
* DISABLED Z_IS_ENABLED3(_XXXX 1, 0)
|
||||
*/
|
||||
#define Z_IS_ENABLED2(one_or_two_args) Z_IS_ENABLED3(one_or_two_args true, false)
|
||||
|
||||
/* And our second argument is thus now cooked to be 1 in the case
|
||||
* where the value is defined to 1, and 0 if not:
|
||||
*/
|
||||
#define Z_IS_ENABLED3(ignore_this, val, ...) val
|
||||
|
||||
/* Used internally by COND_CODE_1 and COND_CODE_0. */
|
||||
#define Z_COND_CODE_1(_flag, _if_1_code, _else_code) \
|
||||
__COND_CODE(_XXXX##_flag, _if_1_code, _else_code)
|
||||
#define Z_COND_CODE_0(_flag, _if_0_code, _else_code) \
|
||||
__COND_CODE(_ZZZZ##_flag, _if_0_code, _else_code)
|
||||
#define _ZZZZ0 _YYYY,
|
||||
#define __COND_CODE(one_or_two_args, _if_code, _else_code) \
|
||||
__GET_ARG2_DEBRACKET(one_or_two_args _if_code, _else_code)
|
||||
|
||||
/* Gets second argument and removes brackets around that argument. It
|
||||
* is expected that the parameter is provided in brackets/parentheses.
|
||||
*/
|
||||
#define __GET_ARG2_DEBRACKET(ignore_this, val, ...) __DEBRACKET val
|
||||
|
||||
/* Used to remove brackets from around a single argument. */
|
||||
#define __DEBRACKET(...) __VA_ARGS__
|
||||
|
||||
/* Used by IS_EMPTY() */
|
||||
#define Z_IS_EMPTY_(...) Z_IS_EMPTY__(__VA_ARGS__)
|
||||
#define Z_IS_EMPTY__(a, ...) Z_IS_EMPTY___(_ZZ##a##ZZ0, __VA_ARGS__)
|
||||
#define Z_IS_EMPTY___(...) Z_IS_EMPTY____(GET_ARGS_LESS_1(__VA_ARGS__))
|
||||
#define Z_IS_EMPTY____(...) GET_ARG2(__VA_ARGS__)
|
||||
|
||||
/* Used by LIST_DROP_EMPTY() */
|
||||
/* Adding ',' after each element would add empty element at the end of
|
||||
* list, which is hard to remove, so instead precede each element with ',',
|
||||
* this way first element is empty, and this one is easy to drop.
|
||||
*/
|
||||
#define Z_LIST_ADD_ELEM(e) EMPTY, e
|
||||
#define Z_LIST_DROP_FIRST(...) GET_ARGS_LESS_1(__VA_ARGS__)
|
||||
#define Z_LIST_NO_EMPTIES(e) \
|
||||
COND_CODE_1(IS_EMPTY(e), (), (Z_LIST_ADD_ELEM(e)))
|
||||
|
||||
/*
|
||||
* Macros for doing code-generation with the preprocessor as if we
|
||||
* could do recursive macro expansion.
|
||||
*
|
||||
* Generally it is better to generate code with the preprocessor than
|
||||
* to copy-paste code or to generate code with the build system /
|
||||
* python script's etc.
|
||||
*
|
||||
* http://stackoverflow.com/a/12540675
|
||||
*/
|
||||
|
||||
#define UTIL_EMPTY(...)
|
||||
#define UTIL_DEFER(...) __VA_ARGS__ UTIL_EMPTY()
|
||||
#define UTIL_OBSTRUCT(...) __VA_ARGS__ UTIL_DEFER(UTIL_EMPTY)()
|
||||
#define UTIL_EXPAND(...) __VA_ARGS__
|
||||
|
||||
#define UTIL_EVAL(...) UTIL_EVAL1(UTIL_EVAL1(UTIL_EVAL1(__VA_ARGS__)))
|
||||
#define UTIL_EVAL1(...) UTIL_EVAL2(UTIL_EVAL2(UTIL_EVAL2(__VA_ARGS__)))
|
||||
#define UTIL_EVAL2(...) UTIL_EVAL3(UTIL_EVAL3(UTIL_EVAL3(__VA_ARGS__)))
|
||||
#define UTIL_EVAL3(...) UTIL_EVAL4(UTIL_EVAL4(UTIL_EVAL4(__VA_ARGS__)))
|
||||
#define UTIL_EVAL4(...) UTIL_EVAL5(UTIL_EVAL5(UTIL_EVAL5(__VA_ARGS__)))
|
||||
#define UTIL_EVAL5(...) __VA_ARGS__
|
||||
|
||||
#define UTIL_CAT(a, ...) UTIL_PRIMITIVE_CAT(a, __VA_ARGS__)
|
||||
#define UTIL_PRIMITIVE_CAT(a, ...) a##__VA_ARGS__
|
||||
|
||||
/*
|
||||
* UTIL_INC(x) for an integer literal x from 0 to 255 expands to an
|
||||
* integer literal whose value is x+1.
|
||||
*
|
||||
* Similarly, UTIL_DEC(x) is (x-1) as an integer literal.
|
||||
*/
|
||||
#define UTIL_INC(x) UTIL_PRIMITIVE_CAT(UTIL_INC_, x)
|
||||
#define UTIL_DEC(x) UTIL_PRIMITIVE_CAT(UTIL_DEC_, x)
|
||||
|
||||
#define UTIL_INC_0 1
|
||||
#define UTIL_INC_1 2
|
||||
#define UTIL_INC_2 3
|
||||
|
@ -541,4 +641,98 @@
|
|||
#define UTIL_DEC_255 254
|
||||
#define UTIL_DEC_256 255
|
||||
|
||||
#define UTIL_CHECK_N(x, n, ...) n
|
||||
#define UTIL_CHECK(...) UTIL_CHECK_N(__VA_ARGS__, 0,)
|
||||
#define UTIL_NOT(x) UTIL_CHECK(UTIL_PRIMITIVE_CAT(UTIL_NOT_, x))
|
||||
#define UTIL_NOT_0 ~, 1,
|
||||
#define UTIL_COMPL(b) UTIL_PRIMITIVE_CAT(UTIL_COMPL_, b)
|
||||
#define UTIL_COMPL_0 1
|
||||
#define UTIL_COMPL_1 0
|
||||
#define UTIL_BOOL(x) UTIL_COMPL(UTIL_NOT(x))
|
||||
#define UTIL_IIF(c) UTIL_PRIMITIVE_CAT(UTIL_IIF_, c)
|
||||
#define UTIL_IIF_0(t, ...) __VA_ARGS__
|
||||
#define UTIL_IIF_1(t, ...) t
|
||||
#define UTIL_IF(c) UTIL_IIF(UTIL_BOOL(c))
|
||||
|
||||
#define UTIL_EAT(...)
|
||||
#define UTIL_WHEN(c) UTIL_IF(c)(UTIL_EXPAND, UTIL_EAT)
|
||||
|
||||
#define UTIL_REPEAT(count, macro, ...) \
|
||||
UTIL_WHEN(count) \
|
||||
( \
|
||||
UTIL_OBSTRUCT(UTIL_REPEAT_INDIRECT) () \
|
||||
( \
|
||||
UTIL_DEC(count), macro, __VA_ARGS__ \
|
||||
) \
|
||||
UTIL_OBSTRUCT(macro) \
|
||||
( \
|
||||
UTIL_DEC(count), __VA_ARGS__ \
|
||||
) \
|
||||
)
|
||||
#define UTIL_REPEAT_INDIRECT() UTIL_REPEAT
|
||||
|
||||
/* Internal macros used by FOR_EACH, FOR_EACH_IDX, etc. */
|
||||
|
||||
#define Z_FOR_EACH_IDX(count, n, macro, sep, fixed_arg0, fixed_arg1, ...)\
|
||||
UTIL_WHEN(count) \
|
||||
( \
|
||||
UTIL_OBSTRUCT(macro) \
|
||||
( \
|
||||
fixed_arg0, fixed_arg1, n, GET_ARG1(__VA_ARGS__)\
|
||||
) COND_CODE_1(count, (), (__DEBRACKET sep)) \
|
||||
UTIL_OBSTRUCT(Z_FOR_EACH_IDX_INDIRECT) () \
|
||||
( \
|
||||
UTIL_DEC(count), UTIL_INC(n), macro, sep, \
|
||||
fixed_arg0, fixed_arg1, \
|
||||
GET_ARGS_LESS_1(__VA_ARGS__) \
|
||||
) \
|
||||
)
|
||||
|
||||
#define Z_FOR_EACH_IDX_INDIRECT() Z_FOR_EACH_IDX
|
||||
|
||||
#define Z_FOR_EACH_IDX2(count, iter, macro, sc, fixed_arg0, fixed_arg1, ...) \
|
||||
UTIL_EVAL(Z_FOR_EACH_IDX(count, iter, macro, sc,\
|
||||
fixed_arg0, fixed_arg1, __VA_ARGS__))
|
||||
|
||||
#define Z_FOR_EACH_SWALLOW_NOTHING(F, fixed_arg, index, arg) \
|
||||
F(index, arg, fixed_arg)
|
||||
|
||||
#define Z_FOR_EACH_SWALLOW_FIXED_ARG(F, fixed_arg, index, arg) F(index, arg)
|
||||
|
||||
#define Z_FOR_EACH_SWALLOW_INDEX_FIXED_ARG(F, fixed_arg, index, arg) F(arg)
|
||||
#define Z_FOR_EACH_SWALLOW_INDEX(F, fixed_arg, index, arg) F(arg, fixed_arg)
|
||||
|
||||
/* Implementation details for NUM_VA_ARGS_LESS_1 */
|
||||
#define NUM_VA_ARGS_LESS_1_IMPL( \
|
||||
_ignored, \
|
||||
_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, \
|
||||
_11, _12, _13, _14, _15, _16, _17, _18, _19, _20, \
|
||||
_21, _22, _23, _24, _25, _26, _27, _28, _29, _30, \
|
||||
_31, _32, _33, _34, _35, _36, _37, _38, _39, _40, \
|
||||
_41, _42, _43, _44, _45, _46, _47, _48, _49, _50, \
|
||||
_51, _52, _53, _54, _55, _56, _57, _58, _59, _60, \
|
||||
_61, _62, N, ...) N
|
||||
|
||||
/* Used by MACRO_MAP_CAT */
|
||||
#define MACRO_MAP_CAT_(...) \
|
||||
/* To make sure it works also for 2 arguments in total */ \
|
||||
MACRO_MAP_CAT_N(NUM_VA_ARGS_LESS_1(__VA_ARGS__), __VA_ARGS__)
|
||||
#define MACRO_MAP_CAT_N_(N, ...) UTIL_CAT(MACRO_MC_, N)(__VA_ARGS__,)
|
||||
#define MACRO_MC_0(...)
|
||||
#define MACRO_MC_1(m, a, ...) m(a)
|
||||
#define MACRO_MC_2(m, a, ...) UTIL_CAT(m(a), MACRO_MC_1(m, __VA_ARGS__,))
|
||||
#define MACRO_MC_3(m, a, ...) UTIL_CAT(m(a), MACRO_MC_2(m, __VA_ARGS__,))
|
||||
#define MACRO_MC_4(m, a, ...) UTIL_CAT(m(a), MACRO_MC_3(m, __VA_ARGS__,))
|
||||
#define MACRO_MC_5(m, a, ...) UTIL_CAT(m(a), MACRO_MC_4(m, __VA_ARGS__,))
|
||||
#define MACRO_MC_6(m, a, ...) UTIL_CAT(m(a), MACRO_MC_5(m, __VA_ARGS__,))
|
||||
#define MACRO_MC_7(m, a, ...) UTIL_CAT(m(a), MACRO_MC_6(m, __VA_ARGS__,))
|
||||
#define MACRO_MC_8(m, a, ...) UTIL_CAT(m(a), MACRO_MC_7(m, __VA_ARGS__,))
|
||||
#define MACRO_MC_9(m, a, ...) UTIL_CAT(m(a), MACRO_MC_8(m, __VA_ARGS__,))
|
||||
#define MACRO_MC_10(m, a, ...) UTIL_CAT(m(a), MACRO_MC_9(m, __VA_ARGS__,))
|
||||
#define MACRO_MC_11(m, a, ...) UTIL_CAT(m(a), MACRO_MC_10(m, __VA_ARGS__,))
|
||||
#define MACRO_MC_12(m, a, ...) UTIL_CAT(m(a), MACRO_MC_11(m, __VA_ARGS__,))
|
||||
#define MACRO_MC_13(m, a, ...) UTIL_CAT(m(a), MACRO_MC_12(m, __VA_ARGS__,))
|
||||
#define MACRO_MC_14(m, a, ...) UTIL_CAT(m(a), MACRO_MC_13(m, __VA_ARGS__,))
|
||||
#define MACRO_MC_15(m, a, ...) UTIL_CAT(m(a), MACRO_MC_14(m, __VA_ARGS__,))
|
||||
|
||||
#endif /* ZEPHYR_INCLUDE_SYS_UTIL_INTERNAL_H_ */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue