File: pp.h

package info (click to toggle)
drgn 0.1.0-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 7,852 kB
  • sloc: python: 74,992; ansic: 54,589; awk: 423; makefile: 351; sh: 99
file content (226 lines) | stat: -rw-r--r-- 10,696 bytes parent folder | download | duplicates (2)
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
// Copyright (c) Meta Platforms, Inc. and affiliates.
// SPDX-License-Identifier: LGPL-2.1-or-later

/**
 * @file
 *
 * Preprocessor utilities.
 *
 * See @ref Preprocessor.
 */

#ifndef DRGN_PP_H
#define DRGN_PP_H

/**
 * @ingroup Internals
 *
 * @defgroup Preprocessor Preprocessor
 *
 * Preprocessor metaprogramming
 *
 * This provides several macros that can be used for preprocessor
 * metaprogramming. It is inspired by the [Boost Preprocessing
 * library](https://www.boost.org/doc/libs/release/libs/preprocessor/doc/index.html).
 *
 * @{
 */

/**
 * Get the number of variadic arguments.
 *
 * ```
 * PP_NARGS(a, b, c) // Expands to 3
 * #define ARGS x, y
 * PP_NARGS(ARGS) // Expands to 2
 * ```
 *
 * An empty argument list is considered to have 0 arguments.
 *
 * ```
 * PP_NARGS() // Expands to 0.
 * ```
 *
 * @remark This depends on the `, ##__VA_ARGS__` GNU C extension. `__VA_OPT__`
 * could be used instead, but it is only supported since GCC 8 (released in
 * 2018) and Clang 12 (released in 2021).
 *
 * @hideinitializer
 */
#define PP_NARGS(...) PP_NARGS_I(__VA_ARGS__)
/** @cond */
// The extra layer of indirection ensures that arguments are expanded.
#define PP_NARGS_I(...) PP_NARGS_II(, ##__VA_ARGS__, 64, 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)
#define PP_NARGS_II(_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, _63, _64, N, ...) N
/** @endcond */

/**
 * Overload a macro based on the number of arguments.
 *
 * This expands to @p prefix concatenated with the number of arguments (as
 * determined by @ref PP_NARGS()). Use it like so:
 *
 * ```
 * #define DEFINE_ARRAY(...) PP_OVERLOAD(DEFINE_ARRAY_I, __VA_ARGS__)(__VA_ARGS__)
 * #define DEFINE_ARRAY_I2(name, type) DEFINE_ARRAY_I3(a, b, DEFAULT_ARRAY_SIZE)
 * #define DEFINE_ARRAY_I3(name, type, size) type name[size]
 * #define DEFAULT_ARRAY_SIZE 5
 *
 * DEFINE_ARRAY(int, several); // Expands to int several[5];
 * DEFINE_ARRAY(int, couple, 2); // Expands to int couple[2];
 * ```
 *
 * @hideinitializer
 */
#define PP_OVERLOAD(prefix, ...) PP_OVERLOAD_CAT_I(prefix, PP_NARGS(__VA_ARGS__))
/** @cond */
#define PP_OVERLOAD_CAT_I(a, b) PP_OVERLOAD_CAT_II(a, b)
#define PP_OVERLOAD_CAT_II(a, b) a##b
/** @endcond */

/**
 * Expand and concatenate arguments.
 *
 * This expands each argument and then joins them with the `##` operator.
 * `PP_CAT` takes two arguments, `PP_CAT3` takes three, `PP_CAT4` takes four,
 * etc.
 *
 * ```
 * #define a foo
 * #define b bar
 * PP_CAT(a, b) // Expands to foobar
 * ```
 *
 * Intermediate results are not expanded:
 * ```
 * #define HELLO oops
 * PP_CAT3(HELL, O, WORLD) // Expands to HELLOWORLD, _not_ oopsWORLD
 * ```
 *
 * All possible intermediate results must be valid preprocessing tokens:
 * ```
 * PP_CAT3(1e, +, 3) // Undefined because +3 is not a valid preprocessing token
 * ```
 *
 * @hideinitializer
 */
#define PP_CAT(_0, _1) PP_CAT_I2(_0, _1)
#define PP_CAT3(_0, _1, _2) PP_CAT_I3(_0, _1, _2)
#define PP_CAT4(_0, _1, _2, _3) PP_CAT_I4(_0, _1, _2, _3)
#define PP_CAT5(_0, _1, _2, _3, _4) PP_CAT_I5(_0, _1, _2, _3, _4)
#define PP_CAT6(_0, _1, _2, _3, _4, _5) PP_CAT_I6(_0, _1, _2, _3, _4, _5)
#define PP_CAT7(_0, _1, _2, _3, _4, _5, _6) PP_CAT_I7(_0, _1, _2, _3, _4, _5, _6)
#define PP_CAT8(_0, _1, _2, _3, _4, _5, _6, _7) PP_CAT_I8(_0, _1, _2, _3, _4, _5, _6, _7)
/** @cond */
#define PP_CAT_I2(_0, _1) _0##_1
#define PP_CAT_I3(_0, _1, _2) _0##_1##_2
#define PP_CAT_I4(_0, _1, _2, _3) _0##_1##_2##_3
#define PP_CAT_I5(_0, _1, _2, _3, _4) _0##_1##_2##_3##_4
#define PP_CAT_I6(_0, _1, _2, _3, _4, _5) _0##_1##_2##_3##_4##_5
#define PP_CAT_I7(_0, _1, _2, _3, _4, _5, _6) _0##_1##_2##_3##_4##_5##_6
#define PP_CAT_I8(_0, _1, _2, _3, _4, _5, _6, _7) _0##_1##_2##_3##_4##_5##_6##_7
/** @endcond */

/**
 * Call a macro on each variable argument.
 *
 * ```
 * #define add_string(arg, x) x arg
 * PP_MAP(add_string, "\n", "abc", "def") // Expands to "abc" "\n" "def" "\n"
 * ```
 *
 * @param[in] func Macro taking @p arg and the next variable argument.
 * @param[in] arg First argument to pass to @p func.
 *
 * @hideinitializer
 */
#define PP_MAP(func, arg, ...) PP_OVERLOAD(PP_MAP_I, __VA_ARGS__)(func, arg, __VA_ARGS__)
/** @cond */
#define PP_MAP_I64(func, arg, x, ...) func(arg, x) PP_MAP_I63(func, arg, __VA_ARGS__)
#define PP_MAP_I63(func, arg, x, ...) func(arg, x) PP_MAP_I62(func, arg, __VA_ARGS__)
#define PP_MAP_I62(func, arg, x, ...) func(arg, x) PP_MAP_I61(func, arg, __VA_ARGS__)
#define PP_MAP_I61(func, arg, x, ...) func(arg, x) PP_MAP_I60(func, arg, __VA_ARGS__)
#define PP_MAP_I60(func, arg, x, ...) func(arg, x) PP_MAP_I59(func, arg, __VA_ARGS__)
#define PP_MAP_I59(func, arg, x, ...) func(arg, x) PP_MAP_I58(func, arg, __VA_ARGS__)
#define PP_MAP_I58(func, arg, x, ...) func(arg, x) PP_MAP_I57(func, arg, __VA_ARGS__)
#define PP_MAP_I57(func, arg, x, ...) func(arg, x) PP_MAP_I56(func, arg, __VA_ARGS__)
#define PP_MAP_I56(func, arg, x, ...) func(arg, x) PP_MAP_I55(func, arg, __VA_ARGS__)
#define PP_MAP_I55(func, arg, x, ...) func(arg, x) PP_MAP_I54(func, arg, __VA_ARGS__)
#define PP_MAP_I54(func, arg, x, ...) func(arg, x) PP_MAP_I53(func, arg, __VA_ARGS__)
#define PP_MAP_I53(func, arg, x, ...) func(arg, x) PP_MAP_I52(func, arg, __VA_ARGS__)
#define PP_MAP_I52(func, arg, x, ...) func(arg, x) PP_MAP_I51(func, arg, __VA_ARGS__)
#define PP_MAP_I51(func, arg, x, ...) func(arg, x) PP_MAP_I50(func, arg, __VA_ARGS__)
#define PP_MAP_I50(func, arg, x, ...) func(arg, x) PP_MAP_I49(func, arg, __VA_ARGS__)
#define PP_MAP_I49(func, arg, x, ...) func(arg, x) PP_MAP_I48(func, arg, __VA_ARGS__)
#define PP_MAP_I48(func, arg, x, ...) func(arg, x) PP_MAP_I47(func, arg, __VA_ARGS__)
#define PP_MAP_I47(func, arg, x, ...) func(arg, x) PP_MAP_I46(func, arg, __VA_ARGS__)
#define PP_MAP_I46(func, arg, x, ...) func(arg, x) PP_MAP_I45(func, arg, __VA_ARGS__)
#define PP_MAP_I45(func, arg, x, ...) func(arg, x) PP_MAP_I44(func, arg, __VA_ARGS__)
#define PP_MAP_I44(func, arg, x, ...) func(arg, x) PP_MAP_I43(func, arg, __VA_ARGS__)
#define PP_MAP_I43(func, arg, x, ...) func(arg, x) PP_MAP_I42(func, arg, __VA_ARGS__)
#define PP_MAP_I42(func, arg, x, ...) func(arg, x) PP_MAP_I41(func, arg, __VA_ARGS__)
#define PP_MAP_I41(func, arg, x, ...) func(arg, x) PP_MAP_I40(func, arg, __VA_ARGS__)
#define PP_MAP_I40(func, arg, x, ...) func(arg, x) PP_MAP_I39(func, arg, __VA_ARGS__)
#define PP_MAP_I39(func, arg, x, ...) func(arg, x) PP_MAP_I38(func, arg, __VA_ARGS__)
#define PP_MAP_I38(func, arg, x, ...) func(arg, x) PP_MAP_I37(func, arg, __VA_ARGS__)
#define PP_MAP_I37(func, arg, x, ...) func(arg, x) PP_MAP_I36(func, arg, __VA_ARGS__)
#define PP_MAP_I36(func, arg, x, ...) func(arg, x) PP_MAP_I35(func, arg, __VA_ARGS__)
#define PP_MAP_I35(func, arg, x, ...) func(arg, x) PP_MAP_I34(func, arg, __VA_ARGS__)
#define PP_MAP_I34(func, arg, x, ...) func(arg, x) PP_MAP_I33(func, arg, __VA_ARGS__)
#define PP_MAP_I33(func, arg, x, ...) func(arg, x) PP_MAP_I32(func, arg, __VA_ARGS__)
#define PP_MAP_I32(func, arg, x, ...) func(arg, x) PP_MAP_I31(func, arg, __VA_ARGS__)
#define PP_MAP_I31(func, arg, x, ...) func(arg, x) PP_MAP_I30(func, arg, __VA_ARGS__)
#define PP_MAP_I30(func, arg, x, ...) func(arg, x) PP_MAP_I29(func, arg, __VA_ARGS__)
#define PP_MAP_I29(func, arg, x, ...) func(arg, x) PP_MAP_I28(func, arg, __VA_ARGS__)
#define PP_MAP_I28(func, arg, x, ...) func(arg, x) PP_MAP_I27(func, arg, __VA_ARGS__)
#define PP_MAP_I27(func, arg, x, ...) func(arg, x) PP_MAP_I26(func, arg, __VA_ARGS__)
#define PP_MAP_I26(func, arg, x, ...) func(arg, x) PP_MAP_I25(func, arg, __VA_ARGS__)
#define PP_MAP_I25(func, arg, x, ...) func(arg, x) PP_MAP_I24(func, arg, __VA_ARGS__)
#define PP_MAP_I24(func, arg, x, ...) func(arg, x) PP_MAP_I23(func, arg, __VA_ARGS__)
#define PP_MAP_I23(func, arg, x, ...) func(arg, x) PP_MAP_I22(func, arg, __VA_ARGS__)
#define PP_MAP_I22(func, arg, x, ...) func(arg, x) PP_MAP_I21(func, arg, __VA_ARGS__)
#define PP_MAP_I21(func, arg, x, ...) func(arg, x) PP_MAP_I20(func, arg, __VA_ARGS__)
#define PP_MAP_I20(func, arg, x, ...) func(arg, x) PP_MAP_I19(func, arg, __VA_ARGS__)
#define PP_MAP_I19(func, arg, x, ...) func(arg, x) PP_MAP_I18(func, arg, __VA_ARGS__)
#define PP_MAP_I18(func, arg, x, ...) func(arg, x) PP_MAP_I17(func, arg, __VA_ARGS__)
#define PP_MAP_I17(func, arg, x, ...) func(arg, x) PP_MAP_I16(func, arg, __VA_ARGS__)
#define PP_MAP_I16(func, arg, x, ...) func(arg, x) PP_MAP_I15(func, arg, __VA_ARGS__)
#define PP_MAP_I15(func, arg, x, ...) func(arg, x) PP_MAP_I14(func, arg, __VA_ARGS__)
#define PP_MAP_I14(func, arg, x, ...) func(arg, x) PP_MAP_I13(func, arg, __VA_ARGS__)
#define PP_MAP_I13(func, arg, x, ...) func(arg, x) PP_MAP_I12(func, arg, __VA_ARGS__)
#define PP_MAP_I12(func, arg, x, ...) func(arg, x) PP_MAP_I11(func, arg, __VA_ARGS__)
#define PP_MAP_I11(func, arg, x, ...) func(arg, x) PP_MAP_I10(func, arg, __VA_ARGS__)
#define PP_MAP_I10(func, arg, x, ...) func(arg, x) PP_MAP_I9(func, arg, __VA_ARGS__)
#define PP_MAP_I9(func, arg, x, ...) func(arg, x) PP_MAP_I8(func, arg, __VA_ARGS__)
#define PP_MAP_I8(func, arg, x, ...) func(arg, x) PP_MAP_I7(func, arg, __VA_ARGS__)
#define PP_MAP_I7(func, arg, x, ...) func(arg, x) PP_MAP_I6(func, arg, __VA_ARGS__)
#define PP_MAP_I6(func, arg, x, ...) func(arg, x) PP_MAP_I5(func, arg, __VA_ARGS__)
#define PP_MAP_I5(func, arg, x, ...) func(arg, x) PP_MAP_I4(func, arg, __VA_ARGS__)
#define PP_MAP_I4(func, arg, x, ...) func(arg, x) PP_MAP_I3(func, arg, __VA_ARGS__)
#define PP_MAP_I3(func, arg, x, ...) func(arg, x) PP_MAP_I2(func, arg, __VA_ARGS__)
#define PP_MAP_I2(func, arg, x, ...) func(arg, x) PP_MAP_I1(func, arg, __VA_ARGS__)
#define PP_MAP_I1(func, arg, x) func(arg, x)
#define PP_MAP_I0(func, arg, x)
/** @endcond */

/**
 * Create a unique name.
 *
 * This can be used to avoid name collisions and shadowing in macros that define
 * local variables.
 *
 * ```
 * #define SWAP(a, b) SWAP_I(a, b, PP_UNIQUE(tmp))
 * #define SWAP_I(a, b, tmp) do { typeof(a) tmp = (a); (a) = (b); (b) = tmp; } while (0)
 * ```
 *
 * @param[in] prefix Prefix for unique name. This makes the created name more
 * recognizable in compiler diagnostics and debuggers. This is not expanded.
 *
 * @hideinitializer
 */
#define PP_UNIQUE(prefix) PP_CAT(prefix##__PP_UNIQUE_, __COUNTER__)

/** @} */

#endif /* DRGN_PP_H */