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