Add bitfield functions wrapping actual macros
[barectf.git] / barectf / templates.py
CommitLineData
67bd189f
PP
1BARECTF_CTX = """struct {prefix}{sid}_ctx {{
2 /* output buffer (will contain a CTF binary packet) */
3 uint8_t* buf;
4
5 /* buffer size in bits */
8079a626 6 uint32_t packet_size;
67bd189f
PP
7
8 /* current position from beginning of buffer in bits */
9 uint32_t at;
10
df892ed5
PP
11 /* clock value callback */
12{clock_cb}
13
14 /* packet header + context size */
15 uint32_t packet_header_context_size;
16
67bd189f
PP
17 /* config-specific members follow */
18{ctx_fields}
19}};"""
20
df892ed5
PP
21FUNC_INIT = """{si}int {prefix}{sid}_init(
22 struct {prefix}{sid}_ctx* ctx,
23 uint8_t* buf,
24 uint32_t buf_size{params}
25)"""
26
e8b2e56a 27FUNC_OPEN = """{si}int {prefix}{sid}_open_packet(
df892ed5
PP
28 struct {prefix}{sid}_ctx* ctx{params}
29)"""
30
e8b2e56a 31FUNC_CLOSE = """{si}int {prefix}{sid}_close_packet(
df892ed5
PP
32 struct {prefix}{sid}_ctx* ctx{params}
33)"""
34
35FUNC_TRACE = """{si}int {prefix}{sid}_trace_{evname}(
36 struct {prefix}{sid}_ctx* ctx{params}
37)"""
38
8079a626 39WRITE_INTEGER = """{ucprefix}_CHK_OFFSET_V(ctx->at, ctx->packet_size, {sz});
c954615b 40{prefix}_write_integer_{signed}_{bo}(ctx->buf, ctx->at, {sz}, {src_name});
6b9ba5f3
PP
41ctx->at += {sz};"""
42
df892ed5 43HEADER = """#ifndef _{ucprefix}_H
67bd189f
PP
44#define _{ucprefix}_H
45
46#include <stdint.h>
8079a626 47#include <string.h>
67bd189f 48
9a0782f7 49#include "{prefix}_bitfield.h"
445687b2 50
67bd189f
PP
51/* barectf contexts */
52{barectf_ctx}
53
54/* barectf error codes */
df892ed5
PP
55#define E{ucprefix}_OK 0
56#define E{ucprefix}_NOSPC 1
67bd189f
PP
57
58/* alignment macro */
59#define {ucprefix}_ALIGN_OFFSET(_at, _align) \\
60 do {{ \\
02cb350d 61 _at = ((_at) + (_align - 1)) & -_align; \\
67bd189f
PP
62 }} while (0)
63
64/* buffer overflow check macro */
65#define {ucprefix}_CHK_OFFSET_V(_at, _bufsize, _size) \\
66 do {{ \\
67 if ((_at) + (_size) > (_bufsize)) {{ \\
02cb350d 68 _at = ctx_at_begin; \\
67bd189f
PP
69 return -E{ucprefix}_NOSPC; \\
70 }} \\
71 }} while (0)
72
73/* generated functions follow */
74{functions}
75
76#endif /* _{ucprefix}_H */
77"""
445687b2 78
8079a626
PP
79CSRC = """#include <stdint.h>
80#include <string.h>
81
82#include "{prefix}.h"
445687b2
PP
83
84{functions}
85"""
9a0782f7
PP
86
87BITFIELD = """#ifndef _$PREFIX$_BITFIELD_H
88#define _$PREFIX$_BITFIELD_H
89
90/*
91 * BabelTrace
92 *
93 * Bitfields read/write functions.
94 *
95 * Copyright 2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
96 *
97 * Permission is hereby granted, free of charge, to any person obtaining a copy
98 * of this software and associated documentation files (the "Software"), to deal
99 * in the Software without restriction, including without limitation the rights
100 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
101 * copies of the Software, and to permit persons to whom the Software is
102 * furnished to do so, subject to the following conditions:
103 *
104 * The above copyright notice and this permission notice shall be included in
105 * all copies or substantial portions of the Software.
106 *
107 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
108 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
109 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
110 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
111 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
112 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
113 * SOFTWARE.
114 */
115
116#include <stdint.h> /* C99 5.2.4.2 Numerical limits */
8079a626 117#include <limits.h>
9a0782f7
PP
118
119#define $PREFIX$_BYTE_ORDER $ENDIAN_DEF$
120
121/* We can't shift a int from 32 bit, >> 32 and << 32 on int is undefined */
122#define _$prefix$_bt_piecewise_rshift(_v, _shift) \\
123({ \\
124 typeof(_v) ___v = (_v); \\
125 typeof(_shift) ___shift = (_shift); \\
126 unsigned long sb = (___shift) / (sizeof(___v) * CHAR_BIT - 1); \\
127 unsigned long final = (___shift) % (sizeof(___v) * CHAR_BIT - 1); \\
128 \\
129 for (; sb; sb--) \\
130 ___v >>= sizeof(___v) * CHAR_BIT - 1; \\
131 ___v >>= final; \\
132})
133
134#define _$prefix$_bt_piecewise_lshift(_v, _shift) \\
135({ \\
136 typeof(_v) ___v = (_v); \\
137 typeof(_shift) ___shift = (_shift); \\
138 unsigned long sb = (___shift) / (sizeof(___v) * CHAR_BIT - 1); \\
139 unsigned long final = (___shift) % (sizeof(___v) * CHAR_BIT - 1); \\
140 \\
141 for (; sb; sb--) \\
142 ___v <<= sizeof(___v) * CHAR_BIT - 1; \\
143 ___v <<= final; \\
144})
145
146#define _$prefix$_bt_is_signed_type(type) ((type) -1 < (type) 0)
147
148#define _$prefix$_bt_unsigned_cast(type, v) \\
149({ \\
150 (sizeof(v) < sizeof(type)) ? \\
151 ((type) (v)) & (~(~(type) 0 << (sizeof(v) * CHAR_BIT))) : \\
152 (type) (v); \\
153})
154
155/*
156 * $prefix$_bt_bitfield_write - write integer to a bitfield in native endianness
157 *
158 * Save integer to the bitfield, which starts at the "start" bit, has "len"
159 * bits.
160 * The inside of a bitfield is from high bits to low bits.
161 * Uses native endianness.
162 * For unsigned "v", pad MSB with 0 if bitfield is larger than v.
163 * For signed "v", sign-extend v if bitfield is larger than v.
164 *
165 * On little endian, bytes are placed from the less significant to the most
166 * significant. Also, consecutive bitfields are placed from lower bits to higher
167 * bits.
168 *
169 * On big endian, bytes are places from most significant to less significant.
170 * Also, consecutive bitfields are placed from higher to lower bits.
171 */
172
173#define _$prefix$_bt_bitfield_write_le(_ptr, type, _start, _length, _v) \\
174do { \\
175 typeof(_v) __v = (_v); \\
176 type *__ptr = (void *) (_ptr); \\
177 unsigned long __start = (_start), __length = (_length); \\
178 type mask, cmask; \\
179 unsigned long ts = sizeof(type) * CHAR_BIT; /* type size */ \\
180 unsigned long start_unit, end_unit, this_unit; \\
181 unsigned long end, cshift; /* cshift is "complement shift" */ \\
182 \\
183 if (!__length) \\
184 break; \\
185 \\
186 end = __start + __length; \\
187 start_unit = __start / ts; \\
188 end_unit = (end + (ts - 1)) / ts; \\
189 \\
190 /* Trim v high bits */ \\
191 if (__length < sizeof(__v) * CHAR_BIT) \\
192 __v &= ~((~(typeof(__v)) 0) << __length); \\
193 \\
194 /* We can now append v with a simple "or", shift it piece-wise */ \\
195 this_unit = start_unit; \\
196 if (start_unit == end_unit - 1) { \\
197 mask = ~((~(type) 0) << (__start % ts)); \\
198 if (end % ts) \\
199 mask |= (~(type) 0) << (end % ts); \\
200 cmask = (type) __v << (__start % ts); \\
201 cmask &= ~mask; \\
202 __ptr[this_unit] &= mask; \\
203 __ptr[this_unit] |= cmask; \\
204 break; \\
205 } \\
206 if (__start % ts) { \\
207 cshift = __start % ts; \\
208 mask = ~((~(type) 0) << cshift); \\
209 cmask = (type) __v << cshift; \\
210 cmask &= ~mask; \\
211 __ptr[this_unit] &= mask; \\
212 __ptr[this_unit] |= cmask; \\
213 __v = _$prefix$_bt_piecewise_rshift(__v, ts - cshift); \\
214 __start += ts - cshift; \\
215 this_unit++; \\
216 } \\
217 for (; this_unit < end_unit - 1; this_unit++) { \\
218 __ptr[this_unit] = (type) __v; \\
219 __v = _$prefix$_bt_piecewise_rshift(__v, ts); \\
220 __start += ts; \\
221 } \\
222 if (end % ts) { \\
223 mask = (~(type) 0) << (end % ts); \\
224 cmask = (type) __v; \\
225 cmask &= ~mask; \\
226 __ptr[this_unit] &= mask; \\
227 __ptr[this_unit] |= cmask; \\
228 } else \\
229 __ptr[this_unit] = (type) __v; \\
230} while (0)
231
232#define _$prefix$_bt_bitfield_write_be(_ptr, type, _start, _length, _v) \\
233do { \\
234 typeof(_v) __v = (_v); \\
235 type *__ptr = (void *) (_ptr); \\
236 unsigned long __start = (_start), __length = (_length); \\
237 type mask, cmask; \\
238 unsigned long ts = sizeof(type) * CHAR_BIT; /* type size */ \\
239 unsigned long start_unit, end_unit, this_unit; \\
240 unsigned long end, cshift; /* cshift is "complement shift" */ \\
241 \\
242 if (!__length) \\
243 break; \\
244 \\
245 end = __start + __length; \\
246 start_unit = __start / ts; \\
247 end_unit = (end + (ts - 1)) / ts; \\
248 \\
249 /* Trim v high bits */ \\
250 if (__length < sizeof(__v) * CHAR_BIT) \\
251 __v &= ~((~(typeof(__v)) 0) << __length); \\
252 \\
253 /* We can now append v with a simple "or", shift it piece-wise */ \\
254 this_unit = end_unit - 1; \\
255 if (start_unit == end_unit - 1) { \\
256 mask = ~((~(type) 0) << ((ts - (end % ts)) % ts)); \\
257 if (__start % ts) \\
258 mask |= (~((type) 0)) << (ts - (__start % ts)); \\
259 cmask = (type) __v << ((ts - (end % ts)) % ts); \\
260 cmask &= ~mask; \\
261 __ptr[this_unit] &= mask; \\
262 __ptr[this_unit] |= cmask; \\
263 break; \\
264 } \\
265 if (end % ts) { \\
266 cshift = end % ts; \\
267 mask = ~((~(type) 0) << (ts - cshift)); \\
268 cmask = (type) __v << (ts - cshift); \\
269 cmask &= ~mask; \\
270 __ptr[this_unit] &= mask; \\
271 __ptr[this_unit] |= cmask; \\
272 __v = _$prefix$_bt_piecewise_rshift(__v, cshift); \\
273 end -= cshift; \\
274 this_unit--; \\
275 } \\
276 for (; (long) this_unit >= (long) start_unit + 1; this_unit--) { \\
277 __ptr[this_unit] = (type) __v; \\
278 __v = _$prefix$_bt_piecewise_rshift(__v, ts); \\
279 end -= ts; \\
280 } \\
281 if (__start % ts) { \\
282 mask = (~(type) 0) << (ts - (__start % ts)); \\
283 cmask = (type) __v; \\
284 cmask &= ~mask; \\
285 __ptr[this_unit] &= mask; \\
286 __ptr[this_unit] |= cmask; \\
287 } else \\
288 __ptr[this_unit] = (type) __v; \\
289} while (0)
290
291/*
292 * $prefix$_bt_bitfield_write - write integer to a bitfield in native endianness
293 * $prefix$_bt_bitfield_write_le - write integer to a bitfield in little endian
294 * $prefix$_bt_bitfield_write_be - write integer to a bitfield in big endian
295 */
296
297#if ($PREFIX$_BYTE_ORDER == LITTLE_ENDIAN)
298
299#define $prefix$_bt_bitfield_write(ptr, type, _start, _length, _v) \\
300 _$prefix$_bt_bitfield_write_le(ptr, type, _start, _length, _v)
301
302#define $prefix$_bt_bitfield_write_le(ptr, type, _start, _length, _v) \\
303 _$prefix$_bt_bitfield_write_le(ptr, type, _start, _length, _v)
304
305#define $prefix$_bt_bitfield_write_be(ptr, type, _start, _length, _v) \\
306 _$prefix$_bt_bitfield_write_be(ptr, unsigned char, _start, _length, _v)
307
308#elif ($PREFIX$_BYTE_ORDER == BIG_ENDIAN)
309
310#define $prefix$_bt_bitfield_write(ptr, type, _start, _length, _v) \\
311 _$prefix$_bt_bitfield_write_be(ptr, type, _start, _length, _v)
312
313#define $prefix$_bt_bitfield_write_le(ptr, type, _start, _length, _v) \\
314 _$prefix$_bt_bitfield_write_le(ptr, unsigned char, _start, _length, _v)
315
316#define $prefix$_bt_bitfield_write_be(ptr, type, _start, _length, _v) \\
317 _$prefix$_bt_bitfield_write_be(ptr, type, _start, _length, _v)
318
319#else /* ($PREFIX$_BYTE_ORDER == PDP_ENDIAN) */
320
321#error "Byte order not supported"
322
323#endif
324
c954615b
PP
325static
326void $prefix$_write_integer_signed_le(void *ptr, uint32_t at, uint32_t len, int64_t v)
327{
328 $prefix$_bt_bitfield_write_le(ptr, uint8_t, at, len, v);
329}
330
331static
332void $prefix$_write_integer_unsigned_le(void *ptr, uint32_t at, uint32_t len, uint64_t v)
333{
334 $prefix$_bt_bitfield_write_le(ptr, uint8_t, at, len, v);
335}
336
337static
338void $prefix$_write_integer_signed_be(void *ptr, uint32_t at, uint32_t len, int64_t v)
339{
340 $prefix$_bt_bitfield_write_be(ptr, uint8_t, at, len, v);
341}
342
343static
344void $prefix$_write_integer_unsigned_be(void *ptr, uint32_t at, uint32_t len, uint64_t v)
345{
346 $prefix$_bt_bitfield_write_be(ptr, uint8_t, at, len, v);
347}
348
9a0782f7
PP
349#endif /* _$PREFIX$_BITFIELD_H */
350"""
This page took 0.0368 seconds and 4 git commands to generate.