libdragon
Loading...
Searching...
No Matches
pputils.h
1/*
2 * Preprocessor metaprogramming utils
3 *
4 * This file contains some generic macros that are useful to implement
5 * preprocessor metaprogramming, that is sometimes useful in providing
6 * nice APIs.
7 *
8 * They are not documented via doxygen because they are not part of the
9 * libdragon public API, though they might be used in header files.
10 */
11#ifndef __LIBDRAGON_PPUTILS_H
12#define __LIBDRAGON_PPUTILS_H
13
15
16// FOREACH helpers. These macros are internally used by __CALL_FOREACH later.
17#define __FE_0(_call, ...)
18#define __FE_1(_call, x) _call(x)
19#define __FE_2(_call, x, ...) _call(x) __FE_1(_call, __VA_ARGS__)
20#define __FE_3(_call, x, ...) _call(x) __FE_2(_call, __VA_ARGS__)
21#define __FE_4(_call, x, ...) _call(x) __FE_3(_call, __VA_ARGS__)
22#define __FE_5(_call, x, ...) _call(x) __FE_4(_call, __VA_ARGS__)
23#define __FE_6(_call, x, ...) _call(x) __FE_5(_call, __VA_ARGS__)
24#define __FE_7(_call, x, ...) _call(x) __FE_6(_call, __VA_ARGS__)
25#define __FE_8(_call, x, ...) _call(x) __FE_7(_call, __VA_ARGS__)
26#define __FE_9(_call, x, ...) _call(x) __FE_8(_call, __VA_ARGS__)
27#define __FE_10(_call, x, ...) _call(x) __FE_9(_call, __VA_ARGS__)
28#define __FE_11(_call, x, ...) _call(x) __FE_10(_call, __VA_ARGS__)
29#define __FE_12(_call, x, ...) _call(x) __FE_11(_call, __VA_ARGS__)
30#define __FE_13(_call, x, ...) _call(x) __FE_12(_call, __VA_ARGS__)
31#define __FE_14(_call, x, ...) _call(x) __FE_13(_call, __VA_ARGS__)
32#define __FE_15(_call, x, ...) _call(x) __FE_14(_call, __VA_ARGS__)
33#define __FE_16(_call, x, ...) _call(x) __FE_15(_call, __VA_ARGS__)
34#define __FE_17(_call, x, ...) _call(x) __FE_16(_call, __VA_ARGS__)
35#define __FE_18(_call, x, ...) _call(x) __FE_17(_call, __VA_ARGS__)
36#define __FE_19(_call, x, ...) _call(x) __FE_18(_call, __VA_ARGS__)
37#define __FE_20(_call, x, ...) _call(x) __FE_19(_call, __VA_ARGS__)
38#define __FE_21(_call, x, ...) _call(x) __FE_20(_call, __VA_ARGS__)
39#define __FE_22(_call, x, ...) _call(x) __FE_21(_call, __VA_ARGS__)
40#define __FE_23(_call, x, ...) _call(x) __FE_22(_call, __VA_ARGS__)
41#define __FE_24(_call, x, ...) _call(x) __FE_23(_call, __VA_ARGS__)
42#define __FE_25(_call, x, ...) _call(x) __FE_24(_call, __VA_ARGS__)
43#define __FE_26(_call, x, ...) _call(x) __FE_25(_call, __VA_ARGS__)
44#define __FE_27(_call, x, ...) _call(x) __FE_26(_call, __VA_ARGS__)
45#define __FE_28(_call, x, ...) _call(x) __FE_27(_call, __VA_ARGS__)
46#define __FE_29(_call, x, ...) _call(x) __FE_28(_call, __VA_ARGS__)
47#define __FE_30(_call, x, ...) _call(x) __FE_29(_call, __VA_ARGS__)
48#define __FE_31(_call, x, ...) _call(x) __FE_30(_call, __VA_ARGS__)
49
50// Get the 33rd argument to this call. This is an useful building block for later macros
51#define __GET_33RD_ARG(_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, N, ...) N
52
53// Return the number of variadic arguments
54#define __COUNT_VARARGS(...) __GET_33RD_ARG("ignored", ##__VA_ARGS__, 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)
55
56// Return 1 if there is at least one variadic argument, otherwise 0
57#define __HAS_VARARGS(...) __GET_33RD_ARG("ignored", ##__VA_ARGS__, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0)
58
59// Call macro fn for each variadic argument
60#define __CALL_FOREACH(fn, ...) __GET_33RD_ARG("ignored", ##__VA_ARGS__, __FE_31, __FE_30, __FE_29, __FE_28, __FE_27, __FE_26, __FE_25, __FE_24, __FE_23, __FE_22, __FE_21, __FE_20, __FE_19, __FE_18, __FE_17, __FE_16, __FE_15, __FE_14, __FE_13, __FE_12, __FE_11, __FE_10, __FE_9, __FE_8, __FE_7, __FE_6, __FE_5, __FE_4, __FE_3, __FE_2, __FE_1, __FE_0)(fn, ##__VA_ARGS__)
61
62// Preprocessor token paste
63#define __PPCAT2(n,x) n ## x
64#define __PPCAT(n,x) __PPCAT2(n,x)
65
66// __CALL_FOREACH_BIS. Like __CALL_FOREACH, but it allows to be called without the expansion
67// of a __CALL_FOREACH.
68#define __FEB_0(_call, ...)
69#define __FEB_1(_call, x) _call(x)
70#define __FEB_2(_call, x, ...) _call(x) __FEB_1(_call, __VA_ARGS__)
71#define __FEB_3(_call, x, ...) _call(x) __FEB_2(_call, __VA_ARGS__)
72#define __FEB_4(_call, x, ...) _call(x) __FEB_3(_call, __VA_ARGS__)
73#define __FEB_5(_call, x, ...) _call(x) __FEB_4(_call, __VA_ARGS__)
74#define __FEB_6(_call, x, ...) _call(x) __FEB_5(_call, __VA_ARGS__)
75#define __FEB_7(_call, x, ...) _call(x) __FEB_6(_call, __VA_ARGS__)
76#define __FEB_8(_call, x, ...) _call(x) __FEB_7(_call, __VA_ARGS__)
77#define __FEB_9(_call, x, ...) _call(x) __FEB_8(_call, __VA_ARGS__)
78#define __FEB_10(_call, x, ...) _call(x) __FEB_9(_call, __VA_ARGS__)
79#define __FEB_11(_call, x, ...) _call(x) __FEB_10(_call, __VA_ARGS__)
80#define __FEB_12(_call, x, ...) _call(x) __FEB_11(_call, __VA_ARGS__)
81#define __FEB_13(_call, x, ...) _call(x) __FEB_12(_call, __VA_ARGS__)
82#define __FEB_14(_call, x, ...) _call(x) __FEB_13(_call, __VA_ARGS__)
83#define __FEB_15(_call, x, ...) _call(x) __FEB_14(_call, __VA_ARGS__)
84#define __FEB_16(_call, x, ...) _call(x) __FEB_15(_call, __VA_ARGS__)
85#define __FEB_17(_call, x, ...) _call(x) __FEB_16(_call, __VA_ARGS__)
86#define __FEB_18(_call, x, ...) _call(x) __FEB_17(_call, __VA_ARGS__)
87#define __FEB_19(_call, x, ...) _call(x) __FEB_18(_call, __VA_ARGS__)
88#define __FEB_20(_call, x, ...) _call(x) __FEB_19(_call, __VA_ARGS__)
89#define __FEB_21(_call, x, ...) _call(x) __FEB_20(_call, __VA_ARGS__)
90#define __FEB_22(_call, x, ...) _call(x) __FEB_21(_call, __VA_ARGS__)
91#define __FEB_23(_call, x, ...) _call(x) __FEB_22(_call, __VA_ARGS__)
92#define __FEB_24(_call, x, ...) _call(x) __FEB_23(_call, __VA_ARGS__)
93#define __FEB_25(_call, x, ...) _call(x) __FEB_24(_call, __VA_ARGS__)
94#define __FEB_26(_call, x, ...) _call(x) __FEB_25(_call, __VA_ARGS__)
95#define __FEB_27(_call, x, ...) _call(x) __FEB_26(_call, __VA_ARGS__)
96#define __FEB_28(_call, x, ...) _call(x) __FEB_27(_call, __VA_ARGS__)
97#define __FEB_29(_call, x, ...) _call(x) __FEB_28(_call, __VA_ARGS__)
98#define __FEB_30(_call, x, ...) _call(x) __FEB_29(_call, __VA_ARGS__)
99#define __FEB_31(_call, x, ...) _call(x) __FEB_30(_call, __VA_ARGS__)
100#define __CALL_FOREACH_BIS(fn, ...) __GET_33RD_ARG("ignored", ##__VA_ARGS__, __FEB_31, __FEB_30, __FEB_29, __FEB_28, __FEB_27, __FEB_26, __FEB_25, __FEB_24, __FEB_23, __FEB_22, __FEB_21, __FEB_20, __FEB_19, __FEB_18, __FEB_17, __FEB_16, __FEB_15, __FEB_14, __FEB_13, __FEB_12, __FEB_11, __FEB_10, __FEB_9, __FEB_8, __FEB_7, __FEB_6, __FEB_5, __FEB_4, __FEB_3, __FEB_2, __FEB_1, __FEB_0)(fn, ##__VA_ARGS__)
101
102// Check that GNU extensions are active and macros work correctly. Specifically
103// we require the extension that allows ##__VA_ARGS__ to elide the previous comma
104// when no variadic arguments are specified.
105#if __COUNT_VARARGS() != 0
106#error GNU extensions are required -- please specify a -std=gnuXX/gnu++XX option to the compiler
107#endif
108
110
111#endif