1 // Copyright 2017 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 //
6 // Internal declarations used by the C tracing macros.
7 // This is not part of the public API: use <trace/event.h> instead.
8 //
9 
10 #ifndef TRACE_INTERNAL_PAIRS_INTERNAL_H_
11 #define TRACE_INTERNAL_PAIRS_INTERNAL_H_
12 
13 // Count the number of pairs of arguments passed to it without evaluating them.
14 // When the number of arguments is uneven, rounds down.
15 // Works with 0 to 15 pairs.
16 #define TRACE_INTERNAL_COUNT_PAIRS(...)                     \
17     TRACE_INTERNAL_COUNT_PAIRS_(__VA_ARGS__,                \
18                                 15, 14, 14, 13, 13, 12, 12, \
19                                 11, 11, 10, 10, 9, 9, 8, 8, \
20                                 7, 7, 6, 6, 5, 5, 4, 4,     \
21                                 3, 3, 2, 2, 1, 1, 0, 0)
22 #define TRACE_INTERNAL_COUNT_PAIRS_(            \
23     _15, _15X, _14, _14X, _13, _13X, _12, _12X, \
24     _11, _11X, _10, _10X, _9, _9X, _8, _8X,     \
25     _7, _7X, _6, _6X, _5, _5X, _4, _4X,         \
26     _3, _3X, _2, _2X, _1, _1X, N, ...) N
27 
28 // Applies a function or macro to each pair of arguments.
29 // Works with 0 to 15 pairs.
30 //
31 // |fn| is the function or macro name to apply
32 // |vn| is the name of a local variable that the caller may be using. It is
33 // passed on to |fn| in case it needs it, e.g., to uniquify any further local
34 // variable names that |fn| as a macro may want to create.
35 //
36 // |fn| must accept four arguments:
37 //   - |vn|, described above
38 //   - |idx|, which is 0,1,2,...,15 and designates the index of the name/value
39 //     pair in the provided list
40 //   - |key|, which is the key part of the key/value pair
41 //   - |value|, which is the value part of the key/value pair
42 //
43 // Example:
44 //     #define MY_FN(vn, idx, a, b)
45 //     TRACE_INTERNAL_APPLY_PAIRWISE(MY_FN, my_var, "x", 1, "y", 2)
46 
47 #define TRACE_INTERNAL_APPLY_PAIRWISE(fn, vn, ...)                          \
48     TRACE_INTERNAL_APPLY_PAIRWISE_(TRACE_INTERNAL_COUNT_PAIRS(__VA_ARGS__)) \
49     (fn, vn, __VA_ARGS__)
50 #define TRACE_INTERNAL_APPLY_PAIRWISE_(n) TRACE_INTERNAL_APPLY_PAIRWISE__(n)
51 #define TRACE_INTERNAL_APPLY_PAIRWISE__(n) TRACE_INTERNAL_APPLY_PAIRWISE##n
52 // clang-format off
53 #define TRACE_INTERNAL_APPLY_PAIRWISE0(fn, vn, ...)
54 #define TRACE_INTERNAL_APPLY_PAIRWISE1(fn, vn, k1, v1) \
55     fn(vn, 1, k1, v1)
56 #define TRACE_INTERNAL_APPLY_PAIRWISE2(fn, vn, k1, v1, k2, v2) \
57     fn(vn, 1, k1, v1) fn(vn, 2, k2, v2)
58 #define TRACE_INTERNAL_APPLY_PAIRWISE3(fn, vn, k1, v1, k2, v2, k3, v3) \
59     fn(vn, 1, k1, v1) fn(vn, 2, k2, v2) fn(vn, 3, k3, v3)
60 #define TRACE_INTERNAL_APPLY_PAIRWISE4(fn, vn, k1, v1, k2, v2, k3, v3, k4, v4) \
61     fn(vn, 1, k1, v1) fn(vn, 2, k2, v2) fn(vn, 3, k3, v3) fn(vn, 4, k4, v4)
62 #define TRACE_INTERNAL_APPLY_PAIRWISE5(fn, vn, k1, v1, k2, v2, k3, v3, k4, v4, \
63                                        k5, v5)                                 \
64     fn(vn, 1, k1, v1) fn(vn, 2, k2, v2) fn(vn, 3, k3, v3) fn(vn, 4, k4, v4)    \
65     fn(vn, 5, k5, v5)
66 #define TRACE_INTERNAL_APPLY_PAIRWISE6(fn, vn, k1, v1, k2, v2, k3, v3, k4, v4, \
67                                        k5, v5, k6, v6)                         \
68     fn(vn, 1, k1, v1) fn(vn, 2, k2, v2) fn(vn, 3, k3, v3) fn(vn, 4, k4, v4)    \
69     fn(vn, 5, k5, v5) fn(vn, 6, k6, v6)
70 #define TRACE_INTERNAL_APPLY_PAIRWISE7(fn, vn, k1, v1, k2, v2, k3, v3, k4, v4, \
71                                        k5, v5, k6, v6, k7, v7)                 \
72     fn(vn, 1, k1, v1) fn(vn, 2, k2, v2) fn(vn, 3, k3, v3) fn(vn, 4, k4, v4)    \
73     fn(vn, 5, k5, v5) fn(vn, 6, k6, v6) fn(vn, 7, k7, v7)
74 #define TRACE_INTERNAL_APPLY_PAIRWISE8(fn, vn, k1, v1, k2, v2, k3, v3, k4, v4, \
75                                        k5, v5, k6, v6, k7, v7, k8, v8)         \
76     fn(vn, 1, k1, v1) fn(vn, 2, k2, v2) fn(vn, 3, k3, v3) fn(vn, 4, k4, v4)    \
77     fn(vn, 5, k5, v5) fn(vn, 6, k6, v6) fn(vn, 7, k7, v7) fn(vn, 8, k8, v8)
78 #define TRACE_INTERNAL_APPLY_PAIRWISE9(fn, vn, k1, v1, k2, v2, k3, v3, k4, v4, \
79                                        k5, v5, k6, v6, k7, v7, k8, v8,         \
80                                        k9, v9)                                 \
81     fn(vn, 1, k1, v1) fn(vn, 2, k2, v2) fn(vn, 3, k3, v3) fn(vn, 4, k4, v4)    \
82     fn(vn, 5, k5, v5) fn(vn, 6, k6, v6) fn(vn, 7, k7, v7) fn(vn, 8, k8, v8)    \
83     fn(vn, 9, k9, v9)
84 #define TRACE_INTERNAL_APPLY_PAIRWISE10(fn, vn, k1, v1, k2, v2, k3, v3, k4, v4, \
85                                         k5, v5, k6, v6, k7, v7, k8, v8,         \
86                                         k9, v9, k10, v10)                       \
87     fn(vn, 1, k1, v1) fn(vn, 2, k2, v2) fn(vn, 3, k3, v3) fn(vn, 4, k4, v4)     \
88     fn(vn, 5, k5, v5) fn(vn, 6, k6, v6) fn(vn, 7, k7, v7) fn(vn, 8, k8, v8)     \
89     fn(vn, 9, k9, v9) fn(vn, 10, k10, v10)
90 #define TRACE_INTERNAL_APPLY_PAIRWISE11(fn, vn, k1, v1, k2, v2, k3, v3, k4, v4, \
91                                         k5, v5, k6, v6, k7, v7, k8, v8,         \
92                                         k9, v9, k10, v10, k11, v11)             \
93     fn(vn, 1, k1, v1) fn(vn, 2, k2, v2) fn(vn, 3, k3, v3) fn(vn, 4, k4, v4)     \
94     fn(vn, 5, k5, v5) fn(vn, 6, k6, v6) fn(vn, 7, k7, v7) fn(vn, 8, k8, v8)     \
95     fn(vn, 9, k9, v9) fn(vn, 10, k10, v10) fn(vn, 11, k11, v11)
96 #define TRACE_INTERNAL_APPLY_PAIRWISE12(fn, vn, k1, v1, k2, v2, k3, v3, k4, v4, \
97                                         k5, v5, k6, v6, k7, v7, k8, v8,         \
98                                         k9, v9, k10, v10, k11, v11, k12, v12)   \
99     fn(vn, 1, k1, v1) fn(vn, 2, k2, v2) fn(vn, 3, k3, v3) fn(vn, 4, k4, v4)     \
100     fn(vn, 5, k5, v5) fn(vn, 6, k6, v6) fn(vn, 7, k7, v7) fn(vn, 8, k8, v8)     \
101     fn(vn, 9, k9, v9) fn(vn, 10, k10, v10) fn(vn, 11, k11, v11) fn(vn, 12, k12, v12)
102 #define TRACE_INTERNAL_APPLY_PAIRWISE13(fn, vn, k1, v1, k2, v2, k3, v3, k4, v4,      \
103                                         k5, v5, k6, v6, k7, v7, k8, v8,              \
104                                         k9, v9, k10, v10, k11, v11, k12, v12,        \
105                                         k13, v13)                                    \
106     fn(vn, 1, k1, v1) fn(vn, 2, k2, v2) fn(vn, 3, k3, v3) fn(vn, 4, k4, v4)          \
107     fn(vn, 5, k5, v5) fn(vn, 6, k6, v6) fn(vn, 7, k7, v7) fn(vn, 8, k8, v8)          \
108     fn(vn, 9, k9, v9) fn(vn, 10, k10, v10) fn(vn, 11, k11, v11) fn(vn, 12, k12, v12) \
109     fn(vn, 13, k13, v13)
110 #define TRACE_INTERNAL_APPLY_PAIRWISE14(fn, vn, k1, v1, k2, v2, k3, v3, k4, v4,      \
111                                         k5, v5, k6, v6, k7, v7, k8, v8,              \
112                                         k9, v9, k10, v10, k11, v11, k12, v12,        \
113                                         k13, v13, k14, v14)                          \
114     fn(vn, 1, k1, v1) fn(vn, 2, k2, v2) fn(vn, 3, k3, v3) fn(vn, 4, k4, v4)          \
115     fn(vn, 5, k5, v5) fn(vn, 6, k6, v6) fn(vn, 7, k7, v7) fn(vn, 8, k8, v8)          \
116     fn(vn, 9, k9, v9) fn(vn, 10, k10, v10) fn(vn, 11, k11, v11) fn(vn, 12, k12, v12) \
117     fn(vn, 13, k13, v13) fn(vn, 14, k14, v14)
118 #define TRACE_INTERNAL_APPLY_PAIRWISE15(fn, vn, k1, v1, k2, v2, k3, v3, k4, v4,      \
119                                         k5, v5, k6, v6, k7, v7, k8, v8,              \
120                                         k9, v9, k10, v10, k11, v11, k12, v12,        \
121                                         k13, v13, k14, v14, k15, v15)                \
122     fn(vn, 1, k1, v1) fn(vn, 2, k2, v2) fn(vn, 3, k3, v3) fn(vn, 4, k4, v4)          \
123     fn(vn, 5, k5, v5) fn(vn, 6, k6, v6) fn(vn, 7, k7, v7) fn(vn, 8, k8, v8)          \
124     fn(vn, 9, k9, v9) fn(vn, 10, k10, v10) fn(vn, 11, k11, v11) fn(vn, 12, k12, v12) \
125     fn(vn, 13, k13, v13) fn(vn, 14, k14, v14) fn(vn, 15, k15, v15)
126 // clang-format on
127 
128 // Applies a function or macro to each pair of arguments to produce a
129 // comma-separated result.  Works with 0 to 15 pairs.
130 //
131 // Example:
132 //     #define MY_FN(vn, idx, a, b)
133 //     TRACE_INTERNAL_APPLY_PAIRWISE_CSV(MY_FN, my_var, "x", 1, "y", 2)
134 #define TRACE_INTERNAL_APPLY_PAIRWISE_CSV(fn, vn, ...)                          \
135     TRACE_INTERNAL_APPLY_PAIRWISE_CSV_(TRACE_INTERNAL_COUNT_PAIRS(__VA_ARGS__)) \
136     (fn, vn, __VA_ARGS__)
137 #define TRACE_INTERNAL_APPLY_PAIRWISE_CSV_(n) TRACE_INTERNAL_APPLY_PAIRWISE_CSV__(n)
138 #define TRACE_INTERNAL_APPLY_PAIRWISE_CSV__(n) TRACE_INTERNAL_APPLY_PAIRWISE_CSV##n
139 // clang-format off
140 #define TRACE_INTERNAL_APPLY_PAIRWISE_CSV0(fn, vn, ...)
141 #define TRACE_INTERNAL_APPLY_PAIRWISE_CSV1(fn, vn, k1, v1) \
142     fn(vn, 1, k1, v1)
143 #define TRACE_INTERNAL_APPLY_PAIRWISE_CSV2(fn, vn, k1, v1, k2, v2) \
144     fn(vn, 1, k1, v1), fn(vn, 2, k2, v2)
145 #define TRACE_INTERNAL_APPLY_PAIRWISE_CSV3(fn, vn, k1, v1, k2, v2, k3, v3) \
146     fn(vn, 1, k1, v1), fn(vn, 2, k2, v2), fn(vn, 3, k3, v3)
147 #define TRACE_INTERNAL_APPLY_PAIRWISE_CSV4(fn, vn, k1, v1, k2, v2, k3, v3, k4, v4) \
148     fn(vn, 1, k1, v1), fn(vn, 2, k2, v2), fn(vn, 3, k3, v3), fn(vn, 4, k4, v4)
149 #define TRACE_INTERNAL_APPLY_PAIRWISE_CSV5(fn, vn, k1, v1, k2, v2, k3, v3, k4, v4, \
150                                            k5, v5)                                 \
151     fn(vn, 1, k1, v1), fn(vn, 2, k2, v2), fn(vn, 3, k3, v3), fn(vn, 4, k4, v4),    \
152     fn(vn, 5, k5, v5)
153 #define TRACE_INTERNAL_APPLY_PAIRWISE_CSV6(fn, vn, k1, v1, k2, v2, k3, v3, k4, v4, \
154                                            k5, v5, k6, v6)                         \
155     fn(vn, 1, k1, v1), fn(vn, 2, k2, v2), fn(vn, 3, k3, v3), fn(vn, 4, k4, v4),    \
156     fn(vn, 5, k5, v5), fn(vn, 6, k6, v6)
157 #define TRACE_INTERNAL_APPLY_PAIRWISE_CSV7(fn, vn, k1, v1, k2, v2, k3, v3, k4, v4, \
158                                            k5, v5, k6, v6, k7, v7)                 \
159     fn(vn, 1, k1, v1), fn(vn, 2, k2, v2), fn(vn, 3, k3, v3), fn(vn, 4, k4, v4),    \
160     fn(vn, 5, k5, v5), fn(vn, 6, k6, v6), fn(vn, 7, k7, v7)
161 #define TRACE_INTERNAL_APPLY_PAIRWISE_CSV8(fn, vn, k1, v1, k2, v2, k3, v3, k4, v4, \
162                                            k5, v5, k6, v6, k7, v7, k8, v8)         \
163     fn(vn, 1, k1, v1), fn(vn, 2, k2, v2), fn(vn, 3, k3, v3), fn(vn, 4, k4, v4),    \
164     fn(vn, 5, k5, v5), fn(vn, 6, k6, v6), fn(vn, 7, k7, v7), fn(vn, 8, k8, v8)
165 #define TRACE_INTERNAL_APPLY_PAIRWISE_CSV9(fn, vn, k1, v1, k2, v2, k3, v3, k4, v4, \
166                                            k5, v5, k6, v6, k7, v7, k8, v8,         \
167                                            k9, v9)                                 \
168     fn(vn, 1, k1, v1), fn(vn, 2, k2, v2), fn(vn, 3, k3, v3), fn(vn, 4, k4, v4),    \
169     fn(vn, 5, k5, v5), fn(vn, 6, k6, v6), fn(vn, 7, k7, v7), fn(vn, 8, k8, v8),    \
170     fn(vn, 9, k9, v9)
171 #define TRACE_INTERNAL_APPLY_PAIRWISE_CSV10(fn, vn, k1, v1, k2, v2, k3, v3, k4, v4, \
172                                             k5, v5, k6, v6, k7, v7, k8, v8,         \
173                                             k9, v9, k10, v10)                       \
174     fn(vn, 1, k1, v1), fn(vn, 2, k2, v2), fn(vn, 3, k3, v3), fn(vn, 4, k4, v4),     \
175     fn(vn, 5, k5, v5), fn(vn, 6, k6, v6), fn(vn, 7, k7, v7), fn(vn, 8, k8, v8),     \
176     fn(vn, 9, k9, v9), fn(vn, 10, k10, v10)
177 #define TRACE_INTERNAL_APPLY_PAIRWISE_CSV11(fn, vn, k1, v1, k2, v2, k3, v3, k4, v4, \
178                                             k5, v5, k6, v6, k7, v7, k8, v8,         \
179                                             k9, v9, k10, v10, k11, v11)             \
180     fn(vn, 1, k1, v1), fn(vn, 2, k2, v2), fn(vn, 3, k3, v3), fn(vn, 4, k4, v4),     \
181     fn(vn, 5, k5, v5), fn(vn, 6, k6, v6), fn(vn, 7, k7, v7), fn(vn, 8, k8, v8),     \
182     fn(vn, 9, k9, v9), fn(vn, 10, k10, v10), fn(vn, 11, k11, v11)
183 #define TRACE_INTERNAL_APPLY_PAIRWISE_CSV12(fn, vn, k1, v1, k2, v2, k3, v3, k4, v4, \
184                                             k5, v5, k6, v6, k7, v7, k8, v8,         \
185                                             k9, v9, k10, v10, k11, v11, k12, v12)   \
186     fn(vn, 1, k1, v1), fn(vn, 2, k2, v2), fn(vn, 3, k3, v3), fn(vn, 4, k4, v4),     \
187     fn(vn, 5, k5, v5), fn(vn, 6, k6, v6), fn(vn, 7, k7, v7), fn(vn, 8, k8, v8),     \
188     fn(vn, 9, k9, v9), fn(vn, 10, k10, v10), fn(vn, 11, k11, v11), fn(vn, 12, k12, v12)
189 #define TRACE_INTERNAL_APPLY_PAIRWISE_CSV13(fn, vn, k1, v1, k2, v2, k3, v3, k4, v4,      \
190                                             k5, v5, k6, v6, k7, v7, k8, v8,              \
191                                             k9, v9, k10, v10, k11, v11, k12, v12,        \
192                                             k13, v13)                                    \
193     fn(vn, 1, k1, v1), fn(vn, 2, k2, v2), fn(vn, 3, k3, v3), fn(vn, 4, k4, v4),          \
194     fn(vn, 5, k5, v5), fn(vn, 6, k6, v6), fn(vn, 7, k7, v7), fn(vn, 8, k8, v8),          \
195     fn(vn, 9, k9, v9), fn(vn, 10, k10, v10), fn(vn, 11, k11, v11), fn(vn, 12, k12, v12), \
196     fn(vn, 13, k13, v13)
197 #define TRACE_INTERNAL_APPLY_PAIRWISE_CSV14(fn, vn, k1, v1, k2, v2, k3, v3, k4, v4,      \
198                                             k5, v5, k6, v6, k7, v7, k8, v8,              \
199                                             k9, v9, k10, v10, k11, v11, k12, v12,        \
200                                             k13, v13, k14, v14)                          \
201     fn(vn, 1, k1, v1), fn(vn, 2, k2, v2), fn(vn, 3, k3, v3), fn(vn, 4, k4, v4),          \
202     fn(vn, 5, k5, v5), fn(vn, 6, k6, v6), fn(vn, 7, k7, v7), fn(vn, 8, k8, v8),          \
203     fn(vn, 9, k9, v9), fn(vn, 10, k10, v10), fn(vn, 11, k11, v11), fn(vn, 12, k12, v12), \
204     fn(vn, 13, k13, v13), fn(vn, 14, k14, v14)
205 #define TRACE_INTERNAL_APPLY_PAIRWISE_CSV15(fn, vn, k1, v1, k2, v2, k3, v3, k4, v4,      \
206                                             k5, v5, k6, v6, k7, v7, k8, v8,              \
207                                             k9, v9, k10, v10, k11, v11, k12, v12,        \
208                                             k13, v13, k14, v14, k15, v15)                \
209     fn(vn, 1, k1, v1), fn(vn, 2, k2, v2), fn(vn, 3, k3, v3), fn(vn, 4, k4, v4),          \
210     fn(vn, 5, k5, v5), fn(vn, 6, k6, v6), fn(vn, 7, k7, v7), fn(vn, 8, k8, v8),          \
211     fn(vn, 9, k9, v9), fn(vn, 10, k10, v10), fn(vn, 11, k11, v11), fn(vn, 12, k12, v12), \
212     fn(vn, 13, k13, v13), fn(vn, 14, k14, v14), fn(vn, 15, k15, v15)
213 // clang-format on
214 
215 #endif // TRACE_INTERNAL_PAIRS_INTERNAL_H_
216