1 /* SPDX-License-Identifier: BSD-3-Clause 2 * 3 * Copyright(c) 2016 Intel Corporation. All rights reserved. 4 * 5 * Author: Michal Jerzy Wierzbicki <michalx.wierzbicki@intel.com> 6 */ 7 8 /* THIS FILE SHOULD NOT BE INCLUDED DIRECTLY */ 9 10 #ifdef __SOF_TRACE_PREPROC_H__ 11 /* Macros defined in this file are only helpers for the macros that are 12 * defined in header file containing "namespace" 13 * __SOF_TRACE_PREPROC_H__ . 14 * This combination of #ifdef and #ifndef should sufficently narrow 15 * the "include-ability" of this dependent header file. 16 * If you wish to use macros from this file directly, be *V E R Y* careful! 17 * HIC SUNT DRACONES 18 */ 19 #ifndef __SOF_TRACE_PREPROC_PRIVATE_H__ 20 #define __SOF_TRACE_PREPROC_PRIVATE_H__ 21 22 /* Include 23 * #define _META_DEC_0 0 24 * #define _META_DEC_1 1 25 * #define _META_DEC_2 1 26 * #define _META_DEC_3 2 27 * ... 28 * #define _META_DEC_N N-1 29 */ 30 #include <sof/trace/preproc-private-dec.h> 31 /* Include 32 * #define _META_INC_0 1 33 * #define _META_INC_1 2 34 * ... 35 * #define _META_INC_N-1 N 36 * #define _META_INC_N N 37 */ 38 #include <sof/trace/preproc-private-inc.h> 39 40 /* count number of var args - during preprocesing 41 * works for predefined number of args 42 * META_COUNT_VARAGS_BEFORE_COMPILE(A,B,C,D) evaluates to 4 43 */ 44 #define _META_PP_NARG_BEFORE_COMPILE_(...) \ 45 _META_PP_ARG_N(__VA_ARGS__) 46 47 #define _META_PP_ARG_N(\ 48 _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, \ 49 _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, \ 50 _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, \ 51 _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, \ 52 _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, \ 53 _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, \ 54 _61, _62, _63, N, ...) N 55 56 #define _META_PP_RSEQ_N() \ 57 63, 62, 61, 60, \ 58 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, \ 59 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, \ 60 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, \ 61 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, \ 62 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, \ 63 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 64 65 /* treat x as string while forcing x expansion beforehand */ 66 #define _META_QUOTE(x) #x 67 68 /* concat x and y while forcing x and y expansion beforehand */ 69 #define _META_CONCAT_BASE(x, y) x##y 70 71 /* discard first x-1 args in vararg and return the xth arg */ 72 #define _META_GET_ARG_1(arg1, ...) arg1 73 #define _META_GET_ARG_2(arg1, arg2, ...) arg2 74 /* TODO: GET_ARG version for arbitrary x>2 should be possible using 75 * META_RECURSE(META_REPEAT 76 */ 77 78 #define _META_NO_ARGS(...) 0 79 80 /* _META_IS_PROBE(...) evaluates to 0 when __VA_ARGS__ is single token 81 * _META_IS_PROBE(PROBE()) evaulates to 1, because it is equivalent to 82 * _META_GET_ARG_2(~, 1, 0) 83 * ~ is no special value, it is just a meaningless placeholder, 84 * it could be something else if that thing would also have no meaning 85 * but be a valid C 86 */ 87 #define _META_IS_PROBE(...) _META_GET_ARG_2(__VA_ARGS__, 0) 88 #define _META_PROBE() ~, 1 89 90 /* _META_NOT_0 evaluates to '~, 1' 91 * _META_NOT_1 evaluates to '_META_NOT_1' (because it is not a macro) 92 * _META_IS_PROBE(_META_NOT_0) evaluates to 1, because it is equivalent to 93 * _META_GET_ARG_2(~, 1, 0) 94 * _META_IS_PROBE(_NOT_1) evaluates to 0, because it is equivalent to 95 * _META_GET_ARG_2(_NOT_1, 0) 96 * 97 * notice, that any x!=0 would also result in 0 98 * e.x. META_NOT(123) evaluates to 0 99 */ 100 #define _META_NOT_0 _META_PROBE() 101 102 /* indirection forces condition to be "cast" to 0 1 103 * then for 0 discard first (), and for 1 discard second () 104 * so META_IF_ELSE(0)(a)(b) expands to b, 105 * and META_IF_ELSE(1)(a)(b) expands to a 106 */ 107 #define _META_IF_ELSE(condition) META_CONCAT(_META_IF_, condition) 108 109 #define _META_IF_1(...) __VA_ARGS__ _META_IF_1_ELSE 110 #define _META_IF_0(...) _META_IF_0_ELSE 111 112 #define _META_IF_1_ELSE(...) 113 #define _META_IF_0_ELSE(...) __VA_ARGS__ 114 115 #define _META_IIF(condition) META_CONCAT(_META_IIF_, condition) 116 #define _META_IIF_0(x, ...) __VA_ARGS__ 117 #define _META_IIF_1(x, ...) x 118 119 /* primitive recursion */ 120 #define _META_REQRS_8(...) _META_REQRS_4( _META_REQRS_4 (__VA_ARGS__)) 121 #define _META_REQRS_4(...) _META_REQRS_2( _META_REQRS_2 (__VA_ARGS__)) 122 #define _META_REQRS_2(...) _META_REQRS_1( _META_REQRS_1 (__VA_ARGS__)) 123 #define _META_REQRS_1(...) __VA_ARGS__ 124 125 /* Delay macro m expansion depth times 126 * IT IS CRUCIAL FOR NO #define _META_EMPTY macro to exist!!! 127 * _META_DEFER_N(depth) will work for any depth valid in META_REPEAT 128 * (which is confined only by META_DEC). 129 * _META_DEFER_N will NOT work inside META_REPEAT, because 130 * _META_DEFER_N uses META_REPEAT as seen below. 131 * In order for META_REPEAT to work (which also requires DEFER functionality) 132 * a duplicate, implicit _META_DEFER_2(m) has to be defined. 133 * It is because how the c preprocesor works. 134 */ 135 #define _META_EMPTY() 136 137 /* These two will expand to: 138 * _META_EMPTY _META_EMPTY ... _META_EMPTY 139 * () () ... () 140 * Why '_META_EMPTY() _META_EMPTY' instead of '_META_EMPTY'? 141 * Using simply '_META_EMPTY' would produce 142 * _META_EMPTY_META_EMPTY_META_EMPTY 143 * and adding _META_EMPTY() introduces a " "(space) token. 144 */ 145 #define _META_EMPTY_GEN(i, rest) _META_EMPTY() _META_EMPTY 146 #define _META_PAREN_GEN(i, rest) () 147 /* You cannot use here META_RECURSE 148 * and must instead use _META_REQRS_{NUMBER}. 149 * If META_RECURSE was used, things like 150 * META_RECURSE(MAP_AGGREGATE 151 * would break. 152 */ 153 #define _META_DEFER_N(depth) \ 154 META_RECURSE_N(8, META_REPEAT(depth, _META_EMPTY_GEN, ~)) \ 155 META_RECURSE_N(8, META_REPEAT(depth, _META_PAREN_GEN, ~)) 156 157 /* Special, implicit defer implementation for META_REPEAT to work */ 158 #define _META_DEFER_2(m) m _META_EMPTY _META_EMPTY () () 159 160 /* helpers for consuming every single arg from __VA_ARGS__ */ 161 // expand and discard 162 #define _META_EAT(...) 163 // force expansion, reverse of META_DEFER 164 #define _META_EXPAND(...) __VA_ARGS__ 165 #define _META_WHEN(c) META_IF(c)(_META_EXPAND, _META_EAT) 166 167 /* while(count--!=0) do 168 * uses DEC so count == N can only work if all following exist 169 * DEC_0, DEC_1, ..., DEC_N-1, DEC_N 170 */ 171 #define _META_REPEAT_INDIRECT() META_REPEAT 172 173 /* map every group of arg_count arguments onto function m 174 * i.e. arg_count=2;m=ADD;args=1,2,3,4,5,6,7... 175 * results in ADD(1,2) ADD(3,4) ADD(5,6) and so on 176 * MAP##N must exist for arg_count == N to work 177 */ 178 #define _META_MAP() META_MAP 179 180 /* implements MAP(1, m, ...) */ 181 #define _META_MAP_1(m, arg1, ...)\ 182 m(arg1)\ 183 _META_DEFER_2(_META_MAP_BODY_TMP)()(1, m, __VA_ARGS__) 184 185 /* implements MAP(2, m, ...) */ 186 #define _META_MAP_2(m, arg1, arg2, ...)\ 187 m(arg1, arg2)\ 188 _META_DEFER_2(_META_MAP_BODY_TMP)()(2, m, __VA_ARGS__) 189 190 /* implements MAP(3, m, ...) */ 191 #define _META_MAP_3(m, arg1, arg2, arg3, ...)\ 192 m(arg1, arg2, arg3)\ 193 _META_DEFER_2(_META_MAP_BODY_TMP)()(3, m, __VA_ARGS__) 194 195 /* used by macro MAP, don't use on its own */ 196 #define _META_MAP_BODY(arg_count, m, ...)\ 197 META_IF_ELSE(META_COUNT_VARAGS_BEFORE_COMPILE(__VA_ARGS__))(\ 198 META_CONCAT(_META_MAP_, arg_count)(m, __VA_ARGS__) \ 199 )() 200 #define _META_MAP_BODY_TMP() _META_MAP_BODY 201 202 /* map aggregator and every group of arg_count arguments onto function m 203 * i.e. aggr=x;arg_count=1;m=ADD;args=1,2,3,4,5,6,7... 204 * results in x = ... ADD(7,ADD(6,ADD(5,ADD(4,ADD(3,ADD(2,ADD(1,x))))))) ... 205 * MAP##N must exist for arg_count == N to work 206 */ 207 #define _META_MAP_AGGREGATE() META_MAP_AGGREGATE 208 209 /* implements MAP_AGGREGATE(1, m, ...) */ 210 #define _META_MAP_AGGREGATE_1(m, aggr, arg1, ...)\ 211 _META_MAP_AGGREGATE_BODY(1, m, m(aggr, arg1), __VA_ARGS__) 212 213 /* implements MAP_AGGREGATE(2, m, ...) */ 214 #define _META_MAP_AGGREGATE_2(m, aggr, arg1, arg2, ...)\ 215 _META_MAP_AGGREGATE_BODY(2, m, m(aggr, arg1, arg2), __VA_ARGS__) 216 217 /* used by macro MAP_AGGREGATE, don't use on its own */ 218 #define _META_MAP_AGGREGATE_BODY(arg_count, m, aggr, ...)\ 219 META_IF_ELSE(META_COUNT_VARAGS_BEFORE_COMPILE(__VA_ARGS__))(\ 220 _META_DEFER_2(_META_MAP_AGGREGATE)()\ 221 (arg_count, m, aggr, __VA_ARGS__)\ 222 )(aggr) 223 224 /* META_CONCAT with parametrised delimeter between concatenised tokens 225 * META_CONCAT_SEQ_DELIM_(A,B,C,D) tokenizes as A_B_C_D 226 */ 227 #define _META_CONCAT_DELIM(delim, x, y) META_CONCAT(META_CONCAT(x, delim),y) 228 #define _META_CONCAT_DELIM_(x, y) _META_CONCAT_DELIM(_, x, y) 229 230 /* UNUSED private macros */ 231 #define _META_VOID(x) (void)(x) 232 #define _META_VOID2(x, y) x; _META_VOID(y) 233 234 #endif /* __SOF_TRACE_PREPROC_PRIVATE_H__ */ 235 #else 236 #error \ 237 Illegal use of header file: \ 238 can only be included from context of \ 239 __INCLUDE_MACRO_METAPROGRAMMING__ 240 #endif /* __SOF_TRACE_PREPROC_H__ */ 241