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 #ifndef __SOF_TRACE_PREPROC_H__ 9 #define __SOF_TRACE_PREPROC_H__ 10 11 /* Macros in this file are to be invoked directly from code. 12 * In order to work, they require a number of other macros that are 13 * defined in the header file specified below. 14 * Macros from the file specified below are not to meant to be used 15 * directly / independently. 16 * For more detailed commentary of innards of macros in this file, 17 * see file specified below. 18 */ 19 #include <sof/trace/preproc-private.h> 20 #include <stdint.h> 21 22 /* count number of var args - during preprocesing 23 * works for predefined number of args 24 * META_COUNT_VARAGS_BEFORE_COMPILE(A,B,C,D) evaluates to 4 25 */ 26 #define META_COUNT_VARAGS_BEFORE_COMPILE(...)\ 27 META_DEC(\ 28 _META_PP_NARG_BEFORE_COMPILE_(\ 29 _, ##__VA_ARGS__, _META_PP_RSEQ_N()\ 30 )\ 31 ) 32 33 /* treat x as string while forcing x expansion beforehand */ 34 #define META_QUOTE(x) _META_QUOTE(x) 35 36 /* concat x and y while forcing x and y expansion beforehand */ 37 #define META_CONCAT(x, y) _META_CONCAT_BASE(x, y) 38 39 /* discard first x-1 args in vararg and return the xth arg */ 40 41 #define META_GET_ARG_N(n, ...) META_CONCAT(_META_GET_ARG_, n)(__VA_ARGS__) 42 43 #define META_HAS_ARGS(...) META_BOOL(\ 44 _META_GET_ARG_1(_META_NO_ARGS __VA_ARGS__)()\ 45 ) 46 47 /* Only META_NOT(0) evaulates to 1 48 * notice, that any x!=0 would also result in 0 49 * e.x. META_NOT(123) evaluates to 0 50 */ 51 #define META_NOT(x) _META_IS_PROBE(META_CONCAT(_META_NOT_, x)) 52 /* hacky way to convert tokens into 0 1*/ 53 #define META_BOOL(x) META_NOT(META_NOT(x)) 54 55 /* META_IF_ELSE(X)(a)(b) expands to 56 * b for X == 0 57 * a for X != 0 58 */ 59 #define META_IF_ELSE(condition) _META_IF_ELSE(META_BOOL(condition)) 60 61 /* same story with indirection as META_IF_ELSE */ 62 #define META_IF(condition) _META_IIF(META_BOOL(condition)) 63 64 /* primitive recursion 65 * default depth is 8 66 */ 67 #define META_RECURSE(...) _META_REQRS_8(__VA_ARGS__) 68 /* choose explicitly depth of recursion 69 */ 70 #define META_RECURSE_N(depth, ...)\ 71 META_CONCAT(_META_REQRS_, depth)(__VA_ARGS__) 72 73 /* The only sane way I found to increment values in cpreproc */ 74 #define META_INC(x) META_CONCAT(_META_INC_, x) 75 76 /* The only sane way I found to decrement values in cpreproc */ 77 #define META_DEC(x) META_CONCAT(_META_DEC_, x) 78 79 /* Delay macro m expansion depth times 80 * by writing META_DEFER(0, m)(args) we expand it in 1st scan 81 * by writing META_DEFER(1, m)(args) we expand it in 2nd scan 82 * ... 83 * by writing META_DEFER(n, m)(args) we expand it in n+1nth scan 84 */ 85 #define META_DEFER(depth, m) m _META_DEFER_N(depth) 86 87 /* while(count--!=0) do 88 * uses DEC so count == N can only work if all following exist 89 * DEC_0, DEC_1, ..., DEC_N-1, DEC_N 90 */ 91 #define META_REPEAT(count, macro, ...)\ 92 _META_WHEN(count)\ 93 (\ 94 _META_DEFER_2(_META_REPEAT_INDIRECT) () \ 95 (META_DEC(count), macro, __VA_ARGS__)\ 96 _META_DEFER_2(macro)\ 97 (META_DEC(count), __VA_ARGS__)\ 98 ) 99 100 /* map every group of arg_count arguments onto function m 101 * i.e. arg_count=2;m=ADD;args=1,2,3,4,5,6,7... 102 * results in ADD(1,2) ADD(3,4) ADD(5,6) and so on 103 * MAP##N must exist for arg_count == N to work 104 */ 105 #define META_MAP(arg_count, m, ...) META_RECURSE(\ 106 _META_MAP_BODY(arg_count, m, __VA_ARGS__)) 107 108 /* map aggregator and every group of arg_count arguments onto function m 109 * i.e. aggr=x;arg_count=1;m=ADD;args=1,2,3,4,5,6,7... 110 * results in x = ... ADD(7,ADD(6,ADD(5,ADD(4,ADD(3,ADD(2,ADD(1,x))))))) ... 111 * MAP##N must exist for arg_count == N to work 112 */ 113 #define META_MAP_AGGREGATE(arg_count, m, aggr, ...)\ 114 META_CONCAT(_META_MAP_AGGREGATE_, arg_count)(m, aggr, __VA_ARGS__) 115 116 /* META_CONCAT_SEQ is basicaly variadic version of macro META_CONCAT 117 * META_CONCAT_SEQ(A,B,C,D) tokenizes to ABCD 118 */ 119 #define META_CONCAT_SEQ(aggr, ...) META_RECURSE(\ 120 META_MAP_AGGREGATE(1, META_CONCAT, aggr, __VA_ARGS__)) 121 122 /* META_CONCAT with parametrised delimeter between concatenised tokens 123 * META_CONCAT_SEQ_DELIM_(A,B,C,D) tokenizes as A_B_C_D 124 */ 125 #define META_CONCAT_SEQ_DELIM_(aggr, ...) META_RECURSE(\ 126 META_MAP_AGGREGATE(1, _META_CONCAT_DELIM_, aggr, __VA_ARGS__)) 127 128 /* META_SEQ_FROM_0_TO(3, META_SEQ_STEP_param) 129 * produces , param0 , param1 , param2 130 */ 131 #define META_SEQ_FROM_0_TO(arg_count, func)\ 132 META_RECURSE(META_REPEAT(arg_count, func, ~)) 133 134 /* Macros to be used as 2nd argument of macro META_SEQ_FROM_0_TO 135 * for instance 136 * META_SEQ_FROM_0_TO(arg_count, META_SEQ_STEP) 137 * produces 138 * 0 1 2 3 4 139 */ 140 #define META_SEQ_STEP(i, _) i 141 #define META_SEQ_STEP_param(i, _) , META_CONCAT(param, i) 142 #define META_SEQ_STEP_param_uint32_t(i, _) , uint32_t META_CONCAT(param, i) 143 #define META_SEQ_STEP_param_uint64_t(i, _) , uint64_t META_CONCAT(param, i) 144 #define META_SEQ_STEP_param_int32_t( i, _) , int32_t META_CONCAT(param, i) 145 #define META_SEQ_STEP_param_int64_t( i, _) , int64_t META_CONCAT(param, i) 146 147 #define META_SEQ_STEP_id(i, _) , META_CONCAT(id_, i) 148 #define META_SEQ_STEP_id_uint32_t(i, _) , uint32_t META_CONCAT(id_, i) 149 150 /* generates function signature 151 * for instance with: 152 * prefix=foo ; postfix=__bar ; return_t=void 153 * args=(int x, int y) 154 * will produce: 155 * void foo_bar(int x, int y) 156 */ 157 #define META_FUNC_WITH_VARARGS(prefix, postfix, return_t, args)\ 158 return_t META_CONCAT(prefix, postfix) (args) 159 160 /* counteract compiler warning about unused variables */ 161 #define UNUSED(arg1, ...) do { META_RECURSE( \ 162 META_MAP_AGGREGATE(1, _META_VOID2, _META_VOID(arg1), __VA_ARGS__)); \ 163 } while (0) 164 165 #endif /* __SOF_TRACE_PREPROC_H__ */ 166